blob: 0f1367cef6b9402ec91c8c16bc1267c769bf2dfa [file] [log] [blame]
Eric Biedermanb138ac82003-04-22 18:44:01 +00001#include <stdarg.h>
2#include <errno.h>
3#include <stdint.h>
4#include <stdlib.h>
5#include <stdio.h>
6#include <sys/types.h>
7#include <sys/stat.h>
8#include <fcntl.h>
9#include <unistd.h>
10#include <stdio.h>
11#include <string.h>
12#include <ctype.h>
13#include <limits.h>
14
15#define DEBUG_ERROR_MESSAGES 0
16#define DEBUG_COLOR_GRAPH 0
17#define DEBUG_SCC 0
18#define X86_4_8BIT_GPRS 1
19
20#warning "FIXME static constant variables"
21#warning "FIXME enable pointers"
22#warning "FIXME enable string constants"
23
24/* Control flow graph of a loop without goto.
25 *
26 * AAA
27 * +---/
28 * /
29 * / +--->CCC
30 * | | / \
31 * | | DDD EEE break;
32 * | | \ \
33 * | | FFF \
34 * \| / \ \
35 * |\ GGG HHH | continue;
36 * | \ \ | |
37 * | \ III | /
38 * | \ | / /
39 * | vvv /
40 * +----BBB /
41 * | /
42 * vv
43 * JJJ
44 *
45 *
46 * AAA
47 * +-----+ | +----+
48 * | \ | / |
49 * | BBB +-+ |
50 * | / \ / | |
51 * | CCC JJJ / /
52 * | / \ / /
53 * | DDD EEE / /
54 * | | +-/ /
55 * | FFF /
56 * | / \ /
57 * | GGG HHH /
58 * | | +-/
59 * | III
60 * +--+
61 *
62 *
63 * DFlocal(X) = { Y <- Succ(X) | idom(Y) != X }
64 * DFup(Z) = { Y <- DF(Z) | idom(Y) != X }
65 *
66 *
67 * [] == DFlocal(X) U DF(X)
68 * () == DFup(X)
69 *
70 * Dominator graph of the same nodes.
71 *
72 * AAA AAA: [ ] ()
73 * / \
74 * BBB JJJ BBB: [ JJJ ] ( JJJ ) JJJ: [ ] ()
75 * |
76 * CCC CCC: [ ] ( BBB, JJJ )
77 * / \
78 * DDD EEE DDD: [ ] ( BBB ) EEE: [ JJJ ] ()
79 * |
80 * FFF FFF: [ ] ( BBB )
81 * / \
82 * GGG HHH GGG: [ ] ( BBB ) HHH: [ BBB ] ()
83 * |
84 * III III: [ BBB ] ()
85 *
86 *
87 * BBB and JJJ are definitely the dominance frontier.
88 * Where do I place phi functions and how do I make that decision.
89 *
90 */
91static void die(char *fmt, ...)
92{
93 va_list args;
94
95 va_start(args, fmt);
96 vfprintf(stderr, fmt, args);
97 va_end(args);
98 fflush(stdout);
99 fflush(stderr);
100 exit(1);
101}
102
103#define MALLOC_STRONG_DEBUG
104static void *xmalloc(size_t size, const char *name)
105{
106 void *buf;
107 buf = malloc(size);
108 if (!buf) {
109 die("Cannot malloc %ld bytes to hold %s: %s\n",
110 size + 0UL, name, strerror(errno));
111 }
112 return buf;
113}
114
115static void *xcmalloc(size_t size, const char *name)
116{
117 void *buf;
118 buf = xmalloc(size, name);
119 memset(buf, 0, size);
120 return buf;
121}
122
123static void xfree(const void *ptr)
124{
125 free((void *)ptr);
126}
127
128static char *xstrdup(const char *str)
129{
130 char *new;
131 int len;
132 len = strlen(str);
133 new = xmalloc(len + 1, "xstrdup string");
134 memcpy(new, str, len);
135 new[len] = '\0';
136 return new;
137}
138
139static void xchdir(const char *path)
140{
141 if (chdir(path) != 0) {
142 die("chdir to %s failed: %s\n",
143 path, strerror(errno));
144 }
145}
146
147static int exists(const char *dirname, const char *filename)
148{
149 int does_exist = 1;
150 xchdir(dirname);
151 if (access(filename, O_RDONLY) < 0) {
152 if ((errno != EACCES) && (errno != EROFS)) {
153 does_exist = 0;
154 }
155 }
156 return does_exist;
157}
158
159
160static char *slurp_file(const char *dirname, const char *filename, off_t *r_size)
161{
162 int fd;
163 char *buf;
164 off_t size, progress;
165 ssize_t result;
166 struct stat stats;
167
168 if (!filename) {
169 *r_size = 0;
170 return 0;
171 }
172 xchdir(dirname);
173 fd = open(filename, O_RDONLY);
174 if (fd < 0) {
175 die("Cannot open '%s' : %s\n",
176 filename, strerror(errno));
177 }
178 result = fstat(fd, &stats);
179 if (result < 0) {
180 die("Cannot stat: %s: %s\n",
181 filename, strerror(errno));
182 }
183 size = stats.st_size;
184 *r_size = size +1;
185 buf = xmalloc(size +2, filename);
186 buf[size] = '\n'; /* Make certain the file is newline terminated */
187 buf[size+1] = '\0'; /* Null terminate the file for good measure */
188 progress = 0;
189 while(progress < size) {
190 result = read(fd, buf + progress, size - progress);
191 if (result < 0) {
192 if ((errno == EINTR) || (errno == EAGAIN))
193 continue;
194 die("read on %s of %ld bytes failed: %s\n",
195 filename, (size - progress)+ 0UL, strerror(errno));
196 }
197 progress += result;
198 }
199 result = close(fd);
200 if (result < 0) {
201 die("Close of %s failed: %s\n",
202 filename, strerror(errno));
203 }
204 return buf;
205}
206
207/* Long on the destination platform */
208typedef unsigned long ulong_t;
209typedef long long_t;
210
211struct file_state {
212 struct file_state *prev;
213 const char *basename;
214 char *dirname;
215 char *buf;
216 off_t size;
217 char *pos;
218 int line;
219 char *line_start;
220};
221struct hash_entry;
222struct token {
223 int tok;
224 struct hash_entry *ident;
225 int str_len;
226 union {
227 ulong_t integer;
228 const char *str;
229 } val;
230};
231
232/* I have two classes of types:
233 * Operational types.
234 * Logical types. (The type the C standard says the operation is of)
235 *
236 * The operational types are:
237 * chars
238 * shorts
239 * ints
240 * longs
241 *
242 * floats
243 * doubles
244 * long doubles
245 *
246 * pointer
247 */
248
249
250/* Machine model.
251 * No memory is useable by the compiler.
252 * There is no floating point support.
253 * All operations take place in general purpose registers.
254 * There is one type of general purpose register.
255 * Unsigned longs are stored in that general purpose register.
256 */
257
258/* Operations on general purpose registers.
259 */
260
261#define OP_SMUL 0
262#define OP_UMUL 1
263#define OP_SDIV 2
264#define OP_UDIV 3
265#define OP_SMOD 4
266#define OP_UMOD 5
267#define OP_ADD 6
268#define OP_SUB 7
269#define OP_SL 8
270#define OP_USR 9
271#define OP_SSR 10
272#define OP_AND 11
273#define OP_XOR 12
274#define OP_OR 13
275#define OP_POS 14 /* Dummy positive operator don't use it */
276#define OP_NEG 15
277#define OP_INVERT 16
278
279#define OP_EQ 20
280#define OP_NOTEQ 21
281#define OP_SLESS 22
282#define OP_ULESS 23
283#define OP_SMORE 24
284#define OP_UMORE 25
285#define OP_SLESSEQ 26
286#define OP_ULESSEQ 27
287#define OP_SMOREEQ 28
288#define OP_UMOREEQ 29
289
290#define OP_LFALSE 30 /* Test if the expression is logically false */
291#define OP_LTRUE 31 /* Test if the expression is logcially true */
292
293#define OP_LOAD 32
294#define OP_STORE 33
295
296#define OP_NOOP 34
297
298#define OP_MIN_CONST 50
299#define OP_MAX_CONST 59
300#define IS_CONST_OP(X) (((X) >= OP_MIN_CONST) && ((X) <= OP_MAX_CONST))
301#define OP_INTCONST 50
302#define OP_BLOBCONST 51
303/* For OP_BLOBCONST triple->type holds the layout and size
304 * information. u.blob holds a pointer to the raw binary
305 * data for the constant initializer.
306 */
307#define OP_ADDRCONST 52
308/* For OP_ADDRCONST triple->type holds the type.
309 * triple->left holds the reference to the static variable.
310 * triple->u.cval holds an offset from that value.
311 */
312
313#define OP_WRITE 60
314/* OP_WRITE moves one pseudo register to another.
315 * triple->left holds the destination pseudo register,
316 * must be an OP_DECL.
317 * triple->right holds the psuedo to move.
318 */
319
320#define OP_READ 61
321/* OP_READ reads the value of a variable and makes
322 * it available for the pseudo operation.
323 * Useful for things like def-use chains.
324 * triple->left holds points to the triple to read from.
325 */
326#define OP_COPY 62
327/* OP_COPY makes a copy of the psedo register or constant in op->left.
328 */
329
330/* Hard operations that I don't know if they are worth supporting */
331#define OP_DEREF 65
332/* OP_DEREF generates an lvalue from a pointer.
333 * triple->left holds the pointer value.
334 * OP_DEREF serves as a place holder to indicate all necessary
335 * checks have been done to indicate a value is an lvalue.
336 */
337#define OP_DOT 66
338
339#define OP_VAL 67
340/* OP_VAL returns the value of a subexpression of the current expression.
341 * Useful for operators that have side effects.
342 * triple->left holds the expression.
343 * triple->right holds the subexpression of triple->left that is the
344 * value of the expression.
345 *
346 * Not seen outside of expressions.
347 */
348#define OP_LAND 68
349/* OP_LAND performs a C logical and between triple->left and triple->right.
350 * Not seen outside of expressions.
351 */
352#define OP_LOR 69
353/* OP_LOR performs a C logical or between triple->left and triple->right.
354 * Not seen outside of expressions.
355 */
356#define OP_COND 70
357/* OP_CODE performas a C ? : operation.
358 * triple->left holds the test.
359 * triple->right holds an OP_PRODUCT triple.
360 * triple->right->left holds the expression to evaluate if
361 * the test returns true.
362 * triple->right->right holds the expression to evaluate if
363 * the test returns false.
364 * Not seen outside of expressions.
365 */
366#define OP_COMMA 71
367/* OP_COMMA performacs a C comma operation.
368 * That is triple->left is evaluated, then triple->right
369 * and the value of triple->right is returned.
370 * Not seen outside of expressions.
371 */
372
373#define OP_CALL 72
374/* OP_CALL performs a procedure call.
375 * triple->left holda a pointer to the OP_LIST of a function
376 * triple->right holds a pointer either a single argument
377 * or a list of arguments. The list is formed by inserting
378 * OP_PRODUCT triples inbetween the argument values.
379 * Currently not seen outside of expressions.
380 */
381#define OP_PRODUCT 73
382/* OP_PRODUCT is a utility triple, both triple->left and triple->right
383 * are used. Other opcodes OP_CALL, and OP_COND use it increase
384 * the number of triple pointers in a triple.
385 * Currently Not seen outside of expressions.
386 */
387
388/* statements */
389#define OP_LIST 80
390/* OP_LIST Holds a list of statements, and a result value.
391 * triple->left holds the list of statements.
392 * triple->right holds the value of the statements.
393 * triple->right must be the last statement in the list.
394 */
395
396#define OP_BRANCH 81 /* branch */
397/* For branch instructions
398 * triple->left holds the branch target.
399 * triple->right holds the branch condition.
400 * triple->next holds where to branch to if the branch is not taken.
401 * The branch target can only be a decl...
402 */
403
404#define OP_LABEL 83
405/* OP_LABEL is a triple that establishes an target for branches.
406 * triple->use is the list of all branches that use this label.
407 */
408
409#define OP_ADECL 84
410/* OP_DECL is a triple that establishes an lvalue for assignments.
411 * triple->use is a list of statements that use the variable.
412 */
413
414#define OP_SDECL 85
415/* OP_VAR is a triple that establishes a variable of static
416 * storage duration.
417 * triple->use is a list of statements that use the variable.
418 * triple->left holds the initializer expression.
419 */
420
421
422#define OP_PHI 86
423/* OP_PHI is a triple used in SSA form code.
424 * It is used when multiple code paths merge and a variable needs
425 * a single assignment from any of those code paths.
426 * The operation is a cross between OP_DECL and OP_WRITE, which
427 * is what OP_PHI is geneared from.
428 *
429 * triple->left points to an array of pointers to triple.
430 * The size of the array is the number of control paths into the block
431 * in which OP_PHI resides. The elements of the array point to point
432 * to the variables OP_PHI is derived from.
433 *
434 * triple->right holds a pointer to the original OP_DECL node
435 */
436
437/* Architecture specific instructions */
438#define OP_CMP 100
439#define OP_TEST 101
440#define OP_SET_EQ 102
441#define OP_SET_NOTEQ 103
442#define OP_SET_SLESS 104
443#define OP_SET_ULESS 105
444#define OP_SET_SMORE 106
445#define OP_SET_UMORE 107
446#define OP_SET_SLESSEQ 108
447#define OP_SET_ULESSEQ 109
448#define OP_SET_SMOREEQ 110
449#define OP_SET_UMOREEQ 111
450
451#define OP_JMP 112
452#define OP_JMP_EQ 113
453#define OP_JMP_NOTEQ 114
454#define OP_JMP_SLESS 115
455#define OP_JMP_ULESS 116
456#define OP_JMP_SMORE 117
457#define OP_JMP_UMORE 118
458#define OP_JMP_SLESSEQ 119
459#define OP_JMP_ULESSEQ 120
460#define OP_JMP_SMOREEQ 121
461#define OP_JMP_UMOREEQ 122
462
463/* Builtin operators that it is just simpler to use the compiler for */
464#define OP_INB 130
465#define OP_INW 131
466#define OP_INL 132
467#define OP_OUTB 133
468#define OP_OUTW 134
469#define OP_OUTL 135
470#define OP_BSF 136
471#define OP_BSR 137
472#warning "FIXME implement rdmsr wrmsr"
473#if 0
474/* I need to implement these but, I need to implment > 32bit return
475 * values first.
476 */
477#define OP_RDMSR 138
478#define OP_WRMSR 139
479#endif
480#define OP_HLT 140
481
482static const char *table_ops[] = {
483[OP_SMUL ] = "smul",
484[OP_UMUL ] = "umul",
485[OP_SDIV ] = "sdiv",
486[OP_UDIV ] = "udiv",
487[OP_SMOD ] = "smod",
488[OP_UMOD ] = "umod",
489[OP_ADD ] = "add",
490[OP_SUB ] = "sub",
491[OP_SL ] = "sl",
492[OP_USR ] = "usr",
493[OP_SSR ] = "ssr",
494[OP_AND ] = "and",
495[OP_XOR ] = "xor",
496[OP_OR ] = "or",
497[OP_POS ] = "pos",
498[OP_NEG ] = "neg",
499[OP_INVERT ] = "invert",
500
501[OP_EQ ] = "eq",
502[OP_NOTEQ ] = "noteq",
503[OP_SLESS ] = "sless",
504[OP_ULESS ] = "uless",
505[OP_SMORE ] = "smore",
506[OP_UMORE ] = "umore",
507[OP_SLESSEQ ] = "slesseq",
508[OP_ULESSEQ ] = "ulesseq",
509[OP_SMOREEQ ] = "smoreeq",
510[OP_UMOREEQ ] = "umoreeq",
511[OP_LFALSE ] = "lfalse",
512[OP_LTRUE ] = "ltrue",
513
514[OP_LOAD ] = "load",
515[OP_STORE ] = "store",
516
517[OP_NOOP ] = "noop",
518
519[OP_INTCONST ] = "intconst",
520[OP_BLOBCONST ] = "blobconst",
521[OP_ADDRCONST ] = "addrconst",
522
523[OP_WRITE ] = "write",
524[OP_READ ] = "read",
525[OP_COPY ] = "copy",
526[OP_DEREF ] = "deref",
527[OP_DOT ] = "dot",
528
529[OP_VAL ] = "val",
530[OP_LAND ] = "land",
531[OP_LOR ] = "lor",
532[OP_COND ] = "cond",
533[OP_COMMA ] = "comma",
534[OP_CALL ] = "call",
535[OP_PRODUCT ] = "product",
536
537[OP_LIST ] = "list",
538[OP_BRANCH ] = "branch",
539[OP_LABEL ] = "label",
540[OP_ADECL ] = "adecl",
541[OP_SDECL ] = "sdecl",
542[OP_PHI ] = "phi",
543
544[OP_CMP ] = "cmp",
545[OP_TEST ] = "test",
546[OP_SET_EQ ] = "set_eq",
547[OP_SET_NOTEQ ] = "set_noteq",
548[OP_SET_SLESS ] = "set_sless",
549[OP_SET_ULESS ] = "set_uless",
550[OP_SET_SMORE ] = "set_smore",
551[OP_SET_SMORE ] = "set_umore",
552[OP_SET_SLESSEQ] = "set_slesseq",
553[OP_SET_ULESSEQ] = "set_ulesseq",
554[OP_SET_SMOREEQ] = "set_smoreq",
555[OP_SET_UMOREEQ] = "set_umoreq",
556[OP_JMP ] = "jmp",
557[OP_JMP_EQ ] = "jmp_eq",
558[OP_JMP_NOTEQ ] = "jmp_noteq",
559[OP_JMP_SLESS ] = "jmp_sless",
560[OP_JMP_ULESS ] = "jmp_uless",
561[OP_JMP_SMORE ] = "jmp_smore",
562[OP_JMP_SMORE ] = "jmp_umore",
563[OP_JMP_SLESSEQ] = "jmp_slesseq",
564[OP_JMP_ULESSEQ] = "jmp_ulesseq",
565[OP_JMP_SMOREEQ] = "jmp_smoreq",
566[OP_JMP_UMOREEQ] = "jmp_umoreq",
567
568[OP_INB ] = "__inb",
569[OP_INW ] = "__inw",
570[OP_INL ] = "__inl",
571[OP_OUTB ] = "__outb",
572[OP_OUTW ] = "__outw",
573[OP_OUTL ] = "__outl",
574[OP_BSF ] = "__bsf",
575[OP_BSR ] = "__bsr",
576[OP_HLT ] = "__hlt",
577
578};
579
580#define OP_MAX (sizeof(table_ops)/sizeof(table_ops[0]))
581
582
583static const char *tops(int index)
584{
585 static const char unknown[] = "unknown op";
586 if (index < 0) {
587 return unknown;
588 }
589 if (index > OP_MAX) {
590 return unknown;
591 }
592 return table_ops[index];
593}
594
595#warning "FIXME Finish defining struct type"
596
597struct triple;
598struct block;
599struct triple_set {
600 struct triple_set *next;
601 struct triple *member;
602};
603
604struct triple {
605 struct triple *next, *prev;
606 struct triple_set *use;
607 struct type *type;
608 int op;
609 unsigned id; /* A scratch value and finally the register */
610 struct triple *left;
611 struct triple *right;
612 union {
613 ulong_t cval;
614 struct block *block;
615 void *blob;
616 } u;
617 const char *filename;
618 int line;
619 int col;
620};
621
622struct block_set {
623 struct block_set *next;
624 struct block *member;
625};
626struct block {
627 struct block *work_next;
628 struct block *left, *right;
629 struct triple *first, *last;
630 int users;
631 struct block_set *use;
632 struct block_set *idominates;
633 struct block_set *domfrontier;
634 struct block *idom;
635 struct block_set *ipdominates;
636 struct block_set *ipdomfrontier;
637 struct block *ipdom;
638 int vertex;
639
640};
641
642struct symbol {
643 struct symbol *next;
644 struct hash_entry *ident;
645 struct triple *def;
646 struct type *type;
647 int scope_depth;
648};
649
650struct macro {
651 struct hash_entry *ident;
652 char *buf;
653 int buf_len;
654};
655
656struct hash_entry {
657 struct hash_entry *next;
658 const char *name;
659 int name_len;
660 int tok;
661 struct macro *sym_define;
662 struct symbol *sym_label;
663 struct symbol *sym_struct;
664 struct symbol *sym_ident;
665};
666
667#define HASH_TABLE_SIZE 2048
668
669struct compile_state {
670 struct triple *vars;
671 struct file_state *file;
672 struct token token[4];
673 struct hash_entry *hash_table[HASH_TABLE_SIZE];
674 struct hash_entry *i_continue;
675 struct hash_entry *i_break;
676 int scope_depth;
677 int if_depth, if_value;
678 int macro_line;
679 struct file_state *macro_file;
680 struct triple *main_function;
681 struct block *first_block, *last_block;
682 int last_vertex;
683 int debug;
684 int optimize;
685};
686
687#define MAX_REGISTERS 75
688#define MAX_REG_EQUIVS 16
689#define MAX_REGC 12
690#define REG_UNSET 0
691
692/* Provision for 8 register classes */
693#define REGC_MASK ((1 << MAX_REGC) - 1)
694#define ID_REG_CLASSES(ID) ((ID) & REGC_MASK)
695#define ID_REG(ID) ((ID) >> MAX_REGC)
696#define MK_REG_ID(REG, CLASSES) (((REG) << MAX_REGC) | ((CLASSES) & REGC_MASK))
697
698static unsigned alloc_virtual_reg(void)
699{
700 static unsigned virtual_reg = MAX_REGISTERS;
701 virtual_reg += 1;
702 return virtual_reg;
703}
704
705static unsigned arch_reg_regcm(struct compile_state *state, int reg);
706static void arch_reg_equivs(
707 struct compile_state *state, unsigned *equiv, int reg);
708static int arch_select_free_register(
709 struct compile_state *state, char *used, int classes);
710static unsigned arch_regc_size(struct compile_state *state, int class);
711static int arch_regcm_intersect(unsigned regcm1, unsigned regcm2);
712static unsigned arch_type_to_regcm(struct compile_state *state, struct type *type);
713static const char *arch_reg_str(int reg);
714
715#define DEBUG_INTERMEDIATE_CODE 0x0001
716#define DEBUG_CONTROL_FLOW 0x0002
717#define DEBUG_BASIC_BLOCKS 0x0004
718#define DEBUG_FDOMINATORS 0x0008
719#define DEBUG_RDOMINATORS 0x0010
720#define DEBUG_TRIPLES 0x0020
721#define DEBUG_INTERFERENCE 0x0040
722#define DEBUG_ARCH_CODE 0x0080
723#define DEBUG_CODE_ELIMINATION 0x0100
724
725#define GLOBAL_SCOPE_DEPTH 1
726
727static void compile_file(struct compile_state *old_state, char *filename, int local);
728
729static int get_col(struct file_state *file)
730{
731 int col;
732 char *ptr, *end;
733 ptr = file->line_start;
734 end = file->pos;
735 for(col = 0; ptr < end; ptr++) {
736 if (*ptr != '\t') {
737 col++;
738 }
739 else {
740 col = (col & ~7) + 8;
741 }
742 }
743 return col;
744}
745
746static void loc(FILE *fp, struct compile_state *state, struct triple *triple)
747{
748 int col;
749 if (triple) {
750 fprintf(fp, "%s:%d.%d: ",
751 triple->filename, triple->line, triple->col);
752 return;
753 }
754 if (!state->file) {
755 return;
756 }
757 col = get_col(state->file);
758 fprintf(fp, "%s:%d.%d: ",
759 state->file->basename, state->file->line, col);
760}
761
762static void __internal_error(struct compile_state *state, struct triple *ptr,
763 char *fmt, ...)
764{
765 va_list args;
766 va_start(args, fmt);
767 loc(stderr, state, ptr);
768 fprintf(stderr, "Internal compiler error: ");
769 vfprintf(stderr, fmt, args);
770 fprintf(stderr, "\n");
771 va_end(args);
772 abort();
773}
774
775
776static void __internal_warning(struct compile_state *state, struct triple *ptr,
777 char *fmt, ...)
778{
779 va_list args;
780 va_start(args, fmt);
781 loc(stderr, state, ptr);
782 fprintf(stderr, "Internal compiler warning: ");
783 vfprintf(stderr, fmt, args);
784 fprintf(stderr, "\n");
785 va_end(args);
786}
787
788
789
790static void __error(struct compile_state *state, struct triple *ptr,
791 char *fmt, ...)
792{
793 va_list args;
794 va_start(args, fmt);
795 loc(stderr, state, ptr);
796 vfprintf(stderr, fmt, args);
797 va_end(args);
798 fprintf(stderr, "\n");
799 exit(1);
800}
801
802static void __warning(struct compile_state *state, struct triple *ptr,
803 char *fmt, ...)
804{
805 va_list args;
806 va_start(args, fmt);
807 loc(stderr, state, ptr);
808 fprintf(stderr, "warning: ");
809 vfprintf(stderr, fmt, args);
810 fprintf(stderr, "\n");
811 va_end(args);
812}
813
814#if DEBUG_ERROR_MESSAGES
815# define internal_error fprintf(stderr, "@ %s.%s:%d \t", __FILE__, __func__, __LINE__),__internal_error
816# define internal_warning fprintf(stderr, "@ %s.%s:%d \t", __FILE__, __func__, __LINE__),__internal_warning
817# define error fprintf(stderr, "@ %s.%s:%d \t", __FILE__, __func__, __LINE__),__error
818# define warning fprintf(stderr, "@ %s.%s:%d \t", __FILE__, __func__, __LINE__),__warning
819#else
820# define internal_error __internal_error
821# define internal_warning __internal_warning
822# define error __error
823# define warning __warning
824#endif
825#define FINISHME() warning(state, 0, "FINISHME @ %s.%s:%d", __FILE__, __func__, __LINE__)
826
827
828static void valid_op(struct compile_state *state, struct triple *ptr)
829{
830 char *fmt = "invalid op: %d";
831 if (ptr->op >= OP_MAX) {
832 internal_error(state, 0, fmt, ptr->op);
833 }
834 if (ptr->op < 0) {
835 internal_error(state, 0, fmt, ptr->op);
836 }
837}
838
839static void process_trigraphs(struct compile_state *state)
840{
841 char *src, *dest, *end;
842 struct file_state *file;
843 file = state->file;
844 src = dest = file->buf;
845 end = file->buf + file->size;
846 while((end - src) >= 3) {
847 if ((src[0] == '?') && (src[1] == '?')) {
848 int c = -1;
849 switch(src[2]) {
850 case '=': c = '#'; break;
851 case '/': c = '\\'; break;
852 case '\'': c = '^'; break;
853 case '(': c = '['; break;
854 case ')': c = ']'; break;
855 case '!': c = '!'; break;
856 case '<': c = '{'; break;
857 case '>': c = '}'; break;
858 case '-': c = '~'; break;
859 }
860 if (c != -1) {
861 *dest++ = c;
862 src += 3;
863 }
864 else {
865 *dest++ = *src++;
866 }
867 }
868 else {
869 *dest++ = *src++;
870 }
871 }
872 while(src != end) {
873 *dest++ = *src++;
874 }
875 file->size = dest - file->buf;
876}
877
878static void splice_lines(struct compile_state *state)
879{
880 char *src, *dest, *end;
881 struct file_state *file;
882 file = state->file;
883 src = dest = file->buf;
884 end = file->buf + file->size;
885 while((end - src) >= 2) {
886 if ((src[0] == '\\') && (src[1] == '\n')) {
887 src += 2;
888 }
889 else {
890 *dest++ = *src++;
891 }
892 }
893 while(src != end) {
894 *dest++ = *src++;
895 }
896 file->size = dest - file->buf;
897}
898
899static struct type void_type;
900static void use_triple(struct triple *used, struct triple *user)
901{
902 struct triple_set **ptr, *new;
903 if (!used)
904 return;
905 if (!user)
906 return;
907 ptr = &used->use;
908 while(*ptr) {
909 if ((*ptr)->member == user) {
910 return;
911 }
912 ptr = &(*ptr)->next;
913 }
914 /* Append new to the head of the list,
915 * copy_func and rename_block_variables
916 * depends on this.
917 */
918 new = xcmalloc(sizeof(*new), "triple_set");
919 new->member = user;
920 new->next = used->use;
921 used->use = new;
922}
923
924static void unuse_triple(struct triple *used, struct triple *unuser)
925{
926 struct triple_set *use, **ptr;
927 ptr = &used->use;
928 while(*ptr) {
929 use = *ptr;
930 if (use->member == unuser) {
931 *ptr = use->next;
932 xfree(use);
933 }
934 else {
935 ptr = &use->next;
936 }
937 }
938}
939
940static void push_triple(struct triple *used, struct triple *user)
941{
942 struct triple_set *new;
943 if (!used)
944 return;
945 if (!user)
946 return;
947 /* Append new to the head of the list,
948 * it's the only sensible behavoir for a stack.
949 */
950 new = xcmalloc(sizeof(*new), "triple_set");
951 new->member = user;
952 new->next = used->use;
953 used->use = new;
954}
955
956static void pop_triple(struct triple *used, struct triple *unuser)
957{
958 struct triple_set *use, **ptr;
959 ptr = &used->use;
960 while(*ptr) {
961 use = *ptr;
962 if (use->member == unuser) {
963 *ptr = use->next;
964 xfree(use);
965 /* Only free one occurance from the stack */
966 return;
967 }
968 else {
969 ptr = &use->next;
970 }
971 }
972}
973
974
975/* The zero triple is used as a place holder when we are removing pointers
976 * from a triple. Having allows certain sanity checks to pass even
977 * when the original triple that was pointed to is gone.
978 */
979static struct triple zero_triple = {
980 .next = &zero_triple,
981 .prev = &zero_triple,
982 .use = 0,
983 .op = OP_INTCONST,
984 .id = -1, /* An invalid id */
985 .left = 0,
986 .right = 0,
987 .u = { .cval = 0, },
988 .filename = __FILE__,
989 .line = __LINE__,
990};
991
992static struct triple *build_triple(struct compile_state *state,
993 int op, struct type *type, struct triple *left, struct triple *right,
994 const char *filename, int line, int col)
995{
996 struct triple *ret;
997 ret = xcmalloc(sizeof(*ret), "tripple");
998 ret->op = op;
999 ret->type = type;
1000 ret->left = left;
1001 ret->right = right;
1002 ret->next = ret;
1003 ret->prev = ret;
1004 ret->filename = filename;
1005 ret->line = line;
1006 ret->col = col;
1007 return ret;
1008}
1009
1010static struct triple *triple(struct compile_state *state,
1011 int op, struct type *type, struct triple *left, struct triple *right)
1012{
1013 struct triple *ret;
1014 const char *filename;
1015 int line, col;
1016 filename = 0;
1017 line = 0;
1018 col = 0;
1019 if (state->file) {
1020 filename = state->file->basename;
1021 line = state->file->line;
1022 col = get_col(state->file);
1023 }
1024 ret = build_triple(state, op, type, left, right, filename, line, col);
1025 /* record the branch target was used */
1026 if (ret->op == OP_BRANCH) {
1027 if (!left || (left->op != OP_LABEL)) {
1028 internal_error(state, 0, "branch not to label");
1029 }
1030 use_triple(left, ret);
1031 }
1032 return ret;
1033}
1034
1035static void insert_triple(struct compile_state *state,
1036 struct triple *first, struct triple *ptr)
1037{
1038 if (ptr) {
1039 if (ptr->next != ptr) {
1040 internal_error(state, ptr, "expression already used");
1041 }
1042 ptr->next = first;
1043 ptr->prev = first->prev;
1044 ptr->prev->next = ptr;
1045 ptr->next->prev = ptr;
1046 if ((ptr->prev->op == OP_BRANCH) && (ptr->prev->right)) {
1047 unuse_triple(first, ptr->prev);
1048 use_triple(ptr, ptr->prev);
1049 }
1050 }
1051}
1052
1053static struct triple *pre_triple(struct compile_state *state,
1054 struct triple *base,
1055 int op, struct type *type, struct triple *left, struct triple *right)
1056{
1057 /* Careful this assumes it can do the easy thing to get the block */
1058 struct triple *ret;
1059 ret = build_triple(state, op, type, left, right,
1060 base->filename, base->line, base->col);
1061 ret->u.block = base->u.block;
1062 insert_triple(state, base, ret);
1063 return ret;
1064}
1065
1066static struct triple *post_triple(struct compile_state *state,
1067 struct triple *base,
1068 int op, struct type *type, struct triple *left, struct triple *right)
1069{
1070 /* Careful this assumes it can do the easy thing to get the block */
1071 struct triple *ret;
1072 ret = build_triple(state, op, type, left, right,
1073 base->filename, base->line, base->col);
1074 ret->u.block = base->u.block;
1075 insert_triple(state, base->next, ret);
1076 return ret;
1077}
1078
1079static struct triple *label(struct compile_state *state)
1080{
1081 /* Labels don't get a type */
1082 struct triple *result;
1083 result = triple(state, OP_LABEL, &void_type, 0, 0);
1084 return result;
1085}
1086
1087static int triple_is_pure(struct compile_state *state, struct triple *ins)
1088{
1089 /* Does the triple have no side effects.
1090 * I.e. Rexecuting the triple with the same arguments
1091 * gives the same value.
1092 */
1093 int pure;
1094 switch(ins->op) {
1095 case OP_SMUL: case OP_UMUL:
1096 case OP_SDIV: case OP_UDIV:
1097 case OP_SMOD: case OP_UMOD:
1098 case OP_ADD: case OP_SUB:
1099 case OP_SL:
1100 case OP_USR: case OP_SSR:
1101 case OP_AND:
1102 case OP_XOR:
1103 case OP_OR:
1104 case OP_POS: case OP_NEG:
1105 case OP_INVERT:
1106 case OP_EQ: case OP_NOTEQ:
1107 case OP_SLESS: case OP_ULESS: case OP_SMORE: case OP_UMORE:
1108 case OP_SLESSEQ: case OP_ULESSEQ: case OP_SMOREEQ: case OP_UMOREEQ:
1109 case OP_LFALSE: case OP_LTRUE:
1110 case OP_NOOP:
1111 case OP_INTCONST:
1112 case OP_BLOBCONST:
1113 case OP_ADDRCONST:
1114
1115 case OP_WRITE:
1116 case OP_READ:
1117 case OP_COPY:
1118 case OP_BRANCH:
1119 case OP_LABEL:
1120 case OP_ADECL:
1121 case OP_SDECL:
1122 case OP_PHI:
1123
1124
1125 case OP_CMP:
1126 case OP_TEST:
1127 case OP_SET_EQ: case OP_SET_NOTEQ:
1128 case OP_SET_SLESS: case OP_SET_ULESS:
1129 case OP_SET_SMORE: case OP_SET_UMORE:
1130 case OP_SET_SLESSEQ: case OP_SET_ULESSEQ:
1131 case OP_SET_SMOREEQ: case OP_SET_UMOREEQ:
1132
1133 case OP_JMP:
1134 case OP_JMP_EQ: case OP_JMP_NOTEQ:
1135 case OP_JMP_SLESS: case OP_JMP_ULESS:
1136 case OP_JMP_SMORE: case OP_JMP_UMORE:
1137 case OP_JMP_SLESSEQ: case OP_JMP_ULESSEQ:
1138 case OP_JMP_SMOREEQ: case OP_JMP_UMOREEQ:
1139
1140 case OP_BSF: case OP_BSR:
1141 pure = 1;
1142 break;
1143 case OP_LOAD: case OP_STORE:
1144 case OP_INB: case OP_INW: case OP_INL:
1145 case OP_OUTB: case OP_OUTW: case OP_OUTL:
1146 case OP_HLT:
1147 pure = 0;
1148 break;
1149 default:
1150 internal_error(state, ins, "purity of %s not known",
1151 tops(ins->op));
1152 pure = 0;
1153 break;
1154 }
1155 return pure;
1156}
1157
1158static int triple_is_branch(struct triple *ins)
1159{
1160 /* This function is used to determine which triples need
1161 * a register.
1162 */
1163 int is_branch = 0;
1164 switch(ins->op) {
1165 case OP_BRANCH:
1166 case OP_JMP:
1167 case OP_JMP_EQ: case OP_JMP_NOTEQ:
1168 case OP_JMP_SLESS: case OP_JMP_ULESS:
1169 case OP_JMP_SMORE: case OP_JMP_UMORE:
1170 case OP_JMP_SLESSEQ: case OP_JMP_ULESSEQ:
1171 case OP_JMP_SMOREEQ: case OP_JMP_UMOREEQ:
1172 is_branch = 1;
1173 break;
1174 }
1175 return is_branch;
1176}
1177
1178static int triple_is_def(struct triple *ins)
1179{
1180 /* This function is used to determine which triples need
1181 * a register.
1182 */
1183 int is_def = 1;
1184 switch(ins->op) {
1185 case OP_ADECL:
1186 case OP_SDECL:
1187 case OP_LABEL:
1188 case OP_INTCONST:
1189 case OP_BLOBCONST:
1190 case OP_ADDRCONST:
1191 case OP_STORE:
1192 case OP_WRITE:
1193 case OP_NOOP:
1194 case OP_OUTB: case OP_OUTW: case OP_OUTL:
1195 case OP_BRANCH:
1196 case OP_JMP:
1197 case OP_JMP_EQ: case OP_JMP_NOTEQ:
1198 case OP_JMP_SLESS: case OP_JMP_ULESS:
1199 case OP_JMP_SMORE: case OP_JMP_UMORE:
1200 case OP_JMP_SLESSEQ: case OP_JMP_ULESSEQ:
1201 case OP_JMP_SMOREEQ: case OP_JMP_UMOREEQ:
1202 is_def = 0;
1203 break;
1204 }
1205 return is_def;
1206}
1207
1208static struct triple **triple_targ(struct compile_state *state,
1209 struct triple *triple, struct triple **last)
1210{
1211 struct triple **ret;
1212 ret = 0;
1213 switch(triple->op) {
1214 case OP_BRANCH:
1215 case OP_JMP:
1216 case OP_JMP_EQ: case OP_JMP_NOTEQ:
1217 case OP_JMP_SLESS: case OP_JMP_ULESS:
1218 case OP_JMP_SMORE: case OP_JMP_UMORE:
1219 case OP_JMP_SLESSEQ: case OP_JMP_ULESSEQ:
1220 case OP_JMP_SMOREEQ: case OP_JMP_UMOREEQ:
1221 if (!last) {
1222 ret = &triple->left;
1223 }
1224 else if ((last == &triple->left) && triple->right) {
1225 ret = &triple->next;
1226 }
1227 break;
1228 }
1229 return ret;
1230}
1231
1232static struct triple **triple_rhs(struct compile_state *state,
1233 struct triple *triple, struct triple **last)
1234{
1235 struct triple **ret;
1236 ret = 0;
1237 switch(triple->op) {
1238 /* binary operations */
1239 case OP_SMUL: case OP_UMUL: case OP_SDIV: case OP_UDIV:
1240 case OP_SMOD: case OP_UMOD: case OP_ADD: case OP_SUB:
1241 case OP_SL: case OP_USR: case OP_SSR: case OP_AND:
1242 case OP_XOR: case OP_OR: case OP_EQ: case OP_NOTEQ:
1243 case OP_SLESS: case OP_ULESS: case OP_SMORE: case OP_UMORE:
1244 case OP_SLESSEQ: case OP_ULESSEQ: case OP_SMOREEQ: case OP_UMOREEQ:
1245 case OP_CMP:
1246 case OP_OUTB: case OP_OUTW: case OP_OUTL:
1247#if 0
1248 if (!triple->left) {
1249 internal_error(state, triple, "left arg missing");
1250 }
1251 if (!triple->right) {
1252 internal_error(state, triple, "right arg missing");
1253 }
1254#endif
1255 if (!last) {
1256 ret = &triple->left;
1257 }
1258 else if (last == &triple->left){
1259 ret = &triple->right;
1260 }
1261 break;
1262 /* unary operations */
1263 case OP_POS: case OP_NEG:
1264 case OP_INVERT: case OP_LFALSE: case OP_LTRUE:
1265 case OP_COPY:
1266 case OP_TEST:
1267 case OP_SET_EQ: case OP_SET_NOTEQ:
1268 case OP_SET_SLESS: case OP_SET_ULESS:
1269 case OP_SET_SMORE: case OP_SET_UMORE:
1270 case OP_SET_SLESSEQ: case OP_SET_ULESSEQ:
1271 case OP_SET_SMOREEQ: case OP_SET_UMOREEQ:
1272 case OP_INB: case OP_INW: case OP_INL:
1273 case OP_BSF: case OP_BSR:
1274#if 0
1275 if (!triple->left) {
1276 internal_error(state, triple, "left arg missing");
1277 }
1278 if (triple->right) {
1279 internal_error(state, triple, "right arg present");
1280 }
1281#endif
1282 if (!last) {
1283 ret = &triple->left;
1284 }
1285 break;
1286 /* Writes */
1287 case OP_WRITE:
1288 case OP_STORE:
1289 if (!last) {
1290 ret = &triple->right;
1291 }
1292 break;
1293 /* Reads */
1294 case OP_READ:
1295 if (!last) {
1296 ret = &triple->left;
1297 }
1298 break;
1299 /* Branches */
1300 case OP_BRANCH:
1301 case OP_JMP:
1302 case OP_JMP_EQ: case OP_JMP_NOTEQ:
1303 case OP_JMP_SLESS: case OP_JMP_ULESS:
1304 case OP_JMP_SMORE: case OP_JMP_UMORE:
1305 case OP_JMP_SLESSEQ: case OP_JMP_ULESSEQ:
1306 case OP_JMP_SMOREEQ: case OP_JMP_UMOREEQ:
1307 if (!last && triple->right) {
1308 ret = &triple->right;
1309 }
1310 break;
1311 /* Phi... */
1312 case OP_PHI:
1313 {
1314 struct triple **slot;
1315 struct block *block;
1316 block = triple->u.block;
1317 slot = (struct triple **)(triple->left);
1318 if (!last) {
1319 ret = slot;
1320 }
1321 else if ((last >= slot) && (last < (slot + block->users -1))) {
1322 ret = last + 1;
1323
1324 }
1325 break;
1326 }
1327 /* Loads */
1328 case OP_LOAD:
1329 /* address constant.. */
1330 case OP_ADDRCONST:
1331 if (!last) {
1332 ret = &triple->left;
1333 }
1334 break;
1335 /* Stores */
1336 break;
1337 /* Variables and labels */
1338 case OP_ADECL: case OP_SDECL: case OP_LABEL:
1339 /* Constants */
1340 case OP_INTCONST:
1341 case OP_BLOBCONST:
1342 case OP_NOOP:
1343 case OP_HLT:
1344 /* These operations that have no rhs expression */
1345 break;
1346 default:
1347 internal_error(state, 0, "unknown expression type: %d %s",
1348 triple->op, tops(triple->op));
1349 break;
1350
1351 }
1352 return ret;
1353}
1354
1355static struct triple **triple_lhs(struct compile_state *state,
1356 struct triple *triple, struct triple **last)
1357{
1358 struct triple **ret;
1359 ret = 0;
1360 switch(triple->op) {
1361 /* binary operations */
1362 case OP_SMUL: case OP_UMUL: case OP_SDIV: case OP_UDIV:
1363 case OP_SMOD: case OP_UMOD: case OP_ADD: case OP_SUB:
1364 case OP_SL: case OP_USR: case OP_SSR: case OP_AND:
1365 case OP_XOR: case OP_OR: case OP_EQ: case OP_NOTEQ:
1366 case OP_SLESS: case OP_ULESS: case OP_SMORE: case OP_UMORE:
1367 case OP_SLESSEQ: case OP_ULESSEQ: case OP_SMOREEQ: case OP_UMOREEQ:
1368 case OP_CMP:
1369 case OP_OUTB: case OP_OUTW: case OP_OUTL:
1370 /* unary operations */
1371 case OP_POS: case OP_NEG:
1372 case OP_INVERT: case OP_LFALSE: case OP_LTRUE:
1373 case OP_COPY:
1374 case OP_TEST:
1375 case OP_SET_EQ: case OP_SET_NOTEQ:
1376 case OP_SET_SLESS: case OP_SET_ULESS:
1377 case OP_SET_SMORE: case OP_SET_UMORE:
1378 case OP_SET_SLESSEQ: case OP_SET_ULESSEQ:
1379 case OP_SET_SMOREEQ: case OP_SET_UMOREEQ:
1380 case OP_INB: case OP_INW: case OP_INL:
1381 case OP_BSF: case OP_BSR:
1382 /* Variable reads */
1383 case OP_READ: case OP_PHI:
1384 /* Branches */
1385 case OP_BRANCH:
1386 case OP_JMP:
1387 case OP_JMP_EQ: case OP_JMP_NOTEQ:
1388 case OP_JMP_SLESS: case OP_JMP_ULESS:
1389 case OP_JMP_SMORE: case OP_JMP_UMORE:
1390 case OP_JMP_SLESSEQ: case OP_JMP_ULESSEQ:
1391 case OP_JMP_SMOREEQ: case OP_JMP_UMOREEQ:
1392 /* Loads */
1393 case OP_LOAD:
1394 /* Address constants */
1395 case OP_ADDRCONST:
1396 /* Variables and labels */
1397 case OP_ADECL: case OP_SDECL: case OP_LABEL:
1398 /* Constants */
1399 case OP_INTCONST:
1400 case OP_BLOBCONST:
1401 case OP_NOOP:
1402 case OP_HLT:
1403 /* These expressions have no lhs expression */
1404 break;
1405 /* Writes */
1406 case OP_WRITE:
1407 /* Stores */
1408 case OP_STORE:
1409 if (!last) {
1410 ret = &triple->left;
1411 }
1412 break;
1413 default:
1414 internal_error(state, 0, "unknown expression type: %d %s",
1415 triple->op, tops(triple->op));
1416 break;
1417 }
1418 return ret;
1419}
1420
1421static void free_triple(struct compile_state *state, struct triple *ptr)
1422{
1423 ptr->prev->next = ptr->next;
1424 ptr->next->prev = ptr->prev;
1425 if (ptr->use) {
1426 internal_error(state, ptr, "ptr->use != 0");
1427 }
1428 if (ptr->op == OP_PHI) {
1429 xfree(ptr->left);
1430 }
1431 memset(ptr, -1, sizeof(*ptr));
1432 xfree(ptr);
1433}
1434
1435static void release_triple(struct compile_state *state, struct triple *ptr)
1436{
1437 struct triple_set *set, *next;
1438 struct triple **expr;
1439 /* Remove ptr from use chains where it is the user */
1440 expr = triple_rhs(state, ptr, 0);
1441 for(; expr; expr = triple_rhs(state, ptr, expr)) {
1442 if (*expr) {
1443 unuse_triple(*expr, ptr);
1444 }
1445 }
1446 expr = triple_lhs(state, ptr, 0);
1447 for(; expr; expr = triple_lhs(state, ptr, expr)) {
1448 if (*expr) {
1449 unuse_triple(*expr, ptr);
1450 }
1451 }
1452 expr = triple_targ(state, ptr, 0);
1453 for(; expr; expr = triple_targ(state, ptr, expr)) {
1454 if (*expr) {
1455 unuse_triple(*expr, ptr);
1456 }
1457 }
1458 /* Reomve ptr from use chains where it is used */
1459 for(set = ptr->use; set; set = next) {
1460 next = set->next;
1461 expr = triple_rhs(state, set->member, 0);
1462 for(; expr; expr = triple_rhs(state, set->member, expr)) {
1463 if (*expr == ptr) {
1464 *expr = &zero_triple;
1465 }
1466 }
1467 expr = triple_lhs(state, set->member, 0);
1468 for(; expr; expr = triple_lhs(state, set->member, expr)) {
1469 if (*expr == ptr) {
1470 *expr = &zero_triple;
1471 }
1472 }
1473 expr = triple_targ(state, set->member, 0);
1474 for(; expr; expr = triple_targ(state, set->member, expr)) {
1475 if (*expr == ptr) {
1476 *expr = &zero_triple;
1477 }
1478 }
1479 unuse_triple(ptr, set->member);
1480 }
1481 free_triple(state, ptr);
1482}
1483
1484static void print_triple(struct compile_state *state, struct triple *ptr);
1485
1486#define TOK_UNKNOWN 0
1487#define TOK_SPACE 1
1488#define TOK_SEMI 2
1489#define TOK_LBRACE 3
1490#define TOK_RBRACE 4
1491#define TOK_COMMA 5
1492#define TOK_EQ 6
1493#define TOK_COLON 7
1494#define TOK_LBRACKET 8
1495#define TOK_RBRACKET 9
1496#define TOK_LPAREN 10
1497#define TOK_RPAREN 11
1498#define TOK_STAR 12
1499#define TOK_DOTS 13
1500#define TOK_MORE 14
1501#define TOK_LESS 15
1502#define TOK_TIMESEQ 16
1503#define TOK_DIVEQ 17
1504#define TOK_MODEQ 18
1505#define TOK_PLUSEQ 19
1506#define TOK_MINUSEQ 20
1507#define TOK_SLEQ 21
1508#define TOK_SREQ 22
1509#define TOK_ANDEQ 23
1510#define TOK_XOREQ 24
1511#define TOK_OREQ 25
1512#define TOK_EQEQ 26
1513#define TOK_NOTEQ 27
1514#define TOK_QUEST 28
1515#define TOK_LOGOR 29
1516#define TOK_LOGAND 30
1517#define TOK_OR 31
1518#define TOK_AND 32
1519#define TOK_XOR 33
1520#define TOK_LESSEQ 34
1521#define TOK_MOREEQ 35
1522#define TOK_SL 36
1523#define TOK_SR 37
1524#define TOK_PLUS 38
1525#define TOK_MINUS 39
1526#define TOK_DIV 40
1527#define TOK_MOD 41
1528#define TOK_PLUSPLUS 42
1529#define TOK_MINUSMINUS 43
1530#define TOK_BANG 44
1531#define TOK_ARROW 45
1532#define TOK_DOT 46
1533#define TOK_TILDE 47
1534#define TOK_LIT_STRING 48
1535#define TOK_LIT_CHAR 49
1536#define TOK_LIT_INT 50
1537#define TOK_LIT_FLOAT 51
1538#define TOK_MACRO 52
1539#define TOK_CONCATENATE 53
1540
1541#define TOK_IDENT 54
1542#define TOK_STRUCT_NAME 55
1543#define TOK_ENUM_CONST 56
1544#define TOK_TYPE_NAME 57
1545
1546#define TOK_AUTO 58
1547#define TOK_BREAK 59
1548#define TOK_CASE 60
1549#define TOK_CHAR 61
1550#define TOK_CONST 62
1551#define TOK_CONTINUE 63
1552#define TOK_DEFAULT 64
1553#define TOK_DO 65
1554#define TOK_DOUBLE 66
1555#define TOK_ELSE 67
1556#define TOK_ENUM 68
1557#define TOK_EXTERN 69
1558#define TOK_FLOAT 70
1559#define TOK_FOR 71
1560#define TOK_GOTO 72
1561#define TOK_IF 73
1562#define TOK_INLINE 74
1563#define TOK_INT 75
1564#define TOK_LONG 76
1565#define TOK_REGISTER 77
1566#define TOK_RESTRICT 78
1567#define TOK_RETURN 79
1568#define TOK_SHORT 80
1569#define TOK_SIGNED 81
1570#define TOK_SIZEOF 82
1571#define TOK_STATIC 83
1572#define TOK_STRUCT 84
1573#define TOK_SWITCH 85
1574#define TOK_TYPEDEF 86
1575#define TOK_UNION 87
1576#define TOK_UNSIGNED 88
1577#define TOK_VOID 89
1578#define TOK_VOLATILE 90
1579#define TOK_WHILE 91
1580#define TOK_ASM 92
1581#define TOK_ATTRIBUTE 93
1582#define TOK_ALIGNOF 94
1583#define TOK_FIRST_KEYWORD TOK_AUTO
1584#define TOK_LAST_KEYWORD TOK_ALIGNOF
1585
1586#define TOK_DEFINE 100
1587#define TOK_UNDEF 101
1588#define TOK_INCLUDE 102
1589#define TOK_LINE 103
1590#define TOK_ERROR 104
1591#define TOK_WARNING 105
1592#define TOK_PRAGMA 106
1593#define TOK_IFDEF 107
1594#define TOK_IFNDEF 108
1595#define TOK_ELIF 109
1596#define TOK_ENDIF 110
1597
1598#define TOK_FIRST_MACRO TOK_DEFINE
1599#define TOK_LAST_MACRO TOK_ENDIF
1600
1601#define TOK_EOF 111
1602
1603static const char *tokens[] = {
1604[TOK_UNKNOWN ] = "unknown",
1605[TOK_SPACE ] = ":space:",
1606[TOK_SEMI ] = ";",
1607[TOK_LBRACE ] = "{",
1608[TOK_RBRACE ] = "}",
1609[TOK_COMMA ] = ",",
1610[TOK_EQ ] = "=",
1611[TOK_COLON ] = ":",
1612[TOK_LBRACKET ] = "[",
1613[TOK_RBRACKET ] = "]",
1614[TOK_LPAREN ] = "(",
1615[TOK_RPAREN ] = ")",
1616[TOK_STAR ] = "*",
1617[TOK_DOTS ] = "...",
1618[TOK_MORE ] = ">",
1619[TOK_LESS ] = "<",
1620[TOK_TIMESEQ ] = "*=",
1621[TOK_DIVEQ ] = "/=",
1622[TOK_MODEQ ] = "%=",
1623[TOK_PLUSEQ ] = "+=",
1624[TOK_MINUSEQ ] = "-=",
1625[TOK_SLEQ ] = "<<=",
1626[TOK_SREQ ] = ">>=",
1627[TOK_ANDEQ ] = "&=",
1628[TOK_XOREQ ] = "^=",
1629[TOK_OREQ ] = "|=",
1630[TOK_EQEQ ] = "==",
1631[TOK_NOTEQ ] = "!=",
1632[TOK_QUEST ] = "?",
1633[TOK_LOGOR ] = "||",
1634[TOK_LOGAND ] = "&&",
1635[TOK_OR ] = "|",
1636[TOK_AND ] = "&",
1637[TOK_XOR ] = "^",
1638[TOK_LESSEQ ] = "<=",
1639[TOK_MOREEQ ] = ">=",
1640[TOK_SL ] = "<<",
1641[TOK_SR ] = ">>",
1642[TOK_PLUS ] = "+",
1643[TOK_MINUS ] = "-",
1644[TOK_DIV ] = "/",
1645[TOK_MOD ] = "%",
1646[TOK_PLUSPLUS ] = "++",
1647[TOK_MINUSMINUS ] = "--",
1648[TOK_BANG ] = "!",
1649[TOK_ARROW ] = "->",
1650[TOK_DOT ] = ".",
1651[TOK_TILDE ] = "~",
1652[TOK_LIT_STRING ] = ":string:",
1653[TOK_IDENT ] = ":ident:",
1654[TOK_TYPE_NAME ] = ":typename:",
1655[TOK_LIT_CHAR ] = ":char:",
1656[TOK_LIT_INT ] = ":integer:",
1657[TOK_LIT_FLOAT ] = ":float:",
1658[TOK_MACRO ] = "#",
1659[TOK_CONCATENATE ] = "##",
1660
1661[TOK_AUTO ] = "auto",
1662[TOK_BREAK ] = "break",
1663[TOK_CASE ] = "case",
1664[TOK_CHAR ] = "char",
1665[TOK_CONST ] = "const",
1666[TOK_CONTINUE ] = "continue",
1667[TOK_DEFAULT ] = "default",
1668[TOK_DO ] = "do",
1669[TOK_DOUBLE ] = "double",
1670[TOK_ELSE ] = "else",
1671[TOK_ENUM ] = "enum",
1672[TOK_EXTERN ] = "extern",
1673[TOK_FLOAT ] = "float",
1674[TOK_FOR ] = "for",
1675[TOK_GOTO ] = "goto",
1676[TOK_IF ] = "if",
1677[TOK_INLINE ] = "inline",
1678[TOK_INT ] = "int",
1679[TOK_LONG ] = "long",
1680[TOK_REGISTER ] = "register",
1681[TOK_RESTRICT ] = "restrict",
1682[TOK_RETURN ] = "return",
1683[TOK_SHORT ] = "short",
1684[TOK_SIGNED ] = "signed",
1685[TOK_SIZEOF ] = "sizeof",
1686[TOK_STATIC ] = "static",
1687[TOK_STRUCT ] = "struct",
1688[TOK_SWITCH ] = "switch",
1689[TOK_TYPEDEF ] = "typedef",
1690[TOK_UNION ] = "union",
1691[TOK_UNSIGNED ] = "unsigned",
1692[TOK_VOID ] = "void",
1693[TOK_VOLATILE ] = "volatile",
1694[TOK_WHILE ] = "while",
1695[TOK_ASM ] = "asm",
1696[TOK_ATTRIBUTE ] = "__attribute__",
1697[TOK_ALIGNOF ] = "__alignof__",
1698
1699[TOK_DEFINE ] = "define",
1700[TOK_UNDEF ] = "undef",
1701[TOK_INCLUDE ] = "include",
1702[TOK_LINE ] = "line",
1703[TOK_ERROR ] = "error",
1704[TOK_WARNING ] = "warning",
1705[TOK_PRAGMA ] = "pragma",
1706[TOK_IFDEF ] = "ifdef",
1707[TOK_IFNDEF ] = "ifndef",
1708[TOK_ELIF ] = "elif",
1709[TOK_ENDIF ] = "endif",
1710
1711[TOK_EOF ] = "EOF",
1712};
1713
1714static unsigned int hash(const char *str, int str_len)
1715{
1716 unsigned int hash;
1717 const char *end;
1718 end = str + str_len;
1719 hash = 0;
1720 for(; str < end; str++) {
1721 hash = (hash *263) + *str;
1722 }
1723 hash = hash & (HASH_TABLE_SIZE -1);
1724 return hash;
1725}
1726
1727static struct hash_entry *lookup(
1728 struct compile_state *state, const char *name, int name_len)
1729{
1730 struct hash_entry *entry;
1731 unsigned int index;
1732 index = hash(name, name_len);
1733 entry = state->hash_table[index];
1734 while(entry &&
1735 ((entry->name_len != name_len) ||
1736 (memcmp(entry->name, name, name_len) != 0))) {
1737 entry = entry->next;
1738 }
1739 if (!entry) {
1740 char *new_name;
1741 /* Get a private copy of the name */
1742 new_name = xmalloc(name_len + 1, "hash_name");
1743 memcpy(new_name, name, name_len);
1744 new_name[name_len] = '\0';
1745
1746 /* Create a new hash entry */
1747 entry = xcmalloc(sizeof(*entry), "hash_entry");
1748 entry->next = state->hash_table[index];
1749 entry->name = new_name;
1750 entry->name_len = name_len;
1751
1752 /* Place the new entry in the hash table */
1753 state->hash_table[index] = entry;
1754 }
1755 return entry;
1756}
1757
1758static void ident_to_keyword(struct compile_state *state, struct token *tk)
1759{
1760 struct hash_entry *entry;
1761 entry = tk->ident;
1762 if (entry && ((entry->tok == TOK_TYPE_NAME) ||
1763 (entry->tok == TOK_ENUM_CONST) ||
1764 ((entry->tok >= TOK_FIRST_KEYWORD) &&
1765 (entry->tok <= TOK_LAST_KEYWORD)))) {
1766 tk->tok = entry->tok;
1767 }
1768}
1769
1770static void ident_to_macro(struct compile_state *state, struct token *tk)
1771{
1772 struct hash_entry *entry;
1773 entry = tk->ident;
1774 if (entry &&
1775 (entry->tok >= TOK_FIRST_MACRO) &&
1776 (entry->tok <= TOK_LAST_MACRO)) {
1777 tk->tok = entry->tok;
1778 }
1779}
1780
1781static void hash_keyword(
1782 struct compile_state *state, const char *keyword, int tok)
1783{
1784 struct hash_entry *entry;
1785 entry = lookup(state, keyword, strlen(keyword));
1786 if (entry && entry->tok != TOK_UNKNOWN) {
1787 die("keyword %s already hashed", keyword);
1788 }
1789 entry->tok = tok;
1790}
1791
1792static void symbol(
1793 struct compile_state *state, struct hash_entry *ident,
1794 struct symbol **chain, struct triple *def, struct type *type)
1795{
1796 struct symbol *sym;
1797 if (*chain && ((*chain)->scope_depth == state->scope_depth)) {
1798 error(state, 0, "%s already defined", ident->name);
1799 }
1800 sym = xcmalloc(sizeof(*sym), "symbol");
1801 sym->ident = ident;
1802 sym->def = def;
1803 sym->type = type;
1804 sym->scope_depth = state->scope_depth;
1805 sym->next = *chain;
1806 *chain = sym;
1807}
1808
1809static void start_scope(struct compile_state *state)
1810{
1811 state->scope_depth++;
1812}
1813
1814static void end_scope_syms(struct symbol **chain, int depth)
1815{
1816 struct symbol *sym, *next;
1817 sym = *chain;
1818 while(sym && (sym->scope_depth == depth)) {
1819 next = sym->next;
1820 xfree(sym);
1821 sym = next;
1822 }
1823 *chain = sym;
1824}
1825
1826static void end_scope(struct compile_state *state)
1827{
1828 int i;
1829 int depth;
1830 /* Walk through the hash table and remove all symbols
1831 * in the current scope.
1832 */
1833 depth = state->scope_depth;
1834 for(i = 0; i < HASH_TABLE_SIZE; i++) {
1835 struct hash_entry *entry;
1836 entry = state->hash_table[i];
1837 while(entry) {
1838 end_scope_syms(&entry->sym_label, depth);
1839 end_scope_syms(&entry->sym_struct, depth);
1840 end_scope_syms(&entry->sym_ident, depth);
1841 entry = entry->next;
1842 }
1843 }
1844 state->scope_depth = depth - 1;
1845}
1846
1847static void register_keywords(struct compile_state *state)
1848{
1849 hash_keyword(state, "auto", TOK_AUTO);
1850 hash_keyword(state, "break", TOK_BREAK);
1851 hash_keyword(state, "case", TOK_CASE);
1852 hash_keyword(state, "char", TOK_CHAR);
1853 hash_keyword(state, "const", TOK_CONST);
1854 hash_keyword(state, "continue", TOK_CONTINUE);
1855 hash_keyword(state, "default", TOK_DEFAULT);
1856 hash_keyword(state, "do", TOK_DO);
1857 hash_keyword(state, "double", TOK_DOUBLE);
1858 hash_keyword(state, "else", TOK_ELSE);
1859 hash_keyword(state, "enum", TOK_ENUM);
1860 hash_keyword(state, "extern", TOK_EXTERN);
1861 hash_keyword(state, "float", TOK_FLOAT);
1862 hash_keyword(state, "for", TOK_FOR);
1863 hash_keyword(state, "goto", TOK_GOTO);
1864 hash_keyword(state, "if", TOK_IF);
1865 hash_keyword(state, "inline", TOK_INLINE);
1866 hash_keyword(state, "int", TOK_INT);
1867 hash_keyword(state, "long", TOK_LONG);
1868 hash_keyword(state, "register", TOK_REGISTER);
1869 hash_keyword(state, "restrict", TOK_RESTRICT);
1870 hash_keyword(state, "return", TOK_RETURN);
1871 hash_keyword(state, "short", TOK_SHORT);
1872 hash_keyword(state, "signed", TOK_SIGNED);
1873 hash_keyword(state, "sizeof", TOK_SIZEOF);
1874 hash_keyword(state, "static", TOK_STATIC);
1875 hash_keyword(state, "struct", TOK_STRUCT);
1876 hash_keyword(state, "switch", TOK_SWITCH);
1877 hash_keyword(state, "typedef", TOK_TYPEDEF);
1878 hash_keyword(state, "union", TOK_UNION);
1879 hash_keyword(state, "unsigned", TOK_UNSIGNED);
1880 hash_keyword(state, "void", TOK_VOID);
1881 hash_keyword(state, "volatile", TOK_VOLATILE);
1882 hash_keyword(state, "while", TOK_WHILE);
1883 hash_keyword(state, "asm", TOK_ASM);
1884 hash_keyword(state, "__attribute__", TOK_ATTRIBUTE);
1885 hash_keyword(state, "__alignof__", TOK_ALIGNOF);
1886}
1887
1888static void register_macro_keywords(struct compile_state *state)
1889{
1890 hash_keyword(state, "define", TOK_DEFINE);
1891 hash_keyword(state, "undef", TOK_UNDEF);
1892 hash_keyword(state, "include", TOK_INCLUDE);
1893 hash_keyword(state, "line", TOK_LINE);
1894 hash_keyword(state, "error", TOK_ERROR);
1895 hash_keyword(state, "warning", TOK_WARNING);
1896 hash_keyword(state, "pragma", TOK_PRAGMA);
1897 hash_keyword(state, "ifdef", TOK_IFDEF);
1898 hash_keyword(state, "ifndef", TOK_IFNDEF);
1899 hash_keyword(state, "elif", TOK_ELIF);
1900 hash_keyword(state, "endif", TOK_ENDIF);
1901}
1902
1903static int spacep(int c)
1904{
1905 int ret = 0;
1906 switch(c) {
1907 case ' ':
1908 case '\t':
1909 case '\f':
1910 case '\v':
1911 case '\r':
1912 case '\n':
1913 ret = 1;
1914 break;
1915 }
1916 return ret;
1917}
1918
1919static int digitp(int c)
1920{
1921 int ret = 0;
1922 switch(c) {
1923 case '0': case '1': case '2': case '3': case '4':
1924 case '5': case '6': case '7': case '8': case '9':
1925 ret = 1;
1926 break;
1927 }
1928 return ret;
1929}
1930
1931static int hexdigitp(int c)
1932{
1933 int ret = 0;
1934 switch(c) {
1935 case '0': case '1': case '2': case '3': case '4':
1936 case '5': case '6': case '7': case '8': case '9':
1937 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
1938 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
1939 ret = 1;
1940 break;
1941 }
1942 return ret;
1943}
1944static int hexdigval(int c)
1945{
1946 int val = -1;
1947 if ((c >= '0') && (c <= '9')) {
1948 val = c - '0';
1949 }
1950 else if ((c >= 'A') && (c <= 'F')) {
1951 val = 10 + (c - 'A');
1952 }
1953 else if ((c >= 'a') && (c <= 'f')) {
1954 val = 10 + (c - 'a');
1955 }
1956 return val;
1957}
1958
1959static int octdigitp(int c)
1960{
1961 int ret = 0;
1962 switch(c) {
1963 case '0': case '1': case '2': case '3':
1964 case '4': case '5': case '6': case '7':
1965 ret = 1;
1966 break;
1967 }
1968 return ret;
1969}
1970static int octdigval(int c)
1971{
1972 int val = -1;
1973 if ((c >= '0') && (c <= '7')) {
1974 val = c - '0';
1975 }
1976 return val;
1977}
1978
1979static int letterp(int c)
1980{
1981 int ret = 0;
1982 switch(c) {
1983 case 'a': case 'b': case 'c': case 'd': case 'e':
1984 case 'f': case 'g': case 'h': case 'i': case 'j':
1985 case 'k': case 'l': case 'm': case 'n': case 'o':
1986 case 'p': case 'q': case 'r': case 's': case 't':
1987 case 'u': case 'v': case 'w': case 'x': case 'y':
1988 case 'z':
1989 case 'A': case 'B': case 'C': case 'D': case 'E':
1990 case 'F': case 'G': case 'H': case 'I': case 'J':
1991 case 'K': case 'L': case 'M': case 'N': case 'O':
1992 case 'P': case 'Q': case 'R': case 'S': case 'T':
1993 case 'U': case 'V': case 'W': case 'X': case 'Y':
1994 case 'Z':
1995 case '_':
1996 ret = 1;
1997 break;
1998 }
1999 return ret;
2000}
2001
2002static int char_value(struct compile_state *state,
2003 const signed char **strp, const signed char *end)
2004{
2005 const signed char *str;
2006 int c;
2007 str = *strp;
2008 c = *str++;
2009 if ((c == '\\') && (str < end)) {
2010 switch(*str) {
2011 case 'n': c = '\n'; str++; break;
2012 case 't': c = '\t'; str++; break;
2013 case 'v': c = '\v'; str++; break;
2014 case 'b': c = '\b'; str++; break;
2015 case 'r': c = '\r'; str++; break;
2016 case 'f': c = '\f'; str++; break;
2017 case 'a': c = '\a'; str++; break;
2018 case '\\': c = '\\'; str++; break;
2019 case '?': c = '?'; str++; break;
2020 case '\'': c = '\''; str++; break;
2021 case '"': c = '"'; break;
2022 case 'x':
2023 c = 0;
2024 str++;
2025 while((str < end) && hexdigitp(*str)) {
2026 c <<= 4;
2027 c += hexdigval(*str);
2028 str++;
2029 }
2030 break;
2031 case '0': case '1': case '2': case '3':
2032 case '4': case '5': case '6': case '7':
2033 c = 0;
2034 while((str < end) && octdigitp(*str)) {
2035 c <<= 3;
2036 c += octdigval(*str);
2037 str++;
2038 }
2039 break;
2040 default:
2041 error(state, 0, "Invalid character constant");
2042 break;
2043 }
2044 }
2045 *strp = str;
2046 return c;
2047}
2048
2049static char *after_digits(char *ptr, char *end)
2050{
2051 while((ptr < end) && digitp(*ptr)) {
2052 ptr++;
2053 }
2054 return ptr;
2055}
2056
2057static char *after_octdigits(char *ptr, char *end)
2058{
2059 while((ptr < end) && octdigitp(*ptr)) {
2060 ptr++;
2061 }
2062 return ptr;
2063}
2064
2065static char *after_hexdigits(char *ptr, char *end)
2066{
2067 while((ptr < end) && hexdigitp(*ptr)) {
2068 ptr++;
2069 }
2070 return ptr;
2071}
2072
2073static void save_string(struct compile_state *state,
2074 struct token *tk, char *start, char *end, const char *id)
2075{
2076 char *str;
2077 int str_len;
2078 /* Create a private copy of the string */
2079 str_len = end - start + 1;
2080 str = xmalloc(str_len + 1, id);
2081 memcpy(str, start, str_len);
2082 str[str_len] = '\0';
2083
2084 /* Store the copy in the token */
2085 tk->val.str = str;
2086 tk->str_len = str_len;
2087}
2088static void next_token(struct compile_state *state, int index)
2089{
2090 struct file_state *file;
2091 struct token *tk;
2092 char *token;
2093 int c, c1, c2, c3;
2094 char *tokp, *end;
2095 int tok;
2096next_token:
2097 file = state->file;
2098 tk = &state->token[index];
2099 tk->str_len = 0;
2100 tk->ident = 0;
2101 token = tokp = file->pos;
2102 end = file->buf + file->size;
2103 tok = TOK_UNKNOWN;
2104 c = -1;
2105 if (tokp < end) {
2106 c = *tokp;
2107 }
2108 c1 = -1;
2109 if ((tokp + 1) < end) {
2110 c1 = tokp[1];
2111 }
2112 c2 = -1;
2113 if ((tokp + 2) < end) {
2114 c2 = tokp[2];
2115 }
2116 c3 = -1;
2117 if ((tokp + 3) < end) {
2118 c3 = tokp[3];
2119 }
2120 if (tokp >= end) {
2121 tok = TOK_EOF;
2122 tokp = end;
2123 }
2124 /* Whitespace */
2125 else if (spacep(c)) {
2126 tok = TOK_SPACE;
2127 while ((tokp < end) && spacep(c)) {
2128 if (c == '\n') {
2129 file->line++;
2130 file->line_start = tokp + 1;
2131 }
2132 c = *(++tokp);
2133 }
2134 if (!spacep(c)) {
2135 tokp--;
2136 }
2137 }
2138 /* EOL Comments */
2139 else if ((c == '/') && (c1 == '/')) {
2140 tok = TOK_SPACE;
2141 for(tokp += 2; tokp < end; tokp++) {
2142 c = *tokp;
2143 if (c == '\n') {
2144 file->line++;
2145 file->line_start = tokp +1;
2146 break;
2147 }
2148 }
2149 }
2150 /* Comments */
2151 else if ((c == '/') && (c1 == '*')) {
2152 int line;
2153 char *line_start;
2154 line = file->line;
2155 line_start = file->line_start;
2156 for(tokp += 2; (end - tokp) >= 2; tokp++) {
2157 c = *tokp;
2158 if (c == '\n') {
2159 line++;
2160 line_start = tokp +1;
2161 }
2162 else if ((c == '*') && (tokp[1] == '/')) {
2163 tok = TOK_SPACE;
2164 tokp += 1;
2165 break;
2166 }
2167 }
2168 if (tok == TOK_UNKNOWN) {
2169 error(state, 0, "unterminated comment");
2170 }
2171 file->line = line;
2172 file->line_start = line_start;
2173 }
2174 /* string constants */
2175 else if ((c == '"') ||
2176 ((c == 'L') && (c1 == '"'))) {
2177 int line;
2178 char *line_start;
2179 int wchar;
2180 line = file->line;
2181 line_start = file->line_start;
2182 wchar = 0;
2183 if (c == 'L') {
2184 wchar = 1;
2185 tokp++;
2186 }
2187 for(tokp += 1; tokp < end; tokp++) {
2188 c = *tokp;
2189 if (c == '\n') {
2190 line++;
2191 line_start = tokp + 1;
2192 }
2193 else if ((c == '\\') && (tokp +1 < end)) {
2194 tokp++;
2195 }
2196 else if (c == '"') {
2197 tok = TOK_LIT_STRING;
2198 break;
2199 }
2200 }
2201 if (tok == TOK_UNKNOWN) {
2202 error(state, 0, "unterminated string constant");
2203 }
2204 if (line != file->line) {
2205 warning(state, 0, "multiline string constant");
2206 }
2207 file->line = line;
2208 file->line_start = line_start;
2209
2210 /* Save the string value */
2211 save_string(state, tk, token, tokp, "literal string");
2212 }
2213 /* character constants */
2214 else if ((c == '\'') ||
2215 ((c == 'L') && (c1 == '\''))) {
2216 int line;
2217 char *line_start;
2218 int wchar;
2219 line = file->line;
2220 line_start = file->line_start;
2221 wchar = 0;
2222 if (c == 'L') {
2223 wchar = 1;
2224 tokp++;
2225 }
2226 for(tokp += 1; tokp < end; tokp++) {
2227 c = *tokp;
2228 if (c == '\n') {
2229 line++;
2230 line_start = tokp + 1;
2231 }
2232 else if ((c == '\\') && (tokp +1 < end)) {
2233 tokp++;
2234 }
2235 else if (c == '\'') {
2236 tok = TOK_LIT_CHAR;
2237 break;
2238 }
2239 }
2240 if (tok == TOK_UNKNOWN) {
2241 error(state, 0, "unterminated character constant");
2242 }
2243 if (line != file->line) {
2244 warning(state, 0, "multiline character constant");
2245 }
2246 file->line = line;
2247 file->line_start = line_start;
2248
2249 /* Save the character value */
2250 save_string(state, tk, token, tokp, "literal character");
2251 }
2252 /* integer and floating constants
2253 * Integer Constants
2254 * {digits}
2255 * 0[Xx]{hexdigits}
2256 * 0{octdigit}+
2257 *
2258 * Floating constants
2259 * {digits}.{digits}[Ee][+-]?{digits}
2260 * {digits}.{digits}
2261 * {digits}[Ee][+-]?{digits}
2262 * .{digits}[Ee][+-]?{digits}
2263 * .{digits}
2264 */
2265
2266 else if (digitp(c) || ((c == '.') && (digitp(c1)))) {
2267 char *next, *new;
2268 int is_float;
2269 is_float = 0;
2270 if (c != '.') {
2271 next = after_digits(tokp, end);
2272 }
2273 else {
2274 next = tokp;
2275 }
2276 if (next[0] == '.') {
2277 new = after_digits(next, end);
2278 is_float = (new != next);
2279 next = new;
2280 }
2281 if ((next[0] == 'e') || (next[0] == 'E')) {
2282 if (((next + 1) < end) &&
2283 ((next[1] == '+') || (next[1] == '-'))) {
2284 next++;
2285 }
2286 new = after_digits(next, end);
2287 is_float = (new != next);
2288 next = new;
2289 }
2290 if (is_float) {
2291 tok = TOK_LIT_FLOAT;
2292 if ((next < end) && (
2293 (next[0] == 'f') ||
2294 (next[0] == 'F') ||
2295 (next[0] == 'l') ||
2296 (next[0] == 'L'))
2297 ) {
2298 next++;
2299 }
2300 }
2301 if (!is_float && digitp(c)) {
2302 tok = TOK_LIT_INT;
2303 if ((c == '0') && ((c1 == 'x') || (c1 == 'X'))) {
2304 next = after_hexdigits(tokp + 2, end);
2305 }
2306 else if (c == '0') {
2307 next = after_octdigits(tokp, end);
2308 }
2309 else {
2310 next = after_digits(tokp, end);
2311 }
2312 /* crazy integer suffixes */
2313 if ((next < end) &&
2314 ((next[0] == 'u') || (next[0] == 'U'))) {
2315 next++;
2316 if ((next < end) &&
2317 ((next[0] == 'l') || (next[0] == 'L'))) {
2318 next++;
2319 }
2320 }
2321 else if ((next < end) &&
2322 ((next[0] == 'l') || (next[0] == 'L'))) {
2323 next++;
2324 if ((next < end) &&
2325 ((next[0] == 'u') || (next[0] == 'U'))) {
2326 next++;
2327 }
2328 }
2329 }
2330 tokp = next - 1;
2331
2332 /* Save the integer/floating point value */
2333 save_string(state, tk, token, tokp, "literal number");
2334 }
2335 /* identifiers */
2336 else if (letterp(c)) {
2337 tok = TOK_IDENT;
2338 for(tokp += 1; tokp < end; tokp++) {
2339 c = *tokp;
2340 if (!letterp(c) && !digitp(c)) {
2341 break;
2342 }
2343 }
2344 tokp -= 1;
2345 tk->ident = lookup(state, token, tokp +1 - token);
2346 }
2347 /* C99 alternate macro characters */
2348 else if ((c == '%') && (c1 == ':') && (c2 == '%') && (c3 == ':')) {
2349 tokp += 3;
2350 tok = TOK_CONCATENATE;
2351 }
2352 else if ((c == '.') && (c1 == '.') && (c2 == '.')) { tokp += 2; tok = TOK_DOTS; }
2353 else if ((c == '<') && (c1 == '<') && (c2 == '=')) { tokp += 2; tok = TOK_SLEQ; }
2354 else if ((c == '>') && (c1 == '>') && (c2 == '=')) { tokp += 2; tok = TOK_SREQ; }
2355 else if ((c == '*') && (c1 == '=')) { tokp += 1; tok = TOK_TIMESEQ; }
2356 else if ((c == '/') && (c1 == '=')) { tokp += 1; tok = TOK_DIVEQ; }
2357 else if ((c == '%') && (c1 == '=')) { tokp += 1; tok = TOK_MODEQ; }
2358 else if ((c == '+') && (c1 == '=')) { tokp += 1; tok = TOK_PLUSEQ; }
2359 else if ((c == '-') && (c1 == '=')) { tokp += 1; tok = TOK_MINUSEQ; }
2360 else if ((c == '&') && (c1 == '=')) { tokp += 1; tok = TOK_ANDEQ; }
2361 else if ((c == '^') && (c1 == '=')) { tokp += 1; tok = TOK_XOREQ; }
2362 else if ((c == '|') && (c1 == '=')) { tokp += 1; tok = TOK_OREQ; }
2363 else if ((c == '=') && (c1 == '=')) { tokp += 1; tok = TOK_EQEQ; }
2364 else if ((c == '!') && (c1 == '=')) { tokp += 1; tok = TOK_NOTEQ; }
2365 else if ((c == '|') && (c1 == '|')) { tokp += 1; tok = TOK_LOGOR; }
2366 else if ((c == '&') && (c1 == '&')) { tokp += 1; tok = TOK_LOGAND; }
2367 else if ((c == '<') && (c1 == '=')) { tokp += 1; tok = TOK_LESSEQ; }
2368 else if ((c == '>') && (c1 == '=')) { tokp += 1; tok = TOK_MOREEQ; }
2369 else if ((c == '<') && (c1 == '<')) { tokp += 1; tok = TOK_SL; }
2370 else if ((c == '>') && (c1 == '>')) { tokp += 1; tok = TOK_SR; }
2371 else if ((c == '+') && (c1 == '+')) { tokp += 1; tok = TOK_PLUSPLUS; }
2372 else if ((c == '-') && (c1 == '-')) { tokp += 1; tok = TOK_MINUSMINUS; }
2373 else if ((c == '-') && (c1 == '>')) { tokp += 1; tok = TOK_ARROW; }
2374 else if ((c == '<') && (c1 == ':')) { tokp += 1; tok = TOK_LBRACKET; }
2375 else if ((c == ':') && (c1 == '>')) { tokp += 1; tok = TOK_RBRACKET; }
2376 else if ((c == '<') && (c1 == '%')) { tokp += 1; tok = TOK_LBRACE; }
2377 else if ((c == '%') && (c1 == '>')) { tokp += 1; tok = TOK_RBRACE; }
2378 else if ((c == '%') && (c1 == ':')) { tokp += 1; tok = TOK_MACRO; }
2379 else if ((c == '#') && (c1 == '#')) { tokp += 1; tok = TOK_CONCATENATE; }
2380 else if (c == ';') { tok = TOK_SEMI; }
2381 else if (c == '{') { tok = TOK_LBRACE; }
2382 else if (c == '}') { tok = TOK_RBRACE; }
2383 else if (c == ',') { tok = TOK_COMMA; }
2384 else if (c == '=') { tok = TOK_EQ; }
2385 else if (c == ':') { tok = TOK_COLON; }
2386 else if (c == '[') { tok = TOK_LBRACKET; }
2387 else if (c == ']') { tok = TOK_RBRACKET; }
2388 else if (c == '(') { tok = TOK_LPAREN; }
2389 else if (c == ')') { tok = TOK_RPAREN; }
2390 else if (c == '*') { tok = TOK_STAR; }
2391 else if (c == '>') { tok = TOK_MORE; }
2392 else if (c == '<') { tok = TOK_LESS; }
2393 else if (c == '?') { tok = TOK_QUEST; }
2394 else if (c == '|') { tok = TOK_OR; }
2395 else if (c == '&') { tok = TOK_AND; }
2396 else if (c == '^') { tok = TOK_XOR; }
2397 else if (c == '+') { tok = TOK_PLUS; }
2398 else if (c == '-') { tok = TOK_MINUS; }
2399 else if (c == '/') { tok = TOK_DIV; }
2400 else if (c == '%') { tok = TOK_MOD; }
2401 else if (c == '!') { tok = TOK_BANG; }
2402 else if (c == '.') { tok = TOK_DOT; }
2403 else if (c == '~') { tok = TOK_TILDE; }
2404 else if (c == '#') { tok = TOK_MACRO; }
2405 if (tok == TOK_MACRO) {
2406 /* Only match preprocessor directives at the start of a line */
2407 char *ptr;
2408 for(ptr = file->line_start; spacep(*ptr); ptr++)
2409 ;
2410 if (ptr != tokp) {
2411 tok = TOK_UNKNOWN;
2412 }
2413 }
2414 if (tok == TOK_UNKNOWN) {
2415 error(state, 0, "unknown token");
2416 }
2417
2418 file->pos = tokp + 1;
2419 tk->tok = tok;
2420 if (tok == TOK_IDENT) {
2421 ident_to_keyword(state, tk);
2422 }
2423 /* Don't return space tokens. */
2424 if (tok == TOK_SPACE) {
2425 goto next_token;
2426 }
2427}
2428
2429static void compile_macro(struct compile_state *state, struct token *tk)
2430{
2431 struct file_state *file;
2432 struct hash_entry *ident;
2433 ident = tk->ident;
2434 file = xmalloc(sizeof(*file), "file_state");
2435 file->basename = xstrdup(tk->ident->name);
2436 file->dirname = xstrdup("");
2437 file->size = ident->sym_define->buf_len;
2438 file->buf = xmalloc(file->size +2, file->basename);
2439 memcpy(file->buf, ident->sym_define->buf, file->size);
2440 file->buf[file->size] = '\n';
2441 file->buf[file->size + 1] = '\0';
2442 file->pos = file->buf;
2443 file->line_start = file->pos;
2444 file->line = 1;
2445 file->prev = state->file;
2446 state->file = file;
2447}
2448
2449
2450static int mpeek(struct compile_state *state, int index)
2451{
2452 struct token *tk;
2453 int rescan;
2454 tk = &state->token[index + 1];
2455 if (tk->tok == -1) {
2456 next_token(state, index + 1);
2457 }
2458 do {
2459 rescan = 0;
2460 if ((tk->tok == TOK_EOF) &&
2461 (state->file != state->macro_file) &&
2462 (state->file->prev)) {
2463 struct file_state *file = state->file;
2464 state->file = file->prev;
2465 /* file->basename is used keep it */
2466 xfree(file->dirname);
2467 xfree(file->buf);
2468 xfree(file);
2469 next_token(state, index + 1);
2470 rescan = 1;
2471 }
2472 else if (tk->ident && tk->ident->sym_define) {
2473 compile_macro(state, tk);
2474 next_token(state, index + 1);
2475 rescan = 1;
2476 }
2477 } while(rescan);
2478 /* Don't show the token on the next line */
2479 if (state->macro_line < state->macro_file->line) {
2480 return TOK_EOF;
2481 }
2482 return state->token[index +1].tok;
2483}
2484
2485static void meat(struct compile_state *state, int index, int tok)
2486{
2487 int next_tok;
2488 int i;
2489 next_tok = mpeek(state, index);
2490 if (next_tok != tok) {
2491 const char *name1, *name2;
2492 name1 = tokens[next_tok];
2493 name2 = "";
2494 if (next_tok == TOK_IDENT) {
2495 name2 = state->token[index + 1].ident->name;
2496 }
2497 error(state, 0, "found %s %s expected %s",
2498 name1, name2, tokens[tok]);
2499 }
2500 /* Free the old token value */
2501 if (state->token[index].str_len) {
2502 memset((void *)(state->token[index].val.str), -1,
2503 state->token[index].str_len);
2504 xfree(state->token[index].val.str);
2505 }
2506 for(i = index; i < sizeof(state->token)/sizeof(state->token[0]) - 1; i++) {
2507 state->token[i] = state->token[i + 1];
2508 }
2509 memset(&state->token[i], 0, sizeof(state->token[i]));
2510 state->token[i].tok = -1;
2511}
2512
2513static long_t mcexpr(struct compile_state *state, int index);
2514
2515static long_t mprimary_expr(struct compile_state *state, int index)
2516{
2517 long_t val;
2518 int tok;
2519 tok = mpeek(state, index);
2520 while(state->token[index + 1].ident &&
2521 state->token[index + 1].ident->sym_define) {
2522 meat(state, index, tok);
2523 compile_macro(state, &state->token[index]);
2524 tok = mpeek(state, index);
2525 }
2526 switch(tok) {
2527 case TOK_LPAREN:
2528 meat(state, index, TOK_LPAREN);
2529 val = mcexpr(state, index);
2530 meat(state, index, TOK_RPAREN);
2531 break;
2532 case TOK_LIT_INT:
2533 {
2534 char *end;
2535 meat(state, index, TOK_LIT_INT);
2536 errno = 0;
2537 val = strtol(state->token[index].val.str, &end, 0);
2538 if (((val == LONG_MIN) || (val == LONG_MAX)) &&
2539 (errno == ERANGE)) {
2540 error(state, 0, "Integer constant to large");
2541 }
2542 break;
2543 }
2544 default:
2545 meat(state, index, TOK_LIT_INT);
2546 val = 0;
2547 }
2548 return val;
2549}
2550static long_t munary_expr(struct compile_state *state, int index)
2551{
2552 long_t val;
2553 switch(mpeek(state, index)) {
2554 case TOK_PLUS:
2555 meat(state, index, TOK_PLUS);
2556 val = munary_expr(state, index);
2557 val = + val;
2558 break;
2559 case TOK_MINUS:
2560 meat(state, index, TOK_MINUS);
2561 val = munary_expr(state, index);
2562 val = - val;
2563 break;
2564 case TOK_TILDE:
2565 meat(state, index, TOK_BANG);
2566 val = munary_expr(state, index);
2567 val = ~ val;
2568 break;
2569 case TOK_BANG:
2570 meat(state, index, TOK_BANG);
2571 val = munary_expr(state, index);
2572 val = ! val;
2573 break;
2574 default:
2575 val = mprimary_expr(state, index);
2576 break;
2577 }
2578 return val;
2579
2580}
2581static long_t mmul_expr(struct compile_state *state, int index)
2582{
2583 long_t val;
2584 int done;
2585 val = munary_expr(state, index);
2586 do {
2587 long_t right;
2588 done = 0;
2589 switch(mpeek(state, index)) {
2590 case TOK_STAR:
2591 meat(state, index, TOK_STAR);
2592 right = munary_expr(state, index);
2593 val = val * right;
2594 break;
2595 case TOK_DIV:
2596 meat(state, index, TOK_DIV);
2597 right = munary_expr(state, index);
2598 val = val / right;
2599 break;
2600 case TOK_MOD:
2601 meat(state, index, TOK_MOD);
2602 right = munary_expr(state, index);
2603 val = val % right;
2604 break;
2605 default:
2606 done = 1;
2607 break;
2608 }
2609 } while(!done);
2610
2611 return val;
2612}
2613
2614static long_t madd_expr(struct compile_state *state, int index)
2615{
2616 long_t val;
2617 int done;
2618 val = mmul_expr(state, index);
2619 do {
2620 long_t right;
2621 done = 0;
2622 switch(mpeek(state, index)) {
2623 case TOK_PLUS:
2624 meat(state, index, TOK_PLUS);
2625 right = mmul_expr(state, index);
2626 val = val + right;
2627 break;
2628 case TOK_MINUS:
2629 meat(state, index, TOK_MINUS);
2630 right = mmul_expr(state, index);
2631 val = val - right;
2632 break;
2633 default:
2634 done = 1;
2635 break;
2636 }
2637 } while(!done);
2638
2639 return val;
2640}
2641
2642static long_t mshift_expr(struct compile_state *state, int index)
2643{
2644 long_t val;
2645 int done;
2646 val = madd_expr(state, index);
2647 do {
2648 long_t right;
2649 done = 0;
2650 switch(mpeek(state, index)) {
2651 case TOK_SL:
2652 meat(state, index, TOK_SL);
2653 right = madd_expr(state, index);
2654 val = val << right;
2655 break;
2656 case TOK_SR:
2657 meat(state, index, TOK_SR);
2658 right = madd_expr(state, index);
2659 val = val >> right;
2660 break;
2661 default:
2662 done = 1;
2663 break;
2664 }
2665 } while(!done);
2666
2667 return val;
2668}
2669
2670static long_t mrel_expr(struct compile_state *state, int index)
2671{
2672 long_t val;
2673 int done;
2674 val = mshift_expr(state, index);
2675 do {
2676 long_t right;
2677 done = 0;
2678 switch(mpeek(state, index)) {
2679 case TOK_LESS:
2680 meat(state, index, TOK_LESS);
2681 right = mshift_expr(state, index);
2682 val = val < right;
2683 break;
2684 case TOK_MORE:
2685 meat(state, index, TOK_MORE);
2686 right = mshift_expr(state, index);
2687 val = val > right;
2688 break;
2689 case TOK_LESSEQ:
2690 meat(state, index, TOK_LESSEQ);
2691 right = mshift_expr(state, index);
2692 val = val <= right;
2693 break;
2694 case TOK_MOREEQ:
2695 meat(state, index, TOK_MOREEQ);
2696 right = mshift_expr(state, index);
2697 val = val >= right;
2698 break;
2699 default:
2700 done = 1;
2701 break;
2702 }
2703 } while(!done);
2704 return val;
2705}
2706
2707static long_t meq_expr(struct compile_state *state, int index)
2708{
2709 long_t val;
2710 int done;
2711 val = mrel_expr(state, index);
2712 do {
2713 long_t right;
2714 done = 0;
2715 switch(mpeek(state, index)) {
2716 case TOK_EQEQ:
2717 meat(state, index, TOK_EQEQ);
2718 right = mrel_expr(state, index);
2719 val = val == right;
2720 break;
2721 case TOK_NOTEQ:
2722 meat(state, index, TOK_NOTEQ);
2723 right = mrel_expr(state, index);
2724 val = val != right;
2725 break;
2726 default:
2727 done = 1;
2728 break;
2729 }
2730 } while(!done);
2731 return val;
2732}
2733
2734static long_t mand_expr(struct compile_state *state, int index)
2735{
2736 long_t val;
2737 val = meq_expr(state, index);
2738 if (mpeek(state, index) == TOK_AND) {
2739 long_t right;
2740 meat(state, index, TOK_AND);
2741 right = meq_expr(state, index);
2742 val = val & right;
2743 }
2744 return val;
2745}
2746
2747static long_t mxor_expr(struct compile_state *state, int index)
2748{
2749 long_t val;
2750 val = mand_expr(state, index);
2751 if (mpeek(state, index) == TOK_XOR) {
2752 long_t right;
2753 meat(state, index, TOK_XOR);
2754 right = mand_expr(state, index);
2755 val = val ^ right;
2756 }
2757 return val;
2758}
2759
2760static long_t mor_expr(struct compile_state *state, int index)
2761{
2762 long_t val;
2763 val = mxor_expr(state, index);
2764 if (mpeek(state, index) == TOK_OR) {
2765 long_t right;
2766 meat(state, index, TOK_OR);
2767 right = mxor_expr(state, index);
2768 val = val | right;
2769 }
2770 return val;
2771}
2772
2773static long_t mland_expr(struct compile_state *state, int index)
2774{
2775 long_t val;
2776 val = mor_expr(state, index);
2777 if (mpeek(state, index) == TOK_LOGAND) {
2778 long_t right;
2779 meat(state, index, TOK_LOGAND);
2780 right = mor_expr(state, index);
2781 val = val && right;
2782 }
2783 return val;
2784}
2785static long_t mlor_expr(struct compile_state *state, int index)
2786{
2787 long_t val;
2788 val = mland_expr(state, index);
2789 if (mpeek(state, index) == TOK_LOGOR) {
2790 long_t right;
2791 meat(state, index, TOK_LOGOR);
2792 right = mland_expr(state, index);
2793 val = val || right;
2794 }
2795 return val;
2796}
2797
2798static long_t mcexpr(struct compile_state *state, int index)
2799{
2800 return mlor_expr(state, index);
2801}
2802static void preprocess(struct compile_state *state, int index)
2803{
2804 /* Doing much more with the preprocessor would require
2805 * a parser and a major restructuring.
2806 * Postpone that for later.
2807 */
2808 struct file_state *file;
2809 struct token *tk;
2810 int line;
2811 int tok;
2812
2813 file = state->file;
2814 tk = &state->token[index];
2815 state->macro_line = line = file->line;
2816 state->macro_file = file;
2817
2818 next_token(state, index);
2819 ident_to_macro(state, tk);
2820 if (tk->tok == TOK_IDENT) {
2821 error(state, 0, "undefined preprocessing directive `%s'",
2822 tk->ident->name);
2823 }
2824 switch(tk->tok) {
2825 case TOK_UNDEF:
2826 case TOK_LINE:
2827 case TOK_PRAGMA:
2828 if (state->if_value < 0) {
2829 break;
2830 }
2831 warning(state, 0, "Ignoring preprocessor directive: %s",
2832 tk->ident->name);
2833 break;
2834 case TOK_ELIF:
2835 error(state, 0, "#elif not supported");
2836#warning "FIXME multiple #elif and #else in an #if do not work properly"
2837 if (state->if_depth == 0) {
2838 error(state, 0, "#elif without #if");
2839 }
2840 /* If the #if was taken the #elif just disables the following code */
2841 if (state->if_value >= 0) {
2842 state->if_value = - state->if_value;
2843 }
2844 /* If the previous #if was not taken see if the #elif enables the
2845 * trailing code.
2846 */
2847 else if ((state->if_value < 0) &&
2848 (state->if_depth == - state->if_value))
2849 {
2850 if (mcexpr(state, index) != 0) {
2851 state->if_value = state->if_depth;
2852 }
2853 else {
2854 state->if_value = - state->if_depth;
2855 }
2856 }
2857 break;
2858 case TOK_IF:
2859 state->if_depth++;
2860 if (state->if_value < 0) {
2861 break;
2862 }
2863 if (mcexpr(state, index) != 0) {
2864 state->if_value = state->if_depth;
2865 }
2866 else {
2867 state->if_value = - state->if_depth;
2868 }
2869 break;
2870 case TOK_IFNDEF:
2871 state->if_depth++;
2872 if (state->if_value < 0) {
2873 break;
2874 }
2875 next_token(state, index);
2876 if ((line != file->line) || (tk->tok != TOK_IDENT)) {
2877 error(state, 0, "Invalid macro name");
2878 }
2879 if (tk->ident->sym_define == 0) {
2880 state->if_value = state->if_depth;
2881 }
2882 else {
2883 state->if_value = - state->if_depth;
2884 }
2885 break;
2886 case TOK_IFDEF:
2887 state->if_depth++;
2888 if (state->if_value < 0) {
2889 break;
2890 }
2891 next_token(state, index);
2892 if ((line != file->line) || (tk->tok != TOK_IDENT)) {
2893 error(state, 0, "Invalid macro name");
2894 }
2895 if (tk->ident->sym_define != 0) {
2896 state->if_value = state->if_depth;
2897 }
2898 else {
2899 state->if_value = - state->if_depth;
2900 }
2901 break;
2902 case TOK_ELSE:
2903 if (state->if_depth == 0) {
2904 error(state, 0, "#else without #if");
2905 }
2906 if ((state->if_value >= 0) ||
2907 ((state->if_value < 0) &&
2908 (state->if_depth == -state->if_value)))
2909 {
2910 state->if_value = - state->if_value;
2911 }
2912 break;
2913 case TOK_ENDIF:
2914 if (state->if_depth == 0) {
2915 error(state, 0, "#endif without #if");
2916 }
2917 if ((state->if_value >= 0) ||
2918 ((state->if_value < 0) &&
2919 (state->if_depth == -state->if_value)))
2920 {
2921 state->if_value = state->if_depth - 1;
2922 }
2923 state->if_depth--;
2924 break;
2925 case TOK_DEFINE:
2926 {
2927 struct hash_entry *ident;
2928 struct macro *macro;
2929 char *ptr;
2930
2931 if (state->if_value < 0) /* quit early when #if'd out */
2932 break;
2933
2934 meat(state, index, TOK_IDENT);
2935 ident = tk->ident;
2936
2937
2938 if (*file->pos == '(') {
2939#warning "FIXME macros with arguments not supported"
2940 error(state, 0, "Macros with arguments not supported");
2941 }
2942
2943 /* Find the end of the line to get an estimate of
2944 * the macro's length.
2945 */
2946 for(ptr = file->pos; *ptr != '\n'; ptr++)
2947 ;
2948
2949 if (ident->sym_define != 0) {
2950 error(state, 0, "macro %s already defined\n", ident->name);
2951 }
2952 macro = xmalloc(sizeof(*macro), "macro");
2953 macro->ident = ident;
2954 macro->buf_len = ptr - file->pos +1;
2955 macro->buf = xmalloc(macro->buf_len +2, "macro buf");
2956
2957 memcpy(macro->buf, file->pos, macro->buf_len);
2958 macro->buf[macro->buf_len] = '\n';
2959 macro->buf[macro->buf_len +1] = '\0';
2960
2961 ident->sym_define = macro;
2962 break;
2963 }
2964 case TOK_ERROR:
2965 {
2966 char *end;
2967 int len;
2968 /* Find the end of the line */
2969 for(end = file->pos; *end != '\n'; end++)
2970 ;
2971 len = (end - file->pos);
2972 if (state->if_value >= 0) {
2973 error(state, 0, "%*.*s", len, len, file->pos);
2974 }
2975 file->pos = end;
2976 break;
2977 }
2978 case TOK_WARNING:
2979 {
2980 char *end;
2981 int len;
2982 /* Find the end of the line */
2983 for(end = file->pos; *end != '\n'; end++)
2984 ;
2985 len = (end - file->pos);
2986 if (state->if_value >= 0) {
2987 warning(state, 0, "%*.*s", len, len, file->pos);
2988 }
2989 file->pos = end;
2990 break;
2991 }
2992 case TOK_INCLUDE:
2993 {
2994 char *name;
2995 char *ptr;
2996 int local;
2997 local = 0;
2998 name = 0;
2999 next_token(state, index);
3000 if (tk->tok == TOK_LIT_STRING) {
3001 const char *token;
3002 int name_len;
3003 name = xmalloc(tk->str_len, "include");
3004 token = tk->val.str +1;
3005 name_len = tk->str_len -2;
3006 if (*token == '"') {
3007 token++;
3008 name_len--;
3009 }
3010 memcpy(name, token, name_len);
3011 name[name_len] = '\0';
3012 local = 1;
3013 }
3014 else if (tk->tok == TOK_LESS) {
3015 char *start, *end;
3016 start = file->pos;
3017 for(end = start; *end != '\n'; end++) {
3018 if (*end == '>') {
3019 break;
3020 }
3021 }
3022 if (*end == '\n') {
3023 error(state, 0, "Unterminated included directive");
3024 }
3025 name = xmalloc(end - start + 1, "include");
3026 memcpy(name, start, end - start);
3027 name[end - start] = '\0';
3028 file->pos = end +1;
3029 local = 0;
3030 }
3031 else {
3032 error(state, 0, "Invalid include directive");
3033 }
3034 /* Error if there are any characters after the include */
3035 for(ptr = file->pos; *ptr != '\n'; ptr++) {
3036 if (!isspace(*ptr)) {
3037 error(state, 0, "garbage after include directive");
3038 }
3039 }
3040 if (state->if_value >= 0) {
3041 compile_file(state, name, local);
3042 }
3043 xfree(name);
3044 next_token(state, index);
3045 return;
3046 }
3047 default:
3048 /* Ignore # without a following ident */
3049 if (tk->tok == TOK_IDENT) {
3050 error(state, 0, "Invalid preprocessor directive: %s",
3051 tk->ident->name);
3052 }
3053 break;
3054 }
3055 /* Consume the rest of the macro line */
3056 do {
3057 tok = mpeek(state, index);
3058 meat(state, index, tok);
3059 } while(tok != TOK_EOF);
3060 return;
3061}
3062
3063static void token(struct compile_state *state, int index)
3064{
3065 struct file_state *file;
3066 struct token *tk;
3067 int rescan;
3068
3069 tk = &state->token[index];
3070 next_token(state, index);
3071 do {
3072 rescan = 0;
3073 file = state->file;
3074 if (tk->tok == TOK_EOF && file->prev) {
3075 state->file = file->prev;
3076 /* file->basename is used keep it */
3077 xfree(file->dirname);
3078 xfree(file->buf);
3079 xfree(file);
3080 next_token(state, index);
3081 rescan = 1;
3082 }
3083 else if (tk->tok == TOK_MACRO) {
3084 preprocess(state, index);
3085 rescan = 1;
3086 }
3087 else if (tk->ident && tk->ident->sym_define) {
3088 compile_macro(state, tk);
3089 next_token(state, index);
3090 rescan = 1;
3091 }
3092 else if (state->if_value < 0) {
3093 next_token(state, index);
3094 rescan = 1;
3095 }
3096 } while(rescan);
3097}
3098
3099static int peek(struct compile_state *state)
3100{
3101 if (state->token[1].tok == -1) {
3102 token(state, 1);
3103 }
3104 return state->token[1].tok;
3105}
3106
3107static int peek2(struct compile_state *state)
3108{
3109 if (state->token[1].tok == -1) {
3110 token(state, 1);
3111 }
3112 if (state->token[2].tok == -1) {
3113 token(state, 2);
3114 }
3115 return state->token[2].tok;
3116}
3117
3118static void __eat(
3119 const char *file, const char *func, int line,
3120 struct compile_state *state, int tok)
3121{
3122 int next_tok;
3123 int i;
3124 next_tok = peek(state);
3125 if (next_tok != tok) {
3126 const char *name1, *name2;
3127 name1 = tokens[next_tok];
3128 name2 = "";
3129 if (next_tok == TOK_IDENT) {
3130 name2 = state->token[1].ident->name;
3131 }
3132 internal_error(state, 0, "@ %s.%s:%d \tfound %s %s expected %s",
3133 file, func, line,
3134 name1, name2, tokens[tok]);
3135 }
3136 /* Free the old token value */
3137 if (state->token[0].str_len) {
3138 xfree((void *)(state->token[0].val.str));
3139 }
3140 for(i = 0; i < sizeof(state->token)/sizeof(state->token[0]) - 1; i++) {
3141 state->token[i] = state->token[i + 1];
3142 }
3143 memset(&state->token[i], 0, sizeof(state->token[i]));
3144 state->token[i].tok = -1;
3145}
3146#define eat(state, tok) __eat(__FILE__, __func__, __LINE__, state, tok)
3147
3148#warning "FIXME do not hardcode the include paths"
3149static char *include_paths[] = {
3150 "/home/eric/projects/linuxbios/checkin/solo/freebios2/src/include",
3151 "/home/eric/projects/linuxbios/checkin/solo/freebios2/src/arch/i386/include",
3152 "/home/eric/projects/linuxbios/checkin/solo/freebios2/src",
3153 0
3154};
3155
3156static void compile_file(struct compile_state *state, char *filename, int local)
3157{
3158 char cwd[4096];
3159 char *subdir, *base;
3160 int subdir_len;
3161 struct file_state *file;
3162 char *basename;
3163 file = xmalloc(sizeof(*file), "file_state");
3164
3165 base = strrchr(filename, '/');
3166 subdir = filename;
3167 if (base != 0) {
3168 subdir_len = base - filename;
3169 base++;
3170 }
3171 else {
3172 base = filename;
3173 subdir_len = 0;
3174 }
3175 basename = xmalloc(strlen(base) +1, "basename");
3176 strcpy(basename, base);
3177 file->basename = basename;
3178
3179 if (getcwd(cwd, sizeof(cwd)) == 0) {
3180 die("cwd buffer to small");
3181 }
3182
3183 if (subdir[0] == '/') {
3184 file->dirname = xmalloc(subdir_len + 1, "dirname");
3185 memcpy(file->dirname, subdir, subdir_len);
3186 file->dirname[subdir_len] = '\0';
3187 }
3188 else {
3189 char *dir;
3190 int dirlen;
3191 char **path;
3192 /* Find the appropriate directory... */
3193 dir = 0;
3194 if (!state->file && exists(cwd, filename)) {
3195 dir = cwd;
3196 }
3197 if (local && state->file && exists(state->file->dirname, filename)) {
3198 dir = state->file->dirname;
3199 }
3200 for(path = include_paths; !dir && *path; path++) {
3201 if (exists(*path, filename)) {
3202 dir = *path;
3203 }
3204 }
3205 if (!dir) {
3206 error(state, 0, "Cannot find `%s'\n", filename);
3207 }
3208 dirlen = strlen(dir);
3209 file->dirname = xmalloc(dirlen + 1 + subdir_len + 1, "dirname");
3210 memcpy(file->dirname, dir, dirlen);
3211 file->dirname[dirlen] = '/';
3212 memcpy(file->dirname + dirlen + 1, subdir, subdir_len);
3213 file->dirname[dirlen + 1 + subdir_len] = '\0';
3214 }
3215 file->buf = slurp_file(file->dirname, file->basename, &file->size);
3216 xchdir(cwd);
3217
3218 file->pos = file->buf;
3219 file->line_start = file->pos;
3220 file->line = 1;
3221
3222 file->prev = state->file;
3223 state->file = file;
3224
3225 process_trigraphs(state);
3226 splice_lines(state);
3227}
3228
3229/* visibility global/local */
3230/* static/auto duration */
3231/* typedef, register, inline */
3232#define STOR_SHIFT 0
3233#define STOR_MASK 0x000f
3234/* Visibility */
3235#define STOR_GLOBAL 0x0001
3236/* Duration */
3237#define STOR_PERM 0x0002
3238/* Storage specifiers */
3239#define STOR_AUTO 0x0000
3240#define STOR_STATIC 0x0002
3241#define STOR_EXTERN 0x0003
3242#define STOR_REGISTER 0x0004
3243#define STOR_TYPEDEF 0x0008
3244#define STOR_INLINE 0x000c
3245
3246#define QUAL_SHIFT 4
3247#define QUAL_MASK 0x0070
3248#define QUAL_NONE 0x0000
3249#define QUAL_CONST 0x0010
3250#define QUAL_VOLATILE 0x0020
3251#define QUAL_RESTRICT 0x0040
3252
3253#define TYPE_SHIFT 8
3254#define TYPE_MASK 0x1f00
3255#define TYPE_INTEGER(TYPE) (((TYPE) >= TYPE_CHAR) && ((TYPE) <= TYPE_ULLONG))
3256#define TYPE_ARITHMETIC(TYPE) (((TYPE) >= TYPE_CHAR) && ((TYPE) <= TYPE_LDOUBLE))
3257#define TYPE_UNSIGNED(TYPE) ((TYPE) & 0x0100)
3258#define TYPE_SIGNED(TYPE) (!TYPE_UNSIGNED(TYPE))
3259#define TYPE_MKUNSIGNED(TYPE) ((TYPE) | 0x0100)
3260#define TYPE_RANK(TYPE) ((TYPE) & ~0x0100)
3261#define TYPE_PTR(TYPE) (((TYPE) & TYPE_MASK) == TYPE_POINTER)
3262#define TYPE_DEFAULT 0x0000
3263#define TYPE_VOID 0x0100
3264#define TYPE_CHAR 0x0200
3265#define TYPE_UCHAR 0x0300
3266#define TYPE_SHORT 0x0400
3267#define TYPE_USHORT 0x0500
3268#define TYPE_INT 0x0600
3269#define TYPE_UINT 0x0700
3270#define TYPE_LONG 0x0800
3271#define TYPE_ULONG 0x0900
3272#define TYPE_LLONG 0x0a00 /* long long */
3273#define TYPE_ULLONG 0x0b00
3274#define TYPE_FLOAT 0x0c00
3275#define TYPE_DOUBLE 0x0d00
3276#define TYPE_LDOUBLE 0x0e00 /* long double */
3277#define TYPE_STRUCT 0x1000
3278#define TYPE_ENUM 0x1100
3279#define TYPE_POINTER 0x1200
3280/* For TYPE_POINTER:
3281 * type->left holds the type pointed to.
3282 */
3283#define TYPE_FUNCTION 0x1300
3284/* For TYPE_FUNCTION:
3285 * type->left holds the return type.
3286 * type->right holds the...
3287 */
3288#define TYPE_PRODUCT 0x1400
3289/* TYPE_PRODUCT is a basic building block when defining structures
3290 * type->left holds the type that appears first in memory.
3291 * type->right holds the type that appears next in memory.
3292 */
3293#define TYPE_OVERLAP 0x1500
3294/* TYPE_OVERLAP is a basic building block when defining unions
3295 * type->left and type->right holds to types that overlap
3296 * each other in memory.
3297 */
3298#define TYPE_ARRAY 0x1600
3299/* TYPE_ARRAY is a basic building block when definitng arrays.
3300 * type->left holds the type we are an array of.
3301 * type-> holds the number of elements.
3302 */
3303
3304#define ELEMENT_COUNT_UNSPECIFIED (~0UL)
3305
3306struct type {
3307 unsigned int type;
3308 struct type *left, *right;
3309 ulong_t elements;
3310 struct hash_entry *ident;
3311};
3312
3313static struct type *new_type(
3314 unsigned int type, struct type *left, struct type *right)
3315{
3316 struct type *result;
3317 result = xmalloc(sizeof(*result), "type");
3318 result->type = type;
3319 result->left = left;
3320 result->right = right;
3321 result->ident = 0;
3322 return result;
3323}
3324
3325static struct type *clone_type(unsigned int specifiers, struct type *old)
3326{
3327 struct type *result;
3328 result = xmalloc(sizeof(*result), "type");
3329 memcpy(result, old, sizeof(*result));
3330 result->type &= TYPE_MASK;
3331 result->type |= specifiers;
3332 return result;
3333}
3334
3335#define SIZEOF_SHORT 2
3336#define SIZEOF_INT 4
3337#define SIZEOF_LONG (sizeof(long_t))
3338
3339#define ALIGNOF_SHORT 2
3340#define ALIGNOF_INT 4
3341#define ALIGNOF_LONG (sizeof(long_t))
3342
3343#define MASK_UCHAR(X) ((X) & ((ulong_t)0xff))
3344#define MASK_USHORT(X) ((X) & (((ulong_t)1 << (SIZEOF_SHORT*8)) - 1))
3345static inline ulong_t mask_uint(ulong_t x)
3346{
3347 if (SIZEOF_INT < SIZEOF_LONG) {
3348 ulong_t mask = (((ulong_t)1) << ((ulong_t)(SIZEOF_INT*8))) -1;
3349 x &= mask;
3350 }
3351 return x;
3352}
3353#define MASK_UINT(X) (mask_uint(X))
3354#define MASK_ULONG(X) (X)
3355
3356
3357static struct type void_type = { .type = TYPE_VOID };
3358static struct type char_type = { .type = TYPE_CHAR };
3359static struct type uchar_type = { .type = TYPE_UCHAR };
3360static struct type short_type = { .type = TYPE_SHORT };
3361static struct type ushort_type = { .type = TYPE_USHORT };
3362static struct type int_type = { .type = TYPE_INT };
3363static struct type uint_type = { .type = TYPE_UINT };
3364static struct type long_type = { .type = TYPE_LONG };
3365static struct type ulong_type = { .type = TYPE_ULONG };
3366
3367static struct triple *variable(struct compile_state *state, struct type *type)
3368{
3369 struct triple *result;
3370 if ((type->type & STOR_MASK) != STOR_PERM) {
3371 result = triple(state, OP_ADECL, type, 0, 0);
3372 }
3373 else {
3374 result = triple(state, OP_SDECL, type, 0, 0);
3375 }
3376 return result;
3377}
3378
3379static void stor_of(FILE *fp, struct type *type)
3380{
3381 switch(type->type & STOR_MASK) {
3382 case STOR_AUTO:
3383 fprintf(fp, "auto ");
3384 break;
3385 case STOR_STATIC:
3386 fprintf(fp, "static ");
3387 break;
3388 case STOR_EXTERN:
3389 fprintf(fp, "extern ");
3390 break;
3391 case STOR_REGISTER:
3392 fprintf(fp, "register ");
3393 break;
3394 case STOR_TYPEDEF:
3395 fprintf(fp, "typedef ");
3396 break;
3397 case STOR_INLINE:
3398 fprintf(fp, "inline ");
3399 break;
3400 }
3401}
3402static void qual_of(FILE *fp, struct type *type)
3403{
3404 if (type->type & QUAL_CONST) {
3405 fprintf(fp, " const");
3406 }
3407 if (type->type & QUAL_VOLATILE) {
3408 fprintf(fp, " volatile");
3409 }
3410 if (type->type & QUAL_RESTRICT) {
3411 fprintf(fp, " restrict");
3412 }
3413}
3414static void name_of(FILE *fp, struct type *type)
3415{
3416 stor_of(fp, type);
3417 switch(type->type & TYPE_MASK) {
3418 case TYPE_VOID:
3419 fprintf(fp, "void");
3420 qual_of(fp, type);
3421 break;
3422 case TYPE_CHAR:
3423 fprintf(fp, "signed char");
3424 qual_of(fp, type);
3425 break;
3426 case TYPE_UCHAR:
3427 fprintf(fp, "unsigned char");
3428 qual_of(fp, type);
3429 break;
3430 case TYPE_SHORT:
3431 fprintf(fp, "signed short");
3432 qual_of(fp, type);
3433 break;
3434 case TYPE_USHORT:
3435 fprintf(fp, "unsigned short");
3436 qual_of(fp, type);
3437 break;
3438 case TYPE_INT:
3439 fprintf(fp, "signed int");
3440 qual_of(fp, type);
3441 break;
3442 case TYPE_UINT:
3443 fprintf(fp, "unsigned int");
3444 qual_of(fp, type);
3445 break;
3446 case TYPE_LONG:
3447 fprintf(fp, "signed long");
3448 qual_of(fp, type);
3449 break;
3450 case TYPE_ULONG:
3451 fprintf(fp, "unsigned long");
3452 qual_of(fp, type);
3453 break;
3454 case TYPE_POINTER:
3455 name_of(fp, type->left);
3456 fprintf(fp, " * ");
3457 qual_of(fp, type);
3458 break;
3459 case TYPE_PRODUCT:
3460 case TYPE_OVERLAP:
3461 name_of(fp, type->left);
3462 fprintf(fp, ", ");
3463 name_of(fp, type->right);
3464 break;
3465 case TYPE_ENUM:
3466 fprintf(fp, "enum %s", type->ident->name);
3467 qual_of(fp, type);
3468 break;
3469 case TYPE_STRUCT:
3470 fprintf(fp, "struct %s", type->ident->name);
3471 qual_of(fp, type);
3472 break;
3473 case TYPE_FUNCTION:
3474 {
3475 name_of(fp, type->left);
3476 fprintf(fp, " (*)(");
3477 name_of(fp, type->right);
3478 fprintf(fp, ")");
3479 break;
3480 }
3481 case TYPE_ARRAY:
3482 name_of(fp, type->left);
3483 fprintf(fp, " [%ld]", type->elements);
3484 break;
3485 default:
3486 fprintf(fp, "????: %x", type->type & TYPE_MASK);
3487 break;
3488 }
3489}
3490
3491static size_t align_of(struct compile_state *state, struct type *type)
3492{
3493 size_t align;
3494 align = 0;
3495 switch(type->type & TYPE_MASK) {
3496 case TYPE_VOID:
3497 align = 1;
3498 break;
3499 case TYPE_CHAR:
3500 case TYPE_UCHAR:
3501 align = 1;
3502 break;
3503 case TYPE_SHORT:
3504 case TYPE_USHORT:
3505 align = ALIGNOF_SHORT;
3506 break;
3507 case TYPE_INT:
3508 case TYPE_UINT:
3509 case TYPE_ENUM:
3510 align = ALIGNOF_INT;
3511 break;
3512 case TYPE_LONG:
3513 case TYPE_ULONG:
3514 case TYPE_POINTER:
3515 align = ALIGNOF_LONG;
3516 break;
3517 case TYPE_PRODUCT:
3518 case TYPE_OVERLAP:
3519 {
3520 size_t left_align, right_align;
3521 left_align = align_of(state, type->left);
3522 right_align = align_of(state, type->right);
3523 align = (left_align >= right_align) ? left_align : right_align;
3524 break;
3525 }
3526 case TYPE_ARRAY:
3527 align = align_of(state, type->left);
3528 break;
3529 default:
3530 error(state, 0, "alignof not yet defined for type\n");
3531 break;
3532 }
3533 return align;
3534}
3535
3536static size_t size_of(struct compile_state *state, struct type *type)
3537{
3538 size_t size;
3539 size = 0;
3540 switch(type->type & TYPE_MASK) {
3541 case TYPE_VOID:
3542 size = 0;
3543 break;
3544 case TYPE_CHAR:
3545 case TYPE_UCHAR:
3546 size = 1;
3547 break;
3548 case TYPE_SHORT:
3549 case TYPE_USHORT:
3550 size = SIZEOF_SHORT;
3551 break;
3552 case TYPE_INT:
3553 case TYPE_UINT:
3554 case TYPE_ENUM:
3555 size = SIZEOF_INT;
3556 break;
3557 case TYPE_LONG:
3558 case TYPE_ULONG:
3559 case TYPE_POINTER:
3560 size = SIZEOF_LONG;
3561 break;
3562 case TYPE_PRODUCT:
3563 {
3564 size_t align, pad;
3565 size = size_of(state, type->left);
3566 while((type->right->type & TYPE_MASK) == TYPE_PRODUCT) {
3567 type = type->right;
3568 align = align_of(state, type->left);
3569 pad = align - (size % align);
3570 size = size + pad + size_of(state, type->left);
3571 }
3572 align = align_of(state, type->right);
3573 pad = align - (size % align);
3574 size = size + pad + sizeof(type->right);
3575 break;
3576 }
3577 case TYPE_OVERLAP:
3578 {
3579 size_t size_left, size_right;
3580 size_left = size_of(state, type->left);
3581 size_right = size_of(state, type->right);
3582 size = (size_left >= size_right)? size_left : size_right;
3583 break;
3584 }
3585 case TYPE_ARRAY:
3586 if (type->elements == ELEMENT_COUNT_UNSPECIFIED) {
3587 internal_error(state, 0, "Invalid array type");
3588 } else {
3589 size = size_of(state, type->left) * type->elements;
3590 }
3591 break;
3592 default:
3593 error(state, 0, "sizeof not yet defined for type\n");
3594 break;
3595 }
3596 return size;
3597}
3598
3599static void arrays_complete(struct compile_state *state, struct type *type)
3600{
3601 if ((type->type & TYPE_MASK) == TYPE_ARRAY) {
3602 if (type->elements == ELEMENT_COUNT_UNSPECIFIED) {
3603 error(state, 0, "array size not specified");
3604 }
3605 arrays_complete(state, type->left);
3606 }
3607}
3608
3609static unsigned int do_integral_promotion(unsigned int type)
3610{
3611 type &= TYPE_MASK;
3612 if (TYPE_INTEGER(type) &&
3613 TYPE_RANK(type) < TYPE_RANK(TYPE_INT)) {
3614 type = TYPE_INT;
3615 }
3616 return type;
3617}
3618
3619static unsigned int do_arithmetic_conversion(
3620 unsigned int left, unsigned int right)
3621{
3622 left &= TYPE_MASK;
3623 right &= TYPE_MASK;
3624 if ((left == TYPE_LDOUBLE) || (right == TYPE_LDOUBLE)) {
3625 return TYPE_LDOUBLE;
3626 }
3627 else if ((left == TYPE_DOUBLE) || (right == TYPE_DOUBLE)) {
3628 return TYPE_DOUBLE;
3629 }
3630 else if ((left == TYPE_FLOAT) || (right == TYPE_FLOAT)) {
3631 return TYPE_FLOAT;
3632 }
3633 left = do_integral_promotion(left);
3634 right = do_integral_promotion(right);
3635 /* If both operands have the same size done */
3636 if (left == right) {
3637 return left;
3638 }
3639 /* If both operands have the same signedness pick the larger */
3640 else if (!!TYPE_UNSIGNED(left) == !!TYPE_UNSIGNED(right)) {
3641 return (TYPE_RANK(left) >= TYPE_RANK(right)) ? left : right;
3642 }
3643 /* If the signed type can hold everything use it */
3644 else if (TYPE_SIGNED(left) && (TYPE_RANK(left) > TYPE_RANK(right))) {
3645 return left;
3646 }
3647 else if (TYPE_SIGNED(right) && (TYPE_RANK(right) > TYPE_RANK(left))) {
3648 return right;
3649 }
3650 /* Convert to the unsigned type with the same rank as the signed type */
3651 else if (TYPE_SIGNED(left)) {
3652 return TYPE_MKUNSIGNED(left);
3653 }
3654 else {
3655 return TYPE_MKUNSIGNED(right);
3656 }
3657}
3658
3659/* see if two types are the same except for qualifiers */
3660static int equiv_types(struct type *left, struct type *right)
3661{
3662 unsigned int type;
3663 /* Error if the basic types do not match */
3664 if ((left->type & TYPE_MASK) != (right->type & TYPE_MASK)) {
3665 return 0;
3666 }
3667 type = left->type & TYPE_MASK;
3668 /* if the basic types match and it is an arithmetic type we are done */
3669 if (TYPE_ARITHMETIC(type)) {
3670 return 1;
3671 }
3672 /* If it is a pointer type recurse and keep testing */
3673 if (type == TYPE_POINTER) {
3674 return equiv_types(left->left, right->left);
3675 }
3676 else if (type == TYPE_ARRAY) {
3677 return (left->elements == right->elements) &&
3678 equiv_types(left->left, right->left);
3679 }
3680 /* test for struct/union equality */
3681 else if (type == TYPE_STRUCT) {
3682 return left->ident == right->ident;
3683 }
3684 /* Test for equivalent functions */
3685 else if (type == TYPE_FUNCTION) {
3686 return equiv_types(left->left, right->left) &&
3687 equiv_types(left->right, right->right);
3688 }
3689 /* We only see TYPE_PRODUCT as part of function equivalence matching */
3690 else if (type == TYPE_PRODUCT) {
3691 return equiv_types(left->left, right->left) &&
3692 equiv_types(left->right, right->right);
3693 }
3694 /* We should see TYPE_OVERLAP */
3695 else {
3696 return 0;
3697 }
3698}
3699
3700static int equiv_ptrs(struct type *left, struct type *right)
3701{
3702 if (((left->type & TYPE_MASK) != TYPE_POINTER) ||
3703 ((right->type & TYPE_MASK) != TYPE_POINTER)) {
3704 return 0;
3705 }
3706 return equiv_types(left->left, right->left);
3707}
3708
3709static struct type *compatible_types(struct type *left, struct type *right)
3710{
3711 struct type *result;
3712 unsigned int type, qual_type;
3713 /* Error if the basic types do not match */
3714 if ((left->type & TYPE_MASK) != (right->type & TYPE_MASK)) {
3715 return 0;
3716 }
3717 type = left->type & TYPE_MASK;
3718 qual_type = (left->type & ~STOR_MASK) | (right->type & ~STOR_MASK);
3719 result = 0;
3720 /* if the basic types match and it is an arithmetic type we are done */
3721 if (TYPE_ARITHMETIC(type)) {
3722 result = new_type(qual_type, 0, 0);
3723 }
3724 /* If it is a pointer type recurse and keep testing */
3725 else if (type == TYPE_POINTER) {
3726 result = compatible_types(left->left, right->left);
3727 if (result) {
3728 result = new_type(qual_type, result, 0);
3729 }
3730 }
3731 /* test for struct/union equality */
3732 else if (type == TYPE_STRUCT) {
3733 if (left->ident == right->ident) {
3734 result = left;
3735 }
3736 }
3737 /* Test for equivalent functions */
3738 else if (type == TYPE_FUNCTION) {
3739 struct type *lf, *rf;
3740 lf = compatible_types(left->left, right->left);
3741 rf = compatible_types(left->right, right->right);
3742 if (lf && rf) {
3743 result = new_type(qual_type, lf, rf);
3744 }
3745 }
3746 /* We only see TYPE_PRODUCT as part of function equivalence matching */
3747 else if (type == TYPE_PRODUCT) {
3748 struct type *lf, *rf;
3749 lf = compatible_types(left->left, right->left);
3750 rf = compatible_types(left->right, right->right);
3751 if (lf && rf) {
3752 result = new_type(qual_type, lf, rf);
3753 }
3754 }
3755 else {
3756 /* Nothing else is compatible */
3757 }
3758 return result;
3759}
3760
3761static struct type *compatible_ptrs(struct type *left, struct type *right)
3762{
3763 struct type *result;
3764 if (((left->type & TYPE_MASK) != TYPE_POINTER) ||
3765 ((right->type & TYPE_MASK) != TYPE_POINTER)) {
3766 return 0;
3767 }
3768 result = compatible_types(left->left, right->left);
3769 if (result) {
3770 unsigned int qual_type;
3771 qual_type = (left->type & ~STOR_MASK) | (right->type & ~STOR_MASK);
3772 result = new_type(qual_type, result, 0);
3773 }
3774 return result;
3775
3776}
3777static struct triple *integral_promotion(
3778 struct compile_state *state, struct triple *def)
3779{
3780 struct type *type;
3781 type = def->type;
3782 /* As all operations are carried out in registers
3783 * the values are converted on load I just convert
3784 * logical type of the operand.
3785 */
3786 if (TYPE_INTEGER(type->type)) {
3787 unsigned int int_type;
3788 int_type = type->type & ~TYPE_MASK;
3789 int_type |= do_integral_promotion(type->type);
3790 if (int_type != type->type) {
3791 def->type = new_type(int_type, 0, 0);
3792 }
3793 }
3794 return def;
3795}
3796
3797
3798static void arithmetic(struct compile_state *state, struct triple *def)
3799{
3800 if (!TYPE_ARITHMETIC(def->type->type)) {
3801 error(state, def, "arithmetic type expexted");
3802 }
3803}
3804
3805static void ptr_arithmetic(struct compile_state *state, struct triple *def)
3806{
3807 if (!TYPE_PTR(def->type->type) && !TYPE_ARITHMETIC(def->type->type)) {
3808 error(state, def, "pointer or arithmetic type expected");
3809 }
3810}
3811
3812static int is_integral(struct triple *ins)
3813{
3814 return TYPE_INTEGER(ins->type->type);
3815}
3816
3817static void integral(struct compile_state *state, struct triple *def)
3818{
3819 if (!is_integral(def)) {
3820 error(state, 0, "integral type expected");
3821 }
3822}
3823
3824
3825static void bool(struct compile_state *state, struct triple *def)
3826{
3827 if (!TYPE_ARITHMETIC(def->type->type) &&
3828 ((def->type->type & TYPE_MASK) != TYPE_POINTER)) {
3829 error(state, 0, "arithmetic or pointer type expected");
3830 }
3831}
3832
3833static int is_signed(struct type *type)
3834{
3835 return !!TYPE_SIGNED(type->type);
3836}
3837
3838/* Is this a stable variable location otherwise it must be a temporary */
3839static int is_stable(struct triple *def)
3840{
3841 int ret;
3842 ret = 0;
3843 if (!def) {
3844 return 0;
3845 }
3846 if ((def->op == OP_ADECL) ||
3847 (def->op == OP_SDECL) ||
3848 (def->op == OP_DEREF) ||
3849 (def->op == OP_BLOBCONST)) {
3850 ret = 1;
3851 }
3852 else if (def->op == OP_DOT) {
3853 ret = is_stable(def->left);
3854 }
3855 return ret;
3856}
3857
3858static int is_lvalue(struct triple *def)
3859{
3860 int ret;
3861 ret = 1;
3862 if (!def) {
3863 return 0;
3864 }
3865 if (!is_stable(def)) {
3866 return 0;
3867 }
3868 if (def->type->type & QUAL_CONST) {
3869 ret = 0;
3870 }
3871 else if (def->op == OP_DOT) {
3872 ret = is_lvalue(def->left);
3873 }
3874 return ret;
3875}
3876
3877static void lvalue(struct compile_state *state, struct triple *def)
3878{
3879 if (!def) {
3880 internal_error(state, def, "nothing where lvalue expected?");
3881 }
3882 if (!is_lvalue(def)) {
3883 error(state, def, "lvalue expected");
3884 }
3885}
3886
3887static int is_pointer(struct triple *def)
3888{
3889 return (def->type->type & TYPE_MASK) == TYPE_POINTER;
3890}
3891
3892static void pointer(struct compile_state *state, struct triple *def)
3893{
3894 if (!is_pointer(def)) {
3895 error(state, def, "pointer expected");
3896 }
3897}
3898
3899static struct triple *int_const(
3900 struct compile_state *state, struct type *type, ulong_t value)
3901{
3902 struct triple *result;
3903 switch(type->type & TYPE_MASK) {
3904 case TYPE_CHAR:
3905 case TYPE_INT: case TYPE_UINT:
3906 case TYPE_LONG: case TYPE_ULONG:
3907 break;
3908 default:
3909 internal_error(state, 0, "constant for unkown type");
3910 }
3911 result = triple(state, OP_INTCONST, type, 0, 0);
3912 result->u.cval = value;
3913 return result;
3914}
3915
3916
3917static struct triple *mk_addr_expr(
3918 struct compile_state *state, struct triple *expr, ulong_t offset)
3919{
3920 struct triple *result;
3921 struct type *type;
3922
3923 lvalue(state, expr);
3924 type = new_type(
3925 TYPE_POINTER | (expr->type->type & QUAL_MASK),
3926 expr->type, 0);
3927
3928 result = 0;
3929 if (expr->op == OP_ADECL) {
3930 error(state, expr, "address of auto variables not supported");
3931 }
3932 else if (expr->op == OP_SDECL) {
3933 result = triple(state, OP_ADDRCONST, type, expr, 0);
3934 result->u.cval = offset;
3935 }
3936 else if (expr->op == OP_DEREF) {
3937 result = triple(state, OP_ADD, type,
3938 expr->left,
3939 int_const(state, &ulong_type, offset));
3940 }
3941 return result;
3942}
3943
3944static struct triple *mk_deref_expr(
3945 struct compile_state *state, struct triple *expr)
3946{
3947 struct type *base_type;
3948 pointer(state, expr);
3949 base_type = expr->type->left;
3950 if (!TYPE_PTR(base_type->type) && !TYPE_ARITHMETIC(base_type->type)) {
3951 error(state, 0,
3952 "Only pointer and arithmetic values can be dereferenced");
3953 }
3954 return triple(state, OP_DEREF, base_type, expr, 0);
3955}
3956
3957static struct triple *read_expr(struct compile_state *state, struct triple *def)
3958{
3959 int op;
3960 if (!def) {
3961 return 0;
3962 }
3963 if (!is_stable(def)) {
3964 return def;
3965 }
3966 /* Tranform an array to a pointer to the first element */
3967#warning "CHECK_ME is this the right place to transform arrays to pointers?"
3968 if ((def->type->type & TYPE_MASK) == TYPE_ARRAY) {
3969 struct type *type;
3970 type = new_type(
3971 TYPE_POINTER | (def->type->type & QUAL_MASK),
3972 def->type->left, 0);
3973 return triple(state, OP_ADDRCONST, type, def, 0);
3974 }
3975 /* Only values in variables need to be read */
3976 if (def->op == OP_ADECL) {
3977 op = OP_READ;
3978 }
3979 else if ((def->op == OP_SDECL) || (def->op == OP_DEREF)) {
3980 op = OP_LOAD;
3981 }
3982 else {
3983 internal_error(state, 0, "unhandled read expr type");
3984 op = -1;
3985 }
3986 return triple(state, op, def->type, def, 0);
3987}
3988
3989static void write_compatible(struct compile_state *state,
3990 struct type *dest, struct type *rval)
3991{
3992 int compatible = 0;
3993 /* Both operands have arithmetic type */
3994 if (TYPE_ARITHMETIC(dest->type) && TYPE_ARITHMETIC(rval->type)) {
3995 compatible = 1;
3996 }
3997 /* One operand is a pointer and the other is a pointer to void */
3998 else if (((dest->type & TYPE_MASK) == TYPE_POINTER) &&
3999 ((rval->type & TYPE_MASK) == TYPE_POINTER) &&
4000 (((dest->left->type & TYPE_MASK) == TYPE_VOID) ||
4001 ((rval->left->type & TYPE_MASK) == TYPE_VOID))) {
4002 compatible = 1;
4003 }
4004 /* If both types are the same without qualifiers we are good */
4005 else if (equiv_ptrs(dest, rval)) {
4006 compatible = 1;
4007 }
4008 if (!compatible) {
4009 error(state, 0, "Incompatible types in assignment");
4010 }
4011}
4012
4013static struct triple *write_expr(
4014 struct compile_state *state, struct triple *dest, struct triple *rval)
4015{
4016 struct triple *def;
4017 int op;
4018
4019 def = 0;
4020 if (!rval) {
4021 internal_error(state, 0, "missing rval");
4022 }
4023
4024 if (rval->op == OP_LIST) {
4025 internal_error(state, 0, "expression of type OP_LIST?");
4026 }
4027 if (!is_lvalue(dest)) {
4028 internal_error(state, 0, "writing to a non lvalue?");
4029 }
4030
4031 write_compatible(state, dest->type, rval->type);
4032
4033 /* Now figure out which assignment operator to use */
4034 op = -1;
4035 if (dest->op == OP_ADECL) {
4036 op = OP_WRITE;
4037 }
4038 else if ((dest->op == OP_SDECL) || (dest->op == OP_DEREF)) {
4039 op = OP_STORE;
4040 }
4041 else {
4042 internal_error(state, 0, "unimplemented lvalue type");
4043 }
4044#warning "FIXME walk through a list of OP_DOT entries and generate a pointer addition"
4045 def = triple(state, op, dest->type, dest, rval);
4046 return def;
4047}
4048
4049static struct triple *init_expr(
4050 struct compile_state *state, struct triple *dest, struct triple *rval)
4051{
4052 struct triple *def;
4053
4054 def = 0;
4055 if (!rval) {
4056 internal_error(state, 0, "missing rval");
4057 }
4058 if ((dest->type->type & STOR_MASK) != STOR_PERM) {
4059 rval = read_expr(state, rval);
4060 def = write_expr(state, dest, rval);
4061 }
4062 else {
4063 /* Fill in the array size if necessary */
4064 if (((dest->type->type & TYPE_MASK) == TYPE_ARRAY) &&
4065 ((rval->type->type & TYPE_MASK) == TYPE_ARRAY)) {
4066 if (dest->type->elements == ELEMENT_COUNT_UNSPECIFIED) {
4067 dest->type->elements = rval->type->elements;
4068 }
4069 }
4070 if (!equiv_types(dest->type, rval->type)) {
4071 error(state, 0, "Incompatible types in inializer");
4072 }
4073 dest->left = rval;
4074 }
4075 return def;
4076}
4077
4078struct type *arithmetic_result(
4079 struct compile_state *state, struct triple *left, struct triple *right)
4080{
4081 struct type *type;
4082 /* Sanity checks to ensure I am working with arithmetic types */
4083 arithmetic(state, left);
4084 arithmetic(state, right);
4085 type = new_type(
4086 do_arithmetic_conversion(
4087 left->type->type,
4088 right->type->type), 0, 0);
4089 return type;
4090}
4091
4092struct type *ptr_arithmetic_result(
4093 struct compile_state *state, struct triple *left, struct triple *right)
4094{
4095 struct type *type;
4096 /* Sanity checks to ensure I am working with the proper types */
4097 ptr_arithmetic(state, left);
4098 arithmetic(state, right);
4099 if (TYPE_ARITHMETIC(left->type->type) &&
4100 TYPE_ARITHMETIC(right->type->type)) {
4101 type = arithmetic_result(state, left, right);
4102 }
4103 else if (TYPE_PTR(left->type->type)) {
4104 type = left->type;
4105 }
4106 else {
4107 internal_error(state, 0, "huh?");
4108 type = 0;
4109 }
4110 return type;
4111}
4112
4113
4114/* boolean helper function */
4115
4116static struct triple *ltrue_expr(struct compile_state *state,
4117 struct triple *expr)
4118{
4119 switch(expr->op) {
4120 case OP_LTRUE: case OP_LFALSE: case OP_EQ: case OP_NOTEQ:
4121 case OP_SLESS: case OP_ULESS: case OP_SMORE: case OP_UMORE:
4122 case OP_SLESSEQ: case OP_ULESSEQ: case OP_SMOREEQ: case OP_UMOREEQ:
4123 /* If the expression is already boolean do nothing */
4124 break;
4125 default:
4126 expr = triple(state, OP_LTRUE, &int_type, expr, 0);
4127 break;
4128 }
4129 return expr;
4130}
4131
4132static struct triple *lfalse_expr(struct compile_state *state,
4133 struct triple *expr)
4134{
4135 return triple(state, OP_LFALSE, &int_type, expr, 0);
4136}
4137
4138static struct triple *cond_expr(
4139 struct compile_state *state,
4140 struct triple *test, struct triple *left, struct triple *right)
4141{
4142 struct triple *def;
4143 struct type *result_type;
4144 unsigned int left_type, right_type;
4145 bool(state, test);
4146 left_type = left->type->type;
4147 right_type = right->type->type;
4148 result_type = 0;
4149 /* Both operands have arithmetic type */
4150 if (TYPE_ARITHMETIC(left_type) && TYPE_ARITHMETIC(right_type)) {
4151 result_type = arithmetic_result(state, left, right);
4152 }
4153 /* Both operands have void type */
4154 else if (((left_type & TYPE_MASK) == TYPE_VOID) &&
4155 ((right_type & TYPE_MASK) == TYPE_VOID)) {
4156 result_type = &void_type;
4157 }
4158 /* pointers to the same type... */
4159 else if ((result_type = compatible_ptrs(left->type, right->type))) {
4160 ;
4161 }
4162 /* Both operands are pointers and left is a pointer to void */
4163 else if (((left_type & TYPE_MASK) == TYPE_POINTER) &&
4164 ((right_type & TYPE_MASK) == TYPE_POINTER) &&
4165 ((left->type->left->type & TYPE_MASK) == TYPE_VOID)) {
4166 result_type = right->type;
4167 }
4168 /* Both operands are pointers and right is a pointer to void */
4169 else if (((left_type & TYPE_MASK) == TYPE_POINTER) &&
4170 ((right_type & TYPE_MASK) == TYPE_POINTER) &&
4171 ((right->type->left->type & TYPE_MASK) == TYPE_VOID)) {
4172 result_type = left->type;
4173 }
4174 if (!result_type) {
4175 error(state, 0, "Incompatible types in conditional expression");
4176 }
4177 def = triple(state, OP_COND, result_type, test,
4178 triple(state, OP_PRODUCT, &void_type, left, right));
4179 return def;
4180}
4181
4182
4183static int expr_depth(struct compile_state *state, struct triple *triple)
4184{
4185 int count;
4186 count = 0;
4187 if (!triple) {
4188 return 0;
4189 }
4190 /* All of the internal helper ops that are not removed by
4191 * flatten must be present here.
4192 */
4193 if (triple->op == OP_READ) {
4194 ;
4195 }
4196 else if (triple->op == OP_DEREF) {
4197 count = expr_depth(state, triple->left) - 1;
4198 }
4199 else if (triple->op == OP_VAL) {
4200 count = expr_depth(state, triple->left) - 1;
4201 }
4202 else if (triple->op == OP_COMMA) {
4203 int left, right;
4204 left = expr_depth(state, triple->left);
4205 right = expr_depth(state, triple->right);
4206 count = (left >= right)? left : right;
4207 }
4208 else if (triple->op == OP_CALL) {
4209 /* Don't figure the depth of a call just guess it is huge */
4210 count = 1000;
4211 }
4212 else {
4213 struct triple **expr;
4214 expr = triple_rhs(state, triple, 0);
4215 for(;expr; expr = triple_rhs(state, triple, expr)) {
4216 int depth;
4217 depth = expr_depth(state, *expr);
4218 if (depth > count) {
4219 count = depth;
4220 }
4221 }
4222 }
4223 return count + 1;
4224}
4225
4226static struct triple *flatten(
4227 struct compile_state *state, struct triple *first, struct triple *ptr);
4228
4229static struct triple *flatten_rhs(
4230 struct compile_state *state, struct triple *first, struct triple *ptr)
4231{
4232 struct triple **left, **right, **last;
4233 /* Only operations with a rhs should come here */
4234 last = triple_lhs(state, ptr, 0);
4235 if (last) {
4236 internal_error(state, ptr, "unexpected rhs for: %d %s",
4237 ptr->op, tops(ptr->op));
4238 }
4239 /* Collect up the rhs */
4240 left = triple_rhs(state, ptr, 0);
4241 right = last = 0;
4242 if (left) {
4243 right = triple_rhs(state, ptr, left);
4244 }
4245 if (right) {
4246 last = triple_rhs(state, ptr, right);
4247 }
4248 if (last) {
4249 internal_error(state, ptr, "too many rhs arguments for: %d %s",
4250 ptr->op, tops(ptr->op));
4251 }
4252 if (left && right) {
4253 if (expr_depth(state, *left) >= expr_depth(state, *right)) {
4254 *left = flatten(state, first, *left);
4255 *right = flatten(state, first, *right);
4256 }
4257 else {
4258 *right = flatten(state, first, *right);
4259 *left = flatten(state, first, *left);
4260 }
4261 use_triple(*left, ptr);
4262 use_triple(*right, ptr);
4263 }
4264 else if (left) {
4265 *left = flatten(state, first, *left);
4266 use_triple(*left, ptr);
4267 }
4268 return ptr;
4269}
4270
4271static struct triple *flatten_land(
4272 struct compile_state *state, struct triple *first, struct triple *ptr)
4273{
4274 struct triple *left, *right;
4275 struct triple *val, *test, *jmp, *label1, *end;
4276
4277 /* Find the triples */
4278 left = ptr->left;
4279 right = ptr->right;
4280
4281 /* Generate the needed triples */
4282 end = label(state);
4283
4284 /* Thread the triples together */
4285 val = flatten(state, first, variable(state, ptr->type));
4286 left = flatten(state, first, write_expr(state, val, left));
4287 test = flatten(state, first,
4288 lfalse_expr(state, read_expr(state, val)));
4289 jmp = flatten(state, first,
4290 triple(state, OP_BRANCH, &void_type, end, test));
4291 label1 = flatten(state, first, label(state));
4292 right = flatten(state, first, write_expr(state, val, right));
4293 jmp->left = flatten(state, first, end);
4294
4295
4296 /* Now give the caller something to chew on */
4297 return read_expr(state, val);
4298}
4299
4300static struct triple *flatten_lor(
4301 struct compile_state *state, struct triple *first, struct triple *ptr)
4302{
4303 struct triple *left, *right;
4304 struct triple *val, *jmp, *label1, *end;
4305
4306 /* Find the triples */
4307 left = ptr->left;
4308 right = ptr->right;
4309
4310 /* Generate the needed triples */
4311 end = label(state);
4312
4313 /* Thread the triples together */
4314 val = flatten(state, first, variable(state, ptr->type));
4315 left = flatten(state, first, write_expr(state, val, left));
4316 jmp = flatten(state, first,
4317 triple(state, OP_BRANCH, &void_type, end, left));
4318 label1 = flatten(state, first, label(state));
4319 right = flatten(state, first, write_expr(state, val, right));
4320 jmp->left = flatten(state, first, end);
4321
4322
4323 /* Now give the caller something to chew on */
4324 return read_expr(state, val);
4325}
4326
4327static struct triple *flatten_cond(
4328 struct compile_state *state, struct triple *first, struct triple *ptr)
4329{
4330 struct triple *test, *left, *right;
4331 struct triple *val, *mv1, *jmp1, *label1, *mv2, *middle, *jmp2, *end;
4332 if (ptr->right->op != OP_PRODUCT) {
4333 internal_error(state, 0, "Improper conditional expression");
4334 }
4335
4336 /* Find the triples */
4337 test = ptr->left;
4338 left = ptr->right->left;
4339 right = ptr->right->right;
4340
4341 /* Generate the needed triples */
4342 end = label(state);
4343 middle = label(state);
4344
4345 /* Thread the triples together */
4346 val = flatten(state, first, variable(state, ptr->type));
4347 test = flatten(state, first, test);
4348 jmp1 = flatten(state, first,
4349 triple(state, OP_BRANCH, &void_type, middle, test));
4350 label1 = flatten(state, first, label(state));
4351 left = flatten(state, first, left);
4352 mv1 = flatten(state, first, write_expr(state, val, left));
4353 jmp2 = flatten(state, first,
4354 triple(state, OP_BRANCH, &void_type, end, 0));
4355 jmp1->left = flatten(state, first, middle);
4356 right = flatten(state, first, right);
4357 mv2 = flatten(state, first, write_expr(state, val, right));
4358 jmp2->left = flatten(state, first, end);
4359
4360
4361 /* Now give the caller something to chew on */
4362 return read_expr(state, val);
4363}
4364
4365struct triple *copy_func(struct compile_state *state, struct triple *ofunc)
4366{
4367 struct triple *nfunc;
4368 struct triple *nfirst, *ofirst;
4369 struct triple *new, *old;
4370
4371#if 0
4372 fprintf(stdout, "\n");
4373 loc(stdout, state, 0);
4374 fprintf(stdout, "\n__________ copy_func _________\n");
4375 print_triple(state, ofunc);
4376 fprintf(stdout, "__________ copy_func _________ done\n\n");
4377#endif
4378
4379 /* Make a new copy of the old function */
4380 nfunc = triple(state, OP_LIST, ofunc->type, 0, 0);
4381 nfirst = 0;
4382 ofirst = old = ofunc->left;
4383 do {
4384 struct triple *new;
4385 new = build_triple(state, old->op, old->type, 0, 0,
4386 old->filename, old->line, old->col);
4387 if (IS_CONST_OP(new->op)) {
4388 memcpy(&new->u, &old->u, sizeof(new->u));
4389 }
4390#warning "WISHLIST find a way to handle SDECL without a special case..."
4391 else if (new->op == OP_SDECL) {
4392 new->left = old->left;
4393 }
4394 if (!nfirst) {
4395 nfunc->left = nfirst = new;
4396 }
4397 else {
4398 insert_triple(state, nfirst, new);
4399 }
4400
4401 /* During the copy remember new as user of old */
4402 use_triple(old, new);
4403
4404 /* Populate the return type if present */
4405 if (old == ofunc->right) {
4406 nfunc->right = new;
4407 }
4408 old = old->next;
4409 } while(old != ofirst);
4410
4411 /* Make a second pass to fix up any unresolved references */
4412 old = ofirst;
4413 new = nfirst;
4414 do {
4415 /* Lookup where the copy is, to join pointers */
4416 if (!new->left && old->left && old->left->use) {
4417 new->left = old->left->use->member;
4418 if (new->left == old) {
4419 internal_error(state, 0, "new == old?");
4420 }
4421 }
4422 if (!new->right && old->right && old->right->use) {
4423 new->right = old->right->use->member;
4424 if (new->right == old) {
4425 internal_error(state, 0, "new == old?");
4426 }
4427 }
4428 if (!new->left && old->left) {
4429 internal_error(state, 0, "Could not copy left");
4430 }
4431 if (!new->right && old->right) {
4432 internal_error(state, 0, "Could not copy right");
4433 }
4434 if (new->op != old->op) {
4435 internal_error(state, 0, "Could not copy op?");
4436 }
4437 if (!new->next && old->next) {
4438 internal_error(state, 0, "Could not copy next");
4439 }
4440 use_triple(new->left, new);
4441 use_triple(new->right, new);
4442 if (new->op == OP_BRANCH) {
4443 if (new->right) {
4444 use_triple(new->next, new);
4445 }
4446 }
4447 old = old->next;
4448 new = new->next;
4449 } while((old != ofirst) && (new != nfirst));
4450
4451 /* Make a third pass to cleanup the extra useses */
4452 old = ofirst;
4453 new = nfirst;
4454 do {
4455 unuse_triple(old, new);
4456 old = old->next;
4457 new = new->next;
4458 } while ((old != ofirst) && (new != nfirst));
4459 return nfunc;
4460}
4461
4462static struct triple *flatten_call(
4463 struct compile_state *state, struct triple *first, struct triple *ptr)
4464{
4465 /* Inline the function call */
4466 struct triple *ofunc, *nfunc, *nfirst, *args, *param, *result;
4467 struct triple *end, *nend;
4468 int done;
4469
4470 /* Find the triples */
4471 ofunc = ptr->left;
4472 args = ptr->right;
4473 if (ofunc->op != OP_LIST) {
4474 internal_error(state, 0, "improper function");
4475 }
4476 nfunc = copy_func(state, ofunc);
4477 nfirst = nfunc->left->next;
4478 param = nfunc->left->next;
4479 /* Prepend the parameter reading into the new function list */
4480 while(args) {
4481 struct triple *arg;
4482 arg = args;
4483 done = 1;
4484 if (args->op == OP_PRODUCT) {
4485 arg = args->left;
4486 }
4487 flatten(state, nfirst,
4488 write_expr(state, param, arg));
4489 param = param->next;
4490 args = (args->op == OP_PRODUCT)? args->right : 0;
4491 }
4492 result = 0;
4493 if ((nfunc->type->left->type & TYPE_MASK) != TYPE_VOID) {
4494 result = read_expr(state, nfunc->right);
4495 }
4496#if 0
4497 fprintf(stdout, "\n");
4498 loc(stdout, state, 0);
4499 fprintf(stdout, "\n__________ flatten_call _________\n");
4500 print_triple(state, nfunc);
4501 fprintf(stdout, "__________ flatten_call _________ done\n\n");
4502#endif
4503
4504 /* Get rid of the extra triples */
4505 nfirst = nfunc->left->next;
4506 free_triple(state, nfunc->left);
4507 nfunc->left = 0;
4508 free_triple(state, nfunc);
4509
4510 /* Append the new function list onto the return list */
4511 end = first->prev;
4512 nend = nfirst->prev;
4513 end->next = nfirst;
4514 nfirst->prev = end;
4515 nend->next = first;
4516 first->prev = nend;
4517
4518 return result;
4519}
4520
4521static struct triple *flatten(
4522 struct compile_state *state, struct triple *first, struct triple *ptr)
4523{
4524 struct triple *orig_ptr;
4525 if (!ptr)
4526 return 0;
4527 do {
4528 orig_ptr = ptr;
4529 switch(ptr->op) {
4530 case OP_WRITE:
4531 case OP_STORE:
4532 ptr->right = flatten(state, first, ptr->right);
4533 ptr->left = flatten(state, first, ptr->left);
4534 use_triple(ptr->left, ptr);
4535 use_triple(ptr->right, ptr);
4536 break;
4537 case OP_COMMA:
4538 ptr->left = flatten(state, first, ptr->left);
4539 ptr = ptr->right;
4540 break;
4541 case OP_VAL:
4542 ptr->left = flatten(state, first, ptr->left);
4543 return ptr->right;
4544 break;
4545 case OP_LAND:
4546 ptr = flatten_land(state, first, ptr);
4547 break;
4548 case OP_LOR:
4549 ptr = flatten_lor(state, first, ptr);
4550 break;
4551 case OP_COND:
4552 ptr = flatten_cond(state, first, ptr);
4553 break;
4554 case OP_CALL:
4555 ptr = flatten_call(state, first, ptr);
4556 break;
4557 case OP_READ:
4558 case OP_LOAD:
4559 ptr->left = flatten(state, first, ptr->left);
4560 use_triple(ptr->left, ptr);
4561 break;
4562 case OP_BRANCH:
4563 use_triple(ptr->left, ptr);
4564 use_triple(ptr->right, ptr);
4565 if (ptr->next != ptr) {
4566 use_triple(ptr->next, ptr);
4567 }
4568 break;
4569 case OP_ADDRCONST:
4570 ptr->left = flatten(state, first, ptr->left);
4571 use_triple(ptr->left, ptr);
4572 break;
4573 case OP_BLOBCONST:
4574 ptr = triple(state, OP_SDECL, ptr->type, ptr, 0);
4575 use_triple(ptr->left, ptr);
4576 break;
4577 case OP_DEREF:
4578 /* Since OP_DEREF is just a marker delete it when I flatten it */
4579 ptr = ptr->left;
4580 orig_ptr->left = 0;
4581 free_triple(state, orig_ptr);
4582 break;
4583 case OP_PRODUCT:
4584 case OP_DOT:
4585 internal_error(state, 0, "unknown expression type: %d %s",
4586 ptr->op, tops(ptr->op));
4587 break;
4588 case OP_SDECL:
4589 case OP_ADECL:
4590 /* Don't flatten already flattened decls */
4591 if ((ptr->next != ptr) || (ptr->prev != ptr)) {
4592 return ptr;
4593 }
4594 break;
4595 default:
4596 /* Flatten the easy cases we don't override */
4597 ptr = flatten_rhs(state, first, ptr);
4598 break;
4599 }
4600 } while(ptr && (ptr != orig_ptr));
4601 insert_triple(state, first, ptr);
4602 return ptr;
4603}
4604
4605static void release_expr(struct compile_state *state, struct triple *expr)
4606{
4607 struct triple *head;
4608 head = label(state);
4609 flatten(state, head, expr);
4610 while(head->next != head) {
4611 release_triple(state, head->next);
4612 }
4613 free_triple(state, head);
4614}
4615
4616static int replace_rhs_use(struct compile_state *state,
4617 struct triple *orig, struct triple *new, struct triple *use)
4618{
4619 struct triple **expr;
4620 int found;
4621 found = 0;
4622 expr = triple_rhs(state, use, 0);
4623 for(;expr; expr = triple_rhs(state, use, expr)) {
4624 if (*expr == orig) {
4625 *expr = new;
4626 found = 1;
4627 }
4628 }
4629 if (found) {
4630 unuse_triple(orig, use);
4631 use_triple(new, use);
4632 }
4633 return found;
4634}
4635
4636static int replace_lhs_use(struct compile_state *state,
4637 struct triple *orig, struct triple *new, struct triple *use)
4638{
4639 struct triple **expr;
4640 int found;
4641 found = 0;
4642 expr = triple_lhs(state, use, 0);
4643 for(;expr; expr = triple_lhs(state, use, expr)) {
4644 if (*expr == orig) {
4645 *expr = new;
4646 found = 1;
4647 }
4648 }
4649 if (found) {
4650 unuse_triple(orig, use);
4651 use_triple(new, use);
4652 }
4653 return found;
4654}
4655
4656static void propogate_use(struct compile_state *state,
4657 struct triple *orig, struct triple *new)
4658{
4659 struct triple_set *user, *next;
4660 for(user = orig->use; user; user = next) {
4661 struct triple *use;
4662 int found;
4663 next = user->next;
4664 use = user->member;
4665 found = 0;
4666 found |= replace_rhs_use(state, orig, new, use);
4667 found |= replace_lhs_use(state, orig, new, use);
4668 if (!found) {
4669 internal_error(state, use, "use without use");
4670 }
4671 }
4672 if (orig->use) {
4673 internal_error(state, orig, "used after propogate_use");
4674 }
4675}
4676
4677/*
4678 * Code generators
4679 * ===========================
4680 */
4681
4682static struct triple *mk_add_expr(
4683 struct compile_state *state, struct triple *left, struct triple *right)
4684{
4685 struct type *result_type;
4686 /* Put pointer operands on the left */
4687 if (is_pointer(right)) {
4688 struct triple *tmp;
4689 tmp = left;
4690 left = right;
4691 right = tmp;
4692 }
4693 result_type = ptr_arithmetic_result(state, left, right);
4694 left = read_expr(state, left);
4695 right = read_expr(state, right);
4696 if (is_pointer(left)) {
4697 right = triple(state,
4698 is_signed(right->type)? OP_SMUL : OP_UMUL,
4699 &ulong_type,
4700 right,
4701 int_const(state, &ulong_type,
4702 size_of(state, left->type->left)));
4703 }
4704 return triple(state, OP_ADD, result_type, left, right);
4705}
4706
4707static struct triple *mk_sub_expr(
4708 struct compile_state *state, struct triple *left, struct triple *right)
4709{
4710 struct type *result_type;
4711 result_type = ptr_arithmetic_result(state, left, right);
4712 left = read_expr(state, left);
4713 right = read_expr(state, right);
4714 if (is_pointer(left)) {
4715 right = triple(state,
4716 is_signed(right->type)? OP_SMUL : OP_UMUL,
4717 &ulong_type,
4718 right,
4719 int_const(state, &ulong_type,
4720 size_of(state, left->type->left)));
4721 }
4722 return triple(state, OP_SUB, result_type, left, right);
4723}
4724
4725static struct triple *mk_pre_inc_expr(
4726 struct compile_state *state, struct triple *def)
4727{
4728 struct triple *val;
4729 lvalue(state, def);
4730 val = mk_add_expr(state, def, int_const(state, &int_type, 1));
4731 return triple(state, OP_VAL, def->type,
4732 write_expr(state, def, val),
4733 val);
4734}
4735
4736static struct triple *mk_pre_dec_expr(
4737 struct compile_state *state, struct triple *def)
4738{
4739 struct triple *val;
4740 lvalue(state, def);
4741 val = mk_sub_expr(state, def, int_const(state, &int_type, 1));
4742 return triple(state, OP_VAL, def->type,
4743 write_expr(state, def, val),
4744 val);
4745}
4746
4747static struct triple *mk_post_inc_expr(
4748 struct compile_state *state, struct triple *def)
4749{
4750 struct triple *val;
4751 lvalue(state, def);
4752 val = read_expr(state, def);
4753 return triple(state, OP_VAL, def->type,
4754 write_expr(state, def,
4755 mk_add_expr(state, val, int_const(state, &int_type, 1)))
4756 , val);
4757}
4758
4759static struct triple *mk_post_dec_expr(
4760 struct compile_state *state, struct triple *def)
4761{
4762 struct triple *val;
4763 lvalue(state, def);
4764 val = read_expr(state, def);
4765 return triple(state, OP_VAL, def->type,
4766 write_expr(state, def,
4767 mk_sub_expr(state, val, int_const(state, &int_type, 1)))
4768 , val);
4769}
4770
4771static struct triple *mk_subscript_expr(
4772 struct compile_state *state, struct triple *left, struct triple *right)
4773{
4774 left = read_expr(state, left);
4775 right = read_expr(state, right);
4776 if (!is_pointer(left) && !is_pointer(right)) {
4777 error(state, left, "subscripted value is not a pointer");
4778 }
4779 return mk_deref_expr(state, mk_add_expr(state, left, right));
4780}
4781
4782/*
4783 * Compile time evaluation
4784 * ===========================
4785 */
4786static int is_const(struct triple *ins)
4787{
4788 return IS_CONST_OP(ins->op);
4789}
4790
4791static int constants_equal(struct compile_state *state,
4792 struct triple *left, struct triple *right)
4793{
4794 int equal;
4795 if (!is_const(left) || !is_const(right)) {
4796 equal = 0;
4797 }
4798 else if (left->op != right->op) {
4799 equal = 0;
4800 }
4801 else if (!equiv_types(left->type, right->type)) {
4802 equal = 0;
4803 }
4804 else {
4805 equal = 0;
4806 switch(left->op) {
4807 case OP_INTCONST:
4808 if (left->u.cval == right->u.cval) {
4809 equal = 1;
4810 }
4811 break;
4812 case OP_BLOBCONST:
4813 {
4814 size_t lsize, rsize;
4815 lsize = size_of(state, left->type);
4816 rsize = size_of(state, right->type);
4817 if (lsize != rsize) {
4818 break;
4819 }
4820 if (memcmp(left->u.blob, right->u.blob, lsize) == 0) {
4821 equal = 1;
4822 }
4823 break;
4824 }
4825 case OP_ADDRCONST:
4826 if ((left->left == right->left) &&
4827 (left->u.cval == right->u.cval)) {
4828 equal = 1;
4829 }
4830 break;
4831 default:
4832 internal_error(state, left, "uknown constant type");
4833 break;
4834 }
4835 }
4836 return equal;
4837}
4838
4839static int is_zero(struct triple *ins)
4840{
4841 return is_const(ins) && (ins->u.cval == 0);
4842}
4843
4844static int is_one(struct triple *ins)
4845{
4846 return is_const(ins) && (ins->u.cval == 1);
4847}
4848
4849static long_t bsr(ulong_t value)
4850{
4851 int i;
4852 for(i = (sizeof(ulong_t)*8) -1; i >= 0; i--) {
4853 ulong_t mask;
4854 mask = 1;
4855 mask <<= i;
4856 if (value & mask) {
4857 return i;
4858 }
4859 }
4860 return -1;
4861}
4862
4863static long_t bsf(ulong_t value)
4864{
4865 int i;
4866 for(i = 0; i < (sizeof(ulong_t)*8); i++) {
4867 ulong_t mask;
4868 mask = 1;
4869 mask <<= 1;
4870 if (value & mask) {
4871 return i;
4872 }
4873 }
4874 return -1;
4875}
4876
4877static long_t log2(ulong_t value)
4878{
4879 return bsr(value);
4880}
4881
4882static long_t tlog2(struct triple *ins)
4883{
4884 return log2(ins->u.cval);
4885}
4886
4887static int is_pow2(struct triple *ins)
4888{
4889 ulong_t value, mask;
4890 long_t log;
4891 if (!is_const(ins)) {
4892 return 0;
4893 }
4894 value = ins->u.cval;
4895 log = log2(value);
4896 if (log == -1) {
4897 return 0;
4898 }
4899 mask = 1;
4900 mask <<= log;
4901 return ((value & mask) == value);
4902}
4903
4904static ulong_t read_const(struct compile_state *state,
4905 struct triple *ins, struct triple **expr)
4906{
4907 struct triple *rhs;
4908 rhs = *expr;
4909 switch(rhs->type->type &TYPE_MASK) {
4910 case TYPE_CHAR:
4911 case TYPE_SHORT:
4912 case TYPE_INT:
4913 case TYPE_LONG:
4914 case TYPE_UCHAR:
4915 case TYPE_USHORT:
4916 case TYPE_UINT:
4917 case TYPE_ULONG:
4918 case TYPE_POINTER:
4919 break;
4920 default:
4921 internal_error(state, rhs, "bad type to read_const\n");
4922 break;
4923 }
4924 return rhs->u.cval;
4925}
4926
4927static long_t read_sconst(struct triple *ins, struct triple **expr)
4928{
4929 struct triple *rhs;
4930 rhs = *expr;
4931 return (long_t)(rhs->u.cval);
4932}
4933
4934static void unuse_rhs(struct compile_state *state, struct triple *ins)
4935{
4936 struct triple **expr;
4937 expr = triple_rhs(state, ins, 0);
4938 for(;expr;expr = triple_rhs(state, ins, expr)) {
4939 unuse_triple(*expr, ins);
4940 *expr = 0;
4941 }
4942}
4943static void check_lhs(struct compile_state *state, struct triple *ins)
4944{
4945 struct triple **expr;
4946 expr = triple_lhs(state, ins, 0);
4947 for(;expr;expr = triple_lhs(state, ins, expr)) {
4948 internal_error(state, ins, "unexpected lhs");
4949 }
4950
4951}
4952static void check_targ(struct compile_state *state, struct triple *ins)
4953{
4954 struct triple **expr;
4955 expr = triple_targ(state, ins, 0);
4956 for(;expr;expr = triple_targ(state, ins, expr)) {
4957 internal_error(state, ins, "unexpected targ");
4958 }
4959}
4960
4961static void wipe_ins(struct compile_state *state, struct triple *ins)
4962{
4963 check_lhs(state, ins);
4964 check_targ(state, ins);
4965 unuse_rhs(state, ins);
4966 if (ins->op == OP_PHI) {
4967 xfree(ins->left);
4968 ins->left = 0;
4969 }
4970}
4971
4972static void mkcopy(struct compile_state *state,
4973 struct triple *ins, struct triple *rhs)
4974{
4975 wipe_ins(state, ins);
4976 ins->op = OP_COPY;
4977 ins->left = rhs;
4978 use_triple(ins->left, ins);
4979}
4980
4981static void mkconst(struct compile_state *state,
4982 struct triple *ins, ulong_t value)
4983{
4984 if (!is_integral(ins) && !is_pointer(ins)) {
4985 internal_error(state, ins, "unknown type to make constant\n");
4986 }
4987 wipe_ins(state, ins);
4988 ins->op = OP_INTCONST;
4989 ins->u.cval = value;
4990}
4991
4992static void mkaddr_const(struct compile_state *state,
4993 struct triple *ins, struct triple *sdecl, ulong_t value)
4994{
4995 wipe_ins(state, ins);
4996 ins->op = OP_ADDRCONST;
4997 ins->left = sdecl;
4998 ins->u.cval = value;
4999 use_triple(sdecl, ins);
5000}
5001
5002/* For those operations that cannot be simplified */
5003static void simplify_noop(struct compile_state *state, struct triple *ins)
5004{
5005 return;
5006}
5007
5008static void simplify_smul(struct compile_state *state, struct triple *ins)
5009{
5010 if (is_const(ins->left) && !is_const(ins->right)) {
5011 struct triple *tmp;
5012 tmp = ins->left;
5013 ins->left = ins->right;
5014 ins->right = tmp;
5015 }
5016 if (is_const(ins->left) && is_const(ins->right)) {
5017 long_t left, right;
5018 left = read_sconst(ins, &ins->left);
5019 right = read_sconst(ins, &ins->right);
5020 mkconst(state, ins, left * right);
5021 }
5022 else if (is_zero(ins->right)) {
5023 mkconst(state, ins, 0);
5024 }
5025 else if (is_one(ins->right)) {
5026 mkcopy(state, ins, ins->left);
5027 }
5028 else if (is_pow2(ins->right)) {
5029 struct triple *val;
5030 val = int_const(state, ins->type, tlog2(ins->right));
5031 ins->op = OP_SL;
5032 insert_triple(state, ins, val);
5033 unuse_triple(ins->right, ins);
5034 use_triple(val, ins);
5035 ins->right = val;
5036 }
5037}
5038
5039static void simplify_umul(struct compile_state *state, struct triple *ins)
5040{
5041 if (is_const(ins->left) && !is_const(ins->right)) {
5042 struct triple *tmp;
5043 tmp = ins->left;
5044 ins->left = ins->right;
5045 ins->right = tmp;
5046 }
5047 if (is_const(ins->left) && is_const(ins->right)) {
5048 ulong_t left, right;
5049 left = read_const(state, ins, &ins->left);
5050 right = read_const(state, ins, &ins->right);
5051 mkconst(state, ins, left * right);
5052 }
5053 else if (is_zero(ins->right)) {
5054 mkconst(state, ins, 0);
5055 }
5056 else if (is_one(ins->right)) {
5057 mkcopy(state, ins, ins->left);
5058 }
5059 else if (is_pow2(ins->right)) {
5060 struct triple *val;
5061 val = int_const(state, ins->type, tlog2(ins->right));
5062 ins->op = OP_SL;
5063 insert_triple(state, ins, val);
5064 unuse_triple(ins->right, ins);
5065 use_triple(val, ins);
5066 ins->right = val;
5067 }
5068}
5069
5070static void simplify_sdiv(struct compile_state *state, struct triple *ins)
5071{
5072 if (is_const(ins->left) && is_const(ins->right)) {
5073 long_t left, right;
5074 left = read_sconst(ins, &ins->left);
5075 right = read_sconst(ins, &ins->right);
5076 mkconst(state, ins, left / right);
5077 }
5078 else if (is_zero(ins->left)) {
5079 mkconst(state, ins, 0);
5080 }
5081 else if (is_zero(ins->right)) {
5082 error(state, ins, "division by zero");
5083 }
5084 else if (is_one(ins->right)) {
5085 mkcopy(state, ins, ins->left);
5086 }
5087 else if (is_pow2(ins->right)) {
5088 struct triple *val;
5089 val = int_const(state, ins->type, tlog2(ins->right));
5090 ins->op = OP_SSR;
5091 insert_triple(state, ins, val);
5092 unuse_triple(ins->right, ins);
5093 use_triple(val, ins);
5094 ins->right = val;
5095 }
5096}
5097
5098static void simplify_udiv(struct compile_state *state, struct triple *ins)
5099{
5100 if (is_const(ins->left) && is_const(ins->right)) {
5101 ulong_t left, right;
5102 left = read_const(state, ins, &ins->left);
5103 right = read_const(state, ins, &ins->right);
5104 mkconst(state, ins, left / right);
5105 }
5106 else if (is_zero(ins->left)) {
5107 mkconst(state, ins, 0);
5108 }
5109 else if (is_zero(ins->right)) {
5110 error(state, ins, "division by zero");
5111 }
5112 else if (is_one(ins->right)) {
5113 mkcopy(state, ins, ins->left);
5114 }
5115 else if (is_pow2(ins->right)) {
5116 struct triple *val;
5117 val = int_const(state, ins->type, tlog2(ins->right));
5118 ins->op = OP_USR;
5119 insert_triple(state, ins, val);
5120 unuse_triple(ins->right, ins);
5121 use_triple(val, ins);
5122 ins->right = val;
5123 }
5124}
5125
5126static void simplify_smod(struct compile_state *state, struct triple *ins)
5127{
5128 if (is_const(ins->left) && is_const(ins->right)) {
5129 long_t left, right;
5130 left = read_const(state, ins, &ins->left);
5131 right = read_const(state, ins, &ins->right);
5132 mkconst(state, ins, left % right);
5133 }
5134 else if (is_zero(ins->left)) {
5135 mkconst(state, ins, 0);
5136 }
5137 else if (is_zero(ins->right)) {
5138 error(state, ins, "division by zero");
5139 }
5140 else if (is_one(ins->right)) {
5141 mkconst(state, ins, 0);
5142 }
5143 else if (is_pow2(ins->right)) {
5144 struct triple *val;
5145 val = int_const(state, ins->type, ins->right->u.cval - 1);
5146 ins->op = OP_AND;
5147 insert_triple(state, ins, val);
5148 unuse_triple(ins->right, ins);
5149 use_triple(val, ins);
5150 ins->right = val;
5151 }
5152}
5153static void simplify_umod(struct compile_state *state, struct triple *ins)
5154{
5155 if (is_const(ins->left) && is_const(ins->right)) {
5156 ulong_t left, right;
5157 left = read_const(state, ins, &ins->left);
5158 right = read_const(state, ins, &ins->right);
5159 mkconst(state, ins, left % right);
5160 }
5161 else if (is_zero(ins->left)) {
5162 mkconst(state, ins, 0);
5163 }
5164 else if (is_zero(ins->right)) {
5165 error(state, ins, "division by zero");
5166 }
5167 else if (is_one(ins->right)) {
5168 mkconst(state, ins, 0);
5169 }
5170 else if (is_pow2(ins->right)) {
5171 struct triple *val;
5172 val = int_const(state, ins->type, ins->right->u.cval - 1);
5173 ins->op = OP_AND;
5174 insert_triple(state, ins, val);
5175 unuse_triple(ins->right, ins);
5176 use_triple(val, ins);
5177 ins->right = val;
5178 }
5179}
5180
5181static void simplify_add(struct compile_state *state, struct triple *ins)
5182{
5183 /* start with the pointer on the left */
5184 if (is_pointer(ins->right)) {
5185 struct triple *tmp;
5186 tmp = ins->left;
5187 ins->left = ins->right;
5188 ins->right = tmp;
5189 }
5190 if (is_const(ins->left) && is_const(ins->right)) {
5191 if (!is_pointer(ins->left)) {
5192 ulong_t left, right;
5193 left = read_const(state, ins, &ins->left);
5194 right = read_const(state, ins, &ins->right);
5195 mkconst(state, ins, left + right);
5196 }
5197 else {
5198 struct triple *sdecl;
5199 ulong_t left, right;
5200 sdecl = ins->left->left;
5201 left = ins->left->u.cval;
5202 right = ins->right->u.cval;
5203 mkaddr_const(state, ins, sdecl, left + right);
5204 }
5205 }
5206 else if (is_const(ins->left) && !is_const(ins->right)) {
5207 struct triple *tmp;
5208 tmp = ins->right;
5209 ins->right = ins->left;
5210 ins->left = tmp;
5211 }
5212}
5213
5214static void simplify_sub(struct compile_state *state, struct triple *ins)
5215{
5216 if (is_const(ins->left) && is_const(ins->right)) {
5217 if (!is_pointer(ins->left)) {
5218 ulong_t left, right;
5219 left = read_const(state, ins, &ins->left);
5220 right = read_const(state, ins, &ins->right);
5221 mkconst(state, ins, left - right);
5222 }
5223 else {
5224 struct triple *sdecl;
5225 ulong_t left, right;
5226 sdecl = ins->left->left;
5227 left = ins->left->u.cval;
5228 right = ins->right->u.cval;
5229 mkaddr_const(state, ins, sdecl, left - right);
5230 }
5231 }
5232}
5233
5234static void simplify_sl(struct compile_state *state, struct triple *ins)
5235{
5236 if (is_const(ins->right)) {
5237 ulong_t right;
5238 right = read_const(state, ins, &ins->right);
5239 if (right >= (size_of(state, ins->type)*8)) {
5240 warning(state, ins, "left shift count >= width of type");
5241 }
5242 }
5243 if (is_const(ins->left) && is_const(ins->right)) {
5244 ulong_t left, right;
5245 left = read_const(state, ins, &ins->left);
5246 right = read_const(state, ins, &ins->right);
5247 mkconst(state, ins, left << right);
5248 }
5249}
5250
5251static void simplify_usr(struct compile_state *state, struct triple *ins)
5252{
5253 if (is_const(ins->right)) {
5254 ulong_t right;
5255 right = read_const(state, ins, &ins->right);
5256 if (right >= (size_of(state, ins->type)*8)) {
5257 warning(state, ins, "right shift count >= width of type");
5258 }
5259 }
5260 if (is_const(ins->left) && is_const(ins->right)) {
5261 ulong_t left, right;
5262 left = read_const(state, ins, &ins->left);
5263 right = read_const(state, ins, &ins->right);
5264 mkconst(state, ins, left >> right);
5265 }
5266}
5267
5268static void simplify_ssr(struct compile_state *state, struct triple *ins)
5269{
5270 if (is_const(ins->right)) {
5271 ulong_t right;
5272 right = read_const(state, ins, &ins->right);
5273 if (right >= (size_of(state, ins->type)*8)) {
5274 warning(state, ins, "right shift count >= width of type");
5275 }
5276 }
5277 if (is_const(ins->left) && is_const(ins->right)) {
5278 long_t left, right;
5279 left = read_sconst(ins, &ins->left);
5280 right = read_sconst(ins, &ins->right);
5281 mkconst(state, ins, left >> right);
5282 }
5283}
5284
5285static void simplify_and(struct compile_state *state, struct triple *ins)
5286{
5287 if (is_const(ins->left) && is_const(ins->right)) {
5288 ulong_t left, right;
5289 left = read_const(state, ins, &ins->left);
5290 right = read_const(state, ins, &ins->right);
5291 mkconst(state, ins, left & right);
5292 }
5293}
5294
5295static void simplify_or(struct compile_state *state, struct triple *ins)
5296{
5297 if (is_const(ins->left) && is_const(ins->right)) {
5298 ulong_t left, right;
5299 left = read_const(state, ins, &ins->left);
5300 right = read_const(state, ins, &ins->right);
5301 mkconst(state, ins, left | right);
5302 }
5303}
5304
5305static void simplify_xor(struct compile_state *state, struct triple *ins)
5306{
5307 if (is_const(ins->left) && is_const(ins->right)) {
5308 ulong_t left, right;
5309 left = read_const(state, ins, &ins->left);
5310 right = read_const(state, ins, &ins->right);
5311 mkconst(state, ins, left ^ right);
5312 }
5313}
5314
5315static void simplify_pos(struct compile_state *state, struct triple *ins)
5316{
5317 if (is_const(ins->left)) {
5318 mkconst(state, ins, ins->left->u.cval);
5319 }
5320 else {
5321 mkcopy(state, ins, ins->left);
5322 }
5323}
5324
5325static void simplify_neg(struct compile_state *state, struct triple *ins)
5326{
5327 if (is_const(ins->left)) {
5328 ulong_t left;
5329 left = read_const(state, ins, &ins->left);
5330 mkconst(state, ins, -left);
5331 }
5332 else if (ins->left->op == OP_NEG) {
5333 mkcopy(state, ins, ins->left->left);
5334 }
5335}
5336
5337static void simplify_invert(struct compile_state *state, struct triple *ins)
5338{
5339 if (is_const(ins->left)) {
5340 ulong_t left;
5341 left = read_const(state, ins, &ins->left);
5342 mkconst(state, ins, ~left);
5343 }
5344}
5345
5346static void simplify_eq(struct compile_state *state, struct triple *ins)
5347{
5348 if (is_const(ins->left) && is_const(ins->right)) {
5349 ulong_t left, right;
5350 left = read_const(state, ins, &ins->left);
5351 right = read_const(state, ins, &ins->right);
5352 mkconst(state, ins, left == right);
5353 }
5354 else if (ins->left == ins->right) {
5355 mkconst(state, ins, 1);
5356 }
5357}
5358
5359static void simplify_noteq(struct compile_state *state, struct triple *ins)
5360{
5361 if (is_const(ins->left) && is_const(ins->right)) {
5362 ulong_t left, right;
5363 left = read_const(state, ins, &ins->left);
5364 right = read_const(state, ins, &ins->right);
5365 mkconst(state, ins, left != right);
5366 }
5367 else if (ins->left == ins->right) {
5368 mkconst(state, ins, 0);
5369 }
5370}
5371
5372static void simplify_sless(struct compile_state *state, struct triple *ins)
5373{
5374 if (is_const(ins->left) && is_const(ins->right)) {
5375 long_t left, right;
5376 left = read_sconst(ins, &ins->left);
5377 right = read_sconst(ins, &ins->right);
5378 mkconst(state, ins, left < right);
5379 }
5380 else if (ins->left == ins->right) {
5381 mkconst(state, ins, 0);
5382 }
5383}
5384
5385static void simplify_uless(struct compile_state *state, struct triple *ins)
5386{
5387 if (is_const(ins->left) && is_const(ins->right)) {
5388 ulong_t left, right;
5389 left = read_const(state, ins, &ins->left);
5390 right = read_const(state, ins, &ins->right);
5391 mkconst(state, ins, left < right);
5392 }
5393 else if (is_zero(ins->left)) {
5394 mkconst(state, ins, 1);
5395 }
5396 else if (ins->left == ins->right) {
5397 mkconst(state, ins, 0);
5398 }
5399}
5400
5401static void simplify_smore(struct compile_state *state, struct triple *ins)
5402{
5403 if (is_const(ins->left) && is_const(ins->right)) {
5404 long_t left, right;
5405 left = read_sconst(ins, &ins->left);
5406 right = read_sconst(ins, &ins->right);
5407 mkconst(state, ins, left > right);
5408 }
5409 else if (ins->left == ins->right) {
5410 mkconst(state, ins, 0);
5411 }
5412}
5413
5414static void simplify_umore(struct compile_state *state, struct triple *ins)
5415{
5416 if (is_const(ins->left) && is_const(ins->right)) {
5417 ulong_t left, right;
5418 left = read_const(state, ins, &ins->left);
5419 right = read_const(state, ins, &ins->right);
5420 mkconst(state, ins, left > right);
5421 }
5422 else if (is_zero(ins->right)) {
5423 mkconst(state, ins, 1);
5424 }
5425 else if (ins->left == ins->right) {
5426 mkconst(state, ins, 0);
5427 }
5428}
5429
5430
5431static void simplify_slesseq(struct compile_state *state, struct triple *ins)
5432{
5433 if (is_const(ins->left) && is_const(ins->right)) {
5434 long_t left, right;
5435 left = read_sconst(ins, &ins->left);
5436 right = read_sconst(ins, &ins->right);
5437 mkconst(state, ins, left <= right);
5438 }
5439 else if (ins->left == ins->right) {
5440 mkconst(state, ins, 1);
5441 }
5442}
5443
5444static void simplify_ulesseq(struct compile_state *state, struct triple *ins)
5445{
5446 if (is_const(ins->left) && is_const(ins->right)) {
5447 ulong_t left, right;
5448 left = read_const(state, ins, &ins->left);
5449 right = read_const(state, ins, &ins->right);
5450 mkconst(state, ins, left <= right);
5451 }
5452 else if (is_zero(ins->left)) {
5453 mkconst(state, ins, 1);
5454 }
5455 else if (ins->left == ins->right) {
5456 mkconst(state, ins, 1);
5457 }
5458}
5459
5460static void simplify_smoreeq(struct compile_state *state, struct triple *ins)
5461{
5462 if (is_const(ins->left) && is_const(ins->right)) {
5463 long_t left, right;
5464 left = read_sconst(ins, &ins->left);
5465 right = read_sconst(ins, &ins->right);
5466 mkconst(state, ins, left >= right);
5467 }
5468 else if (ins->left == ins->right) {
5469 mkconst(state, ins, 1);
5470 }
5471}
5472
5473static void simplify_umoreeq(struct compile_state *state, struct triple *ins)
5474{
5475 if (is_const(ins->left) && is_const(ins->right)) {
5476 ulong_t left, right;
5477 left = read_const(state, ins, &ins->left);
5478 right = read_const(state, ins, &ins->right);
5479 mkconst(state, ins, left >= right);
5480 }
5481 else if (is_zero(ins->right)) {
5482 mkconst(state, ins, 1);
5483 }
5484 else if (ins->left == ins->right) {
5485 mkconst(state, ins, 1);
5486 }
5487}
5488
5489static void simplify_lfalse(struct compile_state *state, struct triple *ins)
5490{
5491 if (is_const(ins->left)) {
5492 ulong_t left;
5493 left = read_const(state, ins, &ins->left);
5494 mkconst(state, ins, left == 0);
5495 }
5496 /* Otherwise if I am the only user... */
5497 else if ((ins->left->use->member == ins) && (ins->left->use->next == 0)) {
5498 int need_copy = 1;
5499 /* Invert a boolean operation */
5500 switch(ins->left->op) {
5501 case OP_LTRUE: ins->left->op = OP_LFALSE; break;
5502 case OP_LFALSE: ins->left->op = OP_LTRUE; break;
5503 case OP_EQ: ins->left->op = OP_NOTEQ; break;
5504 case OP_NOTEQ: ins->left->op = OP_EQ; break;
5505 case OP_SLESS: ins->left->op = OP_SMOREEQ; break;
5506 case OP_ULESS: ins->left->op = OP_UMOREEQ; break;
5507 case OP_SMORE: ins->left->op = OP_SLESSEQ; break;
5508 case OP_UMORE: ins->left->op = OP_ULESSEQ; break;
5509 case OP_SLESSEQ: ins->left->op = OP_SMORE; break;
5510 case OP_ULESSEQ: ins->left->op = OP_UMORE; break;
5511 case OP_SMOREEQ: ins->left->op = OP_SLESS; break;
5512 case OP_UMOREEQ: ins->left->op = OP_ULESS; break;
5513 default:
5514 need_copy = 0;
5515 break;
5516 }
5517 if (need_copy) {
5518 mkcopy(state, ins, ins->left);
5519 }
5520 }
5521}
5522
5523static void simplify_ltrue (struct compile_state *state, struct triple *ins)
5524{
5525 if (is_const(ins->left)) {
5526 ulong_t left;
5527 left = read_const(state, ins, &ins->left);
5528 mkconst(state, ins, left != 0);
5529 }
5530 else switch(ins->left->op) {
5531 case OP_LTRUE: case OP_LFALSE: case OP_EQ: case OP_NOTEQ:
5532 case OP_SLESS: case OP_ULESS: case OP_SMORE: case OP_UMORE:
5533 case OP_SLESSEQ: case OP_ULESSEQ: case OP_SMOREEQ: case OP_UMOREEQ:
5534 mkcopy(state, ins, ins->left);
5535 }
5536
5537}
5538
5539static void simplify_copy(struct compile_state *state, struct triple *ins)
5540{
5541 if (is_const(ins->left)) {
5542 switch(ins->left->op) {
5543 case OP_INTCONST:
5544 {
5545 ulong_t left;
5546 left = read_const(state, ins, &ins->left);
5547 mkconst(state, ins, left);
5548 break;
5549 }
5550 case OP_ADDRCONST:
5551 {
5552 struct triple *sdecl;
5553 ulong_t offset;
5554 sdecl = ins->left;
5555 offset = ins->u.cval;
5556 mkaddr_const(state, ins, sdecl, offset);
5557 break;
5558 }
5559 default:
5560 internal_error(state, ins, "uknown constant");
5561 break;
5562 }
5563 }
5564}
5565
5566static void simplify_dot(struct compile_state *state, struct triple *ins)
5567{
5568 FINISHME();
5569}
5570
5571static void simplify_branch(struct compile_state *state, struct triple *ins)
5572{
5573 struct block *block;
5574 if (ins->op != OP_BRANCH) {
5575 internal_error(state, ins, "not branch");
5576 }
5577 if (ins->use != 0) {
5578 internal_error(state, ins, "branch use");
5579 }
5580#warning "FIXME implement simplify branch."
5581 /* The challenge here with simplify branch is that I need to
5582 * make modifications to the control flow graph as well
5583 * as to the branch instruction itself.
5584 */
5585 block = ins->u.block;
5586
5587 if (ins->right && is_const(ins->right)) {
5588 ulong_t value;
5589 value = read_const(state, ins, &ins->right);
5590 unuse_triple(ins->right, ins);
5591 ins->right = 0;
5592 if (value) {
5593 unuse_triple(ins->next, ins);
5594 }
5595 else {
5596 unuse_triple(ins->left, ins);
5597 ins->left = ins->next;
5598 }
5599#warning "FIXME handle the case of making a branch unconditional"
5600 }
5601 if (ins->left == ins->next) {
5602 unuse_triple(ins->left, ins);
5603 if (ins->right) {
5604 unuse_triple(ins->right, ins);
5605 unuse_triple(ins->next, ins);
5606 }
5607 ins->op = OP_NOOP;
5608 ins->left = 0;
5609 ins->right = 0;
5610 if (ins->use) {
5611 internal_error(state, ins, "noop use != 0");
5612 }
5613#warning "FIXME handle the case of killing a branch"
5614 }
5615}
5616
5617static void simplify_phi(struct compile_state *state, struct triple *ins)
5618{
5619 struct triple **expr;
5620 ulong_t value;
5621 expr = triple_rhs(state, ins, 0);
5622 if (!is_const(*expr)) {
5623 return;
5624 }
5625 value = read_const(state, ins, expr);
5626 for(;expr;expr = triple_rhs(state, ins, expr)) {
5627 if (!is_const(*expr)) {
5628 return;
5629 }
5630 if (value != read_const(state, ins, expr)) {
5631 return;
5632 }
5633 }
5634 mkconst(state, ins, value);
5635}
5636
5637
5638static void simplify_bsf(struct compile_state *state, struct triple *ins)
5639{
5640 if (is_const(ins->left)) {
5641 ulong_t left;
5642 left = read_const(state, ins, &ins->left);
5643 mkconst(state, ins, bsf(left));
5644 }
5645}
5646
5647static void simplify_bsr(struct compile_state *state, struct triple *ins)
5648{
5649 if (is_const(ins->left)) {
5650 ulong_t left;
5651 left = read_const(state, ins, &ins->left);
5652 mkconst(state, ins, bsr(left));
5653 }
5654}
5655
5656
5657typedef void (*simplify_t)(struct compile_state *state, struct triple *ins);
5658static const simplify_t table_simplify[] = {
5659#if 0
5660#define simplify_smul simplify_noop
5661#define simplify_umul simplify_noop
5662#define simplify_sdiv simplify_noop
5663#define simplify_udiv simplify_noop
5664#define simplify_smod simplify_noop
5665#define simplify_umod simplify_noop
5666#endif
5667#if 0
5668#define simplify_add simplify_noop
5669#define simplify_sub simplify_noop
5670#endif
5671#if 0
5672#define simplify_sl simplify_noop
5673#define simplify_usr simplify_noop
5674#define simplify_ssr simplify_noop
5675#endif
5676#if 0
5677#define simplify_and simplify_noop
5678#define simplify_xor simplify_noop
5679#define simplify_or simplify_noop
5680#endif
5681#if 0
5682#define simplify_pos simplify_noop
5683#define simplify_neg simplify_noop
5684#define simplify_invert simplify_noop
5685#endif
5686
5687#if 0
5688#define simplify_eq simplify_noop
5689#define simplify_noteq simplify_noop
5690#endif
5691#if 0
5692#define simplify_sless simplify_noop
5693#define simplify_uless simplify_noop
5694#define simplify_smore simplify_noop
5695#define simplify_umore simplify_noop
5696#endif
5697#if 0
5698#define simplify_slesseq simplify_noop
5699#define simplify_ulesseq simplify_noop
5700#define simplify_smoreeq simplify_noop
5701#define simplify_umoreeq simplify_noop
5702#endif
5703#if 0
5704#define simplify_lfalse simplify_noop
5705#endif
5706#if 0
5707#define simplify_ltrue simplify_noop
5708#endif
5709
5710#if 0
5711#define simplify_copy simplify_noop
5712#endif
5713
5714#if 0
5715#define simplify_dot simplify_noop
5716#endif
5717
5718#if 0
5719#define simplify_branch simplify_noop
5720#endif
5721
5722#if 0
5723#define simplify_phi simplify_noop
5724#endif
5725
5726#if 0
5727#define simplify_bsf simplify_noop
5728#define simplify_bsr simplify_noop
5729#endif
5730
5731[OP_SMUL ] = simplify_smul,
5732[OP_UMUL ] = simplify_umul,
5733[OP_SDIV ] = simplify_sdiv,
5734[OP_UDIV ] = simplify_udiv,
5735[OP_SMOD ] = simplify_smod,
5736[OP_UMOD ] = simplify_umod,
5737[OP_ADD ] = simplify_add,
5738[OP_SUB ] = simplify_sub,
5739[OP_SL ] = simplify_sl,
5740[OP_USR ] = simplify_usr,
5741[OP_SSR ] = simplify_ssr,
5742[OP_AND ] = simplify_and,
5743[OP_XOR ] = simplify_xor,
5744[OP_OR ] = simplify_or,
5745[OP_POS ] = simplify_pos,
5746[OP_NEG ] = simplify_neg,
5747[OP_INVERT ] = simplify_invert,
5748
5749[OP_EQ ] = simplify_eq,
5750[OP_NOTEQ ] = simplify_noteq,
5751[OP_SLESS ] = simplify_sless,
5752[OP_ULESS ] = simplify_uless,
5753[OP_SMORE ] = simplify_smore,
5754[OP_UMORE ] = simplify_umore,
5755[OP_SLESSEQ ] = simplify_slesseq,
5756[OP_ULESSEQ ] = simplify_ulesseq,
5757[OP_SMOREEQ ] = simplify_smoreeq,
5758[OP_UMOREEQ ] = simplify_umoreeq,
5759[OP_LFALSE ] = simplify_lfalse,
5760[OP_LTRUE ] = simplify_ltrue,
5761
5762[OP_LOAD ] = simplify_noop,
5763[OP_STORE ] = simplify_noop,
5764
5765[OP_NOOP ] = simplify_noop,
5766
5767[OP_INTCONST ] = simplify_noop,
5768[OP_BLOBCONST ] = simplify_noop,
5769[OP_ADDRCONST ] = simplify_noop,
5770
5771[OP_WRITE ] = simplify_noop,
5772[OP_READ ] = simplify_noop,
5773[OP_COPY ] = simplify_copy,
5774[OP_DOT ] = simplify_dot,
5775
5776[OP_LIST ] = simplify_noop,
5777[OP_BRANCH ] = simplify_branch,
5778[OP_LABEL ] = simplify_noop,
5779[OP_ADECL ] = simplify_noop,
5780[OP_SDECL ] = simplify_noop,
5781[OP_PHI ] = simplify_phi,
5782
5783[OP_INB ] = simplify_noop,
5784[OP_INW ] = simplify_noop,
5785[OP_INL ] = simplify_noop,
5786[OP_OUTB ] = simplify_noop,
5787[OP_OUTW ] = simplify_noop,
5788[OP_OUTL ] = simplify_noop,
5789[OP_BSF ] = simplify_bsf,
5790[OP_BSR ] = simplify_bsr,
5791};
5792
5793static void simplify(struct compile_state *state, struct triple *ins)
5794{
5795 int op;
5796 simplify_t do_simplify;
5797 do {
5798 op = ins->op;
5799 do_simplify = 0;
5800 if ((op < 0) || (op > sizeof(table_simplify)/sizeof(table_simplify[0]))) {
5801 do_simplify = 0;
5802 }
5803 else {
5804 do_simplify = table_simplify[op];
5805 }
5806 if (!do_simplify) {
5807 internal_error(state, ins, "cannot simplify op: %d %s\n",
5808 op, tops(op));
5809 return;
5810 }
5811 do_simplify(state, ins);
5812 } while(ins->op != op);
5813}
5814
5815static void simplify_all(struct compile_state *state)
5816{
5817 struct triple *ins, *first;
5818 first = state->main_function->left;
5819 ins = first;
5820 do {
5821 simplify(state, ins);
5822 ins = ins->next;
5823 } while(ins != first);
5824}
5825
5826/*
5827 * Builtins....
5828 * ============================
5829 */
5830
5831static void register_builtin_unary(struct compile_state *state,
5832 const char *name, int op, struct type *result, struct type *a1type)
5833{
5834 struct type *ftype, *rtype, *atype;
5835 struct triple *def, *arg1, *work, *last, *first;
5836 struct hash_entry *ident;
5837 int name_len;
5838
5839 /* Dummy file state to get debug handling right */
5840 struct file_state file;
5841 memset(&file, 0, sizeof(file));
5842 file.basename = name;
5843 file.line = 1;
5844 file.prev = state->file;
5845 state->file = &file;
5846
5847 atype = a1type;
5848 rtype = result;
5849 ftype = new_type(TYPE_FUNCTION, rtype, atype);
5850 /* Generate the needed triples */
5851 def = triple(state, OP_LIST, ftype, 0, 0);
5852 first = label(state);
5853 def->left = first;
5854 /* Now string them together into a list */
5855 arg1 = 0;
5856 if ((atype->type & TYPE_MASK) != TYPE_VOID) {
5857 arg1 = flatten(state, first, variable(state, a1type));
5858 }
5859 def->right = 0;
5860 if ((rtype->type & TYPE_MASK) != TYPE_VOID) {
5861 def->right = flatten(state, first, variable(state, rtype));
5862 }
5863 work = triple(state, op, rtype, read_expr(state, arg1), 0);
5864 if (def->right) {
5865 work = write_expr(state, def->right, work);
5866 }
5867 work = flatten(state, first, work);
5868 last = flatten(state, first, label(state));
5869 name_len = strlen(name);
5870 ident = lookup(state, name, name_len);
5871 symbol(state, ident, &ident->sym_ident, def, ftype);
5872
5873 state->file = file.prev;
5874
5875#if 0
5876 fprintf(stdout, "\n");
5877 loc(stdout, state, 0);
5878 fprintf(stdout, "\n__________ builtin_unary _________\n");
5879 print_triple(state, def);
5880 fprintf(stdout, "__________ builtin_unary _________ done\n\n");
5881#endif
5882}
5883
5884static void register_builtin_binary(struct compile_state *state,
5885 const char *name, int op,
5886 struct type *result, struct type *a1type, struct type *a2type)
5887{
5888 struct type *ftype, *rtype, *atype;
5889 struct triple *def, *arg1, *arg2, *work, *last, *first;
5890 struct hash_entry *ident;
5891 int name_len;
5892 /* Dummy file state to get debug handling right */
5893 struct file_state file;
5894 memset(&file, 0, sizeof(file));
5895 file.basename = name;
5896 file.line = 1;
5897 file.prev = state->file;
5898 state->file = &file;
5899
5900 atype = new_type(TYPE_PRODUCT, a1type, a2type);
5901 rtype = result;
5902 ftype = new_type(TYPE_FUNCTION, rtype, atype);
5903 /* Generate the needed triples */
5904 def = triple(state, OP_LIST, ftype, 0, 0);
5905 first = label(state);
5906 def->left = first;
5907 /* String them togher */
5908 arg1 = flatten(state, first, variable(state, a1type));
5909 arg2 = flatten(state, first, variable(state, a2type));
5910 def->right = 0;
5911 if ((rtype->type & TYPE_MASK) != TYPE_VOID) {
5912 def->right = flatten(state, first, variable(state, rtype));
5913 }
5914 work = triple(state, op, rtype,
5915 read_expr(state, arg1), read_expr(state, arg2));
5916 if (def->right) {
5917 work = write_expr(state, def->right, work);
5918 }
5919 work = flatten(state, first, work);
5920 last = flatten(state, first, label(state));
5921 name_len = strlen(name);
5922 ident = lookup(state, name, name_len);
5923 symbol(state, ident, &ident->sym_ident, def, ftype);
5924
5925 state->file = file.prev;
5926
5927#if 0
5928 fprintf(stdout, "\n");
5929 loc(stdout, state, 0);
5930 fprintf(stdout, "\n__________ builtin_binary _________\n");
5931 print_triple(state, def);
5932 fprintf(stdout, "__________ builtin_binary _________ done\n\n");
5933#endif
5934}
5935
5936static void register_builtins(struct compile_state *state)
5937{
5938 register_builtin_unary(state, "__builtin_inb", OP_INB,
5939 &uchar_type, &ushort_type);
5940 register_builtin_unary(state, "__builtin_inw", OP_INW,
5941 &ushort_type, &ushort_type);
5942 register_builtin_unary( state, "__builtin_inl", OP_INL,
5943 &uint_type, &ushort_type);
5944
5945 register_builtin_binary(state, "__builtin_outb", OP_OUTB,
5946 &void_type, &uchar_type, &ushort_type);
5947 register_builtin_binary(state, "__builtin_outw", OP_OUTW,
5948 &void_type, &ushort_type, &ushort_type);
5949 register_builtin_binary(state, "__builtin_outl", OP_OUTL,
5950 &void_type, &uint_type, &ushort_type);
5951
5952 register_builtin_unary(state, "__builtin_bsf", OP_BSF,
5953 &int_type, &int_type);
5954 register_builtin_unary(state, "__builtin_bsr", OP_BSR,
5955 &int_type, &int_type);
5956
5957 register_builtin_unary(state, "__builtin_hlt", OP_HLT,
5958 &void_type, &void_type);
5959}
5960
5961static struct type *declarator(
5962 struct compile_state *state, struct type *type,
5963 struct hash_entry **ident, int need_ident);
5964static void decl(struct compile_state *state, struct triple *first);
5965static struct type *specifier_qualifier_list(struct compile_state *state);
5966static int isdecl_specifier(int tok);
5967static struct type *decl_specifiers(struct compile_state *state);
5968static int istype(int tok);
5969static struct triple *expr(struct compile_state *state);
5970static struct triple *assignment_expr(struct compile_state *state);
5971static struct type *type_name(struct compile_state *state);
5972static void statement(struct compile_state *state, struct triple *fist);
5973
5974static struct triple *call_expr(
5975 struct compile_state *state, struct triple *func)
5976{
5977 struct triple *def, **next;
5978 struct type *type;
5979
5980 if ((func->type->type & TYPE_MASK) != TYPE_FUNCTION) {
5981 error(state, 0, "Called object is not a function");
5982 }
5983 if (func->op != OP_LIST) {
5984 internal_error(state, 0, "improper function");
5985 }
5986 eat(state, TOK_LPAREN);
5987 /* Find the return type without any specifiers */
5988 type = clone_type(0, func->type->left);
5989 def = triple(state, OP_CALL, type, func, 0);
5990 next = &def->right;
5991 if (peek(state) != TOK_RPAREN) {
5992 struct triple *val;
5993 struct type *param, *arg_type;
5994 val = read_expr(state, assignment_expr(state));
5995 param = func->type->right;
5996 arg_type = param;
5997 if ((param->type & TYPE_MASK) == TYPE_PRODUCT) {
5998 arg_type = param->left;
5999 }
6000 else if ((param->type & TYPE_MASK) == TYPE_VOID) {
6001 error(state, 0, "Too many arguments");
6002 }
6003 write_compatible(state, arg_type, val->type);
6004 *next = val;
6005 while(peek(state) == TOK_COMMA) {
6006 eat(state, TOK_COMMA);
6007 val = read_expr(state, assignment_expr(state));
6008 if (arg_type == param) {
6009 error(state, 0, "Too many arguments");
6010 }
6011 arg_type = param = param->right;
6012 if ((param->type & TYPE_MASK) == TYPE_PRODUCT) {
6013 arg_type = param->left;
6014 }
6015 write_compatible(state, arg_type, val->type);
6016 *next = triple(state, OP_PRODUCT, &void_type, *next, val);
6017 next = &((*next)->right);
6018 }
6019 }
6020 eat(state, TOK_RPAREN);
6021 return def;
6022}
6023
6024
6025static struct triple *character_constant(struct compile_state *state)
6026{
6027 struct triple *def;
6028 struct token *tk;
6029 const signed char *str, *end;
6030 int c;
6031 int str_len;
6032 eat(state, TOK_LIT_CHAR);
6033 tk = &state->token[0];
6034 str = tk->val.str + 1;
6035 str_len = tk->str_len - 2;
6036 if (str_len <= 0) {
6037 error(state, 0, "empty character constant");
6038 }
6039 end = str + str_len;
6040 c = char_value(state, &str, end);
6041 if (str != end) {
6042 error(state, 0, "multibyte character constant not supported");
6043 }
6044 def = int_const(state, &char_type, (ulong_t)((long_t)c));
6045 return def;
6046}
6047
6048static struct triple *string_constant(struct compile_state *state)
6049{
6050 struct triple *def;
6051 struct token *tk;
6052 struct type *type;
6053 const signed char *str, *end;
6054 signed char *buf, *ptr;
6055 int str_len;
6056
6057 buf = 0;
6058 type = new_type(TYPE_ARRAY, &char_type, 0);
6059 type->elements = 0;
6060 /* The while loop handles string concatenation */
6061 do {
6062 eat(state, TOK_LIT_STRING);
6063 tk = &state->token[0];
6064 str = tk->val.str + 1;
6065 str_len = tk->str_len - 2;
Eric Biedermanab2ea6b2003-04-26 03:20:53 +00006066 if (str_len < 0) {
6067 error(state, 0, "negative string constant length");
Eric Biedermanb138ac82003-04-22 18:44:01 +00006068 }
6069 end = str + str_len;
6070 ptr = buf;
6071 buf = xmalloc(type->elements + str_len + 1, "string_constant");
6072 memcpy(buf, ptr, type->elements);
6073 ptr = buf + type->elements;
6074 do {
6075 *ptr++ = char_value(state, &str, end);
6076 } while(str < end);
6077 type->elements = ptr - buf;
6078 } while(peek(state) == TOK_LIT_STRING);
6079 *ptr = '\0';
6080 type->elements += 1;
6081 def = triple(state, OP_BLOBCONST, type, 0, 0);
6082 def->u.blob = buf;
6083 return def;
6084}
6085
6086
6087static struct triple *integer_constant(struct compile_state *state)
6088{
6089 struct triple *def;
6090 unsigned long val;
6091 struct token *tk;
6092 char *end;
6093 int u, l, decimal;
6094 struct type *type;
6095
6096 eat(state, TOK_LIT_INT);
6097 tk = &state->token[0];
6098 errno = 0;
6099 decimal = (tk->val.str[0] != '0');
6100 val = strtoul(tk->val.str, &end, 0);
6101 if ((val == ULONG_MAX) && (errno == ERANGE)) {
6102 error(state, 0, "Integer constant to large");
6103 }
6104 u = l = 0;
6105 if ((*end == 'u') || (*end == 'U')) {
6106 u = 1;
6107 end++;
6108 }
6109 if ((*end == 'l') || (*end == 'L')) {
6110 l = 1;
6111 end++;
6112 }
6113 if ((*end == 'u') || (*end == 'U')) {
6114 u = 1;
6115 end++;
6116 }
6117 if (*end) {
6118 error(state, 0, "Junk at end of integer constant");
6119 }
6120 if (u && l) {
6121 type = &ulong_type;
6122 }
6123 else if (l) {
6124 type = &long_type;
6125 if (!decimal && (val > LONG_MAX)) {
6126 type = &ulong_type;
6127 }
6128 }
6129 else if (u) {
6130 type = &uint_type;
6131 if (val > UINT_MAX) {
6132 type = &ulong_type;
6133 }
6134 }
6135 else {
6136 type = &int_type;
6137 if (!decimal && (val > INT_MAX) && (val <= UINT_MAX)) {
6138 type = &uint_type;
6139 }
6140 else if (!decimal && (val > LONG_MAX)) {
6141 type = &ulong_type;
6142 }
6143 else if (val > INT_MAX) {
6144 type = &long_type;
6145 }
6146 }
6147 def = int_const(state, type, val);
6148 return def;
6149}
6150
6151static struct triple *primary_expr(struct compile_state *state)
6152{
6153 struct triple *def;
6154 int tok;
6155 tok = peek(state);
6156 switch(tok) {
6157 case TOK_IDENT:
6158 {
6159 struct hash_entry *ident;
6160 /* Here ident is either:
6161 * a varable name
6162 * a function name
6163 * an enumeration constant.
6164 */
6165 eat(state, TOK_IDENT);
6166 ident = state->token[0].ident;
6167 if (!ident->sym_ident) {
6168 error(state, 0, "%s undeclared", ident->name);
6169 }
6170 def = ident->sym_ident->def;
6171 break;
6172 }
6173 case TOK_ENUM_CONST:
6174 /* Here ident is an enumeration constant */
6175 eat(state, TOK_ENUM_CONST);
6176 def = 0;
6177 FINISHME();
6178 break;
6179 case TOK_LPAREN:
6180 eat(state, TOK_LPAREN);
6181 def = expr(state);
6182 eat(state, TOK_RPAREN);
6183 break;
6184 case TOK_LIT_INT:
6185 def = integer_constant(state);
6186 break;
6187 case TOK_LIT_FLOAT:
6188 eat(state, TOK_LIT_FLOAT);
6189 error(state, 0, "Floating point constants not supported");
6190 def = 0;
6191 FINISHME();
6192 break;
6193 case TOK_LIT_CHAR:
6194 def = character_constant(state);
6195 break;
6196 case TOK_LIT_STRING:
6197 def = string_constant(state);
6198 break;
6199 default:
6200 def = 0;
6201 error(state, 0, "Unexpected token: %s\n", tokens[tok]);
6202 }
6203 return def;
6204}
6205
6206static struct triple *postfix_expr(struct compile_state *state)
6207{
6208 struct triple *def;
6209 int postfix;
6210 def = primary_expr(state);
6211 do {
6212 struct triple *left;
6213 int tok;
6214 postfix = 1;
6215 left = def;
6216 switch((tok = peek(state))) {
6217 case TOK_LBRACKET:
6218 eat(state, TOK_LBRACKET);
6219 def = mk_subscript_expr(state, left, expr(state));
6220 eat(state, TOK_RBRACKET);
6221 break;
6222 case TOK_LPAREN:
6223 def = call_expr(state, def);
6224 break;
6225 case TOK_DOT:
6226 eat(state, TOK_DOT);
6227 eat(state, TOK_IDENT);
6228 FINISHME();
6229 break;
6230 case TOK_ARROW:
6231 eat(state, TOK_ARROW);
6232 eat(state, TOK_IDENT);
6233 FINISHME();
6234 break;
6235 case TOK_PLUSPLUS:
6236 eat(state, TOK_PLUSPLUS);
6237 def = mk_post_inc_expr(state, left);
6238 break;
6239 case TOK_MINUSMINUS:
6240 eat(state, TOK_MINUSMINUS);
6241 def = mk_post_dec_expr(state, left);
6242 break;
6243 default:
6244 postfix = 0;
6245 break;
6246 }
6247 } while(postfix);
6248 return def;
6249}
6250
6251static struct triple *cast_expr(struct compile_state *state);
6252
6253static struct triple *unary_expr(struct compile_state *state)
6254{
6255 struct triple *def, *right;
6256 int tok;
6257 switch((tok = peek(state))) {
6258 case TOK_PLUSPLUS:
6259 eat(state, TOK_PLUSPLUS);
6260 def = mk_pre_inc_expr(state, unary_expr(state));
6261 break;
6262 case TOK_MINUSMINUS:
6263 eat(state, TOK_MINUSMINUS);
6264 def = mk_pre_dec_expr(state, unary_expr(state));
6265 break;
6266 case TOK_AND:
6267 eat(state, TOK_AND);
6268 def = mk_addr_expr(state, cast_expr(state), 0);
6269 break;
6270 case TOK_STAR:
6271 eat(state, TOK_STAR);
6272 def = mk_deref_expr(state, read_expr(state, cast_expr(state)));
6273 break;
6274 case TOK_PLUS:
6275 eat(state, TOK_PLUS);
6276 right = read_expr(state, cast_expr(state));
6277 arithmetic(state, right);
6278 def = integral_promotion(state, right);
6279 break;
6280 case TOK_MINUS:
6281 eat(state, TOK_MINUS);
6282 right = read_expr(state, cast_expr(state));
6283 arithmetic(state, right);
6284 def = integral_promotion(state, right);
6285 def = triple(state, OP_NEG, def->type, def, 0);
6286 break;
6287 case TOK_TILDE:
6288 eat(state, TOK_TILDE);
6289 right = read_expr(state, cast_expr(state));
6290 integral(state, right);
6291 def = integral_promotion(state, right);
6292 def = triple(state, OP_INVERT, def->type, def, 0);
6293 break;
6294 case TOK_BANG:
6295 eat(state, TOK_BANG);
6296 right = read_expr(state, cast_expr(state));
6297 bool(state, right);
6298 def = lfalse_expr(state, right);
6299 break;
6300 case TOK_SIZEOF:
6301 {
6302 struct type *type;
6303 int tok1, tok2;
6304 eat(state, TOK_SIZEOF);
6305 tok1 = peek(state);
6306 tok2 = peek2(state);
6307 if ((tok1 == TOK_LPAREN) && istype(tok2)) {
6308 eat(state, TOK_LPAREN);
6309 type = type_name(state);
6310 eat(state, TOK_RPAREN);
6311 }
6312 else {
6313 struct triple *expr;
6314 expr = unary_expr(state);
6315 type = expr->type;
6316 release_expr(state, expr);
6317 }
6318 def = int_const(state, &ulong_type, size_of(state, type));
6319 break;
6320 }
6321 case TOK_ALIGNOF:
6322 {
6323 struct type *type;
6324 int tok1, tok2;
6325 eat(state, TOK_ALIGNOF);
6326 tok1 = peek(state);
6327 tok2 = peek2(state);
6328 if ((tok1 == TOK_LPAREN) && istype(tok2)) {
6329 eat(state, TOK_LPAREN);
6330 type = type_name(state);
6331 eat(state, TOK_RPAREN);
6332 }
6333 else {
6334 struct triple *expr;
6335 expr = unary_expr(state);
6336 type = expr->type;
6337 release_expr(state, expr);
6338 }
6339 def = int_const(state, &ulong_type, align_of(state, type));
6340 break;
6341 }
6342 default:
6343 def = postfix_expr(state);
6344 break;
6345 }
6346 return def;
6347}
6348
6349static struct triple *cast_expr(struct compile_state *state)
6350{
6351 struct triple *def;
6352 int tok1, tok2;
6353 tok1 = peek(state);
6354 tok2 = peek2(state);
6355 if ((tok1 == TOK_LPAREN) && istype(tok2)) {
6356 struct type *type;
6357 eat(state, TOK_LPAREN);
6358 type = type_name(state);
6359 eat(state, TOK_RPAREN);
6360 def = read_expr(state, cast_expr(state));
6361 def = triple(state, OP_COPY, type, def, 0);
6362#warning "FIXME do I need an OP_CAST expr to be semantically correct here?"
6363 }
6364 else {
6365 def = unary_expr(state);
6366 }
6367 return def;
6368}
6369
6370static struct triple *mult_expr(struct compile_state *state)
6371{
6372 struct triple *def;
6373 int done;
6374 def = cast_expr(state);
6375 do {
6376 struct triple *left, *right;
6377 struct type *result_type;
6378 int tok, op, sign;
6379 done = 0;
6380 switch(tok = (peek(state))) {
6381 case TOK_STAR:
6382 case TOK_DIV:
6383 case TOK_MOD:
6384 left = read_expr(state, def);
6385 arithmetic(state, left);
6386
6387 eat(state, tok);
6388
6389 right = read_expr(state, cast_expr(state));
6390 arithmetic(state, right);
6391
6392 result_type = arithmetic_result(state, left, right);
6393 sign = is_signed(result_type);
6394 op = -1;
6395 switch(tok) {
6396 case TOK_STAR: op = sign? OP_SMUL : OP_UMUL; break;
6397 case TOK_DIV: op = sign? OP_SDIV : OP_UDIV; break;
6398 case TOK_MOD: op = sign? OP_SMOD : OP_UMOD; break;
6399 }
6400 def = triple(state, op, result_type, left, right);
6401 break;
6402 default:
6403 done = 1;
6404 break;
6405 }
6406 } while(!done);
6407 return def;
6408}
6409
6410static struct triple *add_expr(struct compile_state *state)
6411{
6412 struct triple *def;
6413 int done;
6414 def = mult_expr(state);
6415 do {
6416 done = 0;
6417 switch( peek(state)) {
6418 case TOK_PLUS:
6419 eat(state, TOK_PLUS);
6420 def = mk_add_expr(state, def, mult_expr(state));
6421 break;
6422 case TOK_MINUS:
6423 eat(state, TOK_MINUS);
6424 def = mk_sub_expr(state, def, mult_expr(state));
6425 break;
6426 default:
6427 done = 1;
6428 break;
6429 }
6430 } while(!done);
6431 return def;
6432}
6433
6434static struct triple *shift_expr(struct compile_state *state)
6435{
6436 struct triple *def;
6437 int done;
6438 def = add_expr(state);
6439 do {
6440 struct triple *left, *right;
6441 int tok, op;
6442 done = 0;
6443 switch((tok = peek(state))) {
6444 case TOK_SL:
6445 case TOK_SR:
6446 left = read_expr(state, def);
6447 integral(state, left);
6448 left = integral_promotion(state, left);
6449
6450 eat(state, tok);
6451
6452 right = read_expr(state, add_expr(state));
6453 integral(state, right);
6454 right = integral_promotion(state, right);
6455
6456 op = (tok == TOK_SL)? OP_SL :
6457 is_signed(left->type)? OP_SSR: OP_USR;
6458
6459 def = triple(state, op, left->type, left, right);
6460 break;
6461 default:
6462 done = 1;
6463 break;
6464 }
6465 } while(!done);
6466 return def;
6467}
6468
6469static struct triple *relational_expr(struct compile_state *state)
6470{
6471#warning "Extend relational exprs to work on more than arithmetic types"
6472 struct triple *def;
6473 int done;
6474 def = shift_expr(state);
6475 do {
6476 struct triple *left, *right;
6477 struct type *arg_type;
6478 int tok, op, sign;
6479 done = 0;
6480 switch((tok = peek(state))) {
6481 case TOK_LESS:
6482 case TOK_MORE:
6483 case TOK_LESSEQ:
6484 case TOK_MOREEQ:
6485 left = read_expr(state, def);
6486 arithmetic(state, left);
6487
6488 eat(state, tok);
6489
6490 right = read_expr(state, shift_expr(state));
6491 arithmetic(state, right);
6492
6493 arg_type = arithmetic_result(state, left, right);
6494 sign = is_signed(arg_type);
6495 op = -1;
6496 switch(tok) {
6497 case TOK_LESS: op = sign? OP_SLESS : OP_ULESS; break;
6498 case TOK_MORE: op = sign? OP_SMORE : OP_UMORE; break;
6499 case TOK_LESSEQ: op = sign? OP_SLESSEQ : OP_ULESSEQ; break;
6500 case TOK_MOREEQ: op = sign? OP_SMOREEQ : OP_UMOREEQ; break;
6501 }
6502 def = triple(state, op, &int_type, left, right);
6503 break;
6504 default:
6505 done = 1;
6506 break;
6507 }
6508 } while(!done);
6509 return def;
6510}
6511
6512static struct triple *equality_expr(struct compile_state *state)
6513{
6514#warning "Extend equality exprs to work on more than arithmetic types"
6515 struct triple *def;
6516 int done;
6517 def = relational_expr(state);
6518 do {
6519 struct triple *left, *right;
6520 int tok, op;
6521 done = 0;
6522 switch((tok = peek(state))) {
6523 case TOK_EQEQ:
6524 case TOK_NOTEQ:
6525 left = read_expr(state, def);
6526 arithmetic(state, left);
6527 eat(state, tok);
6528 right = read_expr(state, relational_expr(state));
6529 arithmetic(state, right);
6530 op = (tok == TOK_EQEQ) ? OP_EQ: OP_NOTEQ;
6531 def = triple(state, op, &int_type, left, right);
6532 break;
6533 default:
6534 done = 1;
6535 break;
6536 }
6537 } while(!done);
6538 return def;
6539}
6540
6541static struct triple *and_expr(struct compile_state *state)
6542{
6543 struct triple *def;
6544 def = equality_expr(state);
6545 while(peek(state) == TOK_AND) {
6546 struct triple *left, *right;
6547 struct type *result_type;
6548 left = read_expr(state, def);
6549 integral(state, left);
6550 eat(state, TOK_AND);
6551 right = read_expr(state, equality_expr(state));
6552 integral(state, right);
6553 result_type = arithmetic_result(state, left, right);
6554 def = triple(state, OP_AND, result_type, left, right);
6555 }
6556 return def;
6557}
6558
6559static struct triple *xor_expr(struct compile_state *state)
6560{
6561 struct triple *def;
6562 def = and_expr(state);
6563 while(peek(state) == TOK_XOR) {
6564 struct triple *left, *right;
6565 struct type *result_type;
6566 left = read_expr(state, def);
6567 integral(state, left);
6568 eat(state, TOK_XOR);
6569 right = read_expr(state, and_expr(state));
6570 integral(state, right);
6571 result_type = arithmetic_result(state, left, right);
6572 def = triple(state, OP_XOR, result_type, left, right);
6573 }
6574 return def;
6575}
6576
6577static struct triple *or_expr(struct compile_state *state)
6578{
6579 struct triple *def;
6580 def = xor_expr(state);
6581 while(peek(state) == TOK_OR) {
6582 struct triple *left, *right;
6583 struct type *result_type;
6584 left = read_expr(state, def);
6585 integral(state, left);
6586 eat(state, TOK_OR);
6587 right = read_expr(state, xor_expr(state));
6588 integral(state, right);
6589 result_type = arithmetic_result(state, left, right);
6590 def = triple(state, OP_OR, result_type, left, right);
6591 }
6592 return def;
6593}
6594
6595static struct triple *land_expr(struct compile_state *state)
6596{
6597 struct triple *def;
6598 def = or_expr(state);
6599 while(peek(state) == TOK_LOGAND) {
6600 struct triple *left, *right;
6601 left = read_expr(state, def);
6602 bool(state, left);
6603 eat(state, TOK_LOGAND);
6604 right = read_expr(state, or_expr(state));
6605 bool(state, right);
6606
6607 def = triple(state, OP_LAND, &int_type,
6608 ltrue_expr(state, left),
6609 ltrue_expr(state, right));
6610 }
6611 return def;
6612}
6613
6614static struct triple *lor_expr(struct compile_state *state)
6615{
6616 struct triple *def;
6617 def = land_expr(state);
6618 while(peek(state) == TOK_LOGOR) {
6619 struct triple *left, *right;
6620 left = read_expr(state, def);
6621 bool(state, left);
6622 eat(state, TOK_LOGOR);
6623 right = read_expr(state, land_expr(state));
6624 bool(state, right);
6625
6626 def = triple(state, OP_LOR, &int_type,
6627 ltrue_expr(state, left),
6628 ltrue_expr(state, right));
6629 }
6630 return def;
6631}
6632
6633static struct triple *conditional_expr(struct compile_state *state)
6634{
6635 struct triple *def;
6636 def = lor_expr(state);
6637 if (peek(state) == TOK_QUEST) {
6638 struct triple *test, *left, *right;
6639 bool(state, def);
6640 test = ltrue_expr(state, read_expr(state, def));
6641 eat(state, TOK_QUEST);
6642 left = read_expr(state, expr(state));
6643 eat(state, TOK_COLON);
6644 right = read_expr(state, conditional_expr(state));
6645
6646 def = cond_expr(state, test, left, right);
6647 }
6648 return def;
6649}
6650
6651static struct triple *eval_const_expr(
6652 struct compile_state *state, struct triple *expr)
6653{
6654 struct triple *def;
6655 struct triple *head, *ptr;
6656 head = label(state); /* dummy initial triple */
6657 flatten(state, head, expr);
6658 for(ptr = head->next; ptr != head; ptr = ptr->next) {
6659 simplify(state, ptr);
6660 }
6661 /* Remove the constant value the tail of the list */
6662 def = head->prev;
6663 def->prev->next = def->next;
6664 def->next->prev = def->prev;
6665 def->next = def->prev = def;
6666 if (!is_const(def)) {
6667 internal_error(state, 0, "Not a constant expression");
6668 }
6669 /* Free the intermediate expressions */
6670 while(head->next != head) {
6671 release_triple(state, head->next);
6672 }
6673 free_triple(state, head);
6674 return def;
6675}
6676
6677static struct triple *constant_expr(struct compile_state *state)
6678{
6679 return eval_const_expr(state, conditional_expr(state));
6680}
6681
6682static struct triple *assignment_expr(struct compile_state *state)
6683{
6684 struct triple *def, *left, *right;
6685 int tok, op, sign;
6686 /* The C grammer in K&R shows assignment expressions
6687 * only taking unary expressions as input on their
6688 * left hand side. But specifies the precedence of
6689 * assignemnt as the lowest operator except for comma.
6690 *
6691 * Allowing conditional expressions on the left hand side
6692 * of an assignement results in a grammar that accepts
6693 * a larger set of statements than standard C. As long
6694 * as the subset of the grammar that is standard C behaves
6695 * correctly this should cause no problems.
6696 *
6697 * For the extra token strings accepted by the grammar
6698 * none of them should produce a valid lvalue, so they
6699 * should not produce functioning programs.
6700 *
6701 * GCC has this bug as well, so surprises should be minimal.
6702 */
6703 def = conditional_expr(state);
6704 left = def;
6705 switch((tok = peek(state))) {
6706 case TOK_EQ:
6707 lvalue(state, left);
6708 eat(state, TOK_EQ);
6709 def = write_expr(state, left,
6710 read_expr(state, assignment_expr(state)));
6711 break;
6712 case TOK_TIMESEQ:
6713 case TOK_DIVEQ:
6714 case TOK_MODEQ:
6715 case TOK_PLUSEQ:
6716 case TOK_MINUSEQ:
6717 lvalue(state, left);
6718 arithmetic(state, left);
6719 eat(state, tok);
6720 right = read_expr(state, assignment_expr(state));
6721 arithmetic(state, right);
6722
6723 sign = is_signed(left->type);
6724 op = -1;
6725 switch(tok) {
6726 case TOK_TIMESEQ: op = sign? OP_SMUL : OP_UMUL; break;
6727 case TOK_DIVEQ: op = sign? OP_SDIV : OP_UDIV; break;
6728 case TOK_MODEQ: op = sign? OP_SMOD : OP_UMOD; break;
6729 case TOK_PLUSEQ: op = OP_ADD; break;
6730 case TOK_MINUSEQ: op = OP_SUB; break;
6731 }
6732 def = write_expr(state, left,
6733 triple(state, op, left->type,
6734 read_expr(state, left), right));
6735 break;
6736 case TOK_SLEQ:
6737 case TOK_SREQ:
6738 case TOK_ANDEQ:
6739 case TOK_XOREQ:
6740 case TOK_OREQ:
6741 lvalue(state, left);
6742 integral(state, left);
6743 eat(state, tok);
6744 right = read_expr(state, assignment_expr(state));
6745 integral(state, right);
6746 right = integral_promotion(state, right);
6747 sign = is_signed(left->type);
6748 op = -1;
6749 switch(tok) {
6750 case TOK_SLEQ: op = OP_SL; break;
6751 case TOK_SREQ: op = sign? OP_SSR: OP_USR; break;
6752 case TOK_ANDEQ: op = OP_AND; break;
6753 case TOK_XOREQ: op = OP_XOR; break;
6754 case TOK_OREQ: op = OP_OR; break;
6755 }
6756 def = write_expr(state, left,
6757 triple(state, op, left->type,
6758 read_expr(state, left), right));
6759 break;
6760 }
6761 return def;
6762}
6763
6764static struct triple *expr(struct compile_state *state)
6765{
6766 struct triple *def;
6767 def = assignment_expr(state);
6768 while(peek(state) == TOK_COMMA) {
6769 struct triple *left, *right;
6770 left = def;
6771 eat(state, TOK_COMMA);
6772 right = assignment_expr(state);
6773 def = triple(state, OP_COMMA, right->type, left, right);
6774 }
6775 return def;
6776}
6777
6778static void expr_statement(struct compile_state *state, struct triple *first)
6779{
6780 if (peek(state) != TOK_SEMI) {
6781 flatten(state, first, expr(state));
6782 }
6783 eat(state, TOK_SEMI);
6784}
6785
6786static void if_statement(struct compile_state *state, struct triple *first)
6787{
6788 struct triple *test, *jmp1, *jmp2, *middle, *end;
6789
6790 jmp1 = jmp2 = middle = 0;
6791 eat(state, TOK_IF);
6792 eat(state, TOK_LPAREN);
6793 test = expr(state);
6794 bool(state, test);
6795 /* Cleanup and invert the test */
6796 test = lfalse_expr(state, read_expr(state, test));
6797 eat(state, TOK_RPAREN);
6798 /* Generate the needed pieces */
6799 middle = label(state);
6800 jmp1 = triple(state, OP_BRANCH, &void_type, middle, test);
6801 /* Thread the pieces together */
6802 flatten(state, first, test);
6803 flatten(state, first, jmp1);
6804 flatten(state, first, label(state));
6805 statement(state, first);
6806 if (peek(state) == TOK_ELSE) {
6807 eat(state, TOK_ELSE);
6808 /* Generate the rest of the pieces */
6809 end = label(state);
6810 jmp2 = triple(state, OP_BRANCH, &void_type, end, 0);
6811 /* Thread them together */
6812 flatten(state, first, jmp2);
6813 flatten(state, first, middle);
6814 statement(state, first);
6815 flatten(state, first, end);
6816 }
6817 else {
6818 flatten(state, first, middle);
6819 }
6820}
6821
6822static void for_statement(struct compile_state *state, struct triple *first)
6823{
6824 struct triple *head, *test, *tail, *jmp1, *jmp2, *end;
6825 struct triple *label1, *label2, *label3;
6826 struct hash_entry *ident;
6827
6828 eat(state, TOK_FOR);
6829 eat(state, TOK_LPAREN);
6830 head = test = tail = jmp1 = jmp2 = 0;
6831 if (peek(state) != TOK_SEMI) {
6832 head = expr(state);
6833 }
6834 eat(state, TOK_SEMI);
6835 if (peek(state) != TOK_SEMI) {
6836 test = expr(state);
6837 bool(state, test);
6838 test = ltrue_expr(state, read_expr(state, test));
6839 }
6840 eat(state, TOK_SEMI);
6841 if (peek(state) != TOK_RPAREN) {
6842 tail = expr(state);
6843 }
6844 eat(state, TOK_RPAREN);
6845 /* Generate the needed pieces */
6846 label1 = label(state);
6847 label2 = label(state);
6848 label3 = label(state);
6849 if (test) {
6850 jmp1 = triple(state, OP_BRANCH, &void_type, label3, 0);
6851 jmp2 = triple(state, OP_BRANCH, &void_type, label1, test);
6852 }
6853 else {
6854 jmp2 = triple(state, OP_BRANCH, &void_type, label1, 0);
6855 }
6856 end = label(state);
6857 /* Remember where break and continue go */
6858 start_scope(state);
6859 ident = state->i_break;
6860 symbol(state, ident, &ident->sym_ident, end, end->type);
6861 ident = state->i_continue;
6862 symbol(state, ident, &ident->sym_ident, label2, label2->type);
6863 /* Now include the body */
6864 flatten(state, first, head);
6865 flatten(state, first, jmp1);
6866 flatten(state, first, label1);
6867 statement(state, first);
6868 flatten(state, first, label2);
6869 flatten(state, first, tail);
6870 flatten(state, first, label3);
6871 flatten(state, first, test);
6872 flatten(state, first, jmp2);
6873 flatten(state, first, end);
6874 /* Cleanup the break/continue scope */
6875 end_scope(state);
6876}
6877
6878static void while_statement(struct compile_state *state, struct triple *first)
6879{
6880 struct triple *label1, *test, *label2, *jmp1, *jmp2, *end;
6881 struct hash_entry *ident;
6882 eat(state, TOK_WHILE);
6883 eat(state, TOK_LPAREN);
6884 test = expr(state);
6885 bool(state, test);
6886 test = ltrue_expr(state, read_expr(state, test));
6887 eat(state, TOK_RPAREN);
6888 /* Generate the needed pieces */
6889 label1 = label(state);
6890 label2 = label(state);
6891 jmp1 = triple(state, OP_BRANCH, &void_type, label2, 0);
6892 jmp2 = triple(state, OP_BRANCH, &void_type, label1, test);
6893 end = label(state);
6894 /* Remember where break and continue go */
6895 start_scope(state);
6896 ident = state->i_break;
6897 symbol(state, ident, &ident->sym_ident, end, end->type);
6898 ident = state->i_continue;
6899 symbol(state, ident, &ident->sym_ident, label2, label2->type);
6900 /* Thread them together */
6901 flatten(state, first, jmp1);
6902 flatten(state, first, label1);
6903 statement(state, first);
6904 flatten(state, first, label2);
6905 flatten(state, first, test);
6906 flatten(state, first, jmp2);
6907 flatten(state, first, end);
6908 /* Cleanup the break/continue scope */
6909 end_scope(state);
6910}
6911
6912static void do_statement(struct compile_state *state, struct triple *first)
6913{
6914 struct triple *label1, *label2, *test, *end;
6915 struct hash_entry *ident;
6916 eat(state, TOK_DO);
6917 /* Generate the needed pieces */
6918 label1 = label(state);
6919 label2 = label(state);
6920 end = label(state);
6921 /* Remember where break and continue go */
6922 start_scope(state);
6923 ident = state->i_break;
6924 symbol(state, ident, &ident->sym_ident, end, end->type);
6925 ident = state->i_continue;
6926 symbol(state, ident, &ident->sym_ident, label2, label2->type);
6927 /* Now include the body */
6928 flatten(state, first, label1);
6929 statement(state, first);
6930 /* Cleanup the break/continue scope */
6931 end_scope(state);
6932 /* Eat the rest of the loop */
6933 eat(state, TOK_WHILE);
6934 eat(state, TOK_LPAREN);
6935 test = read_expr(state, expr(state));
6936 bool(state, test);
6937 eat(state, TOK_RPAREN);
6938 eat(state, TOK_SEMI);
6939 /* Thread the pieces together */
6940 test = ltrue_expr(state, test);
6941 flatten(state, first, label2);
6942 flatten(state, first, test);
6943 flatten(state, first,
6944 triple(state, OP_BRANCH, &void_type, label1, test));
6945 flatten(state, first, end);
6946}
6947
6948
6949static void return_statement(struct compile_state *state, struct triple *first)
6950{
6951 struct triple *jmp, *mv, *dest, *var, *val;
6952 int last;
6953 eat(state, TOK_RETURN);
6954
6955#warning "FIXME implement a more general excess branch elimination"
6956 val = 0;
6957 /* If we have a return value do some more work */
6958 if (peek(state) != TOK_SEMI) {
6959 val = read_expr(state, expr(state));
6960 }
6961 eat(state, TOK_SEMI);
6962
6963 /* See if this last statement in a function */
6964 last = ((peek(state) == TOK_RBRACE) &&
6965 (state->scope_depth == GLOBAL_SCOPE_DEPTH +2));
6966
6967 /* Find the return variable */
6968 var = state->main_function->right;
6969 /* Find the return destination */
6970 dest = state->main_function->left->prev;
6971 mv = jmp = 0;
6972 /* If needed generate a jump instruction */
6973 if (!last) {
6974 jmp = triple(state, OP_BRANCH, &void_type, dest, 0);
6975 }
6976 /* If needed generate an assignment instruction */
6977 if (val) {
6978 mv = write_expr(state, var, val);
6979 }
6980 /* Now put the code together */
6981 if (mv) {
6982 flatten(state, first, mv);
6983 flatten(state, first, jmp);
6984 }
6985 else if (jmp) {
6986 flatten(state, first, jmp);
6987 }
6988}
6989
6990static void break_statement(struct compile_state *state, struct triple *first)
6991{
6992 struct triple *dest;
6993 eat(state, TOK_BREAK);
6994 eat(state, TOK_SEMI);
6995 if (!state->i_break->sym_ident) {
6996 error(state, 0, "break statement not within loop or switch");
6997 }
6998 dest = state->i_break->sym_ident->def;
6999 flatten(state, first, triple(state, OP_BRANCH, &void_type, dest, 0));
7000}
7001
7002static void continue_statement(struct compile_state *state, struct triple *first)
7003{
7004 struct triple *dest;
7005 eat(state, TOK_CONTINUE);
7006 eat(state, TOK_SEMI);
7007 if (!state->i_continue->sym_ident) {
7008 error(state, 0, "continue statement outside of a loop");
7009 }
7010 dest = state->i_continue->sym_ident->def;
7011 flatten(state, first, triple(state, OP_BRANCH, &void_type, dest, 0));
7012}
7013
7014static void goto_statement(struct compile_state *state, struct triple *first)
7015{
7016 FINISHME();
7017 eat(state, TOK_GOTO);
7018 eat(state, TOK_IDENT);
7019 eat(state, TOK_SEMI);
7020 error(state, 0, "goto is not implemeted");
7021 FINISHME();
7022}
7023
7024static void labeled_statement(struct compile_state *state, struct triple *first)
7025{
7026 FINISHME();
7027 eat(state, TOK_IDENT);
7028 eat(state, TOK_COLON);
7029 statement(state, first);
7030 error(state, 0, "labeled statements are not implemented");
7031 FINISHME();
7032}
7033
7034static void switch_statement(struct compile_state *state, struct triple *first)
7035{
7036 FINISHME();
7037 eat(state, TOK_SWITCH);
7038 eat(state, TOK_LPAREN);
7039 expr(state);
7040 eat(state, TOK_RPAREN);
7041 statement(state, first);
7042 error(state, 0, "switch statements are not implemented");
7043 FINISHME();
7044}
7045
7046static void case_statement(struct compile_state *state, struct triple *first)
7047{
7048 FINISHME();
7049 eat(state, TOK_CASE);
7050 constant_expr(state);
7051 eat(state, TOK_COLON);
7052 statement(state, first);
7053 error(state, 0, "case statements are not implemented");
7054 FINISHME();
7055}
7056
7057static void default_statement(struct compile_state *state, struct triple *first)
7058{
7059 FINISHME();
7060 eat(state, TOK_DEFAULT);
7061 eat(state, TOK_COLON);
7062 statement(state, first);
7063 error(state, 0, "default statements are not implemented");
7064 FINISHME();
7065}
7066
7067static void asm_statement(struct compile_state *state, struct triple *first)
7068{
7069 FINISHME();
7070 error(state, 0, "FIXME finish asm_statement");
7071}
7072
7073
7074static int isdecl(int tok)
7075{
7076 switch(tok) {
7077 case TOK_AUTO:
7078 case TOK_REGISTER:
7079 case TOK_STATIC:
7080 case TOK_EXTERN:
7081 case TOK_TYPEDEF:
7082 case TOK_CONST:
7083 case TOK_RESTRICT:
7084 case TOK_VOLATILE:
7085 case TOK_VOID:
7086 case TOK_CHAR:
7087 case TOK_SHORT:
7088 case TOK_INT:
7089 case TOK_LONG:
7090 case TOK_FLOAT:
7091 case TOK_DOUBLE:
7092 case TOK_SIGNED:
7093 case TOK_UNSIGNED:
7094 case TOK_STRUCT:
7095 case TOK_UNION:
7096 case TOK_ENUM:
7097 case TOK_TYPE_NAME: /* typedef name */
7098 return 1;
7099 default:
7100 return 0;
7101 }
7102}
7103
7104static void compound_statement(struct compile_state *state, struct triple *first)
7105{
7106 eat(state, TOK_LBRACE);
7107 start_scope(state);
7108
7109 /* statement-list opt */
7110 while (peek(state) != TOK_RBRACE) {
7111 statement(state, first);
7112 }
7113 end_scope(state);
7114 eat(state, TOK_RBRACE);
7115}
7116
7117static void statement(struct compile_state *state, struct triple *first)
7118{
7119 int tok;
7120 tok = peek(state);
7121 if (tok == TOK_LBRACE) {
7122 compound_statement(state, first);
7123 }
7124 else if (tok == TOK_IF) {
7125 if_statement(state, first);
7126 }
7127 else if (tok == TOK_FOR) {
7128 for_statement(state, first);
7129 }
7130 else if (tok == TOK_WHILE) {
7131 while_statement(state, first);
7132 }
7133 else if (tok == TOK_DO) {
7134 do_statement(state, first);
7135 }
7136 else if (tok == TOK_RETURN) {
7137 return_statement(state, first);
7138 }
7139 else if (tok == TOK_BREAK) {
7140 break_statement(state, first);
7141 }
7142 else if (tok == TOK_CONTINUE) {
7143 continue_statement(state, first);
7144 }
7145 else if (tok == TOK_GOTO) {
7146 goto_statement(state, first);
7147 }
7148 else if (tok == TOK_SWITCH) {
7149 switch_statement(state, first);
7150 }
7151 else if (tok == TOK_ASM) {
7152 asm_statement(state, first);
7153 }
7154 else if ((tok == TOK_IDENT) && (peek2(state) == TOK_COLON)) {
7155 labeled_statement(state, first);
7156 }
7157 else if (tok == TOK_CASE) {
7158 case_statement(state, first);
7159 }
7160 else if (tok == TOK_DEFAULT) {
7161 default_statement(state, first);
7162 }
7163 else if (isdecl(tok)) {
7164 /* This handles C99 intermixing of statements and decls */
7165 decl(state, first);
7166 }
7167 else {
7168 expr_statement(state, first);
7169 }
7170}
7171
7172static struct type *param_decl(struct compile_state *state)
7173{
7174 struct type *type;
7175 struct hash_entry *ident;
7176 /* Cheat so the declarator will know we are not global */
7177 start_scope(state);
7178 ident = 0;
7179 type = decl_specifiers(state);
7180 type = declarator(state, type, &ident, 0);
7181 type->ident = ident;
7182 end_scope(state);
7183 return type;
7184}
7185
7186static struct type *param_type_list(struct compile_state *state, struct type *type)
7187{
7188 struct type *ftype, **next;
7189 ftype = new_type(TYPE_FUNCTION, type, param_decl(state));
7190 next = &ftype->right;
7191 while(peek(state) == TOK_COMMA) {
7192 eat(state, TOK_COMMA);
7193 if (peek(state) == TOK_DOTS) {
7194 eat(state, TOK_DOTS);
7195 error(state, 0, "variadic functions not supported");
7196 }
7197 else {
7198 *next = new_type(TYPE_PRODUCT, *next, param_decl(state));
7199 next = &((*next)->right);
7200 }
7201 }
7202 return ftype;
7203}
7204
7205
7206static struct type *type_name(struct compile_state *state)
7207{
7208 struct type *type;
7209 type = specifier_qualifier_list(state);
7210 /* abstract-declarator (may consume no tokens) */
7211 type = declarator(state, type, 0, 0);
7212 return type;
7213}
7214
7215static struct type *direct_declarator(
7216 struct compile_state *state, struct type *type,
7217 struct hash_entry **ident, int need_ident)
7218{
7219 struct type *outer;
7220 int op;
7221 outer = 0;
7222 arrays_complete(state, type);
7223 switch(peek(state)) {
7224 case TOK_IDENT:
7225 eat(state, TOK_IDENT);
7226 if (!ident) {
7227 error(state, 0, "Unexpected identifier found");
7228 }
7229 /* The name of what we are declaring */
7230 *ident = state->token[0].ident;
7231 break;
7232 case TOK_LPAREN:
7233 eat(state, TOK_LPAREN);
7234 outer = declarator(state, type, ident, need_ident);
7235 eat(state, TOK_RPAREN);
7236 break;
7237 default:
7238 if (need_ident) {
7239 error(state, 0, "Identifier expected");
7240 }
7241 break;
7242 }
7243 do {
7244 op = 1;
7245 arrays_complete(state, type);
7246 switch(peek(state)) {
7247 case TOK_LPAREN:
7248 eat(state, TOK_LPAREN);
7249 type = param_type_list(state, type);
7250 eat(state, TOK_RPAREN);
7251 break;
7252 case TOK_LBRACKET:
7253 {
7254 unsigned int qualifiers;
7255 struct triple *value;
7256 value = 0;
7257 eat(state, TOK_LBRACKET);
7258 if (peek(state) != TOK_RBRACKET) {
7259 value = constant_expr(state);
7260 integral(state, value);
7261 }
7262 eat(state, TOK_RBRACKET);
7263
7264 qualifiers = type->type & (QUAL_MASK | STOR_MASK);
7265 type = new_type(TYPE_ARRAY | qualifiers, type, 0);
7266 if (value) {
7267 type->elements = value->u.cval;
7268 free_triple(state, value);
7269 } else {
7270 type->elements = ELEMENT_COUNT_UNSPECIFIED;
7271 op = 0;
7272 }
7273 }
7274 break;
7275 default:
7276 op = 0;
7277 break;
7278 }
7279 } while(op);
7280 if (outer) {
7281 struct type *inner;
7282 arrays_complete(state, type);
7283 FINISHME();
7284 for(inner = outer; inner->left; inner = inner->left)
7285 ;
7286 inner->left = type;
7287 type = outer;
7288 }
7289 return type;
7290}
7291
7292static struct type *declarator(
7293 struct compile_state *state, struct type *type,
7294 struct hash_entry **ident, int need_ident)
7295{
7296 while(peek(state) == TOK_STAR) {
7297 eat(state, TOK_STAR);
7298 type = new_type(TYPE_POINTER | (type->type & STOR_MASK), type, 0);
7299 }
7300 type = direct_declarator(state, type, ident, need_ident);
7301 return type;
7302}
7303
7304
7305static struct type *typedef_name(
7306 struct compile_state *state, unsigned int specifiers)
7307{
7308 struct hash_entry *ident;
7309 struct type *type;
7310 eat(state, TOK_TYPE_NAME);
7311 ident = state->token[0].ident;
7312 type = ident->sym_ident->type;
7313 specifiers |= type->type & QUAL_MASK;
7314 if ((specifiers & (STOR_MASK | QUAL_MASK)) !=
7315 (type->type & (STOR_MASK | QUAL_MASK))) {
7316 type = clone_type(specifiers, type);
7317 }
7318 FINISHME();
7319 return type;
7320}
7321
7322static struct type *enum_specifier(
7323 struct compile_state *state, unsigned int specifiers)
7324{
7325 int tok;
7326 struct type *type;
7327 type = 0;
7328 FINISHME();
7329 eat(state, TOK_ENUM);
7330 tok = peek(state);
7331 if (tok == TOK_IDENT) {
7332 eat(state, TOK_IDENT);
7333 }
7334 if ((tok != TOK_IDENT) || (peek(state) == TOK_LBRACE)) {
7335 eat(state, TOK_LBRACE);
7336 do {
7337 eat(state, TOK_IDENT);
7338 if (peek(state) == TOK_EQ) {
7339 eat(state, TOK_EQ);
7340 constant_expr(state);
7341 }
7342 if (peek(state) == TOK_COMMA) {
7343 eat(state, TOK_COMMA);
7344 }
7345 } while(peek(state) != TOK_RBRACE);
7346 eat(state, TOK_RBRACE);
7347 }
7348 FINISHME();
7349 return type;
7350}
7351
7352#if 0
7353static struct type *struct_declarator(
7354 struct compile_state *state, struct type *type, struct hash_entry **ident)
7355{
7356 int tok;
7357#warning "struct_declarator is complicated because of bitfields, kill them?"
7358 tok = peek(state);
7359 if (tok != TOK_COLON) {
7360 type = declarator(state, type, ident, 1);
7361 }
7362 if ((tok == TOK_COLON) || (peek(state) == TOK_COLON)) {
7363 eat(state, TOK_COLON);
7364 constant_expr(state);
7365 }
7366 FINISHME();
7367 return type;
7368}
7369#endif
7370
7371static struct type *struct_or_union_specifier(
7372 struct compile_state *state, unsigned int specifiers)
7373{
7374 struct type *type;
7375 int tok;
7376 FINISHME();
7377 type = 0;
7378 switch(peek(state)) {
7379 case TOK_STRUCT:
7380 eat(state, TOK_STRUCT);
7381 break;
7382 case TOK_UNION:
7383 eat(state, TOK_UNION);
7384 break;
7385 default:
7386 eat(state, TOK_STRUCT);
7387 break;
7388 }
7389 tok = peek(state);
7390 if (tok == TOK_IDENT) {
7391 eat(state, TOK_IDENT);
7392 FINISHME();
7393 }
7394 if ((tok != TOK_IDENT) || (peek(state) == TOK_LBRACE)) {
7395 eat(state, TOK_LBRACE);
7396 do {
7397 struct type *base_type;
7398 int done;
7399 FINISHME();
7400 base_type = specifier_qualifier_list(state);
7401 do {
7402 struct type *type;
7403 struct hash_entry *ident;
7404 done = 1;
7405 type = declarator(state, base_type, &ident, 1);
7406 if (peek(state) == TOK_COMMA) {
7407 done = 0;
7408 eat(state, TOK_COMMA);
7409 }
7410 } while(!done);
7411 eat(state, TOK_SEMI);
7412 } while(peek(state) != TOK_RBRACE);
7413 eat(state, TOK_RBRACE);
7414 }
7415 FINISHME();
7416 return type;
7417}
7418
7419static unsigned int storage_class_specifier_opt(struct compile_state *state)
7420{
7421 unsigned int specifiers;
7422 switch(peek(state)) {
7423 case TOK_AUTO:
7424 eat(state, TOK_AUTO);
7425 specifiers = STOR_AUTO;
7426 break;
7427 case TOK_REGISTER:
7428 eat(state, TOK_REGISTER);
7429 specifiers = STOR_REGISTER;
7430 break;
7431 case TOK_STATIC:
7432 eat(state, TOK_STATIC);
7433 specifiers = STOR_STATIC;
7434 break;
7435 case TOK_EXTERN:
7436 eat(state, TOK_EXTERN);
7437 specifiers = STOR_EXTERN;
7438 break;
7439 case TOK_TYPEDEF:
7440 eat(state, TOK_TYPEDEF);
7441 specifiers = STOR_TYPEDEF;
7442 break;
7443 default:
7444 if (state->scope_depth <= GLOBAL_SCOPE_DEPTH) {
7445 specifiers = STOR_STATIC;
7446 }
7447 else {
7448 specifiers = STOR_AUTO;
7449 }
7450 }
7451 return specifiers;
7452}
7453
7454static unsigned int function_specifier_opt(struct compile_state *state)
7455{
7456 /* Ignore the inline keyword */
7457 unsigned int specifiers;
7458 specifiers = 0;
7459 switch(peek(state)) {
7460 case TOK_INLINE:
7461 eat(state, TOK_INLINE);
7462 specifiers = STOR_INLINE;
7463 }
7464 return specifiers;
7465}
7466
7467static unsigned int type_qualifiers(struct compile_state *state)
7468{
7469 unsigned int specifiers;
7470 int done;
7471 done = 0;
7472 specifiers = QUAL_NONE;
7473 do {
7474 switch(peek(state)) {
7475 case TOK_CONST:
7476 eat(state, TOK_CONST);
7477 specifiers = QUAL_CONST;
7478 break;
7479 case TOK_VOLATILE:
7480 eat(state, TOK_VOLATILE);
7481 specifiers = QUAL_VOLATILE;
7482 break;
7483 case TOK_RESTRICT:
7484 eat(state, TOK_RESTRICT);
7485 specifiers = QUAL_RESTRICT;
7486 break;
7487 default:
7488 done = 1;
7489 break;
7490 }
7491 } while(!done);
7492 return specifiers;
7493}
7494
7495static struct type *type_specifier(
7496 struct compile_state *state, unsigned int spec)
7497{
7498 struct type *type;
7499 type = 0;
7500 switch(peek(state)) {
7501 case TOK_VOID:
7502 eat(state, TOK_VOID);
7503 type = new_type(TYPE_VOID | spec, 0, 0);
7504 break;
7505 case TOK_CHAR:
7506 eat(state, TOK_CHAR);
7507 type = new_type(TYPE_CHAR | spec, 0, 0);
7508 break;
7509 case TOK_SHORT:
7510 eat(state, TOK_SHORT);
7511 if (peek(state) == TOK_INT) {
7512 eat(state, TOK_INT);
7513 }
7514 type = new_type(TYPE_SHORT | spec, 0, 0);
7515 break;
7516 case TOK_INT:
7517 eat(state, TOK_INT);
7518 type = new_type(TYPE_INT | spec, 0, 0);
7519 break;
7520 case TOK_LONG:
7521 eat(state, TOK_LONG);
7522 switch(peek(state)) {
7523 case TOK_LONG:
7524 eat(state, TOK_LONG);
7525 error(state, 0, "long long not supported");
7526 break;
7527 case TOK_DOUBLE:
7528 eat(state, TOK_DOUBLE);
7529 error(state, 0, "long double not supported");
7530 break;
7531 case TOK_INT:
7532 eat(state, TOK_INT);
7533 type = new_type(TYPE_LONG | spec, 0, 0);
7534 break;
7535 default:
7536 type = new_type(TYPE_LONG | spec, 0, 0);
7537 break;
7538 }
7539 break;
7540 case TOK_FLOAT:
7541 eat(state, TOK_FLOAT);
7542 error(state, 0, "type float not supported");
7543 break;
7544 case TOK_DOUBLE:
7545 eat(state, TOK_DOUBLE);
7546 error(state, 0, "type double not supported");
7547 break;
7548 case TOK_SIGNED:
7549 eat(state, TOK_SIGNED);
7550 switch(peek(state)) {
7551 case TOK_LONG:
7552 eat(state, TOK_LONG);
7553 switch(peek(state)) {
7554 case TOK_LONG:
7555 eat(state, TOK_LONG);
7556 error(state, 0, "type long long not supported");
7557 break;
7558 case TOK_INT:
7559 eat(state, TOK_INT);
7560 type = new_type(TYPE_LONG | spec, 0, 0);
7561 break;
7562 default:
7563 type = new_type(TYPE_LONG | spec, 0, 0);
7564 break;
7565 }
7566 break;
7567 case TOK_INT:
7568 eat(state, TOK_INT);
7569 type = new_type(TYPE_INT | spec, 0, 0);
7570 break;
7571 case TOK_SHORT:
7572 eat(state, TOK_SHORT);
7573 type = new_type(TYPE_SHORT | spec, 0, 0);
7574 break;
7575 case TOK_CHAR:
7576 eat(state, TOK_CHAR);
7577 type = new_type(TYPE_CHAR | spec, 0, 0);
7578 break;
7579 default:
7580 type = new_type(TYPE_INT | spec, 0, 0);
7581 break;
7582 }
7583 break;
7584 case TOK_UNSIGNED:
7585 eat(state, TOK_UNSIGNED);
7586 switch(peek(state)) {
7587 case TOK_LONG:
7588 eat(state, TOK_LONG);
7589 switch(peek(state)) {
7590 case TOK_LONG:
7591 eat(state, TOK_LONG);
7592 error(state, 0, "unsigned long long not supported");
7593 break;
7594 case TOK_INT:
7595 eat(state, TOK_INT);
7596 type = new_type(TYPE_ULONG | spec, 0, 0);
7597 break;
7598 default:
7599 type = new_type(TYPE_ULONG | spec, 0, 0);
7600 break;
7601 }
7602 break;
7603 case TOK_INT:
7604 eat(state, TOK_INT);
7605 type = new_type(TYPE_UINT | spec, 0, 0);
7606 break;
7607 case TOK_SHORT:
7608 eat(state, TOK_SHORT);
7609 type = new_type(TYPE_USHORT | spec, 0, 0);
7610 break;
7611 case TOK_CHAR:
7612 eat(state, TOK_CHAR);
7613 type = new_type(TYPE_UCHAR | spec, 0, 0);
7614 break;
7615 default:
7616 type = new_type(TYPE_UINT | spec, 0, 0);
7617 break;
7618 }
7619 break;
7620 /* struct or union specifier */
7621 case TOK_STRUCT:
7622 case TOK_UNION:
7623 type = struct_or_union_specifier(state, spec);
7624 break;
7625 /* enum-spefifier */
7626 case TOK_ENUM:
7627 type = enum_specifier(state, spec);
7628 break;
7629 /* typedef name */
7630 case TOK_TYPE_NAME:
7631 type = typedef_name(state, spec);
7632 break;
7633 default:
7634 error(state, 0, "bad type specifier %s",
7635 tokens[peek(state)]);
7636 break;
7637 }
7638 return type;
7639}
7640
7641static int istype(int tok)
7642{
7643 switch(tok) {
7644 case TOK_CONST:
7645 case TOK_RESTRICT:
7646 case TOK_VOLATILE:
7647 case TOK_VOID:
7648 case TOK_CHAR:
7649 case TOK_SHORT:
7650 case TOK_INT:
7651 case TOK_LONG:
7652 case TOK_FLOAT:
7653 case TOK_DOUBLE:
7654 case TOK_SIGNED:
7655 case TOK_UNSIGNED:
7656 case TOK_STRUCT:
7657 case TOK_UNION:
7658 case TOK_ENUM:
7659 case TOK_TYPE_NAME:
7660 return 1;
7661 default:
7662 return 0;
7663 }
7664}
7665
7666
7667static struct type *specifier_qualifier_list(struct compile_state *state)
7668{
7669 struct type *type;
7670 unsigned int specifiers = 0;
7671
7672 /* type qualifiers */
7673 specifiers |= type_qualifiers(state);
7674
7675 /* type specifier */
7676 type = type_specifier(state, specifiers);
7677
7678 return type;
7679}
7680
7681static int isdecl_specifier(int tok)
7682{
7683 switch(tok) {
7684 /* storage class specifier */
7685 case TOK_AUTO:
7686 case TOK_REGISTER:
7687 case TOK_STATIC:
7688 case TOK_EXTERN:
7689 case TOK_TYPEDEF:
7690 /* type qualifier */
7691 case TOK_CONST:
7692 case TOK_RESTRICT:
7693 case TOK_VOLATILE:
7694 /* type specifiers */
7695 case TOK_VOID:
7696 case TOK_CHAR:
7697 case TOK_SHORT:
7698 case TOK_INT:
7699 case TOK_LONG:
7700 case TOK_FLOAT:
7701 case TOK_DOUBLE:
7702 case TOK_SIGNED:
7703 case TOK_UNSIGNED:
7704 /* struct or union specifier */
7705 case TOK_STRUCT:
7706 case TOK_UNION:
7707 /* enum-spefifier */
7708 case TOK_ENUM:
7709 /* typedef name */
7710 case TOK_TYPE_NAME:
7711 /* function specifiers */
7712 case TOK_INLINE:
7713 return 1;
7714 default:
7715 return 0;
7716 }
7717}
7718
7719static struct type *decl_specifiers(struct compile_state *state)
7720{
7721 struct type *type;
7722 unsigned int specifiers;
7723 /* I am overly restrictive in the arragement of specifiers supported.
7724 * C is overly flexible in this department it makes interpreting
7725 * the parse tree difficult.
7726 */
7727 specifiers = 0;
7728
7729 /* storage class specifier */
7730 specifiers |= storage_class_specifier_opt(state);
7731
7732 /* function-specifier */
7733 specifiers |= function_specifier_opt(state);
7734
7735 /* type qualifier */
7736 specifiers |= type_qualifiers(state);
7737
7738 /* type specifier */
7739 type = type_specifier(state, specifiers);
7740 return type;
7741}
7742
7743static unsigned designator(struct compile_state *state)
7744{
7745 int tok;
7746 unsigned index;
7747 index = -1U;
7748 do {
7749 switch(peek(state)) {
7750 case TOK_LBRACKET:
7751 {
7752 struct triple *value;
7753 eat(state, TOK_LBRACKET);
7754 value = constant_expr(state);
7755 eat(state, TOK_RBRACKET);
7756 index = value->u.cval;
7757 break;
7758 }
7759 case TOK_DOT:
7760 eat(state, TOK_DOT);
7761 eat(state, TOK_IDENT);
7762 error(state, 0, "Struct Designators not currently supported");
7763 break;
7764 default:
7765 error(state, 0, "Invalid designator");
7766 }
7767 tok = peek(state);
7768 } while((tok == TOK_LBRACKET) || (tok == TOK_DOT));
7769 eat(state, TOK_EQ);
7770 return index;
7771}
7772
7773static struct triple *initializer(
7774 struct compile_state *state, struct type *type)
7775{
7776 struct triple *result;
7777 if (peek(state) != TOK_LBRACE) {
7778 result = assignment_expr(state);
7779 }
7780 else {
7781 int comma;
7782 unsigned index, max_index;
7783 void *buf;
7784 max_index = index = 0;
7785 if ((type->type & TYPE_MASK) == TYPE_ARRAY) {
7786 max_index = type->elements;
7787 if (type->elements == ELEMENT_COUNT_UNSPECIFIED) {
7788 type->elements = 0;
7789 }
7790 } else {
7791 error(state, 0, "Struct initializers not currently supported");
7792 }
7793 buf = xcmalloc(size_of(state, type), "initializer");
7794 eat(state, TOK_LBRACE);
7795 do {
7796 struct triple *value;
7797 struct type *value_type;
7798 size_t value_size;
7799 int tok;
7800 comma = 0;
7801 tok = peek(state);
7802 if ((tok == TOK_LBRACKET) || (tok == TOK_DOT)) {
7803 index = designator(state);
7804 }
7805 if ((max_index != ELEMENT_COUNT_UNSPECIFIED) &&
7806 (index > max_index)) {
7807 error(state, 0, "element beyond bounds");
7808 }
7809 value_type = 0;
7810 if ((type->type & TYPE_MASK) == TYPE_ARRAY) {
7811 value_type = type->left;
7812 }
7813 value = eval_const_expr(state, initializer(state, value_type));
7814 value_size = size_of(state, value_type);
7815 if (((type->type & TYPE_MASK) == TYPE_ARRAY) &&
7816 (max_index == ELEMENT_COUNT_UNSPECIFIED) &&
7817 (type->elements <= index)) {
7818 void *old_buf;
7819 size_t old_size;
7820 old_buf = buf;
7821 old_size = size_of(state, type);
7822 type->elements = index + 1;
7823 buf = xmalloc(size_of(state, type), "initializer");
7824 memcpy(buf, old_buf, old_size);
7825 xfree(old_buf);
7826 }
7827 if (value->op == OP_BLOBCONST) {
7828 memcpy((char *)buf + index * value_size, value->u.blob, value_size);
7829 }
7830 else if ((value->op == OP_INTCONST) && (value_size == 1)) {
7831 *(((uint8_t *)buf) + index) = value->u.cval & 0xff;
7832 }
7833 else if ((value->op == OP_INTCONST) && (value_size == 2)) {
7834 *(((uint16_t *)buf) + index) = value->u.cval & 0xffff;
7835 }
7836 else if ((value->op == OP_INTCONST) && (value_size == 4)) {
7837 *(((uint32_t *)buf) + index) = value->u.cval & 0xffffffff;
7838 }
7839 else {
7840 fprintf(stderr, "%d %d\n",
7841 value->op, value_size);
7842 internal_error(state, 0, "unhandled constant initializer");
7843 }
7844 if (peek(state) == TOK_COMMA) {
7845 eat(state, TOK_COMMA);
7846 comma = 1;
7847 }
7848 index += 1;
7849 } while(comma && (peek(state) != TOK_RBRACE));
7850 eat(state, TOK_RBRACE);
7851 result = triple(state, OP_BLOBCONST, type, 0, 0);
7852 result->u.blob = buf;
7853 }
7854 return result;
7855}
7856
7857static struct triple *function_definition(
7858 struct compile_state *state, struct type *type)
7859{
7860 struct triple *def, *tmp, *first, *end;
7861 struct hash_entry *ident;
7862 struct type *param;
7863 int i;
7864 if ((type->type &TYPE_MASK) != TYPE_FUNCTION) {
7865 error(state, 0, "Invalid function header");
7866 }
7867
7868 /* Verify the function type */
7869 if (((type->right->type & TYPE_MASK) != TYPE_VOID) &&
7870 ((type->right->type & TYPE_MASK) != TYPE_PRODUCT) &&
7871 (type->right->ident == 0)) {
7872 error(state, 0, "Invalid function parameters");
7873 }
7874 param = type->right;
7875 i = 0;
7876 while((param->type & TYPE_MASK) == TYPE_PRODUCT) {
7877 i++;
7878 if (!param->left->ident) {
7879 error(state, 0, "No identifier for parameter %d\n", i);
7880 }
7881 param = param->right;
7882 }
7883 i++;
7884 if (((param->type & TYPE_MASK) != TYPE_VOID) && !param->ident) {
7885 error(state, 0, "No identifier for paramter %d\n", i);
7886 }
7887
7888 /* Get a list of statements for this function. */
7889 def = triple(state, OP_LIST, type, 0, 0);
7890
7891 /* Start a new scope for the passed parameters */
7892 start_scope(state);
7893
7894 /* Put a label at the very start of a function */
7895 first = label(state);
7896 def->left = first;
7897
7898 /* Put a label at the very end of a function */
7899 end = label(state);
7900 flatten(state, first, end);
7901
7902 /* Walk through the parameters and create symbol table entries
7903 * for them.
7904 */
7905 param = type->right;
7906 while((param->type & TYPE_MASK) == TYPE_PRODUCT) {
7907 ident = param->left->ident;
7908 tmp = variable(state, param->left);
7909 symbol(state, ident, &ident->sym_ident, tmp, tmp->type);
7910 flatten(state, end, tmp);
7911 param = param->right;
7912 }
7913 if ((param->type & TYPE_MASK) != TYPE_VOID) {
7914 /* And don't forget the last parameter */
7915 ident = param->ident;
7916 tmp = variable(state, param);
7917 symbol(state, ident, &ident->sym_ident, tmp, tmp->type);
7918 flatten(state, end, tmp);
7919 }
7920 /* Add a variable for the return value */
7921 def->right = 0;
7922 if ((type->left->type & TYPE_MASK) != TYPE_VOID) {
7923 /* Remove all type qualifiers from the return type */
7924 tmp = variable(state, clone_type(0, type->left));
7925 flatten(state, end, tmp);
7926 /* Remember where the return value is */
7927 def->right = tmp;
7928 }
7929
7930 /* Remember which function I am compiling.
7931 * Also assume the last defined function is the main function.
7932 */
7933 state->main_function = def;
7934
7935 /* Now get the actual function definition */
7936 compound_statement(state, end);
7937
7938 /* Remove the parameter scope */
7939 end_scope(state);
7940#if 0
7941 fprintf(stdout, "\n");
7942 loc(stdout, state, 0);
7943 fprintf(stdout, "\n__________ function_definition _________\n");
7944 print_triple(state, def);
7945 fprintf(stdout, "__________ function_definition _________ done\n\n");
7946#endif
7947
7948 return def;
7949}
7950
7951static struct triple *do_decl(struct compile_state *state,
7952 struct type *type, struct hash_entry *ident)
7953{
7954 struct triple *def;
7955 def = 0;
7956 /* Clean up the storage types used */
7957 switch (type->type & STOR_MASK) {
7958 case STOR_AUTO:
7959 case STOR_STATIC:
7960 /* These are the good types I am aiming for */
7961 break;
7962 case STOR_REGISTER:
7963 type->type &= ~STOR_MASK;
7964 type->type |= STOR_AUTO;
7965 break;
7966 case STOR_EXTERN:
7967 type->type &= ~STOR_MASK;
7968 type->type |= STOR_STATIC;
7969 break;
7970 case STOR_TYPEDEF:
7971#warning "FIXME support typedefs"
7972 error(state, 0, "typedefs not currently supported");
7973 break;
7974 default:
7975 internal_error(state, 0, "Undefined storage class");
7976 }
7977 if (((type->type & STOR_MASK) == STOR_STATIC) &&
7978 ((type->type & QUAL_CONST) == 0)) {
7979 error(state, 0, "non const static variables not supported");
7980 }
7981 if (ident) {
7982 def = variable(state, type);
7983 symbol(state, ident, &ident->sym_ident, def, type);
7984 }
7985 return def;
7986}
7987
7988static void decl(struct compile_state *state, struct triple *first)
7989{
7990 struct type *base_type, *type;
7991 struct hash_entry *ident;
7992 struct triple *def;
7993 int global;
7994 global = (state->scope_depth <= GLOBAL_SCOPE_DEPTH);
7995 base_type = decl_specifiers(state);
7996 ident = 0;
7997 type = declarator(state, base_type, &ident, 0);
7998 if (global && ident && (peek(state) == TOK_LBRACE)) {
7999 /* function */
8000 def = function_definition(state, type);
8001 symbol(state, ident, &ident->sym_ident, def, type);
8002 }
8003 else {
8004 int done;
8005 flatten(state, first, do_decl(state, type, ident));
8006 /* type or variable definition */
8007 do {
8008 done = 1;
8009 if (peek(state) == TOK_EQ) {
8010 if (!ident) {
8011 error(state, 0, "cannot assign to a type");
8012 }
8013 eat(state, TOK_EQ);
8014 flatten(state, first,
8015 init_expr(state,
8016 ident->sym_ident->def,
8017 initializer(state, type)));
8018 }
8019 arrays_complete(state, type);
8020 if (peek(state) == TOK_COMMA) {
8021 eat(state, TOK_COMMA);
8022 ident = 0;
8023 type = declarator(state, base_type, &ident, 0);
8024 flatten(state, first, do_decl(state, type, ident));
8025 done = 0;
8026 }
8027 } while(!done);
8028 eat(state, TOK_SEMI);
8029 }
8030}
8031
8032static void decls(struct compile_state *state)
8033{
8034 struct triple *list;
8035 int tok;
8036 list = label(state);
8037 while(1) {
8038 tok = peek(state);
8039 if (tok == TOK_EOF) {
8040 return;
8041 }
8042 if (tok == TOK_SPACE) {
8043 eat(state, TOK_SPACE);
8044 }
8045 decl(state, list);
8046 if (list->next != list) {
8047 error(state, 0, "global variables not supported");
8048 }
8049 }
8050}
8051
8052/*
8053 * Data structurs for optimation.
8054 */
8055
8056static void do_use_block(
8057 struct block *used, struct block_set **head, struct block *user,
8058 int front)
8059{
8060 struct block_set **ptr, *new;
8061 if (!used)
8062 return;
8063 if (!user)
8064 return;
8065 ptr = head;
8066 while(*ptr) {
8067 if ((*ptr)->member == user) {
8068 return;
8069 }
8070 ptr = &(*ptr)->next;
8071 }
8072 new = xcmalloc(sizeof(*new), "block_set");
8073 new->member = user;
8074 if (front) {
8075 new->next = *head;
8076 *head = new;
8077 }
8078 else {
8079 new->next = 0;
8080 *ptr = new;
8081 }
8082}
8083static void do_unuse_block(
8084 struct block *used, struct block_set **head, struct block *unuser)
8085{
8086 struct block_set *use, **ptr;
8087 ptr = head;
8088 while(*ptr) {
8089 use = *ptr;
8090 if (use->member == unuser) {
8091 *ptr = use->next;
8092 memset(use, -1, sizeof(*use));
8093 xfree(use);
8094 }
8095 else {
8096 ptr = &use->next;
8097 }
8098 }
8099}
8100
8101static void use_block(struct block *used, struct block *user)
8102{
8103 /* Append new to the head of the list, print_block
8104 * depends on this.
8105 */
8106 do_use_block(used, &used->use, user, 1);
8107 used->users++;
8108}
8109static void unuse_block(struct block *used, struct block *unuser)
8110{
8111 do_unuse_block(used, &used->use, unuser);
8112 used->users--;
8113}
8114
8115static void idom_block(struct block *idom, struct block *user)
8116{
8117 do_use_block(idom, &idom->idominates, user, 0);
8118}
8119
8120static void unidom_block(struct block *idom, struct block *unuser)
8121{
8122 do_unuse_block(idom, &idom->idominates, unuser);
8123}
8124
8125static void domf_block(struct block *block, struct block *domf)
8126{
8127 do_use_block(block, &block->domfrontier, domf, 0);
8128}
8129
8130static void undomf_block(struct block *block, struct block *undomf)
8131{
8132 do_unuse_block(block, &block->domfrontier, undomf);
8133}
8134
8135static void ipdom_block(struct block *ipdom, struct block *user)
8136{
8137 do_use_block(ipdom, &ipdom->ipdominates, user, 0);
8138}
8139
8140static void unipdom_block(struct block *ipdom, struct block *unuser)
8141{
8142 do_unuse_block(ipdom, &ipdom->ipdominates, unuser);
8143}
8144
8145static void ipdomf_block(struct block *block, struct block *ipdomf)
8146{
8147 do_use_block(block, &block->ipdomfrontier, ipdomf, 0);
8148}
8149
8150static void unipdomf_block(struct block *block, struct block *unipdomf)
8151{
8152 do_unuse_block(block, &block->ipdomfrontier, unipdomf);
8153}
8154
8155
8156
8157static int do_walk_triple(struct compile_state *state,
8158 struct triple *ptr, int depth,
8159 int (*cb)(struct compile_state *state, struct triple *ptr, int depth))
8160{
8161 int result;
8162 result = cb(state, ptr, depth);
8163 if ((result == 0) && (ptr->op == OP_LIST)) {
8164 struct triple *list;
8165 list = ptr;
8166 ptr = list->left;
8167 do {
8168 result = do_walk_triple(state, ptr, depth + 1, cb);
8169 if (ptr->next->prev != ptr) {
8170 internal_error(state, ptr->next, "bad prev");
8171 }
8172 ptr = ptr->next;
8173
8174 } while((result == 0) && (ptr != list->left));
8175 }
8176 return result;
8177}
8178
8179static int walk_triple(
8180 struct compile_state *state,
8181 struct triple *ptr,
8182 int (*cb)(struct compile_state *state, struct triple *ptr, int depth))
8183{
8184 return do_walk_triple(state, ptr, 0, cb);
8185}
8186
8187static void do_print_prefix(int depth)
8188{
8189 int i;
8190 for(i = 0; i < depth; i++) {
8191 printf(" ");
8192 }
8193}
8194
8195#define PRINT_LIST 1
8196static int do_print_triple(struct compile_state *state, struct triple *ins, int depth)
8197{
8198 int op;
8199 op = ins->op;
8200 if (op == OP_LIST) {
8201#if !PRINT_LIST
8202 return 0;
8203#endif
8204 }
8205 else if ((op == OP_LABEL) && (ins->use)) {
8206 printf("\n%p:\n", ins);
8207 }
8208 else if (op == OP_INTCONST) {
8209 do_print_prefix(depth);
8210 printf("(%p) %-7s %08lx @ %s:%d.%d\n",
8211 ins, tops(ins->op), ins->u.cval,
8212 ins->filename, ins->line, ins->col);
8213 return 0;
8214 }
8215 else if (op == OP_SDECL) {
8216 do_print_prefix(depth);
8217 printf("(%p) %-7s %-10p @ %s:%d.%d\n",
8218 ins, tops(ins->op), ins->left,
8219 ins->filename, ins->line, ins->col);
8220 do_print_triple(state, ins->left, depth + 1);
8221 }
8222 do_print_prefix(depth);
8223 printf("%s(%p) %-7s %-10p %-10p @ %s:%d.%d\n",
8224 (op == OP_LIST)? "list: ": "",
8225 ins, tops(ins->op), ins->left, ins->right,
8226 ins->filename, ins->line, ins->col);
8227 if ((ins->op == OP_BRANCH) && ins->use) {
8228 internal_error(state, ins, "branch used?");
8229 }
8230#if 0
8231 {
8232 struct triple_set *user;
8233 for(user = ins->use; user; user = user->next) {
8234 printf("use: %p\n", user->member);
8235 }
8236 }
8237#endif
8238 if (triple_is_branch(ins)) {
8239 printf("\n");
8240 }
8241 return 0;
8242}
8243
8244static void print_triple(struct compile_state *state, struct triple *ins)
8245{
8246 walk_triple(state, ins, do_print_triple);
8247}
8248
8249static void print_triples(struct compile_state *state)
8250{
8251 print_triple(state, state->main_function);
8252}
8253
8254struct cf_block {
8255 struct block *block;
8256};
8257static void find_cf_blocks(struct cf_block *cf, struct block *block)
8258{
8259 if (!block || (cf[block->vertex].block == block)) {
8260 return;
8261 }
8262 cf[block->vertex].block = block;
8263 find_cf_blocks(cf, block->left);
8264 find_cf_blocks(cf, block->right);
8265}
8266
8267static void print_control_flow(struct compile_state *state)
8268{
8269 struct cf_block *cf;
8270 int i;
8271 printf("\ncontrol flow\n");
8272 cf = xcmalloc(sizeof(*cf) * (state->last_vertex + 1), "cf_block");
8273 find_cf_blocks(cf, state->first_block);
8274
8275 for(i = 1; i <= state->last_vertex; i++) {
8276 struct block *block;
8277 block = cf[i].block;
8278 if (!block)
8279 continue;
8280 printf("(%p) %d:", block, block->vertex);
8281 if (block->left) {
8282 printf(" %d", block->left->vertex);
8283 }
8284 if (block->right && (block->right != block->left)) {
8285 printf(" %d", block->right->vertex);
8286 }
8287 printf("\n");
8288 }
8289
8290 xfree(cf);
8291}
8292
8293
8294static struct block *basic_block(struct compile_state *state,
8295 struct triple *first)
8296{
8297 struct block *block;
8298 struct triple *ptr;
8299 int op;
8300 if (first->op != OP_LABEL) {
8301 internal_error(state, 0, "block does not start with a label");
8302 }
8303 /* See if this basic block has already been setup */
8304 if (first->u.block != 0) {
8305 return first->u.block;
8306 }
8307 /* Allocate another basic block structure */
8308 state->last_vertex += 1;
8309 block = xcmalloc(sizeof(*block), "block");
8310 block->first = block->last = first;
8311 block->vertex = state->last_vertex;
8312 ptr = first;
8313 do {
8314 if ((ptr != first) && (ptr->op == OP_LABEL) && ptr->use) {
8315 break;
8316 }
8317 block->last = ptr;
8318 /* If ptr->u is not used remember where the baic block is */
8319 if (!is_const(ptr)) {
8320 ptr->u.block = block;
8321 }
8322 if (ptr->op == OP_BRANCH) {
8323 break;
8324 }
8325 ptr = ptr->next;
8326 } while (ptr != state->main_function->left);
8327 if (ptr == state->main_function->left)
8328 return block;
8329 op = ptr->op;
8330 if (op == OP_LABEL) {
8331 block->left = basic_block(state, ptr);
8332 block->right = 0;
8333 use_block(block->left, block);
8334 }
8335 else if (op == OP_BRANCH) {
8336 block->left = 0;
8337 /* Trace the branch target */
8338 block->right = basic_block(state, ptr->left);
8339 use_block(block->right, block);
8340 /* If there is a test trace the branch as well */
8341 if (ptr->right) {
8342 block->left = basic_block(state, ptr->next);
8343 use_block(block->left, block);
8344 }
8345 }
8346 else {
8347 internal_error(state, 0, "Bad basic block split");
8348 }
8349 return block;
8350}
8351
8352
8353static void walk_blocks(struct compile_state *state,
8354 void (*cb)(struct compile_state *state, struct block *block, void *arg),
8355 void *arg)
8356{
8357 struct triple *ptr, *first;
8358 struct block *last_block;
8359 last_block = 0;
8360 first = state->main_function->left;
8361 ptr = first;
8362 do {
8363 struct block *block;
8364 if (ptr->op == OP_LABEL) {
8365 block = ptr->u.block;
8366 if (block && (block != last_block)) {
8367 cb(state, block, arg);
8368 }
8369 last_block = block;
8370 }
8371 ptr = ptr->next;
8372 } while(ptr != first);
8373}
8374
8375static void print_block(
8376 struct compile_state *state, struct block *block, void *arg)
8377{
8378 struct triple *ptr;
8379
8380 printf("\nblock: %p (%d), %p<-%p %p<-%p\n",
8381 block,
8382 block->vertex,
8383 block->left,
8384 block->left && block->left->use?block->left->use->member : 0,
8385 block->right,
8386 block->right && block->right->use?block->right->use->member : 0);
8387 if (block->first->op == OP_LABEL) {
8388 printf("%p:\n", block->first);
8389 }
8390 for(ptr = block->first; ; ptr = ptr->next) {
8391 struct triple_set *user;
8392 int op = ptr->op;
8393
8394 if (!IS_CONST_OP(op)) {
8395 if (ptr->u.block != block) {
8396 internal_error(state, ptr,
8397 "Wrong block pointer: %p\n",
8398 ptr->u.block);
8399 }
8400 }
8401 if (op == OP_ADECL) {
8402 for(user = ptr->use; user; user = user->next) {
8403 if (!user->member->u.block) {
8404 internal_error(state, user->member,
8405 "Use %p not in a block?\n",
8406 user->member);
8407 }
8408 }
8409 }
8410 if (op == OP_INTCONST) {
8411 printf("(%p) %3d %-7s %08lx @ %s:%d.%d\n",
8412 ptr, ID_REG(ptr->id), tops(ptr->op),
8413 ptr->u.cval,
8414 ptr->filename, ptr->line, ptr->col);
8415 }
8416 else if (op == OP_PHI) {
8417 struct triple **slot;
8418 struct block *block;
8419 int edge;
8420 block = ptr->u.block;
8421 slot = (struct triple **)(ptr->left);
8422 printf("(%p) %3d %-7s",
8423 ptr, ID_REG(ptr->id), tops(ptr->op));
8424 for(edge = 0; edge < block->users; edge++) {
8425 printf(" %-10p", slot[edge]);
8426 }
8427 printf(" @%s:%d.%d\n",
8428 ptr->filename, ptr->line, ptr->col);
8429 }
8430 else {
8431 printf("(%p) %3d %-7s %-10p %-10p @ %s:%d.%d\n",
8432 ptr, ID_REG(ptr->id), tops(ptr->op),
8433 ptr->left, ptr->right,
8434 ptr->filename, ptr->line, ptr->col);
8435 }
8436 /* Sanity checks... */
8437 valid_op(state, ptr);
8438 for(user = ptr->use; user; user = user->next) {
8439 struct triple *use;
8440 use = user->member;
8441 valid_op(state, use);
8442 if (!IS_CONST_OP(user->member->op) &&
8443 !user->member->u.block) {
8444 internal_error(state, user->member,
8445 "Use %p not in a block?",
8446 user->member);
8447 }
8448 }
8449
8450 if (ptr == block->last)
8451 break;
8452 }
8453 printf("\n");
8454}
8455
8456
8457static void print_blocks(struct compile_state *state)
8458{
8459 printf("--------------- blocks ---------------\n");
8460 walk_blocks(state, print_block, 0);
8461}
8462
8463static void prune_nonblock_triples(struct compile_state *state)
8464{
8465 struct block *block;
8466 struct triple *first, *ins;
8467 /* Delete the triples not in a basic block */
8468 first = state->main_function->left;
8469 block = 0;
8470 ins = first;
8471 do {
8472 if (ins->op == OP_LABEL) {
8473 block = ins->u.block;
8474 }
8475 ins = ins->next;
8476 if (!block) {
8477 release_triple(state, ins->prev);
8478 }
8479 } while(ins != first);
8480}
8481
8482static void setup_basic_blocks(struct compile_state *state)
8483{
8484 /* Find the basic blocks */
8485 state->last_vertex = 0;
8486 state->first_block = basic_block(state, state->main_function->left);
8487 /* Delete the triples not in a basic block */
8488 prune_nonblock_triples(state);
8489 /* Find the last basic block */
8490 state->last_block = state->main_function->left->prev->u.block;
8491 if (!state->last_block) {
8492 internal_error(state, 0, "end not used?");
8493 }
8494 /* Insert an extra unused edge from start to the end
8495 * This helps with reverse control flow calculations.
8496 */
8497 use_block(state->first_block, state->last_block);
8498 /* If we are debugging print what I have just done */
8499 if (state->debug & DEBUG_BASIC_BLOCKS) {
8500 print_blocks(state);
8501 print_control_flow(state);
8502 }
8503}
8504
8505static void free_basic_block(struct compile_state *state, struct block *block)
8506{
8507 struct block_set *entry, *next;
8508 struct block *child;
8509 if (!block) {
8510 return;
8511 }
8512 if (block->vertex == -1) {
8513 return;
8514 }
8515 block->vertex = -1;
8516 if (block->left) {
8517 unuse_block(block->left, block);
8518 }
8519 if (block->right) {
8520 unuse_block(block->right, block);
8521 }
8522 if (block->idom) {
8523 unidom_block(block->idom, block);
8524 }
8525 block->idom = 0;
8526 if (block->ipdom) {
8527 unipdom_block(block->ipdom, block);
8528 }
8529 block->ipdom = 0;
8530 for(entry = block->use; entry; entry = next) {
8531 next = entry->next;
8532 child = entry->member;
8533 unuse_block(block, child);
8534 if (child->left == block) {
8535 child->left = 0;
8536 }
8537 if (child->right == block) {
8538 child->right = 0;
8539 }
8540 }
8541 for(entry = block->idominates; entry; entry = next) {
8542 next = entry->next;
8543 child = entry->member;
8544 unidom_block(block, child);
8545 child->idom = 0;
8546 }
8547 for(entry = block->domfrontier; entry; entry = next) {
8548 next = entry->next;
8549 child = entry->member;
8550 undomf_block(block, child);
8551 }
8552 for(entry = block->ipdominates; entry; entry = next) {
8553 next = entry->next;
8554 child = entry->member;
8555 unipdom_block(block, child);
8556 child->ipdom = 0;
8557 }
8558 for(entry = block->ipdomfrontier; entry; entry = next) {
8559 next = entry->next;
8560 child = entry->member;
8561 unipdomf_block(block, child);
8562 }
8563 if (block->users != 0) {
8564 internal_error(state, 0, "block still has users");
8565 }
8566 free_basic_block(state, block->left);
8567 block->left = 0;
8568 free_basic_block(state, block->right);
8569 block->right = 0;
8570 memset(block, -1, sizeof(*block));
8571 xfree(block);
8572}
8573
8574static void free_basic_blocks(struct compile_state *state)
8575{
8576 struct triple *first, *ins;
8577 free_basic_block(state, state->first_block);
8578 state->last_vertex = 0;
8579 state->first_block = state->last_block = 0;
8580 first = state->main_function->left;
8581 ins = first;
8582 do {
8583 if (!is_const(ins)) {
8584 ins->u.block = 0;
8585 }
8586 ins = ins->next;
8587 } while(ins != first);
8588
8589}
8590
8591struct sdom_block {
8592 struct block *block;
8593 struct sdom_block *sdominates;
8594 struct sdom_block *sdom_next;
8595 struct sdom_block *sdom;
8596 struct sdom_block *label;
8597 struct sdom_block *parent;
8598 struct sdom_block *ancestor;
8599 int vertex;
8600};
8601
8602
8603static void unsdom_block(struct sdom_block *block)
8604{
8605 struct sdom_block **ptr;
8606 if (!block->sdom_next) {
8607 return;
8608 }
8609 ptr = &block->sdom->sdominates;
8610 while(*ptr) {
8611 if ((*ptr) == block) {
8612 *ptr = block->sdom_next;
8613 return;
8614 }
8615 ptr = &(*ptr)->sdom_next;
8616 }
8617}
8618
8619static void sdom_block(struct sdom_block *sdom, struct sdom_block *block)
8620{
8621 unsdom_block(block);
8622 block->sdom = sdom;
8623 block->sdom_next = sdom->sdominates;
8624 sdom->sdominates = block;
8625}
8626
8627
8628
8629static int initialize_sdblock(struct sdom_block *sd,
8630 struct block *parent, struct block *block, int vertex)
8631{
8632 if (!block || (sd[block->vertex].block == block)) {
8633 return vertex;
8634 }
8635 vertex += 1;
8636 /* Renumber the blocks in a convinient fashion */
8637 block->vertex = vertex;
8638 sd[vertex].block = block;
8639 sd[vertex].sdom = &sd[vertex];
8640 sd[vertex].label = &sd[vertex];
8641 sd[vertex].parent = parent? &sd[parent->vertex] : 0;
8642 sd[vertex].ancestor = 0;
8643 sd[vertex].vertex = vertex;
8644 vertex = initialize_sdblock(sd, block, block->left, vertex);
8645 vertex = initialize_sdblock(sd, block, block->right, vertex);
8646 return vertex;
8647}
8648
8649static int initialize_sdpblock(struct sdom_block *sd,
8650 struct block *parent, struct block *block, int vertex)
8651{
8652 struct block_set *user;
8653 if (!block || (sd[block->vertex].block == block)) {
8654 return vertex;
8655 }
8656 vertex += 1;
8657 /* Renumber the blocks in a convinient fashion */
8658 block->vertex = vertex;
8659 sd[vertex].block = block;
8660 sd[vertex].sdom = &sd[vertex];
8661 sd[vertex].label = &sd[vertex];
8662 sd[vertex].parent = parent? &sd[parent->vertex] : 0;
8663 sd[vertex].ancestor = 0;
8664 sd[vertex].vertex = vertex;
8665 for(user = block->use; user; user = user->next) {
8666 vertex = initialize_sdpblock(sd, block, user->member, vertex);
8667 }
8668 return vertex;
8669}
8670
8671static void compress_ancestors(struct sdom_block *v)
8672{
8673 /* This procedure assumes ancestor(v) != 0 */
8674 /* if (ancestor(ancestor(v)) != 0) {
8675 * compress(ancestor(ancestor(v)));
8676 * if (semi(label(ancestor(v))) < semi(label(v))) {
8677 * label(v) = label(ancestor(v));
8678 * }
8679 * ancestor(v) = ancestor(ancestor(v));
8680 * }
8681 */
8682 if (!v->ancestor) {
8683 return;
8684 }
8685 if (v->ancestor->ancestor) {
8686 compress_ancestors(v->ancestor->ancestor);
8687 if (v->ancestor->label->sdom->vertex < v->label->sdom->vertex) {
8688 v->label = v->ancestor->label;
8689 }
8690 v->ancestor = v->ancestor->ancestor;
8691 }
8692}
8693
8694static void compute_sdom(struct compile_state *state, struct sdom_block *sd)
8695{
8696 int i;
8697 /* // step 2
8698 * for each v <= pred(w) {
8699 * u = EVAL(v);
8700 * if (semi[u] < semi[w] {
8701 * semi[w] = semi[u];
8702 * }
8703 * }
8704 * add w to bucket(vertex(semi[w]));
8705 * LINK(parent(w), w);
8706 *
8707 * // step 3
8708 * for each v <= bucket(parent(w)) {
8709 * delete v from bucket(parent(w));
8710 * u = EVAL(v);
8711 * dom(v) = (semi[u] < semi[v]) ? u : parent(w);
8712 * }
8713 */
8714 for(i = state->last_vertex; i >= 2; i--) {
8715 struct sdom_block *v, *parent, *next;
8716 struct block_set *user;
8717 struct block *block;
8718 block = sd[i].block;
8719 parent = sd[i].parent;
8720 /* Step 2 */
8721 for(user = block->use; user; user = user->next) {
8722 struct sdom_block *v, *u;
8723 v = &sd[user->member->vertex];
8724 u = !(v->ancestor)? v : (compress_ancestors(v), v->label);
8725 if (u->sdom->vertex < sd[i].sdom->vertex) {
8726 sd[i].sdom = u->sdom;
8727 }
8728 }
8729 sdom_block(sd[i].sdom, &sd[i]);
8730 sd[i].ancestor = parent;
8731 /* Step 3 */
8732 for(v = parent->sdominates; v; v = next) {
8733 struct sdom_block *u;
8734 next = v->sdom_next;
8735 unsdom_block(v);
8736 u = (!v->ancestor) ? v : (compress_ancestors(v), v->label);
8737 v->block->idom = (u->sdom->vertex < v->sdom->vertex)?
8738 u->block : parent->block;
8739 }
8740 }
8741}
8742
8743static void compute_spdom(struct compile_state *state, struct sdom_block *sd)
8744{
8745 int i;
8746 /* // step 2
8747 * for each v <= pred(w) {
8748 * u = EVAL(v);
8749 * if (semi[u] < semi[w] {
8750 * semi[w] = semi[u];
8751 * }
8752 * }
8753 * add w to bucket(vertex(semi[w]));
8754 * LINK(parent(w), w);
8755 *
8756 * // step 3
8757 * for each v <= bucket(parent(w)) {
8758 * delete v from bucket(parent(w));
8759 * u = EVAL(v);
8760 * dom(v) = (semi[u] < semi[v]) ? u : parent(w);
8761 * }
8762 */
8763 for(i = state->last_vertex; i >= 2; i--) {
8764 struct sdom_block *u, *v, *parent, *next;
8765 struct block *block;
8766 block = sd[i].block;
8767 parent = sd[i].parent;
8768 /* Step 2 */
8769 if (block->left) {
8770 v = &sd[block->left->vertex];
8771 u = !(v->ancestor)? v : (compress_ancestors(v), v->label);
8772 if (u->sdom->vertex < sd[i].sdom->vertex) {
8773 sd[i].sdom = u->sdom;
8774 }
8775 }
8776 if (block->right && (block->right != block->left)) {
8777 v = &sd[block->right->vertex];
8778 u = !(v->ancestor)? v : (compress_ancestors(v), v->label);
8779 if (u->sdom->vertex < sd[i].sdom->vertex) {
8780 sd[i].sdom = u->sdom;
8781 }
8782 }
8783 sdom_block(sd[i].sdom, &sd[i]);
8784 sd[i].ancestor = parent;
8785 /* Step 3 */
8786 for(v = parent->sdominates; v; v = next) {
8787 struct sdom_block *u;
8788 next = v->sdom_next;
8789 unsdom_block(v);
8790 u = (!v->ancestor) ? v : (compress_ancestors(v), v->label);
8791 v->block->ipdom = (u->sdom->vertex < v->sdom->vertex)?
8792 u->block : parent->block;
8793 }
8794 }
8795}
8796
8797static void compute_idom(struct compile_state *state, struct sdom_block *sd)
8798{
8799 int i;
8800 for(i = 2; i <= state->last_vertex; i++) {
8801 struct block *block;
8802 block = sd[i].block;
8803 if (block->idom->vertex != sd[i].sdom->vertex) {
8804 block->idom = block->idom->idom;
8805 }
8806 idom_block(block->idom, block);
8807 }
8808 sd[1].block->idom = 0;
8809}
8810
8811static void compute_ipdom(struct compile_state *state, struct sdom_block *sd)
8812{
8813 int i;
8814 for(i = 2; i <= state->last_vertex; i++) {
8815 struct block *block;
8816 block = sd[i].block;
8817 if (block->ipdom->vertex != sd[i].sdom->vertex) {
8818 block->ipdom = block->ipdom->ipdom;
8819 }
8820 ipdom_block(block->ipdom, block);
8821 }
8822 sd[1].block->ipdom = 0;
8823}
8824
8825 /* Theorem 1:
8826 * Every vertex of a flowgraph G = (V, E, r) except r has
8827 * a unique immediate dominator.
8828 * The edges {(idom(w), w) |w <= V - {r}} form a directed tree
8829 * rooted at r, called the dominator tree of G, such that
8830 * v dominates w if and only if v is a proper ancestor of w in
8831 * the dominator tree.
8832 */
8833 /* Lemma 1:
8834 * If v and w are vertices of G such that v <= w,
8835 * than any path from v to w must contain a common ancestor
8836 * of v and w in T.
8837 */
8838 /* Lemma 2: For any vertex w != r, idom(w) -> w */
8839 /* Lemma 3: For any vertex w != r, sdom(w) -> w */
8840 /* Lemma 4: For any vertex w != r, idom(w) -> sdom(w) */
8841 /* Theorem 2:
8842 * Let w != r. Suppose every u for which sdom(w) -> u -> w satisfies
8843 * sdom(u) >= sdom(w). Then idom(w) = sdom(w).
8844 */
8845 /* Theorem 3:
8846 * Let w != r and let u be a vertex for which sdom(u) is
8847 * minimum amoung vertices u satisfying sdom(w) -> u -> w.
8848 * Then sdom(u) <= sdom(w) and idom(u) = idom(w).
8849 */
8850 /* Lemma 5: Let vertices v,w satisfy v -> w.
8851 * Then v -> idom(w) or idom(w) -> idom(v)
8852 */
8853
8854static void find_immediate_dominators(struct compile_state *state)
8855{
8856 struct sdom_block *sd;
8857 /* w->sdom = min{v| there is a path v = v0,v1,...,vk = w such that:
8858 * vi > w for (1 <= i <= k - 1}
8859 */
8860 /* Theorem 4:
8861 * For any vertex w != r.
8862 * sdom(w) = min(
8863 * {v|(v,w) <= E and v < w } U
8864 * {sdom(u) | u > w and there is an edge (v, w) such that u -> v})
8865 */
8866 /* Corollary 1:
8867 * Let w != r and let u be a vertex for which sdom(u) is
8868 * minimum amoung vertices u satisfying sdom(w) -> u -> w.
8869 * Then:
8870 * { sdom(w) if sdom(w) = sdom(u),
8871 * idom(w) = {
8872 * { idom(u) otherwise
8873 */
8874 /* The algorithm consists of the following 4 steps.
8875 * Step 1. Carry out a depth-first search of the problem graph.
8876 * Number the vertices from 1 to N as they are reached during
8877 * the search. Initialize the variables used in succeeding steps.
8878 * Step 2. Compute the semidominators of all vertices by applying
8879 * theorem 4. Carry out the computation vertex by vertex in
8880 * decreasing order by number.
8881 * Step 3. Implicitly define the immediate dominator of each vertex
8882 * by applying Corollary 1.
8883 * Step 4. Explicitly define the immediate dominator of each vertex,
8884 * carrying out the computation vertex by vertex in increasing order
8885 * by number.
8886 */
8887 /* Step 1 initialize the basic block information */
8888 sd = xcmalloc(sizeof(*sd) * (state->last_vertex + 1), "sdom_state");
8889 initialize_sdblock(sd, 0, state->first_block, 0);
8890#if 0
8891 sd[1].size = 0;
8892 sd[1].label = 0;
8893 sd[1].sdom = 0;
8894#endif
8895 /* Step 2 compute the semidominators */
8896 /* Step 3 implicitly define the immediate dominator of each vertex */
8897 compute_sdom(state, sd);
8898 /* Step 4 explicitly define the immediate dominator of each vertex */
8899 compute_idom(state, sd);
8900 xfree(sd);
8901}
8902
8903static void find_post_dominators(struct compile_state *state)
8904{
8905 struct sdom_block *sd;
8906 /* Step 1 initialize the basic block information */
8907 sd = xcmalloc(sizeof(*sd) * (state->last_vertex + 1), "sdom_state");
8908
8909 initialize_sdpblock(sd, 0, state->last_block, 0);
8910
8911 /* Step 2 compute the semidominators */
8912 /* Step 3 implicitly define the immediate dominator of each vertex */
8913 compute_spdom(state, sd);
8914 /* Step 4 explicitly define the immediate dominator of each vertex */
8915 compute_ipdom(state, sd);
8916 xfree(sd);
8917}
8918
8919
8920
8921static void find_block_domf(struct compile_state *state, struct block *block)
8922{
8923 struct block *child;
8924 struct block_set *user;
8925 if (block->domfrontier != 0) {
8926 internal_error(state, block->first, "domfrontier present?");
8927 }
8928 for(user = block->idominates; user; user = user->next) {
8929 child = user->member;
8930 if (child->idom != block) {
8931 internal_error(state, block->first, "bad idom");
8932 }
8933 find_block_domf(state, child);
8934 }
8935 if (block->left && block->left->idom != block) {
8936 domf_block(block, block->left);
8937 }
8938 if (block->right && block->right->idom != block) {
8939 domf_block(block, block->right);
8940 }
8941 for(user = block->idominates; user; user = user->next) {
8942 struct block_set *frontier;
8943 child = user->member;
8944 for(frontier = child->domfrontier; frontier; frontier = frontier->next) {
8945 if (frontier->member->idom != block) {
8946 domf_block(block, frontier->member);
8947 }
8948 }
8949 }
8950}
8951
8952static void find_block_ipdomf(struct compile_state *state, struct block *block)
8953{
8954 struct block *child;
8955 struct block_set *user;
8956 if (block->ipdomfrontier != 0) {
8957 internal_error(state, block->first, "ipdomfrontier present?");
8958 }
8959 for(user = block->ipdominates; user; user = user->next) {
8960 child = user->member;
8961 if (child->ipdom != block) {
8962 internal_error(state, block->first, "bad ipdom");
8963 }
8964 find_block_ipdomf(state, child);
8965 }
8966 if (block->left && block->left->ipdom != block) {
8967 ipdomf_block(block, block->left);
8968 }
8969 if (block->right && block->right->ipdom != block) {
8970 ipdomf_block(block, block->right);
8971 }
8972 for(user = block->idominates; user; user = user->next) {
8973 struct block_set *frontier;
8974 child = user->member;
8975 for(frontier = child->ipdomfrontier; frontier; frontier = frontier->next) {
8976 if (frontier->member->ipdom != block) {
8977 ipdomf_block(block, frontier->member);
8978 }
8979 }
8980 }
8981}
8982
8983static int print_dominated(
8984 struct compile_state *state, struct block *block, int vertex)
8985{
8986 struct block_set *user;
8987
8988 if (!block || (block->vertex != vertex + 1)) {
8989 return vertex;
8990 }
8991 vertex += 1;
8992
8993 printf("%d:", block->vertex);
8994 for(user = block->idominates; user; user = user->next) {
8995 printf(" %d", user->member->vertex);
8996 if (user->member->idom != block) {
8997 internal_error(state, user->member->first, "bad idom");
8998 }
8999 }
9000 printf("\n");
9001 vertex = print_dominated(state, block->left, vertex);
9002 vertex = print_dominated(state, block->right, vertex);
9003 return vertex;
9004}
9005
9006static void print_dominators(struct compile_state *state)
9007{
9008 printf("\ndominates\n");
9009 print_dominated(state, state->first_block, 0);
9010}
9011
9012
9013static int print_frontiers(
9014 struct compile_state *state, struct block *block, int vertex)
9015{
9016 struct block_set *user;
9017
9018 if (!block || (block->vertex != vertex + 1)) {
9019 return vertex;
9020 }
9021 vertex += 1;
9022
9023 printf("%d:", block->vertex);
9024 for(user = block->domfrontier; user; user = user->next) {
9025 printf(" %d", user->member->vertex);
9026 }
9027 printf("\n");
9028
9029 vertex = print_frontiers(state, block->left, vertex);
9030 vertex = print_frontiers(state, block->right, vertex);
9031 return vertex;
9032}
9033static void print_dominance_frontiers(struct compile_state *state)
9034{
9035 printf("\ndominance frontiers\n");
9036 print_frontiers(state, state->first_block, 0);
9037
9038}
9039
9040static void analyze_idominators(struct compile_state *state)
9041{
9042 /* Find the immediate dominators */
9043 find_immediate_dominators(state);
9044 /* Find the dominance frontiers */
9045 find_block_domf(state, state->first_block);
9046 /* If debuging print the print what I have just found */
9047 if (state->debug & DEBUG_FDOMINATORS) {
9048 print_dominators(state);
9049 print_dominance_frontiers(state);
9050 print_control_flow(state);
9051 }
9052}
9053
9054
9055
9056static int print_ipdominated(
9057 struct compile_state *state, struct block *block, int vertex)
9058{
9059 struct block_set *user;
9060
9061 if (!block || (block->vertex != vertex + 1)) {
9062 return vertex;
9063 }
9064 vertex += 1;
9065
9066 printf("%d:", block->vertex);
9067 for(user = block->ipdominates; user; user = user->next) {
9068 printf(" %d", user->member->vertex);
9069 if (user->member->ipdom != block) {
9070 internal_error(state, user->member->first, "bad ipdom");
9071 }
9072 }
9073 printf("\n");
9074 for(user = block->use; user; user = user->next) {
9075 vertex = print_ipdominated(state, user->member, vertex);
9076 }
9077 return vertex;
9078}
9079
9080static void print_ipdominators(struct compile_state *state)
9081{
9082 printf("\nipdominates\n");
9083 print_ipdominated(state, state->last_block, 0);
9084}
9085
9086static int print_pfrontiers(
9087 struct compile_state *state, struct block *block, int vertex)
9088{
9089 struct block_set *user;
9090
9091 if (!block || (block->vertex != vertex + 1)) {
9092 return vertex;
9093 }
9094 vertex += 1;
9095
9096 printf("%d:", block->vertex);
9097 for(user = block->ipdomfrontier; user; user = user->next) {
9098 printf(" %d", user->member->vertex);
9099 }
9100 printf("\n");
9101 for(user = block->use; user; user = user->next) {
9102 vertex = print_pfrontiers(state, user->member, vertex);
9103 }
9104 return vertex;
9105}
9106static void print_ipdominance_frontiers(struct compile_state *state)
9107{
9108 printf("\nipdominance frontiers\n");
9109 print_pfrontiers(state, state->last_block, 0);
9110
9111}
9112
9113static void analyze_ipdominators(struct compile_state *state)
9114{
9115 /* Find the post dominators */
9116 find_post_dominators(state);
9117 /* Find the control dependencies (post dominance frontiers) */
9118 find_block_ipdomf(state, state->last_block);
9119 /* If debuging print the print what I have just found */
9120 if (state->debug & DEBUG_RDOMINATORS) {
9121 print_ipdominators(state);
9122 print_ipdominance_frontiers(state);
9123 print_control_flow(state);
9124 }
9125}
9126
9127
9128static void insert_phi_operations(struct compile_state *state)
9129{
9130 size_t size;
9131 struct triple *first;
9132 int *has_already, *work;
9133 struct block *work_list, **work_list_tail;
9134 int iter;
9135 struct triple *var;
9136
9137 size = sizeof(int) * (state->last_vertex + 1);
9138 has_already = xcmalloc(size, "has_already");
9139 work = xcmalloc(size, "work");
9140 iter = 0;
9141
9142 first = state->main_function->left;
9143 for(var = first->next; var != first ; var = var->next) {
9144 struct block *block;
9145 struct triple_set *user;
9146 if ((var->op != OP_ADECL) || !var->use) {
9147 continue;
9148 }
9149 iter += 1;
9150 work_list = 0;
9151 work_list_tail = &work_list;
9152 for(user = var->use; user; user = user->next) {
9153 if (user->member->op == OP_READ) {
9154 continue;
9155 }
9156 if (user->member->op != OP_WRITE) {
9157 internal_error(state, user->member,
9158 "bad variable access");
9159 }
9160 block = user->member->u.block;
9161 if (!block) {
9162 warning(state, user->member, "dead code");
9163 }
9164 work[block->vertex] = iter;
9165 *work_list_tail = block;
9166 block->work_next = 0;
9167 work_list_tail = &block->work_next;
9168 }
9169 for(block = work_list; block; block = block->work_next) {
9170 struct block_set *df;
9171 for(df = block->domfrontier; df; df = df->next) {
9172 struct triple *phi;
9173 struct block *front;
9174 int in_edges;
9175 front = df->member;
9176
9177 if (has_already[front->vertex] >= iter) {
9178 continue;
9179 }
9180 /* Count how many edges flow into this block */
9181 in_edges = front->users;
9182 /* Insert a phi function for this variable */
9183 phi = xcmalloc(in_edges * sizeof(*phi),"phi");
9184 phi = triple(state, OP_PHI, var->type,
9185 phi, var);
9186 phi->filename = front->first->filename;
9187 phi->line = front->first->line;
9188 phi->col = front->first->col;
9189 phi->u.block = front;
9190 use_triple(var, phi);
9191 /* Insert the phi functions immediately after the label */
9192 insert_triple(state, front->first->next, phi);
9193 if (front->first == front->last) {
9194 front->last = front->first->next;
9195 }
9196 has_already[front->vertex] = iter;
9197
9198 /* If necessary plan to visit the basic block */
9199 if (work[front->vertex] >= iter) {
9200 continue;
9201 }
9202 work[front->vertex] = iter;
9203 *work_list_tail = front;
9204 front->work_next = 0;
9205 work_list_tail = &front->work_next;
9206 }
9207 }
9208 }
9209 xfree(has_already);
9210 xfree(work);
9211}
9212
9213/*
9214 * C(V)
9215 * S(V)
9216 */
9217static void fixup_block_phi_variables(
9218 struct compile_state *state, struct block *parent, struct block *block)
9219{
9220 struct block_set *set;
9221 struct triple *ptr;
9222 int edge;
9223 if (!parent || !block)
9224 return;
9225 /* Find the edge I am coming in on */
9226 edge = 0;
9227 for(set = block->use; set; set = set->next, edge++) {
9228 if (set->member == parent) {
9229 break;
9230 }
9231 }
9232 if (!set) {
9233 internal_error(state, 0, "phi input is not on a control predecessor");
9234 }
9235 for(ptr = block->first; ; ptr = ptr->next) {
9236 if (ptr->op == OP_PHI) {
9237 struct triple *var, *val, **slot;
9238 var = ptr->right;
9239 /* Find the current value of the variable */
9240 val = var->use->member;
9241 if ((val->op == OP_WRITE) || (val->op == OP_READ)) {
9242 internal_error(state, val, "bad value in phi");
9243 }
9244 slot = (struct triple **)(ptr->left);
9245 slot += edge;
9246 if ((*slot != 0) && (*slot != val)) {
9247 internal_error(state, ptr, "phi already bound on this edge");
9248 }
9249 *slot = val;
9250 use_triple(val, ptr);
9251 }
9252 if (ptr == block->last) {
9253 break;
9254 }
9255 }
9256}
9257
9258
9259static void rename_block_variables(
9260 struct compile_state *state, struct block *block)
9261{
9262 struct block_set *user;
9263 struct triple *ptr, *next, *last;
9264 int done;
9265 if (!block)
9266 return;
9267 last = block->first;
9268 done = 0;
9269 for(ptr = block->first; !done; ptr = next) {
9270 next = ptr->next;
9271 if (ptr == block->last) {
9272 done = 1;
9273 }
9274 /* RHS(A) */
9275 if (ptr->op == OP_READ) {
9276 struct triple *var, *val;
9277 var = ptr->left;
9278 unuse_triple(var, ptr);
9279 if (!var->use) {
9280 error(state, ptr, "variable used without being set");
9281 }
9282 /* Find the current value of the variable */
9283 val = var->use->member;
9284 if ((val->op == OP_WRITE) || (val->op == OP_READ)) {
9285 internal_error(state, val, "bad value in read");
9286 }
9287 propogate_use(state, ptr, val);
9288 release_triple(state, ptr);
9289 continue;
9290 }
9291 /* LHS(A) */
9292 if (ptr->op == OP_WRITE) {
9293 struct triple *var, *val;
9294 var = ptr->left;
9295 val = ptr->right;
9296 if ((val->op == OP_WRITE) || (val->op == OP_READ)) {
9297 internal_error(state, val, "bad value in write");
9298 }
9299 propogate_use(state, ptr, val);
9300 unuse_triple(var, ptr);
9301 /* Push OP_WRITE ptr->right onto a stack of variable uses */
9302 push_triple(var, val);
9303 }
9304 if (ptr->op == OP_PHI) {
9305 struct triple *var;
9306 var = ptr->right;
9307 /* Push OP_PHI onto a stack of variable uses */
9308 push_triple(var, ptr);
9309 }
9310 last = ptr;
9311 }
9312 block->last = last;
9313
9314 /* Fixup PHI functions in the cf successors */
9315 fixup_block_phi_variables(state, block, block->left);
9316 fixup_block_phi_variables(state, block, block->right);
9317 /* rename variables in the dominated nodes */
9318 for(user = block->idominates; user; user = user->next) {
9319 rename_block_variables(state, user->member);
9320 }
9321 /* pop the renamed variable stack */
9322 last = block->first;
9323 done = 0;
9324 for(ptr = block->first; !done ; ptr = next) {
9325 next = ptr->next;
9326 if (ptr == block->last) {
9327 done = 1;
9328 }
9329 if (ptr->op == OP_WRITE) {
9330 struct triple *var;
9331 var = ptr->left;
9332 /* Pop OP_WRITE ptr->right from the stack of variable uses */
9333 pop_triple(var, ptr->right);
9334 release_triple(state, ptr);
9335 continue;
9336 }
9337 if (ptr->op == OP_PHI) {
9338 struct triple *var;
9339 var = ptr->right;
9340 /* Pop OP_WRITE ptr->right from the stack of variable uses */
9341 pop_triple(var, ptr);
9342 }
9343 last = ptr;
9344 }
9345 block->last = last;
9346}
9347
9348static void prune_block_variables(struct compile_state *state,
9349 struct block *block)
9350{
9351 struct block_set *user;
9352 struct triple *next, *last, *ptr;
9353 int done;
9354 last = block->first;
9355 done = 0;
9356 for(ptr = block->first; !done; ptr = next) {
9357 next = ptr->next;
9358 if (ptr == block->last) {
9359 done = 1;
9360 }
9361 if (ptr->op == OP_ADECL) {
9362 struct triple_set *user, *next;
9363 for(user = ptr->use; user; user = next) {
9364 struct triple *use;
9365 next = user->next;
9366 use = user->member;
9367 if (use->op != OP_PHI) {
9368 internal_error(state, use, "decl still used");
9369 }
9370 if (use->right != ptr) {
9371 internal_error(state, use, "bad phi use of decl");
9372 }
9373 unuse_triple(ptr, use);
9374 use->right = 0;
9375 }
9376 release_triple(state, ptr);
9377 continue;
9378 }
9379 last = ptr;
9380 }
9381 block->last = last;
9382 for(user = block->idominates; user; user = user->next) {
9383 prune_block_variables(state, user->member);
9384 }
9385}
9386
9387static void transform_to_ssa_form(struct compile_state *state)
9388{
9389 insert_phi_operations(state);
9390#if 0
9391 printf("@%s:%d\n", __FILE__, __LINE__);
9392 print_blocks(state);
9393#endif
9394 rename_block_variables(state, state->first_block);
9395 prune_block_variables(state, state->first_block);
9396}
9397
9398
9399static void transform_from_ssa_form(struct compile_state *state)
9400{
9401 /* To get out of ssa form we insert moves on the incoming
9402 * edges to blocks containting phi functions.
9403 */
9404 struct triple *first;
9405 struct triple *phi, *next;
9406
9407 /* Walk all of the operations to find the phi functions */
9408 first = state->main_function->left;
9409 for(phi = first->next; phi != first ; phi = next) {
9410 struct block_set *set;
9411 struct block *block;
9412 struct triple **slot;
9413 struct triple *var, *read;
9414 int edge;
9415 next = phi->next;
9416 if (phi->op != OP_PHI) {
9417 continue;
9418 }
9419 block = phi->u.block;
9420 slot = (struct triple **)(phi->left);
9421
9422 /* A variable to replace the phi function */
9423 var = post_triple(state, phi, OP_ADECL, phi->type, 0,0);
9424 /* A read of the single value that is set into the variable */
9425 read = post_triple(state, var, OP_READ, phi->type, var, 0);
9426 use_triple(var, read);
9427
9428 /* Replaces uses of the phi with variable reads */
9429 propogate_use(state, phi, read);
9430
9431 /* Walk all of the incoming edges/blocks and insert moves.
9432 */
9433 for(edge = 0, set = block->use; set; set = set->next, edge++) {
9434 struct block *eblock;
9435 struct triple *move;
9436 struct triple *val;
9437 eblock = set->member;
9438 val = slot[edge];
9439 unuse_triple(val, phi);
9440
9441 if (val == phi) {
9442 continue;
9443 }
9444
9445 move = post_triple(state,
9446 val, OP_WRITE, phi->type, var, val);
9447 use_triple(val, move);
9448 use_triple(var, move);
9449 }
9450 release_triple(state, phi);
9451 }
9452
9453}
9454
9455static void insert_copies_to_phi(struct compile_state *state)
9456{
9457 /* To get out of ssa form we insert moves on the incoming
9458 * edges to blocks containting phi functions.
9459 */
9460 struct triple *first;
9461 struct triple *phi;
9462
9463 /* Walk all of the operations to find the phi functions */
9464 first = state->main_function->left;
9465 for(phi = first->next; phi != first ; phi = phi->next) {
9466 struct block_set *set;
9467 struct block *block;
9468 struct triple **slot;
9469 int edge;
9470 if (phi->op != OP_PHI) {
9471 continue;
9472 }
9473 if (ID_REG(phi->id) == REG_UNSET) {
9474 phi->id = MK_REG_ID(alloc_virtual_reg(),
9475 ID_REG_CLASSES(phi->id));
9476 }
9477 block = phi->u.block;
9478 slot = (struct triple **)(phi->left);
9479 /* Walk all of the incoming edges/blocks and insert moves.
9480 */
9481 for(edge = 0, set = block->use; set; set = set->next, edge++) {
9482 struct block *eblock;
9483 struct triple *move;
9484 struct triple *val;
9485 struct triple *ptr;
9486 eblock = set->member;
9487 val = slot[edge];
9488
9489 if (val == phi) {
9490 continue;
9491 }
9492
9493 move = build_triple(state, OP_COPY, phi->type, val, 0,
9494 val->filename, val->line, val->col);
9495 move->u.block = eblock;
9496 move->id = phi->id;
9497 use_triple(val, move);
9498
9499 slot[edge] = move;
9500 unuse_triple(val, phi);
9501 use_triple(move, phi);
9502
9503 /* Walk through the block backwards to find
9504 * an appropriate location for the OP_COPY.
9505 */
9506 for(ptr = eblock->last; ptr != eblock->first; ptr = ptr->prev) {
9507 struct triple **expr;
9508 if ((ptr == phi) || (ptr == val)) {
9509 goto out;
9510 }
9511 expr = triple_rhs(state, ptr, 0);
9512 for(;expr; expr = triple_rhs(state, ptr, expr)) {
9513 if ((*expr) == phi) {
9514 goto out;
9515 }
9516 }
9517 }
9518 out:
9519 if (triple_is_branch(ptr)) {
9520 internal_error(state, ptr,
9521 "Could not insert write to phi");
9522 }
9523 insert_triple(state, ptr->next, move);
9524 if (eblock->last == ptr) {
9525 eblock->last = move;
9526 }
9527 }
9528 }
9529}
9530
9531struct triple_reg_set {
9532 struct triple_reg_set *next;
9533 struct triple *member;
9534 struct triple *new;
9535};
9536
9537struct reg_block {
9538 struct block *block;
9539 struct triple_reg_set *in;
9540 struct triple_reg_set *out;
9541 int vertex;
9542};
9543
9544static int do_triple_set(struct triple_reg_set **head,
9545 struct triple *member, struct triple *new_member)
9546{
9547 struct triple_reg_set **ptr, *new;
9548 if (!member)
9549 return 0;
9550 ptr = head;
9551 while(*ptr) {
9552 if ((*ptr)->member == member) {
9553 return 0;
9554 }
9555 ptr = &(*ptr)->next;
9556 }
9557 new = xcmalloc(sizeof(*new), "triple_set");
9558 new->member = member;
9559 new->new = new_member;
9560 new->next = *head;
9561 *head = new;
9562 return 1;
9563}
9564
9565static void do_triple_unset(struct triple_reg_set **head, struct triple *member)
9566{
9567 struct triple_reg_set *entry, **ptr;
9568 ptr = head;
9569 while(*ptr) {
9570 entry = *ptr;
9571 if (entry->member == member) {
9572 *ptr = entry->next;
9573 xfree(entry);
9574 return;
9575 }
9576 else {
9577 ptr = &entry->next;
9578 }
9579 }
9580}
9581
9582static int in_triple(struct reg_block *rb, struct triple *in)
9583{
9584 return do_triple_set(&rb->in, in, 0);
9585}
9586static void unin_triple(struct reg_block *rb, struct triple *unin)
9587{
9588 do_triple_unset(&rb->in, unin);
9589}
9590
9591static int out_triple(struct reg_block *rb, struct triple *out)
9592{
9593 return do_triple_set(&rb->out, out, 0);
9594}
9595static void unout_triple(struct reg_block *rb, struct triple *unout)
9596{
9597 do_triple_unset(&rb->out, unout);
9598}
9599
9600static int initialize_regblock(struct reg_block *blocks,
9601 struct block *block, int vertex)
9602{
9603 struct block_set *user;
9604 if (!block || (blocks[block->vertex].block == block)) {
9605 return vertex;
9606 }
9607 vertex += 1;
9608 /* Renumber the blocks in a convinient fashion */
9609 block->vertex = vertex;
9610 blocks[vertex].block = block;
9611 blocks[vertex].vertex = vertex;
9612 for(user = block->use; user; user = user->next) {
9613 vertex = initialize_regblock(blocks, user->member, vertex);
9614 }
9615 return vertex;
9616}
9617
9618static int phi_in(struct compile_state *state, struct reg_block *blocks,
9619 struct reg_block *rb, struct block *suc)
9620{
9621 /* Read the conditional input set of a successor block
9622 * (i.e. the input to the phi nodes) and place it in the
9623 * current blocks output set.
9624 */
9625 struct block_set *set;
9626 struct triple *ptr;
9627 int edge;
9628 int done, change;
9629 change = 0;
9630 /* Find the edge I am coming in on */
9631 for(edge = 0, set = suc->use; set; set = set->next, edge++) {
9632 if (set->member == rb->block) {
9633 break;
9634 }
9635 }
9636 if (!set) {
9637 internal_error(state, 0, "Not coming on a control edge?");
9638 }
9639 for(done = 0, ptr = suc->first; !done; ptr = ptr->next) {
9640 struct triple **slot, *expr, *ptr2;
9641 int out_change, done2;
9642 done = (ptr == suc->last);
9643 if (ptr->op != OP_PHI) {
9644 continue;
9645 }
9646 slot = (struct triple **)(ptr->left);
9647 expr = slot[edge];
9648 out_change = out_triple(rb, expr);
9649 if (!out_change) {
9650 continue;
9651 }
9652 /* If we don't define the variable also plast it
9653 * in the current blocks input set.
9654 */
9655 ptr2 = rb->block->first;
9656 for(done2 = 0; !done2; ptr2 = ptr2->next) {
9657 if (ptr2 == expr) {
9658 break;
9659 }
9660 done2 = (ptr2 == rb->block->last);
9661 }
9662 if (!done2) {
9663 continue;
9664 }
9665 change |= in_triple(rb, expr);
9666 }
9667 return change;
9668}
9669
9670static int reg_in(struct compile_state *state, struct reg_block *blocks,
9671 struct reg_block *rb, struct block *suc)
9672{
9673 struct triple_reg_set *in_set;
9674 int change;
9675 change = 0;
9676 /* Read the input set of a successor block
9677 * and place it in the current blocks output set.
9678 */
9679 in_set = blocks[suc->vertex].in;
9680 for(; in_set; in_set = in_set->next) {
9681 int out_change, done;
9682 struct triple *first, *last, *ptr;
9683 out_change = out_triple(rb, in_set->member);
9684 if (!out_change) {
9685 continue;
9686 }
9687 /* If we don't define the variable also place it
9688 * in the current blocks input set.
9689 */
9690 first = rb->block->first;
9691 last = rb->block->last;
9692 done = 0;
9693 for(ptr = first; !done; ptr = ptr->next) {
9694 if (ptr == in_set->member) {
9695 break;
9696 }
9697 done = (ptr == last);
9698 }
9699 if (!done) {
9700 continue;
9701 }
9702 change |= in_triple(rb, in_set->member);
9703 }
9704 change |= phi_in(state, blocks, rb, suc);
9705 return change;
9706}
9707
9708
9709static int use_in(struct compile_state *state, struct reg_block *rb)
9710{
9711 /* Find the variables we use but don't define and add
9712 * it to the current blocks input set.
9713 */
9714#warning "FIXME is this O(N^2) algorithm bad?"
9715 struct block *block;
9716 struct triple *ptr;
9717 int done;
9718 int change;
9719 block = rb->block;
9720 change = 0;
9721 for(done = 0, ptr = block->last; !done; ptr = ptr->prev) {
9722 struct triple **expr;
9723 done = (ptr == block->first);
9724 /* The variable a phi function uses depends on the
9725 * control flow, and is handled in phi_in, not
9726 * here.
9727 */
9728 if (ptr->op == OP_PHI) {
9729 continue;
9730 }
9731 expr = triple_rhs(state, ptr, 0);
9732 for(;expr; expr = triple_rhs(state, ptr, expr)) {
9733 struct triple *rhs, *test;
9734 int tdone;
9735 rhs = *expr;
9736 /* See if rhs is defined in this block */
9737 for(tdone = 0, test = ptr; !tdone; test = test->prev) {
9738 tdone = (test == block->first);
9739 if (test == rhs) {
9740 rhs = 0;
9741 break;
9742 }
9743 }
9744 /* If the triple is not a definition skip it. */
9745 if (!triple_is_def(ptr)) {
9746 continue;
9747 }
9748 /* If I still have a valid rhs add it to in */
9749 change |= in_triple(rb, rhs);
9750 }
9751 }
9752 return change;
9753}
9754
9755static struct reg_block *compute_variable_lifetimes(
9756 struct compile_state *state)
9757{
9758 struct reg_block *blocks;
9759 int change;
9760 blocks = xcmalloc(
9761 sizeof(*blocks)*(state->last_vertex + 1), "reg_block");
9762 initialize_regblock(blocks, state->last_block, 0);
9763 do {
9764 int i;
9765 change = 0;
9766 for(i = 1; i <= state->last_vertex; i++) {
9767 struct reg_block *rb;
9768 rb = &blocks[i];
9769 /* Add the left successor's input set to in */
9770 if (rb->block->left) {
9771 change |= reg_in(state, blocks, rb, rb->block->left);
9772 }
9773 /* Add the right successor's input set to in */
9774 if ((rb->block->right) &&
9775 (rb->block->right != rb->block->left)) {
9776 change |= reg_in(state, blocks, rb, rb->block->right);
9777 }
9778 /* Add use to in... */
9779 change |= use_in(state, rb);
9780 }
9781 } while(change);
9782 return blocks;
9783}
9784
9785static void free_variable_lifetimes(
9786 struct compile_state *state, struct reg_block *blocks)
9787{
9788 int i;
9789 /* free in_set && out_set on each block */
9790 for(i = 1; i <= state->last_vertex; i++) {
9791 struct triple_reg_set *entry, *next;
9792 struct reg_block *rb;
9793 rb = &blocks[i];
9794 for(entry = rb->in; entry ; entry = next) {
9795 next = entry->next;
9796 do_triple_unset(&rb->in, entry->member);
9797 }
9798 for(entry = rb->out; entry; entry = next) {
9799 next = entry->next;
9800 do_triple_unset(&rb->out, entry->member);
9801 }
9802 }
9803 xfree(blocks);
9804
9805}
9806
9807typedef struct triple *(*wvl_cb_t)(
9808 struct compile_state *state,
9809 struct reg_block *blocks, struct triple_reg_set *live,
9810 struct reg_block *rb, struct triple *ins, void *arg);
9811
9812static void walk_variable_lifetimes(struct compile_state *state,
9813 struct reg_block *blocks, wvl_cb_t cb, void *arg)
9814{
9815 int i;
9816
9817 for(i = 1; i <= state->last_vertex; i++) {
9818 struct triple_reg_set *live;
9819 struct triple_reg_set *entry, *next;
9820 struct triple *ptr, *prev;
9821 struct reg_block *rb;
9822 struct block *block;
9823 int done;
9824
9825 /* Get the blocks */
9826 rb = &blocks[i];
9827 block = rb->block;
9828
9829 /* Copy out into live */
9830 live = 0;
9831 for(entry = rb->out; entry; entry = next) {
9832 next = entry->next;
9833 do_triple_set(&live, entry->member, entry->new);
9834 }
9835 /* Walk through the basic block calculating live */
9836 for(done = 0, ptr = block->last; !done; ptr = prev) {
9837 struct triple **expr;
9838
9839 prev = ptr->prev;
9840 done = (ptr == block->first);
9841
9842 /* Remove the current definition from live */
9843 do_triple_unset(&live, ptr);
9844
9845 /* If the current instruction was deleted continue */
9846 if (!cb(state, blocks, live, rb, ptr, arg)) {
9847 if (block->last == ptr) {
9848 block->last = prev;
9849 }
9850 continue;
9851 }
9852
9853 /* Add the current uses to live.
9854 *
9855 * It is safe to skip phi functions because they do
9856 * not have any block local uses, and the block
9857 * output sets already properly account for what
9858 * control flow depedent uses phi functions do have.
9859 */
9860 if (ptr->op == OP_PHI) {
9861 continue;
9862 }
9863 expr = triple_rhs(state, ptr, 0);
9864 for(;expr; expr = triple_rhs(state, ptr, expr)) {
9865 /* If the triple is not a definition skip it. */
9866 if (!triple_is_def(*expr)) {
9867 continue;
9868 }
9869 do_triple_set(&live, *expr, 0);
9870 }
9871
9872 }
9873 /* Free live */
9874 for(entry = live; entry; entry = next) {
9875 next = entry->next;
9876 do_triple_unset(&live, entry->member);
9877 }
9878 }
9879}
9880
9881static int count_triples(struct compile_state *state)
9882{
9883 struct triple *first, *ins;
9884 int triples = 0;
9885 first = state->main_function->left;
9886 ins = first;
9887 do {
9888 triples++;
9889 ins = ins->next;
9890 } while (ins != first);
9891 return triples;
9892}
9893struct dead_triple {
9894 struct triple *triple;
9895 struct dead_triple *work_next;
9896 struct block *block;
9897 int color;
9898 int flags;
9899#define TRIPLE_FLAG_ALIVE 1
9900};
9901
9902
9903static void awaken(
9904 struct compile_state *state,
9905 struct dead_triple *dtriple, struct triple **expr,
9906 struct dead_triple ***work_list_tail)
9907{
9908 struct triple *triple;
9909 struct dead_triple *dt;
9910 if (!expr) {
9911 return;
9912 }
9913 triple = *expr;
9914 if (!triple) {
9915 return;
9916 }
9917 if (triple->id <= 0) {
9918 internal_error(state, triple, "bad triple id: %d",
9919 triple->id);
9920 }
9921 if (triple->op == OP_NOOP) {
9922 internal_warning(state, triple, "awakening noop?");
9923 return;
9924 }
9925 dt = &dtriple[triple->id];
9926 if (!(dt->flags & TRIPLE_FLAG_ALIVE)) {
9927 dt->flags |= TRIPLE_FLAG_ALIVE;
9928 if (!dt->work_next) {
9929 **work_list_tail = dt;
9930 *work_list_tail = &dt->work_next;
9931 }
9932 }
9933}
9934
9935static void eliminate_inefectual_code(struct compile_state *state)
9936{
9937 struct block *block;
9938 struct dead_triple *dtriple, *work_list, **work_list_tail, *dt;
9939 int triples, i;
9940 struct triple *first, *ins;
9941
9942 /* Setup the work list */
9943 work_list = 0;
9944 work_list_tail = &work_list;
9945
9946 first = state->main_function->left;
9947
9948 /* Count how many triples I have */
9949 triples = count_triples(state);
9950
9951 /* Now put then in an array and mark all of the triples dead */
9952 dtriple = xcmalloc(sizeof(*dtriple) * (triples + 1), "dtriples");
9953
9954 ins = first;
9955 i = 1;
9956 block = 0;
9957 do {
9958 if (ins->op == OP_LABEL) {
9959 block = ins->u.block;
9960 }
9961 dtriple[i].triple = ins;
9962 dtriple[i].block = block;
9963 dtriple[i].flags = 0;
9964 dtriple[i].color = ins->id;
9965 ins->id = i;
9966 /* See if it is an operation we always keep */
9967#warning "FIXME handle the case of killing a branch instruction"
9968 if (!triple_is_pure(state, ins) || triple_is_branch(ins)) {
9969 awaken(state, dtriple, &ins, &work_list_tail);
9970 }
9971 i++;
9972 ins = ins->next;
9973 } while(ins != first);
9974 while(work_list) {
9975 struct dead_triple *dt;
9976 struct block_set *user;
9977 struct triple **expr;
9978 dt = work_list;
9979 work_list = dt->work_next;
9980 if (!work_list) {
9981 work_list_tail = &work_list;
9982 }
9983 /* Wake up the data depencencies of this triple */
9984 expr = 0;
9985 do {
9986 expr = triple_rhs(state, dt->triple, expr);
9987 awaken(state, dtriple, expr, &work_list_tail);
9988 } while(expr);
9989 do {
9990 expr = triple_lhs(state, dt->triple, expr);
9991 awaken(state, dtriple, expr, &work_list_tail);
9992 } while(expr);
9993 /* Wake up the forward control dependencies */
9994 do {
9995 expr = triple_targ(state, dt->triple, expr);
9996 awaken(state, dtriple, expr, &work_list_tail);
9997 } while(expr);
9998 /* Wake up the reverse control dependencies of this triple */
9999 for(user = dt->block->ipdomfrontier; user; user = user->next) {
10000 awaken(state, dtriple, &user->member->last, &work_list_tail);
10001 }
10002 }
10003 for(dt = &dtriple[1]; dt <= &dtriple[triples]; dt++) {
10004 if ((dt->triple->op == OP_NOOP) &&
10005 (dt->flags & TRIPLE_FLAG_ALIVE)) {
10006 internal_error(state, dt->triple, "noop effective?");
10007 }
10008 dt->triple->id = dt->color; /* Restore the color */
10009 if (!(dt->flags & TRIPLE_FLAG_ALIVE)) {
10010#warning "FIXME handle the case of killing a basic block"
10011 if (dt->block->first == dt->triple) {
10012 continue;
10013 }
10014 if (dt->block->last == dt->triple) {
10015 dt->block->last = dt->triple->prev;
10016 }
10017 release_triple(state, dt->triple);
10018 }
10019 }
10020 xfree(dtriple);
10021}
10022
10023
10024struct live_range_edge;
10025struct live_range {
10026 struct live_range_edge *edges;
10027 struct triple *def;
10028 unsigned color;
10029 unsigned classes;
10030 unsigned degree;
10031 struct live_range *group_next, **group_prev;
10032};
10033
10034struct live_range_edge {
10035 struct live_range_edge *next;
10036 struct live_range *node;
10037};
10038
10039#define LRE_HASH_SIZE 2048
10040struct lre_hash {
10041 struct lre_hash *next;
10042 struct live_range *left;
10043 struct live_range *right;
10044};
10045
10046
10047struct reg_state {
10048 struct lre_hash *hash[LRE_HASH_SIZE];
10049 struct reg_block *blocks;
10050 struct live_range *lr;
10051 struct live_range *low, **low_tail;
10052 struct live_range *high, **high_tail;
10053 unsigned ranges;
10054};
10055
10056
10057static unsigned regc_max_size(struct compile_state *state, int classes)
10058{
10059 unsigned max_size;
10060 int i;
10061 max_size = 0;
10062 for(i = 0; i < MAX_REGC; i++) {
10063 if (classes & (1 << i)) {
10064 unsigned size;
10065 size = arch_regc_size(state, i);
10066 if (size > max_size) {
10067 max_size = size;
10068 }
10069 }
10070 }
10071 return max_size;
10072}
10073
10074static int reg_is_reg(struct compile_state *state, int reg1, int reg2)
10075{
10076 unsigned equivs[MAX_REG_EQUIVS];
10077 int i;
10078 if ((reg1 < 0) || (reg1 >= MAX_REGISTERS)) {
10079 internal_error(state, 0, "invalid register");
10080 }
10081 if ((reg2 < 0) || (reg2 >= MAX_REGISTERS)) {
10082 internal_error(state, 0, "invalid register");
10083 }
10084 arch_reg_equivs(state, equivs, reg1);
10085 for(i = 0; (i < MAX_REG_EQUIVS) && equivs[i] != REG_UNSET; i++) {
10086 if (equivs[i] == reg2) {
10087 return 1;
10088 }
10089 }
10090 return 0;
10091}
10092
10093static void reg_fill_used(struct compile_state *state, char *used, int reg)
10094{
10095 unsigned equivs[MAX_REG_EQUIVS];
10096 int i;
10097 arch_reg_equivs(state, equivs, reg);
10098 for(i = 0; (i < MAX_REG_EQUIVS) && equivs[i] != REG_UNSET; i++) {
10099 used[equivs[i]] = 1;
10100 }
10101 return;
10102}
10103
10104static unsigned int hash_live_edge(
10105 struct live_range *left, struct live_range *right)
10106{
10107 unsigned int hash, val;
10108 unsigned long lval, rval;
10109 lval = ((unsigned long)left)/sizeof(struct live_range);
10110 rval = ((unsigned long)right)/sizeof(struct live_range);
10111 hash = 0;
10112 while(lval) {
10113 val = lval & 0xff;
10114 lval >>= 8;
10115 hash = (hash *263) + val;
10116 }
10117 while(rval) {
10118 val = rval & 0xff;
10119 rval >>= 8;
10120 hash = (hash *263) + val;
10121 }
10122 hash = hash & (LRE_HASH_SIZE - 1);
10123 return hash;
10124}
10125
10126static struct lre_hash **lre_probe(struct reg_state *rstate,
10127 struct live_range *left, struct live_range *right)
10128{
10129 struct lre_hash **ptr;
10130 unsigned int index;
10131 /* Ensure left <= right */
10132 if (left > right) {
10133 struct live_range *tmp;
10134 tmp = left;
10135 left = right;
10136 right = tmp;
10137 }
10138 index = hash_live_edge(left, right);
10139
10140 ptr = &rstate->hash[index];
10141 while((*ptr) && ((*ptr)->left != left) && ((*ptr)->right != right)) {
10142 ptr = &(*ptr)->next;
10143 }
10144 return ptr;
10145}
10146
10147static int interfere(struct reg_state *rstate,
10148 struct live_range *left, struct live_range *right)
10149{
10150 struct lre_hash **ptr;
10151 ptr = lre_probe(rstate, left, right);
10152 return ptr && *ptr;
10153}
10154
10155static void add_live_edge(struct reg_state *rstate,
10156 struct live_range *left, struct live_range *right)
10157{
10158 /* FIXME the memory allocation overhead is noticeable here... */
10159 struct lre_hash **ptr, *new_hash;
10160 struct live_range_edge *edge;
10161
10162 if (left == right) {
10163 return;
10164 }
10165 if ((left == &rstate->lr[0]) || (right == &rstate->lr[0])) {
10166 return;
10167 }
10168 /* Ensure left <= right */
10169 if (left > right) {
10170 struct live_range *tmp;
10171 tmp = left;
10172 left = right;
10173 right = tmp;
10174 }
10175 ptr = lre_probe(rstate, left, right);
10176 if (*ptr) {
10177 return;
10178 }
10179 new_hash = xmalloc(sizeof(*new_hash), "lre_hash");
10180 new_hash->next = *ptr;
10181 new_hash->left = left;
10182 new_hash->right = right;
10183 *ptr = new_hash;
10184
10185 edge = xmalloc(sizeof(*edge), "live_range_edge");
10186 edge->next = left->edges;
10187 edge->node = right;
10188 left->edges = edge;
10189 left->degree += 1;
10190
10191 edge = xmalloc(sizeof(*edge), "live_range_edge");
10192 edge->next = right->edges;
10193 edge->node = left;
10194 right->edges = edge;
10195 right->degree += 1;
10196}
10197
10198static void remove_live_edge(struct reg_state *rstate,
10199 struct live_range *left, struct live_range *right)
10200{
10201 struct live_range_edge *edge, **ptr;
10202 struct lre_hash **hptr, *entry;
10203 hptr = lre_probe(rstate, left, right);
10204 if (!hptr || !*hptr) {
10205 return;
10206 }
10207 entry = *hptr;
10208 *hptr = entry->next;
10209 xfree(entry);
10210
10211 for(ptr = &left->edges; *ptr; ptr = &(*ptr)->next) {
10212 edge = *ptr;
10213 if (edge->node == right) {
10214 *ptr = edge->next;
10215 memset(edge, 0, sizeof(*edge));
10216 xfree(edge);
10217 break;
10218 }
10219 }
10220 for(ptr = &right->edges; *ptr; ptr = &(*ptr)->next) {
10221 edge = *ptr;
10222 if (edge->node == left) {
10223 *ptr = edge->next;
10224 memset(edge, 0, sizeof(*edge));
10225 xfree(edge);
10226 break;
10227 }
10228 }
10229}
10230
10231static void remove_live_edges(struct reg_state *rstate, struct live_range *range)
10232{
10233 struct live_range_edge *edge, *next;
10234 for(edge = range->edges; edge; edge = next) {
10235 next = edge->next;
10236 remove_live_edge(rstate, range, edge->node);
10237 }
10238}
10239
10240
10241/* Interference graph...
10242 *
10243 * new(n) --- Return a graph with n nodes but no edges.
10244 * add(g,x,y) --- Return a graph including g with an between x and y
10245 * interfere(g, x, y) --- Return true if there exists an edge between the nodes
10246 * x and y in the graph g
10247 * degree(g, x) --- Return the degree of the node x in the graph g
10248 * neighbors(g, x, f) --- Apply function f to each neighbor of node x in the graph g
10249 *
10250 * Implement with a hash table && a set of adjcency vectors.
10251 * The hash table supports constant time implementations of add and interfere.
10252 * The adjacency vectors support an efficient implementation of neighbors.
10253 */
10254
10255/*
10256 * +---------------------------------------------------+
10257 * | +--------------+ |
10258 * v v | |
10259 * renumber -> build graph -> colalesce -> spill_costs -> simplify -> select
10260 *
10261 * -- In simplify implment optimistic coloring... (No backtracking)
10262 * -- Implement Rematerialization it is the only form of spilling we can perform
10263 * Essentially this means dropping a constant from a register because
10264 * we can regenerate it later.
10265 *
10266 * --- Very conservative colalescing (don't colalesce just mark the opportunities)
10267 * coalesce at phi points...
10268 * --- Bias coloring if at all possible do the coalesing a compile time.
10269 *
10270 *
10271 */
10272
10273static void different_colored(
10274 struct compile_state *state, struct reg_state *rstate,
10275 struct triple *parent, struct triple *ins)
10276{
10277 struct live_range *lr;
10278 struct triple **expr;
10279 lr = &rstate->lr[ins->id];
10280 expr = triple_rhs(state, ins, 0);
10281 for(;expr; expr = triple_rhs(state, ins, expr)) {
10282 struct live_range *lr2;
10283 if ((*expr == parent) || (*expr == ins)) {
10284 continue;
10285 }
10286 lr2 = &rstate->lr[(*expr)->id];
10287 if (lr->color == lr2->color) {
10288 internal_error(state, ins, "live range too big");
10289 }
10290 }
10291}
10292
10293static void initialize_live_ranges(
10294 struct compile_state *state, struct reg_state *rstate)
10295{
10296 struct triple *ins, *first;
10297 size_t size;
10298 int i;
10299
10300 first = state->main_function->left;
10301 /* First count how many live ranges I will need.
10302 */
10303 rstate->ranges = count_triples(state);
10304 size = sizeof(rstate->lr[0]) * (rstate->ranges + 1);
10305 rstate->lr = xcmalloc(size, "live_range");
10306 /* Setup the dummy live range */
10307 rstate->lr[0].classes = 0;
10308 rstate->lr[0].color = REG_UNSET;
10309 rstate->lr[0].def = 0;
10310 i = 0;
10311 ins = first;
10312 do {
10313 unsigned color, classes;
10314 /* Find the architecture specific color information */
10315 color = ID_REG(ins->id);
10316 classes = ID_REG_CLASSES(ins->id);
10317 if ((color != REG_UNSET) && (color < MAX_REGISTERS)) {
10318 classes = arch_reg_regcm(state, color);
10319 }
10320
10321 /* If the triple is a variable definition give it a live range. */
10322 if (triple_is_def(ins)) {
10323 i++;
10324 ins->id = i;
10325 rstate->lr[i].def = ins;
10326 rstate->lr[i].color = color;
10327 rstate->lr[i].classes = classes;
10328 rstate->lr[i].degree = 0;
10329 if (!classes) {
10330 internal_error(state, ins,
10331 "live range without a class");
10332 }
10333 }
10334 /* Otherwise give the triple the dummy live range. */
10335 else {
10336 ins->id = 0;
10337 }
10338 ins = ins->next;
10339 } while(ins != first);
10340 rstate->ranges = i;
10341 /* Make a second pass to handle achitecture specific register
10342 * constraints.
10343 */
10344 ins = first;
10345 do {
10346 struct live_range *lr;
10347 lr = &rstate->lr[ins->id];
10348 if (lr->color != REG_UNSET) {
10349 struct triple **expr;
10350 /* This assumes the virtual register is only
10351 * used by one input operation.
10352 */
10353 expr = triple_rhs(state, ins, 0);
10354 for(;expr; expr = triple_rhs(state, ins, expr)) {
10355 struct live_range *lr2;
10356 if (ins == *expr) {
10357 continue;
10358 }
10359 lr2 = &rstate->lr[(*expr)->id];
10360 if (lr->color == lr2->color) {
10361 different_colored(state, rstate,
10362 ins, *expr);
10363 (*expr)->id = ins->id;
10364
10365 }
10366 }
10367 }
10368 ins = ins->next;
10369 } while(ins != first);
10370
10371 /* Make a third pass and forget the virtual registers */
10372 for(i = 1; i <= rstate->ranges; i++) {
10373 if (rstate->lr[i].color >= MAX_REGISTERS) {
10374 rstate->lr[i].color = REG_UNSET;
10375 }
10376 }
10377}
10378
10379static struct triple *graph_ins(
10380 struct compile_state *state,
10381 struct reg_block *blocks, struct triple_reg_set *live,
10382 struct reg_block *rb, struct triple *ins, void *arg)
10383{
10384 struct reg_state *rstate = arg;
10385 struct live_range *def;
10386 struct triple_reg_set *entry;
10387
10388 /* If the triple does not start a live range
10389 * we do not have a definition to add to
10390 * the interference graph.
10391 */
10392 if (ins->id <= 0) {
10393 return ins;
10394 }
10395 def = &rstate->lr[ins->id];
10396
10397 /* Create an edge between ins and everything that is
10398 * alive, unless the live_range cannot share
10399 * a physical register with ins.
10400 */
10401 for(entry = live; entry; entry = entry->next) {
10402 struct live_range *lr;
10403 lr= &rstate->lr[entry->member->id];
10404 if (!arch_regcm_intersect(def->classes, lr->classes)) {
10405 continue;
10406 }
10407 add_live_edge(rstate, def, lr);
10408 }
10409 return ins;
10410}
10411
10412
10413static struct triple *print_interference_ins(
10414 struct compile_state *state,
10415 struct reg_block *blocks, struct triple_reg_set *live,
10416 struct reg_block *rb, struct triple *ins, void *arg)
10417{
10418 struct reg_state *rstate = arg;
10419 struct live_range *lr;
10420
10421 lr = &rstate->lr[ins->id];
10422 if ((ins->op == OP_LABEL) && (ins->use)) {
10423 printf("\n%p:\n", ins);
10424 }
10425 else if (ins->op == OP_INTCONST) {
10426 printf("(%p) %-7s %08lx @ %s:%d.%d\n",
10427 ins, tops(ins->op), ins->u.cval,
10428 ins->filename, ins->line, ins->col);
10429 }
10430 else {
10431 printf("(%p) %-7s %-10p %-10p @ %s:%d.%d\n",
10432 ins, tops(ins->op), ins->left, ins->right,
10433 ins->filename, ins->line, ins->col);
10434 }
10435 if (live) {
10436 struct triple_reg_set *entry;
10437 printf(" live:");
10438 for(entry = live; entry; entry = entry->next) {
10439 printf(" %-10p", entry->member);
10440 }
10441 printf("\n");
10442 }
10443 if (lr->edges) {
10444 struct live_range_edge *entry;
10445 printf(" edges:");
10446 for(entry = lr->edges; entry; entry = entry->next) {
10447 printf(" %-10p", entry->node->def);
10448 }
10449 printf("\n");
10450 }
10451 if (triple_is_branch(ins)) {
10452 printf("\n");
10453 }
10454 return ins;
10455}
10456
10457#if DEBUG_COLOR_GRAPH > 1
10458#define cgdebug_printf(...) fprintf(stdout, __VA_ARGS__)
10459#define cgdebug_flush() fflush(stdout)
10460#elif DEBUG_COLOR_GRAPH == 1
10461#define cgdebug_printf(...) fprintf(stderr, __VA_ARGS__)
10462#define cgdebug_flush() fflush(stderr)
10463#else
10464#define cgdebug_printf(...)
10465#define cgdebug_flush()
10466#endif
10467
10468static void select_free_color(struct compile_state *state,
10469 struct reg_state *rstate, struct live_range *range)
10470{
10471 struct triple_set *entry;
10472 struct live_range *phi;
10473 struct live_range_edge *edge;
10474 char used[MAX_REGISTERS];
10475 struct triple **expr;
10476
10477 /* If a color is already assigned don't change it */
10478 if (range->color != REG_UNSET) {
10479 return;
10480 }
10481 /* Instead of doing just the trivial color select here I try
10482 * a few extra things because a good color selection will help reduce
10483 * copies.
10484 */
10485
10486 /* Find the registers currently in use */
10487 memset(used, 0, sizeof(used));
10488 for(edge = range->edges; edge; edge = edge->next) {
10489 if (edge->node->color == REG_UNSET) {
10490 continue;
10491 }
10492 reg_fill_used(state, used, edge->node->color);
10493 }
10494#if DEBUG_COLOR_GRAPH > 1
10495 {
10496 int i;
10497 i = 0;
10498 for(edge = range->edges; edge; edge = edge->next) {
10499 i++;
10500 }
10501 cgdebug_printf("\n%s edges: %d @%s:%d.%d\n",
10502 tops(range->def->op), i,
10503 range->def->filename, range->def->line, range->def->col);
10504 for(i = 0; i < MAX_REGISTERS; i++) {
10505 if (used[i]) {
10506 cgdebug_printf("used: %s\n",
10507 arch_reg_str(i));
10508 }
10509 }
10510 }
10511#endif
10512
10513 /* If I feed into an expression reuse it's color.
10514 * This should help remove copies in the case of 2 register instructions
10515 * and phi functions.
10516 */
10517 phi = 0;
10518 entry = range->def->use;
10519 for(;(range->color == REG_UNSET) && entry; entry = entry->next) {
10520 struct live_range *lr;
10521 lr = &rstate->lr[entry->member->id];
10522 if (entry->member->id == 0) {
10523 continue;
10524 }
10525 if (!phi && (lr->def->op == OP_PHI) &&
10526 !interfere(rstate, range, lr)) {
10527 phi = lr;
10528 }
10529 if ((lr->color == REG_UNSET) ||
10530 ((lr->classes & range->classes) == 0) ||
10531 (used[lr->color])) {
10532 continue;
10533 }
10534 if (interfere(rstate, range, lr)) {
10535 continue;
10536 }
10537 range->color = lr->color;
10538 }
10539 /* If I feed into a phi function reuse it's color of the color
10540 * of something else that feeds into the phi function.
10541 */
10542 if (phi) {
10543 if (phi->color != REG_UNSET) {
10544 if (used[phi->color]) {
10545 range->color = phi->color;
10546 }
10547 }
10548 else {
10549 expr = triple_rhs(state, phi->def, 0);
10550 for(; expr; expr = triple_rhs(state, phi->def, expr)) {
10551 struct live_range *lr;
10552 lr = &rstate->lr[(*expr)->id];
10553 if ((lr->color == REG_UNSET) ||
10554 ((lr->classes & range->classes) == 0) ||
10555 (used[lr->color])) {
10556 continue;
10557 }
10558 if (interfere(rstate, range, lr)) {
10559 continue;
10560 }
10561 range->color = lr->color;
10562 }
10563 }
10564 }
10565 /* If I don't interfere with a rhs node reuse it's color */
10566 if (range->color == REG_UNSET) {
10567 expr = triple_rhs(state, range->def, 0);
10568 for(; expr; expr = triple_rhs(state, range->def, expr)) {
10569 struct live_range *lr;
10570 lr = &rstate->lr[(*expr)->id];
10571 if ((lr->color == -1) ||
10572 ((lr->classes & range->classes) == 0) ||
10573 (used[lr->color])) {
10574 continue;
10575 }
10576 if (interfere(rstate, range, lr)) {
10577 continue;
10578 }
10579 range->color = lr->color;
10580 break;
10581 }
10582 }
10583 /* If I have not opportunitically picked a useful color
10584 * pick the first color that is free.
10585 */
10586 if (range->color == REG_UNSET) {
10587 range->color =
10588 arch_select_free_register(state, used, range->classes);
10589 }
10590 if (range->color == REG_UNSET) {
10591 int i;
10592 for(edge = range->edges; edge; edge = edge->next) {
10593 if (edge->node->color == REG_UNSET) {
10594 continue;
10595 }
10596 warning(state, edge->node->def, "reg %s",
10597 arch_reg_str(edge->node->color));
10598 }
10599 warning(state, range->def, "classes: %x",
10600 range->classes);
10601 for(i = 0; i < MAX_REGISTERS; i++) {
10602 if (used[i]) {
10603 warning(state, range->def, "used: %s",
10604 arch_reg_str(i));
10605 }
10606 }
10607#if DEBUG_COLOR_GRAPH < 2
10608 error(state, range->def, "too few registers");
10609#else
10610 internal_error(state, range->def, "too few registers");
10611#endif
10612 }
10613 range->classes = arch_reg_regcm(state, range->color);
10614 return;
10615}
10616
10617static void color_graph(struct compile_state *state, struct reg_state *rstate)
10618{
10619 struct live_range_edge *edge;
10620 struct live_range *range;
10621 if (rstate->low) {
10622 cgdebug_printf("Lo: ");
10623 range = rstate->low;
10624 if (*range->group_prev != range) {
10625 internal_error(state, 0, "lo: *prev != range?");
10626 }
10627 *range->group_prev = range->group_next;
10628 if (range->group_next) {
10629 range->group_next->group_prev = range->group_prev;
10630 }
10631 if (&range->group_next == rstate->low_tail) {
10632 rstate->low_tail = range->group_prev;
10633 }
10634 if (rstate->low == range) {
10635 internal_error(state, 0, "low: next != prev?");
10636 }
10637 }
10638 else if (rstate->high) {
10639 cgdebug_printf("Hi: ");
10640 range = rstate->high;
10641 if (*range->group_prev != range) {
10642 internal_error(state, 0, "hi: *prev != range?");
10643 }
10644 *range->group_prev = range->group_next;
10645 if (range->group_next) {
10646 range->group_next->group_prev = range->group_prev;
10647 }
10648 if (&range->group_next == rstate->high_tail) {
10649 rstate->high_tail = range->group_prev;
10650 }
10651 if (rstate->high == range) {
10652 internal_error(state, 0, "high: next != prev?");
10653 }
10654 }
10655 else {
10656 return;
10657 }
10658 cgdebug_printf(" %d\n", range - rstate->lr);
10659 range->group_prev = 0;
10660 for(edge = range->edges; edge; edge = edge->next) {
10661 struct live_range *node;
10662 node = edge->node;
10663 /* Move nodes from the high to the low list */
10664 if (node->group_prev && (node->color == REG_UNSET) &&
10665 (node->degree == regc_max_size(state, node->classes))) {
10666 if (*node->group_prev != node) {
10667 internal_error(state, 0, "move: *prev != node?");
10668 }
10669 *node->group_prev = node->group_next;
10670 if (node->group_next) {
10671 node->group_next->group_prev = node->group_prev;
10672 }
10673 if (&node->group_next == rstate->high_tail) {
10674 rstate->high_tail = node->group_prev;
10675 }
10676 cgdebug_printf("Moving...%d to low\n", node - rstate->lr);
10677 node->group_prev = rstate->low_tail;
10678 node->group_next = 0;
10679 *rstate->low_tail = node;
10680 rstate->low_tail = &node->group_next;
10681 if (*node->group_prev != node) {
10682 internal_error(state, 0, "move2: *prev != node?");
10683 }
10684 }
10685 node->degree -= 1;
10686 }
10687 color_graph(state, rstate);
10688 cgdebug_printf("Coloring %d @%s:%d.%d:",
10689 range - rstate->lr,
10690 range->def->filename, range->def->line, range->def->col);
10691 cgdebug_flush();
10692 select_free_color(state, rstate, range);
10693 if (range->color == -1) {
10694 internal_error(state, range->def, "select_free_color did not?");
10695 }
10696 cgdebug_printf(" %s\n", arch_reg_str(range->color));
10697}
10698
10699static void color_triples(struct compile_state *state, struct reg_state *rstate)
10700{
10701 struct live_range *lr;
10702 struct triple *first, *triple;
10703 first = state->main_function->left;
10704 triple = first;
10705 do {
10706 if ((triple->id < 0) || (triple->id > rstate->ranges)) {
10707 internal_error(state, triple,
10708 "triple without a live range");
10709 }
10710 lr = &rstate->lr[triple->id];
10711 triple->id = MK_REG_ID(lr->color, 0);
10712 triple = triple->next;
10713 } while (triple != first);
10714}
10715
10716static void print_interference_block(
10717 struct compile_state *state, struct block *block, void *arg)
10718
10719{
10720 struct reg_state *rstate = arg;
10721 struct reg_block *rb;
10722 struct triple *ptr;
10723 int phi_present;
10724 int done;
10725 rb = &rstate->blocks[block->vertex];
10726
10727 printf("\nblock: %p (%d), %p<-%p %p<-%p\n",
10728 block,
10729 block->vertex,
10730 block->left,
10731 block->left && block->left->use?block->left->use->member : 0,
10732 block->right,
10733 block->right && block->right->use?block->right->use->member : 0);
10734 if (rb->in) {
10735 struct triple_reg_set *in_set;
10736 printf(" in:");
10737 for(in_set = rb->in; in_set; in_set = in_set->next) {
10738 printf(" %-10p", in_set->member);
10739 }
10740 printf("\n");
10741 }
10742 phi_present = 0;
10743 for(done = 0, ptr = block->first; !done; ptr = ptr->next) {
10744 done = (ptr == block->last);
10745 if (ptr->op == OP_PHI) {
10746 phi_present = 1;
10747 break;
10748 }
10749 }
10750 if (phi_present) {
10751 int edge;
10752 for(edge = 0; edge < block->users; edge++) {
10753 printf(" in(%d):", edge);
10754 for(done = 0, ptr = block->first; !done; ptr = ptr->next) {
10755 struct triple **slot;
10756 done = (ptr == block->last);
10757 if (ptr->op != OP_PHI) {
10758 continue;
10759 }
10760 slot = (struct triple **)(ptr->left);
10761 printf(" %-10p", slot[edge]);
10762 }
10763 printf("\n");
10764 }
10765 }
10766 if (block->first->op == OP_LABEL) {
10767 printf("%p:\n", block->first);
10768 }
10769 for(done = 0, ptr = block->first; !done; ptr = ptr->next) {
10770 struct triple_set *user;
10771 struct live_range *lr;
10772 int op;
10773 op = ptr->op;
10774 done = (ptr == block->last);
10775 lr = &rstate->lr[ptr->id];
10776
10777 if (!IS_CONST_OP(op)) {
10778 if (ptr->u.block != block) {
10779 internal_error(state, ptr,
10780 "Wrong block pointer: %p",
10781 ptr->u.block);
10782 }
10783 }
10784 if (op == OP_ADECL) {
10785 for(user = ptr->use; user; user = user->next) {
10786 struct live_range *lr;
10787 lr = &rstate->lr[user->member->id];
10788 if (!user->member->u.block) {
10789 internal_error(state, user->member,
10790 "Use %p not in a block?",
10791 user->member);
10792 }
10793
10794 }
10795 }
10796 if (op == OP_INTCONST) {
10797 printf("(%p) %3d %-7s %08lx @ %s:%d.%d\n",
10798 ptr, lr->color, tops(ptr->op), ptr->u.cval,
10799 ptr->filename, ptr->line, ptr->col);
10800 }
10801 else if (op == OP_PHI) {
10802 struct triple **slot;
10803 struct block *block;
10804 int edge;
10805 block = ptr->u.block;
10806 slot = (struct triple **)(ptr->left);
10807 printf("(%p) %3d %-7s",
10808 ptr, lr->color, tops(ptr->op));
10809 for(edge = 0; edge < block->users; edge++) {
10810 printf(" %-10p", slot[edge]);
10811 }
10812 printf(" @%s:%d.%d\n",
10813 ptr->filename, ptr->line, ptr->col);
10814 }
10815 else {
10816 printf("(%p) %3d %-7s %-10p %-10p @ %s:%d.%d\n",
10817 ptr, lr->color, tops(ptr->op), ptr->left, ptr->right,
10818 ptr->filename, ptr->line, ptr->col);
10819 }
10820 if (lr->edges > 0) {
10821 struct live_range_edge *edge;
10822 printf(" ");
10823 for(edge = lr->edges; edge; edge = edge->next) {
10824 printf(" %-10p", edge->node->def);
10825 }
10826 printf("\n");
10827 }
10828 /* Do a bunch of sanity checks */
10829 valid_op(state, ptr);
10830 if ((ptr->id < 0) || (ptr->id > rstate->ranges)) {
10831 internal_error(state, ptr, "Invalid triple id: %d",
10832 ptr->id);
10833 }
10834 for(user = ptr->use; user; user = user->next) {
10835 struct triple *use;
10836 struct live_range *ulr;
10837 use = user->member;
10838 valid_op(state, use);
10839 if ((use->id < 0) || (use->id > rstate->ranges)) {
10840 internal_error(state, use, "Invalid triple id: %d",
10841 use->id);
10842 }
10843 ulr = &rstate->lr[user->member->id];
10844 if (!IS_CONST_OP(user->member->op) &&
10845 !user->member->u.block) {
10846 internal_error(state, user->member,
10847 "Use %p not in a block?",
10848 user->member);
10849 }
10850 }
10851 }
10852 if (rb->out) {
10853 struct triple_reg_set *out_set;
10854 printf(" out:");
10855 for(out_set = rb->out; out_set; out_set = out_set->next) {
10856 printf(" %-10p", out_set->member);
10857 }
10858 printf("\n");
10859 }
10860 printf("\n");
10861}
10862
10863static struct live_range *merge_sort_lr(
10864 struct live_range *first, struct live_range *last)
10865{
10866 struct live_range *mid, *join, **join_tail, *pick;
10867 size_t size;
10868 size = (last - first) + 1;
10869 if (size >= 2) {
10870 mid = first + size/2;
10871 first = merge_sort_lr(first, mid -1);
10872 mid = merge_sort_lr(mid, last);
10873
10874 join = 0;
10875 join_tail = &join;
10876 /* merge the two lists */
10877 while(first && mid) {
10878 if (first->degree <= mid->degree) {
10879 pick = first;
10880 first = first->group_next;
10881 if (first) {
10882 first->group_prev = 0;
10883 }
10884 }
10885 else {
10886 pick = mid;
10887 mid = mid->group_next;
10888 if (mid) {
10889 mid->group_prev = 0;
10890 }
10891 }
10892 pick->group_next = 0;
10893 pick->group_prev = join_tail;
10894 *join_tail = pick;
10895 join_tail = &pick->group_next;
10896 }
10897 /* Splice the remaining list */
10898 pick = (first)? first : mid;
10899 *join_tail = pick;
10900 pick->group_prev = join_tail;
10901 }
10902 else {
10903 if (!first->def) {
10904 first = 0;
10905 }
10906 join = first;
10907 }
10908 return join;
10909}
10910
10911static void allocate_registers(struct compile_state *state)
10912{
10913 struct reg_state rstate;
10914 struct live_range **point, **next;
10915 int i;
10916
10917 /* Clear out the reg_state */
10918 memset(&rstate, 0, sizeof(rstate));
10919
10920 /* Compute the variable lifetimes */
10921 rstate.blocks = compute_variable_lifetimes(state);
10922
10923 /* Allocate and initialize the live ranges */
10924 initialize_live_ranges(state, &rstate);
10925
10926 /* Compute the interference graph */
10927 walk_variable_lifetimes(
10928 state, rstate.blocks, graph_ins, &rstate);
10929
10930 /* Display the interference graph if desired */
10931 if (state->debug & DEBUG_INTERFERENCE) {
10932 printf("\nlive variables by block\n");
10933 walk_blocks(state, print_interference_block, &rstate);
10934 printf("\nlive variables by instruction\n");
10935 walk_variable_lifetimes(
10936 state, rstate.blocks,
10937 print_interference_ins, &rstate);
10938 }
10939
10940 /* Do not perform coalescing! It is a neat idea but it limits what
10941 * we can do later. It has no benefits that decrease register pressure.
10942 * It only decreases instruction count.
10943 *
10944 * It might be worth testing this reducing the number of
10945 * live_ragnes as opposed to splitting them seems to help.
10946 */
10947
10948 /* Build the groups low and high. But with the nodes
10949 * first sorted by degree order.
10950 */
10951 rstate.low_tail = &rstate.low;
10952 rstate.high_tail = &rstate.high;
10953 rstate.high = merge_sort_lr(&rstate.lr[1], &rstate.lr[rstate.ranges]);
10954 rstate.high->group_prev = &rstate.high;
10955 for(point = &rstate.high; *point; point = &(*point)->group_next)
10956 ;
10957 rstate.high_tail = point;
10958 /* Walk through the high list and move everything that needs
10959 * to be onto low.
10960 */
10961 for(point = &rstate.high; *point; point = next) {
10962 struct live_range *range;
10963 next = &(*point)->group_next;
10964 range = *point;
10965
10966 /* If it has a low degree or it already has a color
10967 * place the node in low.
10968 */
10969 if ((range->degree < regc_max_size(state, range->classes)) ||
10970 (range->color != REG_UNSET)) {
10971 cgdebug_printf("Lo: %5d degree %5d%s\n",
10972 range - rstate.lr, range->degree,
10973 (range->color != REG_UNSET) ? " (colored)": "");
10974 *range->group_prev = range->group_next;
10975 if (range->group_next) {
10976 range->group_next->group_prev = range->group_prev;
10977 }
10978 if (&range->group_next == rstate.high_tail) {
10979 rstate.high_tail = range->group_prev;
10980 }
10981 range->group_prev = rstate.low_tail;
10982 range->group_next = 0;
10983 *rstate.low_tail = range;
10984 rstate.low_tail = &range->group_next;
10985 next = point;
10986 }
10987 else {
10988 cgdebug_printf("hi: %5d degree %5d%s\n",
10989 range - rstate.lr, range->degree,
10990 (range->color != REG_UNSET) ? " (colored)": "");
10991 }
10992
10993 }
10994 /* Color the live_ranges */
10995 color_graph(state, &rstate);
10996
10997 /* Move the colors from the graph to the triples */
10998 color_triples(state, &rstate);
10999
11000 /* Free the edges on each node */
11001 for(i = 1; i <= rstate.ranges; i++) {
11002 remove_live_edges(&rstate, &rstate.lr[i]);
11003 }
11004 xfree(rstate.lr);
11005
11006 /* Free the variable lifetime information */
11007 free_variable_lifetimes(state, rstate.blocks);
11008
11009}
11010
11011/* Sparce Conditional Constant Propogation
11012 * =========================================
11013 */
11014struct ssa_edge;
11015struct flow_block;
11016struct lattice_node {
11017 struct triple *def;
11018 struct ssa_edge *out;
11019 struct flow_block *fblock;
11020 struct triple *val;
11021 /* lattice high val && !is_const(val)
11022 * lattice const is_const(val)
11023 * lattice low val == 0
11024 */
11025 struct triple scratch;
11026};
11027struct ssa_edge {
11028 struct lattice_node *src;
11029 struct lattice_node *dst;
11030 struct ssa_edge *work_next;
11031 struct ssa_edge *work_prev;
11032 struct ssa_edge *out_next;
11033};
11034struct flow_edge {
11035 struct flow_block *src;
11036 struct flow_block *dst;
11037 struct flow_edge *work_next;
11038 struct flow_edge *work_prev;
11039 struct flow_edge *in_next;
11040 struct flow_edge *out_next;
11041 int executable;
11042};
11043struct flow_block {
11044 struct block *block;
11045 struct flow_edge *in;
11046 struct flow_edge *out;
11047 struct flow_edge left, right;
11048};
11049
11050struct scc_state {
11051 struct lattice_node *lattice;
11052 struct ssa_edge *ssa_edges;
11053 struct flow_block *flow_blocks;
11054 struct flow_edge *flow_work_list;
11055 struct ssa_edge *ssa_work_list;
11056};
11057
11058
11059static void scc_add_fedge(struct compile_state *state, struct scc_state *scc,
11060 struct flow_edge *fedge)
11061{
11062 if (!scc->flow_work_list) {
11063 scc->flow_work_list = fedge;
11064 fedge->work_next = fedge->work_prev = fedge;
11065 }
11066 else {
11067 struct flow_edge *ftail;
11068 ftail = scc->flow_work_list->work_prev;
11069 fedge->work_next = ftail->work_next;
11070 fedge->work_prev = ftail;
11071 fedge->work_next->work_prev = fedge;
11072 fedge->work_prev->work_next = fedge;
11073 }
11074}
11075
11076static struct flow_edge *scc_next_fedge(
11077 struct compile_state *state, struct scc_state *scc)
11078{
11079 struct flow_edge *fedge;
11080 fedge = scc->flow_work_list;
11081 if (fedge) {
11082 fedge->work_next->work_prev = fedge->work_prev;
11083 fedge->work_prev->work_next = fedge->work_next;
11084 if (fedge->work_next != fedge) {
11085 scc->flow_work_list = fedge->work_next;
11086 } else {
11087 scc->flow_work_list = 0;
11088 }
11089 }
11090 return fedge;
11091}
11092
11093static void scc_add_sedge(struct compile_state *state, struct scc_state *scc,
11094 struct ssa_edge *sedge)
11095{
11096 if (!scc->ssa_work_list) {
11097 scc->ssa_work_list = sedge;
11098 sedge->work_next = sedge->work_prev = sedge;
11099 }
11100 else {
11101 struct ssa_edge *stail;
11102 stail = scc->ssa_work_list->work_prev;
11103 sedge->work_next = stail->work_next;
11104 sedge->work_prev = stail;
11105 sedge->work_next->work_prev = sedge;
11106 sedge->work_prev->work_next = sedge;
11107 }
11108}
11109
11110static struct ssa_edge *scc_next_sedge(
11111 struct compile_state *state, struct scc_state *scc)
11112{
11113 struct ssa_edge *sedge;
11114 sedge = scc->ssa_work_list;
11115 if (sedge) {
11116 sedge->work_next->work_prev = sedge->work_prev;
11117 sedge->work_prev->work_next = sedge->work_next;
11118 if (sedge->work_next != sedge) {
11119 scc->ssa_work_list = sedge->work_next;
11120 } else {
11121 scc->ssa_work_list = 0;
11122 }
11123 }
11124 return sedge;
11125}
11126
11127static void initialize_scc_state(
11128 struct compile_state *state, struct scc_state *scc)
11129{
11130 int ins_count, ssa_edge_count;
11131 int ins_index, ssa_edge_index, fblock_index;
11132 struct triple *first, *ins;
11133 struct block *block;
11134 struct flow_block *fblock;
11135
11136 memset(scc, 0, sizeof(*scc));
11137
11138 /* Inialize pass zero find out how much memory we need */
11139 first = state->main_function->left;
11140 ins = first;
11141 ins_count = ssa_edge_count = 0;
11142 do {
11143 struct triple_set *edge;
11144 ins_count += 1;
11145 for(edge = ins->use; edge; edge = edge->next) {
11146 ssa_edge_count++;
11147 }
11148 ins = ins->next;
11149 } while(ins != first);
11150#if DEBUG_SCC
11151 fprintf(stderr, "ins_count: %d ssa_edge_count: %d vertex_count: %d\n",
11152 ins_count, ssa_edge_count, state->last_vertex);
11153#endif
11154 scc->lattice =
11155 xcmalloc(sizeof(*scc->lattice)*(ins_count + 1), "lattice");
11156 scc->ssa_edges =
11157 xcmalloc(sizeof(*scc->ssa_edges)*(ssa_edge_count + 1), "ssa_edges");
11158 scc->flow_blocks =
11159 xcmalloc(sizeof(*scc->flow_blocks)*(state->last_vertex + 1),
11160 "flow_blocks");
11161
11162 /* Initialize pass one collect up the nodes */
11163 fblock = 0;
11164 block = 0;
11165 ins_index = ssa_edge_index = fblock_index = 0;
11166 ins = first;
11167 do {
11168 ins->id = 0;
11169 if ((ins->op == OP_LABEL) && (block != ins->u.block)) {
11170 block = ins->u.block;
11171 if (!block) {
11172 internal_error(state, ins, "label without block");
11173 }
11174 fblock_index += 1;
11175 block->vertex = fblock_index;
11176 fblock = &scc->flow_blocks[fblock_index];
11177 fblock->block = block;
11178 }
11179 {
11180 struct lattice_node *lnode;
11181 ins_index += 1;
11182 ins->id = ins_index;
11183 lnode = &scc->lattice[ins_index];
11184 lnode->def = ins;
11185 lnode->out = 0;
11186 lnode->fblock = fblock;
11187 lnode->val = ins; /* LATTICE HIGH */
11188 }
11189 ins = ins->next;
11190 } while(ins != first);
11191 /* Initialize pass two collect up the edges */
11192 block = 0;
11193 fblock = 0;
11194 ins = first;
11195 do {
11196 if ((ins->op == OP_LABEL) && (block != ins->u.block)) {
11197 struct flow_edge *fedge, **ftail;
11198 struct block_set *bedge;
11199 block = ins->u.block;
11200 fblock = &scc->flow_blocks[block->vertex];
11201 fblock->in = 0;
11202 fblock->out = 0;
11203 ftail = &fblock->out;
11204 if (block->left) {
11205 fblock->left.dst = &scc->flow_blocks[block->left->vertex];
11206 if (fblock->left.dst->block != block->left) {
11207 internal_error(state, 0, "block mismatch");
11208 }
11209 fblock->left.out_next = 0;
11210 *ftail = &fblock->left;
11211 ftail = &fblock->left.out_next;
11212 }
11213 if (block->right) {
11214 fblock->right.dst = &scc->flow_blocks[block->right->vertex];
11215 if (fblock->right.dst->block != block->right) {
11216 internal_error(state, 0, "block mismatch");
11217 }
11218 fblock->right.out_next = 0;
11219 *ftail = &fblock->right;
11220 ftail = &fblock->right.out_next;
11221 }
11222 for(fedge = fblock->out; fedge; fedge = fedge->out_next) {
11223 fedge->src = fblock;
11224 fedge->work_next = fedge->work_prev = fedge;
11225 fedge->executable = 0;
11226 }
11227 ftail = &fblock->in;
11228 for(bedge = block->use; bedge; bedge = bedge->next) {
11229 struct block *src_block;
11230 struct flow_block *sfblock;
11231 struct flow_edge *sfedge;
11232 src_block = bedge->member;
11233 sfblock = &scc->flow_blocks[src_block->vertex];
11234 sfedge = 0;
11235 if (src_block->left == block) {
11236 sfedge = &sfblock->left;
11237 } else {
11238 sfedge = &sfblock->right;
11239 }
11240 *ftail = sfedge;
11241 ftail = &sfedge->in_next;
11242 sfedge->in_next = 0;
11243 }
11244 }
11245 {
11246 struct triple_set *edge;
11247 struct ssa_edge **stail;
11248 struct lattice_node *lnode;
11249 lnode = &scc->lattice[ins->id];
11250 lnode->out = 0;
11251 stail = &lnode->out;
11252 for(edge = ins->use; edge; edge = edge->next) {
11253 struct ssa_edge *sedge;
11254 ssa_edge_index += 1;
11255 sedge = &scc->ssa_edges[ssa_edge_index];
11256 *stail = sedge;
11257 stail = &sedge->out_next;
11258 sedge->src = lnode;
11259 sedge->dst = &scc->lattice[edge->member->id];
11260 sedge->work_next = sedge->work_prev = sedge;
11261 sedge->out_next = 0;
11262 }
11263 }
11264 ins = ins->next;
11265 } while(ins != first);
11266 /* Setup a dummy block 0 as a node above the start node */
11267 {
11268 struct flow_block *fblock, *dst;
11269 struct flow_edge *fedge;
11270 fblock = &scc->flow_blocks[0];
11271 fblock->block = 0;
11272 fblock->in = 0;
11273 fblock->out = &fblock->left;
11274 dst = &scc->flow_blocks[state->first_block->vertex];
11275 fedge = &fblock->left;
11276 fedge->src = fblock;
11277 fedge->dst = dst;
11278 fedge->work_next = fedge;
11279 fedge->work_prev = fedge;
11280 fedge->in_next = fedge->dst->in;
11281 fedge->out_next = 0;
11282 fedge->executable = 0;
11283 fedge->dst->in = fedge;
11284
11285 /* Initialize the work lists */
11286 scc->flow_work_list = 0;
11287 scc->ssa_work_list = 0;
11288 scc_add_fedge(state, scc, fedge);
11289 }
11290#if DEBUG_SCC
11291 fprintf(stderr, "ins_index: %d ssa_edge_index: %d fblock_index: %d\n",
11292 ins_index, ssa_edge_index, fblock_index);
11293#endif
11294}
11295
11296
11297static void free_scc_state(
11298 struct compile_state *state, struct scc_state *scc)
11299{
11300 xfree(scc->flow_blocks);
11301 xfree(scc->ssa_edges);
11302 xfree(scc->lattice);
11303}
11304
11305static struct lattice_node *triple_to_lattice(
11306 struct compile_state *state, struct scc_state *scc, struct triple *ins)
11307{
11308 if (ins->id <= 0) {
11309 internal_error(state, ins, "bad id");
11310 }
11311 return &scc->lattice[ins->id];
11312}
11313
11314static void scc_visit_phi(struct compile_state *state, struct scc_state *scc,
11315 struct lattice_node *lnode)
11316{
11317 struct lattice_node *tmp;
11318 struct triple **slot;
11319 struct flow_edge *fedge;
11320 int index;
11321 if (lnode->def->op != OP_PHI) {
11322 internal_error(state, lnode->def, "not phi");
11323 }
11324 /* default to lattice high */
11325 lnode->val = lnode->def;
11326 slot = (struct triple **)lnode->def->left;
11327 index = 0;
11328 for(fedge = lnode->fblock->in; fedge; index++, fedge = fedge->in_next) {
11329 if (!fedge->executable) {
11330 continue;
11331 }
11332 if (!slot[index]) {
11333 internal_error(state, lnode->def, "no phi value");
11334 }
11335 tmp = triple_to_lattice(state, scc, slot[index]);
11336 /* meet(X, lattice low) = lattice low */
11337 if (!tmp->val) {
11338 lnode->val = 0;
11339 }
11340 /* meet(X, lattice high) = X */
11341 else if (!tmp->val) {
11342 lnode->val = lnode->val;
11343 }
11344 /* meet(lattice high, X) = X */
11345 else if (!is_const(lnode->val)) {
11346 lnode->val = tmp->val;
11347 }
11348 /* meet(const, const) = const or lattice low */
11349 else if (!constants_equal(state, lnode->val, tmp->val)) {
11350 lnode->val = 0;
11351 }
11352 if (!lnode->val) {
11353 break;
11354 }
11355 }
11356 /* Do I need to update any work lists here? */
11357#if DEBUG_SCC
11358 fprintf(stderr, "phi: %d -> %s\n",
11359 lnode->def->id,
11360 (!lnode->val)? "lo": is_const(lnode->val)? "const": "hi");
11361#endif
11362}
11363
11364static int compute_lnode_val(struct compile_state *state, struct scc_state *scc,
11365 struct lattice_node *lnode)
11366{
11367 int changed;
11368 struct triple old_buf, *old;
11369 struct triple **dexpr, **vexpr;
11370
11371 /* Store the original value */
11372 if (lnode->val) {
11373 old = &old_buf;
11374 memcpy(old, lnode->val, sizeof(*old));
11375 } else {
11376 old = 0;
11377 }
11378 /* Reinitialize the value */
11379 memset(&lnode->scratch, 0, sizeof(lnode->scratch));
11380 lnode->val = &lnode->scratch;
11381 lnode->val->next = &lnode->scratch;
11382 lnode->val->prev = &lnode->scratch;
11383 lnode->val->use = 0;
11384 lnode->val->type = lnode->def->type;
11385 lnode->val->op = lnode->def->op;
11386 lnode->val->left = 0;
11387 lnode->val->right = 0;
11388 lnode->val->filename = lnode->def->filename;
11389 lnode->val->line = lnode->def->line;
11390 lnode->val->col = lnode->def->col;
11391 if (lnode->def->op != OP_STORE) {
11392 check_lhs(state, lnode->def);
11393 }
11394 dexpr = triple_rhs(state, lnode->def, 0);
11395 vexpr = triple_rhs(state, lnode->val, 0);
11396 while(dexpr && vexpr) {
11397 struct lattice_node *tmp;
11398 tmp = triple_to_lattice(state, scc, *dexpr);
11399 *vexpr = (tmp->val)? tmp->val : tmp->def;
11400 dexpr = triple_rhs(state, lnode->def, dexpr);
11401 vexpr = triple_rhs(state, lnode->val, vexpr);
11402 }
11403 if (is_const(lnode->val)) {
11404 memcpy(&lnode->val->u, &lnode->def->u, sizeof(lnode->def->u));
11405 }
11406 else if (lnode->val->op == OP_BRANCH) {
11407 lnode->val->left = lnode->def->left;
11408 lnode->val->next = lnode->def->next;
11409 }
11410 else if (lnode->val->op == OP_SDECL) {
11411 lnode->val->left = lnode->def->left;
11412 }
11413 /* Recompute the value */
11414#warning "FIXME see if simplify does anything bad"
11415 /* So far it looks like only the strength reduction
11416 * optimization are things I need to worry about.
11417 */
11418 simplify(state, lnode->val);
11419 /* Cleanup my value */
11420 if (lnode->scratch.use) {
11421 internal_error(state, lnode->def, "scratch used?");
11422 }
11423 if ((lnode->scratch.prev != &lnode->scratch) ||
11424 ((lnode->scratch.next != &lnode->scratch) &&
11425 ((lnode->def->op != OP_BRANCH) ||
11426 (lnode->scratch.next != lnode->def->next)))) {
11427 internal_error(state, lnode->def, "scratch in list?");
11428 }
11429 /* undo any uses... */
11430 vexpr = triple_rhs(state, lnode->val, 0);
11431 for(;vexpr;vexpr = triple_rhs(state, lnode->val, vexpr)) {
11432 unuse_triple(*vexpr, lnode->val);
11433 }
11434 if (!is_const(lnode->val)) {
11435 dexpr = triple_rhs(state, lnode->def, 0);
11436 for(;dexpr;dexpr = triple_rhs(state, lnode->def, dexpr)) {
11437 struct lattice_node *tmp;
11438 tmp = triple_to_lattice(state, scc, *dexpr);
11439 if (!tmp->val) {
11440 lnode->val = 0;
11441 }
11442 }
11443 }
11444 if (lnode->val &&
11445 (lnode->val->op == lnode->def->op) &&
11446 (lnode->val->left == lnode->def->left) &&
11447 (lnode->val->right == lnode->def->right) &&
11448 (((memcmp(&lnode->val->u, &lnode->def->u, sizeof(lnode->def->u)) == 0) &&
11449 is_const(lnode->val)) || !is_const(lnode->val))) {
11450 lnode->val = lnode->def;
11451 }
11452 /* Find the cases that are always lattice lo */
11453 if (lnode->val &&
11454 triple_is_def(lnode->val) &&
11455 !triple_is_pure(state, lnode->val)) {
11456 lnode->val = 0;
11457 }
11458#if 1
11459 if (lnode->val &&
11460 (lnode->val->op == OP_SDECL) &&
11461 (lnode->val != lnode->def)) {
11462 internal_error(state, lnode->def, "bad sdecl");
11463 }
11464#endif
11465 /* See if the lattice value has changed */
11466 changed = 1;
11467 if (!old && !lnode->val) {
11468 changed = 0;
11469 }
11470 if (changed && lnode->val && !is_const(lnode->val)) {
11471 changed = 0;
11472 }
11473 if (changed &&
11474 lnode->val && old &&
11475 (lnode->val->op == old->op) &&
11476 (lnode->val->left == old->left) &&
11477 (lnode->val->right == old->right) &&
11478 (memcmp(&lnode->val->u, &old->u, sizeof(old->u)) == 0)) {
11479 changed = 0;
11480 }
11481 return changed;
11482
11483}
11484static void scc_visit_branch(struct compile_state *state, struct scc_state *scc,
11485 struct lattice_node *lnode)
11486{
11487 struct lattice_node *cond;
11488#if DEBUG_SCC
11489 {
11490 struct flow_edge *fedge;
11491 fprintf(stderr, "branch: %d (",
11492 lnode->def->id);
11493
11494 for(fedge = lnode->fblock->out; fedge; fedge = fedge->out_next) {
11495 fprintf(stderr, " %d", fedge->dst->block->vertex);
11496 }
11497 fprintf(stderr, " )");
11498 if (lnode->def->right) {
11499 fprintf(stderr, " <- %d",
11500 lnode->def->right->id);
11501 }
11502 fprintf(stderr, "\n");
11503 }
11504#endif
11505 if (lnode->def->op != OP_BRANCH) {
11506 internal_error(state, lnode->def, "not branch");
11507 }
11508 /* This only applies to conditional branches */
11509 if (lnode->def->right == 0) {
11510 return;
11511 }
11512 cond = triple_to_lattice(state, scc, lnode->def->right);
11513 if (cond->val && !is_const(cond->val)) {
11514#warning "FIXME do I need to do something here?"
11515 warning(state, cond->def, "condition not constant?");
11516 return;
11517 }
11518 if (cond->val == 0) {
11519 scc_add_fedge(state, scc, cond->fblock->out);
11520 scc_add_fedge(state, scc, cond->fblock->out->out_next);
11521 }
11522 else if (cond->val->u.cval) {
11523 scc_add_fedge(state, scc, cond->fblock->out->out_next);
11524
11525 } else {
11526 scc_add_fedge(state, scc, cond->fblock->out);
11527 }
11528
11529}
11530
11531static void scc_visit_expr(struct compile_state *state, struct scc_state *scc,
11532 struct lattice_node *lnode)
11533{
11534 int changed;
11535
11536 changed = compute_lnode_val(state, scc, lnode);
11537#if DEBUG_SCC
11538 {
11539 struct triple **expr;
11540 fprintf(stderr, "expr: %3d %10s (",
11541 lnode->def->id, tops(lnode->def->op));
11542 expr = triple_rhs(state, lnode->def, 0);
11543 for(;expr;expr = triple_rhs(state, lnode->def, expr)) {
11544 fprintf(stderr, " %d", (*expr)->id);
11545 }
11546 fprintf(stderr, " ) -> %s\n",
11547 (!lnode->val)? "lo": is_const(lnode->val)? "const": "hi");
11548 }
11549#endif
11550 if (lnode->def->op == OP_BRANCH) {
11551 scc_visit_branch(state, scc, lnode);
11552
11553 }
11554 else if (changed) {
11555 struct ssa_edge *sedge;
11556 for(sedge = lnode->out; sedge; sedge = sedge->out_next) {
11557 scc_add_sedge(state, scc, sedge);
11558 }
11559 }
11560}
11561
11562static void scc_writeback_values(
11563 struct compile_state *state, struct scc_state *scc)
11564{
11565 struct triple *first, *ins;
11566 first = state->main_function->left;
11567 ins = first;
11568 do {
11569 struct lattice_node *lnode;
11570 lnode = triple_to_lattice(state, scc, ins);
11571#if DEBUG_SCC
11572 if (lnode->val && !is_const(lnode->val)) {
11573 warning(state, lnode->def,
11574 "lattice node still high?");
11575 }
11576#endif
11577 if (lnode->val && (lnode->val != ins)) {
11578 /* See if it something I know how to write back */
11579 switch(lnode->val->op) {
11580 case OP_INTCONST:
11581 mkconst(state, ins, lnode->val->u.cval);
11582 break;
11583 case OP_ADDRCONST:
11584 mkaddr_const(state, ins,
11585 lnode->val->left, lnode->val->u.cval);
11586 break;
11587 default:
11588 /* By default don't copy the changes,
11589 * recompute them in place instead.
11590 */
11591 simplify(state, ins);
11592 break;
11593 }
11594 }
11595 ins = ins->next;
11596 } while(ins != first);
11597}
11598
11599static void scc_transform(struct compile_state *state)
11600{
11601 struct scc_state scc;
11602
11603 initialize_scc_state(state, &scc);
11604
11605 while(scc.flow_work_list || scc.ssa_work_list) {
11606 struct flow_edge *fedge;
11607 struct ssa_edge *sedge;
11608 struct flow_edge *fptr;
11609 while((fedge = scc_next_fedge(state, &scc))) {
11610 struct block *block;
11611 struct triple *ptr;
11612 struct flow_block *fblock;
11613 int time;
11614 int done;
11615 if (fedge->executable) {
11616 continue;
11617 }
11618 if (!fedge->dst) {
11619 internal_error(state, 0, "fedge without dst");
11620 }
11621 if (!fedge->src) {
11622 internal_error(state, 0, "fedge without src");
11623 }
11624 fedge->executable = 1;
11625 fblock = fedge->dst;
11626 block = fblock->block;
11627 time = 0;
11628 for(fptr = fblock->in; fptr; fptr = fptr->in_next) {
11629 if (fptr->executable) {
11630 time++;
11631 }
11632 }
11633#if DEBUG_SCC
11634 fprintf(stderr, "vertex: %d time: %d\n",
11635 block->vertex, time);
11636
11637#endif
11638 done = 0;
11639 for(ptr = block->first; !done; ptr = ptr->next) {
11640 struct lattice_node *lnode;
11641 done = (ptr == block->last);
11642 lnode = &scc.lattice[ptr->id];
11643 if (ptr->op == OP_PHI) {
11644 scc_visit_phi(state, &scc, lnode);
11645 }
11646 else if (time == 1) {
11647 scc_visit_expr(state, &scc, lnode);
11648 }
11649 }
11650 if (fblock->out && !fblock->out->out_next) {
11651 scc_add_fedge(state, &scc, fblock->out);
11652 }
11653 }
11654 while((sedge = scc_next_sedge(state, &scc))) {
11655 struct lattice_node *lnode;
11656 struct flow_block *fblock;
11657 lnode = sedge->dst;
11658 fblock = lnode->fblock;
11659#if DEBUG_SCC
11660 fprintf(stderr, "sedge: %5d (%5d -> %5d)\n",
11661 sedge - scc.ssa_edges,
11662 sedge->src->def->id,
11663 sedge->dst->def->id);
11664#endif
11665 if (lnode->def->op == OP_PHI) {
11666 scc_visit_phi(state, &scc, lnode);
11667 }
11668 else {
11669 for(fptr = fblock->in; fptr; fptr = fptr->in_next) {
11670 if (fptr->executable) {
11671 break;
11672 }
11673 }
11674 if (fptr) {
11675 scc_visit_expr(state, &scc, lnode);
11676 }
11677 }
11678 }
11679 }
11680
11681 scc_writeback_values(state, &scc);
11682 /* FINISH ME move constants from scratch values into the tree */
11683 free_scc_state(state, &scc);
11684}
11685
11686
11687static void transform_to_arch_instructions(struct compile_state *state);
11688
11689
11690static void optimize(struct compile_state *state)
11691{
11692 if (state->debug & DEBUG_TRIPLES) {
11693 print_triples(state);
11694 }
11695 /* Analize the intermediate code */
11696 setup_basic_blocks(state);
11697 analyze_idominators(state);
11698 analyze_ipdominators(state);
11699 /* Transform the code to ssa form */
11700 transform_to_ssa_form(state);
11701 /* Do strength reduction and simple constant optimizations */
11702 if (state->optimize >= 1) {
11703 simplify_all(state);
11704 }
11705 /* Propogate constants throughout the code */
11706 if (state->optimize >= 2) {
11707 scc_transform(state);
11708 transform_from_ssa_form(state);
11709 free_basic_blocks(state);
11710 setup_basic_blocks(state);
11711 analyze_idominators(state);
11712 analyze_ipdominators(state);
11713 transform_to_ssa_form(state);
11714
11715 }
11716#warning "WISHLIST implement single use constants (least possible register pressure)"
11717#warning "WISHLIST implement induction variable elimination"
11718#warning "WISHLIST implement strength reduction"
11719 /* Select architecture instructions and an initial partial
11720 * coloring based on architecture constraints.
11721 */
11722 transform_to_arch_instructions(state);
11723 if (state->debug & DEBUG_ARCH_CODE) {
11724 printf("After transform_to_arch_instructions\n");
11725 print_blocks(state);
11726 print_control_flow(state);
11727 }
11728 eliminate_inefectual_code(state);
11729 if (state->debug & DEBUG_CODE_ELIMINATION) {
11730 printf("After eliminate_inefectual_code\n");
11731 print_blocks(state);
11732 print_control_flow(state);
11733 }
11734 /* Color all of the variables to see if they will fit in registers */
11735 insert_copies_to_phi(state);
11736 allocate_registers(state);
11737 if (state->debug & DEBUG_INTERMEDIATE_CODE) {
11738 print_blocks(state);
11739 }
11740 if (state->debug & DEBUG_CONTROL_FLOW) {
11741 print_control_flow(state);
11742 }
11743 /* Remove the optimization information.
11744 * This is more to check for memory consistency than to free memory.
11745 */
11746 free_basic_blocks(state);
11747}
11748
11749/* The x86 register classes */
11750#define REGC_FLAGS 0
11751#define REGC_GPR8 1
11752#define REGC_GPR16 2
11753#define REGC_GPR32 3
11754#define REGC_GPR64 4
11755#define REGC_MMX 5
11756#define REGC_XMM 6
11757#define REGC_GPR32_8 7
11758#define REGC_GPR16_8 8
11759#define LAST_REGC REGC_GPR16_8
11760#if LAST_REGC >= MAX_REGC
11761#error "MAX_REGC is to low"
11762#endif
11763
11764/* Register class masks */
11765#define REGCM_FLAGS (1 << REGC_FLAGS)
11766#define REGCM_GPR8 (1 << REGC_GPR8)
11767#define REGCM_GPR16 (1 << REGC_GPR16)
11768#define REGCM_GPR32 (1 << REGC_GPR32)
11769#define REGCM_GPR64 (1 << REGC_GPR64)
11770#define REGCM_MMX (1 << REGC_MMX)
11771#define REGCM_XMM (1 << REGC_XMM)
11772#define REGCM_GPR32_8 (1 << REGC_GPR32_8)
11773#define REGCM_GPR16_8 (1 << REGC_GPR16_8)
11774
11775/* The x86 registers */
11776#define REG_EFLAGS 1
11777#define REGC_FLAGS_FIRST REG_EFLAGS
11778#define REGC_FLAGS_LAST REG_EFLAGS
11779#define REG_AL 2
11780#define REG_BL 3
11781#define REG_CL 4
11782#define REG_DL 5
11783#define REG_AH 6
11784#define REG_BH 7
11785#define REG_CH 8
11786#define REG_DH 9
11787#define REGC_GPR8_FIRST REG_AL
11788#if X86_4_8BIT_GPRS
11789#define REGC_GPR8_LAST REG_DL
11790#else
11791#define REGC_GPR8_LAST REG_DH
11792#endif
11793#define REG_AX 10
11794#define REG_BX 11
11795#define REG_CX 12
11796#define REG_DX 13
11797#define REG_SI 14
11798#define REG_DI 15
11799#define REG_BP 16
11800#define REG_SP 17
11801#define REGC_GPR16_FIRST REG_AX
11802#define REGC_GPR16_LAST REG_SP
11803#define REG_EAX 18
11804#define REG_EBX 19
11805#define REG_ECX 20
11806#define REG_EDX 21
11807#define REG_ESI 22
11808#define REG_EDI 23
11809#define REG_EBP 24
11810#define REG_ESP 25
11811#define REGC_GPR32_FIRST REG_EAX
11812#define REGC_GPR32_LAST REG_ESP
11813#define REG_EDXEAX 26
11814#define REGC_GPR64_FIRST REG_EDXEAX
11815#define REGC_GPR64_LAST REG_EDXEAX
11816#define REG_MMX0 27
11817#define REG_MMX1 28
11818#define REG_MMX2 29
11819#define REG_MMX3 30
11820#define REG_MMX4 31
11821#define REG_MMX5 32
11822#define REG_MMX6 33
11823#define REG_MMX7 34
11824#define REGC_MMX_FIRST REG_MMX0
11825#define REGC_MMX_LAST REG_MMX7
11826#define REG_XMM0 35
11827#define REG_XMM1 36
11828#define REG_XMM2 37
11829#define REG_XMM3 38
11830#define REG_XMM4 39
11831#define REG_XMM5 40
11832#define REG_XMM6 41
11833#define REG_XMM7 42
11834#define REGC_XMM_FIRST REG_XMM0
11835#define REGC_XMM_LAST REG_XMM7
11836#warning "WISHLIST figure out how to use pinsrw and pextrw to better use extended regs"
11837#define LAST_REG REG_XMM7
11838
11839#define REGC_GPR32_8_FIRST REG_EAX
11840#define REGC_GPR32_8_LAST REG_EDX
11841#define REGC_GPR16_8_FIRST REG_AX
11842#define REGC_GPR16_8_LAST REG_DX
11843
11844#if LAST_REG >= MAX_REGISTERS
11845#error "MAX_REGISTERS to low"
11846#endif
11847
11848static unsigned arch_regc_size(struct compile_state *state, int class)
11849{
11850 static unsigned regc_size[LAST_REGC +1] = {
11851 [REGC_FLAGS] = REGC_FLAGS_LAST - REGC_FLAGS_FIRST + 1,
11852 [REGC_GPR8] = REGC_GPR8_LAST - REGC_GPR8_FIRST + 1,
11853 [REGC_GPR16] = REGC_GPR16_LAST - REGC_GPR16_FIRST + 1,
11854 [REGC_GPR32] = REGC_GPR32_LAST - REGC_GPR32_FIRST + 1,
11855 [REGC_GPR64] = REGC_GPR64_LAST - REGC_GPR64_FIRST + 1,
11856 [REGC_MMX] = REGC_MMX_LAST - REGC_MMX_FIRST + 1,
11857 [REGC_XMM] = REGC_XMM_LAST - REGC_XMM_FIRST + 1,
11858 [REGC_GPR32_8] = REGC_GPR32_8_LAST - REGC_GPR32_8_FIRST + 1,
11859 [REGC_GPR16_8] = REGC_GPR16_8_LAST - REGC_GPR16_8_FIRST + 1,
11860 };
11861 if ((class < 0) || (class > LAST_REGC)) {
11862 return 0;
11863 }
11864 return regc_size[class];
11865}
11866static int arch_regcm_intersect(unsigned regcm1, unsigned regcm2)
11867{
11868 /* See if two register classes may have overlapping registers */
11869 unsigned gpr_mask = REGCM_GPR8 | REGCM_GPR16_8 | REGCM_GPR16 |
11870 REGCM_GPR32_8 | REGCM_GPR32 | REGCM_GPR64;
11871
11872 return (regcm1 & regcm2) ||
11873 ((regcm1 & gpr_mask) && (regcm2 & gpr_mask));
11874}
11875
11876static void arch_reg_equivs(
11877 struct compile_state *state, unsigned *equiv, int reg)
11878{
11879 if ((reg < 0) || (reg > LAST_REG)) {
11880 internal_error(state, 0, "invalid register");
11881 }
11882 *equiv++ = reg;
11883 switch(reg) {
11884 case REG_AL:
11885 case REG_AH:
11886 *equiv++ = REG_AX;
11887 *equiv++ = REG_EAX;
11888 *equiv++ = REG_EDXEAX;
11889 break;
11890 case REG_BL:
11891 case REG_BH:
11892 *equiv++ = REG_BX;
11893 *equiv++ = REG_EBX;
11894 break;
11895 case REG_CL:
11896 case REG_CH:
11897 *equiv++ = REG_CX;
11898 *equiv++ = REG_ECX;
11899 break;
11900 case REG_DL:
11901 case REG_DH:
11902 *equiv++ = REG_DX;
11903 *equiv++ = REG_EDX;
11904 *equiv++ = REG_EDXEAX;
11905 break;
11906 case REG_AX:
11907 *equiv++ = REG_AL;
11908 *equiv++ = REG_AH;
11909 *equiv++ = REG_EAX;
11910 *equiv++ = REG_EDXEAX;
11911 break;
11912 case REG_BX:
11913 *equiv++ = REG_BL;
11914 *equiv++ = REG_BH;
11915 *equiv++ = REG_EBX;
11916 break;
11917 case REG_CX:
11918 *equiv++ = REG_CL;
11919 *equiv++ = REG_CH;
11920 *equiv++ = REG_ECX;
11921 break;
11922 case REG_DX:
11923 *equiv++ = REG_DL;
11924 *equiv++ = REG_DH;
11925 *equiv++ = REG_EDX;
11926 *equiv++ = REG_EDXEAX;
11927 break;
11928 case REG_SI:
11929 *equiv++ = REG_ESI;
11930 break;
11931 case REG_DI:
11932 *equiv++ = REG_EDI;
11933 break;
11934 case REG_BP:
11935 *equiv++ = REG_EBP;
11936 break;
11937 case REG_SP:
11938 *equiv++ = REG_ESP;
11939 break;
11940 case REG_EAX:
11941 *equiv++ = REG_AL;
11942 *equiv++ = REG_AH;
11943 *equiv++ = REG_AX;
11944 *equiv++ = REG_EDXEAX;
11945 break;
11946 case REG_EBX:
11947 *equiv++ = REG_BL;
11948 *equiv++ = REG_BH;
11949 *equiv++ = REG_BX;
11950 break;
11951 case REG_ECX:
11952 *equiv++ = REG_CL;
11953 *equiv++ = REG_CH;
11954 *equiv++ = REG_CX;
11955 break;
11956 case REG_EDX:
11957 *equiv++ = REG_DL;
11958 *equiv++ = REG_DH;
11959 *equiv++ = REG_DX;
11960 *equiv++ = REG_EDXEAX;
11961 break;
11962 case REG_ESI:
11963 *equiv++ = REG_SI;
11964 break;
11965 case REG_EDI:
11966 *equiv++ = REG_DI;
11967 break;
11968 case REG_EBP:
11969 *equiv++ = REG_BP;
11970 break;
11971 case REG_ESP:
11972 *equiv++ = REG_SP;
11973 break;
11974 case REG_EDXEAX:
11975 *equiv++ = REG_AL;
11976 *equiv++ = REG_AH;
11977 *equiv++ = REG_DL;
11978 *equiv++ = REG_DH;
11979 *equiv++ = REG_AX;
11980 *equiv++ = REG_DX;
11981 *equiv++ = REG_EAX;
11982 *equiv++ = REG_EDX;
11983 break;
11984 }
11985 *equiv++ = REG_UNSET;
11986}
11987
11988
11989static unsigned arch_reg_regcm(struct compile_state *state, int reg)
11990{
11991 static const struct {
11992 int first, last;
11993 } bound[LAST_REGC + 1] = {
11994 [REGC_FLAGS] = { REGC_FLAGS_FIRST, REGC_FLAGS_LAST },
11995 [REGC_GPR8] = { REGC_GPR8_FIRST, REGC_GPR8_LAST },
11996 [REGC_GPR16] = { REGC_GPR16_FIRST, REGC_GPR16_LAST },
11997 [REGC_GPR32] = { REGC_GPR32_FIRST, REGC_GPR32_LAST },
11998 [REGC_GPR64] = { REGC_GPR64_FIRST, REGC_GPR64_LAST },
11999 [REGC_MMX] = { REGC_MMX_FIRST, REGC_MMX_LAST },
12000 [REGC_XMM] = { REGC_XMM_FIRST, REGC_XMM_LAST },
12001 [REGC_GPR32_8] = { REGC_GPR32_8_FIRST, REGC_GPR32_8_LAST },
12002 [REGC_GPR16_8] = { REGC_GPR16_8_FIRST, REGC_GPR16_8_LAST },
12003 };
12004 unsigned mask;
12005 int class;
12006 mask = 0;
12007 for(class = 0; class <= LAST_REGC; class++) {
12008 if ((reg >= bound[class].first) &&
12009 (reg <= bound[class].last)) {
12010 mask |= (1 << class);
12011 }
12012 }
12013 if (!mask) {
12014 internal_error(state, 0, "reg %d not in any class", reg);
12015 }
12016 return mask;
12017}
12018
12019static int do_select_reg(struct compile_state *state,
12020 char *used, int reg, unsigned classes)
12021{
12022 unsigned mask;
12023 if (used[reg]) {
12024 return REG_UNSET;
12025 }
12026 mask = arch_reg_regcm(state, reg);
12027 return (classes & mask) ? reg : REG_UNSET;
12028}
12029
12030static int arch_select_free_register(
12031 struct compile_state *state, char *used, int classes)
12032{
12033 /* Preference: flags, 8bit gprs, 32bit gprs, other 32bit reg
12034 * other types of registers.
12035 */
12036 int i, reg;
12037 reg = REG_UNSET;
12038 for(i = REGC_FLAGS_FIRST; (reg == REG_UNSET) && (i <= REGC_FLAGS_LAST); i++) {
12039 reg = do_select_reg(state, used, i, classes);
12040 }
12041 for(i = REGC_GPR8_FIRST; (reg == REG_UNSET) && (i <= REGC_GPR8_LAST); i++) {
12042 reg = do_select_reg(state, used, i, classes);
12043 }
12044 for(i = REGC_GPR32_FIRST; (reg == REG_UNSET) && (i <= REGC_GPR32_LAST); i++) {
12045 reg = do_select_reg(state, used, i, classes);
12046 }
12047 for(i = REGC_MMX_FIRST; (reg == REG_UNSET) && (i <= REGC_MMX_LAST); i++) {
12048 reg = do_select_reg(state, used, i, classes);
12049 }
12050 for(i = REGC_XMM_FIRST; (reg == REG_UNSET) && (i <= REGC_XMM_LAST); i++) {
12051 reg = do_select_reg(state, used, i, classes);
12052 }
12053 for(i = REGC_GPR16_FIRST; (reg == REG_UNSET) && (i <= REGC_GPR16_LAST); i++) {
12054 reg = do_select_reg(state, used, i, classes);
12055 }
12056 for(i = REGC_GPR64_FIRST; (reg == REG_UNSET) && (i <= REGC_GPR64_LAST); i++) {
12057 reg = do_select_reg(state, used, i, classes);
12058 }
12059 return reg;
12060}
12061
12062static unsigned arch_type_to_regcm(struct compile_state *state, struct type *type)
12063{
12064#warning "FIXME force types smaller (if legal) before I get here"
12065 int use_mmx = 0;
12066 int use_sse = 0;
12067 unsigned avail_mask;
12068 unsigned mask;
12069 avail_mask = REGCM_GPR8 | REGCM_GPR16_8 | REGCM_GPR16 |
12070 REGCM_GPR32 | REGCM_GPR32_8 | REGCM_GPR64;
12071#if 1
12072 /* Don't enable 8 bit values until I can force both operands
12073 * to be 8bits simultaneously.
12074 */
12075 avail_mask &= ~(REGCM_GPR8 | REGCM_GPR16_8 | REGCM_GPR16);
12076#endif
12077 if (use_mmx) {
12078 avail_mask |= REGCM_MMX;
12079 }
12080 if (use_sse) {
12081 avail_mask |= REGCM_XMM;
12082 }
12083 mask = 0;
12084 switch(type->type & TYPE_MASK) {
12085 case TYPE_ARRAY:
12086 case TYPE_VOID:
12087 mask = 0;
12088 break;
12089 case TYPE_CHAR:
12090 case TYPE_UCHAR:
12091 mask = REGCM_GPR8 |
12092 REGCM_GPR16_8 | REGCM_GPR16 |
12093 REGCM_GPR32 | REGCM_GPR32_8 |
12094 REGCM_GPR64 |
12095 REGCM_MMX | REGCM_XMM;
12096 break;
12097 case TYPE_SHORT:
12098 case TYPE_USHORT:
12099 mask = REGCM_GPR16 | REGCM_GPR16_8 |
12100 REGCM_GPR32 | REGCM_GPR32_8 |
12101 REGCM_GPR64 |
12102 REGCM_MMX | REGCM_XMM;
12103 break;
12104 case TYPE_INT:
12105 case TYPE_UINT:
12106 case TYPE_LONG:
12107 case TYPE_ULONG:
12108 case TYPE_POINTER:
12109 mask = REGCM_GPR32 | REGCM_GPR32_8 |
12110 REGCM_GPR64 | REGCM_MMX | REGCM_XMM;
12111 break;
12112 default:
12113 internal_error(state, 0, "no register class for type");
12114 break;
12115 }
12116 mask &= avail_mask;
12117 return mask;
12118}
12119
12120static void get_imm32(struct triple *ins, struct triple **expr)
12121{
12122 struct triple *imm;
12123 if ((*expr)->op != OP_COPY) {
12124 return;
12125 }
12126 imm = (*expr)->left;
12127 while(imm->op == OP_COPY) {
12128 imm = imm->left;
12129 }
12130 if (imm->op != OP_INTCONST) {
12131 return;
12132 }
12133 *expr = imm;
12134 unuse_triple(*expr, ins);
12135 use_triple(*expr, ins);
12136}
12137
12138static void get_imm8(struct triple *ins, struct triple **expr)
12139{
12140 struct triple *imm;
12141 if ((*expr)->op != OP_COPY) {
12142 return;
12143 }
12144 imm = (*expr)->left;
12145 while(imm->op == OP_COPY) {
12146 imm = imm->left;
12147 }
12148 if (imm->op != OP_INTCONST) {
12149 return;
12150 }
12151 /* For imm8 only a sufficienlty small constant can be used */
12152 if (imm->u.cval > 0xff) {
12153 return;
12154 }
12155 *expr = imm;
12156 unuse_triple(*expr, ins);
12157 use_triple(*expr, ins);
12158}
12159
12160static struct triple *pre_copy(struct compile_state *state,
12161 struct triple *ins, struct triple **expr,
12162 unsigned reg, unsigned mask)
12163{
12164 /* Carefully insert enough operations so that I can
12165 * enter any operation with a GPR32.
12166 */
12167 struct triple *in;
12168 /* See if I can directly reach the result from a GPR32 */
12169 if (mask & (REGCM_GPR32 | REGCM_GPR16 | REGCM_MMX | REGCM_XMM)) {
12170 in = triple(state, OP_COPY, (*expr)->type, *expr, 0);
12171 }
12172 /* If it is a byte value force a earlier copy to a GPR32_8 */
12173 else if (mask & REGCM_GPR8) {
12174 struct triple *tmp;
12175 tmp = triple(state, OP_COPY, (*expr)->type, *expr, 0);
12176 tmp->filename = ins->filename;
12177 tmp->line = ins->line;
12178 tmp->col = ins->col;
12179 tmp->u.block = ins->u.block;
12180 tmp->id = MK_REG_ID(REG_UNSET, REGCM_GPR32_8 | REGCM_GPR16_8);
12181 use_triple(tmp->left, tmp);
12182 insert_triple(state, ins, tmp);
12183
12184 in = triple(state, OP_COPY, tmp->type, tmp, 0);
12185 }
12186 else {
12187 internal_error(state, ins, "bad copy type");
12188 in = 0;
12189 }
12190 in->filename = ins->filename;
12191 in->line = ins->line;
12192 in->col = ins->col;
12193 in->u.block = ins->u.block;
12194 in->id = MK_REG_ID(reg, mask);
12195 unuse_triple(*expr, ins);
12196 *expr = in;
12197 use_triple(in->left, in);
12198 use_triple(in, ins);
12199 insert_triple(state, ins, in);
12200 return in;
12201}
12202
12203static struct triple *post_copy(struct compile_state *state, struct triple *ins)
12204{
12205 struct triple_set *entry, *next;
12206 struct triple *out, *label;
12207 struct block *block;
12208 label = ins;
12209 while(label->op != OP_LABEL) {
12210 label = label->prev;
12211 }
12212 block = label->u.block;
12213 out = triple(state, OP_COPY, ins->type, ins, 0);
12214 out->filename = ins->filename;
12215 out->line = ins->line;
12216 out->col = ins->col;
12217 out->u.block = block;
12218 out->id = MK_REG_ID(REG_UNSET,
12219 arch_type_to_regcm(state, ins->type));
12220 use_triple(ins, out);
12221 insert_triple(state, ins->next, out);
12222 if (block->last == ins) {
12223 block->last = out;
12224 }
12225 /* Get the users of ins to use out instead */
12226 for(entry = ins->use; entry; entry = next) {
12227 next = entry->next;
12228 if (entry->member == out) {
12229 continue;
12230 }
12231 replace_rhs_use(state, ins, out, entry->member);
12232 }
12233 return out;
12234}
12235
12236static void fixup_branches(struct compile_state *state,
12237 struct triple *cmp, struct triple *use, int jmp_op)
12238{
12239 struct triple_set *entry, *next;
12240 for(entry = use->use; entry; entry = next) {
12241 next = entry->next;
12242 if (entry->member->op == OP_COPY) {
12243 fixup_branches(state, cmp, entry->member, jmp_op);
12244 }
12245 else if (entry->member->op == OP_BRANCH) {
12246 struct triple *branch, *test;
12247 branch = entry->member;
12248 test = pre_triple(state, branch,
12249 cmp->op, cmp->type, cmp->left, cmp->right);
12250 test->id = MK_REG_ID(REG_EFLAGS, REGCM_FLAGS);
12251 unuse_triple(branch->right, branch);
12252 branch->right = test;
12253 branch->op = jmp_op;
12254 use_triple(branch->right, branch);
12255 }
12256 }
12257}
12258
12259static void bool_cmp(struct compile_state *state,
12260 struct triple *ins, int cmp_op, int jmp_op, int set_op)
12261{
12262 struct block *block;
12263 struct triple_set *entry, *next;
12264 struct triple *set, *tmp1, *tmp2;
12265
12266#warning "WISHLIST implement an expression simplifier to reduce the use of set?"
12267
12268 block = ins->u.block;
12269
12270 /* Put a barrier up before the cmp which preceeds the
12271 * copy instruction. If a set actually occurs this gives
12272 * us a chance to move variables in registers out of the way.
12273 */
12274
12275 /* Modify the comparison operator */
12276 ins->op = cmp_op;
12277 ins->id = MK_REG_ID(REG_EFLAGS, REGCM_FLAGS);
12278 if (cmp_op == OP_CMP) {
12279 get_imm32(ins, &ins->right);
12280 }
12281 /* Generate the instruction sequence that will transform the
12282 * result of the comparison into a logical value.
12283 */
12284 tmp1 = triple(state, set_op, ins->type, ins, 0);
12285 tmp1->filename = ins->filename;
12286 tmp1->line = ins->line;
12287 tmp1->col = ins->col;
12288 tmp1->u.block = block;
12289 tmp1->id = MK_REG_ID(REG_UNSET, REGCM_GPR8);
12290 use_triple(ins, tmp1);
12291 insert_triple(state, ins->next, tmp1);
12292
12293 tmp2 = triple(state, OP_COPY, ins->type, tmp1, 0);
12294 tmp2->filename = ins->filename;
12295 tmp2->line = ins->line;
12296 tmp2->col = ins->col;
12297 tmp2->u.block = block;
12298 tmp2->id = MK_REG_ID(REG_UNSET,
12299 REGCM_GPR32 | REGCM_GPR32_8 | REGCM_GPR16 | REGCM_GPR16_8 | REGCM_GPR8);
12300 use_triple(tmp1, tmp2);
12301 insert_triple(state, tmp1->next, tmp2);
12302
12303 if (block->last == ins) {
12304 block->last = tmp2;
12305 }
12306
12307 set = tmp2;
12308 for(entry = ins->use; entry; entry = next) {
12309 next = entry->next;
12310 if (entry->member == tmp1) {
12311 continue;
12312 }
12313 replace_rhs_use(state, ins, set, entry->member);
12314 }
12315 fixup_branches(state, ins, set, jmp_op);
12316}
12317
12318
12319static void transform_to_arch_instructions(struct compile_state *state)
12320{
12321 /* Transform from generic 3 address instructions
12322 * to archtecture specific instructions.
12323 * And apply architecture specific constrains to instructions.
12324 * Copies are inserted to preserve the register flexibility
12325 * of 3 address instructions.
12326 */
12327 struct triple *ins, *first, *next;
12328 struct triple *in, *in2;
12329 first = state->main_function->left;
12330 ins = first;
12331 do {
12332 next = ins->next;
12333 ins->id = MK_REG_ID(REG_UNSET, arch_type_to_regcm(state, ins->type));
12334 switch(ins->op) {
12335 case OP_INTCONST:
12336 case OP_ADDRCONST:
12337 ins->id = 0;
12338 post_copy(state, ins);
12339 break;
12340 case OP_NOOP:
12341 case OP_SDECL:
12342 case OP_BLOBCONST:
12343 case OP_LABEL:
12344 ins->id = 0;
12345 break;
12346 /* instructions that can be used as is */
12347 case OP_COPY:
12348 case OP_PHI:
12349 break;
12350 case OP_STORE:
12351 {
12352 unsigned mask;
12353 ins->id = 0;
12354 switch(ins->type->type & TYPE_MASK) {
12355 case TYPE_CHAR: case TYPE_UCHAR:
12356 mask = REGCM_GPR8;
12357 break;
12358 case TYPE_SHORT: case TYPE_USHORT:
12359 mask = REGCM_GPR16;
12360 break;
12361 case TYPE_INT: case TYPE_UINT:
12362 case TYPE_LONG: case TYPE_ULONG:
12363 case TYPE_POINTER:
12364 mask = REGCM_GPR32;
12365 break;
12366 default:
12367 internal_error(state, ins, "unknown type in store");
12368 mask = 0;
12369 break;
12370 }
12371 in = pre_copy(state, ins, &ins->right, REG_UNSET, mask);
12372 break;
12373 }
12374 case OP_LOAD:
12375 switch(ins->type->type & TYPE_MASK) {
12376 case TYPE_CHAR: case TYPE_UCHAR:
12377 ins->id = MK_REG_ID(REG_UNSET, REGCM_GPR8);
12378 break;
12379 case TYPE_SHORT:
12380 case TYPE_USHORT:
12381 ins->id = MK_REG_ID(REG_UNSET, REGCM_GPR16);
12382 break;
12383 case TYPE_INT:
12384 case TYPE_UINT:
12385 case TYPE_LONG:
12386 case TYPE_ULONG:
12387 case TYPE_POINTER:
12388 ins->id = MK_REG_ID(REG_UNSET, REGCM_GPR32);
12389 break;
12390 default:
12391 internal_error(state, ins, "unknown type in load");
12392 break;
12393 }
12394 break;
12395 case OP_ADD:
12396 case OP_SUB:
12397 case OP_AND:
12398 case OP_XOR:
12399 case OP_OR:
12400 get_imm32(ins, &ins->right);
12401 in = pre_copy(state, ins, &ins->left,
12402 alloc_virtual_reg(), ID_REG_CLASSES(ins->id));
12403 ins->id = in->id;
12404 break;
12405 case OP_SL:
12406 case OP_SSR:
12407 case OP_USR:
12408 get_imm8(ins, &ins->right);
12409 in = pre_copy(state, ins, &ins->left,
12410 alloc_virtual_reg(), ID_REG_CLASSES(ins->id));
12411 ins->id = in->id;
12412 if (!IS_CONST_OP(ins->right->op)) {
12413 in2 = pre_copy(state, ins, &ins->right,
12414 REG_CL, REGCM_GPR8);
12415 }
12416 break;
12417 case OP_INVERT:
12418 case OP_NEG:
12419 in = pre_copy(state, ins, &ins->left,
12420 alloc_virtual_reg(), ID_REG_CLASSES(ins->id));
12421 ins->id = in->id;
12422 break;
12423 case OP_SMUL:
12424 get_imm32(ins, &ins->right);
12425 in = pre_copy(state, ins, &ins->left,
12426 alloc_virtual_reg(), ID_REG_CLASSES(ins->id));
12427 ins->id = in->id;
12428 if (!IS_CONST_OP(ins->right->op)) {
12429 in2 = pre_copy(state, ins, &ins->right,
12430 REG_UNSET, REGCM_GPR32);
12431 }
12432 break;
12433 case OP_EQ:
12434 bool_cmp(state, ins, OP_CMP, OP_JMP_EQ, OP_SET_EQ);
12435 break;
12436 case OP_NOTEQ:
12437 bool_cmp(state, ins, OP_CMP, OP_JMP_NOTEQ, OP_SET_NOTEQ);
12438 break;
12439 case OP_SLESS:
12440 bool_cmp(state, ins, OP_CMP, OP_JMP_SLESS, OP_SET_SLESS);
12441 break;
12442 case OP_ULESS:
12443 bool_cmp(state, ins, OP_CMP, OP_JMP_ULESS, OP_SET_ULESS);
12444 break;
12445 case OP_SMORE:
12446 bool_cmp(state, ins, OP_CMP, OP_JMP_SMORE, OP_SET_SMORE);
12447 break;
12448 case OP_UMORE:
12449 bool_cmp(state, ins, OP_CMP, OP_JMP_UMORE, OP_SET_UMORE);
12450 break;
12451 case OP_SLESSEQ:
12452 bool_cmp(state, ins, OP_CMP, OP_JMP_SLESSEQ, OP_SET_SLESSEQ);
12453 break;
12454 case OP_ULESSEQ:
12455 bool_cmp(state, ins, OP_CMP, OP_JMP_ULESSEQ, OP_SET_ULESSEQ);
12456 break;
12457 case OP_SMOREEQ:
12458 bool_cmp(state, ins, OP_CMP, OP_JMP_SMOREEQ, OP_SET_SMOREEQ);
12459 break;
12460 case OP_UMOREEQ:
12461 bool_cmp(state, ins, OP_CMP, OP_JMP_UMOREEQ, OP_SET_UMOREEQ);
12462 break;
12463 case OP_LTRUE:
12464 bool_cmp(state, ins, OP_TEST, OP_JMP_NOTEQ, OP_SET_NOTEQ);
12465 break;
12466 case OP_LFALSE:
12467 bool_cmp(state, ins, OP_TEST, OP_JMP_EQ, OP_SET_EQ);
12468 break;
12469 case OP_BRANCH:
12470 if (ins->right) {
12471 internal_error(state, ins, "bad branch test");
12472 }
12473 ins->op = OP_JMP;
12474 break;
12475
12476 case OP_INB:
12477 case OP_INW:
12478 case OP_INL:
12479 get_imm8(ins, &ins->left);
12480 switch(ins->op) {
12481 case OP_INB: ins->id = MK_REG_ID(REG_AL, REGCM_GPR8); break;
12482 case OP_INW: ins->id = MK_REG_ID(REG_AX, REGCM_GPR16); break;
12483 case OP_INL: ins->id = MK_REG_ID(REG_EAX, REGCM_GPR32); break;
12484 }
12485 if (!IS_CONST_OP(ins->left->op)) {
12486 in = pre_copy(state, ins, &ins->left,
12487 REG_DX, REGCM_GPR16);
12488 }
12489 break;
12490 case OP_OUTB:
12491 case OP_OUTW:
12492 case OP_OUTL:
12493 {
12494 unsigned reg, mask;
12495 get_imm8(ins, &ins->right);
12496 switch(ins->op) {
12497 case OP_OUTB: reg = REG_AL; mask = REGCM_GPR8; break;
12498 case OP_OUTW: reg = REG_AX; mask = REGCM_GPR16; break;
12499 case OP_OUTL: reg = REG_EAX; mask = REGCM_GPR32; break;
12500 default: reg = REG_UNSET; mask = 0; break;
12501 }
12502 in = pre_copy(state, ins, &ins->left, reg, mask);
12503 if (!IS_CONST_OP(ins->right->op)) {
12504 in2 = pre_copy(state, ins, &ins->right,
12505 REG_DX, REGCM_GPR16);
12506 }
12507 break;
12508 }
12509 case OP_BSF:
12510 case OP_BSR:
12511 in = pre_copy(state, ins, &ins->left,
12512 REG_UNSET, REGCM_GPR32);
12513 ins->id = MK_REG_ID(REG_UNSET, REGCM_GPR32 | REGCM_GPR32_8);
12514 break;
12515 /* Already transformed instructions */
12516 case OP_CMP:
12517 case OP_TEST:
12518 ins->id = MK_REG_ID(REG_EFLAGS, REGCM_FLAGS);
12519 break;
12520 case OP_JMP_EQ: case OP_JMP_NOTEQ:
12521 case OP_JMP_SLESS: case OP_JMP_ULESS:
12522 case OP_JMP_SMORE: case OP_JMP_UMORE:
12523 case OP_JMP_SLESSEQ: case OP_JMP_ULESSEQ:
12524 case OP_JMP_SMOREEQ: case OP_JMP_UMOREEQ:
12525 case OP_SET_EQ: case OP_SET_NOTEQ:
12526 case OP_SET_SLESS: case OP_SET_ULESS:
12527 case OP_SET_SMORE: case OP_SET_UMORE:
12528 case OP_SET_SLESSEQ: case OP_SET_ULESSEQ:
12529 case OP_SET_SMOREEQ: case OP_SET_UMOREEQ:
12530 break;
12531 default:
12532 internal_error(state, ins, "unhandled ins: %d %s\n",
12533 ins->op, tops(ins->op));
12534 break;
12535 }
12536 ins = next;
12537 } while(ins != first);
12538}
12539
12540
12541
12542static void generate_local_labels(struct compile_state *state)
12543{
12544 struct triple *first, *label;
12545 int label_counter;
12546 label_counter = 0;
12547 first = state->main_function->left;
12548 label = first;
12549 do {
12550 if ((label->op == OP_LABEL) ||
12551 (label->op == OP_SDECL)) {
12552 if (label->use) {
12553 label->u.cval = ++label_counter;
12554 } else {
12555 label->u.cval = 0;
12556 }
12557
12558 }
12559 label = label->next;
12560 } while(label != first);
12561}
12562
12563static int check_reg(struct compile_state *state,
12564 struct triple *triple, int classes)
12565{
12566 unsigned mask;
12567 int reg;
12568 reg = ID_REG(triple->id);
12569 if (reg == REG_UNSET) {
12570 internal_error(state, triple, "register not set");
12571 }
12572 if (ID_REG_CLASSES(triple->id)) {
12573 internal_error(state, triple, "class specifier present");
12574 }
12575 mask = arch_reg_regcm(state, reg);
12576 if (!(classes & mask)) {
12577 internal_error(state, triple, "reg %d in wrong class",
12578 reg);
12579 }
12580 return reg;
12581}
12582
12583static const char *arch_reg_str(int reg)
12584{
12585 static const char *regs[] = {
12586 "%bad_register",
12587 "%eflags",
12588 "%al", "%bl", "%cl", "%dl", "%ah", "%bh", "%ch", "%dh",
12589 "%ax", "%bx", "%cx", "%dx", "%si", "%di", "%bp", "%sp",
12590 "%eax", "%ebx", "%ecx", "%edx", "%esi", "%edi", "%ebp", "%esp",
12591 "%edx:%eax",
12592 "%mm0", "%mm1", "%mm2", "%mm3", "%mm4", "%mm5", "%mm6", "%mm7",
12593 "%xmm0", "%xmm1", "%xmm2", "%xmm3",
12594 "%xmm4", "%xmm5", "%xmm6", "%xmm7",
12595 };
12596 if (!((reg >= REG_EFLAGS) && (reg <= REG_XMM7))) {
12597 reg = 0;
12598 }
12599 return regs[reg];
12600}
12601
12602static const char *reg(struct compile_state *state, struct triple *triple,
12603 int classes)
12604{
12605 int reg;
12606 reg = check_reg(state, triple, classes);
12607 return arch_reg_str(reg);
12608}
12609
12610const char *type_suffix(struct compile_state *state, struct type *type)
12611{
12612 const char *suffix;
12613 switch(size_of(state, type)) {
12614 case 1: suffix = "b"; break;
12615 case 2: suffix = "w"; break;
12616 case 4: suffix = "l"; break;
12617 default:
12618 internal_error(state, 0, "unknown suffix");
12619 suffix = 0;
12620 break;
12621 }
12622 return suffix;
12623}
12624
12625static void print_binary_op(struct compile_state *state,
12626 const char *op, struct triple *ins, FILE *fp)
12627{
12628 unsigned mask;
12629 mask = REGCM_GPR32 | REGCM_GPR16 | REGCM_GPR8;
12630 if (ins->left->id != ins->id) {
12631 internal_error(state, ins, "invalid register assignment");
12632 }
12633 if (IS_CONST_OP(ins->right->op)) {
12634 fprintf(fp, "\t%s $%lu, %s\n",
12635 op,
12636 ins->right->u.cval,
12637 reg(state, ins->left, mask));
12638
12639 }
12640 else {
12641 unsigned lmask, rmask;
12642 int lreg, rreg;
12643 lreg = check_reg(state, ins->left, mask);
12644 rreg = check_reg(state, ins->right, mask);
12645 lmask = arch_reg_regcm(state, lreg);
12646 rmask = arch_reg_regcm(state, rreg);
12647 mask = lmask & rmask;
12648 fprintf(fp, "\t%s %s, %s\n",
12649 op,
12650 reg(state, ins->right, mask),
12651 reg(state, ins->left, mask));
12652 }
12653}
12654static void print_unary_op(struct compile_state *state,
12655 const char *op, struct triple *ins, FILE *fp)
12656{
12657 unsigned mask;
12658 mask = REGCM_GPR32 | REGCM_GPR16 | REGCM_GPR8;
12659 fprintf(fp, "\t%s %s\n",
12660 op,
12661 reg(state, ins->left, mask));
12662}
12663
12664static void print_op_shift(struct compile_state *state,
12665 const char *op, struct triple *ins, FILE *fp)
12666{
12667 unsigned mask;
12668 mask = REGCM_GPR32 | REGCM_GPR16 | REGCM_GPR8;
12669 if (ins->left->id != ins->id) {
12670 internal_error(state, ins, "invalid register assignment");
12671 }
12672 if (IS_CONST_OP(ins->right->op)) {
12673 fprintf(fp, "\t%s $%lu, %s\n",
12674 op,
12675 ins->right->u.cval,
12676 reg(state, ins->left, mask));
12677
12678 }
12679 else {
12680 fprintf(fp, "\t%s %s, %s\n",
12681 op,
12682 reg(state, ins->right, REGCM_GPR8),
12683 reg(state, ins->left, mask));
12684 }
12685}
12686
12687static void print_op_in(struct compile_state *state, struct triple *ins, FILE *fp)
12688{
12689 const char *op;
12690 int mask;
12691 int dreg;
12692 mask = 0;
12693 switch(ins->op) {
12694 case OP_INB: op = "inb", mask = REGCM_GPR8; break;
12695 case OP_INW: op = "inw", mask = REGCM_GPR16; break;
12696 case OP_INL: op = "inl", mask = REGCM_GPR32; break;
12697 default:
12698 internal_error(state, ins, "not an in operation");
12699 op = 0;
12700 break;
12701 }
12702 dreg = check_reg(state, ins, mask);
12703 if (!reg_is_reg(state, dreg, REG_EAX)) {
12704 internal_error(state, ins, "dst != %%eax");
12705 }
12706 if (IS_CONST_OP(ins->left->op)) {
12707 fprintf(fp, "\t%s $%lu, %s\n",
12708 op, ins->left->u.cval,
12709 reg(state, ins, mask));
12710 }
12711 else {
12712 int addr_reg;
12713 addr_reg = check_reg(state, ins->left, REGCM_GPR16);
12714 if (!reg_is_reg(state, addr_reg, REG_DX)) {
12715 internal_error(state, ins, "src != %%dx");
12716 }
12717 fprintf(fp, "\t%s %s, %s\n",
12718 op,
12719 reg(state, ins->left, REGCM_GPR16),
12720 reg(state, ins, mask));
12721 }
12722}
12723
12724static void print_op_out(struct compile_state *state, struct triple *ins, FILE *fp)
12725{
12726 const char *op;
12727 int mask;
12728 int lreg;
12729 mask = 0;
12730 switch(ins->op) {
12731 case OP_OUTB: op = "outb", mask = REGCM_GPR8; break;
12732 case OP_OUTW: op = "outw", mask = REGCM_GPR16; break;
12733 case OP_OUTL: op = "outl", mask = REGCM_GPR32; break;
12734 default:
12735 internal_error(state, ins, "not an out operation");
12736 op = 0;
12737 break;
12738 }
12739 lreg = check_reg(state, ins->left, mask);
12740 if (!reg_is_reg(state, lreg, REG_EAX)) {
12741 internal_error(state, ins, "src != %%eax");
12742 }
12743 if (IS_CONST_OP(ins->right->op)) {
12744 fprintf(fp, "\t%s %s, $%lu\n",
12745 op, reg(state, ins->left, mask),
12746 ins->right->u.cval);
12747 }
12748 else {
12749 int addr_reg;
12750 addr_reg = check_reg(state, ins->right, REGCM_GPR16);
12751 if (!reg_is_reg(state, addr_reg, REG_DX)) {
12752 internal_error(state, ins, "dst != %%dx");
12753 }
12754 fprintf(fp, "\t%s %s, %s\n",
12755 op,
12756 reg(state, ins->left, mask),
12757 reg(state, ins->right, REGCM_GPR16));
12758 }
12759}
12760
12761static void print_op_move(struct compile_state *state,
12762 struct triple *ins, FILE *fp)
12763{
12764 /* op_move is complex because there are many types
12765 * of registers we can move between.
12766 */
12767 int omit_copy = 1; /* Is it o.k. to omit a noop copy? */
12768 struct triple *dst, *src;
12769 if (ins->op == OP_COPY) {
12770 src = ins->left;
12771 dst = ins;
12772 }
12773 else if (ins->op == OP_WRITE) {
12774 dst = ins->left;
12775 src = ins->right;
12776 }
12777 else {
12778 internal_error(state, ins, "unknown move operation");
12779 src = dst = 0;
12780 }
12781 if (!IS_CONST_OP(src->op)) {
12782 int src_reg, dst_reg;
12783 int src_regcm, dst_regcm;
12784 src_reg = ID_REG(src->id);
12785 dst_reg = ID_REG(dst->id);
12786 src_regcm = arch_reg_regcm(state, src_reg);
12787 dst_regcm = arch_reg_regcm(state, dst_reg);
12788 /* If the class is the same just move the register */
12789 if (src_regcm & dst_regcm &
12790 (REGCM_GPR8 | REGCM_GPR16 | REGCM_GPR32)) {
12791 if ((src_reg != dst_reg) || !omit_copy) {
12792 fprintf(fp, "\tmov %s, %s\n",
12793 reg(state, src, src_regcm),
12794 reg(state, dst, dst_regcm));
12795 }
12796 }
12797 /* Move 32bit to 16bit */
12798 else if ((src_regcm & REGCM_GPR32) &&
12799 (dst_regcm & REGCM_GPR16)) {
12800 src_reg = (src_reg - REGC_GPR32_FIRST) + REGC_GPR16_FIRST;
12801 if ((src_reg != dst_reg) || !omit_copy) {
12802 fprintf(fp, "\tmovw %s, %s\n",
12803 arch_reg_str(src_reg),
12804 arch_reg_str(dst_reg));
12805 }
12806 }
12807 /* Move 32bit to 8bit */
12808 else if ((src_regcm & REGCM_GPR32_8) &&
12809 (dst_regcm & REGCM_GPR8))
12810 {
12811 src_reg = (src_reg - REGC_GPR32_8_FIRST) + REGC_GPR8_FIRST;
12812 if ((src_reg != dst_reg) || !omit_copy) {
12813 fprintf(fp, "\tmovb %s, %s\n",
12814 arch_reg_str(src_reg),
12815 arch_reg_str(dst_reg));
12816 }
12817 }
12818 /* Move 16bit to 8bit */
12819 else if ((src_regcm & REGCM_GPR16_8) &&
12820 (dst_regcm & REGCM_GPR8))
12821 {
12822 src_reg = (src_reg - REGC_GPR16_8_FIRST) + REGC_GPR8_FIRST;
12823 if ((src_reg != dst_reg) || !omit_copy) {
12824 fprintf(fp, "\tmovb %s, %s\n",
12825 arch_reg_str(src_reg),
12826 arch_reg_str(dst_reg));
12827 }
12828 }
12829 /* Move 8/16bit to 16/32bit */
12830 else if ((src_regcm & (REGCM_GPR8 | REGCM_GPR16)) &&
12831 (dst_regcm & (REGC_GPR16 | REGCM_GPR32))) {
12832 const char *op;
12833 op = is_signed(src->type)? "movsx": "movzx";
12834 fprintf(fp, "\t%s %s, %s\n",
12835 op,
12836 reg(state, src, src_regcm),
12837 reg(state, dst, dst_regcm));
12838 }
12839 /* Move between sse registers */
12840 else if ((src_regcm & dst_regcm & REGCM_XMM)) {
12841 if ((src_reg != dst_reg) || !omit_copy) {
12842 fprintf(fp, "\tmovdqa %s %s\n",
12843 reg(state, src, src_regcm),
12844 reg(state, dst, dst_regcm));
12845 }
12846 }
12847 /* Move between mmx registers or mmx & sse registers */
12848 else if ((src_regcm & (REGCM_MMX | REGCM_XMM)) &&
12849 (dst_regcm & (REGCM_MMX | REGCM_XMM))) {
12850 if ((src_reg != dst_reg) || !omit_copy) {
12851 fprintf(fp, "\tmovq %s %s\n",
12852 reg(state, src, src_regcm),
12853 reg(state, dst, dst_regcm));
12854 }
12855 }
12856 /* Move between 32bit gprs & mmx/sse registers */
12857 else if ((src_regcm & (REGCM_GPR32 | REGCM_MMX | REGCM_XMM)) &&
12858 (dst_regcm & (REGCM_GPR32 | REGCM_MMX | REGCM_XMM))) {
12859 fprintf(fp, "\tmovd %s, %s\n",
12860 reg(state, src, src_regcm),
12861 reg(state, dst, dst_regcm));
12862 }
12863 else {
12864 internal_error(state, ins, "unknown copy type");
12865 }
12866 }
12867 else switch(src->op) {
12868 case OP_INTCONST:
12869 {
12870 long_t value;
12871 value = (long_t)(src->u.cval);
12872 fprintf(fp, "\tmov $%ld, %s\n",
12873 value,
12874 reg(state, dst, REGCM_GPR32 | REGCM_GPR16 | REGCM_GPR8));
12875 break;
12876 }
12877 case OP_ADDRCONST:
12878 fprintf(fp, "\tmov $L%lu+%lu, %s\n",
12879 src->left->u.cval,
12880 src->u.cval,
12881 reg(state, dst, REGCM_GPR32));
12882 break;
12883 default:
12884 internal_error(state, ins, "uknown copy operation");
12885 }
12886}
12887
12888static void print_op_load(struct compile_state *state,
12889 struct triple *ins, FILE *fp)
12890{
12891 struct triple *dst, *src;
12892 dst = ins;
12893 src = ins->left;
12894 if (is_const(src) || is_const(dst)) {
12895 internal_error(state, ins, "unknown load operation");
12896 }
12897 fprintf(fp, "\tmov (%s), %s\n",
12898 reg(state, src, REGCM_GPR32),
12899 reg(state, dst, REGCM_GPR8 | REGCM_GPR16 | REGCM_GPR32));
12900}
12901
12902
12903static void print_op_store(struct compile_state *state,
12904 struct triple *ins, FILE *fp)
12905{
12906 struct triple *dst, *src;
12907 dst = ins->left;
12908 src = ins->right;
12909 if (is_const(src) && (src->op == OP_INTCONST)) {
12910 long_t value;
12911 value = (long_t)(src->u.cval);
12912 fprintf(fp, "\tmov%s $%ld, (%s)\n",
12913 type_suffix(state, src->type),
12914 value,
12915 reg(state, dst, REGCM_GPR32));
12916 }
12917 else if (is_const(dst) && (dst->op == OP_INTCONST)) {
12918 fprintf(fp, "\tmov%s %s, 0x%08lx\n",
12919 type_suffix(state, src->type),
12920 reg(state, src, REGCM_GPR8 | REGCM_GPR16 | REGCM_GPR32),
12921 dst->u.cval);
12922 }
12923 else {
12924 if (is_const(src) || is_const(dst)) {
12925 internal_error(state, ins, "unknown store operation");
12926 }
12927 fprintf(fp, "\tmov%s %s, (%s)\n",
12928 type_suffix(state, src->type),
12929 reg(state, src, REGCM_GPR8 | REGCM_GPR16 | REGCM_GPR32),
12930 reg(state, dst, REGCM_GPR32));
12931 }
12932
12933
12934}
12935
12936static void print_op_smul(struct compile_state *state,
12937 struct triple *ins, FILE *fp)
12938{
12939 if (!IS_CONST_OP(ins->right->op)) {
12940 fprintf(fp, "\timul %s, %s\n",
12941 reg(state, ins->right, REGCM_GPR32),
12942 reg(state, ins->left, REGCM_GPR32));
12943 }
12944 else {
12945 fprintf(fp, "\timul $%ld, %s\n",
12946 ins->right->u.cval,
12947 reg(state, ins->left, REGCM_GPR32));
12948 }
12949}
12950
12951static void print_op_cmp(struct compile_state *state,
12952 struct triple *ins, FILE *fp)
12953{
12954 unsigned mask;
12955 int dreg;
12956 mask = REGCM_GPR32 | REGCM_GPR16 | REGCM_GPR8;
12957 dreg = check_reg(state, ins, REGCM_FLAGS);
12958 if (!reg_is_reg(state, dreg, REG_EFLAGS)) {
12959 internal_error(state, ins, "bad dest register for cmp");
12960 }
12961 if (IS_CONST_OP(ins->right->op)) {
12962 fprintf(fp, "\tcmp $%lu, %s\n",
12963 ins->right->u.cval,
12964 reg(state, ins->left, mask));
12965 }
12966 else {
12967 unsigned lmask, rmask;
12968 int lreg, rreg;
12969 lreg = check_reg(state, ins->left, mask);
12970 rreg = check_reg(state, ins->right, mask);
12971 lmask = arch_reg_regcm(state, lreg);
12972 rmask = arch_reg_regcm(state, rreg);
12973 mask = lmask & rmask;
12974 fprintf(fp, "\tcmp %s, %s\n",
12975 reg(state, ins->right, mask),
12976 reg(state, ins->left, mask));
12977 }
12978}
12979
12980static void print_op_test(struct compile_state *state,
12981 struct triple *ins, FILE *fp)
12982{
12983 unsigned mask;
12984 mask = REGCM_GPR32 | REGCM_GPR16 | REGCM_GPR8;
12985 fprintf(fp, "\ttest %s, %s\n",
12986 reg(state, ins->left, mask),
12987 reg(state, ins->left, mask));
12988}
12989
12990static void print_op_branch(struct compile_state *state,
12991 struct triple *branch, FILE *fp)
12992{
12993 const char *bop = "j";
12994 if (branch->op == OP_JMP) {
12995 if (branch->right) {
12996 internal_error(state, branch, "jmp with condition?");
12997 }
12998 bop = "jmp";
12999 }
13000 else {
13001 if (!branch->right) {
13002 internal_error(state, branch, "jmpcc without condition?");
13003 }
13004 check_reg(state, branch->right, REGCM_FLAGS);
13005 if ((branch->right->op != OP_CMP) &&
13006 (branch->right->op != OP_TEST)) {
13007 internal_error(state, branch, "bad branch test");
13008 }
13009#warning "FIXME I have observed instructions between the test and branch instructions"
13010 if (branch->right->next != branch) {
13011 internal_error(state, branch, "branch does not follow test");
13012 }
13013 switch(branch->op) {
13014 case OP_JMP_EQ: bop = "jz"; break;
13015 case OP_JMP_NOTEQ: bop = "jnz"; break;
13016 case OP_JMP_SLESS: bop = "jl"; break;
13017 case OP_JMP_ULESS: bop = "jb"; break;
13018 case OP_JMP_SMORE: bop = "jg"; break;
13019 case OP_JMP_UMORE: bop = "ja"; break;
13020 case OP_JMP_SLESSEQ: bop = "jle"; break;
13021 case OP_JMP_ULESSEQ: bop = "jbe"; break;
13022 case OP_JMP_SMOREEQ: bop = "jge"; break;
13023 case OP_JMP_UMOREEQ: bop = "jae"; break;
13024 default:
13025 internal_error(state, branch, "Invalid branch op");
13026 break;
13027 }
13028
13029 }
13030 fprintf(fp, "\t%s L%lu\n",
13031 bop, branch->left->u.cval);
13032}
13033
13034static void print_op_set(struct compile_state *state,
13035 struct triple *set, FILE *fp)
13036{
13037 const char *sop = "set";
13038 if (!set->left) {
13039 internal_error(state, set, "setcc without condition?");
13040 }
13041 check_reg(state, set->left, REGCM_FLAGS);
13042 if ((set->left->op != OP_CMP) &&
13043 (set->left->op != OP_TEST)) {
13044 internal_error(state, set, "bad set test");
13045 }
13046 if (set->left->next != set) {
13047 internal_error(state, set, "set does not follow test");
13048 }
13049 switch(set->op) {
13050 case OP_SET_EQ: sop = "setz"; break;
13051 case OP_SET_NOTEQ: sop = "setnz"; break;
13052 case OP_SET_SLESS: sop = "setl"; break;
13053 case OP_SET_ULESS: sop = "setb"; break;
13054 case OP_SET_SMORE: sop = "setg"; break;
13055 case OP_SET_UMORE: sop = "seta"; break;
13056 case OP_SET_SLESSEQ: sop = "setle"; break;
13057 case OP_SET_ULESSEQ: sop = "setbe"; break;
13058 case OP_SET_SMOREEQ: sop = "setge"; break;
13059 case OP_SET_UMOREEQ: sop = "setae"; break;
13060 default:
13061 internal_error(state, set, "Invalid set op");
13062 break;
13063 }
13064 fprintf(fp, "\t%s %s\n",
13065 sop, reg(state, set, REGCM_GPR8));
13066}
13067
13068static void print_op_bit_scan(struct compile_state *state,
13069 struct triple *ins, FILE *fp)
13070{
13071 const char *op;
13072 switch(ins->op) {
13073 case OP_BSF: op = "bsf"; break;
13074 case OP_BSR: op = "bsr"; break;
13075 default:
13076 internal_error(state, ins, "unknown bit scan");
13077 op = 0;
13078 break;
13079 }
13080 fprintf(fp,
13081 "\t%s %s, %s\n"
13082 "\tjnz 1f\n"
13083 "\tmovl $-1, %s\n"
13084 "1:\n",
13085 op,
13086 reg(state, ins->left, REGCM_GPR32),
13087 reg(state, ins, REGCM_GPR32),
13088 reg(state, ins, REGCM_GPR32));
13089}
13090
13091static void print_const(struct compile_state *state,
13092 struct triple *ins, FILE *fp)
13093{
13094 switch(ins->op) {
13095 case OP_INTCONST:
13096 switch(ins->type->type & TYPE_MASK) {
13097 case TYPE_CHAR:
13098 case TYPE_UCHAR:
13099 fprintf(fp, ".byte 0x%02lx\n", ins->u.cval);
13100 break;
13101 case TYPE_SHORT:
13102 case TYPE_USHORT:
13103 fprintf(fp, ".short 0x%04lx\n", ins->u.cval);
13104 break;
13105 case TYPE_INT:
13106 case TYPE_UINT:
13107 case TYPE_LONG:
13108 case TYPE_ULONG:
13109 fprintf(fp, ".int %lu\n", ins->u.cval);
13110 break;
13111 default:
13112 internal_error(state, ins, "Unknown constant type");
13113 }
13114 break;
13115 case OP_BLOBCONST:
13116 {
13117 unsigned char *blob;
13118 size_t size, i;
13119 size = size_of(state, ins->type);
13120 blob = ins->u.blob;
13121 for(i = 0; i < size; i++) {
13122 fprintf(fp, ".byte 0x%02x\n",
13123 blob[i]);
13124 }
13125 break;
13126 }
13127#if 0
13128 case OP_ADDRCONST:
13129 fprintf(fp, ".int $L%lu+%lu",
13130 ins->left->u.cval,
13131 ins->u.cval);
13132 break;
13133#endif
13134 default:
13135 internal_error(state, ins, "Unknown constant type");
13136 break;
13137 }
13138}
13139
13140static void print_sdecl(struct compile_state *state,
13141 struct triple *ins, FILE *fp)
13142{
13143 fprintf(fp, ".section \".rom.data\"\n");
13144 fprintf(fp, ".balign %d\n", align_of(state, ins->type));
13145 fprintf(fp, "L%lu:\n", ins->u.cval);
13146 print_const(state, ins->left, fp);
13147 fprintf(fp, ".section \".rom.text\"\n");
13148
13149}
13150
13151static void print_instruction(struct compile_state *state,
13152 struct triple *ins, FILE *fp)
13153{
13154 /* Assumption: after I have exted the register allocator
13155 * everything is in a valid register.
13156 */
13157 switch(ins->op) {
13158 case OP_ADD: print_binary_op(state, "add", ins, fp); break;
13159 case OP_SUB: print_binary_op(state, "sub", ins, fp); break;
13160 case OP_AND: print_binary_op(state, "and", ins, fp); break;
13161 case OP_XOR: print_binary_op(state, "xor", ins, fp); break;
13162 case OP_OR: print_binary_op(state, "or", ins, fp); break;
13163 case OP_SL: print_op_shift(state, "shl", ins, fp); break;
13164 case OP_USR: print_op_shift(state, "shr", ins, fp); break;
13165 case OP_SSR: print_op_shift(state, "sar", ins, fp); break;
13166 case OP_POS: break;
13167 case OP_NEG: print_unary_op(state, "neg", ins, fp); break;
13168 case OP_INVERT: print_unary_op(state, "not", ins, fp); break;
13169 case OP_INTCONST:
13170 case OP_ADDRCONST:
13171 /* Don't generate anything here for constants */
13172 case OP_PHI:
13173 /* Don't generate anything for variable declarations. */
13174 break;
13175 case OP_SDECL:
13176 print_sdecl(state, ins, fp);
13177 break;
13178 case OP_WRITE:
13179 case OP_COPY:
13180 print_op_move(state, ins, fp);
13181 break;
13182 case OP_LOAD:
13183 print_op_load(state, ins, fp);
13184 break;
13185 case OP_STORE:
13186 print_op_store(state, ins, fp);
13187 break;
13188 case OP_SMUL:
13189 print_op_smul(state, ins, fp);
13190 break;
13191 case OP_CMP: print_op_cmp(state, ins, fp); break;
13192 case OP_TEST: print_op_test(state, ins, fp); break;
13193 case OP_JMP:
13194 case OP_JMP_EQ: case OP_JMP_NOTEQ:
13195 case OP_JMP_SLESS: case OP_JMP_ULESS:
13196 case OP_JMP_SMORE: case OP_JMP_UMORE:
13197 case OP_JMP_SLESSEQ: case OP_JMP_ULESSEQ:
13198 case OP_JMP_SMOREEQ: case OP_JMP_UMOREEQ:
13199 print_op_branch(state, ins, fp);
13200 break;
13201 case OP_SET_EQ: case OP_SET_NOTEQ:
13202 case OP_SET_SLESS: case OP_SET_ULESS:
13203 case OP_SET_SMORE: case OP_SET_UMORE:
13204 case OP_SET_SLESSEQ: case OP_SET_ULESSEQ:
13205 case OP_SET_SMOREEQ: case OP_SET_UMOREEQ:
13206 print_op_set(state, ins, fp);
13207 break;
13208 case OP_INB: case OP_INW: case OP_INL:
13209 print_op_in(state, ins, fp);
13210 break;
13211 case OP_OUTB: case OP_OUTW: case OP_OUTL:
13212 print_op_out(state, ins, fp);
13213 break;
13214 case OP_BSF:
13215 case OP_BSR:
13216 print_op_bit_scan(state, ins, fp);
13217 break;
13218 case OP_HLT:
13219 fprintf(fp, "\thlt\n");
13220 break;
13221 case OP_LABEL:
13222 if (!ins->use) {
13223 return;
13224 }
13225 fprintf(fp, "L%lu:\n", ins->u.cval);
13226 break;
13227 /* Operations I am not yet certain how to handle */
13228 case OP_UMUL:
13229 case OP_SDIV: case OP_UDIV:
13230 case OP_SMOD: case OP_UMOD:
13231 /* Operations that should never get here */
13232 case OP_LTRUE: case OP_LFALSE: case OP_EQ: case OP_NOTEQ:
13233 case OP_SLESS: case OP_ULESS: case OP_SMORE: case OP_UMORE:
13234 case OP_SLESSEQ: case OP_ULESSEQ: case OP_SMOREEQ: case OP_UMOREEQ:
13235 default:
13236 internal_error(state, ins, "unknown op: %d %s",
13237 ins->op, tops(ins->op));
13238 break;
13239 }
13240}
13241
13242static void print_instructions(struct compile_state *state)
13243{
13244 struct triple *first, *ins;
13245 int print_location;
13246 int last_line;
13247 int last_col;
13248 const char *last_filename;
13249 FILE *fp;
13250 print_location = 1;
13251 last_line = -1;
13252 last_col = -1;
13253 last_filename = 0;
13254 fp = stdout;
13255 fprintf(fp, ".section \".rom.text\"\n");
13256 first = state->main_function->left;
13257 ins = first;
13258 do {
13259 if (print_location &&
13260 ((last_filename != ins->filename) ||
13261 (last_line != ins->line) ||
13262 (last_col != ins->col))) {
13263 fprintf(fp, "\t/* %s:%d */\n",
13264 ins->filename, ins->line);
13265 last_filename = ins->filename;
13266 last_line = ins->line;
13267 last_col = ins->col;
13268 }
13269
13270 print_instruction(state, ins, fp);
13271 ins = ins->next;
13272 } while(ins != first);
13273
13274}
13275static void generate_code(struct compile_state *state)
13276{
13277 generate_local_labels(state);
13278 print_instructions(state);
13279
13280}
13281
13282static void print_tokens(struct compile_state *state)
13283{
13284 struct token *tk;
13285 tk = &state->token[0];
13286 do {
13287#if 1
13288 token(state, 0);
13289#else
13290 next_token(state, 0);
13291#endif
13292 loc(stdout, state, 0);
13293 printf("%s <- `%s'\n",
13294 tokens[tk->tok],
13295 tk->ident ? tk->ident->name :
13296 tk->str_len ? tk->val.str : "");
13297
13298 } while(tk->tok != TOK_EOF);
13299}
13300
13301static void compile(char *filename, int debug, int opt)
13302{
13303 int i;
13304 struct compile_state state;
13305 memset(&state, 0, sizeof(state));
13306 state.file = 0;
13307 for(i = 0; i < sizeof(state.token)/sizeof(state.token[0]); i++) {
13308 memset(&state.token[i], 0, sizeof(state.token[i]));
13309 state.token[i].tok = -1;
13310 }
13311 /* Remember the debug settings */
13312 state.debug = debug;
13313 state.optimize = opt;
13314 /* Prep the preprocessor */
13315 state.if_depth = 0;
13316 state.if_value = 0;
13317 /* register the C keywords */
13318 register_keywords(&state);
13319 /* register the keywords the macro preprocessor knows */
13320 register_macro_keywords(&state);
13321 /* Memorize where some special keywords are. */
13322 state.i_continue = lookup(&state, "continue", 8);
13323 state.i_break = lookup(&state, "break", 5);
13324 /* Enter the globl definition scope */
13325 start_scope(&state);
13326 register_builtins(&state);
13327 compile_file(&state, filename, 1);
13328#if 0
13329 print_tokens(&state);
13330#endif
13331 decls(&state);
13332 /* Exit the global definition scope */
13333 end_scope(&state);
13334
13335 /* Now that basic compilation has happened
13336 * optimize the intermediate code
13337 */
13338 optimize(&state);
13339 generate_code(&state);
13340 if (state.debug) {
13341 fprintf(stderr, "done\n");
13342 }
13343}
13344
13345static void version(void)
13346{
13347 printf("romcc " VERSION " released " RELEASE_DATE "\n");
13348}
13349
13350static void usage(void)
13351{
13352 version();
13353 printf(
13354 "Usage: romcc <source>.c\n"
13355 "Compile a C source file without using ram\n"
13356 );
13357}
13358
13359static void arg_error(char *fmt, ...)
13360{
13361 va_list args;
13362 va_start(args, fmt);
13363 vfprintf(stderr, fmt, args);
13364 va_end(args);
13365 usage();
13366 exit(1);
13367}
13368
13369int main(int argc, char **argv)
13370{
13371 char *filename;
13372 int last_argc;
13373 int debug;
13374 int optimize;
13375 optimize = 0;
13376 debug = 0;
13377 last_argc = -1;
13378 while((argc > 1) && (argc != last_argc)) {
13379 last_argc = argc;
13380 if (strncmp(argv[1], "--debug=", 8) == 0) {
13381 debug = atoi(argv[1] + 8);
13382 argv++;
13383 argc--;
13384 }
13385 else if ((strcmp(argv[1],"-O") == 0) ||
13386 (strcmp(argv[1], "-O1") == 0)) {
13387 optimize = 1;
13388 argv++;
13389 argc--;
13390 }
13391 else if (strcmp(argv[1],"-O2") == 0) {
13392 optimize = 2;
13393 argv++;
13394 argc--;
13395 }
13396 }
13397 if (argc != 2) {
13398 arg_error("Wrong argument count %d\n", argc);
13399 }
13400 filename = argv[1];
13401 compile(filename, debug, optimize);
13402
13403 return 0;
13404}