15 #define DEBUG_ERROR_MESSAGES 0
16 #define DEBUG_COLOR_GRAPH 0
18 #define X86_4_8BIT_GPRS 1
20 #warning "FIXME static constant variables"
21 #warning "FIXME enable pointers"
22 #warning "FIXME enable string constants"
24 /* Control flow graph of a loop without goto.
35 * |\ GGG HHH | continue;
63 * DFlocal(X) = { Y <- Succ(X) | idom(Y) != X }
64 * DFup(Z) = { Y <- DF(Z) | idom(Y) != X }
67 * [] == DFlocal(X) U DF(X)
70 * Dominator graph of the same nodes.
74 * BBB JJJ BBB: [ JJJ ] ( JJJ ) JJJ: [ ] ()
76 * CCC CCC: [ ] ( BBB, JJJ )
78 * DDD EEE DDD: [ ] ( BBB ) EEE: [ JJJ ] ()
80 * FFF FFF: [ ] ( BBB )
82 * GGG HHH GGG: [ ] ( BBB ) HHH: [ BBB ] ()
87 * BBB and JJJ are definitely the dominance frontier.
88 * Where do I place phi functions and how do I make that decision.
91 static void die(char *fmt, ...)
96 vfprintf(stderr, fmt, args);
103 #define MALLOC_STRONG_DEBUG
104 static void *xmalloc(size_t size, const char *name)
109 die("Cannot malloc %ld bytes to hold %s: %s\n",
110 size + 0UL, name, strerror(errno));
115 static void *xcmalloc(size_t size, const char *name)
118 buf = xmalloc(size, name);
119 memset(buf, 0, size);
123 static void xfree(const void *ptr)
128 static char *xstrdup(const char *str)
133 new = xmalloc(len + 1, "xstrdup string");
134 memcpy(new, str, len);
139 static void xchdir(const char *path)
141 if (chdir(path) != 0) {
142 die("chdir to %s failed: %s\n",
143 path, strerror(errno));
147 static int exists(const char *dirname, const char *filename)
151 if (access(filename, O_RDONLY) < 0) {
152 if ((errno != EACCES) && (errno != EROFS)) {
160 static char *slurp_file(const char *dirname, const char *filename, off_t *r_size)
164 off_t size, progress;
173 fd = open(filename, O_RDONLY);
175 die("Cannot open '%s' : %s\n",
176 filename, strerror(errno));
178 result = fstat(fd, &stats);
180 die("Cannot stat: %s: %s\n",
181 filename, strerror(errno));
183 size = stats.st_size;
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 */
189 while(progress < size) {
190 result = read(fd, buf + progress, size - progress);
192 if ((errno == EINTR) || (errno == EAGAIN))
194 die("read on %s of %ld bytes failed: %s\n",
195 filename, (size - progress)+ 0UL, strerror(errno));
201 die("Close of %s failed: %s\n",
202 filename, strerror(errno));
207 /* Long on the destination platform */
208 typedef unsigned long ulong_t;
212 struct file_state *prev;
213 const char *basename;
224 struct hash_entry *ident;
232 /* I have two classes of types:
234 * Logical types. (The type the C standard says the operation is of)
236 * The operational types are:
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.
258 /* Operations on general purpose registers.
275 #define OP_POS 14 /* Dummy positive operator don't use it */
285 #define OP_SLESSEQ 26
286 #define OP_ULESSEQ 27
287 #define OP_SMOREEQ 28
288 #define OP_UMOREEQ 29
290 #define OP_LFALSE 30 /* Test if the expression is logically false */
291 #define OP_LTRUE 31 /* Test if the expression is logcially true */
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.
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.
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.
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.
327 /* OP_COPY makes a copy of the psedo register or constant in op->left.
330 /* Hard operations that I don't know if they are worth supporting */
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.
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.
346 * Not seen outside of expressions.
349 /* OP_LAND performs a C logical and between triple->left and triple->right.
350 * Not seen outside of expressions.
353 /* OP_LOR performs a C logical or between triple->left and triple->right.
354 * Not seen outside of expressions.
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.
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.
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.
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.
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.
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...
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.
410 /* OP_DECL is a triple that establishes an lvalue for assignments.
411 * triple->use is a list of statements that use the variable.
415 /* OP_VAR is a triple that establishes a variable of static
417 * triple->use is a list of statements that use the variable.
418 * triple->left holds the initializer expression.
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.
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.
434 * triple->right holds a pointer to the original OP_DECL node
437 /* Architecture specific instructions */
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
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
463 /* Builtin operators that it is just simpler to use the compiler for */
472 #warning "FIXME implement rdmsr wrmsr"
474 /* I need to implement these but, I need to implment > 32bit return
482 static const char *table_ops[] = {
499 [OP_INVERT ] = "invert",
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",
515 [OP_STORE ] = "store",
519 [OP_INTCONST ] = "intconst",
520 [OP_BLOBCONST ] = "blobconst",
521 [OP_ADDRCONST ] = "addrconst",
523 [OP_WRITE ] = "write",
526 [OP_DEREF ] = "deref",
533 [OP_COMMA ] = "comma",
535 [OP_PRODUCT ] = "product",
538 [OP_BRANCH ] = "branch",
539 [OP_LABEL ] = "label",
540 [OP_ADECL ] = "adecl",
541 [OP_SDECL ] = "sdecl",
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",
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",
571 [OP_OUTB ] = "__outb",
572 [OP_OUTW ] = "__outw",
573 [OP_OUTL ] = "__outl",
580 #define OP_MAX (sizeof(table_ops)/sizeof(table_ops[0]))
583 static const char *tops(int index)
585 static const char unknown[] = "unknown op";
589 if (index > OP_MAX) {
592 return table_ops[index];
595 #warning "FIXME Finish defining struct type"
600 struct triple_set *next;
601 struct triple *member;
605 struct triple *next, *prev;
606 struct triple_set *use;
609 unsigned id; /* A scratch value and finally the register */
611 struct triple *right;
617 const char *filename;
623 struct block_set *next;
624 struct block *member;
627 struct block *work_next;
628 struct block *left, *right;
629 struct triple *first, *last;
631 struct block_set *use;
632 struct block_set *idominates;
633 struct block_set *domfrontier;
635 struct block_set *ipdominates;
636 struct block_set *ipdomfrontier;
644 struct hash_entry *ident;
651 struct hash_entry *ident;
657 struct hash_entry *next;
661 struct macro *sym_define;
662 struct symbol *sym_label;
663 struct symbol *sym_struct;
664 struct symbol *sym_ident;
667 #define HASH_TABLE_SIZE 2048
669 struct compile_state {
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;
677 int if_depth, if_value;
679 struct file_state *macro_file;
680 struct triple *main_function;
681 struct block *first_block, *last_block;
687 #define MAX_REGISTERS 75
688 #define MAX_REG_EQUIVS 16
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))
698 static unsigned alloc_virtual_reg(void)
700 static unsigned virtual_reg = MAX_REGISTERS;
705 static unsigned arch_reg_regcm(struct compile_state *state, int reg);
706 static void arch_reg_equivs(
707 struct compile_state *state, unsigned *equiv, int reg);
708 static int arch_select_free_register(
709 struct compile_state *state, char *used, int classes);
710 static unsigned arch_regc_size(struct compile_state *state, int class);
711 static int arch_regcm_intersect(unsigned regcm1, unsigned regcm2);
712 static unsigned arch_type_to_regcm(struct compile_state *state, struct type *type);
713 static const char *arch_reg_str(int reg);
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
725 #define GLOBAL_SCOPE_DEPTH 1
727 static void compile_file(struct compile_state *old_state, char *filename, int local);
729 static int get_col(struct file_state *file)
733 ptr = file->line_start;
735 for(col = 0; ptr < end; ptr++) {
740 col = (col & ~7) + 8;
746 static void loc(FILE *fp, struct compile_state *state, struct triple *triple)
750 fprintf(fp, "%s:%d.%d: ",
751 triple->filename, triple->line, triple->col);
757 col = get_col(state->file);
758 fprintf(fp, "%s:%d.%d: ",
759 state->file->basename, state->file->line, col);
762 static void __internal_error(struct compile_state *state, struct triple *ptr,
767 loc(stderr, state, ptr);
768 fprintf(stderr, "Internal compiler error: ");
769 vfprintf(stderr, fmt, args);
770 fprintf(stderr, "\n");
776 static void __internal_warning(struct compile_state *state, struct triple *ptr,
781 loc(stderr, state, ptr);
782 fprintf(stderr, "Internal compiler warning: ");
783 vfprintf(stderr, fmt, args);
784 fprintf(stderr, "\n");
790 static void __error(struct compile_state *state, struct triple *ptr,
795 loc(stderr, state, ptr);
796 vfprintf(stderr, fmt, args);
798 fprintf(stderr, "\n");
802 static void __warning(struct compile_state *state, struct triple *ptr,
807 loc(stderr, state, ptr);
808 fprintf(stderr, "warning: ");
809 vfprintf(stderr, fmt, args);
810 fprintf(stderr, "\n");
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
820 # define internal_error __internal_error
821 # define internal_warning __internal_warning
822 # define error __error
823 # define warning __warning
825 #define FINISHME() warning(state, 0, "FINISHME @ %s.%s:%d", __FILE__, __func__, __LINE__)
828 static void valid_op(struct compile_state *state, struct triple *ptr)
830 char *fmt = "invalid op: %d";
831 if (ptr->op >= OP_MAX) {
832 internal_error(state, 0, fmt, ptr->op);
835 internal_error(state, 0, fmt, ptr->op);
839 static void process_trigraphs(struct compile_state *state)
841 char *src, *dest, *end;
842 struct 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] == '?')) {
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;
875 file->size = dest - file->buf;
878 static void splice_lines(struct compile_state *state)
880 char *src, *dest, *end;
881 struct 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')) {
896 file->size = dest - file->buf;
899 static struct type void_type;
900 static void use_triple(struct triple *used, struct triple *user)
902 struct triple_set **ptr, *new;
909 if ((*ptr)->member == user) {
914 /* Append new to the head of the list,
915 * copy_func and rename_block_variables
918 new = xcmalloc(sizeof(*new), "triple_set");
920 new->next = used->use;
924 static void unuse_triple(struct triple *used, struct triple *unuser)
926 struct triple_set *use, **ptr;
930 if (use->member == unuser) {
940 static void push_triple(struct triple *used, struct triple *user)
942 struct triple_set *new;
947 /* Append new to the head of the list,
948 * it's the only sensible behavoir for a stack.
950 new = xcmalloc(sizeof(*new), "triple_set");
952 new->next = used->use;
956 static void pop_triple(struct triple *used, struct triple *unuser)
958 struct triple_set *use, **ptr;
962 if (use->member == unuser) {
965 /* Only free one occurance from the stack */
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.
979 static struct triple zero_triple = {
980 .next = &zero_triple,
981 .prev = &zero_triple,
984 .id = -1, /* An invalid id */
988 .filename = __FILE__,
992 static 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)
997 ret = xcmalloc(sizeof(*ret), "tripple");
1004 ret->filename = filename;
1010 static struct triple *triple(struct compile_state *state,
1011 int op, struct type *type, struct triple *left, struct triple *right)
1014 const char *filename;
1020 filename = state->file->basename;
1021 line = state->file->line;
1022 col = get_col(state->file);
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");
1030 use_triple(left, ret);
1035 static void insert_triple(struct compile_state *state,
1036 struct triple *first, struct triple *ptr)
1039 if (ptr->next != ptr) {
1040 internal_error(state, ptr, "expression already used");
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);
1053 static struct triple *pre_triple(struct compile_state *state,
1054 struct triple *base,
1055 int op, struct type *type, struct triple *left, struct triple *right)
1057 /* Careful this assumes it can do the easy thing to get the block */
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);
1066 static struct triple *post_triple(struct compile_state *state,
1067 struct triple *base,
1068 int op, struct type *type, struct triple *left, struct triple *right)
1070 /* Careful this assumes it can do the easy thing to get the block */
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);
1079 static struct triple *label(struct compile_state *state)
1081 /* Labels don't get a type */
1082 struct triple *result;
1083 result = triple(state, OP_LABEL, &void_type, 0, 0);
1087 static int triple_is_pure(struct compile_state *state, struct triple *ins)
1089 /* Does the triple have no side effects.
1090 * I.e. Rexecuting the triple with the same arguments
1091 * gives the same value.
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:
1100 case OP_USR: case OP_SSR:
1104 case OP_POS: case OP_NEG:
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:
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:
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:
1140 case OP_BSF: case OP_BSR:
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:
1150 internal_error(state, ins, "purity of %s not known",
1158 static int triple_is_branch(struct triple *ins)
1160 /* This function is used to determine which triples need
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:
1178 static int triple_is_def(struct triple *ins)
1180 /* This function is used to determine which triples need
1194 case OP_OUTB: case OP_OUTW: case OP_OUTL:
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:
1208 static struct triple **triple_targ(struct compile_state *state,
1209 struct triple *triple, struct triple **last)
1211 struct triple **ret;
1213 switch(triple->op) {
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:
1222 ret = &triple->left;
1224 else if ((last == &triple->left) && triple->right) {
1225 ret = &triple->next;
1232 static struct triple **triple_rhs(struct compile_state *state,
1233 struct triple *triple, struct triple **last)
1235 struct triple **ret;
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:
1246 case OP_OUTB: case OP_OUTW: case OP_OUTL:
1248 if (!triple->left) {
1249 internal_error(state, triple, "left arg missing");
1251 if (!triple->right) {
1252 internal_error(state, triple, "right arg missing");
1256 ret = &triple->left;
1258 else if (last == &triple->left){
1259 ret = &triple->right;
1262 /* unary operations */
1263 case OP_POS: case OP_NEG:
1264 case OP_INVERT: case OP_LFALSE: case OP_LTRUE:
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:
1275 if (!triple->left) {
1276 internal_error(state, triple, "left arg missing");
1278 if (triple->right) {
1279 internal_error(state, triple, "right arg present");
1283 ret = &triple->left;
1290 ret = &triple->right;
1296 ret = &triple->left;
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;
1314 struct triple **slot;
1315 struct block *block;
1316 block = triple->u.block;
1317 slot = (struct triple **)(triple->left);
1321 else if ((last >= slot) && (last < (slot + block->users -1))) {
1329 /* address constant.. */
1332 ret = &triple->left;
1337 /* Variables and labels */
1338 case OP_ADECL: case OP_SDECL: case OP_LABEL:
1344 /* These operations that have no rhs expression */
1347 internal_error(state, 0, "unknown expression type: %d %s",
1348 triple->op, tops(triple->op));
1355 static struct triple **triple_lhs(struct compile_state *state,
1356 struct triple *triple, struct triple **last)
1358 struct triple **ret;
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:
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:
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:
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:
1394 /* Address constants */
1396 /* Variables and labels */
1397 case OP_ADECL: case OP_SDECL: case OP_LABEL:
1403 /* These expressions have no lhs expression */
1410 ret = &triple->left;
1414 internal_error(state, 0, "unknown expression type: %d %s",
1415 triple->op, tops(triple->op));
1421 static void free_triple(struct compile_state *state, struct triple *ptr)
1423 ptr->prev->next = ptr->next;
1424 ptr->next->prev = ptr->prev;
1426 internal_error(state, ptr, "ptr->use != 0");
1428 if (ptr->op == OP_PHI) {
1431 memset(ptr, -1, sizeof(*ptr));
1435 static void release_triple(struct compile_state *state, struct triple *ptr)
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)) {
1443 unuse_triple(*expr, ptr);
1446 expr = triple_lhs(state, ptr, 0);
1447 for(; expr; expr = triple_lhs(state, ptr, expr)) {
1449 unuse_triple(*expr, ptr);
1452 expr = triple_targ(state, ptr, 0);
1453 for(; expr; expr = triple_targ(state, ptr, expr)) {
1455 unuse_triple(*expr, ptr);
1458 /* Reomve ptr from use chains where it is used */
1459 for(set = ptr->use; set; set = next) {
1461 expr = triple_rhs(state, set->member, 0);
1462 for(; expr; expr = triple_rhs(state, set->member, expr)) {
1464 *expr = &zero_triple;
1467 expr = triple_lhs(state, set->member, 0);
1468 for(; expr; expr = triple_lhs(state, set->member, expr)) {
1470 *expr = &zero_triple;
1473 expr = triple_targ(state, set->member, 0);
1474 for(; expr; expr = triple_targ(state, set->member, expr)) {
1476 *expr = &zero_triple;
1479 unuse_triple(ptr, set->member);
1481 free_triple(state, ptr);
1484 static void print_triple(struct compile_state *state, struct triple *ptr);
1486 #define TOK_UNKNOWN 0
1489 #define TOK_LBRACE 3
1490 #define TOK_RBRACE 4
1494 #define TOK_LBRACKET 8
1495 #define TOK_RBRACKET 9
1496 #define TOK_LPAREN 10
1497 #define TOK_RPAREN 11
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
1509 #define TOK_ANDEQ 23
1510 #define TOK_XOREQ 24
1513 #define TOK_NOTEQ 27
1514 #define TOK_QUEST 28
1515 #define TOK_LOGOR 29
1516 #define TOK_LOGAND 30
1520 #define TOK_LESSEQ 34
1521 #define TOK_MOREEQ 35
1525 #define TOK_MINUS 39
1528 #define TOK_PLUSPLUS 42
1529 #define TOK_MINUSMINUS 43
1531 #define TOK_ARROW 45
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
1541 #define TOK_IDENT 54
1542 #define TOK_STRUCT_NAME 55
1543 #define TOK_ENUM_CONST 56
1544 #define TOK_TYPE_NAME 57
1547 #define TOK_BREAK 59
1550 #define TOK_CONST 62
1551 #define TOK_CONTINUE 63
1552 #define TOK_DEFAULT 64
1554 #define TOK_DOUBLE 66
1557 #define TOK_EXTERN 69
1558 #define TOK_FLOAT 70
1562 #define TOK_INLINE 74
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
1578 #define TOK_VOLATILE 90
1579 #define TOK_WHILE 91
1581 #define TOK_ATTRIBUTE 93
1582 #define TOK_ALIGNOF 94
1583 #define TOK_FIRST_KEYWORD TOK_AUTO
1584 #define TOK_LAST_KEYWORD TOK_ALIGNOF
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
1598 #define TOK_FIRST_MACRO TOK_DEFINE
1599 #define TOK_LAST_MACRO TOK_ENDIF
1603 static const char *tokens[] = {
1604 [TOK_UNKNOWN ] = "unknown",
1605 [TOK_SPACE ] = ":space:",
1607 [TOK_LBRACE ] = "{",
1608 [TOK_RBRACE ] = "}",
1612 [TOK_LBRACKET ] = "[",
1613 [TOK_RBRACKET ] = "]",
1614 [TOK_LPAREN ] = "(",
1615 [TOK_RPAREN ] = ")",
1617 [TOK_DOTS ] = "...",
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 ] = "^=",
1631 [TOK_NOTEQ ] = "!=",
1633 [TOK_LOGOR ] = "||",
1634 [TOK_LOGAND ] = "&&",
1638 [TOK_LESSEQ ] = "<=",
1639 [TOK_MOREEQ ] = ">=",
1646 [TOK_PLUSPLUS ] = "++",
1647 [TOK_MINUSMINUS ] = "--",
1649 [TOK_ARROW ] = "->",
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:",
1659 [TOK_CONCATENATE ] = "##",
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",
1669 [TOK_DOUBLE ] = "double",
1670 [TOK_ELSE ] = "else",
1671 [TOK_ENUM ] = "enum",
1672 [TOK_EXTERN ] = "extern",
1673 [TOK_FLOAT ] = "float",
1675 [TOK_GOTO ] = "goto",
1677 [TOK_INLINE ] = "inline",
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",
1696 [TOK_ATTRIBUTE ] = "__attribute__",
1697 [TOK_ALIGNOF ] = "__alignof__",
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",
1714 static unsigned int hash(const char *str, int str_len)
1718 end = str + str_len;
1720 for(; str < end; str++) {
1721 hash = (hash *263) + *str;
1723 hash = hash & (HASH_TABLE_SIZE -1);
1727 static struct hash_entry *lookup(
1728 struct compile_state *state, const char *name, int name_len)
1730 struct hash_entry *entry;
1732 index = hash(name, name_len);
1733 entry = state->hash_table[index];
1735 ((entry->name_len != name_len) ||
1736 (memcmp(entry->name, name, name_len) != 0))) {
1737 entry = entry->next;
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';
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;
1752 /* Place the new entry in the hash table */
1753 state->hash_table[index] = entry;
1758 static void ident_to_keyword(struct compile_state *state, struct token *tk)
1760 struct hash_entry *entry;
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;
1770 static void ident_to_macro(struct compile_state *state, struct token *tk)
1772 struct hash_entry *entry;
1775 (entry->tok >= TOK_FIRST_MACRO) &&
1776 (entry->tok <= TOK_LAST_MACRO)) {
1777 tk->tok = entry->tok;
1781 static void hash_keyword(
1782 struct compile_state *state, const char *keyword, int tok)
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);
1793 struct compile_state *state, struct hash_entry *ident,
1794 struct symbol **chain, struct triple *def, struct type *type)
1797 if (*chain && ((*chain)->scope_depth == state->scope_depth)) {
1798 error(state, 0, "%s already defined", ident->name);
1800 sym = xcmalloc(sizeof(*sym), "symbol");
1804 sym->scope_depth = state->scope_depth;
1809 static void start_scope(struct compile_state *state)
1811 state->scope_depth++;
1814 static void end_scope_syms(struct symbol **chain, int depth)
1816 struct symbol *sym, *next;
1818 while(sym && (sym->scope_depth == depth)) {
1826 static void end_scope(struct compile_state *state)
1830 /* Walk through the hash table and remove all symbols
1831 * in the current scope.
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];
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;
1844 state->scope_depth = depth - 1;
1847 static void register_keywords(struct compile_state *state)
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);
1888 static void register_macro_keywords(struct compile_state *state)
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);
1903 static int spacep(int c)
1919 static int digitp(int c)
1923 case '0': case '1': case '2': case '3': case '4':
1924 case '5': case '6': case '7': case '8': case '9':
1931 static int hexdigitp(int 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':
1944 static int hexdigval(int c)
1947 if ((c >= '0') && (c <= '9')) {
1950 else if ((c >= 'A') && (c <= 'F')) {
1951 val = 10 + (c - 'A');
1953 else if ((c >= 'a') && (c <= 'f')) {
1954 val = 10 + (c - 'a');
1959 static int octdigitp(int c)
1963 case '0': case '1': case '2': case '3':
1964 case '4': case '5': case '6': case '7':
1970 static int octdigval(int c)
1973 if ((c >= '0') && (c <= '7')) {
1979 static int letterp(int 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':
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':
2002 static int char_value(struct compile_state *state,
2003 const signed char **strp, const signed char *end)
2005 const signed char *str;
2009 if ((c == '\\') && (str < end)) {
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;
2025 while((str < end) && hexdigitp(*str)) {
2027 c += hexdigval(*str);
2031 case '0': case '1': case '2': case '3':
2032 case '4': case '5': case '6': case '7':
2034 while((str < end) && octdigitp(*str)) {
2036 c += octdigval(*str);
2041 error(state, 0, "Invalid character constant");
2049 static char *after_digits(char *ptr, char *end)
2051 while((ptr < end) && digitp(*ptr)) {
2057 static char *after_octdigits(char *ptr, char *end)
2059 while((ptr < end) && octdigitp(*ptr)) {
2065 static char *after_hexdigits(char *ptr, char *end)
2067 while((ptr < end) && hexdigitp(*ptr)) {
2073 static void save_string(struct compile_state *state,
2074 struct token *tk, char *start, char *end, const char *id)
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';
2084 /* Store the copy in the token */
2086 tk->str_len = str_len;
2088 static void next_token(struct compile_state *state, int index)
2090 struct file_state *file;
2098 tk = &state->token[index];
2101 token = tokp = file->pos;
2102 end = file->buf + file->size;
2109 if ((tokp + 1) < end) {
2113 if ((tokp + 2) < end) {
2117 if ((tokp + 3) < end) {
2125 else if (spacep(c)) {
2127 while ((tokp < end) && spacep(c)) {
2130 file->line_start = tokp + 1;
2139 else if ((c == '/') && (c1 == '/')) {
2141 for(tokp += 2; tokp < end; tokp++) {
2145 file->line_start = tokp +1;
2151 else if ((c == '/') && (c1 == '*')) {
2155 line_start = file->line_start;
2156 for(tokp += 2; (end - tokp) >= 2; tokp++) {
2160 line_start = tokp +1;
2162 else if ((c == '*') && (tokp[1] == '/')) {
2168 if (tok == TOK_UNKNOWN) {
2169 error(state, 0, "unterminated comment");
2172 file->line_start = line_start;
2174 /* string constants */
2175 else if ((c == '"') ||
2176 ((c == 'L') && (c1 == '"'))) {
2181 line_start = file->line_start;
2187 for(tokp += 1; tokp < end; tokp++) {
2191 line_start = tokp + 1;
2193 else if ((c == '\\') && (tokp +1 < end)) {
2196 else if (c == '"') {
2197 tok = TOK_LIT_STRING;
2201 if (tok == TOK_UNKNOWN) {
2202 error(state, 0, "unterminated string constant");
2204 if (line != file->line) {
2205 warning(state, 0, "multiline string constant");
2208 file->line_start = line_start;
2210 /* Save the string value */
2211 save_string(state, tk, token, tokp, "literal string");
2213 /* character constants */
2214 else if ((c == '\'') ||
2215 ((c == 'L') && (c1 == '\''))) {
2220 line_start = file->line_start;
2226 for(tokp += 1; tokp < end; tokp++) {
2230 line_start = tokp + 1;
2232 else if ((c == '\\') && (tokp +1 < end)) {
2235 else if (c == '\'') {
2240 if (tok == TOK_UNKNOWN) {
2241 error(state, 0, "unterminated character constant");
2243 if (line != file->line) {
2244 warning(state, 0, "multiline character constant");
2247 file->line_start = line_start;
2249 /* Save the character value */
2250 save_string(state, tk, token, tokp, "literal character");
2252 /* integer and floating constants
2258 * Floating constants
2259 * {digits}.{digits}[Ee][+-]?{digits}
2261 * {digits}[Ee][+-]?{digits}
2262 * .{digits}[Ee][+-]?{digits}
2266 else if (digitp(c) || ((c == '.') && (digitp(c1)))) {
2271 next = after_digits(tokp, end);
2276 if (next[0] == '.') {
2277 new = after_digits(next, end);
2278 is_float = (new != next);
2281 if ((next[0] == 'e') || (next[0] == 'E')) {
2282 if (((next + 1) < end) &&
2283 ((next[1] == '+') || (next[1] == '-'))) {
2286 new = after_digits(next, end);
2287 is_float = (new != next);
2291 tok = TOK_LIT_FLOAT;
2292 if ((next < end) && (
2301 if (!is_float && digitp(c)) {
2303 if ((c == '0') && ((c1 == 'x') || (c1 == 'X'))) {
2304 next = after_hexdigits(tokp + 2, end);
2306 else if (c == '0') {
2307 next = after_octdigits(tokp, end);
2310 next = after_digits(tokp, end);
2312 /* crazy integer suffixes */
2314 ((next[0] == 'u') || (next[0] == 'U'))) {
2317 ((next[0] == 'l') || (next[0] == 'L'))) {
2321 else if ((next < end) &&
2322 ((next[0] == 'l') || (next[0] == 'L'))) {
2325 ((next[0] == 'u') || (next[0] == 'U'))) {
2332 /* Save the integer/floating point value */
2333 save_string(state, tk, token, tokp, "literal number");
2336 else if (letterp(c)) {
2338 for(tokp += 1; tokp < end; tokp++) {
2340 if (!letterp(c) && !digitp(c)) {
2345 tk->ident = lookup(state, token, tokp +1 - token);
2347 /* C99 alternate macro characters */
2348 else if ((c == '%') && (c1 == ':') && (c2 == '%') && (c3 == ':')) {
2350 tok = TOK_CONCATENATE;
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 */
2408 for(ptr = file->line_start; spacep(*ptr); ptr++)
2414 if (tok == TOK_UNKNOWN) {
2415 error(state, 0, "unknown token");
2418 file->pos = tokp + 1;
2420 if (tok == TOK_IDENT) {
2421 ident_to_keyword(state, tk);
2423 /* Don't return space tokens. */
2424 if (tok == TOK_SPACE) {
2429 static void compile_macro(struct compile_state *state, struct token *tk)
2431 struct file_state *file;
2432 struct hash_entry *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;
2445 file->prev = state->file;
2450 static int mpeek(struct compile_state *state, int index)
2454 tk = &state->token[index + 1];
2455 if (tk->tok == -1) {
2456 next_token(state, index + 1);
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);
2469 next_token(state, index + 1);
2472 else if (tk->ident && tk->ident->sym_define) {
2473 compile_macro(state, tk);
2474 next_token(state, index + 1);
2478 /* Don't show the token on the next line */
2479 if (state->macro_line < state->macro_file->line) {
2482 return state->token[index +1].tok;
2485 static void meat(struct compile_state *state, int index, int tok)
2489 next_tok = mpeek(state, index);
2490 if (next_tok != tok) {
2491 const char *name1, *name2;
2492 name1 = tokens[next_tok];
2494 if (next_tok == TOK_IDENT) {
2495 name2 = state->token[index + 1].ident->name;
2497 error(state, 0, "found %s %s expected %s",
2498 name1, name2, tokens[tok]);
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);
2506 for(i = index; i < sizeof(state->token)/sizeof(state->token[0]) - 1; i++) {
2507 state->token[i] = state->token[i + 1];
2509 memset(&state->token[i], 0, sizeof(state->token[i]));
2510 state->token[i].tok = -1;
2513 static long_t mcexpr(struct compile_state *state, int index);
2515 static long_t mprimary_expr(struct compile_state *state, int index)
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);
2528 meat(state, index, TOK_LPAREN);
2529 val = mcexpr(state, index);
2530 meat(state, index, TOK_RPAREN);
2535 meat(state, index, TOK_LIT_INT);
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");
2545 meat(state, index, TOK_LIT_INT);
2550 static long_t munary_expr(struct compile_state *state, int index)
2553 switch(mpeek(state, index)) {
2555 meat(state, index, TOK_PLUS);
2556 val = munary_expr(state, index);
2560 meat(state, index, TOK_MINUS);
2561 val = munary_expr(state, index);
2565 meat(state, index, TOK_BANG);
2566 val = munary_expr(state, index);
2570 meat(state, index, TOK_BANG);
2571 val = munary_expr(state, index);
2575 val = mprimary_expr(state, index);
2581 static long_t mmul_expr(struct compile_state *state, int index)
2585 val = munary_expr(state, index);
2589 switch(mpeek(state, index)) {
2591 meat(state, index, TOK_STAR);
2592 right = munary_expr(state, index);
2596 meat(state, index, TOK_DIV);
2597 right = munary_expr(state, index);
2601 meat(state, index, TOK_MOD);
2602 right = munary_expr(state, index);
2614 static long_t madd_expr(struct compile_state *state, int index)
2618 val = mmul_expr(state, index);
2622 switch(mpeek(state, index)) {
2624 meat(state, index, TOK_PLUS);
2625 right = mmul_expr(state, index);
2629 meat(state, index, TOK_MINUS);
2630 right = mmul_expr(state, index);
2642 static long_t mshift_expr(struct compile_state *state, int index)
2646 val = madd_expr(state, index);
2650 switch(mpeek(state, index)) {
2652 meat(state, index, TOK_SL);
2653 right = madd_expr(state, index);
2657 meat(state, index, TOK_SR);
2658 right = madd_expr(state, index);
2670 static long_t mrel_expr(struct compile_state *state, int index)
2674 val = mshift_expr(state, index);
2678 switch(mpeek(state, index)) {
2680 meat(state, index, TOK_LESS);
2681 right = mshift_expr(state, index);
2685 meat(state, index, TOK_MORE);
2686 right = mshift_expr(state, index);
2690 meat(state, index, TOK_LESSEQ);
2691 right = mshift_expr(state, index);
2695 meat(state, index, TOK_MOREEQ);
2696 right = mshift_expr(state, index);
2707 static long_t meq_expr(struct compile_state *state, int index)
2711 val = mrel_expr(state, index);
2715 switch(mpeek(state, index)) {
2717 meat(state, index, TOK_EQEQ);
2718 right = mrel_expr(state, index);
2722 meat(state, index, TOK_NOTEQ);
2723 right = mrel_expr(state, index);
2734 static long_t mand_expr(struct compile_state *state, int index)
2737 val = meq_expr(state, index);
2738 if (mpeek(state, index) == TOK_AND) {
2740 meat(state, index, TOK_AND);
2741 right = meq_expr(state, index);
2747 static long_t mxor_expr(struct compile_state *state, int index)
2750 val = mand_expr(state, index);
2751 if (mpeek(state, index) == TOK_XOR) {
2753 meat(state, index, TOK_XOR);
2754 right = mand_expr(state, index);
2760 static long_t mor_expr(struct compile_state *state, int index)
2763 val = mxor_expr(state, index);
2764 if (mpeek(state, index) == TOK_OR) {
2766 meat(state, index, TOK_OR);
2767 right = mxor_expr(state, index);
2773 static long_t mland_expr(struct compile_state *state, int index)
2776 val = mor_expr(state, index);
2777 if (mpeek(state, index) == TOK_LOGAND) {
2779 meat(state, index, TOK_LOGAND);
2780 right = mor_expr(state, index);
2785 static long_t mlor_expr(struct compile_state *state, int index)
2788 val = mland_expr(state, index);
2789 if (mpeek(state, index) == TOK_LOGOR) {
2791 meat(state, index, TOK_LOGOR);
2792 right = mland_expr(state, index);
2798 static long_t mcexpr(struct compile_state *state, int index)
2800 return mlor_expr(state, index);
2802 static void preprocess(struct compile_state *state, int index)
2804 /* Doing much more with the preprocessor would require
2805 * a parser and a major restructuring.
2806 * Postpone that for later.
2808 struct file_state *file;
2814 tk = &state->token[index];
2815 state->macro_line = line = file->line;
2816 state->macro_file = file;
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'",
2828 if (state->if_value < 0) {
2831 warning(state, 0, "Ignoring preprocessor directive: %s",
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");
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;
2844 /* If the previous #if was not taken see if the #elif enables the
2847 else if ((state->if_value < 0) &&
2848 (state->if_depth == - state->if_value))
2850 if (mcexpr(state, index) != 0) {
2851 state->if_value = state->if_depth;
2854 state->if_value = - state->if_depth;
2860 if (state->if_value < 0) {
2863 if (mcexpr(state, index) != 0) {
2864 state->if_value = state->if_depth;
2867 state->if_value = - state->if_depth;
2872 if (state->if_value < 0) {
2875 next_token(state, index);
2876 if ((line != file->line) || (tk->tok != TOK_IDENT)) {
2877 error(state, 0, "Invalid macro name");
2879 if (tk->ident->sym_define == 0) {
2880 state->if_value = state->if_depth;
2883 state->if_value = - state->if_depth;
2888 if (state->if_value < 0) {
2891 next_token(state, index);
2892 if ((line != file->line) || (tk->tok != TOK_IDENT)) {
2893 error(state, 0, "Invalid macro name");
2895 if (tk->ident->sym_define != 0) {
2896 state->if_value = state->if_depth;
2899 state->if_value = - state->if_depth;
2903 if (state->if_depth == 0) {
2904 error(state, 0, "#else without #if");
2906 if ((state->if_value >= 0) ||
2907 ((state->if_value < 0) &&
2908 (state->if_depth == -state->if_value)))
2910 state->if_value = - state->if_value;
2914 if (state->if_depth == 0) {
2915 error(state, 0, "#endif without #if");
2917 if ((state->if_value >= 0) ||
2918 ((state->if_value < 0) &&
2919 (state->if_depth == -state->if_value)))
2921 state->if_value = state->if_depth - 1;
2927 struct hash_entry *ident;
2928 struct macro *macro;
2931 if (state->if_value < 0) /* quit early when #if'd out */
2934 meat(state, index, TOK_IDENT);
2938 if (*file->pos == '(') {
2939 #warning "FIXME macros with arguments not supported"
2940 error(state, 0, "Macros with arguments not supported");
2943 /* Find the end of the line to get an estimate of
2944 * the macro's length.
2946 for(ptr = file->pos; *ptr != '\n'; ptr++)
2949 if (ident->sym_define != 0) {
2950 error(state, 0, "macro %s already defined\n", ident->name);
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");
2957 memcpy(macro->buf, file->pos, macro->buf_len);
2958 macro->buf[macro->buf_len] = '\n';
2959 macro->buf[macro->buf_len +1] = '\0';
2961 ident->sym_define = macro;
2968 /* Find the end of the line */
2969 for(end = file->pos; *end != '\n'; end++)
2971 len = (end - file->pos);
2972 if (state->if_value >= 0) {
2973 error(state, 0, "%*.*s", len, len, file->pos);
2982 /* Find the end of the line */
2983 for(end = file->pos; *end != '\n'; end++)
2985 len = (end - file->pos);
2986 if (state->if_value >= 0) {
2987 warning(state, 0, "%*.*s", len, len, file->pos);
2999 next_token(state, index);
3000 if (tk->tok == TOK_LIT_STRING) {
3003 name = xmalloc(tk->str_len, "include");
3004 token = tk->val.str +1;
3005 name_len = tk->str_len -2;
3006 if (*token == '"') {
3010 memcpy(name, token, name_len);
3011 name[name_len] = '\0';
3014 else if (tk->tok == TOK_LESS) {
3017 for(end = start; *end != '\n'; end++) {
3023 error(state, 0, "Unterminated included directive");
3025 name = xmalloc(end - start + 1, "include");
3026 memcpy(name, start, end - start);
3027 name[end - start] = '\0';
3032 error(state, 0, "Invalid include directive");
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");
3040 if (state->if_value >= 0) {
3041 compile_file(state, name, local);
3044 next_token(state, index);
3048 /* Ignore # without a following ident */
3049 if (tk->tok == TOK_IDENT) {
3050 error(state, 0, "Invalid preprocessor directive: %s",
3055 /* Consume the rest of the macro line */
3057 tok = mpeek(state, index);
3058 meat(state, index, tok);
3059 } while(tok != TOK_EOF);
3063 static void token(struct compile_state *state, int index)
3065 struct file_state *file;
3069 tk = &state->token[index];
3070 next_token(state, index);
3074 if (tk->tok == TOK_EOF && file->prev) {
3075 state->file = file->prev;
3076 /* file->basename is used keep it */
3077 xfree(file->dirname);
3080 next_token(state, index);
3083 else if (tk->tok == TOK_MACRO) {
3084 preprocess(state, index);
3087 else if (tk->ident && tk->ident->sym_define) {
3088 compile_macro(state, tk);
3089 next_token(state, index);
3092 else if (state->if_value < 0) {
3093 next_token(state, index);
3099 static int peek(struct compile_state *state)
3101 if (state->token[1].tok == -1) {
3104 return state->token[1].tok;
3107 static int peek2(struct compile_state *state)
3109 if (state->token[1].tok == -1) {
3112 if (state->token[2].tok == -1) {
3115 return state->token[2].tok;
3119 const char *file, const char *func, int line,
3120 struct compile_state *state, int tok)
3124 next_tok = peek(state);
3125 if (next_tok != tok) {
3126 const char *name1, *name2;
3127 name1 = tokens[next_tok];
3129 if (next_tok == TOK_IDENT) {
3130 name2 = state->token[1].ident->name;
3132 internal_error(state, 0, "@ %s.%s:%d \tfound %s %s expected %s",
3134 name1, name2, tokens[tok]);
3136 /* Free the old token value */
3137 if (state->token[0].str_len) {
3138 xfree((void *)(state->token[0].val.str));
3140 for(i = 0; i < sizeof(state->token)/sizeof(state->token[0]) - 1; i++) {
3141 state->token[i] = state->token[i + 1];
3143 memset(&state->token[i], 0, sizeof(state->token[i]));
3144 state->token[i].tok = -1;
3146 #define eat(state, tok) __eat(__FILE__, __func__, __LINE__, state, tok)
3148 #warning "FIXME do not hardcode the include paths"
3149 static 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",
3156 static void compile_file(struct compile_state *state, char *filename, int local)
3159 char *subdir, *base;
3161 struct file_state *file;
3163 file = xmalloc(sizeof(*file), "file_state");
3165 base = strrchr(filename, '/');
3168 subdir_len = base - filename;
3175 basename = xmalloc(strlen(base) +1, "basename");
3176 strcpy(basename, base);
3177 file->basename = basename;
3179 if (getcwd(cwd, sizeof(cwd)) == 0) {
3180 die("cwd buffer to small");
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';
3192 /* Find the appropriate directory... */
3194 if (!state->file && exists(cwd, filename)) {
3197 if (local && state->file && exists(state->file->dirname, filename)) {
3198 dir = state->file->dirname;
3200 for(path = include_paths; !dir && *path; path++) {
3201 if (exists(*path, filename)) {
3206 error(state, 0, "Cannot find `%s'\n", filename);
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';
3215 file->buf = slurp_file(file->dirname, file->basename, &file->size);
3218 file->pos = file->buf;
3219 file->line_start = file->pos;
3222 file->prev = state->file;
3225 process_trigraphs(state);
3226 splice_lines(state);
3229 /* visibility global/local */
3230 /* static/auto duration */
3231 /* typedef, register, inline */
3232 #define STOR_SHIFT 0
3233 #define STOR_MASK 0x000f
3235 #define STOR_GLOBAL 0x0001
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
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
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.
3283 #define TYPE_FUNCTION 0x1300
3284 /* For TYPE_FUNCTION:
3285 * type->left holds the return type.
3286 * type->right holds the...
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.
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.
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.
3304 #define ELEMENT_COUNT_UNSPECIFIED (~0UL)
3308 struct type *left, *right;
3310 struct hash_entry *ident;
3313 static struct type *new_type(
3314 unsigned int type, struct type *left, struct type *right)
3316 struct type *result;
3317 result = xmalloc(sizeof(*result), "type");
3318 result->type = type;
3319 result->left = left;
3320 result->right = right;
3325 static struct type *clone_type(unsigned int specifiers, struct type *old)
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;
3335 #define SIZEOF_SHORT 2
3336 #define SIZEOF_INT 4
3337 #define SIZEOF_LONG (sizeof(long_t))
3339 #define ALIGNOF_SHORT 2
3340 #define ALIGNOF_INT 4
3341 #define ALIGNOF_LONG (sizeof(long_t))
3343 #define MASK_UCHAR(X) ((X) & ((ulong_t)0xff))
3344 #define MASK_USHORT(X) ((X) & (((ulong_t)1 << (SIZEOF_SHORT*8)) - 1))
3345 static inline ulong_t mask_uint(ulong_t x)
3347 if (SIZEOF_INT < SIZEOF_LONG) {
3348 ulong_t mask = (((ulong_t)1) << ((ulong_t)(SIZEOF_INT*8))) -1;
3353 #define MASK_UINT(X) (mask_uint(X))
3354 #define MASK_ULONG(X) (X)
3357 static struct type void_type = { .type = TYPE_VOID };
3358 static struct type char_type = { .type = TYPE_CHAR };
3359 static struct type uchar_type = { .type = TYPE_UCHAR };
3360 static struct type short_type = { .type = TYPE_SHORT };
3361 static struct type ushort_type = { .type = TYPE_USHORT };
3362 static struct type int_type = { .type = TYPE_INT };
3363 static struct type uint_type = { .type = TYPE_UINT };
3364 static struct type long_type = { .type = TYPE_LONG };
3365 static struct type ulong_type = { .type = TYPE_ULONG };
3367 static struct triple *variable(struct compile_state *state, struct type *type)
3369 struct triple *result;
3370 if ((type->type & STOR_MASK) != STOR_PERM) {
3371 result = triple(state, OP_ADECL, type, 0, 0);
3374 result = triple(state, OP_SDECL, type, 0, 0);
3379 static void stor_of(FILE *fp, struct type *type)
3381 switch(type->type & STOR_MASK) {
3383 fprintf(fp, "auto ");
3386 fprintf(fp, "static ");
3389 fprintf(fp, "extern ");
3392 fprintf(fp, "register ");
3395 fprintf(fp, "typedef ");
3398 fprintf(fp, "inline ");
3402 static void qual_of(FILE *fp, struct type *type)
3404 if (type->type & QUAL_CONST) {
3405 fprintf(fp, " const");
3407 if (type->type & QUAL_VOLATILE) {
3408 fprintf(fp, " volatile");
3410 if (type->type & QUAL_RESTRICT) {
3411 fprintf(fp, " restrict");
3414 static void name_of(FILE *fp, struct type *type)
3417 switch(type->type & TYPE_MASK) {
3419 fprintf(fp, "void");
3423 fprintf(fp, "signed char");
3427 fprintf(fp, "unsigned char");
3431 fprintf(fp, "signed short");
3435 fprintf(fp, "unsigned short");
3439 fprintf(fp, "signed int");
3443 fprintf(fp, "unsigned int");
3447 fprintf(fp, "signed long");
3451 fprintf(fp, "unsigned long");
3455 name_of(fp, type->left);
3461 name_of(fp, type->left);
3463 name_of(fp, type->right);
3466 fprintf(fp, "enum %s", type->ident->name);
3470 fprintf(fp, "struct %s", type->ident->name);
3475 name_of(fp, type->left);
3476 fprintf(fp, " (*)(");
3477 name_of(fp, type->right);
3482 name_of(fp, type->left);
3483 fprintf(fp, " [%ld]", type->elements);
3486 fprintf(fp, "????: %x", type->type & TYPE_MASK);
3491 static size_t align_of(struct compile_state *state, struct type *type)
3495 switch(type->type & TYPE_MASK) {
3505 align = ALIGNOF_SHORT;
3510 align = ALIGNOF_INT;
3515 align = ALIGNOF_LONG;
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;
3527 align = align_of(state, type->left);
3530 error(state, 0, "alignof not yet defined for type\n");
3536 static size_t size_of(struct compile_state *state, struct type *type)
3540 switch(type->type & TYPE_MASK) {
3550 size = SIZEOF_SHORT;
3565 size = size_of(state, type->left);
3566 while((type->right->type & TYPE_MASK) == TYPE_PRODUCT) {
3568 align = align_of(state, type->left);
3569 pad = align - (size % align);
3570 size = size + pad + size_of(state, type->left);
3572 align = align_of(state, type->right);
3573 pad = align - (size % align);
3574 size = size + pad + sizeof(type->right);
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;
3586 if (type->elements == ELEMENT_COUNT_UNSPECIFIED) {
3587 internal_error(state, 0, "Invalid array type");
3589 size = size_of(state, type->left) * type->elements;
3593 error(state, 0, "sizeof not yet defined for type\n");
3599 static void arrays_complete(struct compile_state *state, struct type *type)
3601 if ((type->type & TYPE_MASK) == TYPE_ARRAY) {
3602 if (type->elements == ELEMENT_COUNT_UNSPECIFIED) {
3603 error(state, 0, "array size not specified");
3605 arrays_complete(state, type->left);
3609 static unsigned int do_integral_promotion(unsigned int type)
3612 if (TYPE_INTEGER(type) &&
3613 TYPE_RANK(type) < TYPE_RANK(TYPE_INT)) {
3619 static unsigned int do_arithmetic_conversion(
3620 unsigned int left, unsigned int right)
3624 if ((left == TYPE_LDOUBLE) || (right == TYPE_LDOUBLE)) {
3625 return TYPE_LDOUBLE;
3627 else if ((left == TYPE_DOUBLE) || (right == TYPE_DOUBLE)) {
3630 else if ((left == TYPE_FLOAT) || (right == TYPE_FLOAT)) {
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) {
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;
3643 /* If the signed type can hold everything use it */
3644 else if (TYPE_SIGNED(left) && (TYPE_RANK(left) > TYPE_RANK(right))) {
3647 else if (TYPE_SIGNED(right) && (TYPE_RANK(right) > TYPE_RANK(left))) {
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);
3655 return TYPE_MKUNSIGNED(right);
3659 /* see if two types are the same except for qualifiers */
3660 static int equiv_types(struct type *left, struct type *right)
3663 /* Error if the basic types do not match */
3664 if ((left->type & TYPE_MASK) != (right->type & TYPE_MASK)) {
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)) {
3672 /* If it is a pointer type recurse and keep testing */
3673 if (type == TYPE_POINTER) {
3674 return equiv_types(left->left, right->left);
3676 else if (type == TYPE_ARRAY) {
3677 return (left->elements == right->elements) &&
3678 equiv_types(left->left, right->left);
3680 /* test for struct/union equality */
3681 else if (type == TYPE_STRUCT) {
3682 return left->ident == right->ident;
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);
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);
3694 /* We should see TYPE_OVERLAP */
3700 static int equiv_ptrs(struct type *left, struct type *right)
3702 if (((left->type & TYPE_MASK) != TYPE_POINTER) ||
3703 ((right->type & TYPE_MASK) != TYPE_POINTER)) {
3706 return equiv_types(left->left, right->left);
3709 static struct type *compatible_types(struct type *left, struct type *right)
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)) {
3717 type = left->type & TYPE_MASK;
3718 qual_type = (left->type & ~STOR_MASK) | (right->type & ~STOR_MASK);
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);
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);
3728 result = new_type(qual_type, result, 0);
3731 /* test for struct/union equality */
3732 else if (type == TYPE_STRUCT) {
3733 if (left->ident == right->ident) {
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);
3743 result = new_type(qual_type, lf, rf);
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);
3752 result = new_type(qual_type, lf, rf);
3756 /* Nothing else is compatible */
3761 static struct type *compatible_ptrs(struct type *left, struct type *right)
3763 struct type *result;
3764 if (((left->type & TYPE_MASK) != TYPE_POINTER) ||
3765 ((right->type & TYPE_MASK) != TYPE_POINTER)) {
3768 result = compatible_types(left->left, right->left);
3770 unsigned int qual_type;
3771 qual_type = (left->type & ~STOR_MASK) | (right->type & ~STOR_MASK);
3772 result = new_type(qual_type, result, 0);
3777 static struct triple *integral_promotion(
3778 struct compile_state *state, struct triple *def)
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.
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);
3798 static void arithmetic(struct compile_state *state, struct triple *def)
3800 if (!TYPE_ARITHMETIC(def->type->type)) {
3801 error(state, def, "arithmetic type expexted");
3805 static void ptr_arithmetic(struct compile_state *state, struct triple *def)
3807 if (!TYPE_PTR(def->type->type) && !TYPE_ARITHMETIC(def->type->type)) {
3808 error(state, def, "pointer or arithmetic type expected");
3812 static int is_integral(struct triple *ins)
3814 return TYPE_INTEGER(ins->type->type);
3817 static void integral(struct compile_state *state, struct triple *def)
3819 if (!is_integral(def)) {
3820 error(state, 0, "integral type expected");
3825 static void bool(struct compile_state *state, struct triple *def)
3827 if (!TYPE_ARITHMETIC(def->type->type) &&
3828 ((def->type->type & TYPE_MASK) != TYPE_POINTER)) {
3829 error(state, 0, "arithmetic or pointer type expected");
3833 static int is_signed(struct type *type)
3835 return !!TYPE_SIGNED(type->type);
3838 /* Is this a stable variable location otherwise it must be a temporary */
3839 static int is_stable(struct triple *def)
3846 if ((def->op == OP_ADECL) ||
3847 (def->op == OP_SDECL) ||
3848 (def->op == OP_DEREF) ||
3849 (def->op == OP_BLOBCONST)) {
3852 else if (def->op == OP_DOT) {
3853 ret = is_stable(def->left);
3858 static int is_lvalue(struct triple *def)
3865 if (!is_stable(def)) {
3868 if (def->type->type & QUAL_CONST) {
3871 else if (def->op == OP_DOT) {
3872 ret = is_lvalue(def->left);
3877 static void lvalue(struct compile_state *state, struct triple *def)
3880 internal_error(state, def, "nothing where lvalue expected?");
3882 if (!is_lvalue(def)) {
3883 error(state, def, "lvalue expected");
3887 static int is_pointer(struct triple *def)
3889 return (def->type->type & TYPE_MASK) == TYPE_POINTER;
3892 static void pointer(struct compile_state *state, struct triple *def)
3894 if (!is_pointer(def)) {
3895 error(state, def, "pointer expected");
3899 static struct triple *int_const(
3900 struct compile_state *state, struct type *type, ulong_t value)
3902 struct triple *result;
3903 switch(type->type & TYPE_MASK) {
3905 case TYPE_INT: case TYPE_UINT:
3906 case TYPE_LONG: case TYPE_ULONG:
3909 internal_error(state, 0, "constant for unkown type");
3911 result = triple(state, OP_INTCONST, type, 0, 0);
3912 result->u.cval = value;
3917 static struct triple *mk_addr_expr(
3918 struct compile_state *state, struct triple *expr, ulong_t offset)
3920 struct triple *result;
3923 lvalue(state, expr);
3925 TYPE_POINTER | (expr->type->type & QUAL_MASK),
3929 if (expr->op == OP_ADECL) {
3930 error(state, expr, "address of auto variables not supported");
3932 else if (expr->op == OP_SDECL) {
3933 result = triple(state, OP_ADDRCONST, type, expr, 0);
3934 result->u.cval = offset;
3936 else if (expr->op == OP_DEREF) {
3937 result = triple(state, OP_ADD, type,
3939 int_const(state, &ulong_type, offset));
3944 static struct triple *mk_deref_expr(
3945 struct compile_state *state, struct triple *expr)
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)) {
3952 "Only pointer and arithmetic values can be dereferenced");
3954 return triple(state, OP_DEREF, base_type, expr, 0);
3957 static struct triple *read_expr(struct compile_state *state, struct triple *def)
3963 if (!is_stable(def)) {
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) {
3971 TYPE_POINTER | (def->type->type & QUAL_MASK),
3972 def->type->left, 0);
3973 return triple(state, OP_ADDRCONST, type, def, 0);
3975 /* Only values in variables need to be read */
3976 if (def->op == OP_ADECL) {
3979 else if ((def->op == OP_SDECL) || (def->op == OP_DEREF)) {
3983 internal_error(state, 0, "unhandled read expr type");
3986 return triple(state, op, def->type, def, 0);
3989 static void write_compatible(struct compile_state *state,
3990 struct type *dest, struct type *rval)
3993 /* Both operands have arithmetic type */
3994 if (TYPE_ARITHMETIC(dest->type) && TYPE_ARITHMETIC(rval->type)) {
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))) {
4004 /* If both types are the same without qualifiers we are good */
4005 else if (equiv_ptrs(dest, rval)) {
4009 error(state, 0, "Incompatible types in assignment");
4013 static struct triple *write_expr(
4014 struct compile_state *state, struct triple *dest, struct triple *rval)
4021 internal_error(state, 0, "missing rval");
4024 if (rval->op == OP_LIST) {
4025 internal_error(state, 0, "expression of type OP_LIST?");
4027 if (!is_lvalue(dest)) {
4028 internal_error(state, 0, "writing to a non lvalue?");
4031 write_compatible(state, dest->type, rval->type);
4033 /* Now figure out which assignment operator to use */
4035 if (dest->op == OP_ADECL) {
4038 else if ((dest->op == OP_SDECL) || (dest->op == OP_DEREF)) {
4042 internal_error(state, 0, "unimplemented lvalue type");
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);
4049 static struct triple *init_expr(
4050 struct compile_state *state, struct triple *dest, struct triple *rval)
4056 internal_error(state, 0, "missing rval");
4058 if ((dest->type->type & STOR_MASK) != STOR_PERM) {
4059 rval = read_expr(state, rval);
4060 def = write_expr(state, dest, rval);
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;
4070 if (!equiv_types(dest->type, rval->type)) {
4071 error(state, 0, "Incompatible types in inializer");
4078 struct type *arithmetic_result(
4079 struct compile_state *state, struct triple *left, struct triple *right)
4082 /* Sanity checks to ensure I am working with arithmetic types */
4083 arithmetic(state, left);
4084 arithmetic(state, right);
4086 do_arithmetic_conversion(
4088 right->type->type), 0, 0);
4092 struct type *ptr_arithmetic_result(
4093 struct compile_state *state, struct triple *left, struct triple *right)
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);
4103 else if (TYPE_PTR(left->type->type)) {
4107 internal_error(state, 0, "huh?");
4114 /* boolean helper function */
4116 static struct triple *ltrue_expr(struct compile_state *state,
4117 struct triple *expr)
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 */
4126 expr = triple(state, OP_LTRUE, &int_type, expr, 0);
4132 static struct triple *lfalse_expr(struct compile_state *state,
4133 struct triple *expr)
4135 return triple(state, OP_LFALSE, &int_type, expr, 0);
4138 static struct triple *cond_expr(
4139 struct compile_state *state,
4140 struct triple *test, struct triple *left, struct triple *right)
4143 struct type *result_type;
4144 unsigned int left_type, right_type;
4146 left_type = left->type->type;
4147 right_type = right->type->type;
4149 /* Both operands have arithmetic type */
4150 if (TYPE_ARITHMETIC(left_type) && TYPE_ARITHMETIC(right_type)) {
4151 result_type = arithmetic_result(state, left, right);
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;
4158 /* pointers to the same type... */
4159 else if ((result_type = compatible_ptrs(left->type, right->type))) {
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;
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;
4175 error(state, 0, "Incompatible types in conditional expression");
4177 def = triple(state, OP_COND, result_type, test,
4178 triple(state, OP_PRODUCT, &void_type, left, right));
4183 static int expr_depth(struct compile_state *state, struct triple *triple)
4190 /* All of the internal helper ops that are not removed by
4191 * flatten must be present here.
4193 if (triple->op == OP_READ) {
4196 else if (triple->op == OP_DEREF) {
4197 count = expr_depth(state, triple->left) - 1;
4199 else if (triple->op == OP_VAL) {
4200 count = expr_depth(state, triple->left) - 1;
4202 else if (triple->op == OP_COMMA) {
4204 left = expr_depth(state, triple->left);
4205 right = expr_depth(state, triple->right);
4206 count = (left >= right)? left : right;
4208 else if (triple->op == OP_CALL) {
4209 /* Don't figure the depth of a call just guess it is huge */
4213 struct triple **expr;
4214 expr = triple_rhs(state, triple, 0);
4215 for(;expr; expr = triple_rhs(state, triple, expr)) {
4217 depth = expr_depth(state, *expr);
4218 if (depth > count) {
4226 static struct triple *flatten(
4227 struct compile_state *state, struct triple *first, struct triple *ptr);
4229 static struct triple *flatten_rhs(
4230 struct compile_state *state, struct triple *first, struct triple *ptr)
4232 struct triple **left, **right, **last;
4233 /* Only operations with a rhs should come here */
4234 last = triple_lhs(state, ptr, 0);
4236 internal_error(state, ptr, "unexpected rhs for: %d %s",
4237 ptr->op, tops(ptr->op));
4239 /* Collect up the rhs */
4240 left = triple_rhs(state, ptr, 0);
4243 right = triple_rhs(state, ptr, left);
4246 last = triple_rhs(state, ptr, right);
4249 internal_error(state, ptr, "too many rhs arguments for: %d %s",
4250 ptr->op, tops(ptr->op));
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);
4258 *right = flatten(state, first, *right);
4259 *left = flatten(state, first, *left);
4261 use_triple(*left, ptr);
4262 use_triple(*right, ptr);
4265 *left = flatten(state, first, *left);
4266 use_triple(*left, ptr);
4271 static struct triple *flatten_land(
4272 struct compile_state *state, struct triple *first, struct triple *ptr)
4274 struct triple *left, *right;
4275 struct triple *val, *test, *jmp, *label1, *end;
4277 /* Find the triples */
4281 /* Generate the needed triples */
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);
4296 /* Now give the caller something to chew on */
4297 return read_expr(state, val);
4300 static struct triple *flatten_lor(
4301 struct compile_state *state, struct triple *first, struct triple *ptr)
4303 struct triple *left, *right;
4304 struct triple *val, *jmp, *label1, *end;
4306 /* Find the triples */
4310 /* Generate the needed triples */
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);
4323 /* Now give the caller something to chew on */
4324 return read_expr(state, val);
4327 static struct triple *flatten_cond(
4328 struct compile_state *state, struct triple *first, struct triple *ptr)
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");
4336 /* Find the triples */
4338 left = ptr->right->left;
4339 right = ptr->right->right;
4341 /* Generate the needed triples */
4343 middle = label(state);
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);
4361 /* Now give the caller something to chew on */
4362 return read_expr(state, val);
4365 struct triple *copy_func(struct compile_state *state, struct triple *ofunc)
4367 struct triple *nfunc;
4368 struct triple *nfirst, *ofirst;
4369 struct triple *new, *old;
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");
4379 /* Make a new copy of the old function */
4380 nfunc = triple(state, OP_LIST, ofunc->type, 0, 0);
4382 ofirst = old = ofunc->left;
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));
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;
4395 nfunc->left = nfirst = new;
4398 insert_triple(state, nfirst, new);
4401 /* During the copy remember new as user of old */
4402 use_triple(old, new);
4404 /* Populate the return type if present */
4405 if (old == ofunc->right) {
4409 } while(old != ofirst);
4411 /* Make a second pass to fix up any unresolved references */
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?");
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?");
4428 if (!new->left && old->left) {
4429 internal_error(state, 0, "Could not copy left");
4431 if (!new->right && old->right) {
4432 internal_error(state, 0, "Could not copy right");
4434 if (new->op != old->op) {
4435 internal_error(state, 0, "Could not copy op?");
4437 if (!new->next && old->next) {
4438 internal_error(state, 0, "Could not copy next");
4440 use_triple(new->left, new);
4441 use_triple(new->right, new);
4442 if (new->op == OP_BRANCH) {
4444 use_triple(new->next, new);
4449 } while((old != ofirst) && (new != nfirst));
4451 /* Make a third pass to cleanup the extra useses */
4455 unuse_triple(old, new);
4458 } while ((old != ofirst) && (new != nfirst));
4462 static struct triple *flatten_call(
4463 struct compile_state *state, struct triple *first, struct triple *ptr)
4465 /* Inline the function call */
4466 struct triple *ofunc, *nfunc, *nfirst, *args, *param, *result;
4467 struct triple *end, *nend;
4470 /* Find the triples */
4473 if (ofunc->op != OP_LIST) {
4474 internal_error(state, 0, "improper function");
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 */
4484 if (args->op == OP_PRODUCT) {
4487 flatten(state, nfirst,
4488 write_expr(state, param, arg));
4489 param = param->next;
4490 args = (args->op == OP_PRODUCT)? args->right : 0;
4493 if ((nfunc->type->left->type & TYPE_MASK) != TYPE_VOID) {
4494 result = read_expr(state, nfunc->right);
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");
4504 /* Get rid of the extra triples */
4505 nfirst = nfunc->left->next;
4506 free_triple(state, nfunc->left);
4508 free_triple(state, nfunc);
4510 /* Append the new function list onto the return list */
4512 nend = nfirst->prev;
4521 static struct triple *flatten(
4522 struct compile_state *state, struct triple *first, struct triple *ptr)
4524 struct triple *orig_ptr;
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);
4538 ptr->left = flatten(state, first, ptr->left);
4542 ptr->left = flatten(state, first, ptr->left);
4546 ptr = flatten_land(state, first, ptr);
4549 ptr = flatten_lor(state, first, ptr);
4552 ptr = flatten_cond(state, first, ptr);
4555 ptr = flatten_call(state, first, ptr);
4559 ptr->left = flatten(state, first, ptr->left);
4560 use_triple(ptr->left, ptr);
4563 use_triple(ptr->left, ptr);
4564 use_triple(ptr->right, ptr);
4565 if (ptr->next != ptr) {
4566 use_triple(ptr->next, ptr);
4570 ptr->left = flatten(state, first, ptr->left);
4571 use_triple(ptr->left, ptr);
4574 ptr = triple(state, OP_SDECL, ptr->type, ptr, 0);
4575 use_triple(ptr->left, ptr);
4578 /* Since OP_DEREF is just a marker delete it when I flatten it */
4581 free_triple(state, orig_ptr);
4585 internal_error(state, 0, "unknown expression type: %d %s",
4586 ptr->op, tops(ptr->op));
4590 /* Don't flatten already flattened decls */
4591 if ((ptr->next != ptr) || (ptr->prev != ptr)) {
4596 /* Flatten the easy cases we don't override */
4597 ptr = flatten_rhs(state, first, ptr);
4600 } while(ptr && (ptr != orig_ptr));
4601 insert_triple(state, first, ptr);
4605 static void release_expr(struct compile_state *state, struct triple *expr)
4607 struct triple *head;
4608 head = label(state);
4609 flatten(state, head, expr);
4610 while(head->next != head) {
4611 release_triple(state, head->next);
4613 free_triple(state, head);
4616 static int replace_rhs_use(struct compile_state *state,
4617 struct triple *orig, struct triple *new, struct triple *use)
4619 struct triple **expr;
4622 expr = triple_rhs(state, use, 0);
4623 for(;expr; expr = triple_rhs(state, use, expr)) {
4624 if (*expr == orig) {
4630 unuse_triple(orig, use);
4631 use_triple(new, use);
4636 static int replace_lhs_use(struct compile_state *state,
4637 struct triple *orig, struct triple *new, struct triple *use)
4639 struct triple **expr;
4642 expr = triple_lhs(state, use, 0);
4643 for(;expr; expr = triple_lhs(state, use, expr)) {
4644 if (*expr == orig) {
4650 unuse_triple(orig, use);
4651 use_triple(new, use);
4656 static void propogate_use(struct compile_state *state,
4657 struct triple *orig, struct triple *new)
4659 struct triple_set *user, *next;
4660 for(user = orig->use; user; user = next) {
4666 found |= replace_rhs_use(state, orig, new, use);
4667 found |= replace_lhs_use(state, orig, new, use);
4669 internal_error(state, use, "use without use");
4673 internal_error(state, orig, "used after propogate_use");
4679 * ===========================
4682 static struct triple *mk_add_expr(
4683 struct compile_state *state, struct triple *left, struct triple *right)
4685 struct type *result_type;
4686 /* Put pointer operands on the left */
4687 if (is_pointer(right)) {
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,
4701 int_const(state, &ulong_type,
4702 size_of(state, left->type->left)));
4704 return triple(state, OP_ADD, result_type, left, right);
4707 static struct triple *mk_sub_expr(
4708 struct compile_state *state, struct triple *left, struct triple *right)
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,
4719 int_const(state, &ulong_type,
4720 size_of(state, left->type->left)));
4722 return triple(state, OP_SUB, result_type, left, right);
4725 static struct triple *mk_pre_inc_expr(
4726 struct compile_state *state, struct triple *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),
4736 static struct triple *mk_pre_dec_expr(
4737 struct compile_state *state, struct triple *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),
4747 static struct triple *mk_post_inc_expr(
4748 struct compile_state *state, struct triple *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)))
4759 static struct triple *mk_post_dec_expr(
4760 struct compile_state *state, struct triple *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)))
4771 static struct triple *mk_subscript_expr(
4772 struct compile_state *state, struct triple *left, struct triple *right)
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");
4779 return mk_deref_expr(state, mk_add_expr(state, left, right));
4783 * Compile time evaluation
4784 * ===========================
4786 static int is_const(struct triple *ins)
4788 return IS_CONST_OP(ins->op);
4791 static int constants_equal(struct compile_state *state,
4792 struct triple *left, struct triple *right)
4795 if (!is_const(left) || !is_const(right)) {
4798 else if (left->op != right->op) {
4801 else if (!equiv_types(left->type, right->type)) {
4808 if (left->u.cval == right->u.cval) {
4814 size_t lsize, rsize;
4815 lsize = size_of(state, left->type);
4816 rsize = size_of(state, right->type);
4817 if (lsize != rsize) {
4820 if (memcmp(left->u.blob, right->u.blob, lsize) == 0) {
4826 if ((left->left == right->left) &&
4827 (left->u.cval == right->u.cval)) {
4832 internal_error(state, left, "uknown constant type");
4839 static int is_zero(struct triple *ins)
4841 return is_const(ins) && (ins->u.cval == 0);
4844 static int is_one(struct triple *ins)
4846 return is_const(ins) && (ins->u.cval == 1);
4849 static long_t bsr(ulong_t value)
4852 for(i = (sizeof(ulong_t)*8) -1; i >= 0; i--) {
4863 static long_t bsf(ulong_t value)
4866 for(i = 0; i < (sizeof(ulong_t)*8); i++) {
4877 static long_t log2(ulong_t value)
4882 static long_t tlog2(struct triple *ins)
4884 return log2(ins->u.cval);
4887 static int is_pow2(struct triple *ins)
4889 ulong_t value, mask;
4891 if (!is_const(ins)) {
4894 value = ins->u.cval;
4901 return ((value & mask) == value);
4904 static ulong_t read_const(struct compile_state *state,
4905 struct triple *ins, struct triple **expr)
4909 switch(rhs->type->type &TYPE_MASK) {
4921 internal_error(state, rhs, "bad type to read_const\n");
4927 static long_t read_sconst(struct triple *ins, struct triple **expr)
4931 return (long_t)(rhs->u.cval);
4934 static void unuse_rhs(struct compile_state *state, struct triple *ins)
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);
4943 static void check_lhs(struct compile_state *state, struct triple *ins)
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");
4952 static void check_targ(struct compile_state *state, struct triple *ins)
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");
4961 static void wipe_ins(struct compile_state *state, struct triple *ins)
4963 check_lhs(state, ins);
4964 check_targ(state, ins);
4965 unuse_rhs(state, ins);
4966 if (ins->op == OP_PHI) {
4972 static void mkcopy(struct compile_state *state,
4973 struct triple *ins, struct triple *rhs)
4975 wipe_ins(state, ins);
4978 use_triple(ins->left, ins);
4981 static void mkconst(struct compile_state *state,
4982 struct triple *ins, ulong_t value)
4984 if (!is_integral(ins) && !is_pointer(ins)) {
4985 internal_error(state, ins, "unknown type to make constant\n");
4987 wipe_ins(state, ins);
4988 ins->op = OP_INTCONST;
4989 ins->u.cval = value;
4992 static void mkaddr_const(struct compile_state *state,
4993 struct triple *ins, struct triple *sdecl, ulong_t value)
4995 wipe_ins(state, ins);
4996 ins->op = OP_ADDRCONST;
4998 ins->u.cval = value;
4999 use_triple(sdecl, ins);
5002 /* For those operations that cannot be simplified */
5003 static void simplify_noop(struct compile_state *state, struct triple *ins)
5008 static void simplify_smul(struct compile_state *state, struct triple *ins)
5010 if (is_const(ins->left) && !is_const(ins->right)) {
5013 ins->left = ins->right;
5016 if (is_const(ins->left) && is_const(ins->right)) {
5018 left = read_sconst(ins, &ins->left);
5019 right = read_sconst(ins, &ins->right);
5020 mkconst(state, ins, left * right);
5022 else if (is_zero(ins->right)) {
5023 mkconst(state, ins, 0);
5025 else if (is_one(ins->right)) {
5026 mkcopy(state, ins, ins->left);
5028 else if (is_pow2(ins->right)) {
5030 val = int_const(state, ins->type, tlog2(ins->right));
5032 insert_triple(state, ins, val);
5033 unuse_triple(ins->right, ins);
5034 use_triple(val, ins);
5039 static void simplify_umul(struct compile_state *state, struct triple *ins)
5041 if (is_const(ins->left) && !is_const(ins->right)) {
5044 ins->left = ins->right;
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);
5053 else if (is_zero(ins->right)) {
5054 mkconst(state, ins, 0);
5056 else if (is_one(ins->right)) {
5057 mkcopy(state, ins, ins->left);
5059 else if (is_pow2(ins->right)) {
5061 val = int_const(state, ins->type, tlog2(ins->right));
5063 insert_triple(state, ins, val);
5064 unuse_triple(ins->right, ins);
5065 use_triple(val, ins);
5070 static void simplify_sdiv(struct compile_state *state, struct triple *ins)
5072 if (is_const(ins->left) && is_const(ins->right)) {
5074 left = read_sconst(ins, &ins->left);
5075 right = read_sconst(ins, &ins->right);
5076 mkconst(state, ins, left / right);
5078 else if (is_zero(ins->left)) {
5079 mkconst(state, ins, 0);
5081 else if (is_zero(ins->right)) {
5082 error(state, ins, "division by zero");
5084 else if (is_one(ins->right)) {
5085 mkcopy(state, ins, ins->left);
5087 else if (is_pow2(ins->right)) {
5089 val = int_const(state, ins->type, tlog2(ins->right));
5091 insert_triple(state, ins, val);
5092 unuse_triple(ins->right, ins);
5093 use_triple(val, ins);
5098 static void simplify_udiv(struct compile_state *state, struct triple *ins)
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);
5106 else if (is_zero(ins->left)) {
5107 mkconst(state, ins, 0);
5109 else if (is_zero(ins->right)) {
5110 error(state, ins, "division by zero");
5112 else if (is_one(ins->right)) {
5113 mkcopy(state, ins, ins->left);
5115 else if (is_pow2(ins->right)) {
5117 val = int_const(state, ins->type, tlog2(ins->right));
5119 insert_triple(state, ins, val);
5120 unuse_triple(ins->right, ins);
5121 use_triple(val, ins);
5126 static void simplify_smod(struct compile_state *state, struct triple *ins)
5128 if (is_const(ins->left) && is_const(ins->right)) {
5130 left = read_const(state, ins, &ins->left);
5131 right = read_const(state, ins, &ins->right);
5132 mkconst(state, ins, left % right);
5134 else if (is_zero(ins->left)) {
5135 mkconst(state, ins, 0);
5137 else if (is_zero(ins->right)) {
5138 error(state, ins, "division by zero");
5140 else if (is_one(ins->right)) {
5141 mkconst(state, ins, 0);
5143 else if (is_pow2(ins->right)) {
5145 val = int_const(state, ins->type, ins->right->u.cval - 1);
5147 insert_triple(state, ins, val);
5148 unuse_triple(ins->right, ins);
5149 use_triple(val, ins);
5153 static void simplify_umod(struct compile_state *state, struct triple *ins)
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);
5161 else if (is_zero(ins->left)) {
5162 mkconst(state, ins, 0);
5164 else if (is_zero(ins->right)) {
5165 error(state, ins, "division by zero");
5167 else if (is_one(ins->right)) {
5168 mkconst(state, ins, 0);
5170 else if (is_pow2(ins->right)) {
5172 val = int_const(state, ins->type, ins->right->u.cval - 1);
5174 insert_triple(state, ins, val);
5175 unuse_triple(ins->right, ins);
5176 use_triple(val, ins);
5181 static void simplify_add(struct compile_state *state, struct triple *ins)
5183 /* start with the pointer on the left */
5184 if (is_pointer(ins->right)) {
5187 ins->left = ins->right;
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);
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);
5206 else if (is_const(ins->left) && !is_const(ins->right)) {
5209 ins->right = ins->left;
5214 static void simplify_sub(struct compile_state *state, struct triple *ins)
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);
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);
5234 static void simplify_sl(struct compile_state *state, struct triple *ins)
5236 if (is_const(ins->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");
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);
5251 static void simplify_usr(struct compile_state *state, struct triple *ins)
5253 if (is_const(ins->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");
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);
5268 static void simplify_ssr(struct compile_state *state, struct triple *ins)
5270 if (is_const(ins->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");
5277 if (is_const(ins->left) && is_const(ins->right)) {
5279 left = read_sconst(ins, &ins->left);
5280 right = read_sconst(ins, &ins->right);
5281 mkconst(state, ins, left >> right);
5285 static void simplify_and(struct compile_state *state, struct triple *ins)
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);
5295 static void simplify_or(struct compile_state *state, struct triple *ins)
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);
5305 static void simplify_xor(struct compile_state *state, struct triple *ins)
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);
5315 static void simplify_pos(struct compile_state *state, struct triple *ins)
5317 if (is_const(ins->left)) {
5318 mkconst(state, ins, ins->left->u.cval);
5321 mkcopy(state, ins, ins->left);
5325 static void simplify_neg(struct compile_state *state, struct triple *ins)
5327 if (is_const(ins->left)) {
5329 left = read_const(state, ins, &ins->left);
5330 mkconst(state, ins, -left);
5332 else if (ins->left->op == OP_NEG) {
5333 mkcopy(state, ins, ins->left->left);
5337 static void simplify_invert(struct compile_state *state, struct triple *ins)
5339 if (is_const(ins->left)) {
5341 left = read_const(state, ins, &ins->left);
5342 mkconst(state, ins, ~left);
5346 static void simplify_eq(struct compile_state *state, struct triple *ins)
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);
5354 else if (ins->left == ins->right) {
5355 mkconst(state, ins, 1);
5359 static void simplify_noteq(struct compile_state *state, struct triple *ins)
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);
5367 else if (ins->left == ins->right) {
5368 mkconst(state, ins, 0);
5372 static void simplify_sless(struct compile_state *state, struct triple *ins)
5374 if (is_const(ins->left) && is_const(ins->right)) {
5376 left = read_sconst(ins, &ins->left);
5377 right = read_sconst(ins, &ins->right);
5378 mkconst(state, ins, left < right);
5380 else if (ins->left == ins->right) {
5381 mkconst(state, ins, 0);
5385 static void simplify_uless(struct compile_state *state, struct triple *ins)
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);
5393 else if (is_zero(ins->left)) {
5394 mkconst(state, ins, 1);
5396 else if (ins->left == ins->right) {
5397 mkconst(state, ins, 0);
5401 static void simplify_smore(struct compile_state *state, struct triple *ins)
5403 if (is_const(ins->left) && is_const(ins->right)) {
5405 left = read_sconst(ins, &ins->left);
5406 right = read_sconst(ins, &ins->right);
5407 mkconst(state, ins, left > right);
5409 else if (ins->left == ins->right) {
5410 mkconst(state, ins, 0);
5414 static void simplify_umore(struct compile_state *state, struct triple *ins)
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);
5422 else if (is_zero(ins->right)) {
5423 mkconst(state, ins, 1);
5425 else if (ins->left == ins->right) {
5426 mkconst(state, ins, 0);
5431 static void simplify_slesseq(struct compile_state *state, struct triple *ins)
5433 if (is_const(ins->left) && is_const(ins->right)) {
5435 left = read_sconst(ins, &ins->left);
5436 right = read_sconst(ins, &ins->right);
5437 mkconst(state, ins, left <= right);
5439 else if (ins->left == ins->right) {
5440 mkconst(state, ins, 1);
5444 static void simplify_ulesseq(struct compile_state *state, struct triple *ins)
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);
5452 else if (is_zero(ins->left)) {
5453 mkconst(state, ins, 1);
5455 else if (ins->left == ins->right) {
5456 mkconst(state, ins, 1);
5460 static void simplify_smoreeq(struct compile_state *state, struct triple *ins)
5462 if (is_const(ins->left) && is_const(ins->right)) {
5464 left = read_sconst(ins, &ins->left);
5465 right = read_sconst(ins, &ins->right);
5466 mkconst(state, ins, left >= right);
5468 else if (ins->left == ins->right) {
5469 mkconst(state, ins, 1);
5473 static void simplify_umoreeq(struct compile_state *state, struct triple *ins)
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);
5481 else if (is_zero(ins->right)) {
5482 mkconst(state, ins, 1);
5484 else if (ins->left == ins->right) {
5485 mkconst(state, ins, 1);
5489 static void simplify_lfalse(struct compile_state *state, struct triple *ins)
5491 if (is_const(ins->left)) {
5493 left = read_const(state, ins, &ins->left);
5494 mkconst(state, ins, left == 0);
5496 /* Otherwise if I am the only user... */
5497 else if ((ins->left->use->member == ins) && (ins->left->use->next == 0)) {
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;
5518 mkcopy(state, ins, ins->left);
5523 static void simplify_ltrue (struct compile_state *state, struct triple *ins)
5525 if (is_const(ins->left)) {
5527 left = read_const(state, ins, &ins->left);
5528 mkconst(state, ins, left != 0);
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);
5539 static void simplify_copy(struct compile_state *state, struct triple *ins)
5541 if (is_const(ins->left)) {
5542 switch(ins->left->op) {
5546 left = read_const(state, ins, &ins->left);
5547 mkconst(state, ins, left);
5552 struct triple *sdecl;
5555 offset = ins->u.cval;
5556 mkaddr_const(state, ins, sdecl, offset);
5560 internal_error(state, ins, "uknown constant");
5566 static void simplify_dot(struct compile_state *state, struct triple *ins)
5571 static void simplify_branch(struct compile_state *state, struct triple *ins)
5573 struct block *block;
5574 if (ins->op != OP_BRANCH) {
5575 internal_error(state, ins, "not branch");
5577 if (ins->use != 0) {
5578 internal_error(state, ins, "branch use");
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.
5585 block = ins->u.block;
5587 if (ins->right && is_const(ins->right)) {
5589 value = read_const(state, ins, &ins->right);
5590 unuse_triple(ins->right, ins);
5593 unuse_triple(ins->next, ins);
5596 unuse_triple(ins->left, ins);
5597 ins->left = ins->next;
5599 #warning "FIXME handle the case of making a branch unconditional"
5601 if (ins->left == ins->next) {
5602 unuse_triple(ins->left, ins);
5604 unuse_triple(ins->right, ins);
5605 unuse_triple(ins->next, ins);
5611 internal_error(state, ins, "noop use != 0");
5613 #warning "FIXME handle the case of killing a branch"
5617 static void simplify_phi(struct compile_state *state, struct triple *ins)
5619 struct triple **expr;
5621 expr = triple_rhs(state, ins, 0);
5622 if (!is_const(*expr)) {
5625 value = read_const(state, ins, expr);
5626 for(;expr;expr = triple_rhs(state, ins, expr)) {
5627 if (!is_const(*expr)) {
5630 if (value != read_const(state, ins, expr)) {
5634 mkconst(state, ins, value);
5638 static void simplify_bsf(struct compile_state *state, struct triple *ins)
5640 if (is_const(ins->left)) {
5642 left = read_const(state, ins, &ins->left);
5643 mkconst(state, ins, bsf(left));
5647 static void simplify_bsr(struct compile_state *state, struct triple *ins)
5649 if (is_const(ins->left)) {
5651 left = read_const(state, ins, &ins->left);
5652 mkconst(state, ins, bsr(left));
5657 typedef void (*simplify_t)(struct compile_state *state, struct triple *ins);
5658 static const simplify_t table_simplify[] = {
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
5668 #define simplify_add simplify_noop
5669 #define simplify_sub simplify_noop
5672 #define simplify_sl simplify_noop
5673 #define simplify_usr simplify_noop
5674 #define simplify_ssr simplify_noop
5677 #define simplify_and simplify_noop
5678 #define simplify_xor simplify_noop
5679 #define simplify_or simplify_noop
5682 #define simplify_pos simplify_noop
5683 #define simplify_neg simplify_noop
5684 #define simplify_invert simplify_noop
5688 #define simplify_eq simplify_noop
5689 #define simplify_noteq simplify_noop
5692 #define simplify_sless simplify_noop
5693 #define simplify_uless simplify_noop
5694 #define simplify_smore simplify_noop
5695 #define simplify_umore simplify_noop
5698 #define simplify_slesseq simplify_noop
5699 #define simplify_ulesseq simplify_noop
5700 #define simplify_smoreeq simplify_noop
5701 #define simplify_umoreeq simplify_noop
5704 #define simplify_lfalse simplify_noop
5707 #define simplify_ltrue simplify_noop
5711 #define simplify_copy simplify_noop
5715 #define simplify_dot simplify_noop
5719 #define simplify_branch simplify_noop
5723 #define simplify_phi simplify_noop
5727 #define simplify_bsf simplify_noop
5728 #define simplify_bsr simplify_noop
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,
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,
5762 [OP_LOAD ] = simplify_noop,
5763 [OP_STORE ] = simplify_noop,
5765 [OP_NOOP ] = simplify_noop,
5767 [OP_INTCONST ] = simplify_noop,
5768 [OP_BLOBCONST ] = simplify_noop,
5769 [OP_ADDRCONST ] = simplify_noop,
5771 [OP_WRITE ] = simplify_noop,
5772 [OP_READ ] = simplify_noop,
5773 [OP_COPY ] = simplify_copy,
5774 [OP_DOT ] = simplify_dot,
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,
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,
5793 static void simplify(struct compile_state *state, struct triple *ins)
5796 simplify_t do_simplify;
5800 if ((op < 0) || (op > sizeof(table_simplify)/sizeof(table_simplify[0]))) {
5804 do_simplify = table_simplify[op];
5807 internal_error(state, ins, "cannot simplify op: %d %s\n",
5811 do_simplify(state, ins);
5812 } while(ins->op != op);
5815 static void simplify_all(struct compile_state *state)
5817 struct triple *ins, *first;
5818 first = state->main_function->left;
5821 simplify(state, ins);
5823 } while(ins != first);
5828 * ============================
5831 static void register_builtin_unary(struct compile_state *state,
5832 const char *name, int op, struct type *result, struct type *a1type)
5834 struct type *ftype, *rtype, *atype;
5835 struct triple *def, *arg1, *work, *last, *first;
5836 struct hash_entry *ident;
5839 /* Dummy file state to get debug handling right */
5840 struct file_state file;
5841 memset(&file, 0, sizeof(file));
5842 file.basename = name;
5844 file.prev = state->file;
5845 state->file = &file;
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);
5854 /* Now string them together into a list */
5856 if ((atype->type & TYPE_MASK) != TYPE_VOID) {
5857 arg1 = flatten(state, first, variable(state, a1type));
5860 if ((rtype->type & TYPE_MASK) != TYPE_VOID) {
5861 def->right = flatten(state, first, variable(state, rtype));
5863 work = triple(state, op, rtype, read_expr(state, arg1), 0);
5865 work = write_expr(state, def->right, work);
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);
5873 state->file = file.prev;
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");
5884 static void register_builtin_binary(struct compile_state *state,
5885 const char *name, int op,
5886 struct type *result, struct type *a1type, struct type *a2type)
5888 struct type *ftype, *rtype, *atype;
5889 struct triple *def, *arg1, *arg2, *work, *last, *first;
5890 struct hash_entry *ident;
5892 /* Dummy file state to get debug handling right */
5893 struct file_state file;
5894 memset(&file, 0, sizeof(file));
5895 file.basename = name;
5897 file.prev = state->file;
5898 state->file = &file;
5900 atype = new_type(TYPE_PRODUCT, a1type, a2type);
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);
5907 /* String them togher */
5908 arg1 = flatten(state, first, variable(state, a1type));
5909 arg2 = flatten(state, first, variable(state, a2type));
5911 if ((rtype->type & TYPE_MASK) != TYPE_VOID) {
5912 def->right = flatten(state, first, variable(state, rtype));
5914 work = triple(state, op, rtype,
5915 read_expr(state, arg1), read_expr(state, arg2));
5917 work = write_expr(state, def->right, work);
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);
5925 state->file = file.prev;
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");
5936 static void register_builtins(struct compile_state *state)
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);
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);
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);
5957 register_builtin_unary(state, "__builtin_hlt", OP_HLT,
5958 &void_type, &void_type);
5961 static struct type *declarator(
5962 struct compile_state *state, struct type *type,
5963 struct hash_entry **ident, int need_ident);
5964 static void decl(struct compile_state *state, struct triple *first);
5965 static struct type *specifier_qualifier_list(struct compile_state *state);
5966 static int isdecl_specifier(int tok);
5967 static struct type *decl_specifiers(struct compile_state *state);
5968 static int istype(int tok);
5969 static struct triple *expr(struct compile_state *state);
5970 static struct triple *assignment_expr(struct compile_state *state);
5971 static struct type *type_name(struct compile_state *state);
5972 static void statement(struct compile_state *state, struct triple *fist);
5974 static struct triple *call_expr(
5975 struct compile_state *state, struct triple *func)
5977 struct triple *def, **next;
5980 if ((func->type->type & TYPE_MASK) != TYPE_FUNCTION) {
5981 error(state, 0, "Called object is not a function");
5983 if (func->op != OP_LIST) {
5984 internal_error(state, 0, "improper function");
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);
5991 if (peek(state) != TOK_RPAREN) {
5993 struct type *param, *arg_type;
5994 val = read_expr(state, assignment_expr(state));
5995 param = func->type->right;
5997 if ((param->type & TYPE_MASK) == TYPE_PRODUCT) {
5998 arg_type = param->left;
6000 else if ((param->type & TYPE_MASK) == TYPE_VOID) {
6001 error(state, 0, "Too many arguments");
6003 write_compatible(state, arg_type, val->type);
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");
6011 arg_type = param = param->right;
6012 if ((param->type & TYPE_MASK) == TYPE_PRODUCT) {
6013 arg_type = param->left;
6015 write_compatible(state, arg_type, val->type);
6016 *next = triple(state, OP_PRODUCT, &void_type, *next, val);
6017 next = &((*next)->right);
6020 eat(state, TOK_RPAREN);
6025 static struct triple *character_constant(struct compile_state *state)
6029 const signed char *str, *end;
6032 eat(state, TOK_LIT_CHAR);
6033 tk = &state->token[0];
6034 str = tk->val.str + 1;
6035 str_len = tk->str_len - 2;
6037 error(state, 0, "empty character constant");
6039 end = str + str_len;
6040 c = char_value(state, &str, end);
6042 error(state, 0, "multibyte character constant not supported");
6044 def = int_const(state, &char_type, (ulong_t)((long_t)c));
6048 static struct triple *string_constant(struct compile_state *state)
6053 const signed char *str, *end;
6054 signed char *buf, *ptr;
6058 type = new_type(TYPE_ARRAY, &char_type, 0);
6060 /* The while loop handles string concatenation */
6062 eat(state, TOK_LIT_STRING);
6063 tk = &state->token[0];
6064 str = tk->val.str + 1;
6065 str_len = tk->str_len - 2;
6067 error(state, 0, "empty string constant");
6069 end = str + str_len;
6071 buf = xmalloc(type->elements + str_len + 1, "string_constant");
6072 memcpy(buf, ptr, type->elements);
6073 ptr = buf + type->elements;
6075 *ptr++ = char_value(state, &str, end);
6077 type->elements = ptr - buf;
6078 } while(peek(state) == TOK_LIT_STRING);
6080 type->elements += 1;
6081 def = triple(state, OP_BLOBCONST, type, 0, 0);
6087 static struct triple *integer_constant(struct compile_state *state)
6096 eat(state, TOK_LIT_INT);
6097 tk = &state->token[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");
6105 if ((*end == 'u') || (*end == 'U')) {
6109 if ((*end == 'l') || (*end == 'L')) {
6113 if ((*end == 'u') || (*end == 'U')) {
6118 error(state, 0, "Junk at end of integer constant");
6125 if (!decimal && (val > LONG_MAX)) {
6131 if (val > UINT_MAX) {
6137 if (!decimal && (val > INT_MAX) && (val <= UINT_MAX)) {
6140 else if (!decimal && (val > LONG_MAX)) {
6143 else if (val > INT_MAX) {
6147 def = int_const(state, type, val);
6151 static struct triple *primary_expr(struct compile_state *state)
6159 struct hash_entry *ident;
6160 /* Here ident is either:
6163 * an enumeration constant.
6165 eat(state, TOK_IDENT);
6166 ident = state->token[0].ident;
6167 if (!ident->sym_ident) {
6168 error(state, 0, "%s undeclared", ident->name);
6170 def = ident->sym_ident->def;
6173 case TOK_ENUM_CONST:
6174 /* Here ident is an enumeration constant */
6175 eat(state, TOK_ENUM_CONST);
6180 eat(state, TOK_LPAREN);
6182 eat(state, TOK_RPAREN);
6185 def = integer_constant(state);
6188 eat(state, TOK_LIT_FLOAT);
6189 error(state, 0, "Floating point constants not supported");
6194 def = character_constant(state);
6196 case TOK_LIT_STRING:
6197 def = string_constant(state);
6201 error(state, 0, "Unexpected token: %s\n", tokens[tok]);
6206 static struct triple *postfix_expr(struct compile_state *state)
6210 def = primary_expr(state);
6212 struct triple *left;
6216 switch((tok = peek(state))) {
6218 eat(state, TOK_LBRACKET);
6219 def = mk_subscript_expr(state, left, expr(state));
6220 eat(state, TOK_RBRACKET);
6223 def = call_expr(state, def);
6226 eat(state, TOK_DOT);
6227 eat(state, TOK_IDENT);
6231 eat(state, TOK_ARROW);
6232 eat(state, TOK_IDENT);
6236 eat(state, TOK_PLUSPLUS);
6237 def = mk_post_inc_expr(state, left);
6239 case TOK_MINUSMINUS:
6240 eat(state, TOK_MINUSMINUS);
6241 def = mk_post_dec_expr(state, left);
6251 static struct triple *cast_expr(struct compile_state *state);
6253 static struct triple *unary_expr(struct compile_state *state)
6255 struct triple *def, *right;
6257 switch((tok = peek(state))) {
6259 eat(state, TOK_PLUSPLUS);
6260 def = mk_pre_inc_expr(state, unary_expr(state));
6262 case TOK_MINUSMINUS:
6263 eat(state, TOK_MINUSMINUS);
6264 def = mk_pre_dec_expr(state, unary_expr(state));
6267 eat(state, TOK_AND);
6268 def = mk_addr_expr(state, cast_expr(state), 0);
6271 eat(state, TOK_STAR);
6272 def = mk_deref_expr(state, read_expr(state, cast_expr(state)));
6275 eat(state, TOK_PLUS);
6276 right = read_expr(state, cast_expr(state));
6277 arithmetic(state, right);
6278 def = integral_promotion(state, right);
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);
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);
6295 eat(state, TOK_BANG);
6296 right = read_expr(state, cast_expr(state));
6298 def = lfalse_expr(state, right);
6304 eat(state, TOK_SIZEOF);
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);
6313 struct triple *expr;
6314 expr = unary_expr(state);
6316 release_expr(state, expr);
6318 def = int_const(state, &ulong_type, size_of(state, type));
6325 eat(state, TOK_ALIGNOF);
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);
6334 struct triple *expr;
6335 expr = unary_expr(state);
6337 release_expr(state, expr);
6339 def = int_const(state, &ulong_type, align_of(state, type));
6343 def = postfix_expr(state);
6349 static struct triple *cast_expr(struct compile_state *state)
6354 tok2 = peek2(state);
6355 if ((tok1 == TOK_LPAREN) && istype(tok2)) {
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?"
6365 def = unary_expr(state);
6370 static struct triple *mult_expr(struct compile_state *state)
6374 def = cast_expr(state);
6376 struct triple *left, *right;
6377 struct type *result_type;
6380 switch(tok = (peek(state))) {
6384 left = read_expr(state, def);
6385 arithmetic(state, left);
6389 right = read_expr(state, cast_expr(state));
6390 arithmetic(state, right);
6392 result_type = arithmetic_result(state, left, right);
6393 sign = is_signed(result_type);
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;
6400 def = triple(state, op, result_type, left, right);
6410 static struct triple *add_expr(struct compile_state *state)
6414 def = mult_expr(state);
6417 switch( peek(state)) {
6419 eat(state, TOK_PLUS);
6420 def = mk_add_expr(state, def, mult_expr(state));
6423 eat(state, TOK_MINUS);
6424 def = mk_sub_expr(state, def, mult_expr(state));
6434 static struct triple *shift_expr(struct compile_state *state)
6438 def = add_expr(state);
6440 struct triple *left, *right;
6443 switch((tok = peek(state))) {
6446 left = read_expr(state, def);
6447 integral(state, left);
6448 left = integral_promotion(state, left);
6452 right = read_expr(state, add_expr(state));
6453 integral(state, right);
6454 right = integral_promotion(state, right);
6456 op = (tok == TOK_SL)? OP_SL :
6457 is_signed(left->type)? OP_SSR: OP_USR;
6459 def = triple(state, op, left->type, left, right);
6469 static struct triple *relational_expr(struct compile_state *state)
6471 #warning "Extend relational exprs to work on more than arithmetic types"
6474 def = shift_expr(state);
6476 struct triple *left, *right;
6477 struct type *arg_type;
6480 switch((tok = peek(state))) {
6485 left = read_expr(state, def);
6486 arithmetic(state, left);
6490 right = read_expr(state, shift_expr(state));
6491 arithmetic(state, right);
6493 arg_type = arithmetic_result(state, left, right);
6494 sign = is_signed(arg_type);
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;
6502 def = triple(state, op, &int_type, left, right);
6512 static struct triple *equality_expr(struct compile_state *state)
6514 #warning "Extend equality exprs to work on more than arithmetic types"
6517 def = relational_expr(state);
6519 struct triple *left, *right;
6522 switch((tok = peek(state))) {
6525 left = read_expr(state, def);
6526 arithmetic(state, left);
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);
6541 static struct triple *and_expr(struct compile_state *state)
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);
6559 static struct triple *xor_expr(struct compile_state *state)
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);
6577 static struct triple *or_expr(struct compile_state *state)
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);
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);
6595 static struct triple *land_expr(struct compile_state *state)
6598 def = or_expr(state);
6599 while(peek(state) == TOK_LOGAND) {
6600 struct triple *left, *right;
6601 left = read_expr(state, def);
6603 eat(state, TOK_LOGAND);
6604 right = read_expr(state, or_expr(state));
6607 def = triple(state, OP_LAND, &int_type,
6608 ltrue_expr(state, left),
6609 ltrue_expr(state, right));
6614 static struct triple *lor_expr(struct compile_state *state)
6617 def = land_expr(state);
6618 while(peek(state) == TOK_LOGOR) {
6619 struct triple *left, *right;
6620 left = read_expr(state, def);
6622 eat(state, TOK_LOGOR);
6623 right = read_expr(state, land_expr(state));
6626 def = triple(state, OP_LOR, &int_type,
6627 ltrue_expr(state, left),
6628 ltrue_expr(state, right));
6633 static struct triple *conditional_expr(struct compile_state *state)
6636 def = lor_expr(state);
6637 if (peek(state) == TOK_QUEST) {
6638 struct triple *test, *left, *right;
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));
6646 def = cond_expr(state, test, left, right);
6651 static struct triple *eval_const_expr(
6652 struct compile_state *state, struct triple *expr)
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);
6661 /* Remove the constant value the tail of the list */
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");
6669 /* Free the intermediate expressions */
6670 while(head->next != head) {
6671 release_triple(state, head->next);
6673 free_triple(state, head);
6677 static struct triple *constant_expr(struct compile_state *state)
6679 return eval_const_expr(state, conditional_expr(state));
6682 static struct triple *assignment_expr(struct compile_state *state)
6684 struct triple *def, *left, *right;
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.
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.
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.
6701 * GCC has this bug as well, so surprises should be minimal.
6703 def = conditional_expr(state);
6705 switch((tok = peek(state))) {
6707 lvalue(state, left);
6709 def = write_expr(state, left,
6710 read_expr(state, assignment_expr(state)));
6717 lvalue(state, left);
6718 arithmetic(state, left);
6720 right = read_expr(state, assignment_expr(state));
6721 arithmetic(state, right);
6723 sign = is_signed(left->type);
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;
6732 def = write_expr(state, left,
6733 triple(state, op, left->type,
6734 read_expr(state, left), right));
6741 lvalue(state, left);
6742 integral(state, left);
6744 right = read_expr(state, assignment_expr(state));
6745 integral(state, right);
6746 right = integral_promotion(state, right);
6747 sign = is_signed(left->type);
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;
6756 def = write_expr(state, left,
6757 triple(state, op, left->type,
6758 read_expr(state, left), right));
6764 static struct triple *expr(struct compile_state *state)
6767 def = assignment_expr(state);
6768 while(peek(state) == TOK_COMMA) {
6769 struct triple *left, *right;
6771 eat(state, TOK_COMMA);
6772 right = assignment_expr(state);
6773 def = triple(state, OP_COMMA, right->type, left, right);
6778 static void expr_statement(struct compile_state *state, struct triple *first)
6780 if (peek(state) != TOK_SEMI) {
6781 flatten(state, first, expr(state));
6783 eat(state, TOK_SEMI);
6786 static void if_statement(struct compile_state *state, struct triple *first)
6788 struct triple *test, *jmp1, *jmp2, *middle, *end;
6790 jmp1 = jmp2 = middle = 0;
6792 eat(state, TOK_LPAREN);
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 */
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);
6818 flatten(state, first, middle);
6822 static void for_statement(struct compile_state *state, struct triple *first)
6824 struct triple *head, *test, *tail, *jmp1, *jmp2, *end;
6825 struct triple *label1, *label2, *label3;
6826 struct hash_entry *ident;
6828 eat(state, TOK_FOR);
6829 eat(state, TOK_LPAREN);
6830 head = test = tail = jmp1 = jmp2 = 0;
6831 if (peek(state) != TOK_SEMI) {
6834 eat(state, TOK_SEMI);
6835 if (peek(state) != TOK_SEMI) {
6838 test = ltrue_expr(state, read_expr(state, test));
6840 eat(state, TOK_SEMI);
6841 if (peek(state) != TOK_RPAREN) {
6844 eat(state, TOK_RPAREN);
6845 /* Generate the needed pieces */
6846 label1 = label(state);
6847 label2 = label(state);
6848 label3 = label(state);
6850 jmp1 = triple(state, OP_BRANCH, &void_type, label3, 0);
6851 jmp2 = triple(state, OP_BRANCH, &void_type, label1, test);
6854 jmp2 = triple(state, OP_BRANCH, &void_type, label1, 0);
6857 /* Remember where break and continue go */
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 */
6878 static void while_statement(struct compile_state *state, struct triple *first)
6880 struct triple *label1, *test, *label2, *jmp1, *jmp2, *end;
6881 struct hash_entry *ident;
6882 eat(state, TOK_WHILE);
6883 eat(state, TOK_LPAREN);
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);
6894 /* Remember where break and continue go */
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 */
6912 static void do_statement(struct compile_state *state, struct triple *first)
6914 struct triple *label1, *label2, *test, *end;
6915 struct hash_entry *ident;
6917 /* Generate the needed pieces */
6918 label1 = label(state);
6919 label2 = label(state);
6921 /* Remember where break and continue go */
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 */
6932 /* Eat the rest of the loop */
6933 eat(state, TOK_WHILE);
6934 eat(state, TOK_LPAREN);
6935 test = read_expr(state, expr(state));
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);
6949 static void return_statement(struct compile_state *state, struct triple *first)
6951 struct triple *jmp, *mv, *dest, *var, *val;
6953 eat(state, TOK_RETURN);
6955 #warning "FIXME implement a more general excess branch elimination"
6957 /* If we have a return value do some more work */
6958 if (peek(state) != TOK_SEMI) {
6959 val = read_expr(state, expr(state));
6961 eat(state, TOK_SEMI);
6963 /* See if this last statement in a function */
6964 last = ((peek(state) == TOK_RBRACE) &&
6965 (state->scope_depth == GLOBAL_SCOPE_DEPTH +2));
6967 /* Find the return variable */
6968 var = state->main_function->right;
6969 /* Find the return destination */
6970 dest = state->main_function->left->prev;
6972 /* If needed generate a jump instruction */
6974 jmp = triple(state, OP_BRANCH, &void_type, dest, 0);
6976 /* If needed generate an assignment instruction */
6978 mv = write_expr(state, var, val);
6980 /* Now put the code together */
6982 flatten(state, first, mv);
6983 flatten(state, first, jmp);
6986 flatten(state, first, jmp);
6990 static void break_statement(struct compile_state *state, struct triple *first)
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");
6998 dest = state->i_break->sym_ident->def;
6999 flatten(state, first, triple(state, OP_BRANCH, &void_type, dest, 0));
7002 static void continue_statement(struct compile_state *state, struct triple *first)
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");
7010 dest = state->i_continue->sym_ident->def;
7011 flatten(state, first, triple(state, OP_BRANCH, &void_type, dest, 0));
7014 static void goto_statement(struct compile_state *state, struct triple *first)
7017 eat(state, TOK_GOTO);
7018 eat(state, TOK_IDENT);
7019 eat(state, TOK_SEMI);
7020 error(state, 0, "goto is not implemeted");
7024 static void labeled_statement(struct compile_state *state, struct triple *first)
7027 eat(state, TOK_IDENT);
7028 eat(state, TOK_COLON);
7029 statement(state, first);
7030 error(state, 0, "labeled statements are not implemented");
7034 static void switch_statement(struct compile_state *state, struct triple *first)
7037 eat(state, TOK_SWITCH);
7038 eat(state, TOK_LPAREN);
7040 eat(state, TOK_RPAREN);
7041 statement(state, first);
7042 error(state, 0, "switch statements are not implemented");
7046 static void case_statement(struct compile_state *state, struct triple *first)
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");
7057 static void default_statement(struct compile_state *state, struct triple *first)
7060 eat(state, TOK_DEFAULT);
7061 eat(state, TOK_COLON);
7062 statement(state, first);
7063 error(state, 0, "default statements are not implemented");
7067 static void asm_statement(struct compile_state *state, struct triple *first)
7070 error(state, 0, "FIXME finish asm_statement");
7074 static int isdecl(int tok)
7097 case TOK_TYPE_NAME: /* typedef name */
7104 static void compound_statement(struct compile_state *state, struct triple *first)
7106 eat(state, TOK_LBRACE);
7109 /* statement-list opt */
7110 while (peek(state) != TOK_RBRACE) {
7111 statement(state, first);
7114 eat(state, TOK_RBRACE);
7117 static void statement(struct compile_state *state, struct triple *first)
7121 if (tok == TOK_LBRACE) {
7122 compound_statement(state, first);
7124 else if (tok == TOK_IF) {
7125 if_statement(state, first);
7127 else if (tok == TOK_FOR) {
7128 for_statement(state, first);
7130 else if (tok == TOK_WHILE) {
7131 while_statement(state, first);
7133 else if (tok == TOK_DO) {
7134 do_statement(state, first);
7136 else if (tok == TOK_RETURN) {
7137 return_statement(state, first);
7139 else if (tok == TOK_BREAK) {
7140 break_statement(state, first);
7142 else if (tok == TOK_CONTINUE) {
7143 continue_statement(state, first);
7145 else if (tok == TOK_GOTO) {
7146 goto_statement(state, first);
7148 else if (tok == TOK_SWITCH) {
7149 switch_statement(state, first);
7151 else if (tok == TOK_ASM) {
7152 asm_statement(state, first);
7154 else if ((tok == TOK_IDENT) && (peek2(state) == TOK_COLON)) {
7155 labeled_statement(state, first);
7157 else if (tok == TOK_CASE) {
7158 case_statement(state, first);
7160 else if (tok == TOK_DEFAULT) {
7161 default_statement(state, first);
7163 else if (isdecl(tok)) {
7164 /* This handles C99 intermixing of statements and decls */
7168 expr_statement(state, first);
7172 static struct type *param_decl(struct compile_state *state)
7175 struct hash_entry *ident;
7176 /* Cheat so the declarator will know we are not global */
7179 type = decl_specifiers(state);
7180 type = declarator(state, type, &ident, 0);
7181 type->ident = ident;
7186 static struct type *param_type_list(struct compile_state *state, struct type *type)
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");
7198 *next = new_type(TYPE_PRODUCT, *next, param_decl(state));
7199 next = &((*next)->right);
7206 static struct type *type_name(struct compile_state *state)
7209 type = specifier_qualifier_list(state);
7210 /* abstract-declarator (may consume no tokens) */
7211 type = declarator(state, type, 0, 0);
7215 static struct type *direct_declarator(
7216 struct compile_state *state, struct type *type,
7217 struct hash_entry **ident, int need_ident)
7222 arrays_complete(state, type);
7223 switch(peek(state)) {
7225 eat(state, TOK_IDENT);
7227 error(state, 0, "Unexpected identifier found");
7229 /* The name of what we are declaring */
7230 *ident = state->token[0].ident;
7233 eat(state, TOK_LPAREN);
7234 outer = declarator(state, type, ident, need_ident);
7235 eat(state, TOK_RPAREN);
7239 error(state, 0, "Identifier expected");
7245 arrays_complete(state, type);
7246 switch(peek(state)) {
7248 eat(state, TOK_LPAREN);
7249 type = param_type_list(state, type);
7250 eat(state, TOK_RPAREN);
7254 unsigned int qualifiers;
7255 struct triple *value;
7257 eat(state, TOK_LBRACKET);
7258 if (peek(state) != TOK_RBRACKET) {
7259 value = constant_expr(state);
7260 integral(state, value);
7262 eat(state, TOK_RBRACKET);
7264 qualifiers = type->type & (QUAL_MASK | STOR_MASK);
7265 type = new_type(TYPE_ARRAY | qualifiers, type, 0);
7267 type->elements = value->u.cval;
7268 free_triple(state, value);
7270 type->elements = ELEMENT_COUNT_UNSPECIFIED;
7282 arrays_complete(state, type);
7284 for(inner = outer; inner->left; inner = inner->left)
7292 static struct type *declarator(
7293 struct compile_state *state, struct type *type,
7294 struct hash_entry **ident, int need_ident)
7296 while(peek(state) == TOK_STAR) {
7297 eat(state, TOK_STAR);
7298 type = new_type(TYPE_POINTER | (type->type & STOR_MASK), type, 0);
7300 type = direct_declarator(state, type, ident, need_ident);
7305 static struct type *typedef_name(
7306 struct compile_state *state, unsigned int specifiers)
7308 struct hash_entry *ident;
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);
7322 static struct type *enum_specifier(
7323 struct compile_state *state, unsigned int specifiers)
7329 eat(state, TOK_ENUM);
7331 if (tok == TOK_IDENT) {
7332 eat(state, TOK_IDENT);
7334 if ((tok != TOK_IDENT) || (peek(state) == TOK_LBRACE)) {
7335 eat(state, TOK_LBRACE);
7337 eat(state, TOK_IDENT);
7338 if (peek(state) == TOK_EQ) {
7340 constant_expr(state);
7342 if (peek(state) == TOK_COMMA) {
7343 eat(state, TOK_COMMA);
7345 } while(peek(state) != TOK_RBRACE);
7346 eat(state, TOK_RBRACE);
7353 static struct type *struct_declarator(
7354 struct compile_state *state, struct type *type, struct hash_entry **ident)
7357 #warning "struct_declarator is complicated because of bitfields, kill them?"
7359 if (tok != TOK_COLON) {
7360 type = declarator(state, type, ident, 1);
7362 if ((tok == TOK_COLON) || (peek(state) == TOK_COLON)) {
7363 eat(state, TOK_COLON);
7364 constant_expr(state);
7371 static struct type *struct_or_union_specifier(
7372 struct compile_state *state, unsigned int specifiers)
7378 switch(peek(state)) {
7380 eat(state, TOK_STRUCT);
7383 eat(state, TOK_UNION);
7386 eat(state, TOK_STRUCT);
7390 if (tok == TOK_IDENT) {
7391 eat(state, TOK_IDENT);
7394 if ((tok != TOK_IDENT) || (peek(state) == TOK_LBRACE)) {
7395 eat(state, TOK_LBRACE);
7397 struct type *base_type;
7400 base_type = specifier_qualifier_list(state);
7403 struct hash_entry *ident;
7405 type = declarator(state, base_type, &ident, 1);
7406 if (peek(state) == TOK_COMMA) {
7408 eat(state, TOK_COMMA);
7411 eat(state, TOK_SEMI);
7412 } while(peek(state) != TOK_RBRACE);
7413 eat(state, TOK_RBRACE);
7419 static unsigned int storage_class_specifier_opt(struct compile_state *state)
7421 unsigned int specifiers;
7422 switch(peek(state)) {
7424 eat(state, TOK_AUTO);
7425 specifiers = STOR_AUTO;
7428 eat(state, TOK_REGISTER);
7429 specifiers = STOR_REGISTER;
7432 eat(state, TOK_STATIC);
7433 specifiers = STOR_STATIC;
7436 eat(state, TOK_EXTERN);
7437 specifiers = STOR_EXTERN;
7440 eat(state, TOK_TYPEDEF);
7441 specifiers = STOR_TYPEDEF;
7444 if (state->scope_depth <= GLOBAL_SCOPE_DEPTH) {
7445 specifiers = STOR_STATIC;
7448 specifiers = STOR_AUTO;
7454 static unsigned int function_specifier_opt(struct compile_state *state)
7456 /* Ignore the inline keyword */
7457 unsigned int specifiers;
7459 switch(peek(state)) {
7461 eat(state, TOK_INLINE);
7462 specifiers = STOR_INLINE;
7467 static unsigned int type_qualifiers(struct compile_state *state)
7469 unsigned int specifiers;
7472 specifiers = QUAL_NONE;
7474 switch(peek(state)) {
7476 eat(state, TOK_CONST);
7477 specifiers = QUAL_CONST;
7480 eat(state, TOK_VOLATILE);
7481 specifiers = QUAL_VOLATILE;
7484 eat(state, TOK_RESTRICT);
7485 specifiers = QUAL_RESTRICT;
7495 static struct type *type_specifier(
7496 struct compile_state *state, unsigned int spec)
7500 switch(peek(state)) {
7502 eat(state, TOK_VOID);
7503 type = new_type(TYPE_VOID | spec, 0, 0);
7506 eat(state, TOK_CHAR);
7507 type = new_type(TYPE_CHAR | spec, 0, 0);
7510 eat(state, TOK_SHORT);
7511 if (peek(state) == TOK_INT) {
7512 eat(state, TOK_INT);
7514 type = new_type(TYPE_SHORT | spec, 0, 0);
7517 eat(state, TOK_INT);
7518 type = new_type(TYPE_INT | spec, 0, 0);
7521 eat(state, TOK_LONG);
7522 switch(peek(state)) {
7524 eat(state, TOK_LONG);
7525 error(state, 0, "long long not supported");
7528 eat(state, TOK_DOUBLE);
7529 error(state, 0, "long double not supported");
7532 eat(state, TOK_INT);
7533 type = new_type(TYPE_LONG | spec, 0, 0);
7536 type = new_type(TYPE_LONG | spec, 0, 0);
7541 eat(state, TOK_FLOAT);
7542 error(state, 0, "type float not supported");
7545 eat(state, TOK_DOUBLE);
7546 error(state, 0, "type double not supported");
7549 eat(state, TOK_SIGNED);
7550 switch(peek(state)) {
7552 eat(state, TOK_LONG);
7553 switch(peek(state)) {
7555 eat(state, TOK_LONG);
7556 error(state, 0, "type long long not supported");
7559 eat(state, TOK_INT);
7560 type = new_type(TYPE_LONG | spec, 0, 0);
7563 type = new_type(TYPE_LONG | spec, 0, 0);
7568 eat(state, TOK_INT);
7569 type = new_type(TYPE_INT | spec, 0, 0);
7572 eat(state, TOK_SHORT);
7573 type = new_type(TYPE_SHORT | spec, 0, 0);
7576 eat(state, TOK_CHAR);
7577 type = new_type(TYPE_CHAR | spec, 0, 0);
7580 type = new_type(TYPE_INT | spec, 0, 0);
7585 eat(state, TOK_UNSIGNED);
7586 switch(peek(state)) {
7588 eat(state, TOK_LONG);
7589 switch(peek(state)) {
7591 eat(state, TOK_LONG);
7592 error(state, 0, "unsigned long long not supported");
7595 eat(state, TOK_INT);
7596 type = new_type(TYPE_ULONG | spec, 0, 0);
7599 type = new_type(TYPE_ULONG | spec, 0, 0);
7604 eat(state, TOK_INT);
7605 type = new_type(TYPE_UINT | spec, 0, 0);
7608 eat(state, TOK_SHORT);
7609 type = new_type(TYPE_USHORT | spec, 0, 0);
7612 eat(state, TOK_CHAR);
7613 type = new_type(TYPE_UCHAR | spec, 0, 0);
7616 type = new_type(TYPE_UINT | spec, 0, 0);
7620 /* struct or union specifier */
7623 type = struct_or_union_specifier(state, spec);
7625 /* enum-spefifier */
7627 type = enum_specifier(state, spec);
7631 type = typedef_name(state, spec);
7634 error(state, 0, "bad type specifier %s",
7635 tokens[peek(state)]);
7641 static int istype(int tok)
7667 static struct type *specifier_qualifier_list(struct compile_state *state)
7670 unsigned int specifiers = 0;
7672 /* type qualifiers */
7673 specifiers |= type_qualifiers(state);
7675 /* type specifier */
7676 type = type_specifier(state, specifiers);
7681 static int isdecl_specifier(int tok)
7684 /* storage class specifier */
7690 /* type qualifier */
7694 /* type specifiers */
7704 /* struct or union specifier */
7707 /* enum-spefifier */
7711 /* function specifiers */
7719 static struct type *decl_specifiers(struct compile_state *state)
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.
7729 /* storage class specifier */
7730 specifiers |= storage_class_specifier_opt(state);
7732 /* function-specifier */
7733 specifiers |= function_specifier_opt(state);
7735 /* type qualifier */
7736 specifiers |= type_qualifiers(state);
7738 /* type specifier */
7739 type = type_specifier(state, specifiers);
7743 static unsigned designator(struct compile_state *state)
7749 switch(peek(state)) {
7752 struct triple *value;
7753 eat(state, TOK_LBRACKET);
7754 value = constant_expr(state);
7755 eat(state, TOK_RBRACKET);
7756 index = value->u.cval;
7760 eat(state, TOK_DOT);
7761 eat(state, TOK_IDENT);
7762 error(state, 0, "Struct Designators not currently supported");
7765 error(state, 0, "Invalid designator");
7768 } while((tok == TOK_LBRACKET) || (tok == TOK_DOT));
7773 static struct triple *initializer(
7774 struct compile_state *state, struct type *type)
7776 struct triple *result;
7777 if (peek(state) != TOK_LBRACE) {
7778 result = assignment_expr(state);
7782 unsigned index, max_index;
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) {
7791 error(state, 0, "Struct initializers not currently supported");
7793 buf = xcmalloc(size_of(state, type), "initializer");
7794 eat(state, TOK_LBRACE);
7796 struct triple *value;
7797 struct type *value_type;
7802 if ((tok == TOK_LBRACKET) || (tok == TOK_DOT)) {
7803 index = designator(state);
7805 if ((max_index != ELEMENT_COUNT_UNSPECIFIED) &&
7806 (index > max_index)) {
7807 error(state, 0, "element beyond bounds");
7810 if ((type->type & TYPE_MASK) == TYPE_ARRAY) {
7811 value_type = type->left;
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)) {
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);
7827 if (value->op == OP_BLOBCONST) {
7828 memcpy((char *)buf + index * value_size, value->u.blob, value_size);
7830 else if ((value->op == OP_INTCONST) && (value_size == 1)) {
7831 *(((uint8_t *)buf) + index) = value->u.cval & 0xff;
7833 else if ((value->op == OP_INTCONST) && (value_size == 2)) {
7834 *(((uint16_t *)buf) + index) = value->u.cval & 0xffff;
7836 else if ((value->op == OP_INTCONST) && (value_size == 4)) {
7837 *(((uint32_t *)buf) + index) = value->u.cval & 0xffffffff;
7840 fprintf(stderr, "%d %d\n",
7841 value->op, value_size);
7842 internal_error(state, 0, "unhandled constant initializer");
7844 if (peek(state) == TOK_COMMA) {
7845 eat(state, TOK_COMMA);
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;
7857 static struct triple *function_definition(
7858 struct compile_state *state, struct type *type)
7860 struct triple *def, *tmp, *first, *end;
7861 struct hash_entry *ident;
7864 if ((type->type &TYPE_MASK) != TYPE_FUNCTION) {
7865 error(state, 0, "Invalid function header");
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");
7874 param = type->right;
7876 while((param->type & TYPE_MASK) == TYPE_PRODUCT) {
7878 if (!param->left->ident) {
7879 error(state, 0, "No identifier for parameter %d\n", i);
7881 param = param->right;
7884 if (((param->type & TYPE_MASK) != TYPE_VOID) && !param->ident) {
7885 error(state, 0, "No identifier for paramter %d\n", i);
7888 /* Get a list of statements for this function. */
7889 def = triple(state, OP_LIST, type, 0, 0);
7891 /* Start a new scope for the passed parameters */
7894 /* Put a label at the very start of a function */
7895 first = label(state);
7898 /* Put a label at the very end of a function */
7900 flatten(state, first, end);
7902 /* Walk through the parameters and create symbol table entries
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;
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);
7920 /* Add a variable for the return value */
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 */
7930 /* Remember which function I am compiling.
7931 * Also assume the last defined function is the main function.
7933 state->main_function = def;
7935 /* Now get the actual function definition */
7936 compound_statement(state, end);
7938 /* Remove the parameter scope */
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");
7951 static struct triple *do_decl(struct compile_state *state,
7952 struct type *type, struct hash_entry *ident)
7956 /* Clean up the storage types used */
7957 switch (type->type & STOR_MASK) {
7960 /* These are the good types I am aiming for */
7963 type->type &= ~STOR_MASK;
7964 type->type |= STOR_AUTO;
7967 type->type &= ~STOR_MASK;
7968 type->type |= STOR_STATIC;
7971 #warning "FIXME support typedefs"
7972 error(state, 0, "typedefs not currently supported");
7975 internal_error(state, 0, "Undefined storage class");
7977 if (((type->type & STOR_MASK) == STOR_STATIC) &&
7978 ((type->type & QUAL_CONST) == 0)) {
7979 error(state, 0, "non const static variables not supported");
7982 def = variable(state, type);
7983 symbol(state, ident, &ident->sym_ident, def, type);
7988 static void decl(struct compile_state *state, struct triple *first)
7990 struct type *base_type, *type;
7991 struct hash_entry *ident;
7994 global = (state->scope_depth <= GLOBAL_SCOPE_DEPTH);
7995 base_type = decl_specifiers(state);
7997 type = declarator(state, base_type, &ident, 0);
7998 if (global && ident && (peek(state) == TOK_LBRACE)) {
8000 def = function_definition(state, type);
8001 symbol(state, ident, &ident->sym_ident, def, type);
8005 flatten(state, first, do_decl(state, type, ident));
8006 /* type or variable definition */
8009 if (peek(state) == TOK_EQ) {
8011 error(state, 0, "cannot assign to a type");
8014 flatten(state, first,
8016 ident->sym_ident->def,
8017 initializer(state, type)));
8019 arrays_complete(state, type);
8020 if (peek(state) == TOK_COMMA) {
8021 eat(state, TOK_COMMA);
8023 type = declarator(state, base_type, &ident, 0);
8024 flatten(state, first, do_decl(state, type, ident));
8028 eat(state, TOK_SEMI);
8032 static void decls(struct compile_state *state)
8034 struct triple *list;
8036 list = label(state);
8039 if (tok == TOK_EOF) {
8042 if (tok == TOK_SPACE) {
8043 eat(state, TOK_SPACE);
8046 if (list->next != list) {
8047 error(state, 0, "global variables not supported");
8053 * Data structurs for optimation.
8056 static void do_use_block(
8057 struct block *used, struct block_set **head, struct block *user,
8060 struct block_set **ptr, *new;
8067 if ((*ptr)->member == user) {
8070 ptr = &(*ptr)->next;
8072 new = xcmalloc(sizeof(*new), "block_set");
8083 static void do_unuse_block(
8084 struct block *used, struct block_set **head, struct block *unuser)
8086 struct block_set *use, **ptr;
8090 if (use->member == unuser) {
8092 memset(use, -1, sizeof(*use));
8101 static void use_block(struct block *used, struct block *user)
8103 /* Append new to the head of the list, print_block
8106 do_use_block(used, &used->use, user, 1);
8109 static void unuse_block(struct block *used, struct block *unuser)
8111 do_unuse_block(used, &used->use, unuser);
8115 static void idom_block(struct block *idom, struct block *user)
8117 do_use_block(idom, &idom->idominates, user, 0);
8120 static void unidom_block(struct block *idom, struct block *unuser)
8122 do_unuse_block(idom, &idom->idominates, unuser);
8125 static void domf_block(struct block *block, struct block *domf)
8127 do_use_block(block, &block->domfrontier, domf, 0);
8130 static void undomf_block(struct block *block, struct block *undomf)
8132 do_unuse_block(block, &block->domfrontier, undomf);
8135 static void ipdom_block(struct block *ipdom, struct block *user)
8137 do_use_block(ipdom, &ipdom->ipdominates, user, 0);
8140 static void unipdom_block(struct block *ipdom, struct block *unuser)
8142 do_unuse_block(ipdom, &ipdom->ipdominates, unuser);
8145 static void ipdomf_block(struct block *block, struct block *ipdomf)
8147 do_use_block(block, &block->ipdomfrontier, ipdomf, 0);
8150 static void unipdomf_block(struct block *block, struct block *unipdomf)
8152 do_unuse_block(block, &block->ipdomfrontier, unipdomf);
8157 static 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))
8162 result = cb(state, ptr, depth);
8163 if ((result == 0) && (ptr->op == OP_LIST)) {
8164 struct triple *list;
8168 result = do_walk_triple(state, ptr, depth + 1, cb);
8169 if (ptr->next->prev != ptr) {
8170 internal_error(state, ptr->next, "bad prev");
8174 } while((result == 0) && (ptr != list->left));
8179 static int walk_triple(
8180 struct compile_state *state,
8182 int (*cb)(struct compile_state *state, struct triple *ptr, int depth))
8184 return do_walk_triple(state, ptr, 0, cb);
8187 static void do_print_prefix(int depth)
8190 for(i = 0; i < depth; i++) {
8195 #define PRINT_LIST 1
8196 static int do_print_triple(struct compile_state *state, struct triple *ins, int depth)
8200 if (op == OP_LIST) {
8205 else if ((op == OP_LABEL) && (ins->use)) {
8206 printf("\n%p:\n", ins);
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);
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);
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?");
8232 struct triple_set *user;
8233 for(user = ins->use; user; user = user->next) {
8234 printf("use: %p\n", user->member);
8238 if (triple_is_branch(ins)) {
8244 static void print_triple(struct compile_state *state, struct triple *ins)
8246 walk_triple(state, ins, do_print_triple);
8249 static void print_triples(struct compile_state *state)
8251 print_triple(state, state->main_function);
8255 struct block *block;
8257 static void find_cf_blocks(struct cf_block *cf, struct block *block)
8259 if (!block || (cf[block->vertex].block == block)) {
8262 cf[block->vertex].block = block;
8263 find_cf_blocks(cf, block->left);
8264 find_cf_blocks(cf, block->right);
8267 static void print_control_flow(struct compile_state *state)
8269 struct cf_block *cf;
8271 printf("\ncontrol flow\n");
8272 cf = xcmalloc(sizeof(*cf) * (state->last_vertex + 1), "cf_block");
8273 find_cf_blocks(cf, state->first_block);
8275 for(i = 1; i <= state->last_vertex; i++) {
8276 struct block *block;
8277 block = cf[i].block;
8280 printf("(%p) %d:", block, block->vertex);
8282 printf(" %d", block->left->vertex);
8284 if (block->right && (block->right != block->left)) {
8285 printf(" %d", block->right->vertex);
8294 static struct block *basic_block(struct compile_state *state,
8295 struct triple *first)
8297 struct block *block;
8300 if (first->op != OP_LABEL) {
8301 internal_error(state, 0, "block does not start with a label");
8303 /* See if this basic block has already been setup */
8304 if (first->u.block != 0) {
8305 return first->u.block;
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;
8314 if ((ptr != first) && (ptr->op == OP_LABEL) && ptr->use) {
8318 /* If ptr->u is not used remember where the baic block is */
8319 if (!is_const(ptr)) {
8320 ptr->u.block = block;
8322 if (ptr->op == OP_BRANCH) {
8326 } while (ptr != state->main_function->left);
8327 if (ptr == state->main_function->left)
8330 if (op == OP_LABEL) {
8331 block->left = basic_block(state, ptr);
8333 use_block(block->left, block);
8335 else if (op == OP_BRANCH) {
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 */
8342 block->left = basic_block(state, ptr->next);
8343 use_block(block->left, block);
8347 internal_error(state, 0, "Bad basic block split");
8353 static void walk_blocks(struct compile_state *state,
8354 void (*cb)(struct compile_state *state, struct block *block, void *arg),
8357 struct triple *ptr, *first;
8358 struct block *last_block;
8360 first = state->main_function->left;
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);
8372 } while(ptr != first);
8375 static void print_block(
8376 struct compile_state *state, struct block *block, void *arg)
8380 printf("\nblock: %p (%d), %p<-%p %p<-%p\n",
8384 block->left && block->left->use?block->left->use->member : 0,
8386 block->right && block->right->use?block->right->use->member : 0);
8387 if (block->first->op == OP_LABEL) {
8388 printf("%p:\n", block->first);
8390 for(ptr = block->first; ; ptr = ptr->next) {
8391 struct triple_set *user;
8394 if (!IS_CONST_OP(op)) {
8395 if (ptr->u.block != block) {
8396 internal_error(state, ptr,
8397 "Wrong block pointer: %p\n",
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",
8410 if (op == OP_INTCONST) {
8411 printf("(%p) %3d %-7s %08lx @ %s:%d.%d\n",
8412 ptr, ID_REG(ptr->id), tops(ptr->op),
8414 ptr->filename, ptr->line, ptr->col);
8416 else if (op == OP_PHI) {
8417 struct triple **slot;
8418 struct block *block;
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]);
8427 printf(" @%s:%d.%d\n",
8428 ptr->filename, ptr->line, ptr->col);
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);
8436 /* Sanity checks... */
8437 valid_op(state, ptr);
8438 for(user = ptr->use; user; user = user->next) {
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?",
8450 if (ptr == block->last)
8457 static void print_blocks(struct compile_state *state)
8459 printf("--------------- blocks ---------------\n");
8460 walk_blocks(state, print_block, 0);
8463 static void prune_nonblock_triples(struct compile_state *state)
8465 struct block *block;
8466 struct triple *first, *ins;
8467 /* Delete the triples not in a basic block */
8468 first = state->main_function->left;
8472 if (ins->op == OP_LABEL) {
8473 block = ins->u.block;
8477 release_triple(state, ins->prev);
8479 } while(ins != first);
8482 static void setup_basic_blocks(struct compile_state *state)
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?");
8494 /* Insert an extra unused edge from start to the end
8495 * This helps with reverse control flow calculations.
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);
8505 static void free_basic_block(struct compile_state *state, struct block *block)
8507 struct block_set *entry, *next;
8508 struct block *child;
8512 if (block->vertex == -1) {
8517 unuse_block(block->left, block);
8520 unuse_block(block->right, block);
8523 unidom_block(block->idom, block);
8527 unipdom_block(block->ipdom, block);
8530 for(entry = block->use; entry; entry = next) {
8532 child = entry->member;
8533 unuse_block(block, child);
8534 if (child->left == block) {
8537 if (child->right == block) {
8541 for(entry = block->idominates; entry; entry = next) {
8543 child = entry->member;
8544 unidom_block(block, child);
8547 for(entry = block->domfrontier; entry; entry = next) {
8549 child = entry->member;
8550 undomf_block(block, child);
8552 for(entry = block->ipdominates; entry; entry = next) {
8554 child = entry->member;
8555 unipdom_block(block, child);
8558 for(entry = block->ipdomfrontier; entry; entry = next) {
8560 child = entry->member;
8561 unipdomf_block(block, child);
8563 if (block->users != 0) {
8564 internal_error(state, 0, "block still has users");
8566 free_basic_block(state, block->left);
8568 free_basic_block(state, block->right);
8570 memset(block, -1, sizeof(*block));
8574 static void free_basic_blocks(struct compile_state *state)
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;
8583 if (!is_const(ins)) {
8587 } while(ins != first);
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;
8603 static void unsdom_block(struct sdom_block *block)
8605 struct sdom_block **ptr;
8606 if (!block->sdom_next) {
8609 ptr = &block->sdom->sdominates;
8611 if ((*ptr) == block) {
8612 *ptr = block->sdom_next;
8615 ptr = &(*ptr)->sdom_next;
8619 static void sdom_block(struct sdom_block *sdom, struct sdom_block *block)
8621 unsdom_block(block);
8623 block->sdom_next = sdom->sdominates;
8624 sdom->sdominates = block;
8629 static int initialize_sdblock(struct sdom_block *sd,
8630 struct block *parent, struct block *block, int vertex)
8632 if (!block || (sd[block->vertex].block == block)) {
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);
8649 static int initialize_sdpblock(struct sdom_block *sd,
8650 struct block *parent, struct block *block, int vertex)
8652 struct block_set *user;
8653 if (!block || (sd[block->vertex].block == block)) {
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);
8671 static void compress_ancestors(struct sdom_block *v)
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));
8679 * ancestor(v) = ancestor(ancestor(v));
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;
8690 v->ancestor = v->ancestor->ancestor;
8694 static void compute_sdom(struct compile_state *state, struct sdom_block *sd)
8698 * for each v <= pred(w) {
8700 * if (semi[u] < semi[w] {
8701 * semi[w] = semi[u];
8704 * add w to bucket(vertex(semi[w]));
8705 * LINK(parent(w), w);
8708 * for each v <= bucket(parent(w)) {
8709 * delete v from bucket(parent(w));
8711 * dom(v) = (semi[u] < semi[v]) ? u : parent(w);
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;
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;
8729 sdom_block(sd[i].sdom, &sd[i]);
8730 sd[i].ancestor = parent;
8732 for(v = parent->sdominates; v; v = next) {
8733 struct sdom_block *u;
8734 next = v->sdom_next;
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;
8743 static void compute_spdom(struct compile_state *state, struct sdom_block *sd)
8747 * for each v <= pred(w) {
8749 * if (semi[u] < semi[w] {
8750 * semi[w] = semi[u];
8753 * add w to bucket(vertex(semi[w]));
8754 * LINK(parent(w), w);
8757 * for each v <= bucket(parent(w)) {
8758 * delete v from bucket(parent(w));
8760 * dom(v) = (semi[u] < semi[v]) ? u : parent(w);
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;
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;
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;
8783 sdom_block(sd[i].sdom, &sd[i]);
8784 sd[i].ancestor = parent;
8786 for(v = parent->sdominates; v; v = next) {
8787 struct sdom_block *u;
8788 next = v->sdom_next;
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;
8797 static void compute_idom(struct compile_state *state, struct sdom_block *sd)
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;
8806 idom_block(block->idom, block);
8808 sd[1].block->idom = 0;
8811 static void compute_ipdom(struct compile_state *state, struct sdom_block *sd)
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;
8820 ipdom_block(block->ipdom, block);
8822 sd[1].block->ipdom = 0;
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.
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
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) */
8842 * Let w != r. Suppose every u for which sdom(w) -> u -> w satisfies
8843 * sdom(u) >= sdom(w). Then idom(w) = sdom(w).
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).
8850 /* Lemma 5: Let vertices v,w satisfy v -> w.
8851 * Then v -> idom(w) or idom(w) -> idom(v)
8854 static void find_immediate_dominators(struct compile_state *state)
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}
8861 * For any vertex w != r.
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})
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.
8870 * { sdom(w) if sdom(w) = sdom(u),
8872 * { idom(u) otherwise
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
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);
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);
8903 static void find_post_dominators(struct compile_state *state)
8905 struct sdom_block *sd;
8906 /* Step 1 initialize the basic block information */
8907 sd = xcmalloc(sizeof(*sd) * (state->last_vertex + 1), "sdom_state");
8909 initialize_sdpblock(sd, 0, state->last_block, 0);
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);
8921 static void find_block_domf(struct compile_state *state, struct block *block)
8923 struct block *child;
8924 struct block_set *user;
8925 if (block->domfrontier != 0) {
8926 internal_error(state, block->first, "domfrontier present?");
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");
8933 find_block_domf(state, child);
8935 if (block->left && block->left->idom != block) {
8936 domf_block(block, block->left);
8938 if (block->right && block->right->idom != block) {
8939 domf_block(block, block->right);
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);
8952 static void find_block_ipdomf(struct compile_state *state, struct block *block)
8954 struct block *child;
8955 struct block_set *user;
8956 if (block->ipdomfrontier != 0) {
8957 internal_error(state, block->first, "ipdomfrontier present?");
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");
8964 find_block_ipdomf(state, child);
8966 if (block->left && block->left->ipdom != block) {
8967 ipdomf_block(block, block->left);
8969 if (block->right && block->right->ipdom != block) {
8970 ipdomf_block(block, block->right);
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);
8983 static int print_dominated(
8984 struct compile_state *state, struct block *block, int vertex)
8986 struct block_set *user;
8988 if (!block || (block->vertex != vertex + 1)) {
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");
9001 vertex = print_dominated(state, block->left, vertex);
9002 vertex = print_dominated(state, block->right, vertex);
9006 static void print_dominators(struct compile_state *state)
9008 printf("\ndominates\n");
9009 print_dominated(state, state->first_block, 0);
9013 static int print_frontiers(
9014 struct compile_state *state, struct block *block, int vertex)
9016 struct block_set *user;
9018 if (!block || (block->vertex != vertex + 1)) {
9023 printf("%d:", block->vertex);
9024 for(user = block->domfrontier; user; user = user->next) {
9025 printf(" %d", user->member->vertex);
9029 vertex = print_frontiers(state, block->left, vertex);
9030 vertex = print_frontiers(state, block->right, vertex);
9033 static void print_dominance_frontiers(struct compile_state *state)
9035 printf("\ndominance frontiers\n");
9036 print_frontiers(state, state->first_block, 0);
9040 static void analyze_idominators(struct compile_state *state)
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);
9056 static int print_ipdominated(
9057 struct compile_state *state, struct block *block, int vertex)
9059 struct block_set *user;
9061 if (!block || (block->vertex != vertex + 1)) {
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");
9074 for(user = block->use; user; user = user->next) {
9075 vertex = print_ipdominated(state, user->member, vertex);
9080 static void print_ipdominators(struct compile_state *state)
9082 printf("\nipdominates\n");
9083 print_ipdominated(state, state->last_block, 0);
9086 static int print_pfrontiers(
9087 struct compile_state *state, struct block *block, int vertex)
9089 struct block_set *user;
9091 if (!block || (block->vertex != vertex + 1)) {
9096 printf("%d:", block->vertex);
9097 for(user = block->ipdomfrontier; user; user = user->next) {
9098 printf(" %d", user->member->vertex);
9101 for(user = block->use; user; user = user->next) {
9102 vertex = print_pfrontiers(state, user->member, vertex);
9106 static void print_ipdominance_frontiers(struct compile_state *state)
9108 printf("\nipdominance frontiers\n");
9109 print_pfrontiers(state, state->last_block, 0);
9113 static void analyze_ipdominators(struct compile_state *state)
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);
9128 static void insert_phi_operations(struct compile_state *state)
9131 struct triple *first;
9132 int *has_already, *work;
9133 struct block *work_list, **work_list_tail;
9137 size = sizeof(int) * (state->last_vertex + 1);
9138 has_already = xcmalloc(size, "has_already");
9139 work = xcmalloc(size, "work");
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) {
9151 work_list_tail = &work_list;
9152 for(user = var->use; user; user = user->next) {
9153 if (user->member->op == OP_READ) {
9156 if (user->member->op != OP_WRITE) {
9157 internal_error(state, user->member,
9158 "bad variable access");
9160 block = user->member->u.block;
9162 warning(state, user->member, "dead code");
9164 work[block->vertex] = iter;
9165 *work_list_tail = block;
9166 block->work_next = 0;
9167 work_list_tail = &block->work_next;
9169 for(block = work_list; block; block = block->work_next) {
9170 struct block_set *df;
9171 for(df = block->domfrontier; df; df = df->next) {
9173 struct block *front;
9177 if (has_already[front->vertex] >= iter) {
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,
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;
9196 has_already[front->vertex] = iter;
9198 /* If necessary plan to visit the basic block */
9199 if (work[front->vertex] >= iter) {
9202 work[front->vertex] = iter;
9203 *work_list_tail = front;
9204 front->work_next = 0;
9205 work_list_tail = &front->work_next;
9217 static void fixup_block_phi_variables(
9218 struct compile_state *state, struct block *parent, struct block *block)
9220 struct block_set *set;
9223 if (!parent || !block)
9225 /* Find the edge I am coming in on */
9227 for(set = block->use; set; set = set->next, edge++) {
9228 if (set->member == parent) {
9233 internal_error(state, 0, "phi input is not on a control predecessor");
9235 for(ptr = block->first; ; ptr = ptr->next) {
9236 if (ptr->op == OP_PHI) {
9237 struct triple *var, *val, **slot;
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");
9244 slot = (struct triple **)(ptr->left);
9246 if ((*slot != 0) && (*slot != val)) {
9247 internal_error(state, ptr, "phi already bound on this edge");
9250 use_triple(val, ptr);
9252 if (ptr == block->last) {
9259 static void rename_block_variables(
9260 struct compile_state *state, struct block *block)
9262 struct block_set *user;
9263 struct triple *ptr, *next, *last;
9267 last = block->first;
9269 for(ptr = block->first; !done; ptr = next) {
9271 if (ptr == block->last) {
9275 if (ptr->op == OP_READ) {
9276 struct triple *var, *val;
9278 unuse_triple(var, ptr);
9280 error(state, ptr, "variable used without being set");
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");
9287 propogate_use(state, ptr, val);
9288 release_triple(state, ptr);
9292 if (ptr->op == OP_WRITE) {
9293 struct triple *var, *val;
9296 if ((val->op == OP_WRITE) || (val->op == OP_READ)) {
9297 internal_error(state, val, "bad value in write");
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);
9304 if (ptr->op == OP_PHI) {
9307 /* Push OP_PHI onto a stack of variable uses */
9308 push_triple(var, ptr);
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);
9321 /* pop the renamed variable stack */
9322 last = block->first;
9324 for(ptr = block->first; !done ; ptr = next) {
9326 if (ptr == block->last) {
9329 if (ptr->op == OP_WRITE) {
9332 /* Pop OP_WRITE ptr->right from the stack of variable uses */
9333 pop_triple(var, ptr->right);
9334 release_triple(state, ptr);
9337 if (ptr->op == OP_PHI) {
9340 /* Pop OP_WRITE ptr->right from the stack of variable uses */
9341 pop_triple(var, ptr);
9348 static void prune_block_variables(struct compile_state *state,
9349 struct block *block)
9351 struct block_set *user;
9352 struct triple *next, *last, *ptr;
9354 last = block->first;
9356 for(ptr = block->first; !done; ptr = next) {
9358 if (ptr == block->last) {
9361 if (ptr->op == OP_ADECL) {
9362 struct triple_set *user, *next;
9363 for(user = ptr->use; user; user = next) {
9367 if (use->op != OP_PHI) {
9368 internal_error(state, use, "decl still used");
9370 if (use->right != ptr) {
9371 internal_error(state, use, "bad phi use of decl");
9373 unuse_triple(ptr, use);
9376 release_triple(state, ptr);
9382 for(user = block->idominates; user; user = user->next) {
9383 prune_block_variables(state, user->member);
9387 static void transform_to_ssa_form(struct compile_state *state)
9389 insert_phi_operations(state);
9391 printf("@%s:%d\n", __FILE__, __LINE__);
9392 print_blocks(state);
9394 rename_block_variables(state, state->first_block);
9395 prune_block_variables(state, state->first_block);
9399 static void transform_from_ssa_form(struct compile_state *state)
9401 /* To get out of ssa form we insert moves on the incoming
9402 * edges to blocks containting phi functions.
9404 struct triple *first;
9405 struct triple *phi, *next;
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;
9416 if (phi->op != OP_PHI) {
9419 block = phi->u.block;
9420 slot = (struct triple **)(phi->left);
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);
9428 /* Replaces uses of the phi with variable reads */
9429 propogate_use(state, phi, read);
9431 /* Walk all of the incoming edges/blocks and insert moves.
9433 for(edge = 0, set = block->use; set; set = set->next, edge++) {
9434 struct block *eblock;
9435 struct triple *move;
9437 eblock = set->member;
9439 unuse_triple(val, phi);
9445 move = post_triple(state,
9446 val, OP_WRITE, phi->type, var, val);
9447 use_triple(val, move);
9448 use_triple(var, move);
9450 release_triple(state, phi);
9455 static void insert_copies_to_phi(struct compile_state *state)
9457 /* To get out of ssa form we insert moves on the incoming
9458 * edges to blocks containting phi functions.
9460 struct triple *first;
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;
9470 if (phi->op != OP_PHI) {
9473 if (ID_REG(phi->id) == REG_UNSET) {
9474 phi->id = MK_REG_ID(alloc_virtual_reg(),
9475 ID_REG_CLASSES(phi->id));
9477 block = phi->u.block;
9478 slot = (struct triple **)(phi->left);
9479 /* Walk all of the incoming edges/blocks and insert moves.
9481 for(edge = 0, set = block->use; set; set = set->next, edge++) {
9482 struct block *eblock;
9483 struct triple *move;
9486 eblock = set->member;
9493 move = build_triple(state, OP_COPY, phi->type, val, 0,
9494 val->filename, val->line, val->col);
9495 move->u.block = eblock;
9497 use_triple(val, move);
9500 unuse_triple(val, phi);
9501 use_triple(move, phi);
9503 /* Walk through the block backwards to find
9504 * an appropriate location for the OP_COPY.
9506 for(ptr = eblock->last; ptr != eblock->first; ptr = ptr->prev) {
9507 struct triple **expr;
9508 if ((ptr == phi) || (ptr == val)) {
9511 expr = triple_rhs(state, ptr, 0);
9512 for(;expr; expr = triple_rhs(state, ptr, expr)) {
9513 if ((*expr) == phi) {
9519 if (triple_is_branch(ptr)) {
9520 internal_error(state, ptr,
9521 "Could not insert write to phi");
9523 insert_triple(state, ptr->next, move);
9524 if (eblock->last == ptr) {
9525 eblock->last = move;
9531 struct triple_reg_set {
9532 struct triple_reg_set *next;
9533 struct triple *member;
9538 struct block *block;
9539 struct triple_reg_set *in;
9540 struct triple_reg_set *out;
9544 static int do_triple_set(struct triple_reg_set **head,
9545 struct triple *member, struct triple *new_member)
9547 struct triple_reg_set **ptr, *new;
9552 if ((*ptr)->member == member) {
9555 ptr = &(*ptr)->next;
9557 new = xcmalloc(sizeof(*new), "triple_set");
9558 new->member = member;
9559 new->new = new_member;
9565 static void do_triple_unset(struct triple_reg_set **head, struct triple *member)
9567 struct triple_reg_set *entry, **ptr;
9571 if (entry->member == member) {
9582 static int in_triple(struct reg_block *rb, struct triple *in)
9584 return do_triple_set(&rb->in, in, 0);
9586 static void unin_triple(struct reg_block *rb, struct triple *unin)
9588 do_triple_unset(&rb->in, unin);
9591 static int out_triple(struct reg_block *rb, struct triple *out)
9593 return do_triple_set(&rb->out, out, 0);
9595 static void unout_triple(struct reg_block *rb, struct triple *unout)
9597 do_triple_unset(&rb->out, unout);
9600 static int initialize_regblock(struct reg_block *blocks,
9601 struct block *block, int vertex)
9603 struct block_set *user;
9604 if (!block || (blocks[block->vertex].block == block)) {
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);
9618 static int phi_in(struct compile_state *state, struct reg_block *blocks,
9619 struct reg_block *rb, struct block *suc)
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.
9625 struct block_set *set;
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) {
9637 internal_error(state, 0, "Not coming on a control edge?");
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) {
9646 slot = (struct triple **)(ptr->left);
9648 out_change = out_triple(rb, expr);
9652 /* If we don't define the variable also plast it
9653 * in the current blocks input set.
9655 ptr2 = rb->block->first;
9656 for(done2 = 0; !done2; ptr2 = ptr2->next) {
9660 done2 = (ptr2 == rb->block->last);
9665 change |= in_triple(rb, expr);
9670 static int reg_in(struct compile_state *state, struct reg_block *blocks,
9671 struct reg_block *rb, struct block *suc)
9673 struct triple_reg_set *in_set;
9676 /* Read the input set of a successor block
9677 * and place it in the current blocks output set.
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);
9687 /* If we don't define the variable also place it
9688 * in the current blocks input set.
9690 first = rb->block->first;
9691 last = rb->block->last;
9693 for(ptr = first; !done; ptr = ptr->next) {
9694 if (ptr == in_set->member) {
9697 done = (ptr == last);
9702 change |= in_triple(rb, in_set->member);
9704 change |= phi_in(state, blocks, rb, suc);
9709 static int use_in(struct compile_state *state, struct reg_block *rb)
9711 /* Find the variables we use but don't define and add
9712 * it to the current blocks input set.
9714 #warning "FIXME is this O(N^2) algorithm bad?"
9715 struct block *block;
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
9728 if (ptr->op == OP_PHI) {
9731 expr = triple_rhs(state, ptr, 0);
9732 for(;expr; expr = triple_rhs(state, ptr, expr)) {
9733 struct triple *rhs, *test;
9736 /* See if rhs is defined in this block */
9737 for(tdone = 0, test = ptr; !tdone; test = test->prev) {
9738 tdone = (test == block->first);
9744 /* If the triple is not a definition skip it. */
9745 if (!triple_is_def(ptr)) {
9748 /* If I still have a valid rhs add it to in */
9749 change |= in_triple(rb, rhs);
9755 static struct reg_block *compute_variable_lifetimes(
9756 struct compile_state *state)
9758 struct reg_block *blocks;
9761 sizeof(*blocks)*(state->last_vertex + 1), "reg_block");
9762 initialize_regblock(blocks, state->last_block, 0);
9766 for(i = 1; i <= state->last_vertex; i++) {
9767 struct reg_block *rb;
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);
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);
9778 /* Add use to in... */
9779 change |= use_in(state, rb);
9785 static void free_variable_lifetimes(
9786 struct compile_state *state, struct reg_block *blocks)
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;
9794 for(entry = rb->in; entry ; entry = next) {
9796 do_triple_unset(&rb->in, entry->member);
9798 for(entry = rb->out; entry; entry = next) {
9800 do_triple_unset(&rb->out, entry->member);
9807 typedef 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);
9812 static void walk_variable_lifetimes(struct compile_state *state,
9813 struct reg_block *blocks, wvl_cb_t cb, void *arg)
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;
9825 /* Get the blocks */
9829 /* Copy out into live */
9831 for(entry = rb->out; entry; entry = next) {
9833 do_triple_set(&live, entry->member, entry->new);
9835 /* Walk through the basic block calculating live */
9836 for(done = 0, ptr = block->last; !done; ptr = prev) {
9837 struct triple **expr;
9840 done = (ptr == block->first);
9842 /* Remove the current definition from live */
9843 do_triple_unset(&live, ptr);
9845 /* If the current instruction was deleted continue */
9846 if (!cb(state, blocks, live, rb, ptr, arg)) {
9847 if (block->last == ptr) {
9853 /* Add the current uses to live.
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.
9860 if (ptr->op == OP_PHI) {
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)) {
9869 do_triple_set(&live, *expr, 0);
9874 for(entry = live; entry; entry = next) {
9876 do_triple_unset(&live, entry->member);
9881 static int count_triples(struct compile_state *state)
9883 struct triple *first, *ins;
9885 first = state->main_function->left;
9890 } while (ins != first);
9893 struct dead_triple {
9894 struct triple *triple;
9895 struct dead_triple *work_next;
9896 struct block *block;
9899 #define TRIPLE_FLAG_ALIVE 1
9904 struct compile_state *state,
9905 struct dead_triple *dtriple, struct triple **expr,
9906 struct dead_triple ***work_list_tail)
9908 struct triple *triple;
9909 struct dead_triple *dt;
9917 if (triple->id <= 0) {
9918 internal_error(state, triple, "bad triple id: %d",
9921 if (triple->op == OP_NOOP) {
9922 internal_warning(state, triple, "awakening noop?");
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;
9935 static void eliminate_inefectual_code(struct compile_state *state)
9937 struct block *block;
9938 struct dead_triple *dtriple, *work_list, **work_list_tail, *dt;
9940 struct triple *first, *ins;
9942 /* Setup the work list */
9944 work_list_tail = &work_list;
9946 first = state->main_function->left;
9948 /* Count how many triples I have */
9949 triples = count_triples(state);
9951 /* Now put then in an array and mark all of the triples dead */
9952 dtriple = xcmalloc(sizeof(*dtriple) * (triples + 1), "dtriples");
9958 if (ins->op == OP_LABEL) {
9959 block = ins->u.block;
9961 dtriple[i].triple = ins;
9962 dtriple[i].block = block;
9963 dtriple[i].flags = 0;
9964 dtriple[i].color = ins->id;
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);
9973 } while(ins != first);
9975 struct dead_triple *dt;
9976 struct block_set *user;
9977 struct triple **expr;
9979 work_list = dt->work_next;
9981 work_list_tail = &work_list;
9983 /* Wake up the data depencencies of this triple */
9986 expr = triple_rhs(state, dt->triple, expr);
9987 awaken(state, dtriple, expr, &work_list_tail);
9990 expr = triple_lhs(state, dt->triple, expr);
9991 awaken(state, dtriple, expr, &work_list_tail);
9993 /* Wake up the forward control dependencies */
9995 expr = triple_targ(state, dt->triple, expr);
9996 awaken(state, dtriple, expr, &work_list_tail);
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);
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?");
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) {
10014 if (dt->block->last == dt->triple) {
10015 dt->block->last = dt->triple->prev;
10017 release_triple(state, dt->triple);
10024 struct live_range_edge;
10025 struct live_range {
10026 struct live_range_edge *edges;
10027 struct triple *def;
10031 struct live_range *group_next, **group_prev;
10034 struct live_range_edge {
10035 struct live_range_edge *next;
10036 struct live_range *node;
10039 #define LRE_HASH_SIZE 2048
10041 struct lre_hash *next;
10042 struct live_range *left;
10043 struct live_range *right;
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;
10057 static unsigned regc_max_size(struct compile_state *state, int classes)
10062 for(i = 0; i < MAX_REGC; i++) {
10063 if (classes & (1 << i)) {
10065 size = arch_regc_size(state, i);
10066 if (size > max_size) {
10074 static int reg_is_reg(struct compile_state *state, int reg1, int reg2)
10076 unsigned equivs[MAX_REG_EQUIVS];
10078 if ((reg1 < 0) || (reg1 >= MAX_REGISTERS)) {
10079 internal_error(state, 0, "invalid register");
10081 if ((reg2 < 0) || (reg2 >= MAX_REGISTERS)) {
10082 internal_error(state, 0, "invalid register");
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) {
10093 static void reg_fill_used(struct compile_state *state, char *used, int reg)
10095 unsigned equivs[MAX_REG_EQUIVS];
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;
10104 static unsigned int hash_live_edge(
10105 struct live_range *left, struct live_range *right)
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);
10115 hash = (hash *263) + val;
10120 hash = (hash *263) + val;
10122 hash = hash & (LRE_HASH_SIZE - 1);
10126 static struct lre_hash **lre_probe(struct reg_state *rstate,
10127 struct live_range *left, struct live_range *right)
10129 struct lre_hash **ptr;
10130 unsigned int index;
10131 /* Ensure left <= right */
10132 if (left > right) {
10133 struct live_range *tmp;
10138 index = hash_live_edge(left, right);
10140 ptr = &rstate->hash[index];
10141 while((*ptr) && ((*ptr)->left != left) && ((*ptr)->right != right)) {
10142 ptr = &(*ptr)->next;
10147 static int interfere(struct reg_state *rstate,
10148 struct live_range *left, struct live_range *right)
10150 struct lre_hash **ptr;
10151 ptr = lre_probe(rstate, left, right);
10152 return ptr && *ptr;
10155 static void add_live_edge(struct reg_state *rstate,
10156 struct live_range *left, struct live_range *right)
10158 /* FIXME the memory allocation overhead is noticeable here... */
10159 struct lre_hash **ptr, *new_hash;
10160 struct live_range_edge *edge;
10162 if (left == right) {
10165 if ((left == &rstate->lr[0]) || (right == &rstate->lr[0])) {
10168 /* Ensure left <= right */
10169 if (left > right) {
10170 struct live_range *tmp;
10175 ptr = lre_probe(rstate, left, right);
10179 new_hash = xmalloc(sizeof(*new_hash), "lre_hash");
10180 new_hash->next = *ptr;
10181 new_hash->left = left;
10182 new_hash->right = right;
10185 edge = xmalloc(sizeof(*edge), "live_range_edge");
10186 edge->next = left->edges;
10187 edge->node = right;
10188 left->edges = edge;
10191 edge = xmalloc(sizeof(*edge), "live_range_edge");
10192 edge->next = right->edges;
10194 right->edges = edge;
10195 right->degree += 1;
10198 static void remove_live_edge(struct reg_state *rstate,
10199 struct live_range *left, struct live_range *right)
10201 struct live_range_edge *edge, **ptr;
10202 struct lre_hash **hptr, *entry;
10203 hptr = lre_probe(rstate, left, right);
10204 if (!hptr || !*hptr) {
10208 *hptr = entry->next;
10211 for(ptr = &left->edges; *ptr; ptr = &(*ptr)->next) {
10213 if (edge->node == right) {
10215 memset(edge, 0, sizeof(*edge));
10220 for(ptr = &right->edges; *ptr; ptr = &(*ptr)->next) {
10222 if (edge->node == left) {
10224 memset(edge, 0, sizeof(*edge));
10231 static void remove_live_edges(struct reg_state *rstate, struct live_range *range)
10233 struct live_range_edge *edge, *next;
10234 for(edge = range->edges; edge; edge = next) {
10236 remove_live_edge(rstate, range, edge->node);
10241 /* Interference graph...
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
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.
10256 * +---------------------------------------------------+
10257 * | +--------------+ |
10259 * renumber -> build graph -> colalesce -> spill_costs -> simplify -> select
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.
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.
10273 static void different_colored(
10274 struct compile_state *state, struct reg_state *rstate,
10275 struct triple *parent, struct triple *ins)
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)) {
10286 lr2 = &rstate->lr[(*expr)->id];
10287 if (lr->color == lr2->color) {
10288 internal_error(state, ins, "live range too big");
10293 static void initialize_live_ranges(
10294 struct compile_state *state, struct reg_state *rstate)
10296 struct triple *ins, *first;
10300 first = state->main_function->left;
10301 /* First count how many live ranges I will need.
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;
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);
10321 /* If the triple is a variable definition give it a live range. */
10322 if (triple_is_def(ins)) {
10325 rstate->lr[i].def = ins;
10326 rstate->lr[i].color = color;
10327 rstate->lr[i].classes = classes;
10328 rstate->lr[i].degree = 0;
10330 internal_error(state, ins,
10331 "live range without a class");
10334 /* Otherwise give the triple the dummy live range. */
10339 } while(ins != first);
10340 rstate->ranges = i;
10341 /* Make a second pass to handle achitecture specific register
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.
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) {
10359 lr2 = &rstate->lr[(*expr)->id];
10360 if (lr->color == lr2->color) {
10361 different_colored(state, rstate,
10363 (*expr)->id = ins->id;
10369 } while(ins != first);
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;
10379 static 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)
10384 struct reg_state *rstate = arg;
10385 struct live_range *def;
10386 struct triple_reg_set *entry;
10388 /* If the triple does not start a live range
10389 * we do not have a definition to add to
10390 * the interference graph.
10392 if (ins->id <= 0) {
10395 def = &rstate->lr[ins->id];
10397 /* Create an edge between ins and everything that is
10398 * alive, unless the live_range cannot share
10399 * a physical register with ins.
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)) {
10407 add_live_edge(rstate, def, lr);
10413 static 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)
10418 struct reg_state *rstate = arg;
10419 struct live_range *lr;
10421 lr = &rstate->lr[ins->id];
10422 if ((ins->op == OP_LABEL) && (ins->use)) {
10423 printf("\n%p:\n", ins);
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);
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);
10436 struct triple_reg_set *entry;
10438 for(entry = live; entry; entry = entry->next) {
10439 printf(" %-10p", entry->member);
10444 struct live_range_edge *entry;
10446 for(entry = lr->edges; entry; entry = entry->next) {
10447 printf(" %-10p", entry->node->def);
10451 if (triple_is_branch(ins)) {
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)
10464 #define cgdebug_printf(...)
10465 #define cgdebug_flush()
10468 static void select_free_color(struct compile_state *state,
10469 struct reg_state *rstate, struct live_range *range)
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;
10477 /* If a color is already assigned don't change it */
10478 if (range->color != REG_UNSET) {
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
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) {
10492 reg_fill_used(state, used, edge->node->color);
10494 #if DEBUG_COLOR_GRAPH > 1
10498 for(edge = range->edges; edge; edge = edge->next) {
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++) {
10506 cgdebug_printf("used: %s\n",
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.
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) {
10525 if (!phi && (lr->def->op == OP_PHI) &&
10526 !interfere(rstate, range, lr)) {
10529 if ((lr->color == REG_UNSET) ||
10530 ((lr->classes & range->classes) == 0) ||
10531 (used[lr->color])) {
10534 if (interfere(rstate, range, lr)) {
10537 range->color = lr->color;
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.
10543 if (phi->color != REG_UNSET) {
10544 if (used[phi->color]) {
10545 range->color = phi->color;
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])) {
10558 if (interfere(rstate, range, lr)) {
10561 range->color = lr->color;
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])) {
10576 if (interfere(rstate, range, lr)) {
10579 range->color = lr->color;
10583 /* If I have not opportunitically picked a useful color
10584 * pick the first color that is free.
10586 if (range->color == REG_UNSET) {
10588 arch_select_free_register(state, used, range->classes);
10590 if (range->color == REG_UNSET) {
10592 for(edge = range->edges; edge; edge = edge->next) {
10593 if (edge->node->color == REG_UNSET) {
10596 warning(state, edge->node->def, "reg %s",
10597 arch_reg_str(edge->node->color));
10599 warning(state, range->def, "classes: %x",
10601 for(i = 0; i < MAX_REGISTERS; i++) {
10603 warning(state, range->def, "used: %s",
10607 #if DEBUG_COLOR_GRAPH < 2
10608 error(state, range->def, "too few registers");
10610 internal_error(state, range->def, "too few registers");
10613 range->classes = arch_reg_regcm(state, range->color);
10617 static void color_graph(struct compile_state *state, struct reg_state *rstate)
10619 struct live_range_edge *edge;
10620 struct live_range *range;
10622 cgdebug_printf("Lo: ");
10623 range = rstate->low;
10624 if (*range->group_prev != range) {
10625 internal_error(state, 0, "lo: *prev != range?");
10627 *range->group_prev = range->group_next;
10628 if (range->group_next) {
10629 range->group_next->group_prev = range->group_prev;
10631 if (&range->group_next == rstate->low_tail) {
10632 rstate->low_tail = range->group_prev;
10634 if (rstate->low == range) {
10635 internal_error(state, 0, "low: next != prev?");
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?");
10644 *range->group_prev = range->group_next;
10645 if (range->group_next) {
10646 range->group_next->group_prev = range->group_prev;
10648 if (&range->group_next == rstate->high_tail) {
10649 rstate->high_tail = range->group_prev;
10651 if (rstate->high == range) {
10652 internal_error(state, 0, "high: next != prev?");
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;
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?");
10669 *node->group_prev = node->group_next;
10670 if (node->group_next) {
10671 node->group_next->group_prev = node->group_prev;
10673 if (&node->group_next == rstate->high_tail) {
10674 rstate->high_tail = node->group_prev;
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?");
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);
10692 select_free_color(state, rstate, range);
10693 if (range->color == -1) {
10694 internal_error(state, range->def, "select_free_color did not?");
10696 cgdebug_printf(" %s\n", arch_reg_str(range->color));
10699 static void color_triples(struct compile_state *state, struct reg_state *rstate)
10701 struct live_range *lr;
10702 struct triple *first, *triple;
10703 first = state->main_function->left;
10706 if ((triple->id < 0) || (triple->id > rstate->ranges)) {
10707 internal_error(state, triple,
10708 "triple without a live range");
10710 lr = &rstate->lr[triple->id];
10711 triple->id = MK_REG_ID(lr->color, 0);
10712 triple = triple->next;
10713 } while (triple != first);
10716 static void print_interference_block(
10717 struct compile_state *state, struct block *block, void *arg)
10720 struct reg_state *rstate = arg;
10721 struct reg_block *rb;
10722 struct triple *ptr;
10725 rb = &rstate->blocks[block->vertex];
10727 printf("\nblock: %p (%d), %p<-%p %p<-%p\n",
10731 block->left && block->left->use?block->left->use->member : 0,
10733 block->right && block->right->use?block->right->use->member : 0);
10735 struct triple_reg_set *in_set;
10737 for(in_set = rb->in; in_set; in_set = in_set->next) {
10738 printf(" %-10p", in_set->member);
10743 for(done = 0, ptr = block->first; !done; ptr = ptr->next) {
10744 done = (ptr == block->last);
10745 if (ptr->op == OP_PHI) {
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) {
10760 slot = (struct triple **)(ptr->left);
10761 printf(" %-10p", slot[edge]);
10766 if (block->first->op == OP_LABEL) {
10767 printf("%p:\n", block->first);
10769 for(done = 0, ptr = block->first; !done; ptr = ptr->next) {
10770 struct triple_set *user;
10771 struct live_range *lr;
10774 done = (ptr == block->last);
10775 lr = &rstate->lr[ptr->id];
10777 if (!IS_CONST_OP(op)) {
10778 if (ptr->u.block != block) {
10779 internal_error(state, ptr,
10780 "Wrong block pointer: %p",
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?",
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);
10801 else if (op == OP_PHI) {
10802 struct triple **slot;
10803 struct block *block;
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]);
10812 printf(" @%s:%d.%d\n",
10813 ptr->filename, ptr->line, ptr->col);
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);
10820 if (lr->edges > 0) {
10821 struct live_range_edge *edge;
10823 for(edge = lr->edges; edge; edge = edge->next) {
10824 printf(" %-10p", edge->node->def);
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",
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",
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?",
10853 struct triple_reg_set *out_set;
10855 for(out_set = rb->out; out_set; out_set = out_set->next) {
10856 printf(" %-10p", out_set->member);
10863 static struct live_range *merge_sort_lr(
10864 struct live_range *first, struct live_range *last)
10866 struct live_range *mid, *join, **join_tail, *pick;
10868 size = (last - first) + 1;
10870 mid = first + size/2;
10871 first = merge_sort_lr(first, mid -1);
10872 mid = merge_sort_lr(mid, last);
10876 /* merge the two lists */
10877 while(first && mid) {
10878 if (first->degree <= mid->degree) {
10880 first = first->group_next;
10882 first->group_prev = 0;
10887 mid = mid->group_next;
10889 mid->group_prev = 0;
10892 pick->group_next = 0;
10893 pick->group_prev = join_tail;
10895 join_tail = &pick->group_next;
10897 /* Splice the remaining list */
10898 pick = (first)? first : mid;
10900 pick->group_prev = join_tail;
10911 static void allocate_registers(struct compile_state *state)
10913 struct reg_state rstate;
10914 struct live_range **point, **next;
10917 /* Clear out the reg_state */
10918 memset(&rstate, 0, sizeof(rstate));
10920 /* Compute the variable lifetimes */
10921 rstate.blocks = compute_variable_lifetimes(state);
10923 /* Allocate and initialize the live ranges */
10924 initialize_live_ranges(state, &rstate);
10926 /* Compute the interference graph */
10927 walk_variable_lifetimes(
10928 state, rstate.blocks, graph_ins, &rstate);
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);
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.
10944 * It might be worth testing this reducing the number of
10945 * live_ragnes as opposed to splitting them seems to help.
10948 /* Build the groups low and high. But with the nodes
10949 * first sorted by degree order.
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)
10957 rstate.high_tail = point;
10958 /* Walk through the high list and move everything that needs
10961 for(point = &rstate.high; *point; point = next) {
10962 struct live_range *range;
10963 next = &(*point)->group_next;
10966 /* If it has a low degree or it already has a color
10967 * place the node in low.
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;
10978 if (&range->group_next == rstate.high_tail) {
10979 rstate.high_tail = range->group_prev;
10981 range->group_prev = rstate.low_tail;
10982 range->group_next = 0;
10983 *rstate.low_tail = range;
10984 rstate.low_tail = &range->group_next;
10988 cgdebug_printf("hi: %5d degree %5d%s\n",
10989 range - rstate.lr, range->degree,
10990 (range->color != REG_UNSET) ? " (colored)": "");
10994 /* Color the live_ranges */
10995 color_graph(state, &rstate);
10997 /* Move the colors from the graph to the triples */
10998 color_triples(state, &rstate);
11000 /* Free the edges on each node */
11001 for(i = 1; i <= rstate.ranges; i++) {
11002 remove_live_edges(&rstate, &rstate.lr[i]);
11006 /* Free the variable lifetime information */
11007 free_variable_lifetimes(state, rstate.blocks);
11011 /* Sparce Conditional Constant Propogation
11012 * =========================================
11016 struct 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
11025 struct triple scratch;
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;
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;
11043 struct flow_block {
11044 struct block *block;
11045 struct flow_edge *in;
11046 struct flow_edge *out;
11047 struct flow_edge left, right;
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;
11059 static void scc_add_fedge(struct compile_state *state, struct scc_state *scc,
11060 struct flow_edge *fedge)
11062 if (!scc->flow_work_list) {
11063 scc->flow_work_list = fedge;
11064 fedge->work_next = fedge->work_prev = fedge;
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;
11076 static struct flow_edge *scc_next_fedge(
11077 struct compile_state *state, struct scc_state *scc)
11079 struct flow_edge *fedge;
11080 fedge = scc->flow_work_list;
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;
11087 scc->flow_work_list = 0;
11093 static void scc_add_sedge(struct compile_state *state, struct scc_state *scc,
11094 struct ssa_edge *sedge)
11096 if (!scc->ssa_work_list) {
11097 scc->ssa_work_list = sedge;
11098 sedge->work_next = sedge->work_prev = sedge;
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;
11110 static struct ssa_edge *scc_next_sedge(
11111 struct compile_state *state, struct scc_state *scc)
11113 struct ssa_edge *sedge;
11114 sedge = scc->ssa_work_list;
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;
11121 scc->ssa_work_list = 0;
11127 static void initialize_scc_state(
11128 struct compile_state *state, struct scc_state *scc)
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;
11136 memset(scc, 0, sizeof(*scc));
11138 /* Inialize pass zero find out how much memory we need */
11139 first = state->main_function->left;
11141 ins_count = ssa_edge_count = 0;
11143 struct triple_set *edge;
11145 for(edge = ins->use; edge; edge = edge->next) {
11149 } while(ins != first);
11151 fprintf(stderr, "ins_count: %d ssa_edge_count: %d vertex_count: %d\n",
11152 ins_count, ssa_edge_count, state->last_vertex);
11155 xcmalloc(sizeof(*scc->lattice)*(ins_count + 1), "lattice");
11157 xcmalloc(sizeof(*scc->ssa_edges)*(ssa_edge_count + 1), "ssa_edges");
11159 xcmalloc(sizeof(*scc->flow_blocks)*(state->last_vertex + 1),
11162 /* Initialize pass one collect up the nodes */
11165 ins_index = ssa_edge_index = fblock_index = 0;
11169 if ((ins->op == OP_LABEL) && (block != ins->u.block)) {
11170 block = ins->u.block;
11172 internal_error(state, ins, "label without block");
11175 block->vertex = fblock_index;
11176 fblock = &scc->flow_blocks[fblock_index];
11177 fblock->block = block;
11180 struct lattice_node *lnode;
11182 ins->id = ins_index;
11183 lnode = &scc->lattice[ins_index];
11186 lnode->fblock = fblock;
11187 lnode->val = ins; /* LATTICE HIGH */
11190 } while(ins != first);
11191 /* Initialize pass two collect up the edges */
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];
11203 ftail = &fblock->out;
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");
11209 fblock->left.out_next = 0;
11210 *ftail = &fblock->left;
11211 ftail = &fblock->left.out_next;
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");
11218 fblock->right.out_next = 0;
11219 *ftail = &fblock->right;
11220 ftail = &fblock->right.out_next;
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;
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];
11235 if (src_block->left == block) {
11236 sfedge = &sfblock->left;
11238 sfedge = &sfblock->right;
11241 ftail = &sfedge->in_next;
11242 sfedge->in_next = 0;
11246 struct triple_set *edge;
11247 struct ssa_edge **stail;
11248 struct lattice_node *lnode;
11249 lnode = &scc->lattice[ins->id];
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];
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;
11265 } while(ins != first);
11266 /* Setup a dummy block 0 as a node above the start node */
11268 struct flow_block *fblock, *dst;
11269 struct flow_edge *fedge;
11270 fblock = &scc->flow_blocks[0];
11273 fblock->out = &fblock->left;
11274 dst = &scc->flow_blocks[state->first_block->vertex];
11275 fedge = &fblock->left;
11276 fedge->src = fblock;
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;
11285 /* Initialize the work lists */
11286 scc->flow_work_list = 0;
11287 scc->ssa_work_list = 0;
11288 scc_add_fedge(state, scc, fedge);
11291 fprintf(stderr, "ins_index: %d ssa_edge_index: %d fblock_index: %d\n",
11292 ins_index, ssa_edge_index, fblock_index);
11297 static void free_scc_state(
11298 struct compile_state *state, struct scc_state *scc)
11300 xfree(scc->flow_blocks);
11301 xfree(scc->ssa_edges);
11302 xfree(scc->lattice);
11305 static struct lattice_node *triple_to_lattice(
11306 struct compile_state *state, struct scc_state *scc, struct triple *ins)
11308 if (ins->id <= 0) {
11309 internal_error(state, ins, "bad id");
11311 return &scc->lattice[ins->id];
11314 static void scc_visit_phi(struct compile_state *state, struct scc_state *scc,
11315 struct lattice_node *lnode)
11317 struct lattice_node *tmp;
11318 struct triple **slot;
11319 struct flow_edge *fedge;
11321 if (lnode->def->op != OP_PHI) {
11322 internal_error(state, lnode->def, "not phi");
11324 /* default to lattice high */
11325 lnode->val = lnode->def;
11326 slot = (struct triple **)lnode->def->left;
11328 for(fedge = lnode->fblock->in; fedge; index++, fedge = fedge->in_next) {
11329 if (!fedge->executable) {
11332 if (!slot[index]) {
11333 internal_error(state, lnode->def, "no phi value");
11335 tmp = triple_to_lattice(state, scc, slot[index]);
11336 /* meet(X, lattice low) = lattice low */
11340 /* meet(X, lattice high) = X */
11341 else if (!tmp->val) {
11342 lnode->val = lnode->val;
11344 /* meet(lattice high, X) = X */
11345 else if (!is_const(lnode->val)) {
11346 lnode->val = tmp->val;
11348 /* meet(const, const) = const or lattice low */
11349 else if (!constants_equal(state, lnode->val, tmp->val)) {
11356 /* Do I need to update any work lists here? */
11358 fprintf(stderr, "phi: %d -> %s\n",
11360 (!lnode->val)? "lo": is_const(lnode->val)? "const": "hi");
11364 static int compute_lnode_val(struct compile_state *state, struct scc_state *scc,
11365 struct lattice_node *lnode)
11368 struct triple old_buf, *old;
11369 struct triple **dexpr, **vexpr;
11371 /* Store the original value */
11374 memcpy(old, lnode->val, sizeof(*old));
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);
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);
11403 if (is_const(lnode->val)) {
11404 memcpy(&lnode->val->u, &lnode->def->u, sizeof(lnode->def->u));
11406 else if (lnode->val->op == OP_BRANCH) {
11407 lnode->val->left = lnode->def->left;
11408 lnode->val->next = lnode->def->next;
11410 else if (lnode->val->op == OP_SDECL) {
11411 lnode->val->left = lnode->def->left;
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.
11418 simplify(state, lnode->val);
11419 /* Cleanup my value */
11420 if (lnode->scratch.use) {
11421 internal_error(state, lnode->def, "scratch used?");
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?");
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);
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);
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;
11452 /* Find the cases that are always lattice lo */
11454 triple_is_def(lnode->val) &&
11455 !triple_is_pure(state, lnode->val)) {
11460 (lnode->val->op == OP_SDECL) &&
11461 (lnode->val != lnode->def)) {
11462 internal_error(state, lnode->def, "bad sdecl");
11465 /* See if the lattice value has changed */
11467 if (!old && !lnode->val) {
11470 if (changed && lnode->val && !is_const(lnode->val)) {
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)) {
11484 static void scc_visit_branch(struct compile_state *state, struct scc_state *scc,
11485 struct lattice_node *lnode)
11487 struct lattice_node *cond;
11490 struct flow_edge *fedge;
11491 fprintf(stderr, "branch: %d (",
11494 for(fedge = lnode->fblock->out; fedge; fedge = fedge->out_next) {
11495 fprintf(stderr, " %d", fedge->dst->block->vertex);
11497 fprintf(stderr, " )");
11498 if (lnode->def->right) {
11499 fprintf(stderr, " <- %d",
11500 lnode->def->right->id);
11502 fprintf(stderr, "\n");
11505 if (lnode->def->op != OP_BRANCH) {
11506 internal_error(state, lnode->def, "not branch");
11508 /* This only applies to conditional branches */
11509 if (lnode->def->right == 0) {
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?");
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);
11522 else if (cond->val->u.cval) {
11523 scc_add_fedge(state, scc, cond->fblock->out->out_next);
11526 scc_add_fedge(state, scc, cond->fblock->out);
11531 static void scc_visit_expr(struct compile_state *state, struct scc_state *scc,
11532 struct lattice_node *lnode)
11536 changed = compute_lnode_val(state, scc, lnode);
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);
11546 fprintf(stderr, " ) -> %s\n",
11547 (!lnode->val)? "lo": is_const(lnode->val)? "const": "hi");
11550 if (lnode->def->op == OP_BRANCH) {
11551 scc_visit_branch(state, scc, lnode);
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);
11562 static void scc_writeback_values(
11563 struct compile_state *state, struct scc_state *scc)
11565 struct triple *first, *ins;
11566 first = state->main_function->left;
11569 struct lattice_node *lnode;
11570 lnode = triple_to_lattice(state, scc, ins);
11572 if (lnode->val && !is_const(lnode->val)) {
11573 warning(state, lnode->def,
11574 "lattice node still high?");
11577 if (lnode->val && (lnode->val != ins)) {
11578 /* See if it something I know how to write back */
11579 switch(lnode->val->op) {
11581 mkconst(state, ins, lnode->val->u.cval);
11584 mkaddr_const(state, ins,
11585 lnode->val->left, lnode->val->u.cval);
11588 /* By default don't copy the changes,
11589 * recompute them in place instead.
11591 simplify(state, ins);
11596 } while(ins != first);
11599 static void scc_transform(struct compile_state *state)
11601 struct scc_state scc;
11603 initialize_scc_state(state, &scc);
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;
11615 if (fedge->executable) {
11619 internal_error(state, 0, "fedge without dst");
11622 internal_error(state, 0, "fedge without src");
11624 fedge->executable = 1;
11625 fblock = fedge->dst;
11626 block = fblock->block;
11628 for(fptr = fblock->in; fptr; fptr = fptr->in_next) {
11629 if (fptr->executable) {
11634 fprintf(stderr, "vertex: %d time: %d\n",
11635 block->vertex, time);
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);
11646 else if (time == 1) {
11647 scc_visit_expr(state, &scc, lnode);
11650 if (fblock->out && !fblock->out->out_next) {
11651 scc_add_fedge(state, &scc, fblock->out);
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;
11660 fprintf(stderr, "sedge: %5d (%5d -> %5d)\n",
11661 sedge - scc.ssa_edges,
11662 sedge->src->def->id,
11663 sedge->dst->def->id);
11665 if (lnode->def->op == OP_PHI) {
11666 scc_visit_phi(state, &scc, lnode);
11669 for(fptr = fblock->in; fptr; fptr = fptr->in_next) {
11670 if (fptr->executable) {
11675 scc_visit_expr(state, &scc, lnode);
11681 scc_writeback_values(state, &scc);
11682 /* FINISH ME move constants from scratch values into the tree */
11683 free_scc_state(state, &scc);
11687 static void transform_to_arch_instructions(struct compile_state *state);
11690 static void optimize(struct compile_state *state)
11692 if (state->debug & DEBUG_TRIPLES) {
11693 print_triples(state);
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);
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);
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.
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);
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);
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);
11740 if (state->debug & DEBUG_CONTROL_FLOW) {
11741 print_control_flow(state);
11743 /* Remove the optimization information.
11744 * This is more to check for memory consistency than to free memory.
11746 free_basic_blocks(state);
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
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"
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)
11775 /* The x86 registers */
11776 #define REG_EFLAGS 1
11777 #define REGC_FLAGS_FIRST REG_EFLAGS
11778 #define REGC_FLAGS_LAST REG_EFLAGS
11787 #define REGC_GPR8_FIRST REG_AL
11788 #if X86_4_8BIT_GPRS
11789 #define REGC_GPR8_LAST REG_DL
11791 #define REGC_GPR8_LAST REG_DH
11801 #define REGC_GPR16_FIRST REG_AX
11802 #define REGC_GPR16_LAST REG_SP
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
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
11844 #if LAST_REG >= MAX_REGISTERS
11845 #error "MAX_REGISTERS to low"
11848 static unsigned arch_regc_size(struct compile_state *state, int class)
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,
11861 if ((class < 0) || (class > LAST_REGC)) {
11864 return regc_size[class];
11866 static int arch_regcm_intersect(unsigned regcm1, unsigned regcm2)
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;
11872 return (regcm1 & regcm2) ||
11873 ((regcm1 & gpr_mask) && (regcm2 & gpr_mask));
11876 static void arch_reg_equivs(
11877 struct compile_state *state, unsigned *equiv, int reg)
11879 if ((reg < 0) || (reg > LAST_REG)) {
11880 internal_error(state, 0, "invalid register");
11887 *equiv++ = REG_EAX;
11888 *equiv++ = REG_EDXEAX;
11893 *equiv++ = REG_EBX;
11898 *equiv++ = REG_ECX;
11903 *equiv++ = REG_EDX;
11904 *equiv++ = REG_EDXEAX;
11909 *equiv++ = REG_EAX;
11910 *equiv++ = REG_EDXEAX;
11915 *equiv++ = REG_EBX;
11920 *equiv++ = REG_ECX;
11925 *equiv++ = REG_EDX;
11926 *equiv++ = REG_EDXEAX;
11929 *equiv++ = REG_ESI;
11932 *equiv++ = REG_EDI;
11935 *equiv++ = REG_EBP;
11938 *equiv++ = REG_ESP;
11944 *equiv++ = REG_EDXEAX;
11960 *equiv++ = REG_EDXEAX;
11981 *equiv++ = REG_EAX;
11982 *equiv++ = REG_EDX;
11985 *equiv++ = REG_UNSET;
11989 static unsigned arch_reg_regcm(struct compile_state *state, int reg)
11991 static const struct {
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 },
12007 for(class = 0; class <= LAST_REGC; class++) {
12008 if ((reg >= bound[class].first) &&
12009 (reg <= bound[class].last)) {
12010 mask |= (1 << class);
12014 internal_error(state, 0, "reg %d not in any class", reg);
12019 static int do_select_reg(struct compile_state *state,
12020 char *used, int reg, unsigned classes)
12026 mask = arch_reg_regcm(state, reg);
12027 return (classes & mask) ? reg : REG_UNSET;
12030 static int arch_select_free_register(
12031 struct compile_state *state, char *used, int classes)
12033 /* Preference: flags, 8bit gprs, 32bit gprs, other 32bit reg
12034 * other types of registers.
12038 for(i = REGC_FLAGS_FIRST; (reg == REG_UNSET) && (i <= REGC_FLAGS_LAST); i++) {
12039 reg = do_select_reg(state, used, i, classes);
12041 for(i = REGC_GPR8_FIRST; (reg == REG_UNSET) && (i <= REGC_GPR8_LAST); i++) {
12042 reg = do_select_reg(state, used, i, classes);
12044 for(i = REGC_GPR32_FIRST; (reg == REG_UNSET) && (i <= REGC_GPR32_LAST); i++) {
12045 reg = do_select_reg(state, used, i, classes);
12047 for(i = REGC_MMX_FIRST; (reg == REG_UNSET) && (i <= REGC_MMX_LAST); i++) {
12048 reg = do_select_reg(state, used, i, classes);
12050 for(i = REGC_XMM_FIRST; (reg == REG_UNSET) && (i <= REGC_XMM_LAST); i++) {
12051 reg = do_select_reg(state, used, i, classes);
12053 for(i = REGC_GPR16_FIRST; (reg == REG_UNSET) && (i <= REGC_GPR16_LAST); i++) {
12054 reg = do_select_reg(state, used, i, classes);
12056 for(i = REGC_GPR64_FIRST; (reg == REG_UNSET) && (i <= REGC_GPR64_LAST); i++) {
12057 reg = do_select_reg(state, used, i, classes);
12062 static unsigned arch_type_to_regcm(struct compile_state *state, struct type *type)
12064 #warning "FIXME force types smaller (if legal) before I get here"
12067 unsigned avail_mask;
12069 avail_mask = REGCM_GPR8 | REGCM_GPR16_8 | REGCM_GPR16 |
12070 REGCM_GPR32 | REGCM_GPR32_8 | REGCM_GPR64;
12072 /* Don't enable 8 bit values until I can force both operands
12073 * to be 8bits simultaneously.
12075 avail_mask &= ~(REGCM_GPR8 | REGCM_GPR16_8 | REGCM_GPR16);
12078 avail_mask |= REGCM_MMX;
12081 avail_mask |= REGCM_XMM;
12084 switch(type->type & TYPE_MASK) {
12091 mask = REGCM_GPR8 |
12092 REGCM_GPR16_8 | REGCM_GPR16 |
12093 REGCM_GPR32 | REGCM_GPR32_8 |
12095 REGCM_MMX | REGCM_XMM;
12099 mask = REGCM_GPR16 | REGCM_GPR16_8 |
12100 REGCM_GPR32 | REGCM_GPR32_8 |
12102 REGCM_MMX | REGCM_XMM;
12109 mask = REGCM_GPR32 | REGCM_GPR32_8 |
12110 REGCM_GPR64 | REGCM_MMX | REGCM_XMM;
12113 internal_error(state, 0, "no register class for type");
12116 mask &= avail_mask;
12120 static void get_imm32(struct triple *ins, struct triple **expr)
12122 struct triple *imm;
12123 if ((*expr)->op != OP_COPY) {
12126 imm = (*expr)->left;
12127 while(imm->op == OP_COPY) {
12130 if (imm->op != OP_INTCONST) {
12134 unuse_triple(*expr, ins);
12135 use_triple(*expr, ins);
12138 static void get_imm8(struct triple *ins, struct triple **expr)
12140 struct triple *imm;
12141 if ((*expr)->op != OP_COPY) {
12144 imm = (*expr)->left;
12145 while(imm->op == OP_COPY) {
12148 if (imm->op != OP_INTCONST) {
12151 /* For imm8 only a sufficienlty small constant can be used */
12152 if (imm->u.cval > 0xff) {
12156 unuse_triple(*expr, ins);
12157 use_triple(*expr, ins);
12160 static struct triple *pre_copy(struct compile_state *state,
12161 struct triple *ins, struct triple **expr,
12162 unsigned reg, unsigned mask)
12164 /* Carefully insert enough operations so that I can
12165 * enter any operation with a GPR32.
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);
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);
12184 in = triple(state, OP_COPY, tmp->type, tmp, 0);
12187 internal_error(state, ins, "bad copy type");
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);
12197 use_triple(in->left, in);
12198 use_triple(in, ins);
12199 insert_triple(state, ins, in);
12203 static struct triple *post_copy(struct compile_state *state, struct triple *ins)
12205 struct triple_set *entry, *next;
12206 struct triple *out, *label;
12207 struct block *block;
12209 while(label->op != OP_LABEL) {
12210 label = label->prev;
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) {
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) {
12231 replace_rhs_use(state, ins, out, entry->member);
12236 static void fixup_branches(struct compile_state *state,
12237 struct triple *cmp, struct triple *use, int jmp_op)
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);
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);
12259 static void bool_cmp(struct compile_state *state,
12260 struct triple *ins, int cmp_op, int jmp_op, int set_op)
12262 struct block *block;
12263 struct triple_set *entry, *next;
12264 struct triple *set, *tmp1, *tmp2;
12266 #warning "WISHLIST implement an expression simplifier to reduce the use of set?"
12268 block = ins->u.block;
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.
12275 /* Modify the comparison operator */
12277 ins->id = MK_REG_ID(REG_EFLAGS, REGCM_FLAGS);
12278 if (cmp_op == OP_CMP) {
12279 get_imm32(ins, &ins->right);
12281 /* Generate the instruction sequence that will transform the
12282 * result of the comparison into a logical value.
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);
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);
12303 if (block->last == ins) {
12304 block->last = tmp2;
12308 for(entry = ins->use; entry; entry = next) {
12309 next = entry->next;
12310 if (entry->member == tmp1) {
12313 replace_rhs_use(state, ins, set, entry->member);
12315 fixup_branches(state, ins, set, jmp_op);
12319 static void transform_to_arch_instructions(struct compile_state *state)
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.
12327 struct triple *ins, *first, *next;
12328 struct triple *in, *in2;
12329 first = state->main_function->left;
12333 ins->id = MK_REG_ID(REG_UNSET, arch_type_to_regcm(state, ins->type));
12338 post_copy(state, ins);
12346 /* instructions that can be used as is */
12354 switch(ins->type->type & TYPE_MASK) {
12355 case TYPE_CHAR: case TYPE_UCHAR:
12358 case TYPE_SHORT: case TYPE_USHORT:
12359 mask = REGCM_GPR16;
12361 case TYPE_INT: case TYPE_UINT:
12362 case TYPE_LONG: case TYPE_ULONG:
12364 mask = REGCM_GPR32;
12367 internal_error(state, ins, "unknown type in store");
12371 in = pre_copy(state, ins, &ins->right, REG_UNSET, mask);
12375 switch(ins->type->type & TYPE_MASK) {
12376 case TYPE_CHAR: case TYPE_UCHAR:
12377 ins->id = MK_REG_ID(REG_UNSET, REGCM_GPR8);
12381 ins->id = MK_REG_ID(REG_UNSET, REGCM_GPR16);
12388 ins->id = MK_REG_ID(REG_UNSET, REGCM_GPR32);
12391 internal_error(state, ins, "unknown type in load");
12400 get_imm32(ins, &ins->right);
12401 in = pre_copy(state, ins, &ins->left,
12402 alloc_virtual_reg(), ID_REG_CLASSES(ins->id));
12408 get_imm8(ins, &ins->right);
12409 in = pre_copy(state, ins, &ins->left,
12410 alloc_virtual_reg(), ID_REG_CLASSES(ins->id));
12412 if (!IS_CONST_OP(ins->right->op)) {
12413 in2 = pre_copy(state, ins, &ins->right,
12414 REG_CL, REGCM_GPR8);
12419 in = pre_copy(state, ins, &ins->left,
12420 alloc_virtual_reg(), ID_REG_CLASSES(ins->id));
12424 get_imm32(ins, &ins->right);
12425 in = pre_copy(state, ins, &ins->left,
12426 alloc_virtual_reg(), ID_REG_CLASSES(ins->id));
12428 if (!IS_CONST_OP(ins->right->op)) {
12429 in2 = pre_copy(state, ins, &ins->right,
12430 REG_UNSET, REGCM_GPR32);
12434 bool_cmp(state, ins, OP_CMP, OP_JMP_EQ, OP_SET_EQ);
12437 bool_cmp(state, ins, OP_CMP, OP_JMP_NOTEQ, OP_SET_NOTEQ);
12440 bool_cmp(state, ins, OP_CMP, OP_JMP_SLESS, OP_SET_SLESS);
12443 bool_cmp(state, ins, OP_CMP, OP_JMP_ULESS, OP_SET_ULESS);
12446 bool_cmp(state, ins, OP_CMP, OP_JMP_SMORE, OP_SET_SMORE);
12449 bool_cmp(state, ins, OP_CMP, OP_JMP_UMORE, OP_SET_UMORE);
12452 bool_cmp(state, ins, OP_CMP, OP_JMP_SLESSEQ, OP_SET_SLESSEQ);
12455 bool_cmp(state, ins, OP_CMP, OP_JMP_ULESSEQ, OP_SET_ULESSEQ);
12458 bool_cmp(state, ins, OP_CMP, OP_JMP_SMOREEQ, OP_SET_SMOREEQ);
12461 bool_cmp(state, ins, OP_CMP, OP_JMP_UMOREEQ, OP_SET_UMOREEQ);
12464 bool_cmp(state, ins, OP_TEST, OP_JMP_NOTEQ, OP_SET_NOTEQ);
12467 bool_cmp(state, ins, OP_TEST, OP_JMP_EQ, OP_SET_EQ);
12471 internal_error(state, ins, "bad branch test");
12479 get_imm8(ins, &ins->left);
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;
12485 if (!IS_CONST_OP(ins->left->op)) {
12486 in = pre_copy(state, ins, &ins->left,
12487 REG_DX, REGCM_GPR16);
12494 unsigned reg, mask;
12495 get_imm8(ins, &ins->right);
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;
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);
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);
12515 /* Already transformed instructions */
12518 ins->id = MK_REG_ID(REG_EFLAGS, REGCM_FLAGS);
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:
12532 internal_error(state, ins, "unhandled ins: %d %s\n",
12533 ins->op, tops(ins->op));
12537 } while(ins != first);
12542 static void generate_local_labels(struct compile_state *state)
12544 struct triple *first, *label;
12547 first = state->main_function->left;
12550 if ((label->op == OP_LABEL) ||
12551 (label->op == OP_SDECL)) {
12553 label->u.cval = ++label_counter;
12559 label = label->next;
12560 } while(label != first);
12563 static int check_reg(struct compile_state *state,
12564 struct triple *triple, int classes)
12568 reg = ID_REG(triple->id);
12569 if (reg == REG_UNSET) {
12570 internal_error(state, triple, "register not set");
12572 if (ID_REG_CLASSES(triple->id)) {
12573 internal_error(state, triple, "class specifier present");
12575 mask = arch_reg_regcm(state, reg);
12576 if (!(classes & mask)) {
12577 internal_error(state, triple, "reg %d in wrong class",
12583 static const char *arch_reg_str(int reg)
12585 static const char *regs[] = {
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",
12592 "%mm0", "%mm1", "%mm2", "%mm3", "%mm4", "%mm5", "%mm6", "%mm7",
12593 "%xmm0", "%xmm1", "%xmm2", "%xmm3",
12594 "%xmm4", "%xmm5", "%xmm6", "%xmm7",
12596 if (!((reg >= REG_EFLAGS) && (reg <= REG_XMM7))) {
12602 static const char *reg(struct compile_state *state, struct triple *triple,
12606 reg = check_reg(state, triple, classes);
12607 return arch_reg_str(reg);
12610 const char *type_suffix(struct compile_state *state, struct type *type)
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;
12618 internal_error(state, 0, "unknown suffix");
12625 static void print_binary_op(struct compile_state *state,
12626 const char *op, struct triple *ins, FILE *fp)
12629 mask = REGCM_GPR32 | REGCM_GPR16 | REGCM_GPR8;
12630 if (ins->left->id != ins->id) {
12631 internal_error(state, ins, "invalid register assignment");
12633 if (IS_CONST_OP(ins->right->op)) {
12634 fprintf(fp, "\t%s $%lu, %s\n",
12636 ins->right->u.cval,
12637 reg(state, ins->left, mask));
12641 unsigned lmask, rmask;
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",
12650 reg(state, ins->right, mask),
12651 reg(state, ins->left, mask));
12654 static void print_unary_op(struct compile_state *state,
12655 const char *op, struct triple *ins, FILE *fp)
12658 mask = REGCM_GPR32 | REGCM_GPR16 | REGCM_GPR8;
12659 fprintf(fp, "\t%s %s\n",
12661 reg(state, ins->left, mask));
12664 static void print_op_shift(struct compile_state *state,
12665 const char *op, struct triple *ins, FILE *fp)
12668 mask = REGCM_GPR32 | REGCM_GPR16 | REGCM_GPR8;
12669 if (ins->left->id != ins->id) {
12670 internal_error(state, ins, "invalid register assignment");
12672 if (IS_CONST_OP(ins->right->op)) {
12673 fprintf(fp, "\t%s $%lu, %s\n",
12675 ins->right->u.cval,
12676 reg(state, ins->left, mask));
12680 fprintf(fp, "\t%s %s, %s\n",
12682 reg(state, ins->right, REGCM_GPR8),
12683 reg(state, ins->left, mask));
12687 static void print_op_in(struct compile_state *state, struct triple *ins, FILE *fp)
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;
12698 internal_error(state, ins, "not an in operation");
12702 dreg = check_reg(state, ins, mask);
12703 if (!reg_is_reg(state, dreg, REG_EAX)) {
12704 internal_error(state, ins, "dst != %%eax");
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));
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");
12717 fprintf(fp, "\t%s %s, %s\n",
12719 reg(state, ins->left, REGCM_GPR16),
12720 reg(state, ins, mask));
12724 static void print_op_out(struct compile_state *state, struct triple *ins, FILE *fp)
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;
12735 internal_error(state, ins, "not an out operation");
12739 lreg = check_reg(state, ins->left, mask);
12740 if (!reg_is_reg(state, lreg, REG_EAX)) {
12741 internal_error(state, ins, "src != %%eax");
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);
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");
12754 fprintf(fp, "\t%s %s, %s\n",
12756 reg(state, ins->left, mask),
12757 reg(state, ins->right, REGCM_GPR16));
12761 static void print_op_move(struct compile_state *state,
12762 struct triple *ins, FILE *fp)
12764 /* op_move is complex because there are many types
12765 * of registers we can move between.
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) {
12773 else if (ins->op == OP_WRITE) {
12778 internal_error(state, ins, "unknown move operation");
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));
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));
12807 /* Move 32bit to 8bit */
12808 else if ((src_regcm & REGCM_GPR32_8) &&
12809 (dst_regcm & REGCM_GPR8))
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));
12818 /* Move 16bit to 8bit */
12819 else if ((src_regcm & REGCM_GPR16_8) &&
12820 (dst_regcm & REGCM_GPR8))
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));
12829 /* Move 8/16bit to 16/32bit */
12830 else if ((src_regcm & (REGCM_GPR8 | REGCM_GPR16)) &&
12831 (dst_regcm & (REGC_GPR16 | REGCM_GPR32))) {
12833 op = is_signed(src->type)? "movsx": "movzx";
12834 fprintf(fp, "\t%s %s, %s\n",
12836 reg(state, src, src_regcm),
12837 reg(state, dst, dst_regcm));
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));
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));
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));
12864 internal_error(state, ins, "unknown copy type");
12867 else switch(src->op) {
12871 value = (long_t)(src->u.cval);
12872 fprintf(fp, "\tmov $%ld, %s\n",
12874 reg(state, dst, REGCM_GPR32 | REGCM_GPR16 | REGCM_GPR8));
12878 fprintf(fp, "\tmov $L%lu+%lu, %s\n",
12881 reg(state, dst, REGCM_GPR32));
12884 internal_error(state, ins, "uknown copy operation");
12888 static void print_op_load(struct compile_state *state,
12889 struct triple *ins, FILE *fp)
12891 struct triple *dst, *src;
12894 if (is_const(src) || is_const(dst)) {
12895 internal_error(state, ins, "unknown load operation");
12897 fprintf(fp, "\tmov (%s), %s\n",
12898 reg(state, src, REGCM_GPR32),
12899 reg(state, dst, REGCM_GPR8 | REGCM_GPR16 | REGCM_GPR32));
12903 static void print_op_store(struct compile_state *state,
12904 struct triple *ins, FILE *fp)
12906 struct triple *dst, *src;
12909 if (is_const(src) && (src->op == OP_INTCONST)) {
12911 value = (long_t)(src->u.cval);
12912 fprintf(fp, "\tmov%s $%ld, (%s)\n",
12913 type_suffix(state, src->type),
12915 reg(state, dst, REGCM_GPR32));
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),
12924 if (is_const(src) || is_const(dst)) {
12925 internal_error(state, ins, "unknown store operation");
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));
12936 static void print_op_smul(struct compile_state *state,
12937 struct triple *ins, FILE *fp)
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));
12945 fprintf(fp, "\timul $%ld, %s\n",
12946 ins->right->u.cval,
12947 reg(state, ins->left, REGCM_GPR32));
12951 static void print_op_cmp(struct compile_state *state,
12952 struct triple *ins, FILE *fp)
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");
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));
12967 unsigned lmask, rmask;
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));
12980 static void print_op_test(struct compile_state *state,
12981 struct triple *ins, FILE *fp)
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));
12990 static void print_op_branch(struct compile_state *state,
12991 struct triple *branch, FILE *fp)
12993 const char *bop = "j";
12994 if (branch->op == OP_JMP) {
12995 if (branch->right) {
12996 internal_error(state, branch, "jmp with condition?");
13001 if (!branch->right) {
13002 internal_error(state, branch, "jmpcc without condition?");
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");
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");
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;
13025 internal_error(state, branch, "Invalid branch op");
13030 fprintf(fp, "\t%s L%lu\n",
13031 bop, branch->left->u.cval);
13034 static void print_op_set(struct compile_state *state,
13035 struct triple *set, FILE *fp)
13037 const char *sop = "set";
13039 internal_error(state, set, "setcc without condition?");
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");
13046 if (set->left->next != set) {
13047 internal_error(state, set, "set does not follow test");
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;
13061 internal_error(state, set, "Invalid set op");
13064 fprintf(fp, "\t%s %s\n",
13065 sop, reg(state, set, REGCM_GPR8));
13068 static void print_op_bit_scan(struct compile_state *state,
13069 struct triple *ins, FILE *fp)
13073 case OP_BSF: op = "bsf"; break;
13074 case OP_BSR: op = "bsr"; break;
13076 internal_error(state, ins, "unknown bit scan");
13086 reg(state, ins->left, REGCM_GPR32),
13087 reg(state, ins, REGCM_GPR32),
13088 reg(state, ins, REGCM_GPR32));
13091 static void print_const(struct compile_state *state,
13092 struct triple *ins, FILE *fp)
13096 switch(ins->type->type & TYPE_MASK) {
13099 fprintf(fp, ".byte 0x%02lx\n", ins->u.cval);
13103 fprintf(fp, ".short 0x%04lx\n", ins->u.cval);
13109 fprintf(fp, ".int %lu\n", ins->u.cval);
13112 internal_error(state, ins, "Unknown constant type");
13117 unsigned char *blob;
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",
13129 fprintf(fp, ".int $L%lu+%lu",
13135 internal_error(state, ins, "Unknown constant type");
13140 static void print_sdecl(struct compile_state *state,
13141 struct triple *ins, FILE *fp)
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");
13151 static void print_instruction(struct compile_state *state,
13152 struct triple *ins, FILE *fp)
13154 /* Assumption: after I have exted the register allocator
13155 * everything is in a valid register.
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;
13171 /* Don't generate anything here for constants */
13173 /* Don't generate anything for variable declarations. */
13176 print_sdecl(state, ins, fp);
13180 print_op_move(state, ins, fp);
13183 print_op_load(state, ins, fp);
13186 print_op_store(state, ins, fp);
13189 print_op_smul(state, ins, fp);
13191 case OP_CMP: print_op_cmp(state, ins, fp); break;
13192 case OP_TEST: print_op_test(state, ins, fp); break;
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);
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);
13208 case OP_INB: case OP_INW: case OP_INL:
13209 print_op_in(state, ins, fp);
13211 case OP_OUTB: case OP_OUTW: case OP_OUTL:
13212 print_op_out(state, ins, fp);
13216 print_op_bit_scan(state, ins, fp);
13219 fprintf(fp, "\thlt\n");
13225 fprintf(fp, "L%lu:\n", ins->u.cval);
13227 /* Operations I am not yet certain how to handle */
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:
13236 internal_error(state, ins, "unknown op: %d %s",
13237 ins->op, tops(ins->op));
13242 static void print_instructions(struct compile_state *state)
13244 struct triple *first, *ins;
13245 int print_location;
13248 const char *last_filename;
13250 print_location = 1;
13255 fprintf(fp, ".section \".rom.text\"\n");
13256 first = state->main_function->left;
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;
13270 print_instruction(state, ins, fp);
13272 } while(ins != first);
13275 static void generate_code(struct compile_state *state)
13277 generate_local_labels(state);
13278 print_instructions(state);
13282 static void print_tokens(struct compile_state *state)
13285 tk = &state->token[0];
13290 next_token(state, 0);
13292 loc(stdout, state, 0);
13293 printf("%s <- `%s'\n",
13295 tk->ident ? tk->ident->name :
13296 tk->str_len ? tk->val.str : "");
13298 } while(tk->tok != TOK_EOF);
13301 static void compile(char *filename, int debug, int opt)
13304 struct compile_state state;
13305 memset(&state, 0, sizeof(state));
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;
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);
13329 print_tokens(&state);
13332 /* Exit the global definition scope */
13335 /* Now that basic compilation has happened
13336 * optimize the intermediate code
13339 generate_code(&state);
13341 fprintf(stderr, "done\n");
13345 static void version(void)
13347 printf("romcc " VERSION " released " RELEASE_DATE "\n");
13350 static void usage(void)
13354 "Usage: romcc <source>.c\n"
13355 "Compile a C source file without using ram\n"
13359 static void arg_error(char *fmt, ...)
13362 va_start(args, fmt);
13363 vfprintf(stderr, fmt, args);
13369 int main(int argc, char **argv)
13378 while((argc > 1) && (argc != last_argc)) {
13380 if (strncmp(argv[1], "--debug=", 8) == 0) {
13381 debug = atoi(argv[1] + 8);
13385 else if ((strcmp(argv[1],"-O") == 0) ||
13386 (strcmp(argv[1], "-O1") == 0)) {
13391 else if (strcmp(argv[1],"-O2") == 0) {
13398 arg_error("Wrong argument count %d\n", argc);
13400 filename = argv[1];
13401 compile(filename, debug, optimize);