15 static void _tidyUp(char *buf)
17 // Clean up the line so that it is 'prettier'.
19 // If this is a comment line (starts with a ';') then indent it.
20 // PENDING: The outputter does its own pretty print. Disable for now.
22 else if (strchr(buf, ':')) {
23 // Is a label - cant do anything.
26 /* Change the first (and probably only) ' ' to a tab so
39 void iemit(const char *szFormat, ...)
44 va_start(ap, szFormat);
46 tvsprintf(buffer, szFormat, ap);
50 if (_G.lines.current == NULL) {
51 _G.lines.head = newLineNode(buffer);
52 _G.lines.current = _G.lines.head;
55 _G.lines.current = connectLine(_G.lines.current, newLineNode(buffer));
58 // PENDING: Inline support.
59 // _G.lines.current->isInline = inLine;
62 // Mapping between operand type and a friendly name.
68 static OPNAME _opnames[] = {
71 { UNARYMINUS, "genUminus" },
72 { IPUSH, "genIpush" },
75 { PCALL, "genPcall" },
76 { FUNCTION, "genFunction" },
77 { ENDFUNCTION, "genEndFunction" },
79 { LABEL, "genLabel" },
88 { EQ_OP, "genCmpEq" },
89 { AND_OP, "genAndOp" },
93 { BITWISEAND, "genAnd" },
94 { INLINEASM, "genInline" },
97 { GETHBIT, "genHBIT" },
98 { LEFT_OP, "genLeftShift" },
99 { RIGHT_OP, "genRightShift" },
100 { GET_VALUE_AT_ADDRESS, "genPointerGet" },
101 { '=', "genAssign" },
103 { ADDRESS_OF, "genAddrOf" },
104 { JUMPTABLE, "genJumpTab" },
106 { RECEIVE, "genReceive" },
111 // Possible return codes for a find matcher.
114 // This element does match.
116 FIND_GREATER_THAN = 1,
117 // This element doesnt match.
118 FIND_NO_MATCH = FIND_GREATER_THAN,
119 // This element marks the end of list.
123 // Limits the given integer to the find result numbers.
124 static int _limitToFind(int i)
127 return FIND_LESS_THAN;
130 return FIND_GREATER_THAN;
137 // Matches an opname id to the given id.
138 static int _opnamesMatcher(void *pthis, void *pkey)
140 OPNAME *name = pthis;
142 if (name->name == NULL) {
146 return _limitToFind(name->op - *(int *)pkey);
150 // Find an element of an unordered list.
151 static void *_find(void *base, size_t elemSize, void *pkey, int (*match)(void *pthis, void *pkey))
154 switch (match(base, pkey)) {
160 case FIND_GREATER_THAN:
161 base = (char *)base + elemSize;
169 // Finds the friendly operation name for an op number.
170 static const char *_findOpName(int op) {
171 OPNAME *name = _find(_opnames, sizeof(*_opnames), &op, _opnamesMatcher);
181 static bool _isResultRemat (iCode *ic)
183 if (SKIP_IC(ic) || ic->op == IFX)
186 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
187 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
188 if (sym->remat && !POINTER_SET(ic))
195 // Print out the generated lines.
196 static void _printLines(void)
198 // Currently a holder function. The Z80 needs some special mangling
200 printLine(_G.lines.head, codeOutFile);
203 void izt_initEmitters(void)
205 _G.htabs.base = newHashTable(100);
206 _G.htabs.proc = newHashTable(100);
208 izt_initBaseEmitters(&_G.htabs.base);
211 static int _emitterCompare(const void *p1, const void *p2)
215 return ((EMITTER *)p1)->op == ((EMITTER *)p2)->op;
218 static bool _tryEmittingiCode(hTab *h, iCode *ic)
220 EMITTER key = { ic->op, NULL };
223 found = hTabFindByKey(h, ic->op, &key, _emitterCompare);
234 // Add a NULL terminated array of emitters into the given hash table.
235 void izt_addEmittersToHTab(hTab **into, EMITTER _base_emitters[])
237 while (_base_emitters->emit != NULL) {
238 hTabAddItemLong(into, _base_emitters->op, _base_emitters, _base_emitters);
243 void izt_gen(iCode *iic)
248 _G.lines.head = NULL;
249 _G.lines.current = NULL;
251 // No debug info support.
253 for (; ic; ic = ic->next) {
256 // Print out the source file line number.
257 if (cln != ic->lineno) {
258 iemit("; %s %d", ic->filename, ic->lineno);
263 // Code has already been generated. Skip.
266 if (_isResultRemat(ic)) {
267 // The code is spilt and remat. - no need to generate.
271 // Print the friendly name of the operation, if it has one.
272 name = _findOpName(ic->op);
277 iemit("; warning: unrecognised operation name for %u", ic->op);
281 // Now actually call the code generator.
282 // The current processor handler gets first try.
283 if (_tryEmittingiCode(_G.htabs.proc, ic)) {
286 else if (_tryEmittingiCode(_G.htabs.base, ic)) {
287 // Base handler took it.
290 // None took it. Warn the developer.
291 iemit("; warning: no handler for code %u", ic->op);
295 // Pass the code through the peephole optimiser.
296 if (!options.nopeep) {
297 peepHole(&_G.lines.head);
300 // And emit the remainder.