mb/up/squared: Enable Vtd
[coreboot.git] / util / romcc / romcc.c
blob378bfc50f2900ac20da7a1c82cee3d3a8565ddf2
1 #undef VERSION_MAJOR
2 #undef VERSION_MINOR
3 #undef RELEASE_DATE
4 #undef VERSION
5 #define VERSION_MAJOR "0"
6 #define VERSION_MINOR "80"
7 #define RELEASE_DATE "18 November 2015"
8 #define VERSION VERSION_MAJOR "." VERSION_MINOR
10 #include <stdarg.h>
11 #include <errno.h>
12 #include <stdint.h>
13 #include <stdlib.h>
14 #include <stdio.h>
15 #include <sys/types.h>
16 #include <sys/stat.h>
17 #include <fcntl.h>
18 #include <unistd.h>
19 #include <string.h>
20 #include <limits.h>
21 #include <locale.h>
22 #include <time.h>
24 #define MAX_CWD_SIZE 4096
25 #define MAX_ALLOCATION_PASSES 100
27 /* NOTE: Before you even start thinking to touch anything
28 * in this code, set DEBUG_ROMCC_WARNINGS to 1 to get an
29 * insight on the original author's thoughts. We introduced
30 * this switch as romcc was about the only thing producing
31 * massive warnings in our code..
33 #define DEBUG_ROMCC_WARNINGS 0
35 #define DEBUG_CONSISTENCY 1
36 #define DEBUG_SDP_BLOCKS 0
37 #define DEBUG_TRIPLE_COLOR 0
39 #define DEBUG_DISPLAY_USES 1
40 #define DEBUG_DISPLAY_TYPES 1
41 #define DEBUG_REPLACE_CLOSURE_TYPE_HIRES 0
42 #define DEBUG_DECOMPOSE_PRINT_TUPLES 0
43 #define DEBUG_DECOMPOSE_HIRES 0
44 #define DEBUG_INITIALIZER 0
45 #define DEBUG_UPDATE_CLOSURE_TYPE 0
46 #define DEBUG_LOCAL_TRIPLE 0
47 #define DEBUG_BASIC_BLOCKS_VERBOSE 0
48 #define DEBUG_CPS_RENAME_VARIABLES_HIRES 0
49 #define DEBUG_SIMPLIFY_HIRES 0
50 #define DEBUG_SHRINKING 0
51 #define DEBUG_COALESCE_HITCHES 0
52 #define DEBUG_CODE_ELIMINATION 0
54 #define DEBUG_EXPLICIT_CLOSURES 0
56 #if DEBUG_ROMCC_WARNINGS
57 #warning "FIXME give clear error messages about unused variables"
58 #warning "FIXME properly handle multi dimensional arrays"
59 #warning "FIXME handle multiple register sizes"
60 #endif
62 /* Control flow graph of a loop without goto.
64 * AAA
65 * +---/
66 * /
67 * / +--->CCC
68 * | | / \
69 * | | DDD EEE break;
70 * | | \ \
71 * | | FFF \
72 * \| / \ \
73 * |\ GGG HHH | continue;
74 * | \ \ | |
75 * | \ III | /
76 * | \ | / /
77 * | vvv /
78 * +----BBB /
79 * | /
80 * vv
81 * JJJ
84 * AAA
85 * +-----+ | +----+
86 * | \ | / |
87 * | BBB +-+ |
88 * | / \ / | |
89 * | CCC JJJ / /
90 * | / \ / /
91 * | DDD EEE / /
92 * | | +-/ /
93 * | FFF /
94 * | / \ /
95 * | GGG HHH /
96 * | | +-/
97 * | III
98 * +--+
101 * DFlocal(X) = { Y <- Succ(X) | idom(Y) != X }
102 * DFup(Z) = { Y <- DF(Z) | idom(Y) != X }
105 * [] == DFlocal(X) U DF(X)
106 * () == DFup(X)
108 * Dominator graph of the same nodes.
110 * AAA AAA: [ ] ()
111 * / \
112 * BBB JJJ BBB: [ JJJ ] ( JJJ ) JJJ: [ ] ()
114 * CCC CCC: [ ] ( BBB, JJJ )
115 * / \
116 * DDD EEE DDD: [ ] ( BBB ) EEE: [ JJJ ] ()
118 * FFF FFF: [ ] ( BBB )
119 * / \
120 * GGG HHH GGG: [ ] ( BBB ) HHH: [ BBB ] ()
122 * III III: [ BBB ] ()
125 * BBB and JJJ are definitely the dominance frontier.
126 * Where do I place phi functions and how do I make that decision.
130 struct filelist {
131 const char *filename;
132 struct filelist *next;
135 struct filelist *include_filelist = NULL;
137 static void __attribute__((noreturn)) die(char *fmt, ...)
139 va_list args;
141 va_start(args, fmt);
142 vfprintf(stderr, fmt, args);
143 va_end(args);
144 fflush(stdout);
145 fflush(stderr);
146 exit(1);
149 static void *xmalloc(size_t size, const char *name)
151 void *buf;
152 buf = malloc(size);
153 if (!buf) {
154 die("Cannot malloc %ld bytes to hold %s: %s\n",
155 size + 0UL, name, strerror(errno));
157 return buf;
160 static void *xcmalloc(size_t size, const char *name)
162 void *buf;
163 buf = xmalloc(size, name);
164 memset(buf, 0, size);
165 return buf;
168 static void *xrealloc(void *ptr, size_t size, const char *name)
170 void *buf;
171 buf = realloc(ptr, size);
172 if (!buf) {
173 die("Cannot realloc %ld bytes to hold %s: %s\n",
174 size + 0UL, name, strerror(errno));
176 return buf;
179 static void xfree(const void *ptr)
181 free((void *)ptr);
184 static char *xstrdup(const char *str)
186 char *new;
187 int len;
188 len = strlen(str);
189 new = xmalloc(len + 1, "xstrdup string");
190 memcpy(new, str, len);
191 new[len] = '\0';
192 return new;
195 static void xchdir(const char *path)
197 if (chdir(path) != 0) {
198 die("chdir to `%s' failed: %s\n",
199 path, strerror(errno));
203 static int exists(const char *dirname, const char *filename)
205 char cwd[MAX_CWD_SIZE];
206 int does_exist;
208 if (getcwd(cwd, sizeof(cwd)) == 0) {
209 die("cwd buffer to small");
212 does_exist = 1;
213 if (chdir(dirname) != 0) {
214 does_exist = 0;
216 if (does_exist && (access(filename, O_RDONLY) < 0)) {
217 if ((errno != EACCES) && (errno != EROFS)) {
218 does_exist = 0;
221 xchdir(cwd);
222 return does_exist;
225 static off_t get_file_size(FILE *f)
227 struct stat s;
228 int fd = fileno(f);
229 if (fd == -1) return -1;
230 if (fstat(fd, &s) == -1) return -1;
231 return s.st_size;
234 static char *slurp_file(const char *dirname, const char *filename, off_t *r_size)
236 char cwd[MAX_CWD_SIZE];
237 char *buf;
238 off_t size, progress;
239 ssize_t result;
240 FILE* file;
242 if (!filename) {
243 *r_size = 0;
244 return 0;
246 if (getcwd(cwd, sizeof(cwd)) == 0) {
247 die("cwd buffer to small");
249 xchdir(dirname);
250 file = fopen(filename, "rb");
251 xchdir(cwd);
252 if (file == NULL) {
253 die("Cannot open '%s' : %s\n",
254 filename, strerror(errno));
256 size = get_file_size(file);
257 if (size == -1) {
258 die("Could not fetch size of '%s': %s\n", filename, strerror(errno));
260 *r_size = size +1;
261 buf = xmalloc(size +2, filename);
262 buf[size] = '\n'; /* Make certain the file is newline terminated */
263 buf[size+1] = '\0'; /* Null terminate the file for good measure */
264 progress = 0;
265 while(progress < size) {
266 result = fread(buf + progress, 1, size - progress, file);
267 if (result < 0) {
268 if ((errno == EINTR) || (errno == EAGAIN))
269 continue;
270 die("read on %s of %ld bytes failed: %s\n",
271 filename, (size - progress)+ 0UL, strerror(errno));
273 progress += result;
275 fclose(file);
276 return buf;
279 /* Types on the destination platform */
280 #if DEBUG_ROMCC_WARNINGS
281 #warning "FIXME this assumes 32bit x86 is the destination"
282 #endif
283 typedef int8_t schar_t;
284 typedef uint8_t uchar_t;
285 typedef int8_t char_t;
286 typedef int16_t short_t;
287 typedef uint16_t ushort_t;
288 typedef int32_t int_t;
289 typedef uint32_t uint_t;
290 typedef int32_t long_t;
291 #define ulong_t uint32_t
293 #define SCHAR_T_MIN (-128)
294 #define SCHAR_T_MAX 127
295 #define UCHAR_T_MAX 255
296 #define CHAR_T_MIN SCHAR_T_MIN
297 #define CHAR_T_MAX SCHAR_T_MAX
298 #define SHRT_T_MIN (-32768)
299 #define SHRT_T_MAX 32767
300 #define USHRT_T_MAX 65535
301 #define INT_T_MIN (-LONG_T_MAX - 1)
302 #define INT_T_MAX 2147483647
303 #define UINT_T_MAX 4294967295U
304 #define LONG_T_MIN (-LONG_T_MAX - 1)
305 #define LONG_T_MAX 2147483647
306 #define ULONG_T_MAX 4294967295U
308 #define SIZEOF_I8 8
309 #define SIZEOF_I16 16
310 #define SIZEOF_I32 32
311 #define SIZEOF_I64 64
313 #define SIZEOF_CHAR 8
314 #define SIZEOF_SHORT 16
315 #define SIZEOF_INT 32
316 #define SIZEOF_LONG (sizeof(long_t)*SIZEOF_CHAR)
319 #define ALIGNOF_CHAR 8
320 #define ALIGNOF_SHORT 16
321 #define ALIGNOF_INT 32
322 #define ALIGNOF_LONG (sizeof(long_t)*SIZEOF_CHAR)
324 #define REG_SIZEOF_REG 32
325 #define REG_SIZEOF_CHAR REG_SIZEOF_REG
326 #define REG_SIZEOF_SHORT REG_SIZEOF_REG
327 #define REG_SIZEOF_INT REG_SIZEOF_REG
328 #define REG_SIZEOF_LONG REG_SIZEOF_REG
330 #define REG_ALIGNOF_REG REG_SIZEOF_REG
331 #define REG_ALIGNOF_CHAR REG_SIZEOF_REG
332 #define REG_ALIGNOF_SHORT REG_SIZEOF_REG
333 #define REG_ALIGNOF_INT REG_SIZEOF_REG
334 #define REG_ALIGNOF_LONG REG_SIZEOF_REG
336 /* Additional definitions for clarity.
337 * I currently assume a long is the largest native
338 * machine word and that a pointer fits into it.
340 #define SIZEOF_WORD SIZEOF_LONG
341 #define SIZEOF_POINTER SIZEOF_LONG
342 #define ALIGNOF_WORD ALIGNOF_LONG
343 #define ALIGNOF_POINTER ALIGNOF_LONG
344 #define REG_SIZEOF_POINTER REG_SIZEOF_LONG
345 #define REG_ALIGNOF_POINTER REG_ALIGNOF_LONG
347 struct file_state {
348 struct file_state *prev;
349 const char *basename;
350 char *dirname;
351 const char *buf;
352 off_t size;
353 const char *pos;
354 int line;
355 const char *line_start;
356 int report_line;
357 const char *report_name;
358 const char *report_dir;
359 int macro : 1;
360 int trigraphs : 1;
361 int join_lines : 1;
363 struct hash_entry;
364 struct token {
365 int tok;
366 struct hash_entry *ident;
367 const char *pos;
368 int str_len;
369 union {
370 ulong_t integer;
371 const char *str;
372 int notmacro;
373 } val;
376 /* I have two classes of types:
377 * Operational types.
378 * Logical types. (The type the C standard says the operation is of)
380 * The operational types are:
381 * chars
382 * shorts
383 * ints
384 * longs
386 * floats
387 * doubles
388 * long doubles
390 * pointer
394 /* Machine model.
395 * No memory is useable by the compiler.
396 * There is no floating point support.
397 * All operations take place in general purpose registers.
398 * There is one type of general purpose register.
399 * Unsigned longs are stored in that general purpose register.
402 /* Operations on general purpose registers.
405 #define OP_SDIVT 0
406 #define OP_UDIVT 1
407 #define OP_SMUL 2
408 #define OP_UMUL 3
409 #define OP_SDIV 4
410 #define OP_UDIV 5
411 #define OP_SMOD 6
412 #define OP_UMOD 7
413 #define OP_ADD 8
414 #define OP_SUB 9
415 #define OP_SL 10
416 #define OP_USR 11
417 #define OP_SSR 12
418 #define OP_AND 13
419 #define OP_XOR 14
420 #define OP_OR 15
421 #define OP_POS 16 /* Dummy positive operator don't use it */
422 #define OP_NEG 17
423 #define OP_INVERT 18
425 #define OP_EQ 20
426 #define OP_NOTEQ 21
427 #define OP_SLESS 22
428 #define OP_ULESS 23
429 #define OP_SMORE 24
430 #define OP_UMORE 25
431 #define OP_SLESSEQ 26
432 #define OP_ULESSEQ 27
433 #define OP_SMOREEQ 28
434 #define OP_UMOREEQ 29
436 #define OP_LFALSE 30 /* Test if the expression is logically false */
437 #define OP_LTRUE 31 /* Test if the expression is logcially true */
439 #define OP_LOAD 32
440 #define OP_STORE 33
441 /* For OP_STORE ->type holds the type
442 * RHS(0) holds the destination address
443 * RHS(1) holds the value to store.
446 #define OP_UEXTRACT 34
447 /* OP_UEXTRACT extracts an unsigned bitfield from a pseudo register
448 * RHS(0) holds the pseudo register to extract from
449 * ->type holds the size of the bitfield.
450 * ->u.bitfield.size holds the size of the bitfield.
451 * ->u.bitfield.offset holds the offset to extract from
453 #define OP_SEXTRACT 35
454 /* OP_SEXTRACT extracts a signed bitfield from a pseudo register
455 * RHS(0) holds the pseudo register to extract from
456 * ->type holds the size of the bitfield.
457 * ->u.bitfield.size holds the size of the bitfield.
458 * ->u.bitfield.offset holds the offset to extract from
460 #define OP_DEPOSIT 36
461 /* OP_DEPOSIT replaces a bitfield with a new value.
462 * RHS(0) holds the value to replace a bitifield in.
463 * RHS(1) holds the replacement value
464 * ->u.bitfield.size holds the size of the bitfield.
465 * ->u.bitfield.offset holds the deposit into
468 #define OP_NOOP 37
470 #define OP_MIN_CONST 50
471 #define OP_MAX_CONST 58
472 #define IS_CONST_OP(X) (((X) >= OP_MIN_CONST) && ((X) <= OP_MAX_CONST))
473 #define OP_INTCONST 50
474 /* For OP_INTCONST ->type holds the type.
475 * ->u.cval holds the constant value.
477 #define OP_BLOBCONST 51
478 /* For OP_BLOBCONST ->type holds the layout and size
479 * information. u.blob holds a pointer to the raw binary
480 * data for the constant initializer.
482 #define OP_ADDRCONST 52
483 /* For OP_ADDRCONST ->type holds the type.
484 * MISC(0) holds the reference to the static variable.
485 * ->u.cval holds an offset from that value.
487 #define OP_UNKNOWNVAL 59
488 /* For OP_UNKNOWNAL ->type holds the type.
489 * For some reason we don't know what value this type has.
490 * This allows for variables that have don't have values
491 * assigned yet, or variables whose value we simply do not know.
494 #define OP_WRITE 60
495 /* OP_WRITE moves one pseudo register to another.
496 * MISC(0) holds the destination pseudo register, which must be an OP_DECL.
497 * RHS(0) holds the pseudo to move.
500 #define OP_READ 61
501 /* OP_READ reads the value of a variable and makes
502 * it available for the pseudo operation.
503 * Useful for things like def-use chains.
504 * RHS(0) holds points to the triple to read from.
506 #define OP_COPY 62
507 /* OP_COPY makes a copy of the pseudo register or constant in RHS(0).
509 #define OP_CONVERT 63
510 /* OP_CONVERT makes a copy of the pseudo register or constant in RHS(0).
511 * And then the type is converted appropriately.
513 #define OP_PIECE 64
514 /* OP_PIECE returns one piece of a instruction that returns a structure.
515 * MISC(0) is the instruction
516 * u.cval is the LHS piece of the instruction to return.
518 #define OP_ASM 65
519 /* OP_ASM holds a sequence of assembly instructions, the result
520 * of a C asm directive.
521 * RHS(x) holds input value x to the assembly sequence.
522 * LHS(x) holds the output value x from the assembly sequence.
523 * u.blob holds the string of assembly instructions.
526 #define OP_DEREF 66
527 /* OP_DEREF generates an lvalue from a pointer.
528 * RHS(0) holds the pointer value.
529 * OP_DEREF serves as a place holder to indicate all necessary
530 * checks have been done to indicate a value is an lvalue.
532 #define OP_DOT 67
533 /* OP_DOT references a submember of a structure lvalue.
534 * MISC(0) holds the lvalue.
535 * ->u.field holds the name of the field we want.
537 * Not seen after structures are flattened.
539 #define OP_INDEX 68
540 /* OP_INDEX references a submember of a tuple or array lvalue.
541 * MISC(0) holds the lvalue.
542 * ->u.cval holds the index into the lvalue.
544 * Not seen after structures are flattened.
546 #define OP_VAL 69
547 /* OP_VAL returns the value of a subexpression of the current expression.
548 * Useful for operators that have side effects.
549 * RHS(0) holds the expression.
550 * MISC(0) holds the subexpression of RHS(0) that is the
551 * value of the expression.
553 * Not seen outside of expressions.
556 #define OP_TUPLE 70
557 /* OP_TUPLE is an array of triples that are either variable
558 * or values for a structure or an array. It is used as
559 * a place holder when flattening compound types.
560 * The value represented by an OP_TUPLE is held in N registers.
561 * LHS(0..N-1) refer to those registers.
562 * ->use is a list of statements that use the value.
564 * Although OP_TUPLE always has register sized pieces they are not
565 * used until structures are flattened/decomposed into their register
566 * components.
567 * ???? registers ????
570 #define OP_BITREF 71
571 /* OP_BITREF describes a bitfield as an lvalue.
572 * RHS(0) holds the register value.
573 * ->type holds the type of the bitfield.
574 * ->u.bitfield.size holds the size of the bitfield.
575 * ->u.bitfield.offset holds the offset of the bitfield in the register
579 #define OP_FCALL 72
580 /* OP_FCALL performs a procedure call.
581 * MISC(0) holds a pointer to the OP_LIST of a function
582 * RHS(x) holds argument x of a function
584 * Currently not seen outside of expressions.
586 #define OP_PROG 73
587 /* OP_PROG is an expression that holds a list of statements, or
588 * expressions. The final expression is the value of the expression.
589 * RHS(0) holds the start of the list.
592 /* statements */
593 #define OP_LIST 80
594 /* OP_LIST Holds a list of statements that compose a function, and a result value.
595 * RHS(0) holds the list of statements.
596 * A list of all functions is maintained.
599 #define OP_BRANCH 81 /* an unconditional branch */
600 /* For branch instructions
601 * TARG(0) holds the branch target.
602 * ->next holds where to branch to if the branch is not taken.
603 * The branch target can only be a label
606 #define OP_CBRANCH 82 /* a conditional branch */
607 /* For conditional branch instructions
608 * RHS(0) holds the branch condition.
609 * TARG(0) holds the branch target.
610 * ->next holds where to branch to if the branch is not taken.
611 * The branch target can only be a label
614 #define OP_CALL 83 /* an uncontional branch that will return */
615 /* For call instructions
616 * MISC(0) holds the OP_RET that returns from the branch
617 * TARG(0) holds the branch target.
618 * ->next holds where to branch to if the branch is not taken.
619 * The branch target can only be a label
622 #define OP_RET 84 /* an uncontinonal branch through a variable back to an OP_CALL */
623 /* For call instructions
624 * RHS(0) holds the variable with the return address
625 * The branch target can only be a label
628 #define OP_LABEL 86
629 /* OP_LABEL is a triple that establishes an target for branches.
630 * ->use is the list of all branches that use this label.
633 #define OP_ADECL 87
634 /* OP_ADECL is a triple that establishes an lvalue for assignments.
635 * A variable takes N registers to contain.
636 * LHS(0..N-1) refer to an OP_PIECE triple that represents
637 * the Xth register that the variable is stored in.
638 * ->use is a list of statements that use the variable.
640 * Although OP_ADECL always has register sized pieces they are not
641 * used until structures are flattened/decomposed into their register
642 * components.
645 #define OP_SDECL 88
646 /* OP_SDECL is a triple that establishes a variable of static
647 * storage duration.
648 * ->use is a list of statements that use the variable.
649 * MISC(0) holds the initializer expression.
653 #define OP_PHI 89
654 /* OP_PHI is a triple used in SSA form code.
655 * It is used when multiple code paths merge and a variable needs
656 * a single assignment from any of those code paths.
657 * The operation is a cross between OP_DECL and OP_WRITE, which
658 * is what OP_PHI is generated from.
660 * RHS(x) points to the value from code path x
661 * The number of RHS entries is the number of control paths into the block
662 * in which OP_PHI resides. The elements of the array point to point
663 * to the variables OP_PHI is derived from.
665 * MISC(0) holds a pointer to the orginal OP_DECL node.
668 #if 0
669 /* continuation helpers
671 #define OP_CPS_BRANCH 90 /* an unconditional branch */
672 /* OP_CPS_BRANCH calls a continuation
673 * RHS(x) holds argument x of the function
674 * TARG(0) holds OP_CPS_START target
676 #define OP_CPS_CBRANCH 91 /* a conditional branch */
677 /* OP_CPS_CBRANCH conditionally calls one of two continuations
678 * RHS(0) holds the branch condition
679 * RHS(x + 1) holds argument x of the function
680 * TARG(0) holds the OP_CPS_START to jump to when true
681 * ->next holds the OP_CPS_START to jump to when false
683 #define OP_CPS_CALL 92 /* an uncontional branch that will return */
684 /* For OP_CPS_CALL instructions
685 * RHS(x) holds argument x of the function
686 * MISC(0) holds the OP_CPS_RET that returns from the branch
687 * TARG(0) holds the branch target.
688 * ->next holds where the OP_CPS_RET will return to.
690 #define OP_CPS_RET 93
691 /* OP_CPS_RET conditionally calls one of two continuations
692 * RHS(0) holds the variable with the return function address
693 * RHS(x + 1) holds argument x of the function
694 * The branch target may be any OP_CPS_START
696 #define OP_CPS_END 94
697 /* OP_CPS_END is the triple at the end of the program.
698 * For most practical purposes it is a branch.
700 #define OP_CPS_START 95
701 /* OP_CPS_START is a triple at the start of a continuation
702 * The arguments variables takes N registers to contain.
703 * LHS(0..N-1) refer to an OP_PIECE triple that represents
704 * the Xth register that the arguments are stored in.
706 #endif
708 /* Architecture specific instructions */
709 #define OP_CMP 100
710 #define OP_TEST 101
711 #define OP_SET_EQ 102
712 #define OP_SET_NOTEQ 103
713 #define OP_SET_SLESS 104
714 #define OP_SET_ULESS 105
715 #define OP_SET_SMORE 106
716 #define OP_SET_UMORE 107
717 #define OP_SET_SLESSEQ 108
718 #define OP_SET_ULESSEQ 109
719 #define OP_SET_SMOREEQ 110
720 #define OP_SET_UMOREEQ 111
722 #define OP_JMP 112
723 #define OP_JMP_EQ 113
724 #define OP_JMP_NOTEQ 114
725 #define OP_JMP_SLESS 115
726 #define OP_JMP_ULESS 116
727 #define OP_JMP_SMORE 117
728 #define OP_JMP_UMORE 118
729 #define OP_JMP_SLESSEQ 119
730 #define OP_JMP_ULESSEQ 120
731 #define OP_JMP_SMOREEQ 121
732 #define OP_JMP_UMOREEQ 122
734 /* Builtin operators that it is just simpler to use the compiler for */
735 #define OP_INB 130
736 #define OP_INW 131
737 #define OP_INL 132
738 #define OP_OUTB 133
739 #define OP_OUTW 134
740 #define OP_OUTL 135
741 #define OP_BSF 136
742 #define OP_BSR 137
743 #define OP_RDMSR 138
744 #define OP_WRMSR 139
745 #define OP_HLT 140
747 struct op_info {
748 const char *name;
749 unsigned flags;
750 #define PURE 0x001 /* Triple has no side effects */
751 #define IMPURE 0x002 /* Triple has side effects */
752 #define PURE_BITS(FLAGS) ((FLAGS) & 0x3)
753 #define DEF 0x004 /* Triple is a variable definition */
754 #define BLOCK 0x008 /* Triple stores the current block */
755 #define STRUCTURAL 0x010 /* Triple does not generate a machine instruction */
756 #define BRANCH_BITS(FLAGS) ((FLAGS) & 0xe0 )
757 #define UBRANCH 0x020 /* Triple is an unconditional branch instruction */
758 #define CBRANCH 0x040 /* Triple is a conditional branch instruction */
759 #define RETBRANCH 0x060 /* Triple is a return instruction */
760 #define CALLBRANCH 0x080 /* Triple is a call instruction */
761 #define ENDBRANCH 0x0a0 /* Triple is an end instruction */
762 #define PART 0x100 /* Triple is really part of another triple */
763 #define BITFIELD 0x200 /* Triple manipulates a bitfield */
764 signed char lhs, rhs, misc, targ;
767 #define OP(LHS, RHS, MISC, TARG, FLAGS, NAME) { \
768 .name = (NAME), \
769 .flags = (FLAGS), \
770 .lhs = (LHS), \
771 .rhs = (RHS), \
772 .misc = (MISC), \
773 .targ = (TARG), \
775 static const struct op_info table_ops[] = {
776 [OP_SDIVT ] = OP( 2, 2, 0, 0, PURE | BLOCK , "sdivt"),
777 [OP_UDIVT ] = OP( 2, 2, 0, 0, PURE | BLOCK , "udivt"),
778 [OP_SMUL ] = OP( 0, 2, 0, 0, PURE | DEF | BLOCK , "smul"),
779 [OP_UMUL ] = OP( 0, 2, 0, 0, PURE | DEF | BLOCK , "umul"),
780 [OP_SDIV ] = OP( 0, 2, 0, 0, PURE | DEF | BLOCK , "sdiv"),
781 [OP_UDIV ] = OP( 0, 2, 0, 0, PURE | DEF | BLOCK , "udiv"),
782 [OP_SMOD ] = OP( 0, 2, 0, 0, PURE | DEF | BLOCK , "smod"),
783 [OP_UMOD ] = OP( 0, 2, 0, 0, PURE | DEF | BLOCK , "umod"),
784 [OP_ADD ] = OP( 0, 2, 0, 0, PURE | DEF | BLOCK , "add"),
785 [OP_SUB ] = OP( 0, 2, 0, 0, PURE | DEF | BLOCK , "sub"),
786 [OP_SL ] = OP( 0, 2, 0, 0, PURE | DEF | BLOCK , "sl"),
787 [OP_USR ] = OP( 0, 2, 0, 0, PURE | DEF | BLOCK , "usr"),
788 [OP_SSR ] = OP( 0, 2, 0, 0, PURE | DEF | BLOCK , "ssr"),
789 [OP_AND ] = OP( 0, 2, 0, 0, PURE | DEF | BLOCK , "and"),
790 [OP_XOR ] = OP( 0, 2, 0, 0, PURE | DEF | BLOCK , "xor"),
791 [OP_OR ] = OP( 0, 2, 0, 0, PURE | DEF | BLOCK , "or"),
792 [OP_POS ] = OP( 0, 1, 0, 0, PURE | DEF | BLOCK , "pos"),
793 [OP_NEG ] = OP( 0, 1, 0, 0, PURE | DEF | BLOCK , "neg"),
794 [OP_INVERT ] = OP( 0, 1, 0, 0, PURE | DEF | BLOCK , "invert"),
796 [OP_EQ ] = OP( 0, 2, 0, 0, PURE | DEF | BLOCK , "eq"),
797 [OP_NOTEQ ] = OP( 0, 2, 0, 0, PURE | DEF | BLOCK , "noteq"),
798 [OP_SLESS ] = OP( 0, 2, 0, 0, PURE | DEF | BLOCK , "sless"),
799 [OP_ULESS ] = OP( 0, 2, 0, 0, PURE | DEF | BLOCK , "uless"),
800 [OP_SMORE ] = OP( 0, 2, 0, 0, PURE | DEF | BLOCK , "smore"),
801 [OP_UMORE ] = OP( 0, 2, 0, 0, PURE | DEF | BLOCK , "umore"),
802 [OP_SLESSEQ ] = OP( 0, 2, 0, 0, PURE | DEF | BLOCK , "slesseq"),
803 [OP_ULESSEQ ] = OP( 0, 2, 0, 0, PURE | DEF | BLOCK , "ulesseq"),
804 [OP_SMOREEQ ] = OP( 0, 2, 0, 0, PURE | DEF | BLOCK , "smoreeq"),
805 [OP_UMOREEQ ] = OP( 0, 2, 0, 0, PURE | DEF | BLOCK , "umoreeq"),
806 [OP_LFALSE ] = OP( 0, 1, 0, 0, PURE | DEF | BLOCK , "lfalse"),
807 [OP_LTRUE ] = OP( 0, 1, 0, 0, PURE | DEF | BLOCK , "ltrue"),
809 [OP_LOAD ] = OP( 0, 1, 0, 0, PURE | DEF | BLOCK, "load"),
810 [OP_STORE ] = OP( 0, 2, 0, 0, PURE | BLOCK , "store"),
812 [OP_UEXTRACT ] = OP( 0, 1, 0, 0, PURE | DEF | BITFIELD, "uextract"),
813 [OP_SEXTRACT ] = OP( 0, 1, 0, 0, PURE | DEF | BITFIELD, "sextract"),
814 [OP_DEPOSIT ] = OP( 0, 2, 0, 0, PURE | DEF | BITFIELD, "deposit"),
816 [OP_NOOP ] = OP( 0, 0, 0, 0, PURE | BLOCK | STRUCTURAL, "noop"),
818 [OP_INTCONST ] = OP( 0, 0, 0, 0, PURE | DEF, "intconst"),
819 [OP_BLOBCONST ] = OP( 0, 0, 0, 0, PURE , "blobconst"),
820 [OP_ADDRCONST ] = OP( 0, 0, 1, 0, PURE | DEF, "addrconst"),
821 [OP_UNKNOWNVAL ] = OP( 0, 0, 0, 0, PURE | DEF, "unknown"),
823 #if DEBUG_ROMCC_WARNINGS
824 #warning "FIXME is it correct for OP_WRITE to be a def? I currently use it as one..."
825 #endif
826 [OP_WRITE ] = OP( 0, 1, 1, 0, PURE | DEF | BLOCK, "write"),
827 [OP_READ ] = OP( 0, 1, 0, 0, PURE | DEF | BLOCK, "read"),
828 [OP_COPY ] = OP( 0, 1, 0, 0, PURE | DEF | BLOCK, "copy"),
829 [OP_CONVERT ] = OP( 0, 1, 0, 0, PURE | DEF | BLOCK, "convert"),
830 [OP_PIECE ] = OP( 0, 0, 1, 0, PURE | DEF | STRUCTURAL | PART, "piece"),
831 [OP_ASM ] = OP(-1, -1, 0, 0, PURE, "asm"),
832 [OP_DEREF ] = OP( 0, 1, 0, 0, 0 | DEF | BLOCK, "deref"),
833 [OP_DOT ] = OP( 0, 0, 1, 0, PURE | DEF | PART, "dot"),
834 [OP_INDEX ] = OP( 0, 0, 1, 0, PURE | DEF | PART, "index"),
836 [OP_VAL ] = OP( 0, 1, 1, 0, 0 | DEF | BLOCK, "val"),
837 [OP_TUPLE ] = OP(-1, 0, 0, 0, 0 | PURE | BLOCK | STRUCTURAL, "tuple"),
838 [OP_BITREF ] = OP( 0, 1, 0, 0, 0 | DEF | PURE | STRUCTURAL | BITFIELD, "bitref"),
839 /* Call is special most it can stand in for anything so it depends on context */
840 [OP_FCALL ] = OP( 0, -1, 1, 0, 0 | BLOCK | CALLBRANCH, "fcall"),
841 [OP_PROG ] = OP( 0, 1, 0, 0, 0 | IMPURE | BLOCK | STRUCTURAL, "prog"),
842 /* The sizes of OP_FCALL depends upon context */
844 [OP_LIST ] = OP( 0, 1, 1, 0, 0 | DEF | STRUCTURAL, "list"),
845 [OP_BRANCH ] = OP( 0, 0, 0, 1, PURE | BLOCK | UBRANCH, "branch"),
846 [OP_CBRANCH ] = OP( 0, 1, 0, 1, PURE | BLOCK | CBRANCH, "cbranch"),
847 [OP_CALL ] = OP( 0, 0, 1, 1, PURE | BLOCK | CALLBRANCH, "call"),
848 [OP_RET ] = OP( 0, 1, 0, 0, PURE | BLOCK | RETBRANCH, "ret"),
849 [OP_LABEL ] = OP( 0, 0, 0, 0, PURE | BLOCK | STRUCTURAL, "label"),
850 [OP_ADECL ] = OP( 0, 0, 0, 0, PURE | BLOCK | STRUCTURAL, "adecl"),
851 [OP_SDECL ] = OP( 0, 0, 1, 0, PURE | BLOCK | STRUCTURAL, "sdecl"),
852 /* The number of RHS elements of OP_PHI depend upon context */
853 [OP_PHI ] = OP( 0, -1, 1, 0, PURE | DEF | BLOCK, "phi"),
855 #if 0
856 [OP_CPS_BRANCH ] = OP( 0, -1, 0, 1, PURE | BLOCK | UBRANCH, "cps_branch"),
857 [OP_CPS_CBRANCH] = OP( 0, -1, 0, 1, PURE | BLOCK | CBRANCH, "cps_cbranch"),
858 [OP_CPS_CALL ] = OP( 0, -1, 1, 1, PURE | BLOCK | CALLBRANCH, "cps_call"),
859 [OP_CPS_RET ] = OP( 0, -1, 0, 0, PURE | BLOCK | RETBRANCH, "cps_ret"),
860 [OP_CPS_END ] = OP( 0, -1, 0, 0, IMPURE | BLOCK | ENDBRANCH, "cps_end"),
861 [OP_CPS_START ] = OP( -1, 0, 0, 0, PURE | BLOCK | STRUCTURAL, "cps_start"),
862 #endif
864 [OP_CMP ] = OP( 0, 2, 0, 0, PURE | DEF | BLOCK, "cmp"),
865 [OP_TEST ] = OP( 0, 1, 0, 0, PURE | DEF | BLOCK, "test"),
866 [OP_SET_EQ ] = OP( 0, 1, 0, 0, PURE | DEF | BLOCK, "set_eq"),
867 [OP_SET_NOTEQ ] = OP( 0, 1, 0, 0, PURE | DEF | BLOCK, "set_noteq"),
868 [OP_SET_SLESS ] = OP( 0, 1, 0, 0, PURE | DEF | BLOCK, "set_sless"),
869 [OP_SET_ULESS ] = OP( 0, 1, 0, 0, PURE | DEF | BLOCK, "set_uless"),
870 [OP_SET_SMORE ] = OP( 0, 1, 0, 0, PURE | DEF | BLOCK, "set_smore"),
871 [OP_SET_UMORE ] = OP( 0, 1, 0, 0, PURE | DEF | BLOCK, "set_umore"),
872 [OP_SET_SLESSEQ] = OP( 0, 1, 0, 0, PURE | DEF | BLOCK, "set_slesseq"),
873 [OP_SET_ULESSEQ] = OP( 0, 1, 0, 0, PURE | DEF | BLOCK, "set_ulesseq"),
874 [OP_SET_SMOREEQ] = OP( 0, 1, 0, 0, PURE | DEF | BLOCK, "set_smoreq"),
875 [OP_SET_UMOREEQ] = OP( 0, 1, 0, 0, PURE | DEF | BLOCK, "set_umoreq"),
876 [OP_JMP ] = OP( 0, 0, 0, 1, PURE | BLOCK | UBRANCH, "jmp"),
877 [OP_JMP_EQ ] = OP( 0, 1, 0, 1, PURE | BLOCK | CBRANCH, "jmp_eq"),
878 [OP_JMP_NOTEQ ] = OP( 0, 1, 0, 1, PURE | BLOCK | CBRANCH, "jmp_noteq"),
879 [OP_JMP_SLESS ] = OP( 0, 1, 0, 1, PURE | BLOCK | CBRANCH, "jmp_sless"),
880 [OP_JMP_ULESS ] = OP( 0, 1, 0, 1, PURE | BLOCK | CBRANCH, "jmp_uless"),
881 [OP_JMP_SMORE ] = OP( 0, 1, 0, 1, PURE | BLOCK | CBRANCH, "jmp_smore"),
882 [OP_JMP_UMORE ] = OP( 0, 1, 0, 1, PURE | BLOCK | CBRANCH, "jmp_umore"),
883 [OP_JMP_SLESSEQ] = OP( 0, 1, 0, 1, PURE | BLOCK | CBRANCH, "jmp_slesseq"),
884 [OP_JMP_ULESSEQ] = OP( 0, 1, 0, 1, PURE | BLOCK | CBRANCH, "jmp_ulesseq"),
885 [OP_JMP_SMOREEQ] = OP( 0, 1, 0, 1, PURE | BLOCK | CBRANCH, "jmp_smoreq"),
886 [OP_JMP_UMOREEQ] = OP( 0, 1, 0, 1, PURE | BLOCK | CBRANCH, "jmp_umoreq"),
888 [OP_INB ] = OP( 0, 1, 0, 0, IMPURE | DEF | BLOCK, "__inb"),
889 [OP_INW ] = OP( 0, 1, 0, 0, IMPURE | DEF | BLOCK, "__inw"),
890 [OP_INL ] = OP( 0, 1, 0, 0, IMPURE | DEF | BLOCK, "__inl"),
891 [OP_OUTB ] = OP( 0, 2, 0, 0, IMPURE| BLOCK, "__outb"),
892 [OP_OUTW ] = OP( 0, 2, 0, 0, IMPURE| BLOCK, "__outw"),
893 [OP_OUTL ] = OP( 0, 2, 0, 0, IMPURE| BLOCK, "__outl"),
894 [OP_BSF ] = OP( 0, 1, 0, 0, PURE | DEF | BLOCK, "__bsf"),
895 [OP_BSR ] = OP( 0, 1, 0, 0, PURE | DEF | BLOCK, "__bsr"),
896 [OP_RDMSR ] = OP( 2, 1, 0, 0, IMPURE | BLOCK, "__rdmsr"),
897 [OP_WRMSR ] = OP( 0, 3, 0, 0, IMPURE | BLOCK, "__wrmsr"),
898 [OP_HLT ] = OP( 0, 0, 0, 0, IMPURE | BLOCK, "__hlt"),
900 #undef OP
901 #define OP_MAX (sizeof(table_ops)/sizeof(table_ops[0]))
903 static const char *tops(int index)
905 static const char unknown[] = "unknown op";
906 if (index < 0) {
907 return unknown;
909 if (index >= OP_MAX) {
910 return unknown;
912 return table_ops[index].name;
915 struct asm_info;
916 struct triple;
917 struct block;
918 struct triple_set {
919 struct triple_set *next;
920 struct triple *member;
923 #define MAX_LHS 63
924 #define MAX_RHS 127
925 #define MAX_MISC 3
926 #define MAX_TARG 1
928 struct occurrence {
929 int count;
930 const char *filename;
931 const char *function;
932 int line;
933 int col;
934 struct occurrence *parent;
936 struct bitfield {
937 ulong_t size : 8;
938 ulong_t offset : 24;
940 struct triple {
941 struct triple *next, *prev;
942 struct triple_set *use;
943 struct type *type;
944 unsigned int op : 8;
945 unsigned int template_id : 7;
946 unsigned int lhs : 6;
947 unsigned int rhs : 7;
948 unsigned int misc : 2;
949 unsigned int targ : 1;
950 #define TRIPLE_SIZE(TRIPLE) \
951 ((TRIPLE)->lhs + (TRIPLE)->rhs + (TRIPLE)->misc + (TRIPLE)->targ)
952 #define TRIPLE_LHS_OFF(PTR) (0)
953 #define TRIPLE_RHS_OFF(PTR) (TRIPLE_LHS_OFF(PTR) + (PTR)->lhs)
954 #define TRIPLE_MISC_OFF(PTR) (TRIPLE_RHS_OFF(PTR) + (PTR)->rhs)
955 #define TRIPLE_TARG_OFF(PTR) (TRIPLE_MISC_OFF(PTR) + (PTR)->misc)
956 #define LHS(PTR,INDEX) ((PTR)->param[TRIPLE_LHS_OFF(PTR) + (INDEX)])
957 #define RHS(PTR,INDEX) ((PTR)->param[TRIPLE_RHS_OFF(PTR) + (INDEX)])
958 #define TARG(PTR,INDEX) ((PTR)->param[TRIPLE_TARG_OFF(PTR) + (INDEX)])
959 #define MISC(PTR,INDEX) ((PTR)->param[TRIPLE_MISC_OFF(PTR) + (INDEX)])
960 unsigned id; /* A scratch value and finally the register */
961 #define TRIPLE_FLAG_FLATTENED (1 << 31)
962 #define TRIPLE_FLAG_PRE_SPLIT (1 << 30)
963 #define TRIPLE_FLAG_POST_SPLIT (1 << 29)
964 #define TRIPLE_FLAG_VOLATILE (1 << 28)
965 #define TRIPLE_FLAG_INLINE (1 << 27) /* ???? */
966 #define TRIPLE_FLAG_LOCAL (1 << 26)
968 #define TRIPLE_FLAG_COPY TRIPLE_FLAG_VOLATILE
969 struct occurrence *occurrence;
970 union {
971 ulong_t cval;
972 struct bitfield bitfield;
973 struct block *block;
974 void *blob;
975 struct hash_entry *field;
976 struct asm_info *ainfo;
977 struct triple *func;
978 struct symbol *symbol;
979 } u;
980 struct triple *param[2];
983 struct reg_info {
984 unsigned reg;
985 unsigned regcm;
987 struct ins_template {
988 struct reg_info lhs[MAX_LHS + 1], rhs[MAX_RHS + 1];
991 struct asm_info {
992 struct ins_template tmpl;
993 char *str;
996 struct block_set {
997 struct block_set *next;
998 struct block *member;
1000 struct block {
1001 struct block *work_next;
1002 struct triple *first, *last;
1003 int edge_count;
1004 struct block_set *edges;
1005 int users;
1006 struct block_set *use;
1007 struct block_set *idominates;
1008 struct block_set *domfrontier;
1009 struct block *idom;
1010 struct block_set *ipdominates;
1011 struct block_set *ipdomfrontier;
1012 struct block *ipdom;
1013 int vertex;
1017 struct symbol {
1018 struct symbol *next;
1019 struct hash_entry *ident;
1020 struct triple *def;
1021 struct type *type;
1022 int scope_depth;
1025 struct macro_arg {
1026 struct macro_arg *next;
1027 struct hash_entry *ident;
1029 struct macro {
1030 struct hash_entry *ident;
1031 const char *buf;
1032 int buf_len;
1033 struct macro_arg *args;
1034 int argc;
1037 struct hash_entry {
1038 struct hash_entry *next;
1039 const char *name;
1040 int name_len;
1041 int tok;
1042 struct macro *sym_define;
1043 struct symbol *sym_label;
1044 struct symbol *sym_tag;
1045 struct symbol *sym_ident;
1048 #define HASH_TABLE_SIZE 2048
1050 struct compiler_state {
1051 const char *label_prefix;
1052 const char *ofilename;
1053 unsigned long flags;
1054 unsigned long debug;
1055 unsigned long max_allocation_passes;
1057 size_t include_path_count;
1058 const char **include_paths;
1060 size_t define_count;
1061 const char **defines;
1063 size_t undef_count;
1064 const char **undefs;
1066 struct arch_state {
1067 unsigned long features;
1069 struct basic_blocks {
1070 struct triple *func;
1071 struct triple *first;
1072 struct block *first_block, *last_block;
1073 int last_vertex;
1075 #define MAX_PP_IF_DEPTH 63
1076 struct compile_state {
1077 struct compiler_state *compiler;
1078 struct arch_state *arch;
1079 FILE *output;
1080 FILE *errout;
1081 FILE *dbgout;
1082 struct file_state *file;
1083 struct occurrence *last_occurrence;
1084 const char *function;
1085 int token_base;
1086 struct token token[6];
1087 struct hash_entry *hash_table[HASH_TABLE_SIZE];
1088 struct hash_entry *i_switch;
1089 struct hash_entry *i_case;
1090 struct hash_entry *i_continue;
1091 struct hash_entry *i_break;
1092 struct hash_entry *i_default;
1093 struct hash_entry *i_return;
1094 struct hash_entry *i_noreturn;
1095 struct hash_entry *i_unused;
1096 struct hash_entry *i_packed;
1097 /* Additional hash entries for predefined macros */
1098 struct hash_entry *i_defined;
1099 struct hash_entry *i___VA_ARGS__;
1100 struct hash_entry *i___FILE__;
1101 struct hash_entry *i___LINE__;
1102 /* Additional hash entries for predefined identifiers */
1103 struct hash_entry *i___func__;
1104 /* Additional hash entries for attributes */
1105 struct hash_entry *i_noinline;
1106 struct hash_entry *i_always_inline;
1107 int scope_depth;
1108 unsigned char if_bytes[(MAX_PP_IF_DEPTH + CHAR_BIT -1)/CHAR_BIT];
1109 int if_depth;
1110 int eat_depth, eat_targ;
1111 struct file_state *macro_file;
1112 struct triple *functions;
1113 struct triple *main_function;
1114 struct triple *first;
1115 struct triple *global_pool;
1116 struct basic_blocks bb;
1117 int functions_joined;
1120 /* visibility global/local */
1121 /* static/auto duration */
1122 /* typedef, register, inline */
1123 #define STOR_SHIFT 0
1124 #define STOR_MASK 0x001f
1125 /* Visibility */
1126 #define STOR_GLOBAL 0x0001
1127 /* Duration */
1128 #define STOR_PERM 0x0002
1129 /* Definition locality */
1130 #define STOR_NONLOCAL 0x0004 /* The definition is not in this translation unit */
1131 /* Storage specifiers */
1132 #define STOR_AUTO 0x0000
1133 #define STOR_STATIC 0x0002
1134 #define STOR_LOCAL 0x0003
1135 #define STOR_EXTERN 0x0007
1136 #define STOR_INLINE 0x0008
1137 #define STOR_REGISTER 0x0010
1138 #define STOR_TYPEDEF 0x0018
1140 #define QUAL_SHIFT 5
1141 #define QUAL_MASK 0x00e0
1142 #define QUAL_NONE 0x0000
1143 #define QUAL_CONST 0x0020
1144 #define QUAL_VOLATILE 0x0040
1145 #define QUAL_RESTRICT 0x0080
1147 #define TYPE_SHIFT 8
1148 #define TYPE_MASK 0x1f00
1149 #define TYPE_INTEGER(TYPE) ((((TYPE) >= TYPE_CHAR) && ((TYPE) <= TYPE_ULLONG)) || ((TYPE) == TYPE_ENUM) || ((TYPE) == TYPE_BITFIELD))
1150 #define TYPE_ARITHMETIC(TYPE) ((((TYPE) >= TYPE_CHAR) && ((TYPE) <= TYPE_LDOUBLE)) || ((TYPE) == TYPE_ENUM) || ((TYPE) == TYPE_BITFIELD))
1151 #define TYPE_UNSIGNED(TYPE) ((TYPE) & 0x0100)
1152 #define TYPE_SIGNED(TYPE) (!TYPE_UNSIGNED(TYPE))
1153 #define TYPE_MKUNSIGNED(TYPE) (((TYPE) & ~0xF000) | 0x0100)
1154 #define TYPE_RANK(TYPE) ((TYPE) & ~0xF1FF)
1155 #define TYPE_PTR(TYPE) (((TYPE) & TYPE_MASK) == TYPE_POINTER)
1156 #define TYPE_DEFAULT 0x0000
1157 #define TYPE_VOID 0x0100
1158 #define TYPE_CHAR 0x0200
1159 #define TYPE_UCHAR 0x0300
1160 #define TYPE_SHORT 0x0400
1161 #define TYPE_USHORT 0x0500
1162 #define TYPE_INT 0x0600
1163 #define TYPE_UINT 0x0700
1164 #define TYPE_LONG 0x0800
1165 #define TYPE_ULONG 0x0900
1166 #define TYPE_LLONG 0x0a00 /* long long */
1167 #define TYPE_ULLONG 0x0b00
1168 #define TYPE_FLOAT 0x0c00
1169 #define TYPE_DOUBLE 0x0d00
1170 #define TYPE_LDOUBLE 0x0e00 /* long double */
1172 /* Note: TYPE_ENUM is chosen very carefully so TYPE_RANK works */
1173 #define TYPE_ENUM 0x1600
1174 #define TYPE_LIST 0x1700
1175 /* TYPE_LIST is a basic building block when defining enumerations
1176 * type->field_ident holds the name of this enumeration entry.
1177 * type->right holds the entry in the list.
1180 #define TYPE_STRUCT 0x1000
1181 /* For TYPE_STRUCT
1182 * type->left holds the link list of TYPE_PRODUCT entries that
1183 * make up the structure.
1184 * type->elements hold the length of the linked list
1186 #define TYPE_UNION 0x1100
1187 /* For TYPE_UNION
1188 * type->left holds the link list of TYPE_OVERLAP entries that
1189 * make up the union.
1190 * type->elements hold the length of the linked list
1192 #define TYPE_POINTER 0x1200
1193 /* For TYPE_POINTER:
1194 * type->left holds the type pointed to.
1196 #define TYPE_FUNCTION 0x1300
1197 /* For TYPE_FUNCTION:
1198 * type->left holds the return type.
1199 * type->right holds the type of the arguments
1200 * type->elements holds the count of the arguments
1202 #define TYPE_PRODUCT 0x1400
1203 /* TYPE_PRODUCT is a basic building block when defining structures
1204 * type->left holds the type that appears first in memory.
1205 * type->right holds the type that appears next in memory.
1207 #define TYPE_OVERLAP 0x1500
1208 /* TYPE_OVERLAP is a basic building block when defining unions
1209 * type->left and type->right holds to types that overlap
1210 * each other in memory.
1212 #define TYPE_ARRAY 0x1800
1213 /* TYPE_ARRAY is a basic building block when definitng arrays.
1214 * type->left holds the type we are an array of.
1215 * type->elements holds the number of elements.
1217 #define TYPE_TUPLE 0x1900
1218 /* TYPE_TUPLE is a basic building block when defining
1219 * positionally reference type conglomerations. (i.e. closures)
1220 * In essence it is a wrapper for TYPE_PRODUCT, like TYPE_STRUCT
1221 * except it has no field names.
1222 * type->left holds the liked list of TYPE_PRODUCT entries that
1223 * make up the closure type.
1224 * type->elements hold the number of elements in the closure.
1226 #define TYPE_JOIN 0x1a00
1227 /* TYPE_JOIN is a basic building block when defining
1228 * positionally reference type conglomerations. (i.e. closures)
1229 * In essence it is a wrapper for TYPE_OVERLAP, like TYPE_UNION
1230 * except it has no field names.
1231 * type->left holds the liked list of TYPE_OVERLAP entries that
1232 * make up the closure type.
1233 * type->elements hold the number of elements in the closure.
1235 #define TYPE_BITFIELD 0x1b00
1236 /* TYPE_BITFIED is the type of a bitfield.
1237 * type->left holds the type basic type TYPE_BITFIELD is derived from.
1238 * type->elements holds the number of bits in the bitfield.
1240 #define TYPE_UNKNOWN 0x1c00
1241 /* TYPE_UNKNOWN is the type of an unknown value.
1242 * Used on unknown consts and other places where I don't know the type.
1245 #define ATTRIB_SHIFT 16
1246 #define ATTRIB_MASK 0xffff0000
1247 #define ATTRIB_NOINLINE 0x00010000
1248 #define ATTRIB_ALWAYS_INLINE 0x00020000
1250 #define ELEMENT_COUNT_UNSPECIFIED ULONG_T_MAX
1252 struct type {
1253 unsigned int type;
1254 struct type *left, *right;
1255 ulong_t elements;
1256 struct hash_entry *field_ident;
1257 struct hash_entry *type_ident;
1260 #define TEMPLATE_BITS 7
1261 #define MAX_TEMPLATES (1<<TEMPLATE_BITS)
1262 #define MAX_REG_EQUIVS 16
1263 #define MAX_REGC 14
1264 #define MAX_REGISTERS 75
1265 #define REGISTER_BITS 7
1266 #define MAX_VIRT_REGISTERS (1<<REGISTER_BITS)
1267 #define REG_ERROR 0
1268 #define REG_UNSET 1
1269 #define REG_UNNEEDED 2
1270 #define REG_VIRT0 (MAX_REGISTERS + 0)
1271 #define REG_VIRT1 (MAX_REGISTERS + 1)
1272 #define REG_VIRT2 (MAX_REGISTERS + 2)
1273 #define REG_VIRT3 (MAX_REGISTERS + 3)
1274 #define REG_VIRT4 (MAX_REGISTERS + 4)
1275 #define REG_VIRT5 (MAX_REGISTERS + 5)
1276 #define REG_VIRT6 (MAX_REGISTERS + 6)
1277 #define REG_VIRT7 (MAX_REGISTERS + 7)
1278 #define REG_VIRT8 (MAX_REGISTERS + 8)
1279 #define REG_VIRT9 (MAX_REGISTERS + 9)
1281 #if (MAX_REGISTERS + 9) > MAX_VIRT_REGISTERS
1282 #error "MAX_VIRT_REGISTERS to small"
1283 #endif
1284 #if (MAX_REGC + REGISTER_BITS) >= 26
1285 #error "Too many id bits used"
1286 #endif
1288 /* Provision for 8 register classes */
1289 #define REG_SHIFT 0
1290 #define REGC_SHIFT REGISTER_BITS
1291 #define REGC_MASK (((1 << MAX_REGC) - 1) << REGISTER_BITS)
1292 #define REG_MASK (MAX_VIRT_REGISTERS -1)
1293 #define ID_REG(ID) ((ID) & REG_MASK)
1294 #define SET_REG(ID, REG) ((ID) = (((ID) & ~REG_MASK) | ((REG) & REG_MASK)))
1295 #define ID_REGCM(ID) (((ID) & REGC_MASK) >> REGC_SHIFT)
1296 #define SET_REGCM(ID, REGCM) ((ID) = (((ID) & ~REGC_MASK) | (((REGCM) << REGC_SHIFT) & REGC_MASK)))
1297 #define SET_INFO(ID, INFO) ((ID) = (((ID) & ~(REG_MASK | REGC_MASK)) | \
1298 (((INFO).reg) & REG_MASK) | ((((INFO).regcm) << REGC_SHIFT) & REGC_MASK)))
1300 #define ARCH_INPUT_REGS 4
1301 #define ARCH_OUTPUT_REGS 4
1303 static const struct reg_info arch_input_regs[ARCH_INPUT_REGS];
1304 static const struct reg_info arch_output_regs[ARCH_OUTPUT_REGS];
1305 static unsigned arch_reg_regcm(struct compile_state *state, int reg);
1306 static unsigned arch_regcm_normalize(struct compile_state *state, unsigned regcm);
1307 static unsigned arch_regcm_reg_normalize(struct compile_state *state, unsigned regcm);
1308 static void arch_reg_equivs(
1309 struct compile_state *state, unsigned *equiv, int reg);
1310 static int arch_select_free_register(
1311 struct compile_state *state, char *used, int classes);
1312 static unsigned arch_regc_size(struct compile_state *state, int class);
1313 static int arch_regcm_intersect(unsigned regcm1, unsigned regcm2);
1314 static unsigned arch_type_to_regcm(struct compile_state *state, struct type *type);
1315 static const char *arch_reg_str(int reg);
1316 static struct reg_info arch_reg_constraint(
1317 struct compile_state *state, struct type *type, const char *constraint);
1318 static struct reg_info arch_reg_clobber(
1319 struct compile_state *state, const char *clobber);
1320 static struct reg_info arch_reg_lhs(struct compile_state *state,
1321 struct triple *ins, int index);
1322 static struct reg_info arch_reg_rhs(struct compile_state *state,
1323 struct triple *ins, int index);
1324 static int arch_reg_size(int reg);
1325 static struct triple *transform_to_arch_instruction(
1326 struct compile_state *state, struct triple *ins);
1327 static struct triple *flatten(
1328 struct compile_state *state, struct triple *first, struct triple *ptr);
1329 static void print_dominators(struct compile_state *state,
1330 FILE *fp, struct basic_blocks *bb);
1331 static void print_dominance_frontiers(struct compile_state *state,
1332 FILE *fp, struct basic_blocks *bb);
1336 #define DEBUG_ABORT_ON_ERROR 0x00000001
1337 #define DEBUG_BASIC_BLOCKS 0x00000002
1338 #define DEBUG_FDOMINATORS 0x00000004
1339 #define DEBUG_RDOMINATORS 0x00000008
1340 #define DEBUG_TRIPLES 0x00000010
1341 #define DEBUG_INTERFERENCE 0x00000020
1342 #define DEBUG_SCC_TRANSFORM 0x00000040
1343 #define DEBUG_SCC_TRANSFORM2 0x00000080
1344 #define DEBUG_REBUILD_SSA_FORM 0x00000100
1345 #define DEBUG_INLINE 0x00000200
1346 #define DEBUG_RANGE_CONFLICTS 0x00000400
1347 #define DEBUG_RANGE_CONFLICTS2 0x00000800
1348 #define DEBUG_COLOR_GRAPH 0x00001000
1349 #define DEBUG_COLOR_GRAPH2 0x00002000
1350 #define DEBUG_COALESCING 0x00004000
1351 #define DEBUG_COALESCING2 0x00008000
1352 #define DEBUG_VERIFICATION 0x00010000
1353 #define DEBUG_CALLS 0x00020000
1354 #define DEBUG_CALLS2 0x00040000
1355 #define DEBUG_TOKENS 0x80000000
1357 #define DEBUG_DEFAULT ( \
1358 DEBUG_ABORT_ON_ERROR | \
1359 DEBUG_BASIC_BLOCKS | \
1360 DEBUG_FDOMINATORS | \
1361 DEBUG_RDOMINATORS | \
1362 DEBUG_TRIPLES | \
1365 #define DEBUG_ALL ( \
1366 DEBUG_ABORT_ON_ERROR | \
1367 DEBUG_BASIC_BLOCKS | \
1368 DEBUG_FDOMINATORS | \
1369 DEBUG_RDOMINATORS | \
1370 DEBUG_TRIPLES | \
1371 DEBUG_INTERFERENCE | \
1372 DEBUG_SCC_TRANSFORM | \
1373 DEBUG_SCC_TRANSFORM2 | \
1374 DEBUG_REBUILD_SSA_FORM | \
1375 DEBUG_INLINE | \
1376 DEBUG_RANGE_CONFLICTS | \
1377 DEBUG_RANGE_CONFLICTS2 | \
1378 DEBUG_COLOR_GRAPH | \
1379 DEBUG_COLOR_GRAPH2 | \
1380 DEBUG_COALESCING | \
1381 DEBUG_COALESCING2 | \
1382 DEBUG_VERIFICATION | \
1383 DEBUG_CALLS | \
1384 DEBUG_CALLS2 | \
1385 DEBUG_TOKENS | \
1388 #define COMPILER_INLINE_MASK 0x00000007
1389 #define COMPILER_INLINE_ALWAYS 0x00000000
1390 #define COMPILER_INLINE_NEVER 0x00000001
1391 #define COMPILER_INLINE_DEFAULTON 0x00000002
1392 #define COMPILER_INLINE_DEFAULTOFF 0x00000003
1393 #define COMPILER_INLINE_NOPENALTY 0x00000004
1394 #define COMPILER_ELIMINATE_INEFECTUAL_CODE 0x00000008
1395 #define COMPILER_SIMPLIFY 0x00000010
1396 #define COMPILER_SCC_TRANSFORM 0x00000020
1397 #define COMPILER_SIMPLIFY_OP 0x00000040
1398 #define COMPILER_SIMPLIFY_PHI 0x00000080
1399 #define COMPILER_SIMPLIFY_LABEL 0x00000100
1400 #define COMPILER_SIMPLIFY_BRANCH 0x00000200
1401 #define COMPILER_SIMPLIFY_COPY 0x00000400
1402 #define COMPILER_SIMPLIFY_ARITH 0x00000800
1403 #define COMPILER_SIMPLIFY_SHIFT 0x00001000
1404 #define COMPILER_SIMPLIFY_BITWISE 0x00002000
1405 #define COMPILER_SIMPLIFY_LOGICAL 0x00004000
1406 #define COMPILER_SIMPLIFY_BITFIELD 0x00008000
1408 #define COMPILER_TRIGRAPHS 0x40000000
1409 #define COMPILER_PP_ONLY 0x80000000
1411 #define COMPILER_DEFAULT_FLAGS ( \
1412 COMPILER_TRIGRAPHS | \
1413 COMPILER_ELIMINATE_INEFECTUAL_CODE | \
1414 COMPILER_INLINE_DEFAULTON | \
1415 COMPILER_SIMPLIFY_OP | \
1416 COMPILER_SIMPLIFY_PHI | \
1417 COMPILER_SIMPLIFY_LABEL | \
1418 COMPILER_SIMPLIFY_BRANCH | \
1419 COMPILER_SIMPLIFY_COPY | \
1420 COMPILER_SIMPLIFY_ARITH | \
1421 COMPILER_SIMPLIFY_SHIFT | \
1422 COMPILER_SIMPLIFY_BITWISE | \
1423 COMPILER_SIMPLIFY_LOGICAL | \
1424 COMPILER_SIMPLIFY_BITFIELD | \
1427 #define GLOBAL_SCOPE_DEPTH 1
1428 #define FUNCTION_SCOPE_DEPTH (GLOBAL_SCOPE_DEPTH + 1)
1430 static void compile_file(struct compile_state *old_state, const char *filename, int local);
1434 static void init_compiler_state(struct compiler_state *compiler)
1436 memset(compiler, 0, sizeof(*compiler));
1437 compiler->label_prefix = "";
1438 compiler->ofilename = "auto.inc";
1439 compiler->flags = COMPILER_DEFAULT_FLAGS;
1440 compiler->debug = 0;
1441 compiler->max_allocation_passes = MAX_ALLOCATION_PASSES;
1442 compiler->include_path_count = 1;
1443 compiler->include_paths = xcmalloc(sizeof(char *), "include_paths");
1444 compiler->define_count = 1;
1445 compiler->defines = xcmalloc(sizeof(char *), "defines");
1446 compiler->undef_count = 1;
1447 compiler->undefs = xcmalloc(sizeof(char *), "undefs");
1450 struct compiler_flag {
1451 const char *name;
1452 unsigned long flag;
1455 struct compiler_arg {
1456 const char *name;
1457 unsigned long mask;
1458 struct compiler_flag flags[16];
1461 static int set_flag(
1462 const struct compiler_flag *ptr, unsigned long *flags,
1463 int act, const char *flag)
1465 int result = -1;
1466 for(; ptr->name; ptr++) {
1467 if (strcmp(ptr->name, flag) == 0) {
1468 break;
1471 if (ptr->name) {
1472 result = 0;
1473 *flags &= ~(ptr->flag);
1474 if (act) {
1475 *flags |= ptr->flag;
1478 return result;
1481 static int set_arg(
1482 const struct compiler_arg *ptr, unsigned long *flags, const char *arg)
1484 const char *val;
1485 int result = -1;
1486 int len;
1487 val = strchr(arg, '=');
1488 if (val) {
1489 len = val - arg;
1490 val++;
1491 for(; ptr->name; ptr++) {
1492 if (strncmp(ptr->name, arg, len) == 0) {
1493 break;
1496 if (ptr->name) {
1497 *flags &= ~ptr->mask;
1498 result = set_flag(&ptr->flags[0], flags, 1, val);
1501 return result;
1505 static void flag_usage(FILE *fp, const struct compiler_flag *ptr,
1506 const char *prefix, const char *invert_prefix)
1508 for(;ptr->name; ptr++) {
1509 fprintf(fp, "%s%s\n", prefix, ptr->name);
1510 if (invert_prefix) {
1511 fprintf(fp, "%s%s\n", invert_prefix, ptr->name);
1516 static void arg_usage(FILE *fp, const struct compiler_arg *ptr,
1517 const char *prefix)
1519 for(;ptr->name; ptr++) {
1520 const struct compiler_flag *flag;
1521 for(flag = &ptr->flags[0]; flag->name; flag++) {
1522 fprintf(fp, "%s%s=%s\n",
1523 prefix, ptr->name, flag->name);
1528 static int append_string(size_t *max, const char ***vec, const char *str,
1529 const char *name)
1531 size_t count;
1532 count = ++(*max);
1533 *vec = xrealloc(*vec, sizeof(char *)*count, "name");
1534 (*vec)[count -1] = 0;
1535 (*vec)[count -2] = str;
1536 return 0;
1539 static void arg_error(char *fmt, ...);
1540 static void arg_warning(char *fmt, ...);
1541 static const char *identifier(const char *str, const char *end);
1543 static int append_include_path(struct compiler_state *compiler, const char *str)
1545 int result;
1546 if (!exists(str, ".")) {
1547 arg_warning("Warning: Nonexistent include path: `%s'\n",
1548 str);
1550 result = append_string(&compiler->include_path_count,
1551 &compiler->include_paths, str, "include_paths");
1552 return result;
1555 static int append_define(struct compiler_state *compiler, const char *str)
1557 const char *end, *rest;
1558 int result;
1560 end = strchr(str, '=');
1561 if (!end) {
1562 end = str + strlen(str);
1564 rest = identifier(str, end);
1565 if (rest != end) {
1566 int len = end - str - 1;
1567 arg_error("Invalid name cannot define macro: `%*.*s'\n",
1568 len, len, str);
1570 result = append_string(&compiler->define_count,
1571 &compiler->defines, str, "defines");
1572 return result;
1575 static int append_undef(struct compiler_state *compiler, const char *str)
1577 const char *end, *rest;
1578 int result;
1580 end = str + strlen(str);
1581 rest = identifier(str, end);
1582 if (rest != end) {
1583 int len = end - str - 1;
1584 arg_error("Invalid name cannot undefine macro: `%*.*s'\n",
1585 len, len, str);
1587 result = append_string(&compiler->undef_count,
1588 &compiler->undefs, str, "undefs");
1589 return result;
1592 static const struct compiler_flag romcc_flags[] = {
1593 { "trigraphs", COMPILER_TRIGRAPHS },
1594 { "pp-only", COMPILER_PP_ONLY },
1595 { "eliminate-inefectual-code", COMPILER_ELIMINATE_INEFECTUAL_CODE },
1596 { "simplify", COMPILER_SIMPLIFY },
1597 { "scc-transform", COMPILER_SCC_TRANSFORM },
1598 { "simplify-op", COMPILER_SIMPLIFY_OP },
1599 { "simplify-phi", COMPILER_SIMPLIFY_PHI },
1600 { "simplify-label", COMPILER_SIMPLIFY_LABEL },
1601 { "simplify-branch", COMPILER_SIMPLIFY_BRANCH },
1602 { "simplify-copy", COMPILER_SIMPLIFY_COPY },
1603 { "simplify-arith", COMPILER_SIMPLIFY_ARITH },
1604 { "simplify-shift", COMPILER_SIMPLIFY_SHIFT },
1605 { "simplify-bitwise", COMPILER_SIMPLIFY_BITWISE },
1606 { "simplify-logical", COMPILER_SIMPLIFY_LOGICAL },
1607 { "simplify-bitfield", COMPILER_SIMPLIFY_BITFIELD },
1608 { 0, 0 },
1610 static const struct compiler_arg romcc_args[] = {
1611 { "inline-policy", COMPILER_INLINE_MASK,
1613 { "always", COMPILER_INLINE_ALWAYS, },
1614 { "never", COMPILER_INLINE_NEVER, },
1615 { "defaulton", COMPILER_INLINE_DEFAULTON, },
1616 { "defaultoff", COMPILER_INLINE_DEFAULTOFF, },
1617 { "nopenalty", COMPILER_INLINE_NOPENALTY, },
1618 { 0, 0 },
1621 { 0, 0 },
1623 static const struct compiler_flag romcc_opt_flags[] = {
1624 { "-O", COMPILER_SIMPLIFY },
1625 { "-O2", COMPILER_SIMPLIFY | COMPILER_SCC_TRANSFORM },
1626 { "-E", COMPILER_PP_ONLY },
1627 { 0, 0, },
1629 static const struct compiler_flag romcc_debug_flags[] = {
1630 { "all", DEBUG_ALL },
1631 { "abort-on-error", DEBUG_ABORT_ON_ERROR },
1632 { "basic-blocks", DEBUG_BASIC_BLOCKS },
1633 { "fdominators", DEBUG_FDOMINATORS },
1634 { "rdominators", DEBUG_RDOMINATORS },
1635 { "triples", DEBUG_TRIPLES },
1636 { "interference", DEBUG_INTERFERENCE },
1637 { "scc-transform", DEBUG_SCC_TRANSFORM },
1638 { "scc-transform2", DEBUG_SCC_TRANSFORM2 },
1639 { "rebuild-ssa-form", DEBUG_REBUILD_SSA_FORM },
1640 { "inline", DEBUG_INLINE },
1641 { "live-range-conflicts", DEBUG_RANGE_CONFLICTS },
1642 { "live-range-conflicts2", DEBUG_RANGE_CONFLICTS2 },
1643 { "color-graph", DEBUG_COLOR_GRAPH },
1644 { "color-graph2", DEBUG_COLOR_GRAPH2 },
1645 { "coalescing", DEBUG_COALESCING },
1646 { "coalescing2", DEBUG_COALESCING2 },
1647 { "verification", DEBUG_VERIFICATION },
1648 { "calls", DEBUG_CALLS },
1649 { "calls2", DEBUG_CALLS2 },
1650 { "tokens", DEBUG_TOKENS },
1651 { 0, 0 },
1654 static int compiler_encode_flag(
1655 struct compiler_state *compiler, const char *flag)
1657 int act;
1658 int result;
1660 act = 1;
1661 result = -1;
1662 if (strncmp(flag, "no-", 3) == 0) {
1663 flag += 3;
1664 act = 0;
1666 if (strncmp(flag, "-O", 2) == 0) {
1667 result = set_flag(romcc_opt_flags, &compiler->flags, act, flag);
1669 else if (strncmp(flag, "-E", 2) == 0) {
1670 result = set_flag(romcc_opt_flags, &compiler->flags, act, flag);
1672 else if (strncmp(flag, "-I", 2) == 0) {
1673 result = append_include_path(compiler, flag + 2);
1675 else if (strncmp(flag, "-D", 2) == 0) {
1676 result = append_define(compiler, flag + 2);
1678 else if (strncmp(flag, "-U", 2) == 0) {
1679 result = append_undef(compiler, flag + 2);
1681 else if (act && strncmp(flag, "label-prefix=", 13) == 0) {
1682 result = 0;
1683 compiler->label_prefix = flag + 13;
1685 else if (act && strncmp(flag, "max-allocation-passes=", 22) == 0) {
1686 unsigned long max_passes;
1687 char *end;
1688 max_passes = strtoul(flag + 22, &end, 10);
1689 if (end[0] == '\0') {
1690 result = 0;
1691 compiler->max_allocation_passes = max_passes;
1694 else if (act && strcmp(flag, "debug") == 0) {
1695 result = 0;
1696 compiler->debug |= DEBUG_DEFAULT;
1698 else if (strncmp(flag, "debug-", 6) == 0) {
1699 flag += 6;
1700 result = set_flag(romcc_debug_flags, &compiler->debug, act, flag);
1702 else {
1703 result = set_flag(romcc_flags, &compiler->flags, act, flag);
1704 if (result < 0) {
1705 result = set_arg(romcc_args, &compiler->flags, flag);
1708 return result;
1711 static void compiler_usage(FILE *fp)
1713 flag_usage(fp, romcc_opt_flags, "", 0);
1714 flag_usage(fp, romcc_flags, "-f", "-fno-");
1715 arg_usage(fp, romcc_args, "-f");
1716 flag_usage(fp, romcc_debug_flags, "-fdebug-", "-fno-debug-");
1717 fprintf(fp, "-flabel-prefix=<prefix for assembly language labels>\n");
1718 fprintf(fp, "--label-prefix=<prefix for assembly language labels>\n");
1719 fprintf(fp, "-I<include path>\n");
1720 fprintf(fp, "-D<macro>[=defn]\n");
1721 fprintf(fp, "-U<macro>\n");
1724 static void do_cleanup(struct compile_state *state)
1726 if (state->output) {
1727 fclose(state->output);
1728 unlink(state->compiler->ofilename);
1729 state->output = 0;
1731 if (state->dbgout) {
1732 fflush(state->dbgout);
1734 if (state->errout) {
1735 fflush(state->errout);
1739 static struct compile_state *exit_state;
1740 static void exit_cleanup(void)
1742 if (exit_state) {
1743 do_cleanup(exit_state);
1747 static int get_col(struct file_state *file)
1749 int col;
1750 const char *ptr, *end;
1751 ptr = file->line_start;
1752 end = file->pos;
1753 for(col = 0; ptr < end; ptr++) {
1754 if (*ptr != '\t') {
1755 col++;
1757 else {
1758 col = (col & ~7) + 8;
1761 return col;
1764 static void loc(FILE *fp, struct compile_state *state, struct triple *triple)
1766 int col;
1767 if (triple && triple->occurrence) {
1768 struct occurrence *spot;
1769 for(spot = triple->occurrence; spot; spot = spot->parent) {
1770 fprintf(fp, "%s:%d.%d: ",
1771 spot->filename, spot->line, spot->col);
1773 return;
1775 if (!state->file) {
1776 return;
1778 col = get_col(state->file);
1779 fprintf(fp, "%s:%d.%d: ",
1780 state->file->report_name, state->file->report_line, col);
1783 static void __attribute__ ((noreturn)) internal_error(struct compile_state *state, struct triple *ptr,
1784 const char *fmt, ...)
1786 FILE *fp = state->errout;
1787 va_list args;
1788 va_start(args, fmt);
1789 loc(fp, state, ptr);
1790 fputc('\n', fp);
1791 if (ptr) {
1792 fprintf(fp, "%p %-10s ", ptr, tops(ptr->op));
1794 fprintf(fp, "Internal compiler error: ");
1795 vfprintf(fp, fmt, args);
1796 fprintf(fp, "\n");
1797 va_end(args);
1798 do_cleanup(state);
1799 abort();
1803 static void internal_warning(struct compile_state *state, struct triple *ptr,
1804 const char *fmt, ...)
1806 FILE *fp = state->errout;
1807 va_list args;
1808 va_start(args, fmt);
1809 loc(fp, state, ptr);
1810 if (ptr) {
1811 fprintf(fp, "%p %-10s ", ptr, tops(ptr->op));
1813 fprintf(fp, "Internal compiler warning: ");
1814 vfprintf(fp, fmt, args);
1815 fprintf(fp, "\n");
1816 va_end(args);
1821 static void __attribute__ ((noreturn)) error(struct compile_state *state, struct triple *ptr,
1822 const char *fmt, ...)
1824 FILE *fp = state->errout;
1825 va_list args;
1826 va_start(args, fmt);
1827 loc(fp, state, ptr);
1828 fputc('\n', fp);
1829 if (ptr && (state->compiler->debug & DEBUG_ABORT_ON_ERROR)) {
1830 fprintf(fp, "%p %-10s ", ptr, tops(ptr->op));
1832 vfprintf(fp, fmt, args);
1833 va_end(args);
1834 fprintf(fp, "\n");
1835 do_cleanup(state);
1836 if (state->compiler->debug & DEBUG_ABORT_ON_ERROR) {
1837 abort();
1839 exit(1);
1842 static void warning(struct compile_state *state, struct triple *ptr,
1843 const char *fmt, ...)
1845 FILE *fp = state->errout;
1846 va_list args;
1847 va_start(args, fmt);
1848 loc(fp, state, ptr);
1849 fprintf(fp, "warning: ");
1850 if (ptr && (state->compiler->debug & DEBUG_ABORT_ON_ERROR)) {
1851 fprintf(fp, "%p %-10s ", ptr, tops(ptr->op));
1853 vfprintf(fp, fmt, args);
1854 fprintf(fp, "\n");
1855 va_end(args);
1858 #define FINISHME() warning(state, 0, "FINISHME @ %s.%s:%d", __FILE__, __func__, __LINE__)
1860 static void valid_op(struct compile_state *state, int op)
1862 char *fmt = "invalid op: %d";
1863 if (op >= OP_MAX) {
1864 internal_error(state, 0, fmt, op);
1866 if (op < 0) {
1867 internal_error(state, 0, fmt, op);
1871 static void valid_ins(struct compile_state *state, struct triple *ptr)
1873 valid_op(state, ptr->op);
1876 #if DEBUG_ROMCC_WARNING
1877 static void valid_param_count(struct compile_state *state, struct triple *ins)
1879 int lhs, rhs, misc, targ;
1880 valid_ins(state, ins);
1881 lhs = table_ops[ins->op].lhs;
1882 rhs = table_ops[ins->op].rhs;
1883 misc = table_ops[ins->op].misc;
1884 targ = table_ops[ins->op].targ;
1886 if ((lhs >= 0) && (ins->lhs != lhs)) {
1887 internal_error(state, ins, "Bad lhs count");
1889 if ((rhs >= 0) && (ins->rhs != rhs)) {
1890 internal_error(state, ins, "Bad rhs count");
1892 if ((misc >= 0) && (ins->misc != misc)) {
1893 internal_error(state, ins, "Bad misc count");
1895 if ((targ >= 0) && (ins->targ != targ)) {
1896 internal_error(state, ins, "Bad targ count");
1899 #endif
1901 static struct type void_type;
1902 static struct type unknown_type;
1903 static void use_triple(struct triple *used, struct triple *user)
1905 struct triple_set **ptr, *new;
1906 if (!used)
1907 return;
1908 if (!user)
1909 return;
1910 ptr = &used->use;
1911 while(*ptr) {
1912 if ((*ptr)->member == user) {
1913 return;
1915 ptr = &(*ptr)->next;
1917 /* Append new to the head of the list,
1918 * copy_func and rename_block_variables
1919 * depends on this.
1921 new = xcmalloc(sizeof(*new), "triple_set");
1922 new->member = user;
1923 new->next = used->use;
1924 used->use = new;
1927 static void unuse_triple(struct triple *used, struct triple *unuser)
1929 struct triple_set *use, **ptr;
1930 if (!used) {
1931 return;
1933 ptr = &used->use;
1934 while(*ptr) {
1935 use = *ptr;
1936 if (use->member == unuser) {
1937 *ptr = use->next;
1938 xfree(use);
1940 else {
1941 ptr = &use->next;
1946 static void put_occurrence(struct occurrence *occurrence)
1948 if (occurrence) {
1949 occurrence->count -= 1;
1950 if (occurrence->count <= 0) {
1951 if (occurrence->parent) {
1952 put_occurrence(occurrence->parent);
1954 xfree(occurrence);
1959 static void get_occurrence(struct occurrence *occurrence)
1961 if (occurrence) {
1962 occurrence->count += 1;
1967 static struct occurrence *new_occurrence(struct compile_state *state)
1969 struct occurrence *result, *last;
1970 const char *filename;
1971 const char *function;
1972 int line, col;
1974 function = "";
1975 filename = 0;
1976 line = 0;
1977 col = 0;
1978 if (state->file) {
1979 filename = state->file->report_name;
1980 line = state->file->report_line;
1981 col = get_col(state->file);
1983 if (state->function) {
1984 function = state->function;
1986 last = state->last_occurrence;
1987 if (last &&
1988 (last->col == col) &&
1989 (last->line == line) &&
1990 (last->function == function) &&
1991 ((last->filename == filename) ||
1992 (filename != NULL && strcmp(last->filename, filename) == 0)))
1994 get_occurrence(last);
1995 return last;
1997 if (last) {
1998 state->last_occurrence = 0;
1999 put_occurrence(last);
2001 result = xmalloc(sizeof(*result), "occurrence");
2002 result->count = 2;
2003 result->filename = filename;
2004 result->function = function;
2005 result->line = line;
2006 result->col = col;
2007 result->parent = 0;
2008 state->last_occurrence = result;
2009 return result;
2012 static struct occurrence *inline_occurrence(struct compile_state *state,
2013 struct occurrence *base, struct occurrence *top)
2015 struct occurrence *result, *last;
2016 if (top->parent) {
2017 internal_error(state, 0, "inlining an already inlined function?");
2019 /* If I have a null base treat it that way */
2020 if ((base->parent == 0) &&
2021 (base->col == 0) &&
2022 (base->line == 0) &&
2023 (base->function[0] == '\0') &&
2024 (base->filename[0] == '\0')) {
2025 base = 0;
2027 /* See if I can reuse the last occurrence I had */
2028 last = state->last_occurrence;
2029 if (last &&
2030 (last->parent == base) &&
2031 (last->col == top->col) &&
2032 (last->line == top->line) &&
2033 (last->function == top->function) &&
2034 (last->filename == top->filename)) {
2035 get_occurrence(last);
2036 return last;
2038 /* I can't reuse the last occurrence so free it */
2039 if (last) {
2040 state->last_occurrence = 0;
2041 put_occurrence(last);
2043 /* Generate a new occurrence structure */
2044 get_occurrence(base);
2045 result = xmalloc(sizeof(*result), "occurrence");
2046 result->count = 2;
2047 result->filename = top->filename;
2048 result->function = top->function;
2049 result->line = top->line;
2050 result->col = top->col;
2051 result->parent = base;
2052 state->last_occurrence = result;
2053 return result;
2056 static struct occurrence dummy_occurrence = {
2057 .count = 2,
2058 .filename = __FILE__,
2059 .function = "",
2060 .line = __LINE__,
2061 .col = 0,
2062 .parent = 0,
2065 /* The undef triple is used as a place holder when we are removing pointers
2066 * from a triple. Having allows certain sanity checks to pass even
2067 * when the original triple that was pointed to is gone.
2069 static struct triple unknown_triple = {
2070 .next = &unknown_triple,
2071 .prev = &unknown_triple,
2072 .use = 0,
2073 .op = OP_UNKNOWNVAL,
2074 .lhs = 0,
2075 .rhs = 0,
2076 .misc = 0,
2077 .targ = 0,
2078 .type = &unknown_type,
2079 .id = -1, /* An invalid id */
2080 .u = { .cval = 0, },
2081 .occurrence = &dummy_occurrence,
2082 .param = { [0] = 0, [1] = 0, },
2086 static size_t registers_of(struct compile_state *state, struct type *type);
2088 static struct triple *alloc_triple(struct compile_state *state,
2089 int op, struct type *type, int lhs_wanted, int rhs_wanted,
2090 struct occurrence *occurrence)
2092 size_t size, extra_count, min_count;
2093 int lhs, rhs, misc, targ;
2094 struct triple *ret, dummy;
2095 dummy.op = op;
2096 dummy.occurrence = occurrence;
2097 valid_op(state, op);
2098 lhs = table_ops[op].lhs;
2099 rhs = table_ops[op].rhs;
2100 misc = table_ops[op].misc;
2101 targ = table_ops[op].targ;
2103 switch(op) {
2104 case OP_FCALL:
2105 rhs = rhs_wanted;
2106 break;
2107 case OP_PHI:
2108 rhs = rhs_wanted;
2109 break;
2110 case OP_ADECL:
2111 lhs = registers_of(state, type);
2112 break;
2113 case OP_TUPLE:
2114 lhs = registers_of(state, type);
2115 break;
2116 case OP_ASM:
2117 rhs = rhs_wanted;
2118 lhs = lhs_wanted;
2119 break;
2121 if ((rhs < 0) || (rhs > MAX_RHS)) {
2122 internal_error(state, &dummy, "bad rhs count %d", rhs);
2124 if ((lhs < 0) || (lhs > MAX_LHS)) {
2125 internal_error(state, &dummy, "bad lhs count %d", lhs);
2127 if ((misc < 0) || (misc > MAX_MISC)) {
2128 internal_error(state, &dummy, "bad misc count %d", misc);
2130 if ((targ < 0) || (targ > MAX_TARG)) {
2131 internal_error(state, &dummy, "bad targs count %d", targ);
2134 min_count = sizeof(ret->param)/sizeof(ret->param[0]);
2135 extra_count = lhs + rhs + misc + targ;
2136 extra_count = (extra_count < min_count)? 0 : extra_count - min_count;
2138 size = sizeof(*ret) + sizeof(ret->param[0]) * extra_count;
2139 ret = xcmalloc(size, "tripple");
2140 ret->op = op;
2141 ret->lhs = lhs;
2142 ret->rhs = rhs;
2143 ret->misc = misc;
2144 ret->targ = targ;
2145 ret->type = type;
2146 ret->next = ret;
2147 ret->prev = ret;
2148 ret->occurrence = occurrence;
2149 /* A simple sanity check */
2150 if ((ret->op != op) ||
2151 (ret->lhs != lhs) ||
2152 (ret->rhs != rhs) ||
2153 (ret->misc != misc) ||
2154 (ret->targ != targ) ||
2155 (ret->type != type) ||
2156 (ret->next != ret) ||
2157 (ret->prev != ret) ||
2158 (ret->occurrence != occurrence)) {
2159 internal_error(state, ret, "huh?");
2161 return ret;
2164 struct triple *dup_triple(struct compile_state *state, struct triple *src)
2166 struct triple *dup;
2167 int src_lhs, src_rhs, src_size;
2168 src_lhs = src->lhs;
2169 src_rhs = src->rhs;
2170 src_size = TRIPLE_SIZE(src);
2171 get_occurrence(src->occurrence);
2172 dup = alloc_triple(state, src->op, src->type, src_lhs, src_rhs,
2173 src->occurrence);
2174 memcpy(dup, src, sizeof(*src));
2175 memcpy(dup->param, src->param, src_size * sizeof(src->param[0]));
2176 return dup;
2179 static struct triple *copy_triple(struct compile_state *state, struct triple *src)
2181 struct triple *copy;
2182 copy = dup_triple(state, src);
2183 copy->use = 0;
2184 copy->next = copy->prev = copy;
2185 return copy;
2188 static struct triple *new_triple(struct compile_state *state,
2189 int op, struct type *type, int lhs, int rhs)
2191 struct triple *ret;
2192 struct occurrence *occurrence;
2193 occurrence = new_occurrence(state);
2194 ret = alloc_triple(state, op, type, lhs, rhs, occurrence);
2195 return ret;
2198 static struct triple *build_triple(struct compile_state *state,
2199 int op, struct type *type, struct triple *left, struct triple *right,
2200 struct occurrence *occurrence)
2202 struct triple *ret;
2203 size_t count;
2204 ret = alloc_triple(state, op, type, -1, -1, occurrence);
2205 count = TRIPLE_SIZE(ret);
2206 if (count > 0) {
2207 ret->param[0] = left;
2209 if (count > 1) {
2210 ret->param[1] = right;
2212 return ret;
2215 static struct triple *triple(struct compile_state *state,
2216 int op, struct type *type, struct triple *left, struct triple *right)
2218 struct triple *ret;
2219 size_t count;
2220 ret = new_triple(state, op, type, -1, -1);
2221 count = TRIPLE_SIZE(ret);
2222 if (count >= 1) {
2223 ret->param[0] = left;
2225 if (count >= 2) {
2226 ret->param[1] = right;
2228 return ret;
2231 static struct triple *branch(struct compile_state *state,
2232 struct triple *targ, struct triple *test)
2234 struct triple *ret;
2235 if (test) {
2236 ret = new_triple(state, OP_CBRANCH, &void_type, -1, 1);
2237 RHS(ret, 0) = test;
2238 } else {
2239 ret = new_triple(state, OP_BRANCH, &void_type, -1, 0);
2241 TARG(ret, 0) = targ;
2242 /* record the branch target was used */
2243 if (!targ || (targ->op != OP_LABEL)) {
2244 internal_error(state, 0, "branch not to label");
2246 return ret;
2249 static int triple_is_label(struct compile_state *state, struct triple *ins);
2250 static int triple_is_call(struct compile_state *state, struct triple *ins);
2251 static int triple_is_cbranch(struct compile_state *state, struct triple *ins);
2252 static void insert_triple(struct compile_state *state,
2253 struct triple *first, struct triple *ptr)
2255 if (ptr) {
2256 if ((ptr->id & TRIPLE_FLAG_FLATTENED) || (ptr->next != ptr)) {
2257 internal_error(state, ptr, "expression already used");
2259 ptr->next = first;
2260 ptr->prev = first->prev;
2261 ptr->prev->next = ptr;
2262 ptr->next->prev = ptr;
2264 if (triple_is_cbranch(state, ptr->prev) ||
2265 triple_is_call(state, ptr->prev)) {
2266 unuse_triple(first, ptr->prev);
2267 use_triple(ptr, ptr->prev);
2272 static int triple_stores_block(struct compile_state *state, struct triple *ins)
2274 /* This function is used to determine if u.block
2275 * is utilized to store the current block number.
2277 int stores_block;
2278 valid_ins(state, ins);
2279 stores_block = (table_ops[ins->op].flags & BLOCK) == BLOCK;
2280 return stores_block;
2283 static int triple_is_branch(struct compile_state *state, struct triple *ins);
2284 static struct block *block_of_triple(struct compile_state *state,
2285 struct triple *ins)
2287 struct triple *first;
2288 if (!ins || ins == &unknown_triple) {
2289 return 0;
2291 first = state->first;
2292 while(ins != first && !triple_is_branch(state, ins->prev) &&
2293 !triple_stores_block(state, ins))
2295 if (ins == ins->prev) {
2296 internal_error(state, ins, "ins == ins->prev?");
2298 ins = ins->prev;
2300 return triple_stores_block(state, ins)? ins->u.block: 0;
2303 static void generate_lhs_pieces(struct compile_state *state, struct triple *ins);
2304 static struct triple *pre_triple(struct compile_state *state,
2305 struct triple *base,
2306 int op, struct type *type, struct triple *left, struct triple *right)
2308 struct block *block;
2309 struct triple *ret;
2310 int i;
2311 /* If I am an OP_PIECE jump to the real instruction */
2312 if (base->op == OP_PIECE) {
2313 base = MISC(base, 0);
2315 block = block_of_triple(state, base);
2316 get_occurrence(base->occurrence);
2317 ret = build_triple(state, op, type, left, right, base->occurrence);
2318 generate_lhs_pieces(state, ret);
2319 if (triple_stores_block(state, ret)) {
2320 ret->u.block = block;
2322 insert_triple(state, base, ret);
2323 for(i = 0; i < ret->lhs; i++) {
2324 struct triple *piece;
2325 piece = LHS(ret, i);
2326 insert_triple(state, base, piece);
2327 use_triple(ret, piece);
2328 use_triple(piece, ret);
2330 if (block && (block->first == base)) {
2331 block->first = ret;
2333 return ret;
2336 static struct triple *post_triple(struct compile_state *state,
2337 struct triple *base,
2338 int op, struct type *type, struct triple *left, struct triple *right)
2340 struct block *block;
2341 struct triple *ret, *next;
2342 int zlhs, i;
2343 /* If I am an OP_PIECE jump to the real instruction */
2344 if (base->op == OP_PIECE) {
2345 base = MISC(base, 0);
2347 /* If I have a left hand side skip over it */
2348 zlhs = base->lhs;
2349 if (zlhs) {
2350 base = LHS(base, zlhs - 1);
2353 block = block_of_triple(state, base);
2354 get_occurrence(base->occurrence);
2355 ret = build_triple(state, op, type, left, right, base->occurrence);
2356 generate_lhs_pieces(state, ret);
2357 if (triple_stores_block(state, ret)) {
2358 ret->u.block = block;
2360 next = base->next;
2361 insert_triple(state, next, ret);
2362 zlhs = ret->lhs;
2363 for(i = 0; i < zlhs; i++) {
2364 struct triple *piece;
2365 piece = LHS(ret, i);
2366 insert_triple(state, next, piece);
2367 use_triple(ret, piece);
2368 use_triple(piece, ret);
2370 if (block && (block->last == base)) {
2371 block->last = ret;
2372 if (zlhs) {
2373 block->last = LHS(ret, zlhs - 1);
2376 return ret;
2379 static struct type *reg_type(
2380 struct compile_state *state, struct type *type, int reg);
2382 static void generate_lhs_piece(
2383 struct compile_state *state, struct triple *ins, int index)
2385 struct type *piece_type;
2386 struct triple *piece;
2387 get_occurrence(ins->occurrence);
2388 piece_type = reg_type(state, ins->type, index * REG_SIZEOF_REG);
2390 if ((piece_type->type & TYPE_MASK) == TYPE_BITFIELD) {
2391 piece_type = piece_type->left;
2393 #if 0
2395 static void name_of(FILE *fp, struct type *type);
2396 FILE * fp = state->errout;
2397 fprintf(fp, "piece_type(%d): ", index);
2398 name_of(fp, piece_type);
2399 fprintf(fp, "\n");
2401 #endif
2402 piece = alloc_triple(state, OP_PIECE, piece_type, -1, -1, ins->occurrence);
2403 piece->u.cval = index;
2404 LHS(ins, piece->u.cval) = piece;
2405 MISC(piece, 0) = ins;
2408 static void generate_lhs_pieces(struct compile_state *state, struct triple *ins)
2410 int i, zlhs;
2411 zlhs = ins->lhs;
2412 for(i = 0; i < zlhs; i++) {
2413 generate_lhs_piece(state, ins, i);
2417 static struct triple *label(struct compile_state *state)
2419 /* Labels don't get a type */
2420 struct triple *result;
2421 result = triple(state, OP_LABEL, &void_type, 0, 0);
2422 return result;
2425 static struct triple *mkprog(struct compile_state *state, ...)
2427 struct triple *prog, *head, *arg;
2428 va_list args;
2429 int i;
2431 head = label(state);
2432 prog = new_triple(state, OP_PROG, &void_type, -1, -1);
2433 RHS(prog, 0) = head;
2434 va_start(args, state);
2435 i = 0;
2436 while((arg = va_arg(args, struct triple *)) != 0) {
2437 if (++i >= 100) {
2438 internal_error(state, 0, "too many arguments to mkprog");
2440 flatten(state, head, arg);
2442 va_end(args);
2443 prog->type = head->prev->type;
2444 return prog;
2446 static void name_of(FILE *fp, struct type *type);
2447 static void display_triple(FILE *fp, struct triple *ins)
2449 struct occurrence *ptr;
2450 const char *reg;
2451 char pre, post, vol;
2452 pre = post = vol = ' ';
2453 if (ins) {
2454 if (ins->id & TRIPLE_FLAG_PRE_SPLIT) {
2455 pre = '^';
2457 if (ins->id & TRIPLE_FLAG_POST_SPLIT) {
2458 post = ',';
2460 if (ins->id & TRIPLE_FLAG_VOLATILE) {
2461 vol = 'v';
2463 reg = arch_reg_str(ID_REG(ins->id));
2465 if (ins == 0) {
2466 fprintf(fp, "(%p) <nothing> ", ins);
2468 else if (ins->op == OP_INTCONST) {
2469 fprintf(fp, "(%p) %c%c%c %-7s %-2d %-10s <0x%08lx> ",
2470 ins, pre, post, vol, reg, ins->template_id, tops(ins->op),
2471 (unsigned long)(ins->u.cval));
2473 else if (ins->op == OP_ADDRCONST) {
2474 fprintf(fp, "(%p) %c%c%c %-7s %-2d %-10s %-10p <0x%08lx>",
2475 ins, pre, post, vol, reg, ins->template_id, tops(ins->op),
2476 MISC(ins, 0), (unsigned long)(ins->u.cval));
2478 else if (ins->op == OP_INDEX) {
2479 fprintf(fp, "(%p) %c%c%c %-7s %-2d %-10s %-10p <0x%08lx>",
2480 ins, pre, post, vol, reg, ins->template_id, tops(ins->op),
2481 RHS(ins, 0), (unsigned long)(ins->u.cval));
2483 else if (ins->op == OP_PIECE) {
2484 fprintf(fp, "(%p) %c%c%c %-7s %-2d %-10s %-10p <0x%08lx>",
2485 ins, pre, post, vol, reg, ins->template_id, tops(ins->op),
2486 MISC(ins, 0), (unsigned long)(ins->u.cval));
2488 else {
2489 int i, count;
2490 fprintf(fp, "(%p) %c%c%c %-7s %-2d %-10s",
2491 ins, pre, post, vol, reg, ins->template_id, tops(ins->op));
2492 if (table_ops[ins->op].flags & BITFIELD) {
2493 fprintf(fp, " <%2d-%2d:%2d>",
2494 ins->u.bitfield.offset,
2495 ins->u.bitfield.offset + ins->u.bitfield.size,
2496 ins->u.bitfield.size);
2498 count = TRIPLE_SIZE(ins);
2499 for(i = 0; i < count; i++) {
2500 fprintf(fp, " %-10p", ins->param[i]);
2502 for(; i < 2; i++) {
2503 fprintf(fp, " ");
2506 if (ins) {
2507 struct triple_set *user;
2508 #if DEBUG_DISPLAY_TYPES
2509 fprintf(fp, " <");
2510 name_of(fp, ins->type);
2511 fprintf(fp, "> ");
2512 #endif
2513 #if DEBUG_DISPLAY_USES
2514 fprintf(fp, " [");
2515 for(user = ins->use; user; user = user->next) {
2516 fprintf(fp, " %-10p", user->member);
2518 fprintf(fp, " ]");
2519 #endif
2520 fprintf(fp, " @");
2521 for(ptr = ins->occurrence; ptr; ptr = ptr->parent) {
2522 fprintf(fp, " %s,%s:%d.%d",
2523 ptr->function,
2524 ptr->filename,
2525 ptr->line,
2526 ptr->col);
2528 if (ins->op == OP_ASM) {
2529 fprintf(fp, "\n\t%s", ins->u.ainfo->str);
2532 fprintf(fp, "\n");
2533 fflush(fp);
2536 static int equiv_types(struct type *left, struct type *right);
2537 static void display_triple_changes(
2538 FILE *fp, const struct triple *new, const struct triple *orig)
2541 int new_count, orig_count;
2542 new_count = TRIPLE_SIZE(new);
2543 orig_count = TRIPLE_SIZE(orig);
2544 if ((new->op != orig->op) ||
2545 (new_count != orig_count) ||
2546 (memcmp(orig->param, new->param,
2547 orig_count * sizeof(orig->param[0])) != 0) ||
2548 (memcmp(&orig->u, &new->u, sizeof(orig->u)) != 0))
2550 struct occurrence *ptr;
2551 int i, min_count, indent;
2552 fprintf(fp, "(%p %p)", new, orig);
2553 if (orig->op == new->op) {
2554 fprintf(fp, " %-11s", tops(orig->op));
2555 } else {
2556 fprintf(fp, " [%-10s %-10s]",
2557 tops(new->op), tops(orig->op));
2559 min_count = new_count;
2560 if (min_count > orig_count) {
2561 min_count = orig_count;
2563 for(indent = i = 0; i < min_count; i++) {
2564 if (orig->param[i] == new->param[i]) {
2565 fprintf(fp, " %-11p",
2566 orig->param[i]);
2567 indent += 12;
2568 } else {
2569 fprintf(fp, " [%-10p %-10p]",
2570 new->param[i],
2571 orig->param[i]);
2572 indent += 24;
2575 for(; i < orig_count; i++) {
2576 fprintf(fp, " [%-9p]", orig->param[i]);
2577 indent += 12;
2579 for(; i < new_count; i++) {
2580 fprintf(fp, " [%-9p]", new->param[i]);
2581 indent += 12;
2583 if ((new->op == OP_INTCONST)||
2584 (new->op == OP_ADDRCONST)) {
2585 fprintf(fp, " <0x%08lx>",
2586 (unsigned long)(new->u.cval));
2587 indent += 13;
2589 for(;indent < 36; indent++) {
2590 putc(' ', fp);
2593 #if DEBUG_DISPLAY_TYPES
2594 fprintf(fp, " <");
2595 name_of(fp, new->type);
2596 if (!equiv_types(new->type, orig->type)) {
2597 fprintf(fp, " -- ");
2598 name_of(fp, orig->type);
2600 fprintf(fp, "> ");
2601 #endif
2603 fprintf(fp, " @");
2604 for(ptr = orig->occurrence; ptr; ptr = ptr->parent) {
2605 fprintf(fp, " %s,%s:%d.%d",
2606 ptr->function,
2607 ptr->filename,
2608 ptr->line,
2609 ptr->col);
2612 fprintf(fp, "\n");
2613 fflush(fp);
2617 static int triple_is_pure(struct compile_state *state, struct triple *ins, unsigned id)
2619 /* Does the triple have no side effects.
2620 * I.e. Rexecuting the triple with the same arguments
2621 * gives the same value.
2623 unsigned pure;
2624 valid_ins(state, ins);
2625 pure = PURE_BITS(table_ops[ins->op].flags);
2626 if ((pure != PURE) && (pure != IMPURE)) {
2627 internal_error(state, 0, "Purity of %s not known",
2628 tops(ins->op));
2630 return (pure == PURE) && !(id & TRIPLE_FLAG_VOLATILE);
2633 static int triple_is_branch_type(struct compile_state *state,
2634 struct triple *ins, unsigned type)
2636 /* Is this one of the passed branch types? */
2637 valid_ins(state, ins);
2638 return (BRANCH_BITS(table_ops[ins->op].flags) == type);
2641 static int triple_is_branch(struct compile_state *state, struct triple *ins)
2643 /* Is this triple a branch instruction? */
2644 valid_ins(state, ins);
2645 return (BRANCH_BITS(table_ops[ins->op].flags) != 0);
2648 static int triple_is_cbranch(struct compile_state *state, struct triple *ins)
2650 /* Is this triple a conditional branch instruction? */
2651 return triple_is_branch_type(state, ins, CBRANCH);
2654 static int triple_is_ubranch(struct compile_state *state, struct triple *ins)
2656 /* Is this triple a unconditional branch instruction? */
2657 unsigned type;
2658 valid_ins(state, ins);
2659 type = BRANCH_BITS(table_ops[ins->op].flags);
2660 return (type != 0) && (type != CBRANCH);
2663 static int triple_is_call(struct compile_state *state, struct triple *ins)
2665 /* Is this triple a call instruction? */
2666 return triple_is_branch_type(state, ins, CALLBRANCH);
2669 static int triple_is_ret(struct compile_state *state, struct triple *ins)
2671 /* Is this triple a return instruction? */
2672 return triple_is_branch_type(state, ins, RETBRANCH);
2675 #if DEBUG_ROMCC_WARNING
2676 static int triple_is_simple_ubranch(struct compile_state *state, struct triple *ins)
2678 /* Is this triple an unconditional branch and not a call or a
2679 * return? */
2680 return triple_is_branch_type(state, ins, UBRANCH);
2682 #endif
2684 static int triple_is_end(struct compile_state *state, struct triple *ins)
2686 return triple_is_branch_type(state, ins, ENDBRANCH);
2689 static int triple_is_label(struct compile_state *state, struct triple *ins)
2691 valid_ins(state, ins);
2692 return (ins->op == OP_LABEL);
2695 static struct triple *triple_to_block_start(
2696 struct compile_state *state, struct triple *start)
2698 while(!triple_is_branch(state, start->prev) &&
2699 (!triple_is_label(state, start) || !start->use)) {
2700 start = start->prev;
2702 return start;
2705 static int triple_is_def(struct compile_state *state, struct triple *ins)
2707 /* This function is used to determine which triples need
2708 * a register.
2710 int is_def;
2711 valid_ins(state, ins);
2712 is_def = (table_ops[ins->op].flags & DEF) == DEF;
2713 if (ins->lhs >= 1) {
2714 is_def = 0;
2716 return is_def;
2719 static int triple_is_structural(struct compile_state *state, struct triple *ins)
2721 int is_structural;
2722 valid_ins(state, ins);
2723 is_structural = (table_ops[ins->op].flags & STRUCTURAL) == STRUCTURAL;
2724 return is_structural;
2727 static int triple_is_part(struct compile_state *state, struct triple *ins)
2729 int is_part;
2730 valid_ins(state, ins);
2731 is_part = (table_ops[ins->op].flags & PART) == PART;
2732 return is_part;
2735 static int triple_is_auto_var(struct compile_state *state, struct triple *ins)
2737 return (ins->op == OP_PIECE) && (MISC(ins, 0)->op == OP_ADECL);
2740 static struct triple **triple_iter(struct compile_state *state,
2741 size_t count, struct triple **vector,
2742 struct triple *ins, struct triple **last)
2744 struct triple **ret;
2745 ret = 0;
2746 if (count) {
2747 if (!last) {
2748 ret = vector;
2750 else if ((last >= vector) && (last < (vector + count - 1))) {
2751 ret = last + 1;
2754 return ret;
2758 static struct triple **triple_lhs(struct compile_state *state,
2759 struct triple *ins, struct triple **last)
2761 return triple_iter(state, ins->lhs, &LHS(ins,0),
2762 ins, last);
2765 static struct triple **triple_rhs(struct compile_state *state,
2766 struct triple *ins, struct triple **last)
2768 return triple_iter(state, ins->rhs, &RHS(ins,0),
2769 ins, last);
2772 static struct triple **triple_misc(struct compile_state *state,
2773 struct triple *ins, struct triple **last)
2775 return triple_iter(state, ins->misc, &MISC(ins,0),
2776 ins, last);
2779 static struct triple **do_triple_targ(struct compile_state *state,
2780 struct triple *ins, struct triple **last, int call_edges, int next_edges)
2782 size_t count;
2783 struct triple **ret, **vector;
2784 int next_is_targ;
2785 ret = 0;
2786 count = ins->targ;
2787 next_is_targ = 0;
2788 if (triple_is_cbranch(state, ins)) {
2789 next_is_targ = 1;
2791 if (!call_edges && triple_is_call(state, ins)) {
2792 count = 0;
2794 if (next_edges && triple_is_call(state, ins)) {
2795 next_is_targ = 1;
2797 vector = &TARG(ins, 0);
2798 if (!ret && next_is_targ) {
2799 if (!last) {
2800 ret = &ins->next;
2801 } else if (last == &ins->next) {
2802 last = 0;
2805 if (!ret && count) {
2806 if (!last) {
2807 ret = vector;
2809 else if ((last >= vector) && (last < (vector + count - 1))) {
2810 ret = last + 1;
2812 else if (last == vector + count - 1) {
2813 last = 0;
2816 if (!ret && triple_is_ret(state, ins) && call_edges) {
2817 struct triple_set *use;
2818 for(use = ins->use; use; use = use->next) {
2819 if (!triple_is_call(state, use->member)) {
2820 continue;
2822 if (!last) {
2823 ret = &use->member->next;
2824 break;
2826 else if (last == &use->member->next) {
2827 last = 0;
2831 return ret;
2834 static struct triple **triple_targ(struct compile_state *state,
2835 struct triple *ins, struct triple **last)
2837 return do_triple_targ(state, ins, last, 1, 1);
2840 static struct triple **triple_edge_targ(struct compile_state *state,
2841 struct triple *ins, struct triple **last)
2843 return do_triple_targ(state, ins, last,
2844 state->functions_joined, !state->functions_joined);
2847 static struct triple *after_lhs(struct compile_state *state, struct triple *ins)
2849 struct triple *next;
2850 int lhs, i;
2851 lhs = ins->lhs;
2852 next = ins->next;
2853 for(i = 0; i < lhs; i++) {
2854 struct triple *piece;
2855 piece = LHS(ins, i);
2856 if (next != piece) {
2857 internal_error(state, ins, "malformed lhs on %s",
2858 tops(ins->op));
2860 if (next->op != OP_PIECE) {
2861 internal_error(state, ins, "bad lhs op %s at %d on %s",
2862 tops(next->op), i, tops(ins->op));
2864 if (next->u.cval != i) {
2865 internal_error(state, ins, "bad u.cval of %d %d expected",
2866 next->u.cval, i);
2868 next = next->next;
2870 return next;
2873 /* Function piece accessor functions */
2874 static struct triple *do_farg(struct compile_state *state,
2875 struct triple *func, unsigned index)
2877 struct type *ftype;
2878 struct triple *first, *arg;
2879 unsigned i;
2881 ftype = func->type;
2882 if(index >= (ftype->elements + 2)) {
2883 internal_error(state, func, "bad argument index: %d", index);
2885 first = RHS(func, 0);
2886 arg = first->next;
2887 for(i = 0; i < index; i++, arg = after_lhs(state, arg)) {
2888 /* do nothing */
2890 if (arg->op != OP_ADECL) {
2891 internal_error(state, 0, "arg not adecl?");
2893 return arg;
2895 static struct triple *fresult(struct compile_state *state, struct triple *func)
2897 return do_farg(state, func, 0);
2899 static struct triple *fretaddr(struct compile_state *state, struct triple *func)
2901 return do_farg(state, func, 1);
2903 static struct triple *farg(struct compile_state *state,
2904 struct triple *func, unsigned index)
2906 return do_farg(state, func, index + 2);
2910 static void display_func(struct compile_state *state, FILE *fp, struct triple *func)
2912 struct triple *first, *ins;
2913 fprintf(fp, "display_func %s\n", func->type->type_ident->name);
2914 first = ins = RHS(func, 0);
2915 do {
2916 if (triple_is_label(state, ins) && ins->use) {
2917 fprintf(fp, "%p:\n", ins);
2919 display_triple(fp, ins);
2921 if (triple_is_branch(state, ins)) {
2922 fprintf(fp, "\n");
2924 if (ins->next->prev != ins) {
2925 internal_error(state, ins->next, "bad prev");
2927 ins = ins->next;
2928 } while(ins != first);
2931 static void verify_use(struct compile_state *state,
2932 struct triple *user, struct triple *used)
2934 int size, i;
2935 size = TRIPLE_SIZE(user);
2936 for(i = 0; i < size; i++) {
2937 if (user->param[i] == used) {
2938 break;
2941 if (triple_is_branch(state, user)) {
2942 if (user->next == used) {
2943 i = -1;
2946 if (i == size) {
2947 internal_error(state, user, "%s(%p) does not use %s(%p)",
2948 tops(user->op), user, tops(used->op), used);
2952 static int find_rhs_use(struct compile_state *state,
2953 struct triple *user, struct triple *used)
2955 struct triple **param;
2956 int size, i;
2957 verify_use(state, user, used);
2959 #if DEBUG_ROMCC_WARNINGS
2960 #warning "AUDIT ME ->rhs"
2961 #endif
2962 size = user->rhs;
2963 param = &RHS(user, 0);
2964 for(i = 0; i < size; i++) {
2965 if (param[i] == used) {
2966 return i;
2969 return -1;
2972 static void free_triple(struct compile_state *state, struct triple *ptr)
2974 size_t size;
2975 size = sizeof(*ptr) - sizeof(ptr->param) +
2976 (sizeof(ptr->param[0])*TRIPLE_SIZE(ptr));
2977 ptr->prev->next = ptr->next;
2978 ptr->next->prev = ptr->prev;
2979 if (ptr->use) {
2980 internal_error(state, ptr, "ptr->use != 0");
2982 put_occurrence(ptr->occurrence);
2983 memset(ptr, -1, size);
2984 xfree(ptr);
2987 static void release_triple(struct compile_state *state, struct triple *ptr)
2989 struct triple_set *set, *next;
2990 struct triple **expr;
2991 struct block *block;
2992 if (ptr == &unknown_triple) {
2993 return;
2995 valid_ins(state, ptr);
2996 /* Make certain the we are not the first or last element of a block */
2997 block = block_of_triple(state, ptr);
2998 if (block) {
2999 if ((block->last == ptr) && (block->first == ptr)) {
3000 block->last = block->first = 0;
3002 else if (block->last == ptr) {
3003 block->last = ptr->prev;
3005 else if (block->first == ptr) {
3006 block->first = ptr->next;
3009 /* Remove ptr from use chains where it is the user */
3010 expr = triple_rhs(state, ptr, 0);
3011 for(; expr; expr = triple_rhs(state, ptr, expr)) {
3012 if (*expr) {
3013 unuse_triple(*expr, ptr);
3016 expr = triple_lhs(state, ptr, 0);
3017 for(; expr; expr = triple_lhs(state, ptr, expr)) {
3018 if (*expr) {
3019 unuse_triple(*expr, ptr);
3022 expr = triple_misc(state, ptr, 0);
3023 for(; expr; expr = triple_misc(state, ptr, expr)) {
3024 if (*expr) {
3025 unuse_triple(*expr, ptr);
3028 expr = triple_targ(state, ptr, 0);
3029 for(; expr; expr = triple_targ(state, ptr, expr)) {
3030 if (*expr){
3031 unuse_triple(*expr, ptr);
3034 /* Reomve ptr from use chains where it is used */
3035 for(set = ptr->use; set; set = next) {
3036 next = set->next;
3037 valid_ins(state, set->member);
3038 expr = triple_rhs(state, set->member, 0);
3039 for(; expr; expr = triple_rhs(state, set->member, expr)) {
3040 if (*expr == ptr) {
3041 *expr = &unknown_triple;
3044 expr = triple_lhs(state, set->member, 0);
3045 for(; expr; expr = triple_lhs(state, set->member, expr)) {
3046 if (*expr == ptr) {
3047 *expr = &unknown_triple;
3050 expr = triple_misc(state, set->member, 0);
3051 for(; expr; expr = triple_misc(state, set->member, expr)) {
3052 if (*expr == ptr) {
3053 *expr = &unknown_triple;
3056 expr = triple_targ(state, set->member, 0);
3057 for(; expr; expr = triple_targ(state, set->member, expr)) {
3058 if (*expr == ptr) {
3059 *expr = &unknown_triple;
3062 unuse_triple(ptr, set->member);
3064 free_triple(state, ptr);
3067 static void print_triples(struct compile_state *state);
3068 static void print_blocks(struct compile_state *state, const char *func, FILE *fp);
3070 #define TOK_UNKNOWN 0
3071 #define TOK_SPACE 1
3072 #define TOK_SEMI 2
3073 #define TOK_LBRACE 3
3074 #define TOK_RBRACE 4
3075 #define TOK_COMMA 5
3076 #define TOK_EQ 6
3077 #define TOK_COLON 7
3078 #define TOK_LBRACKET 8
3079 #define TOK_RBRACKET 9
3080 #define TOK_LPAREN 10
3081 #define TOK_RPAREN 11
3082 #define TOK_STAR 12
3083 #define TOK_DOTS 13
3084 #define TOK_MORE 14
3085 #define TOK_LESS 15
3086 #define TOK_TIMESEQ 16
3087 #define TOK_DIVEQ 17
3088 #define TOK_MODEQ 18
3089 #define TOK_PLUSEQ 19
3090 #define TOK_MINUSEQ 20
3091 #define TOK_SLEQ 21
3092 #define TOK_SREQ 22
3093 #define TOK_ANDEQ 23
3094 #define TOK_XOREQ 24
3095 #define TOK_OREQ 25
3096 #define TOK_EQEQ 26
3097 #define TOK_NOTEQ 27
3098 #define TOK_QUEST 28
3099 #define TOK_LOGOR 29
3100 #define TOK_LOGAND 30
3101 #define TOK_OR 31
3102 #define TOK_AND 32
3103 #define TOK_XOR 33
3104 #define TOK_LESSEQ 34
3105 #define TOK_MOREEQ 35
3106 #define TOK_SL 36
3107 #define TOK_SR 37
3108 #define TOK_PLUS 38
3109 #define TOK_MINUS 39
3110 #define TOK_DIV 40
3111 #define TOK_MOD 41
3112 #define TOK_PLUSPLUS 42
3113 #define TOK_MINUSMINUS 43
3114 #define TOK_BANG 44
3115 #define TOK_ARROW 45
3116 #define TOK_DOT 46
3117 #define TOK_TILDE 47
3118 #define TOK_LIT_STRING 48
3119 #define TOK_LIT_CHAR 49
3120 #define TOK_LIT_INT 50
3121 #define TOK_LIT_FLOAT 51
3122 #define TOK_MACRO 52
3123 #define TOK_CONCATENATE 53
3125 #define TOK_IDENT 54
3126 #define TOK_STRUCT_NAME 55
3127 #define TOK_ENUM_CONST 56
3128 #define TOK_TYPE_NAME 57
3130 #define TOK_AUTO 58
3131 #define TOK_BREAK 59
3132 #define TOK_CASE 60
3133 #define TOK_CHAR 61
3134 #define TOK_CONST 62
3135 #define TOK_CONTINUE 63
3136 #define TOK_DEFAULT 64
3137 #define TOK_DO 65
3138 #define TOK_DOUBLE 66
3139 #define TOK_ELSE 67
3140 #define TOK_ENUM 68
3141 #define TOK_EXTERN 69
3142 #define TOK_FLOAT 70
3143 #define TOK_FOR 71
3144 #define TOK_GOTO 72
3145 #define TOK_IF 73
3146 #define TOK_INLINE 74
3147 #define TOK_INT 75
3148 #define TOK_LONG 76
3149 #define TOK_REGISTER 77
3150 #define TOK_RESTRICT 78
3151 #define TOK_RETURN 79
3152 #define TOK_SHORT 80
3153 #define TOK_SIGNED 81
3154 #define TOK_SIZEOF 82
3155 #define TOK_STATIC 83
3156 #define TOK_STRUCT 84
3157 #define TOK_SWITCH 85
3158 #define TOK_TYPEDEF 86
3159 #define TOK_UNION 87
3160 #define TOK_UNSIGNED 88
3161 #define TOK_VOID 89
3162 #define TOK_VOLATILE 90
3163 #define TOK_WHILE 91
3164 #define TOK_ASM 92
3165 #define TOK_ATTRIBUTE 93
3166 #define TOK_ALIGNOF 94
3167 #define TOK_FIRST_KEYWORD TOK_AUTO
3168 #define TOK_LAST_KEYWORD TOK_ALIGNOF
3170 #define TOK_MDEFINE 100
3171 #define TOK_MDEFINED 101
3172 #define TOK_MUNDEF 102
3173 #define TOK_MINCLUDE 103
3174 #define TOK_MLINE 104
3175 #define TOK_MERROR 105
3176 #define TOK_MWARNING 106
3177 #define TOK_MPRAGMA 107
3178 #define TOK_MIFDEF 108
3179 #define TOK_MIFNDEF 109
3180 #define TOK_MELIF 110
3181 #define TOK_MENDIF 111
3183 #define TOK_FIRST_MACRO TOK_MDEFINE
3184 #define TOK_LAST_MACRO TOK_MENDIF
3186 #define TOK_MIF 112
3187 #define TOK_MELSE 113
3188 #define TOK_MIDENT 114
3190 #define TOK_EOL 115
3191 #define TOK_EOF 116
3193 static const char *tokens[] = {
3194 [TOK_UNKNOWN ] = ":unknown:",
3195 [TOK_SPACE ] = ":space:",
3196 [TOK_SEMI ] = ";",
3197 [TOK_LBRACE ] = "{",
3198 [TOK_RBRACE ] = "}",
3199 [TOK_COMMA ] = ",",
3200 [TOK_EQ ] = "=",
3201 [TOK_COLON ] = ":",
3202 [TOK_LBRACKET ] = "[",
3203 [TOK_RBRACKET ] = "]",
3204 [TOK_LPAREN ] = "(",
3205 [TOK_RPAREN ] = ")",
3206 [TOK_STAR ] = "*",
3207 [TOK_DOTS ] = "...",
3208 [TOK_MORE ] = ">",
3209 [TOK_LESS ] = "<",
3210 [TOK_TIMESEQ ] = "*=",
3211 [TOK_DIVEQ ] = "/=",
3212 [TOK_MODEQ ] = "%=",
3213 [TOK_PLUSEQ ] = "+=",
3214 [TOK_MINUSEQ ] = "-=",
3215 [TOK_SLEQ ] = "<<=",
3216 [TOK_SREQ ] = ">>=",
3217 [TOK_ANDEQ ] = "&=",
3218 [TOK_XOREQ ] = "^=",
3219 [TOK_OREQ ] = "|=",
3220 [TOK_EQEQ ] = "==",
3221 [TOK_NOTEQ ] = "!=",
3222 [TOK_QUEST ] = "?",
3223 [TOK_LOGOR ] = "||",
3224 [TOK_LOGAND ] = "&&",
3225 [TOK_OR ] = "|",
3226 [TOK_AND ] = "&",
3227 [TOK_XOR ] = "^",
3228 [TOK_LESSEQ ] = "<=",
3229 [TOK_MOREEQ ] = ">=",
3230 [TOK_SL ] = "<<",
3231 [TOK_SR ] = ">>",
3232 [TOK_PLUS ] = "+",
3233 [TOK_MINUS ] = "-",
3234 [TOK_DIV ] = "/",
3235 [TOK_MOD ] = "%",
3236 [TOK_PLUSPLUS ] = "++",
3237 [TOK_MINUSMINUS ] = "--",
3238 [TOK_BANG ] = "!",
3239 [TOK_ARROW ] = "->",
3240 [TOK_DOT ] = ".",
3241 [TOK_TILDE ] = "~",
3242 [TOK_LIT_STRING ] = ":string:",
3243 [TOK_IDENT ] = ":ident:",
3244 [TOK_TYPE_NAME ] = ":typename:",
3245 [TOK_LIT_CHAR ] = ":char:",
3246 [TOK_LIT_INT ] = ":integer:",
3247 [TOK_LIT_FLOAT ] = ":float:",
3248 [TOK_MACRO ] = "#",
3249 [TOK_CONCATENATE ] = "##",
3251 [TOK_AUTO ] = "auto",
3252 [TOK_BREAK ] = "break",
3253 [TOK_CASE ] = "case",
3254 [TOK_CHAR ] = "char",
3255 [TOK_CONST ] = "const",
3256 [TOK_CONTINUE ] = "continue",
3257 [TOK_DEFAULT ] = "default",
3258 [TOK_DO ] = "do",
3259 [TOK_DOUBLE ] = "double",
3260 [TOK_ELSE ] = "else",
3261 [TOK_ENUM ] = "enum",
3262 [TOK_EXTERN ] = "extern",
3263 [TOK_FLOAT ] = "float",
3264 [TOK_FOR ] = "for",
3265 [TOK_GOTO ] = "goto",
3266 [TOK_IF ] = "if",
3267 [TOK_INLINE ] = "inline",
3268 [TOK_INT ] = "int",
3269 [TOK_LONG ] = "long",
3270 [TOK_REGISTER ] = "register",
3271 [TOK_RESTRICT ] = "restrict",
3272 [TOK_RETURN ] = "return",
3273 [TOK_SHORT ] = "short",
3274 [TOK_SIGNED ] = "signed",
3275 [TOK_SIZEOF ] = "sizeof",
3276 [TOK_STATIC ] = "static",
3277 [TOK_STRUCT ] = "struct",
3278 [TOK_SWITCH ] = "switch",
3279 [TOK_TYPEDEF ] = "typedef",
3280 [TOK_UNION ] = "union",
3281 [TOK_UNSIGNED ] = "unsigned",
3282 [TOK_VOID ] = "void",
3283 [TOK_VOLATILE ] = "volatile",
3284 [TOK_WHILE ] = "while",
3285 [TOK_ASM ] = "asm",
3286 [TOK_ATTRIBUTE ] = "__attribute__",
3287 [TOK_ALIGNOF ] = "__alignof__",
3289 [TOK_MDEFINE ] = "#define",
3290 [TOK_MDEFINED ] = "#defined",
3291 [TOK_MUNDEF ] = "#undef",
3292 [TOK_MINCLUDE ] = "#include",
3293 [TOK_MLINE ] = "#line",
3294 [TOK_MERROR ] = "#error",
3295 [TOK_MWARNING ] = "#warning",
3296 [TOK_MPRAGMA ] = "#pragma",
3297 [TOK_MIFDEF ] = "#ifdef",
3298 [TOK_MIFNDEF ] = "#ifndef",
3299 [TOK_MELIF ] = "#elif",
3300 [TOK_MENDIF ] = "#endif",
3302 [TOK_MIF ] = "#if",
3303 [TOK_MELSE ] = "#else",
3304 [TOK_MIDENT ] = "#:ident:",
3305 [TOK_EOL ] = "EOL",
3306 [TOK_EOF ] = "EOF",
3309 static unsigned int hash(const char *str, int str_len)
3311 unsigned int hash;
3312 const char *end;
3313 end = str + str_len;
3314 hash = 0;
3315 for(; str < end; str++) {
3316 hash = (hash *263) + *str;
3318 hash = hash & (HASH_TABLE_SIZE -1);
3319 return hash;
3322 static struct hash_entry *lookup(
3323 struct compile_state *state, const char *name, int name_len)
3325 struct hash_entry *entry;
3326 unsigned int index;
3327 index = hash(name, name_len);
3328 entry = state->hash_table[index];
3329 while(entry &&
3330 ((entry->name_len != name_len) ||
3331 (memcmp(entry->name, name, name_len) != 0))) {
3332 entry = entry->next;
3334 if (!entry) {
3335 char *new_name;
3336 /* Get a private copy of the name */
3337 new_name = xmalloc(name_len + 1, "hash_name");
3338 memcpy(new_name, name, name_len);
3339 new_name[name_len] = '\0';
3341 /* Create a new hash entry */
3342 entry = xcmalloc(sizeof(*entry), "hash_entry");
3343 entry->next = state->hash_table[index];
3344 entry->name = new_name;
3345 entry->name_len = name_len;
3347 /* Place the new entry in the hash table */
3348 state->hash_table[index] = entry;
3350 return entry;
3353 static void ident_to_keyword(struct compile_state *state, struct token *tk)
3355 struct hash_entry *entry;
3356 entry = tk->ident;
3357 if (entry && ((entry->tok == TOK_TYPE_NAME) ||
3358 (entry->tok == TOK_ENUM_CONST) ||
3359 ((entry->tok >= TOK_FIRST_KEYWORD) &&
3360 (entry->tok <= TOK_LAST_KEYWORD)))) {
3361 tk->tok = entry->tok;
3365 static void ident_to_macro(struct compile_state *state, struct token *tk)
3367 struct hash_entry *entry;
3368 entry = tk->ident;
3369 if (!entry)
3370 return;
3371 if ((entry->tok >= TOK_FIRST_MACRO) && (entry->tok <= TOK_LAST_MACRO)) {
3372 tk->tok = entry->tok;
3374 else if (entry->tok == TOK_IF) {
3375 tk->tok = TOK_MIF;
3377 else if (entry->tok == TOK_ELSE) {
3378 tk->tok = TOK_MELSE;
3380 else {
3381 tk->tok = TOK_MIDENT;
3385 static void hash_keyword(
3386 struct compile_state *state, const char *keyword, int tok)
3388 struct hash_entry *entry;
3389 entry = lookup(state, keyword, strlen(keyword));
3390 if (entry && entry->tok != TOK_UNKNOWN) {
3391 die("keyword %s already hashed", keyword);
3393 entry->tok = tok;
3396 static void romcc_symbol(
3397 struct compile_state *state, struct hash_entry *ident,
3398 struct symbol **chain, struct triple *def, struct type *type, int depth)
3400 struct symbol *sym;
3401 if (*chain && ((*chain)->scope_depth >= depth)) {
3402 error(state, 0, "%s already defined", ident->name);
3404 sym = xcmalloc(sizeof(*sym), "symbol");
3405 sym->ident = ident;
3406 sym->def = def;
3407 sym->type = type;
3408 sym->scope_depth = depth;
3409 sym->next = *chain;
3410 *chain = sym;
3413 static void symbol(
3414 struct compile_state *state, struct hash_entry *ident,
3415 struct symbol **chain, struct triple *def, struct type *type)
3417 romcc_symbol(state, ident, chain, def, type, state->scope_depth);
3420 static void var_symbol(struct compile_state *state,
3421 struct hash_entry *ident, struct triple *def)
3423 if ((def->type->type & TYPE_MASK) == TYPE_PRODUCT) {
3424 internal_error(state, 0, "bad var type");
3426 symbol(state, ident, &ident->sym_ident, def, def->type);
3429 static void label_symbol(struct compile_state *state,
3430 struct hash_entry *ident, struct triple *label, int depth)
3432 romcc_symbol(state, ident, &ident->sym_label, label, &void_type, depth);
3435 static void start_scope(struct compile_state *state)
3437 state->scope_depth++;
3440 static void end_scope_syms(struct compile_state *state,
3441 struct symbol **chain, int depth)
3443 struct symbol *sym, *next;
3444 sym = *chain;
3445 while(sym && (sym->scope_depth == depth)) {
3446 next = sym->next;
3447 xfree(sym);
3448 sym = next;
3450 *chain = sym;
3453 static void end_scope(struct compile_state *state)
3455 int i;
3456 int depth;
3457 /* Walk through the hash table and remove all symbols
3458 * in the current scope.
3460 depth = state->scope_depth;
3461 for(i = 0; i < HASH_TABLE_SIZE; i++) {
3462 struct hash_entry *entry;
3463 entry = state->hash_table[i];
3464 while(entry) {
3465 end_scope_syms(state, &entry->sym_label, depth);
3466 end_scope_syms(state, &entry->sym_tag, depth);
3467 end_scope_syms(state, &entry->sym_ident, depth);
3468 entry = entry->next;
3471 state->scope_depth = depth - 1;
3474 static void register_keywords(struct compile_state *state)
3476 hash_keyword(state, "auto", TOK_AUTO);
3477 hash_keyword(state, "break", TOK_BREAK);
3478 hash_keyword(state, "case", TOK_CASE);
3479 hash_keyword(state, "char", TOK_CHAR);
3480 hash_keyword(state, "const", TOK_CONST);
3481 hash_keyword(state, "continue", TOK_CONTINUE);
3482 hash_keyword(state, "default", TOK_DEFAULT);
3483 hash_keyword(state, "do", TOK_DO);
3484 hash_keyword(state, "double", TOK_DOUBLE);
3485 hash_keyword(state, "else", TOK_ELSE);
3486 hash_keyword(state, "enum", TOK_ENUM);
3487 hash_keyword(state, "extern", TOK_EXTERN);
3488 hash_keyword(state, "float", TOK_FLOAT);
3489 hash_keyword(state, "for", TOK_FOR);
3490 hash_keyword(state, "goto", TOK_GOTO);
3491 hash_keyword(state, "if", TOK_IF);
3492 hash_keyword(state, "inline", TOK_INLINE);
3493 hash_keyword(state, "int", TOK_INT);
3494 hash_keyword(state, "long", TOK_LONG);
3495 hash_keyword(state, "register", TOK_REGISTER);
3496 hash_keyword(state, "restrict", TOK_RESTRICT);
3497 hash_keyword(state, "return", TOK_RETURN);
3498 hash_keyword(state, "short", TOK_SHORT);
3499 hash_keyword(state, "signed", TOK_SIGNED);
3500 hash_keyword(state, "sizeof", TOK_SIZEOF);
3501 hash_keyword(state, "static", TOK_STATIC);
3502 hash_keyword(state, "struct", TOK_STRUCT);
3503 hash_keyword(state, "switch", TOK_SWITCH);
3504 hash_keyword(state, "typedef", TOK_TYPEDEF);
3505 hash_keyword(state, "union", TOK_UNION);
3506 hash_keyword(state, "unsigned", TOK_UNSIGNED);
3507 hash_keyword(state, "void", TOK_VOID);
3508 hash_keyword(state, "volatile", TOK_VOLATILE);
3509 hash_keyword(state, "__volatile__", TOK_VOLATILE);
3510 hash_keyword(state, "while", TOK_WHILE);
3511 hash_keyword(state, "asm", TOK_ASM);
3512 hash_keyword(state, "__asm__", TOK_ASM);
3513 hash_keyword(state, "__attribute__", TOK_ATTRIBUTE);
3514 hash_keyword(state, "__alignof__", TOK_ALIGNOF);
3517 static void register_macro_keywords(struct compile_state *state)
3519 hash_keyword(state, "define", TOK_MDEFINE);
3520 hash_keyword(state, "defined", TOK_MDEFINED);
3521 hash_keyword(state, "undef", TOK_MUNDEF);
3522 hash_keyword(state, "include", TOK_MINCLUDE);
3523 hash_keyword(state, "line", TOK_MLINE);
3524 hash_keyword(state, "error", TOK_MERROR);
3525 hash_keyword(state, "warning", TOK_MWARNING);
3526 hash_keyword(state, "pragma", TOK_MPRAGMA);
3527 hash_keyword(state, "ifdef", TOK_MIFDEF);
3528 hash_keyword(state, "ifndef", TOK_MIFNDEF);
3529 hash_keyword(state, "elif", TOK_MELIF);
3530 hash_keyword(state, "endif", TOK_MENDIF);
3534 static void undef_macro(struct compile_state *state, struct hash_entry *ident)
3536 if (ident->sym_define != 0) {
3537 struct macro *macro;
3538 struct macro_arg *arg, *anext;
3539 macro = ident->sym_define;
3540 ident->sym_define = 0;
3542 /* Free the macro arguments... */
3543 anext = macro->args;
3544 while(anext) {
3545 arg = anext;
3546 anext = arg->next;
3547 xfree(arg);
3550 /* Free the macro buffer */
3551 xfree(macro->buf);
3553 /* Now free the macro itself */
3554 xfree(macro);
3558 static void do_define_macro(struct compile_state *state,
3559 struct hash_entry *ident, const char *body,
3560 int argc, struct macro_arg *args)
3562 struct macro *macro;
3563 struct macro_arg *arg;
3564 size_t body_len;
3566 /* Find the length of the body */
3567 body_len = strlen(body);
3568 macro = ident->sym_define;
3569 if (macro != 0) {
3570 int identical_bodies, identical_args;
3571 struct macro_arg *oarg;
3572 /* Explicitly allow identical redfinitions of the same macro */
3573 identical_bodies =
3574 (macro->buf_len == body_len) &&
3575 (memcmp(macro->buf, body, body_len) == 0);
3576 identical_args = macro->argc == argc;
3577 oarg = macro->args;
3578 arg = args;
3579 while(identical_args && arg) {
3580 identical_args = oarg->ident == arg->ident;
3581 arg = arg->next;
3582 oarg = oarg->next;
3584 if (identical_bodies && identical_args) {
3585 xfree(body);
3586 return;
3588 error(state, 0, "macro %s already defined\n", ident->name);
3590 #if 0
3591 fprintf(state->errout, "#define %s: `%*.*s'\n",
3592 ident->name, body_len, body_len, body);
3593 #endif
3594 macro = xmalloc(sizeof(*macro), "macro");
3595 macro->ident = ident;
3596 macro->buf = body;
3597 macro->buf_len = body_len;
3598 macro->args = args;
3599 macro->argc = argc;
3601 ident->sym_define = macro;
3604 static void define_macro(
3605 struct compile_state *state,
3606 struct hash_entry *ident,
3607 const char *body, int body_len,
3608 int argc, struct macro_arg *args)
3610 char *buf;
3611 buf = xmalloc(body_len + 1, "macro buf");
3612 memcpy(buf, body, body_len);
3613 buf[body_len] = '\0';
3614 do_define_macro(state, ident, buf, argc, args);
3617 static void register_builtin_macro(struct compile_state *state,
3618 const char *name, const char *value)
3620 struct hash_entry *ident;
3622 if (value[0] == '(') {
3623 internal_error(state, 0, "Builtin macros with arguments not supported");
3625 ident = lookup(state, name, strlen(name));
3626 define_macro(state, ident, value, strlen(value), -1, 0);
3629 static void register_builtin_macros(struct compile_state *state)
3631 char buf[32];
3632 char scratch[30];
3633 time_t now;
3634 struct tm *tm;
3635 now = time(NULL);
3636 tm = localtime(&now);
3638 register_builtin_macro(state, "__ROMCC__", VERSION_MAJOR);
3639 register_builtin_macro(state, "__ROMCC_MINOR__", VERSION_MINOR);
3640 register_builtin_macro(state, "__FILE__", "\"This should be the filename\"");
3641 register_builtin_macro(state, "__LINE__", "54321");
3643 strftime(scratch, sizeof(scratch), "%b %e %Y", tm);
3644 sprintf(buf, "\"%s\"", scratch);
3645 register_builtin_macro(state, "__DATE__", buf);
3647 strftime(scratch, sizeof(scratch), "%H:%M:%S", tm);
3648 sprintf(buf, "\"%s\"", scratch);
3649 register_builtin_macro(state, "__TIME__", buf);
3651 /* I can't be a conforming implementation of C :( */
3652 register_builtin_macro(state, "__STDC__", "0");
3653 /* In particular I don't conform to C99 */
3654 register_builtin_macro(state, "__STDC_VERSION__", "199901L");
3658 static void process_cmdline_macros(struct compile_state *state)
3660 const char **macro, *name;
3661 struct hash_entry *ident;
3662 for(macro = state->compiler->defines; (name = *macro); macro++) {
3663 const char *body;
3664 size_t name_len;
3666 name_len = strlen(name);
3667 body = strchr(name, '=');
3668 if (!body) {
3669 body = "\0";
3670 } else {
3671 name_len = body - name;
3672 body++;
3674 ident = lookup(state, name, name_len);
3675 define_macro(state, ident, body, strlen(body), -1, 0);
3677 for(macro = state->compiler->undefs; (name = *macro); macro++) {
3678 ident = lookup(state, name, strlen(name));
3679 undef_macro(state, ident);
3683 static int spacep(int c)
3685 int ret = 0;
3686 switch(c) {
3687 case ' ':
3688 case '\t':
3689 case '\f':
3690 case '\v':
3691 case '\r':
3692 ret = 1;
3693 break;
3695 return ret;
3698 static int digitp(int c)
3700 int ret = 0;
3701 switch(c) {
3702 case '0': case '1': case '2': case '3': case '4':
3703 case '5': case '6': case '7': case '8': case '9':
3704 ret = 1;
3705 break;
3707 return ret;
3709 static int digval(int c)
3711 int val = -1;
3712 if ((c >= '0') && (c <= '9')) {
3713 val = c - '0';
3715 return val;
3718 static int hexdigitp(int c)
3720 int ret = 0;
3721 switch(c) {
3722 case '0': case '1': case '2': case '3': case '4':
3723 case '5': case '6': case '7': case '8': case '9':
3724 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
3725 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
3726 ret = 1;
3727 break;
3729 return ret;
3731 static int hexdigval(int c)
3733 int val = -1;
3734 if ((c >= '0') && (c <= '9')) {
3735 val = c - '0';
3737 else if ((c >= 'A') && (c <= 'F')) {
3738 val = 10 + (c - 'A');
3740 else if ((c >= 'a') && (c <= 'f')) {
3741 val = 10 + (c - 'a');
3743 return val;
3746 static int octdigitp(int c)
3748 int ret = 0;
3749 switch(c) {
3750 case '0': case '1': case '2': case '3':
3751 case '4': case '5': case '6': case '7':
3752 ret = 1;
3753 break;
3755 return ret;
3757 static int octdigval(int c)
3759 int val = -1;
3760 if ((c >= '0') && (c <= '7')) {
3761 val = c - '0';
3763 return val;
3766 static int letterp(int c)
3768 int ret = 0;
3769 switch(c) {
3770 case 'a': case 'b': case 'c': case 'd': case 'e':
3771 case 'f': case 'g': case 'h': case 'i': case 'j':
3772 case 'k': case 'l': case 'm': case 'n': case 'o':
3773 case 'p': case 'q': case 'r': case 's': case 't':
3774 case 'u': case 'v': case 'w': case 'x': case 'y':
3775 case 'z':
3776 case 'A': case 'B': case 'C': case 'D': case 'E':
3777 case 'F': case 'G': case 'H': case 'I': case 'J':
3778 case 'K': case 'L': case 'M': case 'N': case 'O':
3779 case 'P': case 'Q': case 'R': case 'S': case 'T':
3780 case 'U': case 'V': case 'W': case 'X': case 'Y':
3781 case 'Z':
3782 case '_':
3783 ret = 1;
3784 break;
3786 return ret;
3789 static const char *identifier(const char *str, const char *end)
3791 if (letterp(*str)) {
3792 for(; str < end; str++) {
3793 int c;
3794 c = *str;
3795 if (!letterp(c) && !digitp(c)) {
3796 break;
3800 return str;
3803 static int char_value(struct compile_state *state,
3804 const signed char **strp, const signed char *end)
3806 const signed char *str;
3807 int c;
3808 str = *strp;
3809 c = *str++;
3810 if ((c == '\\') && (str < end)) {
3811 switch(*str) {
3812 case 'n': c = '\n'; str++; break;
3813 case 't': c = '\t'; str++; break;
3814 case 'v': c = '\v'; str++; break;
3815 case 'b': c = '\b'; str++; break;
3816 case 'r': c = '\r'; str++; break;
3817 case 'f': c = '\f'; str++; break;
3818 case 'a': c = '\a'; str++; break;
3819 case '\\': c = '\\'; str++; break;
3820 case '?': c = '?'; str++; break;
3821 case '\'': c = '\''; str++; break;
3822 case '"': c = '"'; str++; break;
3823 case 'x':
3824 c = 0;
3825 str++;
3826 while((str < end) && hexdigitp(*str)) {
3827 c <<= 4;
3828 c += hexdigval(*str);
3829 str++;
3831 break;
3832 case '0': case '1': case '2': case '3':
3833 case '4': case '5': case '6': case '7':
3834 c = 0;
3835 while((str < end) && octdigitp(*str)) {
3836 c <<= 3;
3837 c += octdigval(*str);
3838 str++;
3840 break;
3841 default:
3842 error(state, 0, "Invalid character constant");
3843 break;
3846 *strp = str;
3847 return c;
3850 static const char *next_char(struct file_state *file, const char *pos, int index)
3852 const char *end = file->buf + file->size;
3853 while(pos < end) {
3854 /* Lookup the character */
3855 int size = 1;
3856 int c = *pos;
3857 /* Is this a trigraph? */
3858 if (file->trigraphs &&
3859 (c == '?') && ((end - pos) >= 3) && (pos[1] == '?'))
3861 switch(pos[2]) {
3862 case '=': c = '#'; break;
3863 case '/': c = '\\'; break;
3864 case '\'': c = '^'; break;
3865 case '(': c = '['; break;
3866 case ')': c = ']'; break;
3867 case '!': c = '!'; break;
3868 case '<': c = '{'; break;
3869 case '>': c = '}'; break;
3870 case '-': c = '~'; break;
3872 if (c != '?') {
3873 size = 3;
3876 /* Is this an escaped newline? */
3877 if (file->join_lines &&
3878 (c == '\\') && (pos + size < end) && ((pos[1] == '\n') || ((pos[1] == '\r') && (pos[2] == '\n'))))
3880 int cr_offset = ((pos[1] == '\r') && (pos[2] == '\n'))?1:0;
3881 /* At the start of a line just eat it */
3882 if (pos == file->pos) {
3883 file->line++;
3884 file->report_line++;
3885 file->line_start = pos + size + 1 + cr_offset;
3887 pos += size + 1 + cr_offset;
3889 /* Do I need to ga any farther? */
3890 else if (index == 0) {
3891 break;
3893 /* Process a normal character */
3894 else {
3895 pos += size;
3896 index -= 1;
3899 return pos;
3902 static int get_char(struct file_state *file, const char *pos)
3904 const char *end = file->buf + file->size;
3905 int c;
3906 c = -1;
3907 pos = next_char(file, pos, 0);
3908 if (pos < end) {
3909 /* Lookup the character */
3910 c = *pos;
3911 /* If it is a trigraph get the trigraph value */
3912 if (file->trigraphs &&
3913 (c == '?') && ((end - pos) >= 3) && (pos[1] == '?'))
3915 switch(pos[2]) {
3916 case '=': c = '#'; break;
3917 case '/': c = '\\'; break;
3918 case '\'': c = '^'; break;
3919 case '(': c = '['; break;
3920 case ')': c = ']'; break;
3921 case '!': c = '!'; break;
3922 case '<': c = '{'; break;
3923 case '>': c = '}'; break;
3924 case '-': c = '~'; break;
3928 return c;
3931 static void eat_chars(struct file_state *file, const char *targ)
3933 const char *pos = file->pos;
3934 while(pos < targ) {
3935 /* Do we have a newline? */
3936 if (pos[0] == '\n') {
3937 file->line++;
3938 file->report_line++;
3939 file->line_start = pos + 1;
3941 pos++;
3943 file->pos = pos;
3947 static size_t char_strlen(struct file_state *file, const char *src, const char *end)
3949 size_t len;
3950 len = 0;
3951 while(src < end) {
3952 src = next_char(file, src, 1);
3953 len++;
3955 return len;
3958 static void char_strcpy(char *dest,
3959 struct file_state *file, const char *src, const char *end)
3961 while(src < end) {
3962 int c;
3963 c = get_char(file, src);
3964 src = next_char(file, src, 1);
3965 *dest++ = c;
3969 static char *char_strdup(struct file_state *file,
3970 const char *start, const char *end, const char *id)
3972 char *str;
3973 size_t str_len;
3974 str_len = char_strlen(file, start, end);
3975 str = xcmalloc(str_len + 1, id);
3976 char_strcpy(str, file, start, end);
3977 str[str_len] = '\0';
3978 return str;
3981 static const char *after_digits(struct file_state *file, const char *ptr)
3983 while(digitp(get_char(file, ptr))) {
3984 ptr = next_char(file, ptr, 1);
3986 return ptr;
3989 static const char *after_octdigits(struct file_state *file, const char *ptr)
3991 while(octdigitp(get_char(file, ptr))) {
3992 ptr = next_char(file, ptr, 1);
3994 return ptr;
3997 static const char *after_hexdigits(struct file_state *file, const char *ptr)
3999 while(hexdigitp(get_char(file, ptr))) {
4000 ptr = next_char(file, ptr, 1);
4002 return ptr;
4005 static const char *after_alnums(struct file_state *file, const char *ptr)
4007 int c;
4008 c = get_char(file, ptr);
4009 while(letterp(c) || digitp(c)) {
4010 ptr = next_char(file, ptr, 1);
4011 c = get_char(file, ptr);
4013 return ptr;
4016 static void save_string(struct file_state *file,
4017 struct token *tk, const char *start, const char *end, const char *id)
4019 char *str;
4021 /* Create a private copy of the string */
4022 str = char_strdup(file, start, end, id);
4024 /* Store the copy in the token */
4025 tk->val.str = str;
4026 tk->str_len = strlen(str);
4029 static void raw_next_token(struct compile_state *state,
4030 struct file_state *file, struct token *tk)
4032 const char *token;
4033 int c, c1, c2, c3;
4034 const char *tokp;
4035 int eat;
4036 int tok;
4038 tk->str_len = 0;
4039 tk->ident = 0;
4040 token = tokp = next_char(file, file->pos, 0);
4041 tok = TOK_UNKNOWN;
4042 c = get_char(file, tokp);
4043 tokp = next_char(file, tokp, 1);
4044 eat = 0;
4045 c1 = get_char(file, tokp);
4046 c2 = get_char(file, next_char(file, tokp, 1));
4047 c3 = get_char(file, next_char(file, tokp, 2));
4049 /* The end of the file */
4050 if (c == -1) {
4051 tok = TOK_EOF;
4053 /* Whitespace */
4054 else if (spacep(c)) {
4055 tok = TOK_SPACE;
4056 while (spacep(get_char(file, tokp))) {
4057 tokp = next_char(file, tokp, 1);
4060 /* EOL Comments */
4061 else if ((c == '/') && (c1 == '/')) {
4062 tok = TOK_SPACE;
4063 tokp = next_char(file, tokp, 1);
4064 while((c = get_char(file, tokp)) != -1) {
4065 /* Advance to the next character only after we verify
4066 * the current character is not a newline.
4067 * EOL is special to the preprocessor so we don't
4068 * want to loose any.
4070 if (c == '\n') {
4071 break;
4073 tokp = next_char(file, tokp, 1);
4076 /* Comments */
4077 else if ((c == '/') && (c1 == '*')) {
4078 tokp = next_char(file, tokp, 2);
4079 c = c2;
4080 while((c1 = get_char(file, tokp)) != -1) {
4081 tokp = next_char(file, tokp, 1);
4082 if ((c == '*') && (c1 == '/')) {
4083 tok = TOK_SPACE;
4084 break;
4086 c = c1;
4088 if (tok == TOK_UNKNOWN) {
4089 error(state, 0, "unterminated comment");
4092 /* string constants */
4093 else if ((c == '"') || ((c == 'L') && (c1 == '"'))) {
4094 int multiline;
4096 multiline = 0;
4097 if (c == 'L') {
4098 tokp = next_char(file, tokp, 1);
4100 while((c = get_char(file, tokp)) != -1) {
4101 tokp = next_char(file, tokp, 1);
4102 if (c == '\n') {
4103 multiline = 1;
4105 else if (c == '\\') {
4106 tokp = next_char(file, tokp, 1);
4108 else if (c == '"') {
4109 tok = TOK_LIT_STRING;
4110 break;
4113 if (tok == TOK_UNKNOWN) {
4114 error(state, 0, "unterminated string constant");
4116 if (multiline) {
4117 warning(state, 0, "multiline string constant");
4120 /* Save the string value */
4121 save_string(file, tk, token, tokp, "literal string");
4123 /* character constants */
4124 else if ((c == '\'') || ((c == 'L') && (c1 == '\''))) {
4125 int multiline;
4127 multiline = 0;
4128 if (c == 'L') {
4129 tokp = next_char(file, tokp, 1);
4131 while((c = get_char(file, tokp)) != -1) {
4132 tokp = next_char(file, tokp, 1);
4133 if (c == '\n') {
4134 multiline = 1;
4136 else if (c == '\\') {
4137 tokp = next_char(file, tokp, 1);
4139 else if (c == '\'') {
4140 tok = TOK_LIT_CHAR;
4141 break;
4144 if (tok == TOK_UNKNOWN) {
4145 error(state, 0, "unterminated character constant");
4147 if (multiline) {
4148 warning(state, 0, "multiline character constant");
4151 /* Save the character value */
4152 save_string(file, tk, token, tokp, "literal character");
4154 /* integer and floating constants
4155 * Integer Constants
4156 * {digits}
4157 * 0[Xx]{hexdigits}
4158 * 0{octdigit}+
4160 * Floating constants
4161 * {digits}.{digits}[Ee][+-]?{digits}
4162 * {digits}.{digits}
4163 * {digits}[Ee][+-]?{digits}
4164 * .{digits}[Ee][+-]?{digits}
4165 * .{digits}
4167 else if (digitp(c) || ((c == '.') && (digitp(c1)))) {
4168 const char *next;
4169 int is_float;
4170 int cn;
4171 is_float = 0;
4172 if (c != '.') {
4173 next = after_digits(file, tokp);
4175 else {
4176 next = token;
4178 cn = get_char(file, next);
4179 if (cn == '.') {
4180 next = next_char(file, next, 1);
4181 next = after_digits(file, next);
4182 is_float = 1;
4184 cn = get_char(file, next);
4185 if ((cn == 'e') || (cn == 'E')) {
4186 const char *new;
4187 next = next_char(file, next, 1);
4188 cn = get_char(file, next);
4189 if ((cn == '+') || (cn == '-')) {
4190 next = next_char(file, next, 1);
4192 new = after_digits(file, next);
4193 is_float |= (new != next);
4194 next = new;
4196 if (is_float) {
4197 tok = TOK_LIT_FLOAT;
4198 cn = get_char(file, next);
4199 if ((cn == 'f') || (cn == 'F') || (cn == 'l') || (cn == 'L')) {
4200 next = next_char(file, next, 1);
4203 if (!is_float && digitp(c)) {
4204 tok = TOK_LIT_INT;
4205 if ((c == '0') && ((c1 == 'x') || (c1 == 'X'))) {
4206 next = next_char(file, tokp, 1);
4207 next = after_hexdigits(file, next);
4209 else if (c == '0') {
4210 next = after_octdigits(file, tokp);
4212 else {
4213 next = after_digits(file, tokp);
4215 /* crazy integer suffixes */
4216 cn = get_char(file, next);
4217 if ((cn == 'u') || (cn == 'U')) {
4218 next = next_char(file, next, 1);
4219 cn = get_char(file, next);
4220 if ((cn == 'l') || (cn == 'L')) {
4221 next = next_char(file, next, 1);
4222 cn = get_char(file, next);
4224 if ((cn == 'l') || (cn == 'L')) {
4225 next = next_char(file, next, 1);
4228 else if ((cn == 'l') || (cn == 'L')) {
4229 next = next_char(file, next, 1);
4230 cn = get_char(file, next);
4231 if ((cn == 'l') || (cn == 'L')) {
4232 next = next_char(file, next, 1);
4233 cn = get_char(file, next);
4235 if ((cn == 'u') || (cn == 'U')) {
4236 next = next_char(file, next, 1);
4240 tokp = next;
4242 /* Save the integer/floating point value */
4243 save_string(file, tk, token, tokp, "literal number");
4245 /* identifiers */
4246 else if (letterp(c)) {
4247 tok = TOK_IDENT;
4249 /* Find and save the identifier string */
4250 tokp = after_alnums(file, tokp);
4251 save_string(file, tk, token, tokp, "identifier");
4253 /* Look up to see which identifier it is */
4254 tk->ident = lookup(state, tk->val.str, tk->str_len);
4256 /* Free the identifier string */
4257 tk->str_len = 0;
4258 xfree(tk->val.str);
4260 /* See if this identifier can be macro expanded */
4261 tk->val.notmacro = 0;
4262 c = get_char(file, tokp);
4263 if (c == '$') {
4264 tokp = next_char(file, tokp, 1);
4265 tk->val.notmacro = 1;
4268 /* C99 alternate macro characters */
4269 else if ((c == '%') && (c1 == ':') && (c2 == '%') && (c3 == ':')) {
4270 eat += 3;
4271 tok = TOK_CONCATENATE;
4273 else if ((c == '.') && (c1 == '.') && (c2 == '.')) { eat += 2; tok = TOK_DOTS; }
4274 else if ((c == '<') && (c1 == '<') && (c2 == '=')) { eat += 2; tok = TOK_SLEQ; }
4275 else if ((c == '>') && (c1 == '>') && (c2 == '=')) { eat += 2; tok = TOK_SREQ; }
4276 else if ((c == '*') && (c1 == '=')) { eat += 1; tok = TOK_TIMESEQ; }
4277 else if ((c == '/') && (c1 == '=')) { eat += 1; tok = TOK_DIVEQ; }
4278 else if ((c == '%') && (c1 == '=')) { eat += 1; tok = TOK_MODEQ; }
4279 else if ((c == '+') && (c1 == '=')) { eat += 1; tok = TOK_PLUSEQ; }
4280 else if ((c == '-') && (c1 == '=')) { eat += 1; tok = TOK_MINUSEQ; }
4281 else if ((c == '&') && (c1 == '=')) { eat += 1; tok = TOK_ANDEQ; }
4282 else if ((c == '^') && (c1 == '=')) { eat += 1; tok = TOK_XOREQ; }
4283 else if ((c == '|') && (c1 == '=')) { eat += 1; tok = TOK_OREQ; }
4284 else if ((c == '=') && (c1 == '=')) { eat += 1; tok = TOK_EQEQ; }
4285 else if ((c == '!') && (c1 == '=')) { eat += 1; tok = TOK_NOTEQ; }
4286 else if ((c == '|') && (c1 == '|')) { eat += 1; tok = TOK_LOGOR; }
4287 else if ((c == '&') && (c1 == '&')) { eat += 1; tok = TOK_LOGAND; }
4288 else if ((c == '<') && (c1 == '=')) { eat += 1; tok = TOK_LESSEQ; }
4289 else if ((c == '>') && (c1 == '=')) { eat += 1; tok = TOK_MOREEQ; }
4290 else if ((c == '<') && (c1 == '<')) { eat += 1; tok = TOK_SL; }
4291 else if ((c == '>') && (c1 == '>')) { eat += 1; tok = TOK_SR; }
4292 else if ((c == '+') && (c1 == '+')) { eat += 1; tok = TOK_PLUSPLUS; }
4293 else if ((c == '-') && (c1 == '-')) { eat += 1; tok = TOK_MINUSMINUS; }
4294 else if ((c == '-') && (c1 == '>')) { eat += 1; tok = TOK_ARROW; }
4295 else if ((c == '<') && (c1 == ':')) { eat += 1; tok = TOK_LBRACKET; }
4296 else if ((c == ':') && (c1 == '>')) { eat += 1; tok = TOK_RBRACKET; }
4297 else if ((c == '<') && (c1 == '%')) { eat += 1; tok = TOK_LBRACE; }
4298 else if ((c == '%') && (c1 == '>')) { eat += 1; tok = TOK_RBRACE; }
4299 else if ((c == '%') && (c1 == ':')) { eat += 1; tok = TOK_MACRO; }
4300 else if ((c == '#') && (c1 == '#')) { eat += 1; tok = TOK_CONCATENATE; }
4301 else if (c == ';') { tok = TOK_SEMI; }
4302 else if (c == '{') { tok = TOK_LBRACE; }
4303 else if (c == '}') { tok = TOK_RBRACE; }
4304 else if (c == ',') { tok = TOK_COMMA; }
4305 else if (c == '=') { tok = TOK_EQ; }
4306 else if (c == ':') { tok = TOK_COLON; }
4307 else if (c == '[') { tok = TOK_LBRACKET; }
4308 else if (c == ']') { tok = TOK_RBRACKET; }
4309 else if (c == '(') { tok = TOK_LPAREN; }
4310 else if (c == ')') { tok = TOK_RPAREN; }
4311 else if (c == '*') { tok = TOK_STAR; }
4312 else if (c == '>') { tok = TOK_MORE; }
4313 else if (c == '<') { tok = TOK_LESS; }
4314 else if (c == '?') { tok = TOK_QUEST; }
4315 else if (c == '|') { tok = TOK_OR; }
4316 else if (c == '&') { tok = TOK_AND; }
4317 else if (c == '^') { tok = TOK_XOR; }
4318 else if (c == '+') { tok = TOK_PLUS; }
4319 else if (c == '-') { tok = TOK_MINUS; }
4320 else if (c == '/') { tok = TOK_DIV; }
4321 else if (c == '%') { tok = TOK_MOD; }
4322 else if (c == '!') { tok = TOK_BANG; }
4323 else if (c == '.') { tok = TOK_DOT; }
4324 else if (c == '~') { tok = TOK_TILDE; }
4325 else if (c == '#') { tok = TOK_MACRO; }
4326 else if (c == '\n') { tok = TOK_EOL; }
4328 tokp = next_char(file, tokp, eat);
4329 eat_chars(file, tokp);
4330 tk->tok = tok;
4331 tk->pos = token;
4334 static void check_tok(struct compile_state *state, struct token *tk, int tok)
4336 if (tk->tok != tok) {
4337 const char *name1, *name2;
4338 name1 = tokens[tk->tok];
4339 name2 = "";
4340 if ((tk->tok == TOK_IDENT) || (tk->tok == TOK_MIDENT)) {
4341 name2 = tk->ident->name;
4343 error(state, 0, "\tfound %s %s expected %s",
4344 name1, name2, tokens[tok]);
4348 struct macro_arg_value {
4349 struct hash_entry *ident;
4350 char *value;
4351 size_t len;
4353 static struct macro_arg_value *read_macro_args(
4354 struct compile_state *state, struct macro *macro,
4355 struct file_state *file, struct token *tk)
4357 struct macro_arg_value *argv;
4358 struct macro_arg *arg;
4359 int paren_depth;
4360 int i;
4362 if (macro->argc == 0) {
4363 do {
4364 raw_next_token(state, file, tk);
4365 } while(tk->tok == TOK_SPACE);
4366 return NULL;
4368 argv = xcmalloc(sizeof(*argv) * macro->argc, "macro args");
4369 for(i = 0, arg = macro->args; arg; arg = arg->next, i++) {
4370 argv[i].value = 0;
4371 argv[i].len = 0;
4372 argv[i].ident = arg->ident;
4374 paren_depth = 0;
4375 i = 0;
4377 for(;;) {
4378 const char *start;
4379 size_t len;
4380 start = file->pos;
4381 raw_next_token(state, file, tk);
4383 if (!paren_depth && (tk->tok == TOK_COMMA) &&
4384 (argv[i].ident != state->i___VA_ARGS__))
4386 i++;
4387 if (i >= macro->argc) {
4388 error(state, 0, "too many args to %s\n",
4389 macro->ident->name);
4391 continue;
4394 if (tk->tok == TOK_LPAREN) {
4395 paren_depth++;
4398 if (tk->tok == TOK_RPAREN) {
4399 if (paren_depth == 0) {
4400 break;
4402 paren_depth--;
4404 if (tk->tok == TOK_EOF) {
4405 error(state, 0, "End of file encountered while parsing macro arguments");
4408 len = char_strlen(file, start, file->pos);
4409 argv[i].value = xrealloc(
4410 argv[i].value, argv[i].len + len, "macro args");
4411 char_strcpy((char *)argv[i].value + argv[i].len, file, start, file->pos);
4412 argv[i].len += len;
4414 if (i != macro->argc -1) {
4415 error(state, 0, "missing %s arg %d\n",
4416 macro->ident->name, i +2);
4418 return argv;
4422 static void free_macro_args(struct macro *macro, struct macro_arg_value *argv)
4424 int i;
4425 for(i = 0; i < macro->argc; i++) {
4426 xfree(argv[i].value);
4428 xfree(argv);
4431 struct macro_buf {
4432 char *str;
4433 size_t len, pos;
4436 static void grow_macro_buf(struct compile_state *state,
4437 const char *id, struct macro_buf *buf,
4438 size_t grow)
4440 if ((buf->pos + grow) >= buf->len) {
4441 buf->str = xrealloc(buf->str, buf->len + grow, id);
4442 buf->len += grow;
4446 static void append_macro_text(struct compile_state *state,
4447 const char *id, struct macro_buf *buf,
4448 const char *fstart, size_t flen)
4450 grow_macro_buf(state, id, buf, flen);
4451 memcpy(buf->str + buf->pos, fstart, flen);
4452 #if 0
4453 fprintf(state->errout, "append: `%*.*s' `%*.*s'\n",
4454 buf->pos, buf->pos, buf->str,
4455 flen, flen, buf->str + buf->pos);
4456 #endif
4457 buf->pos += flen;
4461 static void append_macro_chars(struct compile_state *state,
4462 const char *id, struct macro_buf *buf,
4463 struct file_state *file, const char *start, const char *end)
4465 size_t flen;
4466 flen = char_strlen(file, start, end);
4467 grow_macro_buf(state, id, buf, flen);
4468 char_strcpy(buf->str + buf->pos, file, start, end);
4469 #if 0
4470 fprintf(state->errout, "append: `%*.*s' `%*.*s'\n",
4471 buf->pos, buf->pos, buf->str,
4472 flen, flen, buf->str + buf->pos);
4473 #endif
4474 buf->pos += flen;
4477 static int compile_macro(struct compile_state *state,
4478 struct file_state **filep, struct token *tk);
4480 static void macro_expand_args(struct compile_state *state,
4481 struct macro *macro, struct macro_arg_value *argv, struct token *tk)
4483 int i;
4485 for(i = 0; i < macro->argc; i++) {
4486 struct file_state fmacro, *file;
4487 struct macro_buf buf;
4489 fmacro.prev = 0;
4490 fmacro.basename = argv[i].ident->name;
4491 fmacro.dirname = "";
4492 fmacro.buf = (char *)argv[i].value;
4493 fmacro.size = argv[i].len;
4494 fmacro.pos = fmacro.buf;
4495 fmacro.line = 1;
4496 fmacro.line_start = fmacro.buf;
4497 fmacro.report_line = 1;
4498 fmacro.report_name = fmacro.basename;
4499 fmacro.report_dir = fmacro.dirname;
4500 fmacro.macro = 1;
4501 fmacro.trigraphs = 0;
4502 fmacro.join_lines = 0;
4504 buf.len = argv[i].len;
4505 buf.str = xmalloc(buf.len, argv[i].ident->name);
4506 buf.pos = 0;
4508 file = &fmacro;
4509 for(;;) {
4510 raw_next_token(state, file, tk);
4512 /* If we have recursed into another macro body
4513 * get out of it.
4515 if (tk->tok == TOK_EOF) {
4516 struct file_state *old;
4517 old = file;
4518 file = file->prev;
4519 if (!file) {
4520 break;
4522 /* old->basename is used keep it */
4523 xfree(old->dirname);
4524 xfree(old->buf);
4525 xfree(old);
4526 continue;
4528 else if (tk->ident && tk->ident->sym_define) {
4529 if (compile_macro(state, &file, tk)) {
4530 continue;
4534 append_macro_chars(state, macro->ident->name, &buf,
4535 file, tk->pos, file->pos);
4538 xfree(argv[i].value);
4539 argv[i].value = buf.str;
4540 argv[i].len = buf.pos;
4542 return;
4545 static void expand_macro(struct compile_state *state,
4546 struct macro *macro, struct macro_buf *buf,
4547 struct macro_arg_value *argv, struct token *tk)
4549 struct file_state fmacro;
4550 const char space[] = " ";
4551 const char *fstart;
4552 size_t flen;
4553 int i, j;
4555 /* Place the macro body in a dummy file */
4556 fmacro.prev = 0;
4557 fmacro.basename = macro->ident->name;
4558 fmacro.dirname = "";
4559 fmacro.buf = macro->buf;
4560 fmacro.size = macro->buf_len;
4561 fmacro.pos = fmacro.buf;
4562 fmacro.line = 1;
4563 fmacro.line_start = fmacro.buf;
4564 fmacro.report_line = 1;
4565 fmacro.report_name = fmacro.basename;
4566 fmacro.report_dir = fmacro.dirname;
4567 fmacro.macro = 1;
4568 fmacro.trigraphs = 0;
4569 fmacro.join_lines = 0;
4571 /* Allocate a buffer to hold the macro expansion */
4572 buf->len = macro->buf_len + 3;
4573 buf->str = xmalloc(buf->len, macro->ident->name);
4574 buf->pos = 0;
4576 fstart = fmacro.pos;
4577 raw_next_token(state, &fmacro, tk);
4578 while(tk->tok != TOK_EOF) {
4579 flen = fmacro.pos - fstart;
4580 switch(tk->tok) {
4581 case TOK_IDENT:
4582 if (macro->argc < 0) {
4583 break;
4585 for(i = 0; i < macro->argc; i++) {
4586 if (argv[i].ident == tk->ident) {
4587 break;
4590 if (i >= macro->argc) {
4591 break;
4593 /* Substitute macro parameter */
4594 fstart = argv[i].value;
4595 flen = argv[i].len;
4596 break;
4597 case TOK_MACRO:
4598 if (macro->argc < 0) {
4599 break;
4601 do {
4602 raw_next_token(state, &fmacro, tk);
4603 } while(tk->tok == TOK_SPACE);
4604 check_tok(state, tk, TOK_IDENT);
4605 for(i = 0; i < macro->argc; i++) {
4606 if (argv[i].ident == tk->ident) {
4607 break;
4610 if (i >= macro->argc) {
4611 error(state, 0, "parameter `%s' not found",
4612 tk->ident->name);
4614 /* Stringize token */
4615 append_macro_text(state, macro->ident->name, buf, "\"", 1);
4616 for(j = 0; j < argv[i].len; j++) {
4617 char *str = argv[i].value + j;
4618 size_t len = 1;
4619 if (*str == '\\') {
4620 str = "\\";
4621 len = 2;
4623 else if (*str == '"') {
4624 str = "\\\"";
4625 len = 2;
4627 append_macro_text(state, macro->ident->name, buf, str, len);
4629 append_macro_text(state, macro->ident->name, buf, "\"", 1);
4630 fstart = 0;
4631 flen = 0;
4632 break;
4633 case TOK_CONCATENATE:
4634 /* Concatenate tokens */
4635 /* Delete the previous whitespace token */
4636 if (buf->str[buf->pos - 1] == ' ') {
4637 buf->pos -= 1;
4639 /* Skip the next sequence of whitspace tokens */
4640 do {
4641 fstart = fmacro.pos;
4642 raw_next_token(state, &fmacro, tk);
4643 } while(tk->tok == TOK_SPACE);
4644 /* Restart at the top of the loop.
4645 * I need to process the non white space token.
4647 continue;
4648 break;
4649 case TOK_SPACE:
4650 /* Collapse multiple spaces into one */
4651 if (buf->str[buf->pos - 1] != ' ') {
4652 fstart = space;
4653 flen = 1;
4654 } else {
4655 fstart = 0;
4656 flen = 0;
4658 break;
4659 default:
4660 break;
4663 append_macro_text(state, macro->ident->name, buf, fstart, flen);
4665 fstart = fmacro.pos;
4666 raw_next_token(state, &fmacro, tk);
4670 static void tag_macro_name(struct compile_state *state,
4671 struct macro *macro, struct macro_buf *buf,
4672 struct token *tk)
4674 /* Guard all instances of the macro name in the replacement
4675 * text from further macro expansion.
4677 struct file_state fmacro;
4678 const char *fstart;
4679 size_t flen;
4681 /* Put the old macro expansion buffer in a file */
4682 fmacro.prev = 0;
4683 fmacro.basename = macro->ident->name;
4684 fmacro.dirname = "";
4685 fmacro.buf = buf->str;
4686 fmacro.size = buf->pos;
4687 fmacro.pos = fmacro.buf;
4688 fmacro.line = 1;
4689 fmacro.line_start = fmacro.buf;
4690 fmacro.report_line = 1;
4691 fmacro.report_name = fmacro.basename;
4692 fmacro.report_dir = fmacro.dirname;
4693 fmacro.macro = 1;
4694 fmacro.trigraphs = 0;
4695 fmacro.join_lines = 0;
4697 /* Allocate a new macro expansion buffer */
4698 buf->len = macro->buf_len + 3;
4699 buf->str = xmalloc(buf->len, macro->ident->name);
4700 buf->pos = 0;
4702 fstart = fmacro.pos;
4703 raw_next_token(state, &fmacro, tk);
4704 while(tk->tok != TOK_EOF) {
4705 flen = fmacro.pos - fstart;
4706 if ((tk->tok == TOK_IDENT) &&
4707 (tk->ident == macro->ident) &&
4708 (tk->val.notmacro == 0))
4710 append_macro_text(state, macro->ident->name, buf, fstart, flen);
4711 fstart = "$";
4712 flen = 1;
4715 append_macro_text(state, macro->ident->name, buf, fstart, flen);
4717 fstart = fmacro.pos;
4718 raw_next_token(state, &fmacro, tk);
4720 xfree(fmacro.buf);
4723 static int compile_macro(struct compile_state *state,
4724 struct file_state **filep, struct token *tk)
4726 struct file_state *file;
4727 struct hash_entry *ident;
4728 struct macro *macro;
4729 struct macro_arg_value *argv;
4730 struct macro_buf buf;
4732 #if 0
4733 fprintf(state->errout, "macro: %s\n", tk->ident->name);
4734 #endif
4735 ident = tk->ident;
4736 macro = ident->sym_define;
4738 /* If this token comes from a macro expansion ignore it */
4739 if (tk->val.notmacro) {
4740 return 0;
4742 /* If I am a function like macro and the identifier is not followed
4743 * by a left parenthesis, do nothing.
4745 if ((macro->argc >= 0) && (get_char(*filep, (*filep)->pos) != '(')) {
4746 return 0;
4749 /* Read in the macro arguments */
4750 argv = 0;
4751 if (macro->argc >= 0) {
4752 raw_next_token(state, *filep, tk);
4753 check_tok(state, tk, TOK_LPAREN);
4755 argv = read_macro_args(state, macro, *filep, tk);
4757 check_tok(state, tk, TOK_RPAREN);
4759 /* Macro expand the macro arguments */
4760 macro_expand_args(state, macro, argv, tk);
4762 buf.str = 0;
4763 buf.len = 0;
4764 buf.pos = 0;
4765 if (ident == state->i___FILE__) {
4766 buf.len = strlen(state->file->basename) + 1 + 2 + 3;
4767 buf.str = xmalloc(buf.len, ident->name);
4768 sprintf(buf.str, "\"%s\"", state->file->basename);
4769 buf.pos = strlen(buf.str);
4771 else if (ident == state->i___LINE__) {
4772 buf.len = 30;
4773 buf.str = xmalloc(buf.len, ident->name);
4774 sprintf(buf.str, "%d", state->file->line);
4775 buf.pos = strlen(buf.str);
4777 else {
4778 expand_macro(state, macro, &buf, argv, tk);
4780 /* Tag the macro name with a $ so it will no longer
4781 * be regonized as a canidate for macro expansion.
4783 tag_macro_name(state, macro, &buf, tk);
4785 #if 0
4786 fprintf(state->errout, "%s: %d -> `%*.*s'\n",
4787 ident->name, buf.pos, buf.pos, (int)(buf.pos), buf.str);
4788 #endif
4790 free_macro_args(macro, argv);
4792 file = xmalloc(sizeof(*file), "file_state");
4793 file->prev = *filep;
4794 file->basename = xstrdup(ident->name);
4795 file->dirname = xstrdup("");
4796 file->buf = buf.str;
4797 file->size = buf.pos;
4798 file->pos = file->buf;
4799 file->line = 1;
4800 file->line_start = file->pos;
4801 file->report_line = 1;
4802 file->report_name = file->basename;
4803 file->report_dir = file->dirname;
4804 file->macro = 1;
4805 file->trigraphs = 0;
4806 file->join_lines = 0;
4807 *filep = file;
4808 return 1;
4811 static void eat_tokens(struct compile_state *state, int targ_tok)
4813 if (state->eat_depth > 0) {
4814 internal_error(state, 0, "Already eating...");
4816 state->eat_depth = state->if_depth;
4817 state->eat_targ = targ_tok;
4819 static int if_eat(struct compile_state *state)
4821 return state->eat_depth > 0;
4823 static int if_value(struct compile_state *state)
4825 int index, offset;
4826 index = state->if_depth / CHAR_BIT;
4827 offset = state->if_depth % CHAR_BIT;
4828 return !!(state->if_bytes[index] & (1 << (offset)));
4830 static void set_if_value(struct compile_state *state, int value)
4832 int index, offset;
4833 index = state->if_depth / CHAR_BIT;
4834 offset = state->if_depth % CHAR_BIT;
4836 state->if_bytes[index] &= ~(1 << offset);
4837 if (value) {
4838 state->if_bytes[index] |= (1 << offset);
4841 static void in_if(struct compile_state *state, const char *name)
4843 if (state->if_depth <= 0) {
4844 error(state, 0, "%s without #if", name);
4847 static void enter_if(struct compile_state *state)
4849 state->if_depth += 1;
4850 if (state->if_depth > MAX_PP_IF_DEPTH) {
4851 error(state, 0, "#if depth too great");
4854 static void reenter_if(struct compile_state *state, const char *name)
4856 in_if(state, name);
4857 if ((state->eat_depth == state->if_depth) &&
4858 (state->eat_targ == TOK_MELSE)) {
4859 state->eat_depth = 0;
4860 state->eat_targ = 0;
4863 static void enter_else(struct compile_state *state, const char *name)
4865 in_if(state, name);
4866 if ((state->eat_depth == state->if_depth) &&
4867 (state->eat_targ == TOK_MELSE)) {
4868 state->eat_depth = 0;
4869 state->eat_targ = 0;
4872 static void exit_if(struct compile_state *state, const char *name)
4874 in_if(state, name);
4875 if (state->eat_depth == state->if_depth) {
4876 state->eat_depth = 0;
4877 state->eat_targ = 0;
4879 state->if_depth -= 1;
4882 static void raw_token(struct compile_state *state, struct token *tk)
4884 struct file_state *file;
4885 int rescan;
4887 file = state->file;
4888 raw_next_token(state, file, tk);
4889 do {
4890 rescan = 0;
4891 file = state->file;
4892 /* Exit out of an include directive or macro call */
4893 if ((tk->tok == TOK_EOF) &&
4894 (file != state->macro_file) && file->prev)
4896 state->file = file->prev;
4897 /* file->basename is used keep it */
4898 xfree(file->dirname);
4899 xfree(file->buf);
4900 xfree(file);
4901 file = 0;
4902 raw_next_token(state, state->file, tk);
4903 rescan = 1;
4905 } while(rescan);
4908 static void pp_token(struct compile_state *state, struct token *tk)
4910 int rescan;
4912 raw_token(state, tk);
4913 do {
4914 rescan = 0;
4915 if (tk->tok == TOK_SPACE) {
4916 raw_token(state, tk);
4917 rescan = 1;
4919 else if (tk->tok == TOK_IDENT) {
4920 if (state->token_base == 0) {
4921 ident_to_keyword(state, tk);
4922 } else {
4923 ident_to_macro(state, tk);
4926 } while(rescan);
4929 static void preprocess(struct compile_state *state, struct token *tk);
4931 static void token(struct compile_state *state, struct token *tk)
4933 int rescan;
4934 pp_token(state, tk);
4935 do {
4936 rescan = 0;
4937 /* Process a macro directive */
4938 if (tk->tok == TOK_MACRO) {
4939 /* Only match preprocessor directives at the start of a line */
4940 const char *ptr;
4941 ptr = state->file->line_start;
4942 while((ptr < tk->pos)
4943 && spacep(get_char(state->file, ptr)))
4945 ptr = next_char(state->file, ptr, 1);
4947 if (ptr == tk->pos) {
4948 preprocess(state, tk);
4949 rescan = 1;
4952 /* Expand a macro call */
4953 else if (tk->ident && tk->ident->sym_define) {
4954 rescan = compile_macro(state, &state->file, tk);
4955 if (rescan) {
4956 pp_token(state, tk);
4959 /* Eat tokens disabled by the preprocessor
4960 * (Unless we are parsing a preprocessor directive
4962 else if (if_eat(state) && (state->token_base == 0)) {
4963 pp_token(state, tk);
4964 rescan = 1;
4966 /* Make certain EOL only shows up in preprocessor directives */
4967 else if ((tk->tok == TOK_EOL) && (state->token_base == 0)) {
4968 pp_token(state, tk);
4969 rescan = 1;
4971 /* Error on unknown tokens */
4972 else if (tk->tok == TOK_UNKNOWN) {
4973 error(state, 0, "unknown token");
4975 } while(rescan);
4979 static inline struct token *get_token(struct compile_state *state, int offset)
4981 int index;
4982 index = state->token_base + offset;
4983 if (index >= sizeof(state->token)/sizeof(state->token[0])) {
4984 internal_error(state, 0, "token array to small");
4986 return &state->token[index];
4989 static struct token *do_eat_token(struct compile_state *state, int tok)
4991 struct token *tk;
4992 int i;
4993 check_tok(state, get_token(state, 1), tok);
4995 /* Free the old token value */
4996 tk = get_token(state, 0);
4997 if (tk->str_len) {
4998 memset((void *)tk->val.str, -1, tk->str_len);
4999 xfree(tk->val.str);
5001 /* Overwrite the old token with newer tokens */
5002 for(i = state->token_base; i < sizeof(state->token)/sizeof(state->token[0]) - 1; i++) {
5003 state->token[i] = state->token[i + 1];
5005 /* Clear the last token */
5006 memset(&state->token[i], 0, sizeof(state->token[i]));
5007 state->token[i].tok = -1;
5009 /* Return the token */
5010 return tk;
5013 static int raw_peek(struct compile_state *state)
5015 struct token *tk1;
5016 tk1 = get_token(state, 1);
5017 if (tk1->tok == -1) {
5018 raw_token(state, tk1);
5020 return tk1->tok;
5023 static struct token *raw_eat(struct compile_state *state, int tok)
5025 raw_peek(state);
5026 return do_eat_token(state, tok);
5029 static int pp_peek(struct compile_state *state)
5031 struct token *tk1;
5032 tk1 = get_token(state, 1);
5033 if (tk1->tok == -1) {
5034 pp_token(state, tk1);
5036 return tk1->tok;
5039 static struct token *pp_eat(struct compile_state *state, int tok)
5041 pp_peek(state);
5042 return do_eat_token(state, tok);
5045 static int peek(struct compile_state *state)
5047 struct token *tk1;
5048 tk1 = get_token(state, 1);
5049 if (tk1->tok == -1) {
5050 token(state, tk1);
5052 return tk1->tok;
5055 static int peek2(struct compile_state *state)
5057 struct token *tk1, *tk2;
5058 tk1 = get_token(state, 1);
5059 tk2 = get_token(state, 2);
5060 if (tk1->tok == -1) {
5061 token(state, tk1);
5063 if (tk2->tok == -1) {
5064 token(state, tk2);
5066 return tk2->tok;
5069 static struct token *eat(struct compile_state *state, int tok)
5071 peek(state);
5072 return do_eat_token(state, tok);
5075 static void compile_file(struct compile_state *state, const char *filename, int local)
5077 char cwd[MAX_CWD_SIZE];
5078 const char *subdir, *base;
5079 int subdir_len;
5080 struct file_state *file;
5081 char *basename;
5082 file = xmalloc(sizeof(*file), "file_state");
5084 base = strrchr(filename, '/');
5085 subdir = filename;
5086 if (base != 0) {
5087 subdir_len = base - filename;
5088 base++;
5090 else {
5091 base = filename;
5092 subdir_len = 0;
5094 basename = xmalloc(strlen(base) +1, "basename");
5095 strcpy(basename, base);
5096 file->basename = basename;
5098 if (getcwd(cwd, sizeof(cwd)) == 0) {
5099 die("cwd buffer to small");
5101 if ((subdir[0] == '/') || ((subdir[1] == ':') && ((subdir[2] == '/') || (subdir[2] == '\\')))) {
5102 file->dirname = xmalloc(subdir_len + 1, "dirname");
5103 memcpy(file->dirname, subdir, subdir_len);
5104 file->dirname[subdir_len] = '\0';
5106 else {
5107 const char *dir;
5108 int dirlen;
5109 const char **path;
5110 /* Find the appropriate directory... */
5111 dir = 0;
5112 if (!state->file && exists(cwd, filename)) {
5113 dir = cwd;
5115 if (local && state->file && exists(state->file->dirname, filename)) {
5116 dir = state->file->dirname;
5118 for(path = state->compiler->include_paths; !dir && *path; path++) {
5119 if (exists(*path, filename)) {
5120 dir = *path;
5123 if (!dir) {
5124 error(state, 0, "Cannot open `%s'\n", filename);
5126 dirlen = strlen(dir);
5127 file->dirname = xmalloc(dirlen + 1 + subdir_len + 1, "dirname");
5128 memcpy(file->dirname, dir, dirlen);
5129 file->dirname[dirlen] = '/';
5130 memcpy(file->dirname + dirlen + 1, subdir, subdir_len);
5131 file->dirname[dirlen + 1 + subdir_len] = '\0';
5133 file->buf = slurp_file(file->dirname, file->basename, &file->size);
5135 file->pos = file->buf;
5136 file->line_start = file->pos;
5137 file->line = 1;
5139 file->report_line = 1;
5140 file->report_name = file->basename;
5141 file->report_dir = file->dirname;
5142 file->macro = 0;
5143 file->trigraphs = (state->compiler->flags & COMPILER_TRIGRAPHS)? 1: 0;
5144 file->join_lines = 1;
5146 file->prev = state->file;
5147 state->file = file;
5150 static struct triple *constant_expr(struct compile_state *state);
5151 static void integral(struct compile_state *state, struct triple *def);
5153 static int mcexpr(struct compile_state *state)
5155 struct triple *cvalue;
5156 cvalue = constant_expr(state);
5157 integral(state, cvalue);
5158 if (cvalue->op != OP_INTCONST) {
5159 error(state, 0, "integer constant expected");
5161 return cvalue->u.cval != 0;
5164 static void preprocess(struct compile_state *state, struct token *current_token)
5166 /* Doing much more with the preprocessor would require
5167 * a parser and a major restructuring.
5168 * Postpone that for later.
5170 int old_token_base;
5171 int tok;
5173 state->macro_file = state->file;
5175 old_token_base = state->token_base;
5176 state->token_base = current_token - state->token;
5178 tok = pp_peek(state);
5179 switch(tok) {
5180 case TOK_LIT_INT:
5182 struct token *tk;
5183 int override_line;
5184 tk = pp_eat(state, TOK_LIT_INT);
5185 override_line = strtoul(tk->val.str, 0, 10);
5186 /* I have a preprocessor line marker parse it */
5187 if (pp_peek(state) == TOK_LIT_STRING) {
5188 const char *token, *base;
5189 char *name, *dir;
5190 int name_len, dir_len;
5191 tk = pp_eat(state, TOK_LIT_STRING);
5192 name = xmalloc(tk->str_len, "report_name");
5193 token = tk->val.str + 1;
5194 base = strrchr(token, '/');
5195 name_len = tk->str_len -2;
5196 if (base != 0) {
5197 dir_len = base - token;
5198 base++;
5199 name_len -= base - token;
5200 } else {
5201 dir_len = 0;
5202 base = token;
5204 memcpy(name, base, name_len);
5205 name[name_len] = '\0';
5206 dir = xmalloc(dir_len + 1, "report_dir");
5207 memcpy(dir, token, dir_len);
5208 dir[dir_len] = '\0';
5209 state->file->report_line = override_line - 1;
5210 state->file->report_name = name;
5211 state->file->report_dir = dir;
5212 state->file->macro = 0;
5214 break;
5216 case TOK_MLINE:
5218 struct token *tk;
5219 pp_eat(state, TOK_MLINE);
5220 tk = eat(state, TOK_LIT_INT);
5221 state->file->report_line = strtoul(tk->val.str, 0, 10) -1;
5222 if (pp_peek(state) == TOK_LIT_STRING) {
5223 const char *token, *base;
5224 char *name, *dir;
5225 int name_len, dir_len;
5226 tk = pp_eat(state, TOK_LIT_STRING);
5227 name = xmalloc(tk->str_len, "report_name");
5228 token = tk->val.str + 1;
5229 base = strrchr(token, '/');
5230 name_len = tk->str_len - 2;
5231 if (base != 0) {
5232 dir_len = base - token;
5233 base++;
5234 name_len -= base - token;
5235 } else {
5236 dir_len = 0;
5237 base = token;
5239 memcpy(name, base, name_len);
5240 name[name_len] = '\0';
5241 dir = xmalloc(dir_len + 1, "report_dir");
5242 memcpy(dir, token, dir_len);
5243 dir[dir_len] = '\0';
5244 state->file->report_name = name;
5245 state->file->report_dir = dir;
5246 state->file->macro = 0;
5248 break;
5250 case TOK_MUNDEF:
5252 struct hash_entry *ident;
5253 pp_eat(state, TOK_MUNDEF);
5254 if (if_eat(state)) /* quit early when #if'd out */
5255 break;
5257 ident = pp_eat(state, TOK_MIDENT)->ident;
5259 undef_macro(state, ident);
5260 break;
5262 case TOK_MPRAGMA:
5263 pp_eat(state, TOK_MPRAGMA);
5264 if (if_eat(state)) /* quit early when #if'd out */
5265 break;
5266 warning(state, 0, "Ignoring pragma");
5267 break;
5268 case TOK_MELIF:
5269 pp_eat(state, TOK_MELIF);
5270 reenter_if(state, "#elif");
5271 if (if_eat(state)) /* quit early when #if'd out */
5272 break;
5273 /* If the #if was taken the #elif just disables the following code */
5274 if (if_value(state)) {
5275 eat_tokens(state, TOK_MENDIF);
5277 /* If the previous #if was not taken see if the #elif enables the
5278 * trailing code.
5280 else {
5281 set_if_value(state, mcexpr(state));
5282 if (!if_value(state)) {
5283 eat_tokens(state, TOK_MELSE);
5286 break;
5287 case TOK_MIF:
5288 pp_eat(state, TOK_MIF);
5289 enter_if(state);
5290 if (if_eat(state)) /* quit early when #if'd out */
5291 break;
5292 set_if_value(state, mcexpr(state));
5293 if (!if_value(state)) {
5294 eat_tokens(state, TOK_MELSE);
5296 break;
5297 case TOK_MIFNDEF:
5299 struct hash_entry *ident;
5301 pp_eat(state, TOK_MIFNDEF);
5302 enter_if(state);
5303 if (if_eat(state)) /* quit early when #if'd out */
5304 break;
5305 ident = pp_eat(state, TOK_MIDENT)->ident;
5306 set_if_value(state, ident->sym_define == 0);
5307 if (!if_value(state)) {
5308 eat_tokens(state, TOK_MELSE);
5310 break;
5312 case TOK_MIFDEF:
5314 struct hash_entry *ident;
5315 pp_eat(state, TOK_MIFDEF);
5316 enter_if(state);
5317 if (if_eat(state)) /* quit early when #if'd out */
5318 break;
5319 ident = pp_eat(state, TOK_MIDENT)->ident;
5320 set_if_value(state, ident->sym_define != 0);
5321 if (!if_value(state)) {
5322 eat_tokens(state, TOK_MELSE);
5324 break;
5326 case TOK_MELSE:
5327 pp_eat(state, TOK_MELSE);
5328 enter_else(state, "#else");
5329 if (!if_eat(state) && if_value(state)) {
5330 eat_tokens(state, TOK_MENDIF);
5332 break;
5333 case TOK_MENDIF:
5334 pp_eat(state, TOK_MENDIF);
5335 exit_if(state, "#endif");
5336 break;
5337 case TOK_MDEFINE:
5339 struct hash_entry *ident;
5340 struct macro_arg *args, **larg;
5341 const char *mstart, *mend;
5342 int argc;
5344 pp_eat(state, TOK_MDEFINE);
5345 if (if_eat(state)) /* quit early when #if'd out */
5346 break;
5347 ident = pp_eat(state, TOK_MIDENT)->ident;
5348 argc = -1;
5349 args = 0;
5350 larg = &args;
5352 /* Parse macro parameters */
5353 if (raw_peek(state) == TOK_LPAREN) {
5354 raw_eat(state, TOK_LPAREN);
5355 argc += 1;
5357 for(;;) {
5358 struct macro_arg *narg, *arg;
5359 struct hash_entry *aident;
5360 int tok;
5362 tok = pp_peek(state);
5363 if (!args && (tok == TOK_RPAREN)) {
5364 break;
5366 else if (tok == TOK_DOTS) {
5367 pp_eat(state, TOK_DOTS);
5368 aident = state->i___VA_ARGS__;
5370 else {
5371 aident = pp_eat(state, TOK_MIDENT)->ident;
5374 narg = xcmalloc(sizeof(*arg), "macro arg");
5375 narg->ident = aident;
5377 /* Verify I don't have a duplicate identifier */
5378 for(arg = args; arg; arg = arg->next) {
5379 if (arg->ident == narg->ident) {
5380 error(state, 0, "Duplicate macro arg `%s'",
5381 narg->ident->name);
5384 /* Add the new argument to the end of the list */
5385 *larg = narg;
5386 larg = &narg->next;
5387 argc += 1;
5389 if ((aident == state->i___VA_ARGS__) ||
5390 (pp_peek(state) != TOK_COMMA)) {
5391 break;
5393 pp_eat(state, TOK_COMMA);
5395 pp_eat(state, TOK_RPAREN);
5397 /* Remove leading whitespace */
5398 while(raw_peek(state) == TOK_SPACE) {
5399 raw_eat(state, TOK_SPACE);
5402 /* Remember the start of the macro body */
5403 raw_peek(state);
5404 mend = mstart = get_token(state, 1)->pos;
5406 /* Find the end of the macro */
5407 for(tok = raw_peek(state); tok != TOK_EOL; tok = raw_peek(state)) {
5408 raw_eat(state, tok);
5409 /* Remember the end of the last non space token */
5410 raw_peek(state);
5411 if (tok != TOK_SPACE) {
5412 mend = get_token(state, 1)->pos;
5416 /* Now that I have found the body defined the token */
5417 do_define_macro(state, ident,
5418 char_strdup(state->file, mstart, mend, "macro buf"),
5419 argc, args);
5420 break;
5422 case TOK_MERROR:
5424 const char *start, *end;
5425 int len;
5427 pp_eat(state, TOK_MERROR);
5428 /* Find the start of the line */
5429 raw_peek(state);
5430 start = get_token(state, 1)->pos;
5432 /* Find the end of the line */
5433 while((tok = raw_peek(state)) != TOK_EOL) {
5434 raw_eat(state, tok);
5436 end = get_token(state, 1)->pos;
5437 len = end - start;
5438 if (!if_eat(state)) {
5439 error(state, 0, "%*.*s", len, len, start);
5441 break;
5443 case TOK_MWARNING:
5445 const char *start, *end;
5446 int len;
5448 pp_eat(state, TOK_MWARNING);
5450 /* Find the start of the line */
5451 raw_peek(state);
5452 start = get_token(state, 1)->pos;
5454 /* Find the end of the line */
5455 while((tok = raw_peek(state)) != TOK_EOL) {
5456 raw_eat(state, tok);
5458 end = get_token(state, 1)->pos;
5459 len = end - start;
5460 if (!if_eat(state)) {
5461 warning(state, 0, "%*.*s", len, len, start);
5463 break;
5465 case TOK_MINCLUDE:
5467 char *name;
5468 int local;
5469 name = 0;
5471 pp_eat(state, TOK_MINCLUDE);
5472 if (if_eat(state)) {
5473 /* Find the end of the line */
5474 while((tok = raw_peek(state)) != TOK_EOL) {
5475 raw_eat(state, tok);
5477 break;
5479 tok = peek(state);
5480 if (tok == TOK_LIT_STRING) {
5481 struct token *tk;
5482 const char *token;
5483 int name_len;
5484 tk = eat(state, TOK_LIT_STRING);
5485 name = xmalloc(tk->str_len, "include");
5486 token = tk->val.str +1;
5487 name_len = tk->str_len -2;
5488 if (*token == '"') {
5489 token++;
5490 name_len--;
5492 memcpy(name, token, name_len);
5493 name[name_len] = '\0';
5494 local = 1;
5496 else if (tok == TOK_LESS) {
5497 struct macro_buf buf;
5498 eat(state, TOK_LESS);
5500 buf.len = 40;
5501 buf.str = xmalloc(buf.len, "include");
5502 buf.pos = 0;
5504 tok = peek(state);
5505 while((tok != TOK_MORE) &&
5506 (tok != TOK_EOL) && (tok != TOK_EOF))
5508 struct token *tk;
5509 tk = eat(state, tok);
5510 append_macro_chars(state, "include", &buf,
5511 state->file, tk->pos, state->file->pos);
5512 tok = peek(state);
5514 append_macro_text(state, "include", &buf, "\0", 1);
5515 if (peek(state) != TOK_MORE) {
5516 error(state, 0, "Unterminated include directive");
5518 eat(state, TOK_MORE);
5519 local = 0;
5520 name = buf.str;
5522 else {
5523 error(state, 0, "Invalid include directive");
5525 /* Error if there are any tokens after the include */
5526 if (pp_peek(state) != TOK_EOL) {
5527 error(state, 0, "garbage after include directive");
5529 if (!if_eat(state)) {
5530 compile_file(state, name, local);
5532 xfree(name);
5533 break;
5535 case TOK_EOL:
5536 /* Ignore # without a following ident */
5537 break;
5538 default:
5540 const char *name1, *name2;
5541 name1 = tokens[tok];
5542 name2 = "";
5543 if (tok == TOK_MIDENT) {
5544 name2 = get_token(state, 1)->ident->name;
5546 error(state, 0, "Invalid preprocessor directive: %s %s",
5547 name1, name2);
5548 break;
5551 /* Consume the rest of the macro line */
5552 do {
5553 tok = pp_peek(state);
5554 pp_eat(state, tok);
5555 } while((tok != TOK_EOF) && (tok != TOK_EOL));
5556 state->token_base = old_token_base;
5557 state->macro_file = NULL;
5558 return;
5561 /* Type helper functions */
5563 static struct type *new_type(
5564 unsigned int type, struct type *left, struct type *right)
5566 struct type *result;
5567 result = xmalloc(sizeof(*result), "type");
5568 result->type = type;
5569 result->left = left;
5570 result->right = right;
5571 result->field_ident = 0;
5572 result->type_ident = 0;
5573 result->elements = 0;
5574 return result;
5577 static struct type *clone_type(unsigned int specifiers, struct type *old)
5579 struct type *result;
5580 result = xmalloc(sizeof(*result), "type");
5581 memcpy(result, old, sizeof(*result));
5582 result->type &= TYPE_MASK;
5583 result->type |= specifiers;
5584 return result;
5587 static struct type *dup_type(struct compile_state *state, struct type *orig)
5589 struct type *new;
5590 new = xcmalloc(sizeof(*new), "type");
5591 new->type = orig->type;
5592 new->field_ident = orig->field_ident;
5593 new->type_ident = orig->type_ident;
5594 new->elements = orig->elements;
5595 if (orig->left) {
5596 new->left = dup_type(state, orig->left);
5598 if (orig->right) {
5599 new->right = dup_type(state, orig->right);
5601 return new;
5605 static struct type *invalid_type(struct compile_state *state, struct type *type)
5607 struct type *invalid, *member;
5608 invalid = 0;
5609 if (!type) {
5610 internal_error(state, 0, "type missing?");
5612 switch(type->type & TYPE_MASK) {
5613 case TYPE_VOID:
5614 case TYPE_CHAR: case TYPE_UCHAR:
5615 case TYPE_SHORT: case TYPE_USHORT:
5616 case TYPE_INT: case TYPE_UINT:
5617 case TYPE_LONG: case TYPE_ULONG:
5618 case TYPE_LLONG: case TYPE_ULLONG:
5619 case TYPE_POINTER:
5620 case TYPE_ENUM:
5621 break;
5622 case TYPE_BITFIELD:
5623 invalid = invalid_type(state, type->left);
5624 break;
5625 case TYPE_ARRAY:
5626 invalid = invalid_type(state, type->left);
5627 break;
5628 case TYPE_STRUCT:
5629 case TYPE_TUPLE:
5630 member = type->left;
5631 while(member && (invalid == 0) &&
5632 ((member->type & TYPE_MASK) == TYPE_PRODUCT)) {
5633 invalid = invalid_type(state, member->left);
5634 member = member->right;
5636 if (!invalid) {
5637 invalid = invalid_type(state, member);
5639 break;
5640 case TYPE_UNION:
5641 case TYPE_JOIN:
5642 member = type->left;
5643 while(member && (invalid == 0) &&
5644 ((member->type & TYPE_MASK) == TYPE_OVERLAP)) {
5645 invalid = invalid_type(state, member->left);
5646 member = member->right;
5648 if (!invalid) {
5649 invalid = invalid_type(state, member);
5651 break;
5652 default:
5653 invalid = type;
5654 break;
5656 return invalid;
5660 static struct type void_type = { .type = TYPE_VOID };
5661 static struct type char_type = { .type = TYPE_CHAR };
5662 static struct type uchar_type = { .type = TYPE_UCHAR };
5663 #if DEBUG_ROMCC_WARNING
5664 static struct type short_type = { .type = TYPE_SHORT };
5665 #endif
5666 static struct type ushort_type = { .type = TYPE_USHORT };
5667 static struct type int_type = { .type = TYPE_INT };
5668 static struct type uint_type = { .type = TYPE_UINT };
5669 static struct type long_type = { .type = TYPE_LONG };
5670 static struct type ulong_type = { .type = TYPE_ULONG };
5671 static struct type unknown_type = { .type = TYPE_UNKNOWN };
5673 static struct type void_ptr_type = {
5674 .type = TYPE_POINTER,
5675 .left = &void_type,
5678 #if DEBUG_ROMCC_WARNING
5679 static struct type void_func_type = {
5680 .type = TYPE_FUNCTION,
5681 .left = &void_type,
5682 .right = &void_type,
5684 #endif
5686 static size_t bits_to_bytes(size_t size)
5688 return (size + SIZEOF_CHAR - 1)/SIZEOF_CHAR;
5691 static struct triple *variable(struct compile_state *state, struct type *type)
5693 struct triple *result;
5694 if ((type->type & STOR_MASK) != STOR_PERM) {
5695 result = triple(state, OP_ADECL, type, 0, 0);
5696 generate_lhs_pieces(state, result);
5698 else {
5699 result = triple(state, OP_SDECL, type, 0, 0);
5701 return result;
5704 static void stor_of(FILE *fp, struct type *type)
5706 switch(type->type & STOR_MASK) {
5707 case STOR_AUTO:
5708 fprintf(fp, "auto ");
5709 break;
5710 case STOR_STATIC:
5711 fprintf(fp, "static ");
5712 break;
5713 case STOR_LOCAL:
5714 fprintf(fp, "local ");
5715 break;
5716 case STOR_EXTERN:
5717 fprintf(fp, "extern ");
5718 break;
5719 case STOR_REGISTER:
5720 fprintf(fp, "register ");
5721 break;
5722 case STOR_TYPEDEF:
5723 fprintf(fp, "typedef ");
5724 break;
5725 case STOR_INLINE | STOR_LOCAL:
5726 fprintf(fp, "inline ");
5727 break;
5728 case STOR_INLINE | STOR_STATIC:
5729 fprintf(fp, "static inline");
5730 break;
5731 case STOR_INLINE | STOR_EXTERN:
5732 fprintf(fp, "extern inline");
5733 break;
5734 default:
5735 fprintf(fp, "stor:%x", type->type & STOR_MASK);
5736 break;
5739 static void qual_of(FILE *fp, struct type *type)
5741 if (type->type & QUAL_CONST) {
5742 fprintf(fp, " const");
5744 if (type->type & QUAL_VOLATILE) {
5745 fprintf(fp, " volatile");
5747 if (type->type & QUAL_RESTRICT) {
5748 fprintf(fp, " restrict");
5752 static void name_of(FILE *fp, struct type *type)
5754 unsigned int base_type;
5755 base_type = type->type & TYPE_MASK;
5756 if ((base_type != TYPE_PRODUCT) && (base_type != TYPE_OVERLAP)) {
5757 stor_of(fp, type);
5759 switch(base_type) {
5760 case TYPE_VOID:
5761 fprintf(fp, "void");
5762 qual_of(fp, type);
5763 break;
5764 case TYPE_CHAR:
5765 fprintf(fp, "signed char");
5766 qual_of(fp, type);
5767 break;
5768 case TYPE_UCHAR:
5769 fprintf(fp, "unsigned char");
5770 qual_of(fp, type);
5771 break;
5772 case TYPE_SHORT:
5773 fprintf(fp, "signed short");
5774 qual_of(fp, type);
5775 break;
5776 case TYPE_USHORT:
5777 fprintf(fp, "unsigned short");
5778 qual_of(fp, type);
5779 break;
5780 case TYPE_INT:
5781 fprintf(fp, "signed int");
5782 qual_of(fp, type);
5783 break;
5784 case TYPE_UINT:
5785 fprintf(fp, "unsigned int");
5786 qual_of(fp, type);
5787 break;
5788 case TYPE_LONG:
5789 fprintf(fp, "signed long");
5790 qual_of(fp, type);
5791 break;
5792 case TYPE_ULONG:
5793 fprintf(fp, "unsigned long");
5794 qual_of(fp, type);
5795 break;
5796 case TYPE_POINTER:
5797 name_of(fp, type->left);
5798 fprintf(fp, " * ");
5799 qual_of(fp, type);
5800 break;
5801 case TYPE_PRODUCT:
5802 name_of(fp, type->left);
5803 fprintf(fp, ", ");
5804 name_of(fp, type->right);
5805 break;
5806 case TYPE_OVERLAP:
5807 name_of(fp, type->left);
5808 fprintf(fp, ",| ");
5809 name_of(fp, type->right);
5810 break;
5811 case TYPE_ENUM:
5812 fprintf(fp, "enum %s",
5813 (type->type_ident)? type->type_ident->name : "");
5814 qual_of(fp, type);
5815 break;
5816 case TYPE_STRUCT:
5817 fprintf(fp, "struct %s { ",
5818 (type->type_ident)? type->type_ident->name : "");
5819 name_of(fp, type->left);
5820 fprintf(fp, " } ");
5821 qual_of(fp, type);
5822 break;
5823 case TYPE_UNION:
5824 fprintf(fp, "union %s { ",
5825 (type->type_ident)? type->type_ident->name : "");
5826 name_of(fp, type->left);
5827 fprintf(fp, " } ");
5828 qual_of(fp, type);
5829 break;
5830 case TYPE_FUNCTION:
5831 name_of(fp, type->left);
5832 fprintf(fp, " (*)(");
5833 name_of(fp, type->right);
5834 fprintf(fp, ")");
5835 break;
5836 case TYPE_ARRAY:
5837 name_of(fp, type->left);
5838 fprintf(fp, " [%ld]", (long)(type->elements));
5839 break;
5840 case TYPE_TUPLE:
5841 fprintf(fp, "tuple { ");
5842 name_of(fp, type->left);
5843 fprintf(fp, " } ");
5844 qual_of(fp, type);
5845 break;
5846 case TYPE_JOIN:
5847 fprintf(fp, "join { ");
5848 name_of(fp, type->left);
5849 fprintf(fp, " } ");
5850 qual_of(fp, type);
5851 break;
5852 case TYPE_BITFIELD:
5853 name_of(fp, type->left);
5854 fprintf(fp, " : %d ", type->elements);
5855 qual_of(fp, type);
5856 break;
5857 case TYPE_UNKNOWN:
5858 fprintf(fp, "unknown_t");
5859 break;
5860 default:
5861 fprintf(fp, "????: %x", base_type);
5862 break;
5864 if (type->field_ident && type->field_ident->name) {
5865 fprintf(fp, " .%s", type->field_ident->name);
5869 static size_t align_of(struct compile_state *state, struct type *type)
5871 size_t align;
5872 switch(type->type & TYPE_MASK) {
5873 case TYPE_VOID:
5874 align = 1;
5875 break;
5876 case TYPE_BITFIELD:
5877 align = 1;
5878 break;
5879 case TYPE_CHAR:
5880 case TYPE_UCHAR:
5881 align = ALIGNOF_CHAR;
5882 break;
5883 case TYPE_SHORT:
5884 case TYPE_USHORT:
5885 align = ALIGNOF_SHORT;
5886 break;
5887 case TYPE_INT:
5888 case TYPE_UINT:
5889 case TYPE_ENUM:
5890 align = ALIGNOF_INT;
5891 break;
5892 case TYPE_LONG:
5893 case TYPE_ULONG:
5894 align = ALIGNOF_LONG;
5895 break;
5896 case TYPE_POINTER:
5897 align = ALIGNOF_POINTER;
5898 break;
5899 case TYPE_PRODUCT:
5900 case TYPE_OVERLAP:
5902 size_t left_align, right_align;
5903 left_align = align_of(state, type->left);
5904 right_align = align_of(state, type->right);
5905 align = (left_align >= right_align) ? left_align : right_align;
5906 break;
5908 case TYPE_ARRAY:
5909 align = align_of(state, type->left);
5910 break;
5911 case TYPE_STRUCT:
5912 case TYPE_TUPLE:
5913 case TYPE_UNION:
5914 case TYPE_JOIN:
5915 align = align_of(state, type->left);
5916 break;
5917 default:
5918 error(state, 0, "alignof not yet defined for type\n");
5919 break;
5921 return align;
5924 static size_t reg_align_of(struct compile_state *state, struct type *type)
5926 size_t align;
5927 switch(type->type & TYPE_MASK) {
5928 case TYPE_VOID:
5929 align = 1;
5930 break;
5931 case TYPE_BITFIELD:
5932 align = 1;
5933 break;
5934 case TYPE_CHAR:
5935 case TYPE_UCHAR:
5936 align = REG_ALIGNOF_CHAR;
5937 break;
5938 case TYPE_SHORT:
5939 case TYPE_USHORT:
5940 align = REG_ALIGNOF_SHORT;
5941 break;
5942 case TYPE_INT:
5943 case TYPE_UINT:
5944 case TYPE_ENUM:
5945 align = REG_ALIGNOF_INT;
5946 break;
5947 case TYPE_LONG:
5948 case TYPE_ULONG:
5949 align = REG_ALIGNOF_LONG;
5950 break;
5951 case TYPE_POINTER:
5952 align = REG_ALIGNOF_POINTER;
5953 break;
5954 case TYPE_PRODUCT:
5955 case TYPE_OVERLAP:
5957 size_t left_align, right_align;
5958 left_align = reg_align_of(state, type->left);
5959 right_align = reg_align_of(state, type->right);
5960 align = (left_align >= right_align) ? left_align : right_align;
5961 break;
5963 case TYPE_ARRAY:
5964 align = reg_align_of(state, type->left);
5965 break;
5966 case TYPE_STRUCT:
5967 case TYPE_UNION:
5968 case TYPE_TUPLE:
5969 case TYPE_JOIN:
5970 align = reg_align_of(state, type->left);
5971 break;
5972 default:
5973 error(state, 0, "alignof not yet defined for type\n");
5974 break;
5976 return align;
5979 static size_t align_of_in_bytes(struct compile_state *state, struct type *type)
5981 return bits_to_bytes(align_of(state, type));
5983 static size_t size_of(struct compile_state *state, struct type *type);
5984 static size_t reg_size_of(struct compile_state *state, struct type *type);
5986 static size_t needed_padding(struct compile_state *state,
5987 struct type *type, size_t offset)
5989 size_t padding, align;
5990 align = align_of(state, type);
5991 /* Align to the next machine word if the bitfield does completely
5992 * fit into the current word.
5994 if ((type->type & TYPE_MASK) == TYPE_BITFIELD) {
5995 size_t size;
5996 size = size_of(state, type);
5997 if ((offset + type->elements)/size != offset/size) {
5998 align = size;
6001 padding = 0;
6002 if (offset % align) {
6003 padding = align - (offset % align);
6005 return padding;
6008 static size_t reg_needed_padding(struct compile_state *state,
6009 struct type *type, size_t offset)
6011 size_t padding, align;
6012 align = reg_align_of(state, type);
6013 /* Align to the next register word if the bitfield does completely
6014 * fit into the current register.
6016 if (((type->type & TYPE_MASK) == TYPE_BITFIELD) &&
6017 (((offset + type->elements)/REG_SIZEOF_REG) != (offset/REG_SIZEOF_REG)))
6019 align = REG_SIZEOF_REG;
6021 padding = 0;
6022 if (offset % align) {
6023 padding = align - (offset % align);
6025 return padding;
6028 static size_t size_of(struct compile_state *state, struct type *type)
6030 size_t size;
6031 switch(type->type & TYPE_MASK) {
6032 case TYPE_VOID:
6033 size = 0;
6034 break;
6035 case TYPE_BITFIELD:
6036 size = type->elements;
6037 break;
6038 case TYPE_CHAR:
6039 case TYPE_UCHAR:
6040 size = SIZEOF_CHAR;
6041 break;
6042 case TYPE_SHORT:
6043 case TYPE_USHORT:
6044 size = SIZEOF_SHORT;
6045 break;
6046 case TYPE_INT:
6047 case TYPE_UINT:
6048 case TYPE_ENUM:
6049 size = SIZEOF_INT;
6050 break;
6051 case TYPE_LONG:
6052 case TYPE_ULONG:
6053 size = SIZEOF_LONG;
6054 break;
6055 case TYPE_POINTER:
6056 size = SIZEOF_POINTER;
6057 break;
6058 case TYPE_PRODUCT:
6060 size_t pad;
6061 size = 0;
6062 while((type->type & TYPE_MASK) == TYPE_PRODUCT) {
6063 pad = needed_padding(state, type->left, size);
6064 size = size + pad + size_of(state, type->left);
6065 type = type->right;
6067 pad = needed_padding(state, type, size);
6068 size = size + pad + size_of(state, type);
6069 break;
6071 case TYPE_OVERLAP:
6073 size_t size_left, size_right;
6074 size_left = size_of(state, type->left);
6075 size_right = size_of(state, type->right);
6076 size = (size_left >= size_right)? size_left : size_right;
6077 break;
6079 case TYPE_ARRAY:
6080 if (type->elements == ELEMENT_COUNT_UNSPECIFIED) {
6081 internal_error(state, 0, "Invalid array type");
6082 } else {
6083 size = size_of(state, type->left) * type->elements;
6085 break;
6086 case TYPE_STRUCT:
6087 case TYPE_TUPLE:
6089 size_t pad;
6090 size = size_of(state, type->left);
6091 /* Pad structures so their size is a multiples of their alignment */
6092 pad = needed_padding(state, type, size);
6093 size = size + pad;
6094 break;
6096 case TYPE_UNION:
6097 case TYPE_JOIN:
6099 size_t pad;
6100 size = size_of(state, type->left);
6101 /* Pad unions so their size is a multiple of their alignment */
6102 pad = needed_padding(state, type, size);
6103 size = size + pad;
6104 break;
6106 default:
6107 internal_error(state, 0, "sizeof not yet defined for type");
6108 break;
6110 return size;
6113 static size_t reg_size_of(struct compile_state *state, struct type *type)
6115 size_t size;
6116 switch(type->type & TYPE_MASK) {
6117 case TYPE_VOID:
6118 size = 0;
6119 break;
6120 case TYPE_BITFIELD:
6121 size = type->elements;
6122 break;
6123 case TYPE_CHAR:
6124 case TYPE_UCHAR:
6125 size = REG_SIZEOF_CHAR;
6126 break;
6127 case TYPE_SHORT:
6128 case TYPE_USHORT:
6129 size = REG_SIZEOF_SHORT;
6130 break;
6131 case TYPE_INT:
6132 case TYPE_UINT:
6133 case TYPE_ENUM:
6134 size = REG_SIZEOF_INT;
6135 break;
6136 case TYPE_LONG:
6137 case TYPE_ULONG:
6138 size = REG_SIZEOF_LONG;
6139 break;
6140 case TYPE_POINTER:
6141 size = REG_SIZEOF_POINTER;
6142 break;
6143 case TYPE_PRODUCT:
6145 size_t pad;
6146 size = 0;
6147 while((type->type & TYPE_MASK) == TYPE_PRODUCT) {
6148 pad = reg_needed_padding(state, type->left, size);
6149 size = size + pad + reg_size_of(state, type->left);
6150 type = type->right;
6152 pad = reg_needed_padding(state, type, size);
6153 size = size + pad + reg_size_of(state, type);
6154 break;
6156 case TYPE_OVERLAP:
6158 size_t size_left, size_right;
6159 size_left = reg_size_of(state, type->left);
6160 size_right = reg_size_of(state, type->right);
6161 size = (size_left >= size_right)? size_left : size_right;
6162 break;
6164 case TYPE_ARRAY:
6165 if (type->elements == ELEMENT_COUNT_UNSPECIFIED) {
6166 internal_error(state, 0, "Invalid array type");
6167 } else {
6168 size = reg_size_of(state, type->left) * type->elements;
6170 break;
6171 case TYPE_STRUCT:
6172 case TYPE_TUPLE:
6174 size_t pad;
6175 size = reg_size_of(state, type->left);
6176 /* Pad structures so their size is a multiples of their alignment */
6177 pad = reg_needed_padding(state, type, size);
6178 size = size + pad;
6179 break;
6181 case TYPE_UNION:
6182 case TYPE_JOIN:
6184 size_t pad;
6185 size = reg_size_of(state, type->left);
6186 /* Pad unions so their size is a multiple of their alignment */
6187 pad = reg_needed_padding(state, type, size);
6188 size = size + pad;
6189 break;
6191 default:
6192 internal_error(state, 0, "sizeof not yet defined for type");
6193 break;
6195 return size;
6198 static size_t registers_of(struct compile_state *state, struct type *type)
6200 size_t registers;
6201 registers = reg_size_of(state, type);
6202 registers += REG_SIZEOF_REG - 1;
6203 registers /= REG_SIZEOF_REG;
6204 return registers;
6207 static size_t size_of_in_bytes(struct compile_state *state, struct type *type)
6209 return bits_to_bytes(size_of(state, type));
6212 static size_t field_offset(struct compile_state *state,
6213 struct type *type, struct hash_entry *field)
6215 struct type *member;
6216 size_t size;
6218 size = 0;
6219 member = 0;
6220 if ((type->type & TYPE_MASK) == TYPE_STRUCT) {
6221 member = type->left;
6222 while(member && ((member->type & TYPE_MASK) == TYPE_PRODUCT)) {
6223 size += needed_padding(state, member->left, size);
6224 if (member->left->field_ident == field) {
6225 member = member->left;
6226 break;
6228 size += size_of(state, member->left);
6229 member = member->right;
6231 if (member == NULL)
6232 internal_error(state, 0, "Member is NULL");
6233 size += needed_padding(state, member, size);
6235 else if ((type->type & TYPE_MASK) == TYPE_UNION) {
6236 member = type->left;
6237 while(member && ((member->type & TYPE_MASK) == TYPE_OVERLAP)) {
6238 if (member->left->field_ident == field) {
6239 member = member->left;
6240 break;
6242 member = member->right;
6245 else {
6246 internal_error(state, 0, "field_offset only works on structures and unions");
6249 if (!member || (member->field_ident != field)) {
6250 error(state, 0, "member %s not present", field->name);
6252 return size;
6255 static size_t field_reg_offset(struct compile_state *state,
6256 struct type *type, struct hash_entry *field)
6258 struct type *member;
6259 size_t size;
6261 size = 0;
6262 member = 0;
6263 if ((type->type & TYPE_MASK) == TYPE_STRUCT) {
6264 member = type->left;
6265 while(member && ((member->type & TYPE_MASK) == TYPE_PRODUCT)) {
6266 size += reg_needed_padding(state, member->left, size);
6267 if (member->left->field_ident == field) {
6268 member = member->left;
6269 break;
6271 size += reg_size_of(state, member->left);
6272 member = member->right;
6275 else if ((type->type & TYPE_MASK) == TYPE_UNION) {
6276 member = type->left;
6277 while(member && ((member->type & TYPE_MASK) == TYPE_OVERLAP)) {
6278 if (member->left->field_ident == field) {
6279 member = member->left;
6280 break;
6282 member = member->right;
6285 else {
6286 internal_error(state, 0, "field_reg_offset only works on structures and unions");
6289 if (!member || (member->field_ident != field)) {
6290 error(state, 0, "member %s not present", field->name);
6292 size += reg_needed_padding(state, member, size);
6293 return size;
6296 static struct type *field_type(struct compile_state *state,
6297 struct type *type, struct hash_entry *field)
6299 struct type *member;
6301 member = 0;
6302 if ((type->type & TYPE_MASK) == TYPE_STRUCT) {
6303 member = type->left;
6304 while(member && ((member->type & TYPE_MASK) == TYPE_PRODUCT)) {
6305 if (member->left->field_ident == field) {
6306 member = member->left;
6307 break;
6309 member = member->right;
6312 else if ((type->type & TYPE_MASK) == TYPE_UNION) {
6313 member = type->left;
6314 while(member && ((member->type & TYPE_MASK) == TYPE_OVERLAP)) {
6315 if (member->left->field_ident == field) {
6316 member = member->left;
6317 break;
6319 member = member->right;
6322 else {
6323 internal_error(state, 0, "field_type only works on structures and unions");
6326 if (!member || (member->field_ident != field)) {
6327 error(state, 0, "member %s not present", field->name);
6329 return member;
6332 static size_t index_offset(struct compile_state *state,
6333 struct type *type, ulong_t index)
6335 struct type *member;
6336 size_t size;
6337 size = 0;
6338 if ((type->type & TYPE_MASK) == TYPE_ARRAY) {
6339 size = size_of(state, type->left) * index;
6341 else if ((type->type & TYPE_MASK) == TYPE_TUPLE) {
6342 ulong_t i;
6343 member = type->left;
6344 i = 0;
6345 while(member && ((member->type & TYPE_MASK) == TYPE_PRODUCT)) {
6346 size += needed_padding(state, member->left, size);
6347 if (i == index) {
6348 member = member->left;
6349 break;
6351 size += size_of(state, member->left);
6352 i++;
6353 member = member->right;
6355 if (member == NULL)
6356 internal_error(state, 0, "Member is NULL");
6357 if (i != index) {
6358 internal_error(state, 0, "Missing member index: %u", index);
6360 size += needed_padding(state, member, size);
6362 else if ((type->type & TYPE_MASK) == TYPE_JOIN) {
6363 ulong_t i;
6364 size = 0;
6365 member = type->left;
6366 i = 0;
6367 while(member && ((member->type & TYPE_MASK) == TYPE_OVERLAP)) {
6368 if (i == index) {
6369 break;
6371 i++;
6372 member = member->right;
6374 if (i != index) {
6375 internal_error(state, 0, "Missing member index: %u", index);
6378 else {
6379 internal_error(state, 0,
6380 "request for index %u in something not an array, tuple or join",
6381 index);
6383 return size;
6386 static size_t index_reg_offset(struct compile_state *state,
6387 struct type *type, ulong_t index)
6389 struct type *member;
6390 size_t size;
6391 size = 0;
6392 if ((type->type & TYPE_MASK) == TYPE_ARRAY) {
6393 size = reg_size_of(state, type->left) * index;
6395 else if ((type->type & TYPE_MASK) == TYPE_TUPLE) {
6396 ulong_t i;
6397 member = type->left;
6398 i = 0;
6399 while(member && ((member->type & TYPE_MASK) == TYPE_PRODUCT)) {
6400 size += reg_needed_padding(state, member->left, size);
6401 if (i == index) {
6402 member = member->left;
6403 break;
6405 size += reg_size_of(state, member->left);
6406 i++;
6407 member = member->right;
6409 if (member == NULL)
6410 internal_error(state, 0, "Member is NULL");
6411 if (i != index) {
6412 internal_error(state, 0, "Missing member index: %u", index);
6414 size += reg_needed_padding(state, member, size);
6416 else if ((type->type & TYPE_MASK) == TYPE_JOIN) {
6417 ulong_t i;
6418 size = 0;
6419 member = type->left;
6420 i = 0;
6421 while(member && ((member->type & TYPE_MASK) == TYPE_OVERLAP)) {
6422 if (i == index) {
6423 break;
6425 i++;
6426 member = member->right;
6428 if (i != index) {
6429 internal_error(state, 0, "Missing member index: %u", index);
6432 else {
6433 internal_error(state, 0,
6434 "request for index %u in something not an array, tuple or join",
6435 index);
6437 return size;
6440 static struct type *index_type(struct compile_state *state,
6441 struct type *type, ulong_t index)
6443 struct type *member;
6444 if (index >= type->elements) {
6445 internal_error(state, 0, "Invalid element %u requested", index);
6447 if ((type->type & TYPE_MASK) == TYPE_ARRAY) {
6448 member = type->left;
6450 else if ((type->type & TYPE_MASK) == TYPE_TUPLE) {
6451 ulong_t i;
6452 member = type->left;
6453 i = 0;
6454 while(member && ((member->type & TYPE_MASK) == TYPE_PRODUCT)) {
6455 if (i == index) {
6456 member = member->left;
6457 break;
6459 i++;
6460 member = member->right;
6462 if (i != index) {
6463 internal_error(state, 0, "Missing member index: %u", index);
6466 else if ((type->type & TYPE_MASK) == TYPE_JOIN) {
6467 ulong_t i;
6468 member = type->left;
6469 i = 0;
6470 while(member && ((member->type & TYPE_MASK) == TYPE_OVERLAP)) {
6471 if (i == index) {
6472 member = member->left;
6473 break;
6475 i++;
6476 member = member->right;
6478 if (i != index) {
6479 internal_error(state, 0, "Missing member index: %u", index);
6482 else {
6483 member = 0;
6484 internal_error(state, 0,
6485 "request for index %u in something not an array, tuple or join",
6486 index);
6488 return member;
6491 static struct type *unpack_type(struct compile_state *state, struct type *type)
6493 /* If I have a single register compound type not a bit-field
6494 * find the real type.
6496 struct type *start_type;
6497 size_t size;
6498 /* Get out early if I need multiple registers for this type */
6499 size = reg_size_of(state, type);
6500 if (size > REG_SIZEOF_REG) {
6501 return type;
6503 /* Get out early if I don't need any registers for this type */
6504 if (size == 0) {
6505 return &void_type;
6507 /* Loop until I have no more layers I can remove */
6508 do {
6509 start_type = type;
6510 switch(type->type & TYPE_MASK) {
6511 case TYPE_ARRAY:
6512 /* If I have a single element the unpacked type
6513 * is that element.
6515 if (type->elements == 1) {
6516 type = type->left;
6518 break;
6519 case TYPE_STRUCT:
6520 case TYPE_TUPLE:
6521 /* If I have a single element the unpacked type
6522 * is that element.
6524 if (type->elements == 1) {
6525 type = type->left;
6527 /* If I have multiple elements the unpacked
6528 * type is the non-void element.
6530 else {
6531 struct type *next, *member;
6532 struct type *sub_type;
6533 sub_type = 0;
6534 next = type->left;
6535 while(next) {
6536 member = next;
6537 next = 0;
6538 if ((member->type & TYPE_MASK) == TYPE_PRODUCT) {
6539 next = member->right;
6540 member = member->left;
6542 if (reg_size_of(state, member) > 0) {
6543 if (sub_type) {
6544 internal_error(state, 0, "true compound type in a register");
6546 sub_type = member;
6549 if (sub_type) {
6550 type = sub_type;
6553 break;
6555 case TYPE_UNION:
6556 case TYPE_JOIN:
6557 /* If I have a single element the unpacked type
6558 * is that element.
6560 if (type->elements == 1) {
6561 type = type->left;
6563 /* I can't in general unpack union types */
6564 break;
6565 default:
6566 /* If I'm not a compound type I can't unpack it */
6567 break;
6569 } while(start_type != type);
6570 switch(type->type & TYPE_MASK) {
6571 case TYPE_STRUCT:
6572 case TYPE_ARRAY:
6573 case TYPE_TUPLE:
6574 internal_error(state, 0, "irredicible type?");
6575 break;
6577 return type;
6580 static int equiv_types(struct type *left, struct type *right);
6581 static int is_compound_type(struct type *type);
6583 static struct type *reg_type(
6584 struct compile_state *state, struct type *type, int reg_offset)
6586 struct type *member;
6587 size_t size;
6588 #if 1
6589 struct type *invalid;
6590 invalid = invalid_type(state, type);
6591 if (invalid) {
6592 fprintf(state->errout, "type: ");
6593 name_of(state->errout, type);
6594 fprintf(state->errout, "\n");
6595 fprintf(state->errout, "invalid: ");
6596 name_of(state->errout, invalid);
6597 fprintf(state->errout, "\n");
6598 internal_error(state, 0, "bad input type?");
6600 #endif
6602 size = reg_size_of(state, type);
6603 if (reg_offset > size) {
6604 member = 0;
6605 fprintf(state->errout, "type: ");
6606 name_of(state->errout, type);
6607 fprintf(state->errout, "\n");
6608 internal_error(state, 0, "offset outside of type");
6610 else {
6611 switch(type->type & TYPE_MASK) {
6612 /* Don't do anything with the basic types */
6613 case TYPE_VOID:
6614 case TYPE_CHAR: case TYPE_UCHAR:
6615 case TYPE_SHORT: case TYPE_USHORT:
6616 case TYPE_INT: case TYPE_UINT:
6617 case TYPE_LONG: case TYPE_ULONG:
6618 case TYPE_LLONG: case TYPE_ULLONG:
6619 case TYPE_FLOAT: case TYPE_DOUBLE:
6620 case TYPE_LDOUBLE:
6621 case TYPE_POINTER:
6622 case TYPE_ENUM:
6623 case TYPE_BITFIELD:
6624 member = type;
6625 break;
6626 case TYPE_ARRAY:
6627 member = type->left;
6628 size = reg_size_of(state, member);
6629 if (size > REG_SIZEOF_REG) {
6630 member = reg_type(state, member, reg_offset % size);
6632 break;
6633 case TYPE_STRUCT:
6634 case TYPE_TUPLE:
6636 size_t offset;
6637 offset = 0;
6638 member = type->left;
6639 while(member && ((member->type & TYPE_MASK) == TYPE_PRODUCT)) {
6640 size = reg_size_of(state, member->left);
6641 offset += reg_needed_padding(state, member->left, offset);
6642 if ((offset + size) > reg_offset) {
6643 member = member->left;
6644 break;
6646 offset += size;
6647 member = member->right;
6649 if (member == NULL)
6650 internal_error(state, 0, "Member is NULL");
6651 offset += reg_needed_padding(state, member, offset);
6652 member = reg_type(state, member, reg_offset - offset);
6653 break;
6655 case TYPE_UNION:
6656 case TYPE_JOIN:
6658 struct type *join, **jnext, *mnext;
6659 join = new_type(TYPE_JOIN, 0, 0);
6660 jnext = &join->left;
6661 mnext = type->left;
6662 while(mnext) {
6663 size_t size;
6664 member = mnext;
6665 mnext = 0;
6666 if ((member->type & TYPE_MASK) == TYPE_OVERLAP) {
6667 mnext = member->right;
6668 member = member->left;
6670 size = reg_size_of(state, member);
6671 if (size > reg_offset) {
6672 struct type *part, *hunt;
6673 part = reg_type(state, member, reg_offset);
6674 /* See if this type is already in the union */
6675 hunt = join->left;
6676 while(hunt) {
6677 struct type *test = hunt;
6678 hunt = 0;
6679 if ((test->type & TYPE_MASK) == TYPE_OVERLAP) {
6680 hunt = test->right;
6681 test = test->left;
6683 if (equiv_types(part, test)) {
6684 goto next;
6687 /* Nope add it */
6688 if (!*jnext) {
6689 *jnext = part;
6690 } else {
6691 *jnext = new_type(TYPE_OVERLAP, *jnext, part);
6692 jnext = &(*jnext)->right;
6694 join->elements++;
6696 next:
6699 if (join->elements == 0) {
6700 internal_error(state, 0, "No elements?");
6702 member = join;
6703 break;
6705 default:
6706 member = 0;
6707 fprintf(state->errout, "type: ");
6708 name_of(state->errout, type);
6709 fprintf(state->errout, "\n");
6710 internal_error(state, 0, "reg_type not yet defined for type");
6714 /* If I have a single register compound type not a bit-field
6715 * find the real type.
6717 member = unpack_type(state, member);
6719 size = reg_size_of(state, member);
6720 if (size > REG_SIZEOF_REG) {
6721 internal_error(state, 0, "Cannot find type of single register");
6723 #if 1
6724 invalid = invalid_type(state, member);
6725 if (invalid) {
6726 fprintf(state->errout, "type: ");
6727 name_of(state->errout, member);
6728 fprintf(state->errout, "\n");
6729 fprintf(state->errout, "invalid: ");
6730 name_of(state->errout, invalid);
6731 fprintf(state->errout, "\n");
6732 internal_error(state, 0, "returning bad type?");
6734 #endif
6735 return member;
6738 static struct type *next_field(struct compile_state *state,
6739 struct type *type, struct type *prev_member)
6741 struct type *member;
6742 if ((type->type & TYPE_MASK) != TYPE_STRUCT) {
6743 internal_error(state, 0, "next_field only works on structures");
6745 member = type->left;
6746 while((member->type & TYPE_MASK) == TYPE_PRODUCT) {
6747 if (!prev_member) {
6748 member = member->left;
6749 break;
6751 if (member->left == prev_member) {
6752 prev_member = 0;
6754 member = member->right;
6756 if (member == prev_member) {
6757 prev_member = 0;
6759 if (prev_member) {
6760 internal_error(state, 0, "prev_member %s not present",
6761 prev_member->field_ident->name);
6763 return member;
6766 typedef void (*walk_type_fields_cb_t)(struct compile_state *state, struct type *type,
6767 size_t ret_offset, size_t mem_offset, void *arg);
6769 static void walk_type_fields(struct compile_state *state,
6770 struct type *type, size_t reg_offset, size_t mem_offset,
6771 walk_type_fields_cb_t cb, void *arg);
6773 static void walk_struct_fields(struct compile_state *state,
6774 struct type *type, size_t reg_offset, size_t mem_offset,
6775 walk_type_fields_cb_t cb, void *arg)
6777 struct type *tptr;
6778 ulong_t i;
6779 if ((type->type & TYPE_MASK) != TYPE_STRUCT) {
6780 internal_error(state, 0, "walk_struct_fields only works on structures");
6782 tptr = type->left;
6783 for(i = 0; i < type->elements; i++) {
6784 struct type *mtype;
6785 mtype = tptr;
6786 if ((mtype->type & TYPE_MASK) == TYPE_PRODUCT) {
6787 mtype = mtype->left;
6789 walk_type_fields(state, mtype,
6790 reg_offset +
6791 field_reg_offset(state, type, mtype->field_ident),
6792 mem_offset +
6793 field_offset(state, type, mtype->field_ident),
6794 cb, arg);
6795 tptr = tptr->right;
6800 static void walk_type_fields(struct compile_state *state,
6801 struct type *type, size_t reg_offset, size_t mem_offset,
6802 walk_type_fields_cb_t cb, void *arg)
6804 switch(type->type & TYPE_MASK) {
6805 case TYPE_STRUCT:
6806 walk_struct_fields(state, type, reg_offset, mem_offset, cb, arg);
6807 break;
6808 case TYPE_CHAR:
6809 case TYPE_UCHAR:
6810 case TYPE_SHORT:
6811 case TYPE_USHORT:
6812 case TYPE_INT:
6813 case TYPE_UINT:
6814 case TYPE_LONG:
6815 case TYPE_ULONG:
6816 cb(state, type, reg_offset, mem_offset, arg);
6817 break;
6818 case TYPE_VOID:
6819 break;
6820 default:
6821 internal_error(state, 0, "walk_type_fields not yet implemented for type");
6825 static void arrays_complete(struct compile_state *state, struct type *type)
6827 if ((type->type & TYPE_MASK) == TYPE_ARRAY) {
6828 if (type->elements == ELEMENT_COUNT_UNSPECIFIED) {
6829 error(state, 0, "array size not specified");
6831 arrays_complete(state, type->left);
6835 static unsigned int get_basic_type(struct type *type)
6837 unsigned int basic;
6838 basic = type->type & TYPE_MASK;
6839 /* Convert enums to ints */
6840 if (basic == TYPE_ENUM) {
6841 basic = TYPE_INT;
6843 /* Convert bitfields to standard types */
6844 else if (basic == TYPE_BITFIELD) {
6845 if (type->elements <= SIZEOF_CHAR) {
6846 basic = TYPE_CHAR;
6848 else if (type->elements <= SIZEOF_SHORT) {
6849 basic = TYPE_SHORT;
6851 else if (type->elements <= SIZEOF_INT) {
6852 basic = TYPE_INT;
6854 else if (type->elements <= SIZEOF_LONG) {
6855 basic = TYPE_LONG;
6857 if (!TYPE_SIGNED(type->left->type)) {
6858 basic += 1;
6861 return basic;
6864 static unsigned int do_integral_promotion(unsigned int type)
6866 if (TYPE_INTEGER(type) && (TYPE_RANK(type) < TYPE_RANK(TYPE_INT))) {
6867 type = TYPE_INT;
6869 return type;
6872 static unsigned int do_arithmetic_conversion(
6873 unsigned int left, unsigned int right)
6875 if ((left == TYPE_LDOUBLE) || (right == TYPE_LDOUBLE)) {
6876 return TYPE_LDOUBLE;
6878 else if ((left == TYPE_DOUBLE) || (right == TYPE_DOUBLE)) {
6879 return TYPE_DOUBLE;
6881 else if ((left == TYPE_FLOAT) || (right == TYPE_FLOAT)) {
6882 return TYPE_FLOAT;
6884 left = do_integral_promotion(left);
6885 right = do_integral_promotion(right);
6886 /* If both operands have the same size done */
6887 if (left == right) {
6888 return left;
6890 /* If both operands have the same signedness pick the larger */
6891 else if (!!TYPE_UNSIGNED(left) == !!TYPE_UNSIGNED(right)) {
6892 return (TYPE_RANK(left) >= TYPE_RANK(right)) ? left : right;
6894 /* If the signed type can hold everything use it */
6895 else if (TYPE_SIGNED(left) && (TYPE_RANK(left) > TYPE_RANK(right))) {
6896 return left;
6898 else if (TYPE_SIGNED(right) && (TYPE_RANK(right) > TYPE_RANK(left))) {
6899 return right;
6901 /* Convert to the unsigned type with the same rank as the signed type */
6902 else if (TYPE_SIGNED(left)) {
6903 return TYPE_MKUNSIGNED(left);
6905 else {
6906 return TYPE_MKUNSIGNED(right);
6910 /* see if two types are the same except for qualifiers */
6911 static int equiv_types(struct type *left, struct type *right)
6913 unsigned int type;
6914 /* Error if the basic types do not match */
6915 if ((left->type & TYPE_MASK) != (right->type & TYPE_MASK)) {
6916 return 0;
6918 type = left->type & TYPE_MASK;
6919 /* If the basic types match and it is a void type we are done */
6920 if (type == TYPE_VOID) {
6921 return 1;
6923 /* For bitfields we need to compare the sizes */
6924 else if (type == TYPE_BITFIELD) {
6925 return (left->elements == right->elements) &&
6926 (TYPE_SIGNED(left->left->type) == TYPE_SIGNED(right->left->type));
6928 /* if the basic types match and it is an arithmetic type we are done */
6929 else if (TYPE_ARITHMETIC(type)) {
6930 return 1;
6932 /* If it is a pointer type recurse and keep testing */
6933 else if (type == TYPE_POINTER) {
6934 return equiv_types(left->left, right->left);
6936 else if (type == TYPE_ARRAY) {
6937 return (left->elements == right->elements) &&
6938 equiv_types(left->left, right->left);
6940 /* test for struct equality */
6941 else if (type == TYPE_STRUCT) {
6942 return left->type_ident == right->type_ident;
6944 /* test for union equality */
6945 else if (type == TYPE_UNION) {
6946 return left->type_ident == right->type_ident;
6948 /* Test for equivalent functions */
6949 else if (type == TYPE_FUNCTION) {
6950 return equiv_types(left->left, right->left) &&
6951 equiv_types(left->right, right->right);
6953 /* We only see TYPE_PRODUCT as part of function equivalence matching */
6954 /* We also see TYPE_PRODUCT as part of of tuple equivalence matchin */
6955 else if (type == TYPE_PRODUCT) {
6956 return equiv_types(left->left, right->left) &&
6957 equiv_types(left->right, right->right);
6959 /* We should see TYPE_OVERLAP when comparing joins */
6960 else if (type == TYPE_OVERLAP) {
6961 return equiv_types(left->left, right->left) &&
6962 equiv_types(left->right, right->right);
6964 /* Test for equivalence of tuples */
6965 else if (type == TYPE_TUPLE) {
6966 return (left->elements == right->elements) &&
6967 equiv_types(left->left, right->left);
6969 /* Test for equivalence of joins */
6970 else if (type == TYPE_JOIN) {
6971 return (left->elements == right->elements) &&
6972 equiv_types(left->left, right->left);
6974 else {
6975 return 0;
6979 static int equiv_ptrs(struct type *left, struct type *right)
6981 if (((left->type & TYPE_MASK) != TYPE_POINTER) ||
6982 ((right->type & TYPE_MASK) != TYPE_POINTER)) {
6983 return 0;
6985 return equiv_types(left->left, right->left);
6988 static struct type *compatible_types(struct type *left, struct type *right)
6990 struct type *result;
6991 unsigned int type, qual_type;
6992 /* Error if the basic types do not match */
6993 if ((left->type & TYPE_MASK) != (right->type & TYPE_MASK)) {
6994 return 0;
6996 type = left->type & TYPE_MASK;
6997 qual_type = (left->type & ~STOR_MASK) | (right->type & ~STOR_MASK);
6998 result = 0;
6999 /* if the basic types match and it is an arithmetic type we are done */
7000 if (TYPE_ARITHMETIC(type)) {
7001 result = new_type(qual_type, 0, 0);
7003 /* If it is a pointer type recurse and keep testing */
7004 else if (type == TYPE_POINTER) {
7005 result = compatible_types(left->left, right->left);
7006 if (result) {
7007 result = new_type(qual_type, result, 0);
7010 /* test for struct equality */
7011 else if (type == TYPE_STRUCT) {
7012 if (left->type_ident == right->type_ident) {
7013 result = left;
7016 /* test for union equality */
7017 else if (type == TYPE_UNION) {
7018 if (left->type_ident == right->type_ident) {
7019 result = left;
7022 /* Test for equivalent functions */
7023 else if (type == TYPE_FUNCTION) {
7024 struct type *lf, *rf;
7025 lf = compatible_types(left->left, right->left);
7026 rf = compatible_types(left->right, right->right);
7027 if (lf && rf) {
7028 result = new_type(qual_type, lf, rf);
7031 /* We only see TYPE_PRODUCT as part of function equivalence matching */
7032 else if (type == TYPE_PRODUCT) {
7033 struct type *lf, *rf;
7034 lf = compatible_types(left->left, right->left);
7035 rf = compatible_types(left->right, right->right);
7036 if (lf && rf) {
7037 result = new_type(qual_type, lf, rf);
7040 else {
7041 /* Nothing else is compatible */
7043 return result;
7046 /* See if left is a equivalent to right or right is a union member of left */
7047 static int is_subset_type(struct type *left, struct type *right)
7049 if (equiv_types(left, right)) {
7050 return 1;
7052 if ((left->type & TYPE_MASK) == TYPE_JOIN) {
7053 struct type *member, *mnext;
7054 mnext = left->left;
7055 while(mnext) {
7056 member = mnext;
7057 mnext = 0;
7058 if ((member->type & TYPE_MASK) == TYPE_OVERLAP) {
7059 mnext = member->right;
7060 member = member->left;
7062 if (is_subset_type( member, right)) {
7063 return 1;
7067 return 0;
7070 static struct type *compatible_ptrs(struct type *left, struct type *right)
7072 struct type *result;
7073 if (((left->type & TYPE_MASK) != TYPE_POINTER) ||
7074 ((right->type & TYPE_MASK) != TYPE_POINTER)) {
7075 return 0;
7077 result = compatible_types(left->left, right->left);
7078 if (result) {
7079 unsigned int qual_type;
7080 qual_type = (left->type & ~STOR_MASK) | (right->type & ~STOR_MASK);
7081 result = new_type(qual_type, result, 0);
7083 return result;
7086 static struct triple *integral_promotion(
7087 struct compile_state *state, struct triple *def)
7089 struct type *type;
7090 type = def->type;
7091 /* As all operations are carried out in registers
7092 * the values are converted on load I just convert
7093 * logical type of the operand.
7095 if (TYPE_INTEGER(type->type)) {
7096 unsigned int int_type;
7097 int_type = type->type & ~TYPE_MASK;
7098 int_type |= do_integral_promotion(get_basic_type(type));
7099 if (int_type != type->type) {
7100 if (def->op != OP_LOAD) {
7101 def->type = new_type(int_type, 0, 0);
7103 else {
7104 def = triple(state, OP_CONVERT,
7105 new_type(int_type, 0, 0), def, 0);
7109 return def;
7113 static void arithmetic(struct compile_state *state, struct triple *def)
7115 if (!TYPE_ARITHMETIC(def->type->type)) {
7116 error(state, 0, "arithmetic type expexted");
7120 static void ptr_arithmetic(struct compile_state *state, struct triple *def)
7122 if (!TYPE_PTR(def->type->type) && !TYPE_ARITHMETIC(def->type->type)) {
7123 error(state, def, "pointer or arithmetic type expected");
7127 static int is_integral(struct triple *ins)
7129 return TYPE_INTEGER(ins->type->type);
7132 static void integral(struct compile_state *state, struct triple *def)
7134 if (!is_integral(def)) {
7135 error(state, 0, "integral type expected");
7140 static void bool(struct compile_state *state, struct triple *def)
7142 if (!TYPE_ARITHMETIC(def->type->type) &&
7143 ((def->type->type & TYPE_MASK) != TYPE_POINTER)) {
7144 error(state, 0, "arithmetic or pointer type expected");
7148 static int is_signed(struct type *type)
7150 if ((type->type & TYPE_MASK) == TYPE_BITFIELD) {
7151 type = type->left;
7153 return !!TYPE_SIGNED(type->type);
7155 static int is_compound_type(struct type *type)
7157 int is_compound;
7158 switch((type->type & TYPE_MASK)) {
7159 case TYPE_ARRAY:
7160 case TYPE_STRUCT:
7161 case TYPE_TUPLE:
7162 case TYPE_UNION:
7163 case TYPE_JOIN:
7164 is_compound = 1;
7165 break;
7166 default:
7167 is_compound = 0;
7168 break;
7170 return is_compound;
7173 /* Is this value located in a register otherwise it must be in memory */
7174 static int is_in_reg(struct compile_state *state, struct triple *def)
7176 int in_reg;
7177 if (def->op == OP_ADECL) {
7178 in_reg = 1;
7180 else if ((def->op == OP_SDECL) || (def->op == OP_DEREF)) {
7181 in_reg = 0;
7183 else if (triple_is_part(state, def)) {
7184 in_reg = is_in_reg(state, MISC(def, 0));
7186 else {
7187 internal_error(state, def, "unknown expr storage location");
7188 in_reg = -1;
7190 return in_reg;
7193 /* Is this an auto or static variable location? Something that can
7194 * be assigned to. Otherwise it must must be a pure value, a temporary.
7196 static int is_lvalue(struct compile_state *state, struct triple *def)
7198 int ret;
7199 ret = 0;
7200 if (!def) {
7201 return 0;
7203 if ((def->op == OP_ADECL) ||
7204 (def->op == OP_SDECL) ||
7205 (def->op == OP_DEREF) ||
7206 (def->op == OP_BLOBCONST) ||
7207 (def->op == OP_LIST)) {
7208 ret = 1;
7210 else if (triple_is_part(state, def)) {
7211 ret = is_lvalue(state, MISC(def, 0));
7213 return ret;
7216 static void clvalue(struct compile_state *state, struct triple *def)
7218 if (!def) {
7219 internal_error(state, def, "nothing where lvalue expected?");
7221 if (!is_lvalue(state, def)) {
7222 error(state, def, "lvalue expected");
7225 static void lvalue(struct compile_state *state, struct triple *def)
7227 clvalue(state, def);
7228 if (def->type->type & QUAL_CONST) {
7229 error(state, def, "modifable lvalue expected");
7233 static int is_pointer(struct triple *def)
7235 return (def->type->type & TYPE_MASK) == TYPE_POINTER;
7238 static void pointer(struct compile_state *state, struct triple *def)
7240 if (!is_pointer(def)) {
7241 error(state, def, "pointer expected");
7245 static struct triple *int_const(
7246 struct compile_state *state, struct type *type, ulong_t value)
7248 struct triple *result;
7249 switch(type->type & TYPE_MASK) {
7250 case TYPE_CHAR:
7251 case TYPE_INT: case TYPE_UINT:
7252 case TYPE_LONG: case TYPE_ULONG:
7253 break;
7254 default:
7255 internal_error(state, 0, "constant for unknown type");
7257 result = triple(state, OP_INTCONST, type, 0, 0);
7258 result->u.cval = value;
7259 return result;
7263 static struct triple *read_expr(struct compile_state *state, struct triple *def);
7265 static struct triple *do_mk_addr_expr(struct compile_state *state,
7266 struct triple *expr, struct type *type, ulong_t offset)
7268 struct triple *result;
7269 clvalue(state, expr);
7272 result = 0;
7273 if (expr->op == OP_ADECL) {
7274 error(state, expr, "address of auto variables not supported");
7276 else if (expr->op == OP_SDECL) {
7277 struct type *ptr_type;
7278 ptr_type = new_type(TYPE_POINTER | (type->type & QUAL_MASK), type, 0);
7280 result = triple(state, OP_ADDRCONST, ptr_type, 0, 0);
7281 MISC(result, 0) = expr;
7282 result->u.cval = offset;
7284 else if (expr->op == OP_DEREF) {
7285 struct type *ptr_type;
7286 ptr_type = new_type(TYPE_POINTER | (type->type & QUAL_MASK), type, 0);
7288 result = triple(state, OP_ADD, ptr_type,
7289 RHS(expr, 0),
7290 int_const(state, &ulong_type, offset));
7292 else if (expr->op == OP_BLOBCONST) {
7293 FINISHME();
7294 internal_error(state, expr, "not yet implemented");
7296 else if (expr->op == OP_LIST) {
7297 error(state, 0, "Function addresses not supported");
7299 else if (triple_is_part(state, expr)) {
7300 struct triple *part;
7301 part = expr;
7302 expr = MISC(expr, 0);
7303 if (part->op == OP_DOT) {
7304 offset += bits_to_bytes(
7305 field_offset(state, expr->type, part->u.field));
7307 else if (part->op == OP_INDEX) {
7308 offset += bits_to_bytes(
7309 index_offset(state, expr->type, part->u.cval));
7311 else {
7312 internal_error(state, part, "unhandled part type");
7314 result = do_mk_addr_expr(state, expr, type, offset);
7316 if (!result) {
7317 internal_error(state, expr, "cannot take address of expression");
7319 return result;
7322 static struct triple *mk_addr_expr(
7323 struct compile_state *state, struct triple *expr, ulong_t offset)
7325 return do_mk_addr_expr(state, expr, expr->type, offset);
7328 static struct triple *mk_deref_expr(
7329 struct compile_state *state, struct triple *expr)
7331 struct type *base_type;
7332 pointer(state, expr);
7333 base_type = expr->type->left;
7334 return triple(state, OP_DEREF, base_type, expr, 0);
7337 /* lvalue conversions always apply except when certain operators
7338 * are applied. So I apply apply it when I know no more
7339 * operators will be applied.
7341 static struct triple *lvalue_conversion(struct compile_state *state, struct triple *def)
7343 /* Tranform an array to a pointer to the first element */
7344 if ((def->type->type & TYPE_MASK) == TYPE_ARRAY) {
7345 struct type *type;
7346 type = new_type(
7347 TYPE_POINTER | (def->type->type & QUAL_MASK),
7348 def->type->left, 0);
7349 if ((def->op == OP_SDECL) || IS_CONST_OP(def->op)) {
7350 struct triple *addrconst;
7351 if ((def->op != OP_SDECL) && (def->op != OP_BLOBCONST)) {
7352 internal_error(state, def, "bad array constant");
7354 addrconst = triple(state, OP_ADDRCONST, type, 0, 0);
7355 MISC(addrconst, 0) = def;
7356 def = addrconst;
7358 else {
7359 def = triple(state, OP_CONVERT, type, def, 0);
7362 /* Transform a function to a pointer to it */
7363 else if ((def->type->type & TYPE_MASK) == TYPE_FUNCTION) {
7364 def = mk_addr_expr(state, def, 0);
7366 return def;
7369 static struct triple *deref_field(
7370 struct compile_state *state, struct triple *expr, struct hash_entry *field)
7372 struct triple *result;
7373 struct type *type, *member;
7374 ulong_t offset;
7375 if (!field) {
7376 internal_error(state, 0, "No field passed to deref_field");
7378 result = 0;
7379 type = expr->type;
7380 if (((type->type & TYPE_MASK) != TYPE_STRUCT) &&
7381 ((type->type & TYPE_MASK) != TYPE_UNION)) {
7382 error(state, 0, "request for member %s in something not a struct or union",
7383 field->name);
7385 member = field_type(state, type, field);
7386 if ((type->type & STOR_MASK) == STOR_PERM) {
7387 /* Do the pointer arithmetic to get a deref the field */
7388 offset = bits_to_bytes(field_offset(state, type, field));
7389 result = do_mk_addr_expr(state, expr, member, offset);
7390 result = mk_deref_expr(state, result);
7392 else {
7393 /* Find the variable for the field I want. */
7394 result = triple(state, OP_DOT, member, expr, 0);
7395 result->u.field = field;
7397 return result;
7400 static struct triple *deref_index(
7401 struct compile_state *state, struct triple *expr, size_t index)
7403 struct triple *result;
7404 struct type *type, *member;
7405 ulong_t offset;
7407 result = 0;
7408 type = expr->type;
7409 member = index_type(state, type, index);
7411 if ((type->type & STOR_MASK) == STOR_PERM) {
7412 offset = bits_to_bytes(index_offset(state, type, index));
7413 result = do_mk_addr_expr(state, expr, member, offset);
7414 result = mk_deref_expr(state, result);
7416 else {
7417 result = triple(state, OP_INDEX, member, expr, 0);
7418 result->u.cval = index;
7420 return result;
7423 static struct triple *read_expr(struct compile_state *state, struct triple *def)
7425 int op;
7426 if (!def) {
7427 return 0;
7429 #if DEBUG_ROMCC_WARNINGS
7430 #warning "CHECK_ME is this the only place I need to do lvalue conversions?"
7431 #endif
7432 /* Transform lvalues into something we can read */
7433 def = lvalue_conversion(state, def);
7434 if (!is_lvalue(state, def)) {
7435 return def;
7437 if (is_in_reg(state, def)) {
7438 op = OP_READ;
7439 } else {
7440 if (def->op == OP_SDECL) {
7441 def = mk_addr_expr(state, def, 0);
7442 def = mk_deref_expr(state, def);
7444 op = OP_LOAD;
7446 def = triple(state, op, def->type, def, 0);
7447 if (def->type->type & QUAL_VOLATILE) {
7448 def->id |= TRIPLE_FLAG_VOLATILE;
7450 return def;
7453 int is_write_compatible(struct compile_state *state,
7454 struct type *dest, struct type *rval)
7456 int compatible = 0;
7457 /* Both operands have arithmetic type */
7458 if (TYPE_ARITHMETIC(dest->type) && TYPE_ARITHMETIC(rval->type)) {
7459 compatible = 1;
7461 /* One operand is a pointer and the other is a pointer to void */
7462 else if (((dest->type & TYPE_MASK) == TYPE_POINTER) &&
7463 ((rval->type & TYPE_MASK) == TYPE_POINTER) &&
7464 (((dest->left->type & TYPE_MASK) == TYPE_VOID) ||
7465 ((rval->left->type & TYPE_MASK) == TYPE_VOID))) {
7466 compatible = 1;
7468 /* If both types are the same without qualifiers we are good */
7469 else if (equiv_ptrs(dest, rval)) {
7470 compatible = 1;
7472 /* test for struct/union equality */
7473 else if (equiv_types(dest, rval)) {
7474 compatible = 1;
7476 return compatible;
7479 static void write_compatible(struct compile_state *state,
7480 struct type *dest, struct type *rval)
7482 if (!is_write_compatible(state, dest, rval)) {
7483 FILE *fp = state->errout;
7484 fprintf(fp, "dest: ");
7485 name_of(fp, dest);
7486 fprintf(fp,"\nrval: ");
7487 name_of(fp, rval);
7488 fprintf(fp, "\n");
7489 error(state, 0, "Incompatible types in assignment");
7493 static int is_init_compatible(struct compile_state *state,
7494 struct type *dest, struct type *rval)
7496 int compatible = 0;
7497 if (is_write_compatible(state, dest, rval)) {
7498 compatible = 1;
7500 else if (equiv_types(dest, rval)) {
7501 compatible = 1;
7503 return compatible;
7506 static struct triple *write_expr(
7507 struct compile_state *state, struct triple *dest, struct triple *rval)
7509 struct triple *def;
7511 def = 0;
7512 if (!rval) {
7513 internal_error(state, 0, "missing rval");
7516 if (rval->op == OP_LIST) {
7517 internal_error(state, 0, "expression of type OP_LIST?");
7519 if (!is_lvalue(state, dest)) {
7520 internal_error(state, 0, "writing to a non lvalue?");
7522 if (dest->type->type & QUAL_CONST) {
7523 internal_error(state, 0, "modifable lvalue expexted");
7526 write_compatible(state, dest->type, rval->type);
7527 if (!equiv_types(dest->type, rval->type)) {
7528 rval = triple(state, OP_CONVERT, dest->type, rval, 0);
7531 /* Now figure out which assignment operator to use */
7532 if (is_in_reg(state, dest)) {
7533 def = triple(state, OP_WRITE, dest->type, rval, dest);
7534 if (MISC(def, 0) != dest) {
7535 internal_error(state, def, "huh?");
7537 if (RHS(def, 0) != rval) {
7538 internal_error(state, def, "huh?");
7540 } else {
7541 def = triple(state, OP_STORE, dest->type, dest, rval);
7543 if (def->type->type & QUAL_VOLATILE) {
7544 def->id |= TRIPLE_FLAG_VOLATILE;
7546 return def;
7549 static struct triple *init_expr(
7550 struct compile_state *state, struct triple *dest, struct triple *rval)
7552 struct triple *def;
7554 def = 0;
7555 if (!rval) {
7556 internal_error(state, 0, "missing rval");
7558 if ((dest->type->type & STOR_MASK) != STOR_PERM) {
7559 rval = read_expr(state, rval);
7560 def = write_expr(state, dest, rval);
7562 else {
7563 /* Fill in the array size if necessary */
7564 if (((dest->type->type & TYPE_MASK) == TYPE_ARRAY) &&
7565 ((rval->type->type & TYPE_MASK) == TYPE_ARRAY)) {
7566 if (dest->type->elements == ELEMENT_COUNT_UNSPECIFIED) {
7567 dest->type->elements = rval->type->elements;
7570 if (!equiv_types(dest->type, rval->type)) {
7571 error(state, 0, "Incompatible types in inializer");
7573 MISC(dest, 0) = rval;
7574 insert_triple(state, dest, rval);
7575 rval->id |= TRIPLE_FLAG_FLATTENED;
7576 use_triple(MISC(dest, 0), dest);
7578 return def;
7581 struct type *arithmetic_result(
7582 struct compile_state *state, struct triple *left, struct triple *right)
7584 struct type *type;
7585 /* Sanity checks to ensure I am working with arithmetic types */
7586 arithmetic(state, left);
7587 arithmetic(state, right);
7588 type = new_type(
7589 do_arithmetic_conversion(
7590 get_basic_type(left->type),
7591 get_basic_type(right->type)),
7592 0, 0);
7593 return type;
7596 struct type *ptr_arithmetic_result(
7597 struct compile_state *state, struct triple *left, struct triple *right)
7599 struct type *type;
7600 /* Sanity checks to ensure I am working with the proper types */
7601 ptr_arithmetic(state, left);
7602 arithmetic(state, right);
7603 if (TYPE_ARITHMETIC(left->type->type) &&
7604 TYPE_ARITHMETIC(right->type->type)) {
7605 type = arithmetic_result(state, left, right);
7607 else if (TYPE_PTR(left->type->type)) {
7608 type = left->type;
7610 else {
7611 internal_error(state, 0, "huh?");
7612 type = 0;
7614 return type;
7617 /* boolean helper function */
7619 static struct triple *ltrue_expr(struct compile_state *state,
7620 struct triple *expr)
7622 switch(expr->op) {
7623 case OP_LTRUE: case OP_LFALSE: case OP_EQ: case OP_NOTEQ:
7624 case OP_SLESS: case OP_ULESS: case OP_SMORE: case OP_UMORE:
7625 case OP_SLESSEQ: case OP_ULESSEQ: case OP_SMOREEQ: case OP_UMOREEQ:
7626 /* If the expression is already boolean do nothing */
7627 break;
7628 default:
7629 expr = triple(state, OP_LTRUE, &int_type, expr, 0);
7630 break;
7632 return expr;
7635 static struct triple *lfalse_expr(struct compile_state *state,
7636 struct triple *expr)
7638 return triple(state, OP_LFALSE, &int_type, expr, 0);
7641 static struct triple *mkland_expr(
7642 struct compile_state *state,
7643 struct triple *left, struct triple *right)
7645 struct triple *def, *val, *var, *jmp, *mid, *end;
7646 struct triple *lstore, *rstore;
7648 /* Generate some intermediate triples */
7649 end = label(state);
7650 var = variable(state, &int_type);
7652 /* Store the left hand side value */
7653 lstore = write_expr(state, var, left);
7655 /* Jump if the value is false */
7656 jmp = branch(state, end,
7657 lfalse_expr(state, read_expr(state, var)));
7658 mid = label(state);
7660 /* Store the right hand side value */
7661 rstore = write_expr(state, var, right);
7663 /* An expression for the computed value */
7664 val = read_expr(state, var);
7666 /* Generate the prog for a logical and */
7667 def = mkprog(state, var, lstore, jmp, mid, rstore, end, val, 0UL);
7669 return def;
7672 static struct triple *mklor_expr(
7673 struct compile_state *state,
7674 struct triple *left, struct triple *right)
7676 struct triple *def, *val, *var, *jmp, *mid, *end;
7678 /* Generate some intermediate triples */
7679 end = label(state);
7680 var = variable(state, &int_type);
7682 /* Store the left hand side value */
7683 left = write_expr(state, var, left);
7685 /* Jump if the value is true */
7686 jmp = branch(state, end, read_expr(state, var));
7687 mid = label(state);
7689 /* Store the right hand side value */
7690 right = write_expr(state, var, right);
7692 /* An expression for the computed value*/
7693 val = read_expr(state, var);
7695 /* Generate the prog for a logical or */
7696 def = mkprog(state, var, left, jmp, mid, right, end, val, 0UL);
7698 return def;
7701 static struct triple *mkcond_expr(
7702 struct compile_state *state,
7703 struct triple *test, struct triple *left, struct triple *right)
7705 struct triple *def, *val, *var, *jmp1, *jmp2, *top, *mid, *end;
7706 struct type *result_type;
7707 unsigned int left_type, right_type;
7708 bool(state, test);
7709 left_type = left->type->type;
7710 right_type = right->type->type;
7711 result_type = 0;
7712 /* Both operands have arithmetic type */
7713 if (TYPE_ARITHMETIC(left_type) && TYPE_ARITHMETIC(right_type)) {
7714 result_type = arithmetic_result(state, left, right);
7716 /* Both operands have void type */
7717 else if (((left_type & TYPE_MASK) == TYPE_VOID) &&
7718 ((right_type & TYPE_MASK) == TYPE_VOID)) {
7719 result_type = &void_type;
7721 /* pointers to the same type... */
7722 else if ((result_type = compatible_ptrs(left->type, right->type))) {
7725 /* Both operands are pointers and left is a pointer to void */
7726 else if (((left_type & TYPE_MASK) == TYPE_POINTER) &&
7727 ((right_type & TYPE_MASK) == TYPE_POINTER) &&
7728 ((left->type->left->type & TYPE_MASK) == TYPE_VOID)) {
7729 result_type = right->type;
7731 /* Both operands are pointers and right is a pointer to void */
7732 else if (((left_type & TYPE_MASK) == TYPE_POINTER) &&
7733 ((right_type & TYPE_MASK) == TYPE_POINTER) &&
7734 ((right->type->left->type & TYPE_MASK) == TYPE_VOID)) {
7735 result_type = left->type;
7737 if (!result_type) {
7738 error(state, 0, "Incompatible types in conditional expression");
7740 /* Generate some intermediate triples */
7741 mid = label(state);
7742 end = label(state);
7743 var = variable(state, result_type);
7745 /* Branch if the test is false */
7746 jmp1 = branch(state, mid, lfalse_expr(state, read_expr(state, test)));
7747 top = label(state);
7749 /* Store the left hand side value */
7750 left = write_expr(state, var, left);
7752 /* Branch to the end */
7753 jmp2 = branch(state, end, 0);
7755 /* Store the right hand side value */
7756 right = write_expr(state, var, right);
7758 /* An expression for the computed value */
7759 val = read_expr(state, var);
7761 /* Generate the prog for a conditional expression */
7762 def = mkprog(state, var, jmp1, top, left, jmp2, mid, right, end, val, 0UL);
7764 return def;
7768 static int expr_depth(struct compile_state *state, struct triple *ins)
7770 #if DEBUG_ROMCC_WARNINGS
7771 #warning "FIXME move optimal ordering of subexpressions into the optimizer"
7772 #endif
7773 int count;
7774 count = 0;
7775 if (!ins || (ins->id & TRIPLE_FLAG_FLATTENED)) {
7776 count = 0;
7778 else if (ins->op == OP_DEREF) {
7779 count = expr_depth(state, RHS(ins, 0)) - 1;
7781 else if (ins->op == OP_VAL) {
7782 count = expr_depth(state, RHS(ins, 0)) - 1;
7784 else if (ins->op == OP_FCALL) {
7785 /* Don't figure the depth of a call just guess it is huge */
7786 count = 1000;
7788 else {
7789 struct triple **expr;
7790 expr = triple_rhs(state, ins, 0);
7791 for(;expr; expr = triple_rhs(state, ins, expr)) {
7792 if (*expr) {
7793 int depth;
7794 depth = expr_depth(state, *expr);
7795 if (depth > count) {
7796 count = depth;
7801 return count + 1;
7804 static struct triple *flatten_generic(
7805 struct compile_state *state, struct triple *first, struct triple *ptr,
7806 int ignored)
7808 struct rhs_vector {
7809 int depth;
7810 struct triple **ins;
7811 } vector[MAX_RHS];
7812 int i, rhs, lhs;
7813 /* Only operations with just a rhs and a lhs should come here */
7814 rhs = ptr->rhs;
7815 lhs = ptr->lhs;
7816 if (TRIPLE_SIZE(ptr) != lhs + rhs + ignored) {
7817 internal_error(state, ptr, "unexpected args for: %d %s",
7818 ptr->op, tops(ptr->op));
7820 /* Find the depth of the rhs elements */
7821 for(i = 0; i < rhs; i++) {
7822 vector[i].ins = &RHS(ptr, i);
7823 vector[i].depth = expr_depth(state, *vector[i].ins);
7825 /* Selection sort the rhs */
7826 for(i = 0; i < rhs; i++) {
7827 int j, max = i;
7828 for(j = i + 1; j < rhs; j++ ) {
7829 if (vector[j].depth > vector[max].depth) {
7830 max = j;
7833 if (max != i) {
7834 struct rhs_vector tmp;
7835 tmp = vector[i];
7836 vector[i] = vector[max];
7837 vector[max] = tmp;
7840 /* Now flatten the rhs elements */
7841 for(i = 0; i < rhs; i++) {
7842 *vector[i].ins = flatten(state, first, *vector[i].ins);
7843 use_triple(*vector[i].ins, ptr);
7845 if (lhs) {
7846 insert_triple(state, first, ptr);
7847 ptr->id |= TRIPLE_FLAG_FLATTENED;
7848 ptr->id &= ~TRIPLE_FLAG_LOCAL;
7850 /* Now flatten the lhs elements */
7851 for(i = 0; i < lhs; i++) {
7852 struct triple **ins = &LHS(ptr, i);
7853 *ins = flatten(state, first, *ins);
7854 use_triple(*ins, ptr);
7857 return ptr;
7860 static struct triple *flatten_prog(
7861 struct compile_state *state, struct triple *first, struct triple *ptr)
7863 struct triple *head, *body, *val;
7864 head = RHS(ptr, 0);
7865 RHS(ptr, 0) = 0;
7866 val = head->prev;
7867 body = head->next;
7868 release_triple(state, head);
7869 release_triple(state, ptr);
7870 val->next = first;
7871 body->prev = first->prev;
7872 body->prev->next = body;
7873 val->next->prev = val;
7875 if (triple_is_cbranch(state, body->prev) ||
7876 triple_is_call(state, body->prev)) {
7877 unuse_triple(first, body->prev);
7878 use_triple(body, body->prev);
7881 if (!(val->id & TRIPLE_FLAG_FLATTENED)) {
7882 internal_error(state, val, "val not flattened?");
7885 return val;
7889 static struct triple *flatten_part(
7890 struct compile_state *state, struct triple *first, struct triple *ptr)
7892 if (!triple_is_part(state, ptr)) {
7893 internal_error(state, ptr, "not a part");
7895 if (ptr->rhs || ptr->lhs || ptr->targ || (ptr->misc != 1)) {
7896 internal_error(state, ptr, "unexpected args for: %d %s",
7897 ptr->op, tops(ptr->op));
7899 MISC(ptr, 0) = flatten(state, first, MISC(ptr, 0));
7900 use_triple(MISC(ptr, 0), ptr);
7901 return flatten_generic(state, first, ptr, 1);
7904 static struct triple *flatten(
7905 struct compile_state *state, struct triple *first, struct triple *ptr)
7907 struct triple *orig_ptr;
7908 if (!ptr)
7909 return 0;
7910 do {
7911 orig_ptr = ptr;
7912 /* Only flatten triples once */
7913 if (ptr->id & TRIPLE_FLAG_FLATTENED) {
7914 return ptr;
7916 switch(ptr->op) {
7917 case OP_VAL:
7918 RHS(ptr, 0) = flatten(state, first, RHS(ptr, 0));
7919 return MISC(ptr, 0);
7920 break;
7921 case OP_PROG:
7922 ptr = flatten_prog(state, first, ptr);
7923 break;
7924 case OP_FCALL:
7925 ptr = flatten_generic(state, first, ptr, 1);
7926 insert_triple(state, first, ptr);
7927 ptr->id |= TRIPLE_FLAG_FLATTENED;
7928 ptr->id &= ~TRIPLE_FLAG_LOCAL;
7929 if (ptr->next != ptr) {
7930 use_triple(ptr->next, ptr);
7932 break;
7933 case OP_READ:
7934 case OP_LOAD:
7935 RHS(ptr, 0) = flatten(state, first, RHS(ptr, 0));
7936 use_triple(RHS(ptr, 0), ptr);
7937 break;
7938 case OP_WRITE:
7939 ptr = flatten_generic(state, first, ptr, 1);
7940 MISC(ptr, 0) = flatten(state, first, MISC(ptr, 0));
7941 use_triple(MISC(ptr, 0), ptr);
7942 break;
7943 case OP_BRANCH:
7944 use_triple(TARG(ptr, 0), ptr);
7945 break;
7946 case OP_CBRANCH:
7947 RHS(ptr, 0) = flatten(state, first, RHS(ptr, 0));
7948 use_triple(RHS(ptr, 0), ptr);
7949 use_triple(TARG(ptr, 0), ptr);
7950 insert_triple(state, first, ptr);
7951 ptr->id |= TRIPLE_FLAG_FLATTENED;
7952 ptr->id &= ~TRIPLE_FLAG_LOCAL;
7953 if (ptr->next != ptr) {
7954 use_triple(ptr->next, ptr);
7956 break;
7957 case OP_CALL:
7958 MISC(ptr, 0) = flatten(state, first, MISC(ptr, 0));
7959 use_triple(MISC(ptr, 0), ptr);
7960 use_triple(TARG(ptr, 0), ptr);
7961 insert_triple(state, first, ptr);
7962 ptr->id |= TRIPLE_FLAG_FLATTENED;
7963 ptr->id &= ~TRIPLE_FLAG_LOCAL;
7964 if (ptr->next != ptr) {
7965 use_triple(ptr->next, ptr);
7967 break;
7968 case OP_RET:
7969 RHS(ptr, 0) = flatten(state, first, RHS(ptr, 0));
7970 use_triple(RHS(ptr, 0), ptr);
7971 break;
7972 case OP_BLOBCONST:
7973 insert_triple(state, state->global_pool, ptr);
7974 ptr->id |= TRIPLE_FLAG_FLATTENED;
7975 ptr->id &= ~TRIPLE_FLAG_LOCAL;
7976 ptr = triple(state, OP_SDECL, ptr->type, ptr, 0);
7977 use_triple(MISC(ptr, 0), ptr);
7978 break;
7979 case OP_DEREF:
7980 /* Since OP_DEREF is just a marker delete it when I flatten it */
7981 ptr = RHS(ptr, 0);
7982 RHS(orig_ptr, 0) = 0;
7983 free_triple(state, orig_ptr);
7984 break;
7985 case OP_DOT:
7986 if (RHS(ptr, 0)->op == OP_DEREF) {
7987 struct triple *base, *left;
7988 ulong_t offset;
7989 base = MISC(ptr, 0);
7990 offset = bits_to_bytes(field_offset(state, base->type, ptr->u.field));
7991 left = RHS(base, 0);
7992 ptr = triple(state, OP_ADD, left->type,
7993 read_expr(state, left),
7994 int_const(state, &ulong_type, offset));
7995 free_triple(state, base);
7997 else {
7998 ptr = flatten_part(state, first, ptr);
8000 break;
8001 case OP_INDEX:
8002 if (RHS(ptr, 0)->op == OP_DEREF) {
8003 struct triple *base, *left;
8004 ulong_t offset;
8005 base = MISC(ptr, 0);
8006 offset = bits_to_bytes(index_offset(state, base->type, ptr->u.cval));
8007 left = RHS(base, 0);
8008 ptr = triple(state, OP_ADD, left->type,
8009 read_expr(state, left),
8010 int_const(state, &long_type, offset));
8011 free_triple(state, base);
8013 else {
8014 ptr = flatten_part(state, first, ptr);
8016 break;
8017 case OP_PIECE:
8018 ptr = flatten_part(state, first, ptr);
8019 use_triple(ptr, MISC(ptr, 0));
8020 break;
8021 case OP_ADDRCONST:
8022 MISC(ptr, 0) = flatten(state, first, MISC(ptr, 0));
8023 use_triple(MISC(ptr, 0), ptr);
8024 break;
8025 case OP_SDECL:
8026 first = state->global_pool;
8027 MISC(ptr, 0) = flatten(state, first, MISC(ptr, 0));
8028 use_triple(MISC(ptr, 0), ptr);
8029 insert_triple(state, first, ptr);
8030 ptr->id |= TRIPLE_FLAG_FLATTENED;
8031 ptr->id &= ~TRIPLE_FLAG_LOCAL;
8032 return ptr;
8033 case OP_ADECL:
8034 ptr = flatten_generic(state, first, ptr, 0);
8035 break;
8036 default:
8037 /* Flatten the easy cases we don't override */
8038 ptr = flatten_generic(state, first, ptr, 0);
8039 break;
8041 } while(ptr && (ptr != orig_ptr));
8042 if (ptr && !(ptr->id & TRIPLE_FLAG_FLATTENED)) {
8043 insert_triple(state, first, ptr);
8044 ptr->id |= TRIPLE_FLAG_FLATTENED;
8045 ptr->id &= ~TRIPLE_FLAG_LOCAL;
8047 return ptr;
8050 static void release_expr(struct compile_state *state, struct triple *expr)
8052 struct triple *head;
8053 head = label(state);
8054 flatten(state, head, expr);
8055 while(head->next != head) {
8056 release_triple(state, head->next);
8058 free_triple(state, head);
8061 static int replace_rhs_use(struct compile_state *state,
8062 struct triple *orig, struct triple *new, struct triple *use)
8064 struct triple **expr;
8065 int found;
8066 found = 0;
8067 expr = triple_rhs(state, use, 0);
8068 for(;expr; expr = triple_rhs(state, use, expr)) {
8069 if (*expr == orig) {
8070 *expr = new;
8071 found = 1;
8074 if (found) {
8075 unuse_triple(orig, use);
8076 use_triple(new, use);
8078 return found;
8081 static int replace_lhs_use(struct compile_state *state,
8082 struct triple *orig, struct triple *new, struct triple *use)
8084 struct triple **expr;
8085 int found;
8086 found = 0;
8087 expr = triple_lhs(state, use, 0);
8088 for(;expr; expr = triple_lhs(state, use, expr)) {
8089 if (*expr == orig) {
8090 *expr = new;
8091 found = 1;
8094 if (found) {
8095 unuse_triple(orig, use);
8096 use_triple(new, use);
8098 return found;
8101 static int replace_misc_use(struct compile_state *state,
8102 struct triple *orig, struct triple *new, struct triple *use)
8104 struct triple **expr;
8105 int found;
8106 found = 0;
8107 expr = triple_misc(state, use, 0);
8108 for(;expr; expr = triple_misc(state, use, expr)) {
8109 if (*expr == orig) {
8110 *expr = new;
8111 found = 1;
8114 if (found) {
8115 unuse_triple(orig, use);
8116 use_triple(new, use);
8118 return found;
8121 static int replace_targ_use(struct compile_state *state,
8122 struct triple *orig, struct triple *new, struct triple *use)
8124 struct triple **expr;
8125 int found;
8126 found = 0;
8127 expr = triple_targ(state, use, 0);
8128 for(;expr; expr = triple_targ(state, use, expr)) {
8129 if (*expr == orig) {
8130 *expr = new;
8131 found = 1;
8134 if (found) {
8135 unuse_triple(orig, use);
8136 use_triple(new, use);
8138 return found;
8141 static void replace_use(struct compile_state *state,
8142 struct triple *orig, struct triple *new, struct triple *use)
8144 int found;
8145 found = 0;
8146 found |= replace_rhs_use(state, orig, new, use);
8147 found |= replace_lhs_use(state, orig, new, use);
8148 found |= replace_misc_use(state, orig, new, use);
8149 found |= replace_targ_use(state, orig, new, use);
8150 if (!found) {
8151 internal_error(state, use, "use without use");
8155 static void propagate_use(struct compile_state *state,
8156 struct triple *orig, struct triple *new)
8158 struct triple_set *user, *next;
8159 for(user = orig->use; user; user = next) {
8160 /* Careful replace_use modifies the use chain and
8161 * removes use. So we must get a copy of the next
8162 * entry early.
8164 next = user->next;
8165 replace_use(state, orig, new, user->member);
8167 if (orig->use) {
8168 internal_error(state, orig, "used after propagate_use");
8173 * Code generators
8174 * ===========================
8177 static struct triple *mk_cast_expr(
8178 struct compile_state *state, struct type *type, struct triple *expr)
8180 struct triple *def;
8181 def = read_expr(state, expr);
8182 def = triple(state, OP_CONVERT, type, def, 0);
8183 return def;
8186 static struct triple *mk_add_expr(
8187 struct compile_state *state, struct triple *left, struct triple *right)
8189 struct type *result_type;
8190 /* Put pointer operands on the left */
8191 if (is_pointer(right)) {
8192 struct triple *tmp;
8193 tmp = left;
8194 left = right;
8195 right = tmp;
8197 left = read_expr(state, left);
8198 right = read_expr(state, right);
8199 result_type = ptr_arithmetic_result(state, left, right);
8200 if (is_pointer(left)) {
8201 struct type *ptr_math;
8202 int op;
8203 if (is_signed(right->type)) {
8204 ptr_math = &long_type;
8205 op = OP_SMUL;
8206 } else {
8207 ptr_math = &ulong_type;
8208 op = OP_UMUL;
8210 if (!equiv_types(right->type, ptr_math)) {
8211 right = mk_cast_expr(state, ptr_math, right);
8213 right = triple(state, op, ptr_math, right,
8214 int_const(state, ptr_math,
8215 size_of_in_bytes(state, left->type->left)));
8217 return triple(state, OP_ADD, result_type, left, right);
8220 static struct triple *mk_sub_expr(
8221 struct compile_state *state, struct triple *left, struct triple *right)
8223 struct type *result_type;
8224 result_type = ptr_arithmetic_result(state, left, right);
8225 left = read_expr(state, left);
8226 right = read_expr(state, right);
8227 if (is_pointer(left)) {
8228 struct type *ptr_math;
8229 int op;
8230 if (is_signed(right->type)) {
8231 ptr_math = &long_type;
8232 op = OP_SMUL;
8233 } else {
8234 ptr_math = &ulong_type;
8235 op = OP_UMUL;
8237 if (!equiv_types(right->type, ptr_math)) {
8238 right = mk_cast_expr(state, ptr_math, right);
8240 right = triple(state, op, ptr_math, right,
8241 int_const(state, ptr_math,
8242 size_of_in_bytes(state, left->type->left)));
8244 return triple(state, OP_SUB, result_type, left, right);
8247 static struct triple *mk_pre_inc_expr(
8248 struct compile_state *state, struct triple *def)
8250 struct triple *val;
8251 lvalue(state, def);
8252 val = mk_add_expr(state, def, int_const(state, &int_type, 1));
8253 return triple(state, OP_VAL, def->type,
8254 write_expr(state, def, val),
8255 val);
8258 static struct triple *mk_pre_dec_expr(
8259 struct compile_state *state, struct triple *def)
8261 struct triple *val;
8262 lvalue(state, def);
8263 val = mk_sub_expr(state, def, int_const(state, &int_type, 1));
8264 return triple(state, OP_VAL, def->type,
8265 write_expr(state, def, val),
8266 val);
8269 static struct triple *mk_post_inc_expr(
8270 struct compile_state *state, struct triple *def)
8272 struct triple *val;
8273 lvalue(state, def);
8274 val = read_expr(state, def);
8275 return triple(state, OP_VAL, def->type,
8276 write_expr(state, def,
8277 mk_add_expr(state, val, int_const(state, &int_type, 1)))
8278 , val);
8281 static struct triple *mk_post_dec_expr(
8282 struct compile_state *state, struct triple *def)
8284 struct triple *val;
8285 lvalue(state, def);
8286 val = read_expr(state, def);
8287 return triple(state, OP_VAL, def->type,
8288 write_expr(state, def,
8289 mk_sub_expr(state, val, int_const(state, &int_type, 1)))
8290 , val);
8293 static struct triple *mk_subscript_expr(
8294 struct compile_state *state, struct triple *left, struct triple *right)
8296 left = read_expr(state, left);
8297 right = read_expr(state, right);
8298 if (!is_pointer(left) && !is_pointer(right)) {
8299 error(state, left, "subscripted value is not a pointer");
8301 return mk_deref_expr(state, mk_add_expr(state, left, right));
8306 * Compile time evaluation
8307 * ===========================
8309 static int is_const(struct triple *ins)
8311 return IS_CONST_OP(ins->op);
8314 static int is_simple_const(struct triple *ins)
8316 /* Is this a constant that u.cval has the value.
8317 * Or equivalently is this a constant that read_const
8318 * works on.
8319 * So far only OP_INTCONST qualifies.
8321 return (ins->op == OP_INTCONST);
8324 static int constants_equal(struct compile_state *state,
8325 struct triple *left, struct triple *right)
8327 int equal;
8328 if ((left->op == OP_UNKNOWNVAL) || (right->op == OP_UNKNOWNVAL)) {
8329 equal = 0;
8331 else if (!is_const(left) || !is_const(right)) {
8332 equal = 0;
8334 else if (left->op != right->op) {
8335 equal = 0;
8337 else if (!equiv_types(left->type, right->type)) {
8338 equal = 0;
8340 else {
8341 equal = 0;
8342 switch(left->op) {
8343 case OP_INTCONST:
8344 if (left->u.cval == right->u.cval) {
8345 equal = 1;
8347 break;
8348 case OP_BLOBCONST:
8350 size_t lsize, rsize, bytes;
8351 lsize = size_of(state, left->type);
8352 rsize = size_of(state, right->type);
8353 if (lsize != rsize) {
8354 break;
8356 bytes = bits_to_bytes(lsize);
8357 if (memcmp(left->u.blob, right->u.blob, bytes) == 0) {
8358 equal = 1;
8360 break;
8362 case OP_ADDRCONST:
8363 if ((MISC(left, 0) == MISC(right, 0)) &&
8364 (left->u.cval == right->u.cval)) {
8365 equal = 1;
8367 break;
8368 default:
8369 internal_error(state, left, "uknown constant type");
8370 break;
8373 return equal;
8376 static int is_zero(struct triple *ins)
8378 return is_simple_const(ins) && (ins->u.cval == 0);
8381 static int is_one(struct triple *ins)
8383 return is_simple_const(ins) && (ins->u.cval == 1);
8386 #if DEBUG_ROMCC_WARNING
8387 static long_t bit_count(ulong_t value)
8389 int count;
8390 int i;
8391 count = 0;
8392 for(i = (sizeof(ulong_t)*8) -1; i >= 0; i--) {
8393 ulong_t mask;
8394 mask = 1;
8395 mask <<= i;
8396 if (value & mask) {
8397 count++;
8400 return count;
8403 #endif
8405 static long_t bsr(ulong_t value)
8407 int i;
8408 for(i = (sizeof(ulong_t)*8) -1; i >= 0; i--) {
8409 ulong_t mask;
8410 mask = 1;
8411 mask <<= i;
8412 if (value & mask) {
8413 return i;
8416 return -1;
8419 static long_t bsf(ulong_t value)
8421 int i;
8422 for(i = 0; i < (sizeof(ulong_t)*8); i++) {
8423 ulong_t mask;
8424 mask = 1;
8425 mask <<= 1;
8426 if (value & mask) {
8427 return i;
8430 return -1;
8433 static long_t ilog2(ulong_t value)
8435 return bsr(value);
8438 static long_t tlog2(struct triple *ins)
8440 return ilog2(ins->u.cval);
8443 static int is_pow2(struct triple *ins)
8445 ulong_t value, mask;
8446 long_t log;
8447 if (!is_const(ins)) {
8448 return 0;
8450 value = ins->u.cval;
8451 log = ilog2(value);
8452 if (log == -1) {
8453 return 0;
8455 mask = 1;
8456 mask <<= log;
8457 return ((value & mask) == value);
8460 static ulong_t read_const(struct compile_state *state,
8461 struct triple *ins, struct triple *rhs)
8463 switch(rhs->type->type &TYPE_MASK) {
8464 case TYPE_CHAR:
8465 case TYPE_SHORT:
8466 case TYPE_INT:
8467 case TYPE_LONG:
8468 case TYPE_UCHAR:
8469 case TYPE_USHORT:
8470 case TYPE_UINT:
8471 case TYPE_ULONG:
8472 case TYPE_POINTER:
8473 case TYPE_BITFIELD:
8474 break;
8475 default:
8476 fprintf(state->errout, "type: ");
8477 name_of(state->errout, rhs->type);
8478 fprintf(state->errout, "\n");
8479 internal_warning(state, rhs, "bad type to read_const");
8480 break;
8482 if (!is_simple_const(rhs)) {
8483 internal_error(state, rhs, "bad op to read_const");
8485 return rhs->u.cval;
8488 static long_t read_sconst(struct compile_state *state,
8489 struct triple *ins, struct triple *rhs)
8491 return (long_t)(rhs->u.cval);
8494 int const_ltrue(struct compile_state *state, struct triple *ins, struct triple *rhs)
8496 if (!is_const(rhs)) {
8497 internal_error(state, 0, "non const passed to const_true");
8499 return !is_zero(rhs);
8502 int const_eq(struct compile_state *state, struct triple *ins,
8503 struct triple *left, struct triple *right)
8505 int result;
8506 if (!is_const(left) || !is_const(right)) {
8507 internal_warning(state, ins, "non const passed to const_eq");
8508 result = -1;
8510 else if (left == right) {
8511 result = 1;
8513 else if (is_simple_const(left) && is_simple_const(right)) {
8514 ulong_t lval, rval;
8515 lval = read_const(state, ins, left);
8516 rval = read_const(state, ins, right);
8517 result = (lval == rval);
8519 else if ((left->op == OP_ADDRCONST) &&
8520 (right->op == OP_ADDRCONST)) {
8521 result = (MISC(left, 0) == MISC(right, 0)) &&
8522 (left->u.cval == right->u.cval);
8524 else {
8525 internal_warning(state, ins, "incomparable constants passed to const_eq");
8526 result = -1;
8528 return result;
8532 int const_ucmp(struct compile_state *state, struct triple *ins,
8533 struct triple *left, struct triple *right)
8535 int result;
8536 if (!is_const(left) || !is_const(right)) {
8537 internal_warning(state, ins, "non const past to const_ucmp");
8538 result = -2;
8540 else if (left == right) {
8541 result = 0;
8543 else if (is_simple_const(left) && is_simple_const(right)) {
8544 ulong_t lval, rval;
8545 lval = read_const(state, ins, left);
8546 rval = read_const(state, ins, right);
8547 result = 0;
8548 if (lval > rval) {
8549 result = 1;
8550 } else if (rval > lval) {
8551 result = -1;
8554 else if ((left->op == OP_ADDRCONST) &&
8555 (right->op == OP_ADDRCONST) &&
8556 (MISC(left, 0) == MISC(right, 0))) {
8557 result = 0;
8558 if (left->u.cval > right->u.cval) {
8559 result = 1;
8560 } else if (left->u.cval < right->u.cval) {
8561 result = -1;
8564 else {
8565 internal_warning(state, ins, "incomparable constants passed to const_ucmp");
8566 result = -2;
8568 return result;
8571 int const_scmp(struct compile_state *state, struct triple *ins,
8572 struct triple *left, struct triple *right)
8574 int result;
8575 if (!is_const(left) || !is_const(right)) {
8576 internal_warning(state, ins, "non const past to ucmp_const");
8577 result = -2;
8579 else if (left == right) {
8580 result = 0;
8582 else if (is_simple_const(left) && is_simple_const(right)) {
8583 long_t lval, rval;
8584 lval = read_sconst(state, ins, left);
8585 rval = read_sconst(state, ins, right);
8586 result = 0;
8587 if (lval > rval) {
8588 result = 1;
8589 } else if (rval > lval) {
8590 result = -1;
8593 else {
8594 internal_warning(state, ins, "incomparable constants passed to const_scmp");
8595 result = -2;
8597 return result;
8600 static void unuse_rhs(struct compile_state *state, struct triple *ins)
8602 struct triple **expr;
8603 expr = triple_rhs(state, ins, 0);
8604 for(;expr;expr = triple_rhs(state, ins, expr)) {
8605 if (*expr) {
8606 unuse_triple(*expr, ins);
8607 *expr = 0;
8612 static void unuse_lhs(struct compile_state *state, struct triple *ins)
8614 struct triple **expr;
8615 expr = triple_lhs(state, ins, 0);
8616 for(;expr;expr = triple_lhs(state, ins, expr)) {
8617 unuse_triple(*expr, ins);
8618 *expr = 0;
8622 #if DEBUG_ROMCC_WARNING
8623 static void unuse_misc(struct compile_state *state, struct triple *ins)
8625 struct triple **expr;
8626 expr = triple_misc(state, ins, 0);
8627 for(;expr;expr = triple_misc(state, ins, expr)) {
8628 unuse_triple(*expr, ins);
8629 *expr = 0;
8633 static void unuse_targ(struct compile_state *state, struct triple *ins)
8635 int i;
8636 struct triple **slot;
8637 slot = &TARG(ins, 0);
8638 for(i = 0; i < ins->targ; i++) {
8639 unuse_triple(slot[i], ins);
8640 slot[i] = 0;
8644 static void check_lhs(struct compile_state *state, struct triple *ins)
8646 struct triple **expr;
8647 expr = triple_lhs(state, ins, 0);
8648 for(;expr;expr = triple_lhs(state, ins, expr)) {
8649 internal_error(state, ins, "unexpected lhs");
8653 #endif
8655 static void check_misc(struct compile_state *state, struct triple *ins)
8657 struct triple **expr;
8658 expr = triple_misc(state, ins, 0);
8659 for(;expr;expr = triple_misc(state, ins, expr)) {
8660 if (*expr) {
8661 internal_error(state, ins, "unexpected misc");
8666 static void check_targ(struct compile_state *state, struct triple *ins)
8668 struct triple **expr;
8669 expr = triple_targ(state, ins, 0);
8670 for(;expr;expr = triple_targ(state, ins, expr)) {
8671 internal_error(state, ins, "unexpected targ");
8675 static void wipe_ins(struct compile_state *state, struct triple *ins)
8677 /* Becareful which instructions you replace the wiped
8678 * instruction with, as there are not enough slots
8679 * in all instructions to hold all others.
8681 check_targ(state, ins);
8682 check_misc(state, ins);
8683 unuse_rhs(state, ins);
8684 unuse_lhs(state, ins);
8685 ins->lhs = 0;
8686 ins->rhs = 0;
8687 ins->misc = 0;
8688 ins->targ = 0;
8691 #if DEBUG_ROMCC_WARNING
8692 static void wipe_branch(struct compile_state *state, struct triple *ins)
8694 /* Becareful which instructions you replace the wiped
8695 * instruction with, as there are not enough slots
8696 * in all instructions to hold all others.
8698 unuse_rhs(state, ins);
8699 unuse_lhs(state, ins);
8700 unuse_misc(state, ins);
8701 unuse_targ(state, ins);
8702 ins->lhs = 0;
8703 ins->rhs = 0;
8704 ins->misc = 0;
8705 ins->targ = 0;
8707 #endif
8709 static void mkcopy(struct compile_state *state,
8710 struct triple *ins, struct triple *rhs)
8712 struct block *block;
8713 if (!equiv_types(ins->type, rhs->type)) {
8714 FILE *fp = state->errout;
8715 fprintf(fp, "src type: ");
8716 name_of(fp, rhs->type);
8717 fprintf(fp, "\ndst type: ");
8718 name_of(fp, ins->type);
8719 fprintf(fp, "\n");
8720 internal_error(state, ins, "mkcopy type mismatch");
8722 block = block_of_triple(state, ins);
8723 wipe_ins(state, ins);
8724 ins->op = OP_COPY;
8725 ins->rhs = 1;
8726 ins->u.block = block;
8727 RHS(ins, 0) = rhs;
8728 use_triple(RHS(ins, 0), ins);
8731 static void mkconst(struct compile_state *state,
8732 struct triple *ins, ulong_t value)
8734 if (!is_integral(ins) && !is_pointer(ins)) {
8735 fprintf(state->errout, "type: ");
8736 name_of(state->errout, ins->type);
8737 fprintf(state->errout, "\n");
8738 internal_error(state, ins, "unknown type to make constant value: %ld",
8739 value);
8741 wipe_ins(state, ins);
8742 ins->op = OP_INTCONST;
8743 ins->u.cval = value;
8746 static void mkaddr_const(struct compile_state *state,
8747 struct triple *ins, struct triple *sdecl, ulong_t value)
8749 if ((sdecl->op != OP_SDECL) && (sdecl->op != OP_LABEL)) {
8750 internal_error(state, ins, "bad base for addrconst");
8752 wipe_ins(state, ins);
8753 ins->op = OP_ADDRCONST;
8754 ins->misc = 1;
8755 MISC(ins, 0) = sdecl;
8756 ins->u.cval = value;
8757 use_triple(sdecl, ins);
8760 #if DEBUG_DECOMPOSE_PRINT_TUPLES
8761 static void print_tuple(struct compile_state *state,
8762 struct triple *ins, struct triple *tuple)
8764 FILE *fp = state->dbgout;
8765 fprintf(fp, "%5s %p tuple: %p ", tops(ins->op), ins, tuple);
8766 name_of(fp, tuple->type);
8767 if (tuple->lhs > 0) {
8768 fprintf(fp, " lhs: ");
8769 name_of(fp, LHS(tuple, 0)->type);
8771 fprintf(fp, "\n");
8774 #endif
8776 static struct triple *decompose_with_tuple(struct compile_state *state,
8777 struct triple *ins, struct triple *tuple)
8779 struct triple *next;
8780 next = ins->next;
8781 flatten(state, next, tuple);
8782 #if DEBUG_DECOMPOSE_PRINT_TUPLES
8783 print_tuple(state, ins, tuple);
8784 #endif
8786 if (!is_compound_type(tuple->type) && (tuple->lhs > 0)) {
8787 struct triple *tmp;
8788 if (tuple->lhs != 1) {
8789 internal_error(state, tuple, "plain type in multiple registers?");
8791 tmp = LHS(tuple, 0);
8792 release_triple(state, tuple);
8793 tuple = tmp;
8796 propagate_use(state, ins, tuple);
8797 release_triple(state, ins);
8799 return next;
8802 static struct triple *decompose_unknownval(struct compile_state *state,
8803 struct triple *ins)
8805 struct triple *tuple;
8806 ulong_t i;
8808 #if DEBUG_DECOMPOSE_HIRES
8809 FILE *fp = state->dbgout;
8810 fprintf(fp, "unknown type: ");
8811 name_of(fp, ins->type);
8812 fprintf(fp, "\n");
8813 #endif
8815 get_occurrence(ins->occurrence);
8816 tuple = alloc_triple(state, OP_TUPLE, ins->type, -1, -1,
8817 ins->occurrence);
8819 for(i = 0; i < tuple->lhs; i++) {
8820 struct type *piece_type;
8821 struct triple *unknown;
8823 piece_type = reg_type(state, ins->type, i * REG_SIZEOF_REG);
8824 get_occurrence(tuple->occurrence);
8825 unknown = alloc_triple(state, OP_UNKNOWNVAL, piece_type, 0, 0,
8826 tuple->occurrence);
8827 LHS(tuple, i) = unknown;
8829 return decompose_with_tuple(state, ins, tuple);
8833 static struct triple *decompose_read(struct compile_state *state,
8834 struct triple *ins)
8836 struct triple *tuple, *lval;
8837 ulong_t i;
8839 lval = RHS(ins, 0);
8841 if (lval->op == OP_PIECE) {
8842 return ins->next;
8844 get_occurrence(ins->occurrence);
8845 tuple = alloc_triple(state, OP_TUPLE, lval->type, -1, -1,
8846 ins->occurrence);
8848 if ((tuple->lhs != lval->lhs) &&
8849 (!triple_is_def(state, lval) || (tuple->lhs != 1)))
8851 internal_error(state, ins, "lhs size inconsistency?");
8853 for(i = 0; i < tuple->lhs; i++) {
8854 struct triple *piece, *read, *bitref;
8855 if ((i != 0) || !triple_is_def(state, lval)) {
8856 piece = LHS(lval, i);
8857 } else {
8858 piece = lval;
8861 /* See if the piece is really a bitref */
8862 bitref = 0;
8863 if (piece->op == OP_BITREF) {
8864 bitref = piece;
8865 piece = RHS(bitref, 0);
8868 get_occurrence(tuple->occurrence);
8869 read = alloc_triple(state, OP_READ, piece->type, -1, -1,
8870 tuple->occurrence);
8871 RHS(read, 0) = piece;
8873 if (bitref) {
8874 struct triple *extract;
8875 int op;
8876 if (is_signed(bitref->type->left)) {
8877 op = OP_SEXTRACT;
8878 } else {
8879 op = OP_UEXTRACT;
8881 get_occurrence(tuple->occurrence);
8882 extract = alloc_triple(state, op, bitref->type, -1, -1,
8883 tuple->occurrence);
8884 RHS(extract, 0) = read;
8885 extract->u.bitfield.size = bitref->u.bitfield.size;
8886 extract->u.bitfield.offset = bitref->u.bitfield.offset;
8888 read = extract;
8891 LHS(tuple, i) = read;
8893 return decompose_with_tuple(state, ins, tuple);
8896 static struct triple *decompose_write(struct compile_state *state,
8897 struct triple *ins)
8899 struct triple *tuple, *lval, *val;
8900 ulong_t i;
8902 lval = MISC(ins, 0);
8903 val = RHS(ins, 0);
8904 get_occurrence(ins->occurrence);
8905 tuple = alloc_triple(state, OP_TUPLE, ins->type, -1, -1,
8906 ins->occurrence);
8908 if ((tuple->lhs != lval->lhs) &&
8909 (!triple_is_def(state, lval) || tuple->lhs != 1))
8911 internal_error(state, ins, "lhs size inconsistency?");
8913 for(i = 0; i < tuple->lhs; i++) {
8914 struct triple *piece, *write, *pval, *bitref;
8915 if ((i != 0) || !triple_is_def(state, lval)) {
8916 piece = LHS(lval, i);
8917 } else {
8918 piece = lval;
8920 if ((i == 0) && (tuple->lhs == 1) && (val->lhs == 0)) {
8921 pval = val;
8923 else {
8924 if (i > val->lhs) {
8925 internal_error(state, ins, "lhs size inconsistency?");
8927 pval = LHS(val, i);
8930 /* See if the piece is really a bitref */
8931 bitref = 0;
8932 if (piece->op == OP_BITREF) {
8933 struct triple *read, *deposit;
8934 bitref = piece;
8935 piece = RHS(bitref, 0);
8937 /* Read the destination register */
8938 get_occurrence(tuple->occurrence);
8939 read = alloc_triple(state, OP_READ, piece->type, -1, -1,
8940 tuple->occurrence);
8941 RHS(read, 0) = piece;
8943 /* Deposit the new bitfield value */
8944 get_occurrence(tuple->occurrence);
8945 deposit = alloc_triple(state, OP_DEPOSIT, piece->type, -1, -1,
8946 tuple->occurrence);
8947 RHS(deposit, 0) = read;
8948 RHS(deposit, 1) = pval;
8949 deposit->u.bitfield.size = bitref->u.bitfield.size;
8950 deposit->u.bitfield.offset = bitref->u.bitfield.offset;
8952 /* Now write the newly generated value */
8953 pval = deposit;
8956 get_occurrence(tuple->occurrence);
8957 write = alloc_triple(state, OP_WRITE, piece->type, -1, -1,
8958 tuple->occurrence);
8959 MISC(write, 0) = piece;
8960 RHS(write, 0) = pval;
8961 LHS(tuple, i) = write;
8963 return decompose_with_tuple(state, ins, tuple);
8966 struct decompose_load_info {
8967 struct occurrence *occurrence;
8968 struct triple *lval;
8969 struct triple *tuple;
8971 static void decompose_load_cb(struct compile_state *state,
8972 struct type *type, size_t reg_offset, size_t mem_offset, void *arg)
8974 struct decompose_load_info *info = arg;
8975 struct triple *load;
8977 if (reg_offset > info->tuple->lhs) {
8978 internal_error(state, info->tuple, "lhs to small?");
8980 get_occurrence(info->occurrence);
8981 load = alloc_triple(state, OP_LOAD, type, -1, -1, info->occurrence);
8982 RHS(load, 0) = mk_addr_expr(state, info->lval, mem_offset);
8983 LHS(info->tuple, reg_offset/REG_SIZEOF_REG) = load;
8986 static struct triple *decompose_load(struct compile_state *state,
8987 struct triple *ins)
8989 struct triple *tuple;
8990 struct decompose_load_info info;
8992 if (!is_compound_type(ins->type)) {
8993 return ins->next;
8995 get_occurrence(ins->occurrence);
8996 tuple = alloc_triple(state, OP_TUPLE, ins->type, -1, -1,
8997 ins->occurrence);
8999 info.occurrence = ins->occurrence;
9000 info.lval = RHS(ins, 0);
9001 info.tuple = tuple;
9002 walk_type_fields(state, ins->type, 0, 0, decompose_load_cb, &info);
9004 return decompose_with_tuple(state, ins, tuple);
9008 struct decompose_store_info {
9009 struct occurrence *occurrence;
9010 struct triple *lval;
9011 struct triple *val;
9012 struct triple *tuple;
9014 static void decompose_store_cb(struct compile_state *state,
9015 struct type *type, size_t reg_offset, size_t mem_offset, void *arg)
9017 struct decompose_store_info *info = arg;
9018 struct triple *store;
9020 if (reg_offset > info->tuple->lhs) {
9021 internal_error(state, info->tuple, "lhs to small?");
9023 get_occurrence(info->occurrence);
9024 store = alloc_triple(state, OP_STORE, type, -1, -1, info->occurrence);
9025 RHS(store, 0) = mk_addr_expr(state, info->lval, mem_offset);
9026 RHS(store, 1) = LHS(info->val, reg_offset);
9027 LHS(info->tuple, reg_offset/REG_SIZEOF_REG) = store;
9030 static struct triple *decompose_store(struct compile_state *state,
9031 struct triple *ins)
9033 struct triple *tuple;
9034 struct decompose_store_info info;
9036 if (!is_compound_type(ins->type)) {
9037 return ins->next;
9039 get_occurrence(ins->occurrence);
9040 tuple = alloc_triple(state, OP_TUPLE, ins->type, -1, -1,
9041 ins->occurrence);
9043 info.occurrence = ins->occurrence;
9044 info.lval = RHS(ins, 0);
9045 info.val = RHS(ins, 1);
9046 info.tuple = tuple;
9047 walk_type_fields(state, ins->type, 0, 0, decompose_store_cb, &info);
9049 return decompose_with_tuple(state, ins, tuple);
9052 static struct triple *decompose_dot(struct compile_state *state,
9053 struct triple *ins)
9055 struct triple *tuple, *lval;
9056 struct type *type;
9057 size_t reg_offset;
9058 int i, idx;
9060 lval = MISC(ins, 0);
9061 reg_offset = field_reg_offset(state, lval->type, ins->u.field);
9062 idx = reg_offset/REG_SIZEOF_REG;
9063 type = field_type(state, lval->type, ins->u.field);
9064 #if DEBUG_DECOMPOSE_HIRES
9066 FILE *fp = state->dbgout;
9067 fprintf(fp, "field type: ");
9068 name_of(fp, type);
9069 fprintf(fp, "\n");
9071 #endif
9073 get_occurrence(ins->occurrence);
9074 tuple = alloc_triple(state, OP_TUPLE, type, -1, -1,
9075 ins->occurrence);
9077 if (((ins->type->type & TYPE_MASK) == TYPE_BITFIELD) &&
9078 (tuple->lhs != 1))
9080 internal_error(state, ins, "multi register bitfield?");
9083 for(i = 0; i < tuple->lhs; i++, idx++) {
9084 struct triple *piece;
9085 if (!triple_is_def(state, lval)) {
9086 if (idx > lval->lhs) {
9087 internal_error(state, ins, "inconsistent lhs count");
9089 piece = LHS(lval, idx);
9090 } else {
9091 if (idx != 0) {
9092 internal_error(state, ins, "bad reg_offset into def");
9094 if (i != 0) {
9095 internal_error(state, ins, "bad reg count from def");
9097 piece = lval;
9100 /* Remember the offset of the bitfield */
9101 if ((type->type & TYPE_MASK) == TYPE_BITFIELD) {
9102 get_occurrence(ins->occurrence);
9103 piece = build_triple(state, OP_BITREF, type, piece, 0,
9104 ins->occurrence);
9105 piece->u.bitfield.size = size_of(state, type);
9106 piece->u.bitfield.offset = reg_offset % REG_SIZEOF_REG;
9108 else if ((reg_offset % REG_SIZEOF_REG) != 0) {
9109 internal_error(state, ins,
9110 "request for a nonbitfield sub register?");
9113 LHS(tuple, i) = piece;
9116 return decompose_with_tuple(state, ins, tuple);
9119 static struct triple *decompose_index(struct compile_state *state,
9120 struct triple *ins)
9122 struct triple *tuple, *lval;
9123 struct type *type;
9124 int i, idx;
9126 lval = MISC(ins, 0);
9127 idx = index_reg_offset(state, lval->type, ins->u.cval)/REG_SIZEOF_REG;
9128 type = index_type(state, lval->type, ins->u.cval);
9129 #if DEBUG_DECOMPOSE_HIRES
9131 FILE *fp = state->dbgout;
9132 fprintf(fp, "index type: ");
9133 name_of(fp, type);
9134 fprintf(fp, "\n");
9136 #endif
9138 get_occurrence(ins->occurrence);
9139 tuple = alloc_triple(state, OP_TUPLE, type, -1, -1,
9140 ins->occurrence);
9142 for(i = 0; i < tuple->lhs; i++, idx++) {
9143 struct triple *piece;
9144 if (!triple_is_def(state, lval)) {
9145 if (idx > lval->lhs) {
9146 internal_error(state, ins, "inconsistent lhs count");
9148 piece = LHS(lval, idx);
9149 } else {
9150 if (idx != 0) {
9151 internal_error(state, ins, "bad reg_offset into def");
9153 if (i != 0) {
9154 internal_error(state, ins, "bad reg count from def");
9156 piece = lval;
9158 LHS(tuple, i) = piece;
9161 return decompose_with_tuple(state, ins, tuple);
9164 static void decompose_compound_types(struct compile_state *state)
9166 struct triple *ins, *next, *first;
9167 first = state->first;
9169 /* Pass one expand compound values into pseudo registers.
9171 next = first;
9172 do {
9173 ins = next;
9174 next = ins->next;
9175 switch(ins->op) {
9176 case OP_UNKNOWNVAL:
9177 next = decompose_unknownval(state, ins);
9178 break;
9180 case OP_READ:
9181 next = decompose_read(state, ins);
9182 break;
9184 case OP_WRITE:
9185 next = decompose_write(state, ins);
9186 break;
9189 /* Be very careful with the load/store logic. These
9190 * operations must convert from the in register layout
9191 * to the in memory layout, which is nontrivial.
9193 case OP_LOAD:
9194 next = decompose_load(state, ins);
9195 break;
9196 case OP_STORE:
9197 next = decompose_store(state, ins);
9198 break;
9200 case OP_DOT:
9201 next = decompose_dot(state, ins);
9202 break;
9203 case OP_INDEX:
9204 next = decompose_index(state, ins);
9205 break;
9208 #if DEBUG_DECOMPOSE_HIRES
9209 fprintf(fp, "decompose next: %p\n", next);
9210 fflush(fp);
9211 fprintf(fp, "next->op: %d %s\n",
9212 next->op, tops(next->op));
9213 /* High resolution debugging mode */
9214 print_triples(state);
9215 #endif
9216 } while (next != first);
9218 /* Pass two remove the tuples.
9220 ins = first;
9221 do {
9222 next = ins->next;
9223 if (ins->op == OP_TUPLE) {
9224 if (ins->use) {
9225 internal_error(state, ins, "tuple used");
9227 else {
9228 release_triple(state, ins);
9231 ins = next;
9232 } while(ins != first);
9233 ins = first;
9234 do {
9235 next = ins->next;
9236 if (ins->op == OP_BITREF) {
9237 if (ins->use) {
9238 internal_error(state, ins, "bitref used");
9240 else {
9241 release_triple(state, ins);
9244 ins = next;
9245 } while(ins != first);
9247 /* Pass three verify the state and set ->id to 0.
9249 next = first;
9250 do {
9251 ins = next;
9252 next = ins->next;
9253 ins->id &= ~TRIPLE_FLAG_FLATTENED;
9254 if (triple_stores_block(state, ins)) {
9255 ins->u.block = 0;
9257 if (triple_is_def(state, ins)) {
9258 if (reg_size_of(state, ins->type) > REG_SIZEOF_REG) {
9259 internal_error(state, ins, "multi register value remains?");
9262 if (ins->op == OP_DOT) {
9263 internal_error(state, ins, "OP_DOT remains?");
9265 if (ins->op == OP_INDEX) {
9266 internal_error(state, ins, "OP_INDEX remains?");
9268 if (ins->op == OP_BITREF) {
9269 internal_error(state, ins, "OP_BITREF remains?");
9271 if (ins->op == OP_TUPLE) {
9272 internal_error(state, ins, "OP_TUPLE remains?");
9274 } while(next != first);
9277 /* For those operations that cannot be simplified */
9278 static void simplify_noop(struct compile_state *state, struct triple *ins)
9280 return;
9283 static void simplify_smul(struct compile_state *state, struct triple *ins)
9285 if (is_const(RHS(ins, 0)) && !is_const(RHS(ins, 1))) {
9286 struct triple *tmp;
9287 tmp = RHS(ins, 0);
9288 RHS(ins, 0) = RHS(ins, 1);
9289 RHS(ins, 1) = tmp;
9291 if (is_const(RHS(ins, 0)) && is_const(RHS(ins, 1))) {
9292 long_t left, right;
9293 left = read_sconst(state, ins, RHS(ins, 0));
9294 right = read_sconst(state, ins, RHS(ins, 1));
9295 mkconst(state, ins, left * right);
9297 else if (is_zero(RHS(ins, 1))) {
9298 mkconst(state, ins, 0);
9300 else if (is_one(RHS(ins, 1))) {
9301 mkcopy(state, ins, RHS(ins, 0));
9303 else if (is_pow2(RHS(ins, 1))) {
9304 struct triple *val;
9305 val = int_const(state, ins->type, tlog2(RHS(ins, 1)));
9306 ins->op = OP_SL;
9307 insert_triple(state, state->global_pool, val);
9308 unuse_triple(RHS(ins, 1), ins);
9309 use_triple(val, ins);
9310 RHS(ins, 1) = val;
9314 static void simplify_umul(struct compile_state *state, struct triple *ins)
9316 if (is_const(RHS(ins, 0)) && !is_const(RHS(ins, 1))) {
9317 struct triple *tmp;
9318 tmp = RHS(ins, 0);
9319 RHS(ins, 0) = RHS(ins, 1);
9320 RHS(ins, 1) = tmp;
9322 if (is_simple_const(RHS(ins, 0)) && is_simple_const(RHS(ins, 1))) {
9323 ulong_t left, right;
9324 left = read_const(state, ins, RHS(ins, 0));
9325 right = read_const(state, ins, RHS(ins, 1));
9326 mkconst(state, ins, left * right);
9328 else if (is_zero(RHS(ins, 1))) {
9329 mkconst(state, ins, 0);
9331 else if (is_one(RHS(ins, 1))) {
9332 mkcopy(state, ins, RHS(ins, 0));
9334 else if (is_pow2(RHS(ins, 1))) {
9335 struct triple *val;
9336 val = int_const(state, ins->type, tlog2(RHS(ins, 1)));
9337 ins->op = OP_SL;
9338 insert_triple(state, state->global_pool, val);
9339 unuse_triple(RHS(ins, 1), ins);
9340 use_triple(val, ins);
9341 RHS(ins, 1) = val;
9345 static void simplify_sdiv(struct compile_state *state, struct triple *ins)
9347 if (is_const(RHS(ins, 0)) && is_const(RHS(ins, 1))) {
9348 long_t left, right;
9349 left = read_sconst(state, ins, RHS(ins, 0));
9350 right = read_sconst(state, ins, RHS(ins, 1));
9351 mkconst(state, ins, left / right);
9353 else if (is_zero(RHS(ins, 0))) {
9354 mkconst(state, ins, 0);
9356 else if (is_zero(RHS(ins, 1))) {
9357 error(state, ins, "division by zero");
9359 else if (is_one(RHS(ins, 1))) {
9360 mkcopy(state, ins, RHS(ins, 0));
9362 else if (is_pow2(RHS(ins, 1))) {
9363 struct triple *val;
9364 val = int_const(state, ins->type, tlog2(RHS(ins, 1)));
9365 ins->op = OP_SSR;
9366 insert_triple(state, state->global_pool, val);
9367 unuse_triple(RHS(ins, 1), ins);
9368 use_triple(val, ins);
9369 RHS(ins, 1) = val;
9373 static void simplify_udiv(struct compile_state *state, struct triple *ins)
9375 if (is_simple_const(RHS(ins, 0)) && is_simple_const(RHS(ins, 1))) {
9376 ulong_t left, right;
9377 left = read_const(state, ins, RHS(ins, 0));
9378 right = read_const(state, ins, RHS(ins, 1));
9379 mkconst(state, ins, left / right);
9381 else if (is_zero(RHS(ins, 0))) {
9382 mkconst(state, ins, 0);
9384 else if (is_zero(RHS(ins, 1))) {
9385 error(state, ins, "division by zero");
9387 else if (is_one(RHS(ins, 1))) {
9388 mkcopy(state, ins, RHS(ins, 0));
9390 else if (is_pow2(RHS(ins, 1))) {
9391 struct triple *val;
9392 val = int_const(state, ins->type, tlog2(RHS(ins, 1)));
9393 ins->op = OP_USR;
9394 insert_triple(state, state->global_pool, val);
9395 unuse_triple(RHS(ins, 1), ins);
9396 use_triple(val, ins);
9397 RHS(ins, 1) = val;
9401 static void simplify_smod(struct compile_state *state, struct triple *ins)
9403 if (is_simple_const(RHS(ins, 0)) && is_simple_const(RHS(ins, 1))) {
9404 long_t left, right;
9405 left = read_const(state, ins, RHS(ins, 0));
9406 right = read_const(state, ins, RHS(ins, 1));
9407 mkconst(state, ins, left % right);
9409 else if (is_zero(RHS(ins, 0))) {
9410 mkconst(state, ins, 0);
9412 else if (is_zero(RHS(ins, 1))) {
9413 error(state, ins, "division by zero");
9415 else if (is_one(RHS(ins, 1))) {
9416 mkconst(state, ins, 0);
9418 else if (is_pow2(RHS(ins, 1))) {
9419 struct triple *val;
9420 val = int_const(state, ins->type, RHS(ins, 1)->u.cval - 1);
9421 ins->op = OP_AND;
9422 insert_triple(state, state->global_pool, val);
9423 unuse_triple(RHS(ins, 1), ins);
9424 use_triple(val, ins);
9425 RHS(ins, 1) = val;
9429 static void simplify_umod(struct compile_state *state, struct triple *ins)
9431 if (is_simple_const(RHS(ins, 0)) && is_simple_const(RHS(ins, 1))) {
9432 ulong_t left, right;
9433 left = read_const(state, ins, RHS(ins, 0));
9434 right = read_const(state, ins, RHS(ins, 1));
9435 mkconst(state, ins, left % right);
9437 else if (is_zero(RHS(ins, 0))) {
9438 mkconst(state, ins, 0);
9440 else if (is_zero(RHS(ins, 1))) {
9441 error(state, ins, "division by zero");
9443 else if (is_one(RHS(ins, 1))) {
9444 mkconst(state, ins, 0);
9446 else if (is_pow2(RHS(ins, 1))) {
9447 struct triple *val;
9448 val = int_const(state, ins->type, RHS(ins, 1)->u.cval - 1);
9449 ins->op = OP_AND;
9450 insert_triple(state, state->global_pool, val);
9451 unuse_triple(RHS(ins, 1), ins);
9452 use_triple(val, ins);
9453 RHS(ins, 1) = val;
9457 static void simplify_add(struct compile_state *state, struct triple *ins)
9459 /* start with the pointer on the left */
9460 if (is_pointer(RHS(ins, 1))) {
9461 struct triple *tmp;
9462 tmp = RHS(ins, 0);
9463 RHS(ins, 0) = RHS(ins, 1);
9464 RHS(ins, 1) = tmp;
9466 if (is_const(RHS(ins, 0)) && is_simple_const(RHS(ins, 1))) {
9467 if (RHS(ins, 0)->op == OP_INTCONST) {
9468 ulong_t left, right;
9469 left = read_const(state, ins, RHS(ins, 0));
9470 right = read_const(state, ins, RHS(ins, 1));
9471 mkconst(state, ins, left + right);
9473 else if (RHS(ins, 0)->op == OP_ADDRCONST) {
9474 struct triple *sdecl;
9475 ulong_t left, right;
9476 sdecl = MISC(RHS(ins, 0), 0);
9477 left = RHS(ins, 0)->u.cval;
9478 right = RHS(ins, 1)->u.cval;
9479 mkaddr_const(state, ins, sdecl, left + right);
9481 else {
9482 internal_warning(state, ins, "Optimize me!");
9485 else if (is_const(RHS(ins, 0)) && !is_const(RHS(ins, 1))) {
9486 struct triple *tmp;
9487 tmp = RHS(ins, 1);
9488 RHS(ins, 1) = RHS(ins, 0);
9489 RHS(ins, 0) = tmp;
9493 static void simplify_sub(struct compile_state *state, struct triple *ins)
9495 if (is_const(RHS(ins, 0)) && is_simple_const(RHS(ins, 1))) {
9496 if (RHS(ins, 0)->op == OP_INTCONST) {
9497 ulong_t left, right;
9498 left = read_const(state, ins, RHS(ins, 0));
9499 right = read_const(state, ins, RHS(ins, 1));
9500 mkconst(state, ins, left - right);
9502 else if (RHS(ins, 0)->op == OP_ADDRCONST) {
9503 struct triple *sdecl;
9504 ulong_t left, right;
9505 sdecl = MISC(RHS(ins, 0), 0);
9506 left = RHS(ins, 0)->u.cval;
9507 right = RHS(ins, 1)->u.cval;
9508 mkaddr_const(state, ins, sdecl, left - right);
9510 else {
9511 internal_warning(state, ins, "Optimize me!");
9516 static void simplify_sl(struct compile_state *state, struct triple *ins)
9518 if (is_simple_const(RHS(ins, 1))) {
9519 ulong_t right;
9520 right = read_const(state, ins, RHS(ins, 1));
9521 if (right >= (size_of(state, ins->type))) {
9522 warning(state, ins, "left shift count >= width of type");
9525 if (is_simple_const(RHS(ins, 0)) && is_simple_const(RHS(ins, 1))) {
9526 ulong_t left, right;
9527 left = read_const(state, ins, RHS(ins, 0));
9528 right = read_const(state, ins, RHS(ins, 1));
9529 mkconst(state, ins, left << right);
9533 static void simplify_usr(struct compile_state *state, struct triple *ins)
9535 if (is_simple_const(RHS(ins, 1))) {
9536 ulong_t right;
9537 right = read_const(state, ins, RHS(ins, 1));
9538 if (right >= (size_of(state, ins->type))) {
9539 warning(state, ins, "right shift count >= width of type");
9542 if (is_simple_const(RHS(ins, 0)) && is_simple_const(RHS(ins, 1))) {
9543 ulong_t left, right;
9544 left = read_const(state, ins, RHS(ins, 0));
9545 right = read_const(state, ins, RHS(ins, 1));
9546 mkconst(state, ins, left >> right);
9550 static void simplify_ssr(struct compile_state *state, struct triple *ins)
9552 if (is_simple_const(RHS(ins, 1))) {
9553 ulong_t right;
9554 right = read_const(state, ins, RHS(ins, 1));
9555 if (right >= (size_of(state, ins->type))) {
9556 warning(state, ins, "right shift count >= width of type");
9559 if (is_simple_const(RHS(ins, 0)) && is_simple_const(RHS(ins, 1))) {
9560 long_t left, right;
9561 left = read_sconst(state, ins, RHS(ins, 0));
9562 right = read_sconst(state, ins, RHS(ins, 1));
9563 mkconst(state, ins, left >> right);
9567 static void simplify_and(struct compile_state *state, struct triple *ins)
9569 struct triple *left, *right;
9570 left = RHS(ins, 0);
9571 right = RHS(ins, 1);
9573 if (is_simple_const(left) && is_simple_const(right)) {
9574 ulong_t lval, rval;
9575 lval = read_const(state, ins, left);
9576 rval = read_const(state, ins, right);
9577 mkconst(state, ins, lval & rval);
9579 else if (is_zero(right) || is_zero(left)) {
9580 mkconst(state, ins, 0);
9584 static void simplify_or(struct compile_state *state, struct triple *ins)
9586 struct triple *left, *right;
9587 left = RHS(ins, 0);
9588 right = RHS(ins, 1);
9590 if (is_simple_const(left) && is_simple_const(right)) {
9591 ulong_t lval, rval;
9592 lval = read_const(state, ins, left);
9593 rval = read_const(state, ins, right);
9594 mkconst(state, ins, lval | rval);
9596 #if 0 /* I need to handle type mismatches here... */
9597 else if (is_zero(right)) {
9598 mkcopy(state, ins, left);
9600 else if (is_zero(left)) {
9601 mkcopy(state, ins, right);
9603 #endif
9606 static void simplify_xor(struct compile_state *state, struct triple *ins)
9608 if (is_simple_const(RHS(ins, 0)) && is_simple_const(RHS(ins, 1))) {
9609 ulong_t left, right;
9610 left = read_const(state, ins, RHS(ins, 0));
9611 right = read_const(state, ins, RHS(ins, 1));
9612 mkconst(state, ins, left ^ right);
9616 static void simplify_pos(struct compile_state *state, struct triple *ins)
9618 if (is_const(RHS(ins, 0))) {
9619 mkconst(state, ins, RHS(ins, 0)->u.cval);
9621 else {
9622 mkcopy(state, ins, RHS(ins, 0));
9626 static void simplify_neg(struct compile_state *state, struct triple *ins)
9628 if (is_simple_const(RHS(ins, 0))) {
9629 ulong_t left;
9630 left = read_const(state, ins, RHS(ins, 0));
9631 mkconst(state, ins, -left);
9633 else if (RHS(ins, 0)->op == OP_NEG) {
9634 mkcopy(state, ins, RHS(RHS(ins, 0), 0));
9638 static void simplify_invert(struct compile_state *state, struct triple *ins)
9640 if (is_simple_const(RHS(ins, 0))) {
9641 ulong_t left;
9642 left = read_const(state, ins, RHS(ins, 0));
9643 mkconst(state, ins, ~left);
9647 static void simplify_eq(struct compile_state *state, struct triple *ins)
9649 struct triple *left, *right;
9650 left = RHS(ins, 0);
9651 right = RHS(ins, 1);
9653 if (is_const(left) && is_const(right)) {
9654 int val;
9655 val = const_eq(state, ins, left, right);
9656 if (val >= 0) {
9657 mkconst(state, ins, val == 1);
9660 else if (left == right) {
9661 mkconst(state, ins, 1);
9665 static void simplify_noteq(struct compile_state *state, struct triple *ins)
9667 struct triple *left, *right;
9668 left = RHS(ins, 0);
9669 right = RHS(ins, 1);
9671 if (is_const(left) && is_const(right)) {
9672 int val;
9673 val = const_eq(state, ins, left, right);
9674 if (val >= 0) {
9675 mkconst(state, ins, val != 1);
9678 if (left == right) {
9679 mkconst(state, ins, 0);
9683 static void simplify_sless(struct compile_state *state, struct triple *ins)
9685 struct triple *left, *right;
9686 left = RHS(ins, 0);
9687 right = RHS(ins, 1);
9689 if (is_const(left) && is_const(right)) {
9690 int val;
9691 val = const_scmp(state, ins, left, right);
9692 if ((val >= -1) && (val <= 1)) {
9693 mkconst(state, ins, val < 0);
9696 else if (left == right) {
9697 mkconst(state, ins, 0);
9701 static void simplify_uless(struct compile_state *state, struct triple *ins)
9703 struct triple *left, *right;
9704 left = RHS(ins, 0);
9705 right = RHS(ins, 1);
9707 if (is_const(left) && is_const(right)) {
9708 int val;
9709 val = const_ucmp(state, ins, left, right);
9710 if ((val >= -1) && (val <= 1)) {
9711 mkconst(state, ins, val < 0);
9714 else if (is_zero(right)) {
9715 mkconst(state, ins, 0);
9717 else if (left == right) {
9718 mkconst(state, ins, 0);
9722 static void simplify_smore(struct compile_state *state, struct triple *ins)
9724 struct triple *left, *right;
9725 left = RHS(ins, 0);
9726 right = RHS(ins, 1);
9728 if (is_const(left) && is_const(right)) {
9729 int val;
9730 val = const_scmp(state, ins, left, right);
9731 if ((val >= -1) && (val <= 1)) {
9732 mkconst(state, ins, val > 0);
9735 else if (left == right) {
9736 mkconst(state, ins, 0);
9740 static void simplify_umore(struct compile_state *state, struct triple *ins)
9742 struct triple *left, *right;
9743 left = RHS(ins, 0);
9744 right = RHS(ins, 1);
9746 if (is_const(left) && is_const(right)) {
9747 int val;
9748 val = const_ucmp(state, ins, left, right);
9749 if ((val >= -1) && (val <= 1)) {
9750 mkconst(state, ins, val > 0);
9753 else if (is_zero(left)) {
9754 mkconst(state, ins, 0);
9756 else if (left == right) {
9757 mkconst(state, ins, 0);
9762 static void simplify_slesseq(struct compile_state *state, struct triple *ins)
9764 struct triple *left, *right;
9765 left = RHS(ins, 0);
9766 right = RHS(ins, 1);
9768 if (is_const(left) && is_const(right)) {
9769 int val;
9770 val = const_scmp(state, ins, left, right);
9771 if ((val >= -1) && (val <= 1)) {
9772 mkconst(state, ins, val <= 0);
9775 else if (left == right) {
9776 mkconst(state, ins, 1);
9780 static void simplify_ulesseq(struct compile_state *state, struct triple *ins)
9782 struct triple *left, *right;
9783 left = RHS(ins, 0);
9784 right = RHS(ins, 1);
9786 if (is_const(left) && is_const(right)) {
9787 int val;
9788 val = const_ucmp(state, ins, left, right);
9789 if ((val >= -1) && (val <= 1)) {
9790 mkconst(state, ins, val <= 0);
9793 else if (is_zero(left)) {
9794 mkconst(state, ins, 1);
9796 else if (left == right) {
9797 mkconst(state, ins, 1);
9801 static void simplify_smoreeq(struct compile_state *state, struct triple *ins)
9803 struct triple *left, *right;
9804 left = RHS(ins, 0);
9805 right = RHS(ins, 1);
9807 if (is_const(left) && is_const(right)) {
9808 int val;
9809 val = const_scmp(state, ins, left, right);
9810 if ((val >= -1) && (val <= 1)) {
9811 mkconst(state, ins, val >= 0);
9814 else if (left == right) {
9815 mkconst(state, ins, 1);
9819 static void simplify_umoreeq(struct compile_state *state, struct triple *ins)
9821 struct triple *left, *right;
9822 left = RHS(ins, 0);
9823 right = RHS(ins, 1);
9825 if (is_const(left) && is_const(right)) {
9826 int val;
9827 val = const_ucmp(state, ins, left, right);
9828 if ((val >= -1) && (val <= 1)) {
9829 mkconst(state, ins, val >= 0);
9832 else if (is_zero(right)) {
9833 mkconst(state, ins, 1);
9835 else if (left == right) {
9836 mkconst(state, ins, 1);
9840 static void simplify_lfalse(struct compile_state *state, struct triple *ins)
9842 struct triple *rhs;
9843 rhs = RHS(ins, 0);
9845 if (is_const(rhs)) {
9846 mkconst(state, ins, !const_ltrue(state, ins, rhs));
9848 /* Otherwise if I am the only user... */
9849 else if ((rhs->use) &&
9850 (rhs->use->member == ins) && (rhs->use->next == 0)) {
9851 int need_copy = 1;
9852 /* Invert a boolean operation */
9853 switch(rhs->op) {
9854 case OP_LTRUE: rhs->op = OP_LFALSE; break;
9855 case OP_LFALSE: rhs->op = OP_LTRUE; break;
9856 case OP_EQ: rhs->op = OP_NOTEQ; break;
9857 case OP_NOTEQ: rhs->op = OP_EQ; break;
9858 case OP_SLESS: rhs->op = OP_SMOREEQ; break;
9859 case OP_ULESS: rhs->op = OP_UMOREEQ; break;
9860 case OP_SMORE: rhs->op = OP_SLESSEQ; break;
9861 case OP_UMORE: rhs->op = OP_ULESSEQ; break;
9862 case OP_SLESSEQ: rhs->op = OP_SMORE; break;
9863 case OP_ULESSEQ: rhs->op = OP_UMORE; break;
9864 case OP_SMOREEQ: rhs->op = OP_SLESS; break;
9865 case OP_UMOREEQ: rhs->op = OP_ULESS; break;
9866 default:
9867 need_copy = 0;
9868 break;
9870 if (need_copy) {
9871 mkcopy(state, ins, rhs);
9876 static void simplify_ltrue (struct compile_state *state, struct triple *ins)
9878 struct triple *rhs;
9879 rhs = RHS(ins, 0);
9881 if (is_const(rhs)) {
9882 mkconst(state, ins, const_ltrue(state, ins, rhs));
9884 else switch(rhs->op) {
9885 case OP_LTRUE: case OP_LFALSE: case OP_EQ: case OP_NOTEQ:
9886 case OP_SLESS: case OP_ULESS: case OP_SMORE: case OP_UMORE:
9887 case OP_SLESSEQ: case OP_ULESSEQ: case OP_SMOREEQ: case OP_UMOREEQ:
9888 mkcopy(state, ins, rhs);
9893 static void simplify_load(struct compile_state *state, struct triple *ins)
9895 struct triple *addr, *sdecl, *blob;
9897 /* If I am doing a load with a constant pointer from a constant
9898 * table get the value.
9900 addr = RHS(ins, 0);
9901 if ((addr->op == OP_ADDRCONST) && (sdecl = MISC(addr, 0)) &&
9902 (sdecl->op == OP_SDECL) && (blob = MISC(sdecl, 0)) &&
9903 (blob->op == OP_BLOBCONST)) {
9904 unsigned char buffer[SIZEOF_WORD];
9905 size_t reg_size, mem_size;
9906 const char *src, *end;
9907 ulong_t val;
9908 reg_size = reg_size_of(state, ins->type);
9909 if (reg_size > REG_SIZEOF_REG) {
9910 internal_error(state, ins, "load size greater than register");
9912 mem_size = size_of(state, ins->type);
9913 end = blob->u.blob;
9914 end += bits_to_bytes(size_of(state, sdecl->type));
9915 src = blob->u.blob;
9916 src += addr->u.cval;
9918 if (src > end) {
9919 error(state, ins, "Load address out of bounds");
9922 memset(buffer, 0, sizeof(buffer));
9923 memcpy(buffer, src, bits_to_bytes(mem_size));
9925 switch(mem_size) {
9926 case SIZEOF_I8: val = *((uint8_t *) buffer); break;
9927 case SIZEOF_I16: val = *((uint16_t *)buffer); break;
9928 case SIZEOF_I32: val = *((uint32_t *)buffer); break;
9929 case SIZEOF_I64: val = *((uint64_t *)buffer); break;
9930 default:
9931 internal_error(state, ins, "mem_size: %d not handled",
9932 mem_size);
9933 val = 0;
9934 break;
9936 mkconst(state, ins, val);
9940 static void simplify_uextract(struct compile_state *state, struct triple *ins)
9942 if (is_simple_const(RHS(ins, 0))) {
9943 ulong_t val;
9944 ulong_t mask;
9945 val = read_const(state, ins, RHS(ins, 0));
9946 mask = 1;
9947 mask <<= ins->u.bitfield.size;
9948 mask -= 1;
9949 val >>= ins->u.bitfield.offset;
9950 val &= mask;
9951 mkconst(state, ins, val);
9955 static void simplify_sextract(struct compile_state *state, struct triple *ins)
9957 if (is_simple_const(RHS(ins, 0))) {
9958 ulong_t val;
9959 ulong_t mask;
9960 long_t sval;
9961 val = read_const(state, ins, RHS(ins, 0));
9962 mask = 1;
9963 mask <<= ins->u.bitfield.size;
9964 mask -= 1;
9965 val >>= ins->u.bitfield.offset;
9966 val &= mask;
9967 val <<= (SIZEOF_LONG - ins->u.bitfield.size);
9968 sval = val;
9969 sval >>= (SIZEOF_LONG - ins->u.bitfield.size);
9970 mkconst(state, ins, sval);
9974 static void simplify_deposit(struct compile_state *state, struct triple *ins)
9976 if (is_simple_const(RHS(ins, 0)) && is_simple_const(RHS(ins, 1))) {
9977 ulong_t targ, val;
9978 ulong_t mask;
9979 targ = read_const(state, ins, RHS(ins, 0));
9980 val = read_const(state, ins, RHS(ins, 1));
9981 mask = 1;
9982 mask <<= ins->u.bitfield.size;
9983 mask -= 1;
9984 mask <<= ins->u.bitfield.offset;
9985 targ &= ~mask;
9986 val <<= ins->u.bitfield.offset;
9987 val &= mask;
9988 targ |= val;
9989 mkconst(state, ins, targ);
9993 static void simplify_copy(struct compile_state *state, struct triple *ins)
9995 struct triple *right;
9996 right = RHS(ins, 0);
9997 if (is_subset_type(ins->type, right->type)) {
9998 ins->type = right->type;
10000 if (equiv_types(ins->type, right->type)) {
10001 ins->op = OP_COPY;/* I don't need to convert if the types match */
10002 } else {
10003 if (ins->op == OP_COPY) {
10004 internal_error(state, ins, "type mismatch on copy");
10007 if (is_const(right) && (right->op == OP_ADDRCONST) && is_pointer(ins)) {
10008 struct triple *sdecl;
10009 ulong_t offset;
10010 sdecl = MISC(right, 0);
10011 offset = right->u.cval;
10012 mkaddr_const(state, ins, sdecl, offset);
10014 else if (is_const(right) && is_write_compatible(state, ins->type, right->type)) {
10015 switch(right->op) {
10016 case OP_INTCONST:
10018 ulong_t left;
10019 left = read_const(state, ins, right);
10020 /* Ensure I have not overflowed the destination. */
10021 if (size_of(state, right->type) > size_of(state, ins->type)) {
10022 ulong_t mask;
10023 mask = 1;
10024 mask <<= size_of(state, ins->type);
10025 mask -= 1;
10026 left &= mask;
10028 /* Ensure I am properly sign extended */
10029 if (size_of(state, right->type) < size_of(state, ins->type) &&
10030 is_signed(right->type)) {
10031 uint64_t val;
10032 int shift;
10033 shift = SIZEOF_LONG - size_of(state, right->type);
10034 val = left;
10035 val <<= shift;
10036 val >>= shift;
10037 left = (ulong_t)val;
10039 mkconst(state, ins, left);
10040 break;
10042 default:
10043 internal_error(state, ins, "uknown constant");
10044 break;
10049 static int phi_present(struct block *block)
10051 struct triple *ptr;
10052 if (!block) {
10053 return 0;
10055 ptr = block->first;
10056 do {
10057 if (ptr->op == OP_PHI) {
10058 return 1;
10060 ptr = ptr->next;
10061 } while(ptr != block->last);
10062 return 0;
10065 static int phi_dependency(struct block *block)
10067 /* A block has a phi dependency if a phi function
10068 * depends on that block to exist, and makes a block
10069 * that is otherwise useless unsafe to remove.
10071 if (block) {
10072 struct block_set *edge;
10073 for(edge = block->edges; edge; edge = edge->next) {
10074 if (phi_present(edge->member)) {
10075 return 1;
10079 return 0;
10082 static struct triple *branch_target(struct compile_state *state, struct triple *ins)
10084 struct triple *targ;
10085 targ = TARG(ins, 0);
10086 /* During scc_transform temporary triples are allocated that
10087 * loop back onto themselves. If I see one don't advance the
10088 * target.
10090 while(triple_is_structural(state, targ) &&
10091 (targ->next != targ) && (targ->next != state->first)) {
10092 targ = targ->next;
10094 return targ;
10098 static void simplify_branch(struct compile_state *state, struct triple *ins)
10100 int simplified, loops;
10101 if ((ins->op != OP_BRANCH) && (ins->op != OP_CBRANCH)) {
10102 internal_error(state, ins, "not branch");
10104 if (ins->use != 0) {
10105 internal_error(state, ins, "branch use");
10107 /* The challenge here with simplify branch is that I need to
10108 * make modifications to the control flow graph as well
10109 * as to the branch instruction itself. That is handled
10110 * by rebuilding the basic blocks after simplify all is called.
10113 /* If we have a branch to an unconditional branch update
10114 * our target. But watch out for dependencies from phi
10115 * functions.
10116 * Also only do this a limited number of times so
10117 * we don't get into an infinite loop.
10119 loops = 0;
10120 do {
10121 struct triple *targ;
10122 simplified = 0;
10123 targ = branch_target(state, ins);
10124 if ((targ != ins) && (targ->op == OP_BRANCH) &&
10125 !phi_dependency(targ->u.block))
10127 unuse_triple(TARG(ins, 0), ins);
10128 TARG(ins, 0) = TARG(targ, 0);
10129 use_triple(TARG(ins, 0), ins);
10130 simplified = 1;
10132 } while(simplified && (++loops < 20));
10134 /* If we have a conditional branch with a constant condition
10135 * make it an unconditional branch.
10137 if ((ins->op == OP_CBRANCH) && is_simple_const(RHS(ins, 0))) {
10138 struct triple *targ;
10139 ulong_t value;
10140 value = read_const(state, ins, RHS(ins, 0));
10141 unuse_triple(RHS(ins, 0), ins);
10142 targ = TARG(ins, 0);
10143 ins->rhs = 0;
10144 ins->targ = 1;
10145 ins->op = OP_BRANCH;
10146 if (value) {
10147 unuse_triple(ins->next, ins);
10148 TARG(ins, 0) = targ;
10150 else {
10151 unuse_triple(targ, ins);
10152 TARG(ins, 0) = ins->next;
10156 /* If we have a branch to the next instruction,
10157 * make it a noop.
10159 if (TARG(ins, 0) == ins->next) {
10160 unuse_triple(TARG(ins, 0), ins);
10161 if (ins->op == OP_CBRANCH) {
10162 unuse_triple(RHS(ins, 0), ins);
10163 unuse_triple(ins->next, ins);
10165 ins->lhs = 0;
10166 ins->rhs = 0;
10167 ins->misc = 0;
10168 ins->targ = 0;
10169 ins->op = OP_NOOP;
10170 if (ins->use) {
10171 internal_error(state, ins, "noop use != 0");
10176 static void simplify_label(struct compile_state *state, struct triple *ins)
10178 /* Ignore volatile labels */
10179 if (!triple_is_pure(state, ins, ins->id)) {
10180 return;
10182 if (ins->use == 0) {
10183 ins->op = OP_NOOP;
10185 else if (ins->prev->op == OP_LABEL) {
10186 /* In general it is not safe to merge one label that
10187 * imediately follows another. The problem is that the empty
10188 * looking block may have phi functions that depend on it.
10190 if (!phi_dependency(ins->prev->u.block)) {
10191 struct triple_set *user, *next;
10192 ins->op = OP_NOOP;
10193 for(user = ins->use; user; user = next) {
10194 struct triple *use, **expr;
10195 next = user->next;
10196 use = user->member;
10197 expr = triple_targ(state, use, 0);
10198 for(;expr; expr = triple_targ(state, use, expr)) {
10199 if (*expr == ins) {
10200 *expr = ins->prev;
10201 unuse_triple(ins, use);
10202 use_triple(ins->prev, use);
10207 if (ins->use) {
10208 internal_error(state, ins, "noop use != 0");
10214 static void simplify_phi(struct compile_state *state, struct triple *ins)
10216 struct triple **slot;
10217 struct triple *value;
10218 int zrhs, i;
10219 ulong_t cvalue;
10220 slot = &RHS(ins, 0);
10221 zrhs = ins->rhs;
10222 if (zrhs == 0) {
10223 return;
10225 /* See if all of the rhs members of a phi have the same value */
10226 if (slot[0] && is_simple_const(slot[0])) {
10227 cvalue = read_const(state, ins, slot[0]);
10228 for(i = 1; i < zrhs; i++) {
10229 if ( !slot[i] ||
10230 !is_simple_const(slot[i]) ||
10231 !equiv_types(slot[0]->type, slot[i]->type) ||
10232 (cvalue != read_const(state, ins, slot[i]))) {
10233 break;
10236 if (i == zrhs) {
10237 mkconst(state, ins, cvalue);
10238 return;
10242 /* See if all of rhs members of a phi are the same */
10243 value = slot[0];
10244 for(i = 1; i < zrhs; i++) {
10245 if (slot[i] != value) {
10246 break;
10249 if (i == zrhs) {
10250 /* If the phi has a single value just copy it */
10251 if (!is_subset_type(ins->type, value->type)) {
10252 internal_error(state, ins, "bad input type to phi");
10254 /* Make the types match */
10255 if (!equiv_types(ins->type, value->type)) {
10256 ins->type = value->type;
10258 /* Now make the actual copy */
10259 mkcopy(state, ins, value);
10260 return;
10265 static void simplify_bsf(struct compile_state *state, struct triple *ins)
10267 if (is_simple_const(RHS(ins, 0))) {
10268 ulong_t left;
10269 left = read_const(state, ins, RHS(ins, 0));
10270 mkconst(state, ins, bsf(left));
10274 static void simplify_bsr(struct compile_state *state, struct triple *ins)
10276 if (is_simple_const(RHS(ins, 0))) {
10277 ulong_t left;
10278 left = read_const(state, ins, RHS(ins, 0));
10279 mkconst(state, ins, bsr(left));
10284 typedef void (*simplify_t)(struct compile_state *state, struct triple *ins);
10285 static const struct simplify_table {
10286 simplify_t func;
10287 unsigned long flag;
10288 } table_simplify[] = {
10289 #define simplify_sdivt simplify_noop
10290 #define simplify_udivt simplify_noop
10291 #define simplify_piece simplify_noop
10293 [OP_SDIVT ] = { simplify_sdivt, COMPILER_SIMPLIFY_ARITH },
10294 [OP_UDIVT ] = { simplify_udivt, COMPILER_SIMPLIFY_ARITH },
10295 [OP_SMUL ] = { simplify_smul, COMPILER_SIMPLIFY_ARITH },
10296 [OP_UMUL ] = { simplify_umul, COMPILER_SIMPLIFY_ARITH },
10297 [OP_SDIV ] = { simplify_sdiv, COMPILER_SIMPLIFY_ARITH },
10298 [OP_UDIV ] = { simplify_udiv, COMPILER_SIMPLIFY_ARITH },
10299 [OP_SMOD ] = { simplify_smod, COMPILER_SIMPLIFY_ARITH },
10300 [OP_UMOD ] = { simplify_umod, COMPILER_SIMPLIFY_ARITH },
10301 [OP_ADD ] = { simplify_add, COMPILER_SIMPLIFY_ARITH },
10302 [OP_SUB ] = { simplify_sub, COMPILER_SIMPLIFY_ARITH },
10303 [OP_SL ] = { simplify_sl, COMPILER_SIMPLIFY_SHIFT },
10304 [OP_USR ] = { simplify_usr, COMPILER_SIMPLIFY_SHIFT },
10305 [OP_SSR ] = { simplify_ssr, COMPILER_SIMPLIFY_SHIFT },
10306 [OP_AND ] = { simplify_and, COMPILER_SIMPLIFY_BITWISE },
10307 [OP_XOR ] = { simplify_xor, COMPILER_SIMPLIFY_BITWISE },
10308 [OP_OR ] = { simplify_or, COMPILER_SIMPLIFY_BITWISE },
10309 [OP_POS ] = { simplify_pos, COMPILER_SIMPLIFY_ARITH },
10310 [OP_NEG ] = { simplify_neg, COMPILER_SIMPLIFY_ARITH },
10311 [OP_INVERT ] = { simplify_invert, COMPILER_SIMPLIFY_BITWISE },
10313 [OP_EQ ] = { simplify_eq, COMPILER_SIMPLIFY_LOGICAL },
10314 [OP_NOTEQ ] = { simplify_noteq, COMPILER_SIMPLIFY_LOGICAL },
10315 [OP_SLESS ] = { simplify_sless, COMPILER_SIMPLIFY_LOGICAL },
10316 [OP_ULESS ] = { simplify_uless, COMPILER_SIMPLIFY_LOGICAL },
10317 [OP_SMORE ] = { simplify_smore, COMPILER_SIMPLIFY_LOGICAL },
10318 [OP_UMORE ] = { simplify_umore, COMPILER_SIMPLIFY_LOGICAL },
10319 [OP_SLESSEQ ] = { simplify_slesseq, COMPILER_SIMPLIFY_LOGICAL },
10320 [OP_ULESSEQ ] = { simplify_ulesseq, COMPILER_SIMPLIFY_LOGICAL },
10321 [OP_SMOREEQ ] = { simplify_smoreeq, COMPILER_SIMPLIFY_LOGICAL },
10322 [OP_UMOREEQ ] = { simplify_umoreeq, COMPILER_SIMPLIFY_LOGICAL },
10323 [OP_LFALSE ] = { simplify_lfalse, COMPILER_SIMPLIFY_LOGICAL },
10324 [OP_LTRUE ] = { simplify_ltrue, COMPILER_SIMPLIFY_LOGICAL },
10326 [OP_LOAD ] = { simplify_load, COMPILER_SIMPLIFY_OP },
10327 [OP_STORE ] = { simplify_noop, COMPILER_SIMPLIFY_OP },
10329 [OP_UEXTRACT ] = { simplify_uextract, COMPILER_SIMPLIFY_BITFIELD },
10330 [OP_SEXTRACT ] = { simplify_sextract, COMPILER_SIMPLIFY_BITFIELD },
10331 [OP_DEPOSIT ] = { simplify_deposit, COMPILER_SIMPLIFY_BITFIELD },
10333 [OP_NOOP ] = { simplify_noop, COMPILER_SIMPLIFY_OP },
10335 [OP_INTCONST ] = { simplify_noop, COMPILER_SIMPLIFY_OP },
10336 [OP_BLOBCONST ] = { simplify_noop, COMPILER_SIMPLIFY_OP },
10337 [OP_ADDRCONST ] = { simplify_noop, COMPILER_SIMPLIFY_OP },
10338 [OP_UNKNOWNVAL ] = { simplify_noop, COMPILER_SIMPLIFY_OP },
10340 [OP_WRITE ] = { simplify_noop, COMPILER_SIMPLIFY_OP },
10341 [OP_READ ] = { simplify_noop, COMPILER_SIMPLIFY_OP },
10342 [OP_COPY ] = { simplify_copy, COMPILER_SIMPLIFY_COPY },
10343 [OP_CONVERT ] = { simplify_copy, COMPILER_SIMPLIFY_COPY },
10344 [OP_PIECE ] = { simplify_piece, COMPILER_SIMPLIFY_OP },
10345 [OP_ASM ] = { simplify_noop, COMPILER_SIMPLIFY_OP },
10347 [OP_DOT ] = { simplify_noop, COMPILER_SIMPLIFY_OP },
10348 [OP_INDEX ] = { simplify_noop, COMPILER_SIMPLIFY_OP },
10350 [OP_LIST ] = { simplify_noop, COMPILER_SIMPLIFY_OP },
10351 [OP_BRANCH ] = { simplify_branch, COMPILER_SIMPLIFY_BRANCH },
10352 [OP_CBRANCH ] = { simplify_branch, COMPILER_SIMPLIFY_BRANCH },
10353 [OP_CALL ] = { simplify_noop, COMPILER_SIMPLIFY_BRANCH },
10354 [OP_RET ] = { simplify_noop, COMPILER_SIMPLIFY_BRANCH },
10355 [OP_LABEL ] = { simplify_label, COMPILER_SIMPLIFY_LABEL },
10356 [OP_ADECL ] = { simplify_noop, COMPILER_SIMPLIFY_OP },
10357 [OP_SDECL ] = { simplify_noop, COMPILER_SIMPLIFY_OP },
10358 [OP_PHI ] = { simplify_phi, COMPILER_SIMPLIFY_PHI },
10360 [OP_INB ] = { simplify_noop, COMPILER_SIMPLIFY_OP },
10361 [OP_INW ] = { simplify_noop, COMPILER_SIMPLIFY_OP },
10362 [OP_INL ] = { simplify_noop, COMPILER_SIMPLIFY_OP },
10363 [OP_OUTB ] = { simplify_noop, COMPILER_SIMPLIFY_OP },
10364 [OP_OUTW ] = { simplify_noop, COMPILER_SIMPLIFY_OP },
10365 [OP_OUTL ] = { simplify_noop, COMPILER_SIMPLIFY_OP },
10366 [OP_BSF ] = { simplify_bsf, COMPILER_SIMPLIFY_OP },
10367 [OP_BSR ] = { simplify_bsr, COMPILER_SIMPLIFY_OP },
10368 [OP_RDMSR ] = { simplify_noop, COMPILER_SIMPLIFY_OP },
10369 [OP_WRMSR ] = { simplify_noop, COMPILER_SIMPLIFY_OP },
10370 [OP_HLT ] = { simplify_noop, COMPILER_SIMPLIFY_OP },
10373 static inline void debug_simplify(struct compile_state *state,
10374 simplify_t do_simplify, struct triple *ins)
10376 #if DEBUG_SIMPLIFY_HIRES
10377 if (state->functions_joined && (do_simplify != simplify_noop)) {
10378 /* High resolution debugging mode */
10379 fprintf(state->dbgout, "simplifing: ");
10380 display_triple(state->dbgout, ins);
10382 #endif
10383 do_simplify(state, ins);
10384 #if DEBUG_SIMPLIFY_HIRES
10385 if (state->functions_joined && (do_simplify != simplify_noop)) {
10386 /* High resolution debugging mode */
10387 fprintf(state->dbgout, "simplified: ");
10388 display_triple(state->dbgout, ins);
10390 #endif
10392 static void simplify(struct compile_state *state, struct triple *ins)
10394 int op;
10395 simplify_t do_simplify;
10396 if (ins == &unknown_triple) {
10397 internal_error(state, ins, "simplifying the unknown triple?");
10399 do {
10400 op = ins->op;
10401 do_simplify = 0;
10402 if ((op < 0) || (op >= sizeof(table_simplify)/sizeof(table_simplify[0]))) {
10403 do_simplify = 0;
10405 else {
10406 do_simplify = table_simplify[op].func;
10408 if (do_simplify &&
10409 !(state->compiler->flags & table_simplify[op].flag)) {
10410 do_simplify = simplify_noop;
10412 if (do_simplify && (ins->id & TRIPLE_FLAG_VOLATILE)) {
10413 do_simplify = simplify_noop;
10416 if (!do_simplify) {
10417 internal_error(state, ins, "cannot simplify op: %d %s",
10418 op, tops(op));
10419 return;
10421 debug_simplify(state, do_simplify, ins);
10422 } while(ins->op != op);
10425 static void rebuild_ssa_form(struct compile_state *state);
10427 static void simplify_all(struct compile_state *state)
10429 struct triple *ins, *first;
10430 if (!(state->compiler->flags & COMPILER_SIMPLIFY)) {
10431 return;
10433 first = state->first;
10434 ins = first->prev;
10435 do {
10436 simplify(state, ins);
10437 ins = ins->prev;
10438 } while(ins != first->prev);
10439 ins = first;
10440 do {
10441 simplify(state, ins);
10442 ins = ins->next;
10443 }while(ins != first);
10444 rebuild_ssa_form(state);
10446 print_blocks(state, __func__, state->dbgout);
10450 * Builtins....
10451 * ============================
10454 static void register_builtin_function(struct compile_state *state,
10455 const char *name, int op, struct type *rtype, ...)
10457 struct type *ftype, *atype, *ctype, *crtype, *param, **next;
10458 struct triple *def, *result, *work, *first, *retvar, *ret;
10459 struct hash_entry *ident;
10460 struct file_state file;
10461 int parameters;
10462 int name_len;
10463 va_list args;
10464 int i;
10466 /* Dummy file state to get debug handling right */
10467 memset(&file, 0, sizeof(file));
10468 file.basename = "<built-in>";
10469 file.line = 1;
10470 file.report_line = 1;
10471 file.report_name = file.basename;
10472 file.prev = state->file;
10473 state->file = &file;
10474 state->function = name;
10476 /* Find the Parameter count */
10477 valid_op(state, op);
10478 parameters = table_ops[op].rhs;
10479 if (parameters < 0 ) {
10480 internal_error(state, 0, "Invalid builtin parameter count");
10483 /* Find the function type */
10484 ftype = new_type(TYPE_FUNCTION | STOR_INLINE | STOR_STATIC, rtype, 0);
10485 ftype->elements = parameters;
10486 next = &ftype->right;
10487 va_start(args, rtype);
10488 for(i = 0; i < parameters; i++) {
10489 atype = va_arg(args, struct type *);
10490 if (!*next) {
10491 *next = atype;
10492 } else {
10493 *next = new_type(TYPE_PRODUCT, *next, atype);
10494 next = &((*next)->right);
10497 if (!*next) {
10498 *next = &void_type;
10500 va_end(args);
10502 /* Get the initial closure type */
10503 ctype = new_type(TYPE_JOIN, &void_type, 0);
10504 ctype->elements = 1;
10506 /* Get the return type */
10507 crtype = new_type(TYPE_TUPLE, new_type(TYPE_PRODUCT, ctype, rtype), 0);
10508 crtype->elements = 2;
10510 /* Generate the needed triples */
10511 def = triple(state, OP_LIST, ftype, 0, 0);
10512 first = label(state);
10513 RHS(def, 0) = first;
10514 result = flatten(state, first, variable(state, crtype));
10515 retvar = flatten(state, first, variable(state, &void_ptr_type));
10516 ret = triple(state, OP_RET, &void_type, read_expr(state, retvar), 0);
10518 /* Now string them together */
10519 param = ftype->right;
10520 for(i = 0; i < parameters; i++) {
10521 if ((param->type & TYPE_MASK) == TYPE_PRODUCT) {
10522 atype = param->left;
10523 } else {
10524 atype = param;
10526 flatten(state, first, variable(state, atype));
10527 param = param->right;
10529 work = new_triple(state, op, rtype, -1, parameters);
10530 generate_lhs_pieces(state, work);
10531 for(i = 0; i < parameters; i++) {
10532 RHS(work, i) = read_expr(state, farg(state, def, i));
10534 if ((rtype->type & TYPE_MASK) != TYPE_VOID) {
10535 work = write_expr(state, deref_index(state, result, 1), work);
10537 flatten(state, first, work);
10538 flatten(state, first, label(state));
10539 flatten(state, first, ret);
10540 name_len = strlen(name);
10541 ident = lookup(state, name, name_len);
10542 ftype->type_ident = ident;
10543 symbol(state, ident, &ident->sym_ident, def, ftype);
10545 state->file = file.prev;
10546 state->function = 0;
10547 state->main_function = 0;
10549 if (!state->functions) {
10550 state->functions = def;
10551 } else {
10552 insert_triple(state, state->functions, def);
10554 if (state->compiler->debug & DEBUG_INLINE) {
10555 FILE *fp = state->dbgout;
10556 fprintf(fp, "\n");
10557 loc(fp, state, 0);
10558 fprintf(fp, "\n__________ %s _________\n", __FUNCTION__);
10559 display_func(state, fp, def);
10560 fprintf(fp, "__________ %s _________ done\n\n", __FUNCTION__);
10564 static struct type *partial_struct(struct compile_state *state,
10565 const char *field_name, struct type *type, struct type *rest)
10567 struct hash_entry *field_ident;
10568 struct type *result;
10569 int field_name_len;
10571 field_name_len = strlen(field_name);
10572 field_ident = lookup(state, field_name, field_name_len);
10574 result = clone_type(0, type);
10575 result->field_ident = field_ident;
10577 if (rest) {
10578 result = new_type(TYPE_PRODUCT, result, rest);
10580 return result;
10583 static struct type *register_builtin_type(struct compile_state *state,
10584 const char *name, struct type *type)
10586 struct hash_entry *ident;
10587 int name_len;
10589 name_len = strlen(name);
10590 ident = lookup(state, name, name_len);
10592 if ((type->type & TYPE_MASK) == TYPE_PRODUCT) {
10593 ulong_t elements = 0;
10594 struct type *field;
10595 type = new_type(TYPE_STRUCT, type, 0);
10596 field = type->left;
10597 while((field->type & TYPE_MASK) == TYPE_PRODUCT) {
10598 elements++;
10599 field = field->right;
10601 elements++;
10602 symbol(state, ident, &ident->sym_tag, 0, type);
10603 type->type_ident = ident;
10604 type->elements = elements;
10606 symbol(state, ident, &ident->sym_ident, 0, type);
10607 ident->tok = TOK_TYPE_NAME;
10608 return type;
10612 static void register_builtins(struct compile_state *state)
10614 struct type *div_type, *ldiv_type;
10615 struct type *udiv_type, *uldiv_type;
10616 struct type *msr_type;
10618 div_type = register_builtin_type(state, "__builtin_div_t",
10619 partial_struct(state, "quot", &int_type,
10620 partial_struct(state, "rem", &int_type, 0)));
10621 ldiv_type = register_builtin_type(state, "__builtin_ldiv_t",
10622 partial_struct(state, "quot", &long_type,
10623 partial_struct(state, "rem", &long_type, 0)));
10624 udiv_type = register_builtin_type(state, "__builtin_udiv_t",
10625 partial_struct(state, "quot", &uint_type,
10626 partial_struct(state, "rem", &uint_type, 0)));
10627 uldiv_type = register_builtin_type(state, "__builtin_uldiv_t",
10628 partial_struct(state, "quot", &ulong_type,
10629 partial_struct(state, "rem", &ulong_type, 0)));
10631 register_builtin_function(state, "__builtin_div", OP_SDIVT, div_type,
10632 &int_type, &int_type);
10633 register_builtin_function(state, "__builtin_ldiv", OP_SDIVT, ldiv_type,
10634 &long_type, &long_type);
10635 register_builtin_function(state, "__builtin_udiv", OP_UDIVT, udiv_type,
10636 &uint_type, &uint_type);
10637 register_builtin_function(state, "__builtin_uldiv", OP_UDIVT, uldiv_type,
10638 &ulong_type, &ulong_type);
10640 register_builtin_function(state, "__builtin_inb", OP_INB, &uchar_type,
10641 &ushort_type);
10642 register_builtin_function(state, "__builtin_inw", OP_INW, &ushort_type,
10643 &ushort_type);
10644 register_builtin_function(state, "__builtin_inl", OP_INL, &uint_type,
10645 &ushort_type);
10647 register_builtin_function(state, "__builtin_outb", OP_OUTB, &void_type,
10648 &uchar_type, &ushort_type);
10649 register_builtin_function(state, "__builtin_outw", OP_OUTW, &void_type,
10650 &ushort_type, &ushort_type);
10651 register_builtin_function(state, "__builtin_outl", OP_OUTL, &void_type,
10652 &uint_type, &ushort_type);
10654 register_builtin_function(state, "__builtin_bsf", OP_BSF, &int_type,
10655 &int_type);
10656 register_builtin_function(state, "__builtin_bsr", OP_BSR, &int_type,
10657 &int_type);
10659 msr_type = register_builtin_type(state, "__builtin_msr_t",
10660 partial_struct(state, "lo", &ulong_type,
10661 partial_struct(state, "hi", &ulong_type, 0)));
10663 register_builtin_function(state, "__builtin_rdmsr", OP_RDMSR, msr_type,
10664 &ulong_type);
10665 register_builtin_function(state, "__builtin_wrmsr", OP_WRMSR, &void_type,
10666 &ulong_type, &ulong_type, &ulong_type);
10668 register_builtin_function(state, "__builtin_hlt", OP_HLT, &void_type,
10669 &void_type);
10672 static struct type *declarator(
10673 struct compile_state *state, struct type *type,
10674 struct hash_entry **ident, int need_ident);
10675 static void decl(struct compile_state *state, struct triple *first);
10676 static struct type *specifier_qualifier_list(struct compile_state *state);
10677 #if DEBUG_ROMCC_WARNING
10678 static int isdecl_specifier(int tok);
10679 #endif
10680 static struct type *decl_specifiers(struct compile_state *state);
10681 static int istype(int tok);
10682 static struct triple *expr(struct compile_state *state);
10683 static struct triple *assignment_expr(struct compile_state *state);
10684 static struct type *type_name(struct compile_state *state);
10685 static void statement(struct compile_state *state, struct triple *first);
10687 static struct triple *call_expr(
10688 struct compile_state *state, struct triple *func)
10690 struct triple *def;
10691 struct type *param, *type;
10692 ulong_t pvals, index;
10694 if ((func->type->type & TYPE_MASK) != TYPE_FUNCTION) {
10695 error(state, 0, "Called object is not a function");
10697 if (func->op != OP_LIST) {
10698 internal_error(state, 0, "improper function");
10700 eat(state, TOK_LPAREN);
10701 /* Find the return type without any specifiers */
10702 type = clone_type(0, func->type->left);
10703 /* Count the number of rhs entries for OP_FCALL */
10704 param = func->type->right;
10705 pvals = 0;
10706 while((param->type & TYPE_MASK) == TYPE_PRODUCT) {
10707 pvals++;
10708 param = param->right;
10710 if ((param->type & TYPE_MASK) != TYPE_VOID) {
10711 pvals++;
10713 def = new_triple(state, OP_FCALL, type, -1, pvals);
10714 MISC(def, 0) = func;
10716 param = func->type->right;
10717 for(index = 0; index < pvals; index++) {
10718 struct triple *val;
10719 struct type *arg_type;
10720 val = read_expr(state, assignment_expr(state));
10721 arg_type = param;
10722 if ((param->type & TYPE_MASK) == TYPE_PRODUCT) {
10723 arg_type = param->left;
10725 write_compatible(state, arg_type, val->type);
10726 RHS(def, index) = val;
10727 if (index != (pvals - 1)) {
10728 eat(state, TOK_COMMA);
10729 param = param->right;
10732 eat(state, TOK_RPAREN);
10733 return def;
10737 static struct triple *character_constant(struct compile_state *state)
10739 struct triple *def;
10740 struct token *tk;
10741 const signed char *str, *end;
10742 int c;
10743 int str_len;
10744 tk = eat(state, TOK_LIT_CHAR);
10745 str = (signed char *)tk->val.str + 1;
10746 str_len = tk->str_len - 2;
10747 if (str_len <= 0) {
10748 error(state, 0, "empty character constant");
10750 end = str + str_len;
10751 c = char_value(state, &str, end);
10752 if (str != end) {
10753 error(state, 0, "multibyte character constant not supported");
10755 def = int_const(state, &char_type, (ulong_t)((long_t)c));
10756 return def;
10759 static struct triple *string_constant(struct compile_state *state)
10761 struct triple *def;
10762 struct token *tk;
10763 struct type *type;
10764 const signed char *str, *end;
10765 signed char *buf, *ptr;
10766 int str_len;
10768 buf = 0;
10769 type = new_type(TYPE_ARRAY, &char_type, 0);
10770 type->elements = 0;
10771 /* The while loop handles string concatenation */
10772 do {
10773 tk = eat(state, TOK_LIT_STRING);
10774 str = (signed char *)tk->val.str + 1;
10775 str_len = tk->str_len - 2;
10776 if (str_len < 0) {
10777 error(state, 0, "negative string constant length");
10779 /* ignore empty string tokens */
10780 if ('"' == *str && 0 == str[1])
10781 continue;
10782 end = str + str_len;
10783 ptr = buf;
10784 buf = xmalloc(type->elements + str_len + 1, "string_constant");
10785 memcpy(buf, ptr, type->elements);
10786 free(ptr);
10787 ptr = buf + type->elements;
10788 do {
10789 *ptr++ = char_value(state, &str, end);
10790 } while(str < end);
10791 type->elements = ptr - buf;
10792 } while(peek(state) == TOK_LIT_STRING);
10794 /* buf contains the allocated buffer for the string constant. However,
10795 if buf is NULL, then the string constant is empty, but we still
10796 need to allocate one byte for the null character. */
10797 if (buf == NULL) {
10798 buf = xmalloc(1, "string_constant");
10799 ptr = buf;
10802 *ptr = '\0';
10803 type->elements += 1;
10804 def = triple(state, OP_BLOBCONST, type, 0, 0);
10805 def->u.blob = buf;
10807 return def;
10811 static struct triple *integer_constant(struct compile_state *state)
10813 struct triple *def;
10814 unsigned long val;
10815 struct token *tk;
10816 char *end;
10817 int u, l, decimal;
10818 struct type *type;
10820 tk = eat(state, TOK_LIT_INT);
10821 errno = 0;
10822 decimal = (tk->val.str[0] != '0');
10823 val = strtoul(tk->val.str, &end, 0);
10824 if (errno == ERANGE) {
10825 error(state, 0, "Integer constant out of range");
10827 u = l = 0;
10828 if ((*end == 'u') || (*end == 'U')) {
10829 u = 1;
10830 end++;
10832 if ((*end == 'l') || (*end == 'L')) {
10833 l = 1;
10834 end++;
10836 if ((*end == 'u') || (*end == 'U')) {
10837 u = 1;
10838 end++;
10840 if (*end) {
10841 error(state, 0, "Junk at end of integer constant");
10843 if (u && l) {
10844 type = &ulong_type;
10846 else if (l) {
10847 type = &long_type;
10848 if (!decimal && (val > LONG_T_MAX)) {
10849 type = &ulong_type;
10852 else if (u) {
10853 type = &uint_type;
10854 if (val > UINT_T_MAX) {
10855 type = &ulong_type;
10858 else {
10859 type = &int_type;
10860 if (!decimal && (val > INT_T_MAX) && (val <= UINT_T_MAX)) {
10861 type = &uint_type;
10863 else if (!decimal && (val > LONG_T_MAX)) {
10864 type = &ulong_type;
10866 else if (val > INT_T_MAX) {
10867 type = &long_type;
10870 def = int_const(state, type, val);
10871 return def;
10874 static struct triple *primary_expr(struct compile_state *state)
10876 struct triple *def;
10877 int tok;
10878 tok = peek(state);
10879 switch(tok) {
10880 case TOK_IDENT:
10882 struct hash_entry *ident;
10883 /* Here ident is either:
10884 * a varable name
10885 * a function name
10887 ident = eat(state, TOK_IDENT)->ident;
10888 if (!ident->sym_ident) {
10889 error(state, 0, "%s undeclared", ident->name);
10891 def = ident->sym_ident->def;
10892 break;
10894 case TOK_ENUM_CONST:
10896 struct hash_entry *ident;
10897 /* Here ident is an enumeration constant */
10898 ident = eat(state, TOK_ENUM_CONST)->ident;
10899 if (!ident->sym_ident) {
10900 error(state, 0, "%s undeclared", ident->name);
10902 def = ident->sym_ident->def;
10903 break;
10905 case TOK_MIDENT:
10907 struct hash_entry *ident;
10908 ident = eat(state, TOK_MIDENT)->ident;
10909 warning(state, 0, "Replacing undefined macro: %s with 0",
10910 ident->name);
10911 def = int_const(state, &int_type, 0);
10912 break;
10914 case TOK_LPAREN:
10915 eat(state, TOK_LPAREN);
10916 def = expr(state);
10917 eat(state, TOK_RPAREN);
10918 break;
10919 case TOK_LIT_INT:
10920 def = integer_constant(state);
10921 break;
10922 case TOK_LIT_FLOAT:
10923 eat(state, TOK_LIT_FLOAT);
10924 error(state, 0, "Floating point constants not supported");
10925 def = 0;
10926 FINISHME();
10927 break;
10928 case TOK_LIT_CHAR:
10929 def = character_constant(state);
10930 break;
10931 case TOK_LIT_STRING:
10932 def = string_constant(state);
10933 break;
10934 default:
10935 def = 0;
10936 error(state, 0, "Unexpected token: %s\n", tokens[tok]);
10938 return def;
10941 static struct triple *postfix_expr(struct compile_state *state)
10943 struct triple *def;
10944 int postfix;
10945 def = primary_expr(state);
10946 do {
10947 struct triple *left;
10948 int tok;
10949 postfix = 1;
10950 left = def;
10951 switch((tok = peek(state))) {
10952 case TOK_LBRACKET:
10953 eat(state, TOK_LBRACKET);
10954 def = mk_subscript_expr(state, left, expr(state));
10955 eat(state, TOK_RBRACKET);
10956 break;
10957 case TOK_LPAREN:
10958 def = call_expr(state, def);
10959 break;
10960 case TOK_DOT:
10962 struct hash_entry *field;
10963 eat(state, TOK_DOT);
10964 field = eat(state, TOK_IDENT)->ident;
10965 def = deref_field(state, def, field);
10966 break;
10968 case TOK_ARROW:
10970 struct hash_entry *field;
10971 eat(state, TOK_ARROW);
10972 field = eat(state, TOK_IDENT)->ident;
10973 def = mk_deref_expr(state, read_expr(state, def));
10974 def = deref_field(state, def, field);
10975 break;
10977 case TOK_PLUSPLUS:
10978 eat(state, TOK_PLUSPLUS);
10979 def = mk_post_inc_expr(state, left);
10980 break;
10981 case TOK_MINUSMINUS:
10982 eat(state, TOK_MINUSMINUS);
10983 def = mk_post_dec_expr(state, left);
10984 break;
10985 default:
10986 postfix = 0;
10987 break;
10989 } while(postfix);
10990 return def;
10993 static struct triple *cast_expr(struct compile_state *state);
10995 static struct triple *unary_expr(struct compile_state *state)
10997 struct triple *def, *right;
10998 int tok;
10999 switch((tok = peek(state))) {
11000 case TOK_PLUSPLUS:
11001 eat(state, TOK_PLUSPLUS);
11002 def = mk_pre_inc_expr(state, unary_expr(state));
11003 break;
11004 case TOK_MINUSMINUS:
11005 eat(state, TOK_MINUSMINUS);
11006 def = mk_pre_dec_expr(state, unary_expr(state));
11007 break;
11008 case TOK_AND:
11009 eat(state, TOK_AND);
11010 def = mk_addr_expr(state, cast_expr(state), 0);
11011 break;
11012 case TOK_STAR:
11013 eat(state, TOK_STAR);
11014 def = mk_deref_expr(state, read_expr(state, cast_expr(state)));
11015 break;
11016 case TOK_PLUS:
11017 eat(state, TOK_PLUS);
11018 right = read_expr(state, cast_expr(state));
11019 arithmetic(state, right);
11020 def = integral_promotion(state, right);
11021 break;
11022 case TOK_MINUS:
11023 eat(state, TOK_MINUS);
11024 right = read_expr(state, cast_expr(state));
11025 arithmetic(state, right);
11026 def = integral_promotion(state, right);
11027 def = triple(state, OP_NEG, def->type, def, 0);
11028 break;
11029 case TOK_TILDE:
11030 eat(state, TOK_TILDE);
11031 right = read_expr(state, cast_expr(state));
11032 integral(state, right);
11033 def = integral_promotion(state, right);
11034 def = triple(state, OP_INVERT, def->type, def, 0);
11035 break;
11036 case TOK_BANG:
11037 eat(state, TOK_BANG);
11038 right = read_expr(state, cast_expr(state));
11039 bool(state, right);
11040 def = lfalse_expr(state, right);
11041 break;
11042 case TOK_SIZEOF:
11044 struct type *type;
11045 int tok1, tok2;
11046 eat(state, TOK_SIZEOF);
11047 tok1 = peek(state);
11048 tok2 = peek2(state);
11049 if ((tok1 == TOK_LPAREN) && istype(tok2)) {
11050 eat(state, TOK_LPAREN);
11051 type = type_name(state);
11052 eat(state, TOK_RPAREN);
11054 else {
11055 struct triple *expr;
11056 expr = unary_expr(state);
11057 type = expr->type;
11058 release_expr(state, expr);
11060 def = int_const(state, &ulong_type, size_of_in_bytes(state, type));
11061 break;
11063 case TOK_ALIGNOF:
11065 struct type *type;
11066 int tok1, tok2;
11067 eat(state, TOK_ALIGNOF);
11068 tok1 = peek(state);
11069 tok2 = peek2(state);
11070 if ((tok1 == TOK_LPAREN) && istype(tok2)) {
11071 eat(state, TOK_LPAREN);
11072 type = type_name(state);
11073 eat(state, TOK_RPAREN);
11075 else {
11076 struct triple *expr;
11077 expr = unary_expr(state);
11078 type = expr->type;
11079 release_expr(state, expr);
11081 def = int_const(state, &ulong_type, align_of_in_bytes(state, type));
11082 break;
11084 case TOK_MDEFINED:
11086 /* We only come here if we are called from the preprocessor */
11087 struct hash_entry *ident;
11088 int parens;
11089 eat(state, TOK_MDEFINED);
11090 parens = 0;
11091 if (pp_peek(state) == TOK_LPAREN) {
11092 pp_eat(state, TOK_LPAREN);
11093 parens = 1;
11095 ident = pp_eat(state, TOK_MIDENT)->ident;
11096 if (parens) {
11097 eat(state, TOK_RPAREN);
11099 def = int_const(state, &int_type, ident->sym_define != 0);
11100 break;
11102 default:
11103 def = postfix_expr(state);
11104 break;
11106 return def;
11109 static struct triple *cast_expr(struct compile_state *state)
11111 struct triple *def;
11112 int tok1, tok2;
11113 tok1 = peek(state);
11114 tok2 = peek2(state);
11115 if ((tok1 == TOK_LPAREN) && istype(tok2)) {
11116 struct type *type;
11117 eat(state, TOK_LPAREN);
11118 type = type_name(state);
11119 eat(state, TOK_RPAREN);
11120 def = mk_cast_expr(state, type, cast_expr(state));
11122 else {
11123 def = unary_expr(state);
11125 return def;
11128 static struct triple *mult_expr(struct compile_state *state)
11130 struct triple *def;
11131 int done;
11132 def = cast_expr(state);
11133 do {
11134 struct triple *left, *right;
11135 struct type *result_type;
11136 int tok, op, sign;
11137 done = 0;
11138 tok = peek(state);
11139 switch(tok) {
11140 case TOK_STAR:
11141 case TOK_DIV:
11142 case TOK_MOD:
11143 left = read_expr(state, def);
11144 arithmetic(state, left);
11146 eat(state, tok);
11148 right = read_expr(state, cast_expr(state));
11149 arithmetic(state, right);
11151 result_type = arithmetic_result(state, left, right);
11152 sign = is_signed(result_type);
11153 op = -1;
11154 switch(tok) {
11155 case TOK_STAR: op = sign? OP_SMUL : OP_UMUL; break;
11156 case TOK_DIV: op = sign? OP_SDIV : OP_UDIV; break;
11157 case TOK_MOD: op = sign? OP_SMOD : OP_UMOD; break;
11159 def = triple(state, op, result_type, left, right);
11160 break;
11161 default:
11162 done = 1;
11163 break;
11165 } while(!done);
11166 return def;
11169 static struct triple *add_expr(struct compile_state *state)
11171 struct triple *def;
11172 int done;
11173 def = mult_expr(state);
11174 do {
11175 done = 0;
11176 switch( peek(state)) {
11177 case TOK_PLUS:
11178 eat(state, TOK_PLUS);
11179 def = mk_add_expr(state, def, mult_expr(state));
11180 break;
11181 case TOK_MINUS:
11182 eat(state, TOK_MINUS);
11183 def = mk_sub_expr(state, def, mult_expr(state));
11184 break;
11185 default:
11186 done = 1;
11187 break;
11189 } while(!done);
11190 return def;
11193 static struct triple *shift_expr(struct compile_state *state)
11195 struct triple *def;
11196 int done;
11197 def = add_expr(state);
11198 do {
11199 struct triple *left, *right;
11200 int tok, op;
11201 done = 0;
11202 switch((tok = peek(state))) {
11203 case TOK_SL:
11204 case TOK_SR:
11205 left = read_expr(state, def);
11206 integral(state, left);
11207 left = integral_promotion(state, left);
11209 eat(state, tok);
11211 right = read_expr(state, add_expr(state));
11212 integral(state, right);
11213 right = integral_promotion(state, right);
11215 op = (tok == TOK_SL)? OP_SL :
11216 is_signed(left->type)? OP_SSR: OP_USR;
11218 def = triple(state, op, left->type, left, right);
11219 break;
11220 default:
11221 done = 1;
11222 break;
11224 } while(!done);
11225 return def;
11228 static struct triple *relational_expr(struct compile_state *state)
11230 #if DEBUG_ROMCC_WARNINGS
11231 #warning "Extend relational exprs to work on more than arithmetic types"
11232 #endif
11233 struct triple *def;
11234 int done;
11235 def = shift_expr(state);
11236 do {
11237 struct triple *left, *right;
11238 struct type *arg_type;
11239 int tok, op, sign;
11240 done = 0;
11241 switch((tok = peek(state))) {
11242 case TOK_LESS:
11243 case TOK_MORE:
11244 case TOK_LESSEQ:
11245 case TOK_MOREEQ:
11246 left = read_expr(state, def);
11247 arithmetic(state, left);
11249 eat(state, tok);
11251 right = read_expr(state, shift_expr(state));
11252 arithmetic(state, right);
11254 arg_type = arithmetic_result(state, left, right);
11255 sign = is_signed(arg_type);
11256 xfree(arg_type);
11257 op = -1;
11258 switch(tok) {
11259 case TOK_LESS: op = sign? OP_SLESS : OP_ULESS; break;
11260 case TOK_MORE: op = sign? OP_SMORE : OP_UMORE; break;
11261 case TOK_LESSEQ: op = sign? OP_SLESSEQ : OP_ULESSEQ; break;
11262 case TOK_MOREEQ: op = sign? OP_SMOREEQ : OP_UMOREEQ; break;
11264 def = triple(state, op, &int_type, left, right);
11265 break;
11266 default:
11267 done = 1;
11268 break;
11270 } while(!done);
11271 return def;
11274 static struct triple *equality_expr(struct compile_state *state)
11276 #if DEBUG_ROMCC_WARNINGS
11277 #warning "Extend equality exprs to work on more than arithmetic types"
11278 #endif
11279 struct triple *def;
11280 int done;
11281 def = relational_expr(state);
11282 do {
11283 struct triple *left, *right;
11284 int tok, op;
11285 done = 0;
11286 switch((tok = peek(state))) {
11287 case TOK_EQEQ:
11288 case TOK_NOTEQ:
11289 left = read_expr(state, def);
11290 arithmetic(state, left);
11291 eat(state, tok);
11292 right = read_expr(state, relational_expr(state));
11293 arithmetic(state, right);
11294 op = (tok == TOK_EQEQ) ? OP_EQ: OP_NOTEQ;
11295 def = triple(state, op, &int_type, left, right);
11296 break;
11297 default:
11298 done = 1;
11299 break;
11301 } while(!done);
11302 return def;
11305 static struct triple *and_expr(struct compile_state *state)
11307 struct triple *def;
11308 def = equality_expr(state);
11309 while(peek(state) == TOK_AND) {
11310 struct triple *left, *right;
11311 struct type *result_type;
11312 left = read_expr(state, def);
11313 integral(state, left);
11314 eat(state, TOK_AND);
11315 right = read_expr(state, equality_expr(state));
11316 integral(state, right);
11317 result_type = arithmetic_result(state, left, right);
11318 def = triple(state, OP_AND, result_type, left, right);
11320 return def;
11323 static struct triple *xor_expr(struct compile_state *state)
11325 struct triple *def;
11326 def = and_expr(state);
11327 while(peek(state) == TOK_XOR) {
11328 struct triple *left, *right;
11329 struct type *result_type;
11330 left = read_expr(state, def);
11331 integral(state, left);
11332 eat(state, TOK_XOR);
11333 right = read_expr(state, and_expr(state));
11334 integral(state, right);
11335 result_type = arithmetic_result(state, left, right);
11336 def = triple(state, OP_XOR, result_type, left, right);
11338 return def;
11341 static struct triple *or_expr(struct compile_state *state)
11343 struct triple *def;
11344 def = xor_expr(state);
11345 while(peek(state) == TOK_OR) {
11346 struct triple *left, *right;
11347 struct type *result_type;
11348 left = read_expr(state, def);
11349 integral(state, left);
11350 eat(state, TOK_OR);
11351 right = read_expr(state, xor_expr(state));
11352 integral(state, right);
11353 result_type = arithmetic_result(state, left, right);
11354 def = triple(state, OP_OR, result_type, left, right);
11356 return def;
11359 static struct triple *land_expr(struct compile_state *state)
11361 struct triple *def;
11362 def = or_expr(state);
11363 while(peek(state) == TOK_LOGAND) {
11364 struct triple *left, *right;
11365 left = read_expr(state, def);
11366 bool(state, left);
11367 eat(state, TOK_LOGAND);
11368 right = read_expr(state, or_expr(state));
11369 bool(state, right);
11371 def = mkland_expr(state,
11372 ltrue_expr(state, left),
11373 ltrue_expr(state, right));
11375 return def;
11378 static struct triple *lor_expr(struct compile_state *state)
11380 struct triple *def;
11381 def = land_expr(state);
11382 while(peek(state) == TOK_LOGOR) {
11383 struct triple *left, *right;
11384 left = read_expr(state, def);
11385 bool(state, left);
11386 eat(state, TOK_LOGOR);
11387 right = read_expr(state, land_expr(state));
11388 bool(state, right);
11390 def = mklor_expr(state,
11391 ltrue_expr(state, left),
11392 ltrue_expr(state, right));
11394 return def;
11397 static struct triple *conditional_expr(struct compile_state *state)
11399 struct triple *def;
11400 def = lor_expr(state);
11401 if (peek(state) == TOK_QUEST) {
11402 struct triple *test, *left, *right;
11403 bool(state, def);
11404 test = ltrue_expr(state, read_expr(state, def));
11405 eat(state, TOK_QUEST);
11406 left = read_expr(state, expr(state));
11407 eat(state, TOK_COLON);
11408 right = read_expr(state, conditional_expr(state));
11410 def = mkcond_expr(state, test, left, right);
11412 return def;
11415 struct cv_triple {
11416 struct triple *val;
11417 int id;
11420 static void set_cv(struct compile_state *state, struct cv_triple *cv,
11421 struct triple *dest, struct triple *val)
11423 if (cv[dest->id].val) {
11424 free_triple(state, cv[dest->id].val);
11426 cv[dest->id].val = val;
11428 static struct triple *get_cv(struct compile_state *state, struct cv_triple *cv,
11429 struct triple *src)
11431 return cv[src->id].val;
11434 static struct triple *eval_const_expr(
11435 struct compile_state *state, struct triple *expr)
11437 struct triple *def;
11438 if (is_const(expr)) {
11439 def = expr;
11441 else {
11442 /* If we don't start out as a constant simplify into one */
11443 struct triple *head, *ptr;
11444 struct cv_triple *cv;
11445 int i, count;
11446 head = label(state); /* dummy initial triple */
11447 flatten(state, head, expr);
11448 count = 1;
11449 for(ptr = head->next; ptr != head; ptr = ptr->next) {
11450 count++;
11452 cv = xcmalloc(sizeof(struct cv_triple)*count, "const value vector");
11453 i = 1;
11454 for(ptr = head->next; ptr != head; ptr = ptr->next) {
11455 cv[i].val = 0;
11456 cv[i].id = ptr->id;
11457 ptr->id = i;
11458 i++;
11460 ptr = head->next;
11461 do {
11462 valid_ins(state, ptr);
11463 if ((ptr->op == OP_PHI) || (ptr->op == OP_LIST)) {
11464 internal_error(state, ptr,
11465 "unexpected %s in constant expression",
11466 tops(ptr->op));
11468 else if (ptr->op == OP_LIST) {
11470 else if (triple_is_structural(state, ptr)) {
11471 ptr = ptr->next;
11473 else if (triple_is_ubranch(state, ptr)) {
11474 ptr = TARG(ptr, 0);
11476 else if (triple_is_cbranch(state, ptr)) {
11477 struct triple *cond_val;
11478 cond_val = get_cv(state, cv, RHS(ptr, 0));
11479 if (!cond_val || !is_const(cond_val) ||
11480 (cond_val->op != OP_INTCONST))
11482 internal_error(state, ptr, "bad branch condition");
11484 if (cond_val->u.cval == 0) {
11485 ptr = ptr->next;
11486 } else {
11487 ptr = TARG(ptr, 0);
11490 else if (triple_is_branch(state, ptr)) {
11491 error(state, ptr, "bad branch type in constant expression");
11493 else if (ptr->op == OP_WRITE) {
11494 struct triple *val;
11495 val = get_cv(state, cv, RHS(ptr, 0));
11497 set_cv(state, cv, MISC(ptr, 0),
11498 copy_triple(state, val));
11499 set_cv(state, cv, ptr,
11500 copy_triple(state, val));
11501 ptr = ptr->next;
11503 else if (ptr->op == OP_READ) {
11504 set_cv(state, cv, ptr,
11505 copy_triple(state,
11506 get_cv(state, cv, RHS(ptr, 0))));
11507 ptr = ptr->next;
11509 else if (triple_is_pure(state, ptr, cv[ptr->id].id)) {
11510 struct triple *val, **rhs;
11511 val = copy_triple(state, ptr);
11512 rhs = triple_rhs(state, val, 0);
11513 for(; rhs; rhs = triple_rhs(state, val, rhs)) {
11514 if (!*rhs) {
11515 internal_error(state, ptr, "Missing rhs");
11517 *rhs = get_cv(state, cv, *rhs);
11519 simplify(state, val);
11520 set_cv(state, cv, ptr, val);
11521 ptr = ptr->next;
11523 else {
11524 error(state, ptr, "impure operation in constant expression");
11527 } while(ptr != head);
11529 /* Get the result value */
11530 def = get_cv(state, cv, head->prev);
11531 cv[head->prev->id].val = 0;
11533 /* Free the temporary values */
11534 for(i = 0; i < count; i++) {
11535 if (cv[i].val) {
11536 free_triple(state, cv[i].val);
11537 cv[i].val = 0;
11540 xfree(cv);
11541 /* Free the intermediate expressions */
11542 while(head->next != head) {
11543 release_triple(state, head->next);
11545 free_triple(state, head);
11547 if (!is_const(def)) {
11548 error(state, expr, "Not a constant expression");
11550 return def;
11553 static struct triple *constant_expr(struct compile_state *state)
11555 return eval_const_expr(state, conditional_expr(state));
11558 static struct triple *assignment_expr(struct compile_state *state)
11560 struct triple *def, *left, *right;
11561 int tok, op, sign;
11562 /* The C grammer in K&R shows assignment expressions
11563 * only taking unary expressions as input on their
11564 * left hand side. But specifies the precedence of
11565 * assignemnt as the lowest operator except for comma.
11567 * Allowing conditional expressions on the left hand side
11568 * of an assignement results in a grammar that accepts
11569 * a larger set of statements than standard C. As long
11570 * as the subset of the grammar that is standard C behaves
11571 * correctly this should cause no problems.
11573 * For the extra token strings accepted by the grammar
11574 * none of them should produce a valid lvalue, so they
11575 * should not produce functioning programs.
11577 * GCC has this bug as well, so surprises should be minimal.
11579 def = conditional_expr(state);
11580 left = def;
11581 switch((tok = peek(state))) {
11582 case TOK_EQ:
11583 lvalue(state, left);
11584 eat(state, TOK_EQ);
11585 def = write_expr(state, left,
11586 read_expr(state, assignment_expr(state)));
11587 break;
11588 case TOK_TIMESEQ:
11589 case TOK_DIVEQ:
11590 case TOK_MODEQ:
11591 lvalue(state, left);
11592 arithmetic(state, left);
11593 eat(state, tok);
11594 right = read_expr(state, assignment_expr(state));
11595 arithmetic(state, right);
11597 sign = is_signed(left->type);
11598 op = -1;
11599 switch(tok) {
11600 case TOK_TIMESEQ: op = sign? OP_SMUL : OP_UMUL; break;
11601 case TOK_DIVEQ: op = sign? OP_SDIV : OP_UDIV; break;
11602 case TOK_MODEQ: op = sign? OP_SMOD : OP_UMOD; break;
11604 def = write_expr(state, left,
11605 triple(state, op, left->type,
11606 read_expr(state, left), right));
11607 break;
11608 case TOK_PLUSEQ:
11609 lvalue(state, left);
11610 eat(state, TOK_PLUSEQ);
11611 def = write_expr(state, left,
11612 mk_add_expr(state, left, assignment_expr(state)));
11613 break;
11614 case TOK_MINUSEQ:
11615 lvalue(state, left);
11616 eat(state, TOK_MINUSEQ);
11617 def = write_expr(state, left,
11618 mk_sub_expr(state, left, assignment_expr(state)));
11619 break;
11620 case TOK_SLEQ:
11621 case TOK_SREQ:
11622 case TOK_ANDEQ:
11623 case TOK_XOREQ:
11624 case TOK_OREQ:
11625 lvalue(state, left);
11626 integral(state, left);
11627 eat(state, tok);
11628 right = read_expr(state, assignment_expr(state));
11629 integral(state, right);
11630 right = integral_promotion(state, right);
11631 sign = is_signed(left->type);
11632 op = -1;
11633 switch(tok) {
11634 case TOK_SLEQ: op = OP_SL; break;
11635 case TOK_SREQ: op = sign? OP_SSR: OP_USR; break;
11636 case TOK_ANDEQ: op = OP_AND; break;
11637 case TOK_XOREQ: op = OP_XOR; break;
11638 case TOK_OREQ: op = OP_OR; break;
11640 def = write_expr(state, left,
11641 triple(state, op, left->type,
11642 read_expr(state, left), right));
11643 break;
11645 return def;
11648 static struct triple *expr(struct compile_state *state)
11650 struct triple *def;
11651 def = assignment_expr(state);
11652 while(peek(state) == TOK_COMMA) {
11653 eat(state, TOK_COMMA);
11654 def = mkprog(state, def, assignment_expr(state), 0UL);
11656 return def;
11659 static void expr_statement(struct compile_state *state, struct triple *first)
11661 if (peek(state) != TOK_SEMI) {
11662 /* lvalue conversions always apply except when certian operators
11663 * are applied. I apply the lvalue conversions here
11664 * as I know no more operators will be applied.
11666 flatten(state, first, lvalue_conversion(state, expr(state)));
11668 eat(state, TOK_SEMI);
11671 static void if_statement(struct compile_state *state, struct triple *first)
11673 struct triple *test, *jmp1, *jmp2, *middle, *end;
11675 jmp1 = jmp2 = middle = 0;
11676 eat(state, TOK_IF);
11677 eat(state, TOK_LPAREN);
11678 test = expr(state);
11679 bool(state, test);
11680 /* Cleanup and invert the test */
11681 test = lfalse_expr(state, read_expr(state, test));
11682 eat(state, TOK_RPAREN);
11683 /* Generate the needed pieces */
11684 middle = label(state);
11685 jmp1 = branch(state, middle, test);
11686 /* Thread the pieces together */
11687 flatten(state, first, test);
11688 flatten(state, first, jmp1);
11689 flatten(state, first, label(state));
11690 statement(state, first);
11691 if (peek(state) == TOK_ELSE) {
11692 eat(state, TOK_ELSE);
11693 /* Generate the rest of the pieces */
11694 end = label(state);
11695 jmp2 = branch(state, end, 0);
11696 /* Thread them together */
11697 flatten(state, first, jmp2);
11698 flatten(state, first, middle);
11699 statement(state, first);
11700 flatten(state, first, end);
11702 else {
11703 flatten(state, first, middle);
11707 static void for_statement(struct compile_state *state, struct triple *first)
11709 struct triple *head, *test, *tail, *jmp1, *jmp2, *end;
11710 struct triple *label1, *label2, *label3;
11711 struct hash_entry *ident;
11713 eat(state, TOK_FOR);
11714 eat(state, TOK_LPAREN);
11715 head = test = tail = jmp1 = jmp2 = 0;
11716 if (peek(state) != TOK_SEMI) {
11717 head = expr(state);
11719 eat(state, TOK_SEMI);
11720 if (peek(state) != TOK_SEMI) {
11721 test = expr(state);
11722 bool(state, test);
11723 test = ltrue_expr(state, read_expr(state, test));
11725 eat(state, TOK_SEMI);
11726 if (peek(state) != TOK_RPAREN) {
11727 tail = expr(state);
11729 eat(state, TOK_RPAREN);
11730 /* Generate the needed pieces */
11731 label1 = label(state);
11732 label2 = label(state);
11733 label3 = label(state);
11734 if (test) {
11735 jmp1 = branch(state, label3, 0);
11736 jmp2 = branch(state, label1, test);
11738 else {
11739 jmp2 = branch(state, label1, 0);
11741 end = label(state);
11742 /* Remember where break and continue go */
11743 start_scope(state);
11744 ident = state->i_break;
11745 symbol(state, ident, &ident->sym_ident, end, end->type);
11746 ident = state->i_continue;
11747 symbol(state, ident, &ident->sym_ident, label2, label2->type);
11748 /* Now include the body */
11749 flatten(state, first, head);
11750 flatten(state, first, jmp1);
11751 flatten(state, first, label1);
11752 statement(state, first);
11753 flatten(state, first, label2);
11754 flatten(state, first, tail);
11755 flatten(state, first, label3);
11756 flatten(state, first, test);
11757 flatten(state, first, jmp2);
11758 flatten(state, first, end);
11759 /* Cleanup the break/continue scope */
11760 end_scope(state);
11763 static void while_statement(struct compile_state *state, struct triple *first)
11765 struct triple *label1, *test, *label2, *jmp1, *jmp2, *end;
11766 struct hash_entry *ident;
11767 eat(state, TOK_WHILE);
11768 eat(state, TOK_LPAREN);
11769 test = expr(state);
11770 bool(state, test);
11771 test = ltrue_expr(state, read_expr(state, test));
11772 eat(state, TOK_RPAREN);
11773 /* Generate the needed pieces */
11774 label1 = label(state);
11775 label2 = label(state);
11776 jmp1 = branch(state, label2, 0);
11777 jmp2 = branch(state, label1, test);
11778 end = label(state);
11779 /* Remember where break and continue go */
11780 start_scope(state);
11781 ident = state->i_break;
11782 symbol(state, ident, &ident->sym_ident, end, end->type);
11783 ident = state->i_continue;
11784 symbol(state, ident, &ident->sym_ident, label2, label2->type);
11785 /* Thread them together */
11786 flatten(state, first, jmp1);
11787 flatten(state, first, label1);
11788 statement(state, first);
11789 flatten(state, first, label2);
11790 flatten(state, first, test);
11791 flatten(state, first, jmp2);
11792 flatten(state, first, end);
11793 /* Cleanup the break/continue scope */
11794 end_scope(state);
11797 static void do_statement(struct compile_state *state, struct triple *first)
11799 struct triple *label1, *label2, *test, *end;
11800 struct hash_entry *ident;
11801 eat(state, TOK_DO);
11802 /* Generate the needed pieces */
11803 label1 = label(state);
11804 label2 = label(state);
11805 end = label(state);
11806 /* Remember where break and continue go */
11807 start_scope(state);
11808 ident = state->i_break;
11809 symbol(state, ident, &ident->sym_ident, end, end->type);
11810 ident = state->i_continue;
11811 symbol(state, ident, &ident->sym_ident, label2, label2->type);
11812 /* Now include the body */
11813 flatten(state, first, label1);
11814 statement(state, first);
11815 /* Cleanup the break/continue scope */
11816 end_scope(state);
11817 /* Eat the rest of the loop */
11818 eat(state, TOK_WHILE);
11819 eat(state, TOK_LPAREN);
11820 test = read_expr(state, expr(state));
11821 bool(state, test);
11822 eat(state, TOK_RPAREN);
11823 eat(state, TOK_SEMI);
11824 /* Thread the pieces together */
11825 test = ltrue_expr(state, test);
11826 flatten(state, first, label2);
11827 flatten(state, first, test);
11828 flatten(state, first, branch(state, label1, test));
11829 flatten(state, first, end);
11833 static void return_statement(struct compile_state *state, struct triple *first)
11835 struct triple *jmp, *mv, *dest, *var, *val;
11836 int last;
11837 eat(state, TOK_RETURN);
11839 #if DEBUG_ROMCC_WARNINGS
11840 #warning "FIXME implement a more general excess branch elimination"
11841 #endif
11842 val = 0;
11843 /* If we have a return value do some more work */
11844 if (peek(state) != TOK_SEMI) {
11845 val = read_expr(state, expr(state));
11847 eat(state, TOK_SEMI);
11849 /* See if this last statement in a function */
11850 last = ((peek(state) == TOK_RBRACE) &&
11851 (state->scope_depth == GLOBAL_SCOPE_DEPTH +2));
11853 /* Find the return variable */
11854 var = fresult(state, state->main_function);
11856 /* Find the return destination */
11857 dest = state->i_return->sym_ident->def;
11858 mv = jmp = 0;
11859 /* If needed generate a jump instruction */
11860 if (!last) {
11861 jmp = branch(state, dest, 0);
11863 /* If needed generate an assignment instruction */
11864 if (val) {
11865 mv = write_expr(state, deref_index(state, var, 1), val);
11867 /* Now put the code together */
11868 if (mv) {
11869 flatten(state, first, mv);
11870 flatten(state, first, jmp);
11872 else if (jmp) {
11873 flatten(state, first, jmp);
11877 static void break_statement(struct compile_state *state, struct triple *first)
11879 struct triple *dest;
11880 eat(state, TOK_BREAK);
11881 eat(state, TOK_SEMI);
11882 if (!state->i_break->sym_ident) {
11883 error(state, 0, "break statement not within loop or switch");
11885 dest = state->i_break->sym_ident->def;
11886 flatten(state, first, branch(state, dest, 0));
11889 static void continue_statement(struct compile_state *state, struct triple *first)
11891 struct triple *dest;
11892 eat(state, TOK_CONTINUE);
11893 eat(state, TOK_SEMI);
11894 if (!state->i_continue->sym_ident) {
11895 error(state, 0, "continue statement outside of a loop");
11897 dest = state->i_continue->sym_ident->def;
11898 flatten(state, first, branch(state, dest, 0));
11901 static void goto_statement(struct compile_state *state, struct triple *first)
11903 struct hash_entry *ident;
11904 eat(state, TOK_GOTO);
11905 ident = eat(state, TOK_IDENT)->ident;
11906 if (!ident->sym_label) {
11907 /* If this is a forward branch allocate the label now,
11908 * it will be flattend in the appropriate location later.
11910 struct triple *ins;
11911 ins = label(state);
11912 label_symbol(state, ident, ins, FUNCTION_SCOPE_DEPTH);
11914 eat(state, TOK_SEMI);
11916 flatten(state, first, branch(state, ident->sym_label->def, 0));
11919 static void labeled_statement(struct compile_state *state, struct triple *first)
11921 struct triple *ins;
11922 struct hash_entry *ident;
11924 ident = eat(state, TOK_IDENT)->ident;
11925 if (ident->sym_label && ident->sym_label->def) {
11926 ins = ident->sym_label->def;
11927 put_occurrence(ins->occurrence);
11928 ins->occurrence = new_occurrence(state);
11930 else {
11931 ins = label(state);
11932 label_symbol(state, ident, ins, FUNCTION_SCOPE_DEPTH);
11934 if (ins->id & TRIPLE_FLAG_FLATTENED) {
11935 error(state, 0, "label %s already defined", ident->name);
11937 flatten(state, first, ins);
11939 eat(state, TOK_COLON);
11940 statement(state, first);
11943 static void switch_statement(struct compile_state *state, struct triple *first)
11945 struct triple *value, *top, *end, *dbranch;
11946 struct hash_entry *ident;
11948 /* See if we have a valid switch statement */
11949 eat(state, TOK_SWITCH);
11950 eat(state, TOK_LPAREN);
11951 value = expr(state);
11952 integral(state, value);
11953 value = read_expr(state, value);
11954 eat(state, TOK_RPAREN);
11955 /* Generate the needed pieces */
11956 top = label(state);
11957 end = label(state);
11958 dbranch = branch(state, end, 0);
11959 /* Remember where case branches and break goes */
11960 start_scope(state);
11961 ident = state->i_switch;
11962 symbol(state, ident, &ident->sym_ident, value, value->type);
11963 ident = state->i_case;
11964 symbol(state, ident, &ident->sym_ident, top, top->type);
11965 ident = state->i_break;
11966 symbol(state, ident, &ident->sym_ident, end, end->type);
11967 ident = state->i_default;
11968 symbol(state, ident, &ident->sym_ident, dbranch, dbranch->type);
11969 /* Thread them together */
11970 flatten(state, first, value);
11971 flatten(state, first, top);
11972 flatten(state, first, dbranch);
11973 statement(state, first);
11974 flatten(state, first, end);
11975 /* Cleanup the switch scope */
11976 end_scope(state);
11979 static void case_statement(struct compile_state *state, struct triple *first)
11981 struct triple *cvalue, *dest, *test, *jmp;
11982 struct triple *ptr, *value, *top, *dbranch;
11984 /* See if w have a valid case statement */
11985 eat(state, TOK_CASE);
11986 cvalue = constant_expr(state);
11987 integral(state, cvalue);
11988 if (cvalue->op != OP_INTCONST) {
11989 error(state, 0, "integer constant expected");
11991 eat(state, TOK_COLON);
11992 if (!state->i_case->sym_ident) {
11993 error(state, 0, "case statement not within a switch");
11996 /* Lookup the interesting pieces */
11997 top = state->i_case->sym_ident->def;
11998 value = state->i_switch->sym_ident->def;
11999 dbranch = state->i_default->sym_ident->def;
12001 /* See if this case label has already been used */
12002 for(ptr = top; ptr != dbranch; ptr = ptr->next) {
12003 if (ptr->op != OP_EQ) {
12004 continue;
12006 if (RHS(ptr, 1)->u.cval == cvalue->u.cval) {
12007 error(state, 0, "duplicate case %d statement",
12008 cvalue->u.cval);
12011 /* Generate the needed pieces */
12012 dest = label(state);
12013 test = triple(state, OP_EQ, &int_type, value, cvalue);
12014 jmp = branch(state, dest, test);
12015 /* Thread the pieces together */
12016 flatten(state, dbranch, test);
12017 flatten(state, dbranch, jmp);
12018 flatten(state, dbranch, label(state));
12019 flatten(state, first, dest);
12020 statement(state, first);
12023 static void default_statement(struct compile_state *state, struct triple *first)
12025 struct triple *dest;
12026 struct triple *dbranch, *end;
12028 /* See if we have a valid default statement */
12029 eat(state, TOK_DEFAULT);
12030 eat(state, TOK_COLON);
12032 if (!state->i_case->sym_ident) {
12033 error(state, 0, "default statement not within a switch");
12036 /* Lookup the interesting pieces */
12037 dbranch = state->i_default->sym_ident->def;
12038 end = state->i_break->sym_ident->def;
12040 /* See if a default statement has already happened */
12041 if (TARG(dbranch, 0) != end) {
12042 error(state, 0, "duplicate default statement");
12045 /* Generate the needed pieces */
12046 dest = label(state);
12048 /* Blame the branch on the default statement */
12049 put_occurrence(dbranch->occurrence);
12050 dbranch->occurrence = new_occurrence(state);
12052 /* Thread the pieces together */
12053 TARG(dbranch, 0) = dest;
12054 use_triple(dest, dbranch);
12055 flatten(state, first, dest);
12056 statement(state, first);
12059 static void asm_statement(struct compile_state *state, struct triple *first)
12061 struct asm_info *info;
12062 struct {
12063 struct triple *constraint;
12064 struct triple *expr;
12065 } out_param[MAX_LHS], in_param[MAX_RHS], clob_param[MAX_LHS];
12066 struct triple *def, *asm_str;
12067 int out, in, clobbers, more, colons, i;
12068 int flags;
12070 flags = 0;
12071 eat(state, TOK_ASM);
12072 /* For now ignore the qualifiers */
12073 switch(peek(state)) {
12074 case TOK_CONST:
12075 eat(state, TOK_CONST);
12076 break;
12077 case TOK_VOLATILE:
12078 eat(state, TOK_VOLATILE);
12079 flags |= TRIPLE_FLAG_VOLATILE;
12080 break;
12082 eat(state, TOK_LPAREN);
12083 asm_str = string_constant(state);
12085 colons = 0;
12086 out = in = clobbers = 0;
12087 /* Outputs */
12088 if ((colons == 0) && (peek(state) == TOK_COLON)) {
12089 eat(state, TOK_COLON);
12090 colons++;
12091 more = (peek(state) == TOK_LIT_STRING);
12092 while(more) {
12093 struct triple *var;
12094 struct triple *constraint;
12095 char *str;
12096 more = 0;
12097 if (out > MAX_LHS) {
12098 error(state, 0, "Maximum output count exceeded.");
12100 constraint = string_constant(state);
12101 str = constraint->u.blob;
12102 if (str[0] != '=') {
12103 error(state, 0, "Output constraint does not start with =");
12105 constraint->u.blob = str + 1;
12106 eat(state, TOK_LPAREN);
12107 var = conditional_expr(state);
12108 eat(state, TOK_RPAREN);
12110 lvalue(state, var);
12111 out_param[out].constraint = constraint;
12112 out_param[out].expr = var;
12113 if (peek(state) == TOK_COMMA) {
12114 eat(state, TOK_COMMA);
12115 more = 1;
12117 out++;
12120 /* Inputs */
12121 if ((colons == 1) && (peek(state) == TOK_COLON)) {
12122 eat(state, TOK_COLON);
12123 colons++;
12124 more = (peek(state) == TOK_LIT_STRING);
12125 while(more) {
12126 struct triple *val;
12127 struct triple *constraint;
12128 char *str;
12129 more = 0;
12130 if (in > MAX_RHS) {
12131 error(state, 0, "Maximum input count exceeded.");
12133 constraint = string_constant(state);
12134 str = constraint->u.blob;
12135 if (digitp(str[0] && str[1] == '\0')) {
12136 int val;
12137 val = digval(str[0]);
12138 if ((val < 0) || (val >= out)) {
12139 error(state, 0, "Invalid input constraint %d", val);
12142 eat(state, TOK_LPAREN);
12143 val = conditional_expr(state);
12144 eat(state, TOK_RPAREN);
12146 in_param[in].constraint = constraint;
12147 in_param[in].expr = val;
12148 if (peek(state) == TOK_COMMA) {
12149 eat(state, TOK_COMMA);
12150 more = 1;
12152 in++;
12156 /* Clobber */
12157 if ((colons == 2) && (peek(state) == TOK_COLON)) {
12158 eat(state, TOK_COLON);
12159 colons++;
12160 more = (peek(state) == TOK_LIT_STRING);
12161 while(more) {
12162 struct triple *clobber;
12163 more = 0;
12164 if ((clobbers + out) > MAX_LHS) {
12165 error(state, 0, "Maximum clobber limit exceeded.");
12167 clobber = string_constant(state);
12169 clob_param[clobbers].constraint = clobber;
12170 if (peek(state) == TOK_COMMA) {
12171 eat(state, TOK_COMMA);
12172 more = 1;
12174 clobbers++;
12177 eat(state, TOK_RPAREN);
12178 eat(state, TOK_SEMI);
12181 info = xcmalloc(sizeof(*info), "asm_info");
12182 info->str = asm_str->u.blob;
12183 free_triple(state, asm_str);
12185 def = new_triple(state, OP_ASM, &void_type, clobbers + out, in);
12186 def->u.ainfo = info;
12187 def->id |= flags;
12189 /* Find the register constraints */
12190 for(i = 0; i < out; i++) {
12191 struct triple *constraint;
12192 constraint = out_param[i].constraint;
12193 info->tmpl.lhs[i] = arch_reg_constraint(state,
12194 out_param[i].expr->type, constraint->u.blob);
12195 free_triple(state, constraint);
12197 for(; i - out < clobbers; i++) {
12198 struct triple *constraint;
12199 constraint = clob_param[i - out].constraint;
12200 info->tmpl.lhs[i] = arch_reg_clobber(state, constraint->u.blob);
12201 free_triple(state, constraint);
12203 for(i = 0; i < in; i++) {
12204 struct triple *constraint;
12205 const char *str;
12206 constraint = in_param[i].constraint;
12207 str = constraint->u.blob;
12208 if (digitp(str[0]) && str[1] == '\0') {
12209 struct reg_info cinfo;
12210 int val;
12211 val = digval(str[0]);
12212 cinfo.reg = info->tmpl.lhs[val].reg;
12213 cinfo.regcm = arch_type_to_regcm(state, in_param[i].expr->type);
12214 cinfo.regcm &= info->tmpl.lhs[val].regcm;
12215 if (cinfo.reg == REG_UNSET) {
12216 cinfo.reg = REG_VIRT0 + val;
12218 if (cinfo.regcm == 0) {
12219 error(state, 0, "No registers for %d", val);
12221 info->tmpl.lhs[val] = cinfo;
12222 info->tmpl.rhs[i] = cinfo;
12224 } else {
12225 info->tmpl.rhs[i] = arch_reg_constraint(state,
12226 in_param[i].expr->type, str);
12228 free_triple(state, constraint);
12231 /* Now build the helper expressions */
12232 for(i = 0; i < in; i++) {
12233 RHS(def, i) = read_expr(state, in_param[i].expr);
12235 flatten(state, first, def);
12236 for(i = 0; i < (out + clobbers); i++) {
12237 struct type *type;
12238 struct triple *piece;
12239 if (i < out) {
12240 type = out_param[i].expr->type;
12241 } else {
12242 size_t size = arch_reg_size(info->tmpl.lhs[i].reg);
12243 if (size >= SIZEOF_LONG) {
12244 type = &ulong_type;
12246 else if (size >= SIZEOF_INT) {
12247 type = &uint_type;
12249 else if (size >= SIZEOF_SHORT) {
12250 type = &ushort_type;
12252 else {
12253 type = &uchar_type;
12256 piece = triple(state, OP_PIECE, type, def, 0);
12257 piece->u.cval = i;
12258 LHS(def, i) = piece;
12259 flatten(state, first, piece);
12261 /* And write the helpers to their destinations */
12262 for(i = 0; i < out; i++) {
12263 struct triple *piece;
12264 piece = LHS(def, i);
12265 flatten(state, first,
12266 write_expr(state, out_param[i].expr, piece));
12271 static int isdecl(int tok)
12273 switch(tok) {
12274 case TOK_AUTO:
12275 case TOK_REGISTER:
12276 case TOK_STATIC:
12277 case TOK_EXTERN:
12278 case TOK_TYPEDEF:
12279 case TOK_CONST:
12280 case TOK_RESTRICT:
12281 case TOK_VOLATILE:
12282 case TOK_VOID:
12283 case TOK_CHAR:
12284 case TOK_SHORT:
12285 case TOK_INT:
12286 case TOK_LONG:
12287 case TOK_FLOAT:
12288 case TOK_DOUBLE:
12289 case TOK_SIGNED:
12290 case TOK_UNSIGNED:
12291 case TOK_STRUCT:
12292 case TOK_UNION:
12293 case TOK_ENUM:
12294 case TOK_TYPE_NAME: /* typedef name */
12295 return 1;
12296 default:
12297 return 0;
12301 static void compound_statement(struct compile_state *state, struct triple *first)
12303 eat(state, TOK_LBRACE);
12304 start_scope(state);
12306 /* statement-list opt */
12307 while (peek(state) != TOK_RBRACE) {
12308 statement(state, first);
12310 end_scope(state);
12311 eat(state, TOK_RBRACE);
12314 static void statement(struct compile_state *state, struct triple *first)
12316 int tok;
12317 tok = peek(state);
12318 if (tok == TOK_LBRACE) {
12319 compound_statement(state, first);
12321 else if (tok == TOK_IF) {
12322 if_statement(state, first);
12324 else if (tok == TOK_FOR) {
12325 for_statement(state, first);
12327 else if (tok == TOK_WHILE) {
12328 while_statement(state, first);
12330 else if (tok == TOK_DO) {
12331 do_statement(state, first);
12333 else if (tok == TOK_RETURN) {
12334 return_statement(state, first);
12336 else if (tok == TOK_BREAK) {
12337 break_statement(state, first);
12339 else if (tok == TOK_CONTINUE) {
12340 continue_statement(state, first);
12342 else if (tok == TOK_GOTO) {
12343 goto_statement(state, first);
12345 else if (tok == TOK_SWITCH) {
12346 switch_statement(state, first);
12348 else if (tok == TOK_ASM) {
12349 asm_statement(state, first);
12351 else if ((tok == TOK_IDENT) && (peek2(state) == TOK_COLON)) {
12352 labeled_statement(state, first);
12354 else if (tok == TOK_CASE) {
12355 case_statement(state, first);
12357 else if (tok == TOK_DEFAULT) {
12358 default_statement(state, first);
12360 else if (isdecl(tok)) {
12361 /* This handles C99 intermixing of statements and decls */
12362 decl(state, first);
12364 else {
12365 expr_statement(state, first);
12369 static struct type *param_decl(struct compile_state *state)
12371 struct type *type;
12372 struct hash_entry *ident;
12373 /* Cheat so the declarator will know we are not global */
12374 start_scope(state);
12375 ident = 0;
12376 type = decl_specifiers(state);
12377 type = declarator(state, type, &ident, 0);
12378 type->field_ident = ident;
12379 end_scope(state);
12380 return type;
12383 static struct type *param_type_list(struct compile_state *state, struct type *type)
12385 struct type *ftype, **next;
12386 ftype = new_type(TYPE_FUNCTION | (type->type & STOR_MASK), type, param_decl(state));
12387 next = &ftype->right;
12388 ftype->elements = 1;
12389 while(peek(state) == TOK_COMMA) {
12390 eat(state, TOK_COMMA);
12391 if (peek(state) == TOK_DOTS) {
12392 eat(state, TOK_DOTS);
12393 error(state, 0, "variadic functions not supported");
12395 else {
12396 *next = new_type(TYPE_PRODUCT, *next, param_decl(state));
12397 next = &((*next)->right);
12398 ftype->elements++;
12401 return ftype;
12404 static struct type *type_name(struct compile_state *state)
12406 struct type *type;
12407 type = specifier_qualifier_list(state);
12408 /* abstract-declarator (may consume no tokens) */
12409 type = declarator(state, type, 0, 0);
12410 return type;
12413 static struct type *direct_declarator(
12414 struct compile_state *state, struct type *type,
12415 struct hash_entry **pident, int need_ident)
12417 struct hash_entry *ident;
12418 struct type *outer;
12419 int op;
12420 outer = 0;
12421 arrays_complete(state, type);
12422 switch(peek(state)) {
12423 case TOK_IDENT:
12424 ident = eat(state, TOK_IDENT)->ident;
12425 if (!ident) {
12426 error(state, 0, "Unexpected identifier found");
12428 /* The name of what we are declaring */
12429 *pident = ident;
12430 break;
12431 case TOK_LPAREN:
12432 eat(state, TOK_LPAREN);
12433 outer = declarator(state, type, pident, need_ident);
12434 eat(state, TOK_RPAREN);
12435 break;
12436 default:
12437 if (need_ident) {
12438 error(state, 0, "Identifier expected");
12440 break;
12442 do {
12443 op = 1;
12444 arrays_complete(state, type);
12445 switch(peek(state)) {
12446 case TOK_LPAREN:
12447 eat(state, TOK_LPAREN);
12448 type = param_type_list(state, type);
12449 eat(state, TOK_RPAREN);
12450 break;
12451 case TOK_LBRACKET:
12453 unsigned int qualifiers;
12454 struct triple *value;
12455 value = 0;
12456 eat(state, TOK_LBRACKET);
12457 if (peek(state) != TOK_RBRACKET) {
12458 value = constant_expr(state);
12459 integral(state, value);
12461 eat(state, TOK_RBRACKET);
12463 qualifiers = type->type & (QUAL_MASK | STOR_MASK);
12464 type = new_type(TYPE_ARRAY | qualifiers, type, 0);
12465 if (value) {
12466 type->elements = value->u.cval;
12467 free_triple(state, value);
12468 } else {
12469 type->elements = ELEMENT_COUNT_UNSPECIFIED;
12470 op = 0;
12473 break;
12474 default:
12475 op = 0;
12476 break;
12478 } while(op);
12479 if (outer) {
12480 struct type *inner;
12481 arrays_complete(state, type);
12482 FINISHME();
12483 for(inner = outer; inner->left; inner = inner->left)
12485 inner->left = type;
12486 type = outer;
12488 return type;
12491 static struct type *declarator(
12492 struct compile_state *state, struct type *type,
12493 struct hash_entry **pident, int need_ident)
12495 while(peek(state) == TOK_STAR) {
12496 eat(state, TOK_STAR);
12497 type = new_type(TYPE_POINTER | (type->type & STOR_MASK), type, 0);
12499 type = direct_declarator(state, type, pident, need_ident);
12500 return type;
12503 static struct type *typedef_name(
12504 struct compile_state *state, unsigned int specifiers)
12506 struct hash_entry *ident;
12507 struct type *type;
12508 ident = eat(state, TOK_TYPE_NAME)->ident;
12509 type = ident->sym_ident->type;
12510 specifiers |= type->type & QUAL_MASK;
12511 if ((specifiers & (STOR_MASK | QUAL_MASK)) !=
12512 (type->type & (STOR_MASK | QUAL_MASK))) {
12513 type = clone_type(specifiers, type);
12515 return type;
12518 static struct type *enum_specifier(
12519 struct compile_state *state, unsigned int spec)
12521 struct hash_entry *ident;
12522 ulong_t base;
12523 int tok;
12524 struct type *enum_type;
12525 enum_type = 0;
12526 ident = 0;
12527 eat(state, TOK_ENUM);
12528 tok = peek(state);
12529 if ((tok == TOK_IDENT) || (tok == TOK_ENUM_CONST) || (tok == TOK_TYPE_NAME)) {
12530 ident = eat(state, tok)->ident;
12532 base = 0;
12533 if (!ident || (peek(state) == TOK_LBRACE)) {
12534 struct type **next;
12535 eat(state, TOK_LBRACE);
12536 enum_type = new_type(TYPE_ENUM | spec, 0, 0);
12537 enum_type->type_ident = ident;
12538 next = &enum_type->right;
12539 do {
12540 struct hash_entry *eident;
12541 struct triple *value;
12542 struct type *entry;
12543 eident = eat(state, TOK_IDENT)->ident;
12544 if (eident->sym_ident) {
12545 error(state, 0, "%s already declared",
12546 eident->name);
12548 eident->tok = TOK_ENUM_CONST;
12549 if (peek(state) == TOK_EQ) {
12550 struct triple *val;
12551 eat(state, TOK_EQ);
12552 val = constant_expr(state);
12553 integral(state, val);
12554 base = val->u.cval;
12556 value = int_const(state, &int_type, base);
12557 symbol(state, eident, &eident->sym_ident, value, &int_type);
12558 entry = new_type(TYPE_LIST, 0, 0);
12559 entry->field_ident = eident;
12560 *next = entry;
12561 next = &entry->right;
12562 base += 1;
12563 if (peek(state) == TOK_COMMA) {
12564 eat(state, TOK_COMMA);
12566 } while(peek(state) != TOK_RBRACE);
12567 eat(state, TOK_RBRACE);
12568 if (ident) {
12569 symbol(state, ident, &ident->sym_tag, 0, enum_type);
12572 if (ident && ident->sym_tag &&
12573 ident->sym_tag->type &&
12574 ((ident->sym_tag->type->type & TYPE_MASK) == TYPE_ENUM)) {
12575 enum_type = clone_type(spec, ident->sym_tag->type);
12577 else if (ident && !enum_type) {
12578 error(state, 0, "enum %s undeclared", ident->name);
12580 return enum_type;
12583 static struct type *struct_declarator(
12584 struct compile_state *state, struct type *type, struct hash_entry **ident)
12586 if (peek(state) != TOK_COLON) {
12587 type = declarator(state, type, ident, 1);
12589 if (peek(state) == TOK_COLON) {
12590 struct triple *value;
12591 eat(state, TOK_COLON);
12592 value = constant_expr(state);
12593 if (value->op != OP_INTCONST) {
12594 error(state, 0, "Invalid constant expression");
12596 if (value->u.cval > size_of(state, type)) {
12597 error(state, 0, "bitfield larger than base type");
12599 if (!TYPE_INTEGER(type->type) || ((type->type & TYPE_MASK) == TYPE_BITFIELD)) {
12600 error(state, 0, "bitfield base not an integer type");
12602 type = new_type(TYPE_BITFIELD, type, 0);
12603 type->elements = value->u.cval;
12604 } else
12605 type = clone_type(0, type);
12607 return type;
12610 static struct type *struct_or_union_specifier(
12611 struct compile_state *state, unsigned int spec)
12613 struct type *struct_type;
12614 struct hash_entry *ident;
12615 unsigned int type_main;
12616 unsigned int type_join;
12617 int tok;
12618 struct_type = 0;
12619 ident = 0;
12620 switch(peek(state)) {
12621 case TOK_STRUCT:
12622 eat(state, TOK_STRUCT);
12623 type_main = TYPE_STRUCT;
12624 type_join = TYPE_PRODUCT;
12625 break;
12626 case TOK_UNION:
12627 eat(state, TOK_UNION);
12628 type_main = TYPE_UNION;
12629 type_join = TYPE_OVERLAP;
12630 break;
12631 default:
12632 eat(state, TOK_STRUCT);
12633 type_main = TYPE_STRUCT;
12634 type_join = TYPE_PRODUCT;
12635 break;
12637 tok = peek(state);
12638 if ((tok == TOK_IDENT) || (tok == TOK_ENUM_CONST) || (tok == TOK_TYPE_NAME)) {
12639 ident = eat(state, tok)->ident;
12641 if (!ident || (peek(state) == TOK_LBRACE)) {
12642 ulong_t elements;
12643 struct type **next;
12644 elements = 0;
12645 eat(state, TOK_LBRACE);
12646 next = &struct_type;
12647 do {
12648 struct type *base_type;
12649 int done;
12650 base_type = specifier_qualifier_list(state);
12651 do {
12652 struct type *type;
12653 struct hash_entry *fident;
12654 done = 1;
12655 type = struct_declarator(state, base_type, &fident);
12656 elements++;
12657 if (peek(state) == TOK_COMMA) {
12658 done = 0;
12659 eat(state, TOK_COMMA);
12661 type->field_ident = fident;
12662 if (*next) {
12663 *next = new_type(type_join, *next, type);
12664 next = &((*next)->right);
12665 } else {
12666 *next = type;
12668 } while(!done);
12669 eat(state, TOK_SEMI);
12670 } while(peek(state) != TOK_RBRACE);
12671 eat(state, TOK_RBRACE);
12672 struct_type = new_type(type_main | spec, struct_type, 0);
12673 struct_type->type_ident = ident;
12674 struct_type->elements = elements;
12675 if (ident) {
12676 symbol(state, ident, &ident->sym_tag, 0, struct_type);
12679 if (ident && ident->sym_tag &&
12680 ident->sym_tag->type &&
12681 ((ident->sym_tag->type->type & TYPE_MASK) == type_main)) {
12682 struct_type = clone_type(spec, ident->sym_tag->type);
12684 else if (ident && !struct_type) {
12685 error(state, 0, "%s %s undeclared",
12686 (type_main == TYPE_STRUCT)?"struct" : "union",
12687 ident->name);
12689 return struct_type;
12692 static unsigned int storage_class_specifier_opt(struct compile_state *state)
12694 unsigned int specifiers;
12695 switch(peek(state)) {
12696 case TOK_AUTO:
12697 eat(state, TOK_AUTO);
12698 specifiers = STOR_AUTO;
12699 break;
12700 case TOK_REGISTER:
12701 eat(state, TOK_REGISTER);
12702 specifiers = STOR_REGISTER;
12703 break;
12704 case TOK_STATIC:
12705 eat(state, TOK_STATIC);
12706 specifiers = STOR_STATIC;
12707 break;
12708 case TOK_EXTERN:
12709 eat(state, TOK_EXTERN);
12710 specifiers = STOR_EXTERN;
12711 break;
12712 case TOK_TYPEDEF:
12713 eat(state, TOK_TYPEDEF);
12714 specifiers = STOR_TYPEDEF;
12715 break;
12716 default:
12717 if (state->scope_depth <= GLOBAL_SCOPE_DEPTH) {
12718 specifiers = STOR_LOCAL;
12720 else {
12721 specifiers = STOR_AUTO;
12724 return specifiers;
12727 static unsigned int function_specifier_opt(struct compile_state *state)
12729 /* Ignore the inline keyword */
12730 unsigned int specifiers;
12731 specifiers = 0;
12732 switch(peek(state)) {
12733 case TOK_INLINE:
12734 eat(state, TOK_INLINE);
12735 specifiers = STOR_INLINE;
12737 return specifiers;
12740 static unsigned int attrib(struct compile_state *state, unsigned int attributes)
12742 int tok = peek(state);
12743 switch(tok) {
12744 case TOK_COMMA:
12745 case TOK_LPAREN:
12746 /* The empty attribute ignore it */
12747 break;
12748 case TOK_IDENT:
12749 case TOK_ENUM_CONST:
12750 case TOK_TYPE_NAME:
12752 struct hash_entry *ident;
12753 ident = eat(state, TOK_IDENT)->ident;
12755 if (ident == state->i_noinline) {
12756 if (attributes & ATTRIB_ALWAYS_INLINE) {
12757 error(state, 0, "both always_inline and noinline attribtes");
12759 attributes |= ATTRIB_NOINLINE;
12761 else if (ident == state->i_always_inline) {
12762 if (attributes & ATTRIB_NOINLINE) {
12763 error(state, 0, "both noinline and always_inline attribtes");
12765 attributes |= ATTRIB_ALWAYS_INLINE;
12767 else if (ident == state->i_noreturn) {
12768 // attribute((noreturn)) does nothing (yet?)
12770 else if (ident == state->i_unused) {
12771 // attribute((unused)) does nothing (yet?)
12773 else if (ident == state->i_packed) {
12774 // attribute((packed)) does nothing (yet?)
12776 else {
12777 error(state, 0, "Unknown attribute:%s", ident->name);
12779 break;
12781 default:
12782 error(state, 0, "Unexpected token: %s\n", tokens[tok]);
12783 break;
12785 return attributes;
12788 static unsigned int attribute_list(struct compile_state *state, unsigned type)
12790 type = attrib(state, type);
12791 while(peek(state) == TOK_COMMA) {
12792 eat(state, TOK_COMMA);
12793 type = attrib(state, type);
12795 return type;
12798 static unsigned int attributes_opt(struct compile_state *state, unsigned type)
12800 if (peek(state) == TOK_ATTRIBUTE) {
12801 eat(state, TOK_ATTRIBUTE);
12802 eat(state, TOK_LPAREN);
12803 eat(state, TOK_LPAREN);
12804 type = attribute_list(state, type);
12805 eat(state, TOK_RPAREN);
12806 eat(state, TOK_RPAREN);
12808 return type;
12811 static unsigned int type_qualifiers(struct compile_state *state)
12813 unsigned int specifiers;
12814 int done;
12815 done = 0;
12816 specifiers = QUAL_NONE;
12817 do {
12818 switch(peek(state)) {
12819 case TOK_CONST:
12820 eat(state, TOK_CONST);
12821 specifiers |= QUAL_CONST;
12822 break;
12823 case TOK_VOLATILE:
12824 eat(state, TOK_VOLATILE);
12825 specifiers |= QUAL_VOLATILE;
12826 break;
12827 case TOK_RESTRICT:
12828 eat(state, TOK_RESTRICT);
12829 specifiers |= QUAL_RESTRICT;
12830 break;
12831 default:
12832 done = 1;
12833 break;
12835 } while(!done);
12836 return specifiers;
12839 static struct type *type_specifier(
12840 struct compile_state *state, unsigned int spec)
12842 struct type *type;
12843 int tok;
12844 type = 0;
12845 switch((tok = peek(state))) {
12846 case TOK_VOID:
12847 eat(state, TOK_VOID);
12848 type = new_type(TYPE_VOID | spec, 0, 0);
12849 break;
12850 case TOK_CHAR:
12851 eat(state, TOK_CHAR);
12852 type = new_type(TYPE_CHAR | spec, 0, 0);
12853 break;
12854 case TOK_SHORT:
12855 eat(state, TOK_SHORT);
12856 if (peek(state) == TOK_INT) {
12857 eat(state, TOK_INT);
12859 type = new_type(TYPE_SHORT | spec, 0, 0);
12860 break;
12861 case TOK_INT:
12862 eat(state, TOK_INT);
12863 type = new_type(TYPE_INT | spec, 0, 0);
12864 break;
12865 case TOK_LONG:
12866 eat(state, TOK_LONG);
12867 switch(peek(state)) {
12868 case TOK_LONG:
12869 eat(state, TOK_LONG);
12870 error(state, 0, "long long not supported");
12871 break;
12872 case TOK_DOUBLE:
12873 eat(state, TOK_DOUBLE);
12874 error(state, 0, "long double not supported");
12875 break;
12876 case TOK_INT:
12877 eat(state, TOK_INT);
12878 type = new_type(TYPE_LONG | spec, 0, 0);
12879 break;
12880 default:
12881 type = new_type(TYPE_LONG | spec, 0, 0);
12882 break;
12884 break;
12885 case TOK_FLOAT:
12886 eat(state, TOK_FLOAT);
12887 error(state, 0, "type float not supported");
12888 break;
12889 case TOK_DOUBLE:
12890 eat(state, TOK_DOUBLE);
12891 error(state, 0, "type double not supported");
12892 break;
12893 case TOK_SIGNED:
12894 eat(state, TOK_SIGNED);
12895 switch(peek(state)) {
12896 case TOK_LONG:
12897 eat(state, TOK_LONG);
12898 switch(peek(state)) {
12899 case TOK_LONG:
12900 eat(state, TOK_LONG);
12901 error(state, 0, "type long long not supported");
12902 break;
12903 case TOK_INT:
12904 eat(state, TOK_INT);
12905 type = new_type(TYPE_LONG | spec, 0, 0);
12906 break;
12907 default:
12908 type = new_type(TYPE_LONG | spec, 0, 0);
12909 break;
12911 break;
12912 case TOK_INT:
12913 eat(state, TOK_INT);
12914 type = new_type(TYPE_INT | spec, 0, 0);
12915 break;
12916 case TOK_SHORT:
12917 eat(state, TOK_SHORT);
12918 type = new_type(TYPE_SHORT | spec, 0, 0);
12919 break;
12920 case TOK_CHAR:
12921 eat(state, TOK_CHAR);
12922 type = new_type(TYPE_CHAR | spec, 0, 0);
12923 break;
12924 default:
12925 type = new_type(TYPE_INT | spec, 0, 0);
12926 break;
12928 break;
12929 case TOK_UNSIGNED:
12930 eat(state, TOK_UNSIGNED);
12931 switch(peek(state)) {
12932 case TOK_LONG:
12933 eat(state, TOK_LONG);
12934 switch(peek(state)) {
12935 case TOK_LONG:
12936 eat(state, TOK_LONG);
12937 error(state, 0, "unsigned long long not supported");
12938 break;
12939 case TOK_INT:
12940 eat(state, TOK_INT);
12941 type = new_type(TYPE_ULONG | spec, 0, 0);
12942 break;
12943 default:
12944 type = new_type(TYPE_ULONG | spec, 0, 0);
12945 break;
12947 break;
12948 case TOK_INT:
12949 eat(state, TOK_INT);
12950 type = new_type(TYPE_UINT | spec, 0, 0);
12951 break;
12952 case TOK_SHORT:
12953 eat(state, TOK_SHORT);
12954 type = new_type(TYPE_USHORT | spec, 0, 0);
12955 break;
12956 case TOK_CHAR:
12957 eat(state, TOK_CHAR);
12958 type = new_type(TYPE_UCHAR | spec, 0, 0);
12959 break;
12960 default:
12961 type = new_type(TYPE_UINT | spec, 0, 0);
12962 break;
12964 break;
12965 /* struct or union specifier */
12966 case TOK_STRUCT:
12967 case TOK_UNION:
12968 type = struct_or_union_specifier(state, spec);
12969 break;
12970 /* enum-spefifier */
12971 case TOK_ENUM:
12972 type = enum_specifier(state, spec);
12973 break;
12974 /* typedef name */
12975 case TOK_TYPE_NAME:
12976 type = typedef_name(state, spec);
12977 break;
12978 default:
12979 error(state, 0, "bad type specifier %s",
12980 tokens[tok]);
12981 break;
12983 return type;
12986 static int istype(int tok)
12988 switch(tok) {
12989 case TOK_CONST:
12990 case TOK_RESTRICT:
12991 case TOK_VOLATILE:
12992 case TOK_VOID:
12993 case TOK_CHAR:
12994 case TOK_SHORT:
12995 case TOK_INT:
12996 case TOK_LONG:
12997 case TOK_FLOAT:
12998 case TOK_DOUBLE:
12999 case TOK_SIGNED:
13000 case TOK_UNSIGNED:
13001 case TOK_STRUCT:
13002 case TOK_UNION:
13003 case TOK_ENUM:
13004 case TOK_TYPE_NAME:
13005 return 1;
13006 default:
13007 return 0;
13012 static struct type *specifier_qualifier_list(struct compile_state *state)
13014 struct type *type;
13015 unsigned int specifiers = 0;
13017 /* type qualifiers */
13018 specifiers |= type_qualifiers(state);
13020 /* type specifier */
13021 type = type_specifier(state, specifiers);
13023 return type;
13026 #if DEBUG_ROMCC_WARNING
13027 static int isdecl_specifier(int tok)
13029 switch(tok) {
13030 /* storage class specifier */
13031 case TOK_AUTO:
13032 case TOK_REGISTER:
13033 case TOK_STATIC:
13034 case TOK_EXTERN:
13035 case TOK_TYPEDEF:
13036 /* type qualifier */
13037 case TOK_CONST:
13038 case TOK_RESTRICT:
13039 case TOK_VOLATILE:
13040 /* type specifiers */
13041 case TOK_VOID:
13042 case TOK_CHAR:
13043 case TOK_SHORT:
13044 case TOK_INT:
13045 case TOK_LONG:
13046 case TOK_FLOAT:
13047 case TOK_DOUBLE:
13048 case TOK_SIGNED:
13049 case TOK_UNSIGNED:
13050 /* struct or union specifier */
13051 case TOK_STRUCT:
13052 case TOK_UNION:
13053 /* enum-spefifier */
13054 case TOK_ENUM:
13055 /* typedef name */
13056 case TOK_TYPE_NAME:
13057 /* function specifiers */
13058 case TOK_INLINE:
13059 return 1;
13060 default:
13061 return 0;
13064 #endif
13066 static struct type *decl_specifiers(struct compile_state *state)
13068 struct type *type;
13069 unsigned int specifiers;
13070 /* I am overly restrictive in the arragement of specifiers supported.
13071 * C is overly flexible in this department it makes interpreting
13072 * the parse tree difficult.
13074 specifiers = 0;
13076 /* storage class specifier */
13077 specifiers |= storage_class_specifier_opt(state);
13079 /* function-specifier */
13080 specifiers |= function_specifier_opt(state);
13082 /* attributes */
13083 specifiers |= attributes_opt(state, 0);
13085 /* type qualifier */
13086 specifiers |= type_qualifiers(state);
13088 /* type specifier */
13089 type = type_specifier(state, specifiers);
13090 return type;
13093 struct field_info {
13094 struct type *type;
13095 size_t offset;
13098 static struct field_info designator(struct compile_state *state, struct type *type)
13100 int tok;
13101 struct field_info info;
13102 info.offset = ~0U;
13103 info.type = 0;
13104 do {
13105 switch(peek(state)) {
13106 case TOK_LBRACKET:
13108 struct triple *value;
13109 if ((type->type & TYPE_MASK) != TYPE_ARRAY) {
13110 error(state, 0, "Array designator not in array initializer");
13112 eat(state, TOK_LBRACKET);
13113 value = constant_expr(state);
13114 eat(state, TOK_RBRACKET);
13116 info.type = type->left;
13117 info.offset = value->u.cval * size_of(state, info.type);
13118 break;
13120 case TOK_DOT:
13122 struct hash_entry *field;
13123 if (((type->type & TYPE_MASK) != TYPE_STRUCT) &&
13124 ((type->type & TYPE_MASK) != TYPE_UNION))
13126 error(state, 0, "Struct designator not in struct initializer");
13128 eat(state, TOK_DOT);
13129 field = eat(state, TOK_IDENT)->ident;
13130 info.offset = field_offset(state, type, field);
13131 info.type = field_type(state, type, field);
13132 break;
13134 default:
13135 error(state, 0, "Invalid designator");
13137 tok = peek(state);
13138 } while((tok == TOK_LBRACKET) || (tok == TOK_DOT));
13139 eat(state, TOK_EQ);
13140 return info;
13143 static struct triple *initializer(
13144 struct compile_state *state, struct type *type)
13146 struct triple *result;
13147 #if DEBUG_ROMCC_WARNINGS
13148 #warning "FIXME more consistent initializer handling (where should eval_const_expr go?"
13149 #endif
13150 if (peek(state) != TOK_LBRACE) {
13151 result = assignment_expr(state);
13152 if (((type->type & TYPE_MASK) == TYPE_ARRAY) &&
13153 (type->elements == ELEMENT_COUNT_UNSPECIFIED) &&
13154 ((result->type->type & TYPE_MASK) == TYPE_ARRAY) &&
13155 (result->type->elements != ELEMENT_COUNT_UNSPECIFIED) &&
13156 (equiv_types(type->left, result->type->left))) {
13157 type->elements = result->type->elements;
13159 if (is_lvalue(state, result) &&
13160 ((result->type->type & TYPE_MASK) == TYPE_ARRAY) &&
13161 (type->type & TYPE_MASK) != TYPE_ARRAY)
13163 result = lvalue_conversion(state, result);
13165 if (!is_init_compatible(state, type, result->type)) {
13166 error(state, 0, "Incompatible types in initializer");
13168 if (!equiv_types(type, result->type)) {
13169 result = mk_cast_expr(state, type, result);
13172 else {
13173 int comma;
13174 size_t max_offset;
13175 struct field_info info;
13176 void *buf;
13177 if (((type->type & TYPE_MASK) != TYPE_ARRAY) &&
13178 ((type->type & TYPE_MASK) != TYPE_STRUCT)) {
13179 internal_error(state, 0, "unknown initializer type");
13181 info.offset = 0;
13182 info.type = type->left;
13183 if ((type->type & TYPE_MASK) == TYPE_STRUCT) {
13184 info.type = next_field(state, type, 0);
13186 if (type->elements == ELEMENT_COUNT_UNSPECIFIED) {
13187 max_offset = 0;
13188 } else {
13189 max_offset = size_of(state, type);
13191 buf = xcmalloc(bits_to_bytes(max_offset), "initializer");
13192 eat(state, TOK_LBRACE);
13193 do {
13194 struct triple *value;
13195 struct type *value_type;
13196 size_t value_size;
13197 void *dest;
13198 int tok;
13199 comma = 0;
13200 tok = peek(state);
13201 if ((tok == TOK_LBRACKET) || (tok == TOK_DOT)) {
13202 info = designator(state, type);
13204 if ((type->elements != ELEMENT_COUNT_UNSPECIFIED) &&
13205 (info.offset >= max_offset)) {
13206 error(state, 0, "element beyond bounds");
13208 value_type = info.type;
13209 value = eval_const_expr(state, initializer(state, value_type));
13210 value_size = size_of(state, value_type);
13211 if (((type->type & TYPE_MASK) == TYPE_ARRAY) &&
13212 (type->elements == ELEMENT_COUNT_UNSPECIFIED) &&
13213 (max_offset <= info.offset)) {
13214 void *old_buf;
13215 size_t old_size;
13216 old_buf = buf;
13217 old_size = max_offset;
13218 max_offset = info.offset + value_size;
13219 buf = xmalloc(bits_to_bytes(max_offset), "initializer");
13220 memcpy(buf, old_buf, bits_to_bytes(old_size));
13221 xfree(old_buf);
13223 dest = ((char *)buf) + bits_to_bytes(info.offset);
13224 #if DEBUG_INITIALIZER
13225 fprintf(state->errout, "dest = buf + %d max_offset: %d value_size: %d op: %d\n",
13226 dest - buf,
13227 bits_to_bytes(max_offset),
13228 bits_to_bytes(value_size),
13229 value->op);
13230 #endif
13231 if (value->op == OP_BLOBCONST) {
13232 memcpy(dest, value->u.blob, bits_to_bytes(value_size));
13234 else if ((value->op == OP_INTCONST) && (value_size == SIZEOF_I8)) {
13235 #if DEBUG_INITIALIZER
13236 fprintf(state->errout, "byte: %02x\n", value->u.cval & 0xff);
13237 #endif
13238 *((uint8_t *)dest) = value->u.cval & 0xff;
13240 else if ((value->op == OP_INTCONST) && (value_size == SIZEOF_I16)) {
13241 *((uint16_t *)dest) = value->u.cval & 0xffff;
13243 else if ((value->op == OP_INTCONST) && (value_size == SIZEOF_I32)) {
13244 *((uint32_t *)dest) = value->u.cval & 0xffffffff;
13246 else {
13247 internal_error(state, 0, "unhandled constant initializer");
13249 free_triple(state, value);
13250 if (peek(state) == TOK_COMMA) {
13251 eat(state, TOK_COMMA);
13252 comma = 1;
13254 info.offset += value_size;
13255 if ((type->type & TYPE_MASK) == TYPE_STRUCT) {
13256 info.type = next_field(state, type, info.type);
13257 info.offset = field_offset(state, type,
13258 info.type->field_ident);
13260 } while(comma && (peek(state) != TOK_RBRACE));
13261 if ((type->elements == ELEMENT_COUNT_UNSPECIFIED) &&
13262 ((type->type & TYPE_MASK) == TYPE_ARRAY)) {
13263 type->elements = max_offset / size_of(state, type->left);
13265 eat(state, TOK_RBRACE);
13266 result = triple(state, OP_BLOBCONST, type, 0, 0);
13267 result->u.blob = buf;
13269 return result;
13272 static void resolve_branches(struct compile_state *state, struct triple *first)
13274 /* Make a second pass and finish anything outstanding
13275 * with respect to branches. The only outstanding item
13276 * is to see if there are goto to labels that have not
13277 * been defined and to error about them.
13279 int i;
13280 struct triple *ins;
13281 /* Also error on branches that do not use their targets */
13282 ins = first;
13283 do {
13284 if (!triple_is_ret(state, ins)) {
13285 struct triple **expr ;
13286 struct triple_set *set;
13287 expr = triple_targ(state, ins, 0);
13288 for(; expr; expr = triple_targ(state, ins, expr)) {
13289 struct triple *targ;
13290 targ = *expr;
13291 for(set = targ?targ->use:0; set; set = set->next) {
13292 if (set->member == ins) {
13293 break;
13296 if (!set) {
13297 internal_error(state, ins, "targ not used");
13301 ins = ins->next;
13302 } while(ins != first);
13303 /* See if there are goto to labels that have not been defined */
13304 for(i = 0; i < HASH_TABLE_SIZE; i++) {
13305 struct hash_entry *entry;
13306 for(entry = state->hash_table[i]; entry; entry = entry->next) {
13307 struct triple *ins;
13308 if (!entry->sym_label) {
13309 continue;
13311 ins = entry->sym_label->def;
13312 if (!(ins->id & TRIPLE_FLAG_FLATTENED)) {
13313 error(state, ins, "label `%s' used but not defined",
13314 entry->name);
13320 static struct triple *function_definition(
13321 struct compile_state *state, struct type *type)
13323 struct triple *def, *tmp, *first, *end, *retvar, *ret;
13324 struct triple *fname;
13325 struct type *fname_type;
13326 struct hash_entry *ident;
13327 struct type *param, *crtype, *ctype;
13328 int i;
13329 if ((type->type &TYPE_MASK) != TYPE_FUNCTION) {
13330 error(state, 0, "Invalid function header");
13333 /* Verify the function type */
13334 if (((type->right->type & TYPE_MASK) != TYPE_VOID) &&
13335 ((type->right->type & TYPE_MASK) != TYPE_PRODUCT) &&
13336 (type->right->field_ident == 0)) {
13337 error(state, 0, "Invalid function parameters");
13339 param = type->right;
13340 i = 0;
13341 while((param->type & TYPE_MASK) == TYPE_PRODUCT) {
13342 i++;
13343 if (!param->left->field_ident) {
13344 error(state, 0, "No identifier for parameter %d\n", i);
13346 param = param->right;
13348 i++;
13349 if (((param->type & TYPE_MASK) != TYPE_VOID) && !param->field_ident) {
13350 error(state, 0, "No identifier for parameter %d\n", i);
13353 /* Get a list of statements for this function. */
13354 def = triple(state, OP_LIST, type, 0, 0);
13356 /* Start a new scope for the passed parameters */
13357 start_scope(state);
13359 /* Put a label at the very start of a function */
13360 first = label(state);
13361 RHS(def, 0) = first;
13363 /* Put a label at the very end of a function */
13364 end = label(state);
13365 flatten(state, first, end);
13366 /* Remember where return goes */
13367 ident = state->i_return;
13368 symbol(state, ident, &ident->sym_ident, end, end->type);
13370 /* Get the initial closure type */
13371 ctype = new_type(TYPE_JOIN, &void_type, 0);
13372 ctype->elements = 1;
13374 /* Add a variable for the return value */
13375 crtype = new_type(TYPE_TUPLE,
13376 /* Remove all type qualifiers from the return type */
13377 new_type(TYPE_PRODUCT, ctype, clone_type(0, type->left)), 0);
13378 crtype->elements = 2;
13379 flatten(state, end, variable(state, crtype));
13381 /* Allocate a variable for the return address */
13382 retvar = flatten(state, end, variable(state, &void_ptr_type));
13384 /* Add in the return instruction */
13385 ret = triple(state, OP_RET, &void_type, read_expr(state, retvar), 0);
13386 flatten(state, first, ret);
13388 /* Walk through the parameters and create symbol table entries
13389 * for them.
13391 param = type->right;
13392 while((param->type & TYPE_MASK) == TYPE_PRODUCT) {
13393 ident = param->left->field_ident;
13394 tmp = variable(state, param->left);
13395 var_symbol(state, ident, tmp);
13396 flatten(state, end, tmp);
13397 param = param->right;
13399 if ((param->type & TYPE_MASK) != TYPE_VOID) {
13400 /* And don't forget the last parameter */
13401 ident = param->field_ident;
13402 tmp = variable(state, param);
13403 symbol(state, ident, &ident->sym_ident, tmp, tmp->type);
13404 flatten(state, end, tmp);
13407 /* Add the declaration static const char __func__ [] = "func-name" */
13408 fname_type = new_type(TYPE_ARRAY,
13409 clone_type(QUAL_CONST | STOR_STATIC, &char_type), 0);
13410 fname_type->type |= QUAL_CONST | STOR_STATIC;
13411 fname_type->elements = strlen(state->function) + 1;
13413 fname = triple(state, OP_BLOBCONST, fname_type, 0, 0);
13414 fname->u.blob = (void *)state->function;
13415 fname = flatten(state, end, fname);
13417 ident = state->i___func__;
13418 symbol(state, ident, &ident->sym_ident, fname, fname_type);
13420 /* Remember which function I am compiling.
13421 * Also assume the last defined function is the main function.
13423 state->main_function = def;
13425 /* Now get the actual function definition */
13426 compound_statement(state, end);
13428 /* Finish anything unfinished with branches */
13429 resolve_branches(state, first);
13431 /* Remove the parameter scope */
13432 end_scope(state);
13435 /* Remember I have defined a function */
13436 if (!state->functions) {
13437 state->functions = def;
13438 } else {
13439 insert_triple(state, state->functions, def);
13441 if (state->compiler->debug & DEBUG_INLINE) {
13442 FILE *fp = state->dbgout;
13443 fprintf(fp, "\n");
13444 loc(fp, state, 0);
13445 fprintf(fp, "\n__________ %s _________\n", __FUNCTION__);
13446 display_func(state, fp, def);
13447 fprintf(fp, "__________ %s _________ done\n\n", __FUNCTION__);
13450 return def;
13453 static struct triple *do_decl(struct compile_state *state,
13454 struct type *type, struct hash_entry *ident)
13456 struct triple *def;
13457 def = 0;
13458 /* Clean up the storage types used */
13459 switch (type->type & STOR_MASK) {
13460 case STOR_AUTO:
13461 case STOR_STATIC:
13462 /* These are the good types I am aiming for */
13463 break;
13464 case STOR_REGISTER:
13465 type->type &= ~STOR_MASK;
13466 type->type |= STOR_AUTO;
13467 break;
13468 case STOR_LOCAL:
13469 case STOR_EXTERN:
13470 type->type &= ~STOR_MASK;
13471 type->type |= STOR_STATIC;
13472 break;
13473 case STOR_TYPEDEF:
13474 if (!ident) {
13475 error(state, 0, "typedef without name");
13477 symbol(state, ident, &ident->sym_ident, 0, type);
13478 ident->tok = TOK_TYPE_NAME;
13479 return 0;
13480 break;
13481 default:
13482 internal_error(state, 0, "Undefined storage class");
13484 if ((type->type & TYPE_MASK) == TYPE_FUNCTION) {
13485 // ignore function prototypes
13486 return def;
13488 if (ident &&
13489 ((type->type & TYPE_MASK) == TYPE_ARRAY) &&
13490 ((type->type & STOR_MASK) != STOR_STATIC))
13491 error(state, 0, "non static arrays not supported");
13492 if (ident &&
13493 ((type->type & STOR_MASK) == STOR_STATIC) &&
13494 ((type->type & QUAL_CONST) == 0)) {
13495 error(state, 0, "non const static variables not supported");
13497 if (ident) {
13498 def = variable(state, type);
13499 var_symbol(state, ident, def);
13501 return def;
13504 static void decl(struct compile_state *state, struct triple *first)
13506 struct type *base_type, *type;
13507 struct hash_entry *ident;
13508 struct triple *def;
13509 int global;
13510 global = (state->scope_depth <= GLOBAL_SCOPE_DEPTH);
13511 base_type = decl_specifiers(state);
13512 ident = 0;
13513 type = declarator(state, base_type, &ident, 0);
13514 type->type = attributes_opt(state, type->type);
13515 if (global && ident && (peek(state) == TOK_LBRACE)) {
13516 /* function */
13517 type->type_ident = ident;
13518 state->function = ident->name;
13519 def = function_definition(state, type);
13520 symbol(state, ident, &ident->sym_ident, def, type);
13521 state->function = 0;
13523 else {
13524 int done;
13525 flatten(state, first, do_decl(state, type, ident));
13526 /* type or variable definition */
13527 do {
13528 done = 1;
13529 if (peek(state) == TOK_EQ) {
13530 if (!ident) {
13531 error(state, 0, "cannot assign to a type");
13533 eat(state, TOK_EQ);
13534 flatten(state, first,
13535 init_expr(state,
13536 ident->sym_ident->def,
13537 initializer(state, type)));
13539 arrays_complete(state, type);
13540 if (peek(state) == TOK_COMMA) {
13541 eat(state, TOK_COMMA);
13542 ident = 0;
13543 type = declarator(state, base_type, &ident, 0);
13544 flatten(state, first, do_decl(state, type, ident));
13545 done = 0;
13547 } while(!done);
13548 eat(state, TOK_SEMI);
13552 static void decls(struct compile_state *state)
13554 struct triple *list;
13555 int tok;
13556 list = label(state);
13557 while(1) {
13558 tok = peek(state);
13559 if (tok == TOK_EOF) {
13560 return;
13562 if (tok == TOK_SPACE) {
13563 eat(state, TOK_SPACE);
13565 decl(state, list);
13566 if (list->next != list) {
13567 error(state, 0, "global variables not supported");
13573 * Function inlining
13575 struct triple_reg_set {
13576 struct triple_reg_set *next;
13577 struct triple *member;
13578 struct triple *new;
13580 struct reg_block {
13581 struct block *block;
13582 struct triple_reg_set *in;
13583 struct triple_reg_set *out;
13584 int vertex;
13586 static void setup_basic_blocks(struct compile_state *, struct basic_blocks *bb);
13587 static void analyze_basic_blocks(struct compile_state *state, struct basic_blocks *bb);
13588 static void free_basic_blocks(struct compile_state *, struct basic_blocks *bb);
13589 static int tdominates(struct compile_state *state, struct triple *dom, struct triple *sub);
13590 static void walk_blocks(struct compile_state *state, struct basic_blocks *bb,
13591 void (*cb)(struct compile_state *state, struct block *block, void *arg),
13592 void *arg);
13593 static void print_block(
13594 struct compile_state *state, struct block *block, void *arg);
13595 static int do_triple_set(struct triple_reg_set **head,
13596 struct triple *member, struct triple *new_member);
13597 static void do_triple_unset(struct triple_reg_set **head, struct triple *member);
13598 static struct reg_block *compute_variable_lifetimes(
13599 struct compile_state *state, struct basic_blocks *bb);
13600 static void free_variable_lifetimes(struct compile_state *state,
13601 struct basic_blocks *bb, struct reg_block *blocks);
13602 #if DEBUG_EXPLICIT_CLOSURES
13603 static void print_live_variables(struct compile_state *state,
13604 struct basic_blocks *bb, struct reg_block *rb, FILE *fp);
13605 #endif
13608 static struct triple *call(struct compile_state *state,
13609 struct triple *retvar, struct triple *ret_addr,
13610 struct triple *targ, struct triple *ret)
13612 struct triple *call;
13614 if (!retvar || !is_lvalue(state, retvar)) {
13615 internal_error(state, 0, "writing to a non lvalue?");
13617 write_compatible(state, retvar->type, &void_ptr_type);
13619 call = new_triple(state, OP_CALL, &void_type, 1, 0);
13620 TARG(call, 0) = targ;
13621 MISC(call, 0) = ret;
13622 if (!targ || (targ->op != OP_LABEL)) {
13623 internal_error(state, 0, "call not to a label");
13625 if (!ret || (ret->op != OP_RET)) {
13626 internal_error(state, 0, "call not matched with return");
13628 return call;
13631 static void walk_functions(struct compile_state *state,
13632 void (*cb)(struct compile_state *state, struct triple *func, void *arg),
13633 void *arg)
13635 struct triple *func, *first;
13636 func = first = state->functions;
13637 do {
13638 cb(state, func, arg);
13639 func = func->next;
13640 } while(func != first);
13643 static void reverse_walk_functions(struct compile_state *state,
13644 void (*cb)(struct compile_state *state, struct triple *func, void *arg),
13645 void *arg)
13647 struct triple *func, *first;
13648 func = first = state->functions;
13649 do {
13650 func = func->prev;
13651 cb(state, func, arg);
13652 } while(func != first);
13656 static void mark_live(struct compile_state *state, struct triple *func, void *arg)
13658 struct triple *ptr, *first;
13659 if (func->u.cval == 0) {
13660 return;
13662 ptr = first = RHS(func, 0);
13663 do {
13664 if (ptr->op == OP_FCALL) {
13665 struct triple *called_func;
13666 called_func = MISC(ptr, 0);
13667 /* Mark the called function as used */
13668 if (!(func->id & TRIPLE_FLAG_FLATTENED)) {
13669 called_func->u.cval++;
13671 /* Remove the called function from the list */
13672 called_func->prev->next = called_func->next;
13673 called_func->next->prev = called_func->prev;
13675 /* Place the called function before me on the list */
13676 called_func->next = func;
13677 called_func->prev = func->prev;
13678 called_func->prev->next = called_func;
13679 called_func->next->prev = called_func;
13681 ptr = ptr->next;
13682 } while(ptr != first);
13683 func->id |= TRIPLE_FLAG_FLATTENED;
13686 static void mark_live_functions(struct compile_state *state)
13688 /* Ensure state->main_function is the last function in
13689 * the list of functions.
13691 if ((state->main_function->next != state->functions) ||
13692 (state->functions->prev != state->main_function)) {
13693 internal_error(state, 0,
13694 "state->main_function is not at the end of the function list ");
13696 state->main_function->u.cval = 1;
13697 reverse_walk_functions(state, mark_live, 0);
13700 static int local_triple(struct compile_state *state,
13701 struct triple *func, struct triple *ins)
13703 int local = (ins->id & TRIPLE_FLAG_LOCAL);
13704 #if 0
13705 if (!local) {
13706 FILE *fp = state->errout;
13707 fprintf(fp, "global: ");
13708 display_triple(fp, ins);
13710 #endif
13711 return local;
13714 struct triple *copy_func(struct compile_state *state, struct triple *ofunc,
13715 struct occurrence *base_occurrence)
13717 struct triple *nfunc;
13718 struct triple *nfirst, *ofirst;
13719 struct triple *new, *old;
13721 if (state->compiler->debug & DEBUG_INLINE) {
13722 FILE *fp = state->dbgout;
13723 fprintf(fp, "\n");
13724 loc(fp, state, 0);
13725 fprintf(fp, "\n__________ %s _________\n", __FUNCTION__);
13726 display_func(state, fp, ofunc);
13727 fprintf(fp, "__________ %s _________ done\n\n", __FUNCTION__);
13730 /* Make a new copy of the old function */
13731 nfunc = triple(state, OP_LIST, ofunc->type, 0, 0);
13732 nfirst = 0;
13733 ofirst = old = RHS(ofunc, 0);
13734 do {
13735 struct triple *new;
13736 struct occurrence *occurrence;
13737 int old_lhs, old_rhs;
13738 old_lhs = old->lhs;
13739 old_rhs = old->rhs;
13740 occurrence = inline_occurrence(state, base_occurrence, old->occurrence);
13741 if (ofunc->u.cval && (old->op == OP_FCALL)) {
13742 MISC(old, 0)->u.cval += 1;
13744 new = alloc_triple(state, old->op, old->type, old_lhs, old_rhs,
13745 occurrence);
13746 if (!triple_stores_block(state, new)) {
13747 memcpy(&new->u, &old->u, sizeof(new->u));
13749 if (!nfirst) {
13750 RHS(nfunc, 0) = nfirst = new;
13752 else {
13753 insert_triple(state, nfirst, new);
13755 new->id |= TRIPLE_FLAG_FLATTENED;
13756 new->id |= old->id & TRIPLE_FLAG_COPY;
13758 /* During the copy remember new as user of old */
13759 use_triple(old, new);
13761 /* Remember which instructions are local */
13762 old->id |= TRIPLE_FLAG_LOCAL;
13763 old = old->next;
13764 } while(old != ofirst);
13766 /* Make a second pass to fix up any unresolved references */
13767 old = ofirst;
13768 new = nfirst;
13769 do {
13770 struct triple **oexpr, **nexpr;
13771 int count, i;
13772 /* Lookup where the copy is, to join pointers */
13773 count = TRIPLE_SIZE(old);
13774 for(i = 0; i < count; i++) {
13775 oexpr = &old->param[i];
13776 nexpr = &new->param[i];
13777 if (*oexpr && !*nexpr) {
13778 if (!local_triple(state, ofunc, *oexpr)) {
13779 *nexpr = *oexpr;
13781 else if ((*oexpr)->use) {
13782 *nexpr = (*oexpr)->use->member;
13784 if (*nexpr == old) {
13785 internal_error(state, 0, "new == old?");
13787 use_triple(*nexpr, new);
13789 if (!*nexpr && *oexpr) {
13790 internal_error(state, 0, "Could not copy %d", i);
13793 old = old->next;
13794 new = new->next;
13795 } while((old != ofirst) && (new != nfirst));
13797 /* Make a third pass to cleanup the extra useses */
13798 old = ofirst;
13799 new = nfirst;
13800 do {
13801 unuse_triple(old, new);
13802 /* Forget which instructions are local */
13803 old->id &= ~TRIPLE_FLAG_LOCAL;
13804 old = old->next;
13805 new = new->next;
13806 } while ((old != ofirst) && (new != nfirst));
13807 return nfunc;
13810 static void expand_inline_call(
13811 struct compile_state *state, struct triple *me, struct triple *fcall)
13813 /* Inline the function call */
13814 struct type *ptype;
13815 struct triple *ofunc, *nfunc, *nfirst, *result, *retvar, *ins;
13816 struct triple *end, *nend;
13817 int pvals, i;
13819 /* Find the triples */
13820 ofunc = MISC(fcall, 0);
13821 if (ofunc->op != OP_LIST) {
13822 internal_error(state, 0, "improper function");
13824 nfunc = copy_func(state, ofunc, fcall->occurrence);
13825 /* Prepend the parameter reading into the new function list */
13826 ptype = nfunc->type->right;
13827 pvals = fcall->rhs;
13828 for(i = 0; i < pvals; i++) {
13829 struct type *atype;
13830 struct triple *arg, *param;
13831 atype = ptype;
13832 if ((ptype->type & TYPE_MASK) == TYPE_PRODUCT) {
13833 atype = ptype->left;
13835 param = farg(state, nfunc, i);
13836 if ((param->type->type & TYPE_MASK) != (atype->type & TYPE_MASK)) {
13837 internal_error(state, fcall, "param %d type mismatch", i);
13839 arg = RHS(fcall, i);
13840 flatten(state, fcall, write_expr(state, param, arg));
13841 ptype = ptype->right;
13843 result = 0;
13844 if ((nfunc->type->left->type & TYPE_MASK) != TYPE_VOID) {
13845 result = read_expr(state,
13846 deref_index(state, fresult(state, nfunc), 1));
13848 if (state->compiler->debug & DEBUG_INLINE) {
13849 FILE *fp = state->dbgout;
13850 fprintf(fp, "\n");
13851 loc(fp, state, 0);
13852 fprintf(fp, "\n__________ %s _________\n", __FUNCTION__);
13853 display_func(state, fp, nfunc);
13854 fprintf(fp, "__________ %s _________ done\n\n", __FUNCTION__);
13858 * Get rid of the extra triples
13860 /* Remove the read of the return address */
13861 ins = RHS(nfunc, 0)->prev->prev;
13862 if ((ins->op != OP_READ) || (RHS(ins, 0) != fretaddr(state, nfunc))) {
13863 internal_error(state, ins, "Not return address read?");
13865 release_triple(state, ins);
13866 /* Remove the return instruction */
13867 ins = RHS(nfunc, 0)->prev;
13868 if (ins->op != OP_RET) {
13869 internal_error(state, ins, "Not return?");
13871 release_triple(state, ins);
13872 /* Remove the retaddres variable */
13873 retvar = fretaddr(state, nfunc);
13874 if ((retvar->lhs != 1) ||
13875 (retvar->op != OP_ADECL) ||
13876 (retvar->next->op != OP_PIECE) ||
13877 (MISC(retvar->next, 0) != retvar)) {
13878 internal_error(state, retvar, "Not the return address?");
13880 release_triple(state, retvar->next);
13881 release_triple(state, retvar);
13883 /* Remove the label at the start of the function */
13884 ins = RHS(nfunc, 0);
13885 if (ins->op != OP_LABEL) {
13886 internal_error(state, ins, "Not label?");
13888 nfirst = ins->next;
13889 free_triple(state, ins);
13890 /* Release the new function header */
13891 RHS(nfunc, 0) = 0;
13892 free_triple(state, nfunc);
13894 /* Append the new function list onto the return list */
13895 end = fcall->prev;
13896 nend = nfirst->prev;
13897 end->next = nfirst;
13898 nfirst->prev = end;
13899 nend->next = fcall;
13900 fcall->prev = nend;
13902 /* Now the result reading code */
13903 if (result) {
13904 result = flatten(state, fcall, result);
13905 propagate_use(state, fcall, result);
13908 /* Release the original fcall instruction */
13909 release_triple(state, fcall);
13911 return;
13916 * Type of the result variable.
13918 * result
13920 * +----------+------------+
13921 * | |
13922 * union of closures result_type
13924 * +------------------+---------------+
13925 * | |
13926 * closure1 ... closuerN
13927 * | |
13928 * +----+--+-+--------+-----+ +----+----+---+-----+
13929 * | | | | | | | | |
13930 * var1 var2 var3 ... varN result var1 var2 ... varN result
13932 * +--------+---------+
13933 * | |
13934 * union of closures result_type
13936 * +-----+-------------------+
13937 * | |
13938 * closure1 ... closureN
13939 * | |
13940 * +-----+---+----+----+ +----+---+----+-----+
13941 * | | | | | | | |
13942 * var1 var2 ... varN result var1 var2 ... varN result
13945 static int add_closure_type(struct compile_state *state,
13946 struct triple *func, struct type *closure_type)
13948 struct type *type, *ctype, **next;
13949 struct triple *var, *new_var;
13950 int i;
13952 #if 0
13953 FILE *fp = state->errout;
13954 fprintf(fp, "original_type: ");
13955 name_of(fp, fresult(state, func)->type);
13956 fprintf(fp, "\n");
13957 #endif
13958 /* find the original type */
13959 var = fresult(state, func);
13960 type = var->type;
13961 if (type->elements != 2) {
13962 internal_error(state, var, "bad return type");
13965 /* Find the complete closure type and update it */
13966 ctype = type->left->left;
13967 next = &ctype->left;
13968 while(((*next)->type & TYPE_MASK) == TYPE_OVERLAP) {
13969 next = &(*next)->right;
13971 *next = new_type(TYPE_OVERLAP, *next, dup_type(state, closure_type));
13972 ctype->elements += 1;
13974 #if 0
13975 fprintf(fp, "new_type: ");
13976 name_of(fp, type);
13977 fprintf(fp, "\n");
13978 fprintf(fp, "ctype: %p %d bits: %d ",
13979 ctype, ctype->elements, reg_size_of(state, ctype));
13980 name_of(fp, ctype);
13981 fprintf(fp, "\n");
13982 #endif
13984 /* Regenerate the variable with the new type definition */
13985 new_var = pre_triple(state, var, OP_ADECL, type, 0, 0);
13986 new_var->id |= TRIPLE_FLAG_FLATTENED;
13987 for(i = 0; i < new_var->lhs; i++) {
13988 LHS(new_var, i)->id |= TRIPLE_FLAG_FLATTENED;
13991 /* Point everyone at the new variable */
13992 propagate_use(state, var, new_var);
13994 /* Release the original variable */
13995 for(i = 0; i < var->lhs; i++) {
13996 release_triple(state, LHS(var, i));
13998 release_triple(state, var);
14000 /* Return the index of the added closure type */
14001 return ctype->elements - 1;
14004 static struct triple *closure_expr(struct compile_state *state,
14005 struct triple *func, int closure_idx, int var_idx)
14007 return deref_index(state,
14008 deref_index(state,
14009 deref_index(state, fresult(state, func), 0),
14010 closure_idx),
14011 var_idx);
14015 static void insert_triple_set(
14016 struct triple_reg_set **head, struct triple *member)
14018 struct triple_reg_set *new;
14019 new = xcmalloc(sizeof(*new), "triple_set");
14020 new->member = member;
14021 new->new = 0;
14022 new->next = *head;
14023 *head = new;
14026 static int ordered_triple_set(
14027 struct triple_reg_set **head, struct triple *member)
14029 struct triple_reg_set **ptr;
14030 if (!member)
14031 return 0;
14032 ptr = head;
14033 while(*ptr) {
14034 if (member == (*ptr)->member) {
14035 return 0;
14037 /* keep the list ordered */
14038 if (member->id < (*ptr)->member->id) {
14039 break;
14041 ptr = &(*ptr)->next;
14043 insert_triple_set(ptr, member);
14044 return 1;
14048 static void free_closure_variables(struct compile_state *state,
14049 struct triple_reg_set **enclose)
14051 struct triple_reg_set *entry, *next;
14052 for(entry = *enclose; entry; entry = next) {
14053 next = entry->next;
14054 do_triple_unset(enclose, entry->member);
14058 static int lookup_closure_index(struct compile_state *state,
14059 struct triple *me, struct triple *val)
14061 struct triple *first, *ins, *next;
14062 first = RHS(me, 0);
14063 next = first;
14064 do {
14065 struct triple *result;
14066 struct triple *index0, *index1, *index2, *read, *write;
14067 ins = next;
14068 next = ins->next;
14069 if (ins->op != OP_CALL) {
14070 continue;
14072 /* I am at a previous call point examine it closely */
14073 if (ins->next->op != OP_LABEL) {
14074 internal_error(state, ins, "call not followed by label");
14076 /* Does this call does not enclose any variables? */
14077 if ((ins->next->next->op != OP_INDEX) ||
14078 (ins->next->next->u.cval != 0) ||
14079 (result = MISC(ins->next->next, 0)) ||
14080 (result->id & TRIPLE_FLAG_LOCAL)) {
14081 continue;
14083 /* The pattern is:
14084 * 0 index result < 0 >
14085 * 1 index 0 < ? >
14086 * 2 index 1 < ? >
14087 * 3 read 2
14088 * 4 write 3 var
14090 for(index0 = ins->next->next;
14091 (index0->op == OP_INDEX) &&
14092 (MISC(index0, 0) == result) &&
14093 (index0->u.cval == 0) ;
14094 index0 = write->next)
14096 index1 = index0->next;
14097 index2 = index1->next;
14098 read = index2->next;
14099 write = read->next;
14100 if ((index0->op != OP_INDEX) ||
14101 (index1->op != OP_INDEX) ||
14102 (index2->op != OP_INDEX) ||
14103 (read->op != OP_READ) ||
14104 (write->op != OP_WRITE) ||
14105 (MISC(index1, 0) != index0) ||
14106 (MISC(index2, 0) != index1) ||
14107 (RHS(read, 0) != index2) ||
14108 (RHS(write, 0) != read)) {
14109 internal_error(state, index0, "bad var read");
14111 if (MISC(write, 0) == val) {
14112 return index2->u.cval;
14115 } while(next != first);
14116 return -1;
14119 static inline int enclose_triple(struct triple *ins)
14121 return (ins && ((ins->type->type & TYPE_MASK) != TYPE_VOID));
14124 static void compute_closure_variables(struct compile_state *state,
14125 struct triple *me, struct triple *fcall, struct triple_reg_set **enclose)
14127 struct triple_reg_set *set, *vars, **last_var;
14128 struct basic_blocks bb;
14129 struct reg_block *rb;
14130 struct block *block;
14131 struct triple *old_result, *first, *ins;
14132 size_t count, idx;
14133 uint64_t used_indices;
14134 int i, max_index;
14135 #define MAX_INDICES (sizeof(used_indices)*CHAR_BIT)
14136 #define ID_BITS(X) ((X) & (TRIPLE_FLAG_LOCAL -1))
14137 struct {
14138 unsigned id;
14139 int index;
14140 } *info;
14143 /* Find the basic blocks of this function */
14144 bb.func = me;
14145 bb.first = RHS(me, 0);
14146 old_result = 0;
14147 if (!triple_is_ret(state, bb.first->prev)) {
14148 bb.func = 0;
14149 } else {
14150 old_result = fresult(state, me);
14152 analyze_basic_blocks(state, &bb);
14154 /* Find which variables are currently alive in a given block */
14155 rb = compute_variable_lifetimes(state, &bb);
14157 /* Find the variables that are currently alive */
14158 block = block_of_triple(state, fcall);
14159 if (!block || (block->vertex <= 0) || (block->vertex > bb.last_vertex)) {
14160 internal_error(state, fcall, "No reg block? block: %p", block);
14163 #if DEBUG_EXPLICIT_CLOSURES
14164 print_live_variables(state, &bb, rb, state->dbgout);
14165 fflush(state->dbgout);
14166 #endif
14168 /* Count the number of triples in the function */
14169 first = RHS(me, 0);
14170 ins = first;
14171 count = 0;
14172 do {
14173 count++;
14174 ins = ins->next;
14175 } while(ins != first);
14177 /* Allocate some memory to temporary hold the id info */
14178 info = xcmalloc(sizeof(*info) * (count +1), "info");
14180 /* Mark the local function */
14181 first = RHS(me, 0);
14182 ins = first;
14183 idx = 1;
14184 do {
14185 info[idx].id = ins->id;
14186 ins->id = TRIPLE_FLAG_LOCAL | idx;
14187 idx++;
14188 ins = ins->next;
14189 } while(ins != first);
14192 * Build the list of variables to enclose.
14194 * A target it to put the same variable in the
14195 * same slot for ever call of a given function.
14196 * After coloring this removes all of the variable
14197 * manipulation code.
14199 * The list of variables to enclose is built ordered
14200 * program order because except in corner cases this
14201 * gives me the stability of assignment I need.
14203 * To gurantee that stability I lookup the variables
14204 * to see where they have been used before and
14205 * I build my final list with the assigned indices.
14207 vars = 0;
14208 if (enclose_triple(old_result)) {
14209 ordered_triple_set(&vars, old_result);
14211 for(set = rb[block->vertex].out; set; set = set->next) {
14212 if (!enclose_triple(set->member)) {
14213 continue;
14215 if ((set->member == fcall) || (set->member == old_result)) {
14216 continue;
14218 if (!local_triple(state, me, set->member)) {
14219 internal_error(state, set->member, "not local?");
14221 ordered_triple_set(&vars, set->member);
14224 /* Lookup the current indices of the live varialbe */
14225 used_indices = 0;
14226 max_index = -1;
14227 for(set = vars; set ; set = set->next) {
14228 struct triple *ins;
14229 int index;
14230 ins = set->member;
14231 index = lookup_closure_index(state, me, ins);
14232 info[ID_BITS(ins->id)].index = index;
14233 if (index < 0) {
14234 continue;
14236 if (index >= MAX_INDICES) {
14237 internal_error(state, ins, "index unexpectedly large");
14239 if (used_indices & ((uint64_t)1 << index)) {
14240 internal_error(state, ins, "index previously used?");
14242 /* Remember which indices have been used */
14243 used_indices |= ((uint64_t)1 << index);
14244 if (index > max_index) {
14245 max_index = index;
14249 /* Walk through the live variables and make certain
14250 * everything is assigned an index.
14252 for(set = vars; set; set = set->next) {
14253 struct triple *ins;
14254 int index;
14255 ins = set->member;
14256 index = info[ID_BITS(ins->id)].index;
14257 if (index >= 0) {
14258 continue;
14260 /* Find the lowest unused index value */
14261 for(index = 0; index < MAX_INDICES; index++) {
14262 if (!(used_indices & ((uint64_t)1 << index))) {
14263 break;
14266 if (index == MAX_INDICES) {
14267 internal_error(state, ins, "no free indices?");
14269 info[ID_BITS(ins->id)].index = index;
14270 /* Remember which indices have been used */
14271 used_indices |= ((uint64_t)1 << index);
14272 if (index > max_index) {
14273 max_index = index;
14277 /* Build the return list of variables with positions matching
14278 * their indices.
14280 *enclose = 0;
14281 last_var = enclose;
14282 for(i = 0; i <= max_index; i++) {
14283 struct triple *var;
14284 var = 0;
14285 if (used_indices & ((uint64_t)1 << i)) {
14286 for(set = vars; set; set = set->next) {
14287 int index;
14288 index = info[ID_BITS(set->member->id)].index;
14289 if (index == i) {
14290 var = set->member;
14291 break;
14294 if (!var) {
14295 internal_error(state, me, "missing variable");
14298 insert_triple_set(last_var, var);
14299 last_var = &(*last_var)->next;
14302 #if DEBUG_EXPLICIT_CLOSURES
14303 /* Print out the variables to be enclosed */
14304 loc(state->dbgout, state, fcall);
14305 fprintf(state->dbgout, "Alive:\n");
14306 for(set = *enclose; set; set = set->next) {
14307 display_triple(state->dbgout, set->member);
14309 fflush(state->dbgout);
14310 #endif
14312 /* Clear the marks */
14313 ins = first;
14314 do {
14315 ins->id = info[ID_BITS(ins->id)].id;
14316 ins = ins->next;
14317 } while(ins != first);
14319 /* Release the ordered list of live variables */
14320 free_closure_variables(state, &vars);
14322 /* Release the storage of the old ids */
14323 xfree(info);
14325 /* Release the variable lifetime information */
14326 free_variable_lifetimes(state, &bb, rb);
14328 /* Release the basic blocks of this function */
14329 free_basic_blocks(state, &bb);
14332 static void expand_function_call(
14333 struct compile_state *state, struct triple *me, struct triple *fcall)
14335 /* Generate an ordinary function call */
14336 struct type *closure_type, **closure_next;
14337 struct triple *func, *func_first, *func_last, *retvar;
14338 struct triple *first;
14339 struct type *ptype, *rtype;
14340 struct triple *ret_addr, *ret_loc;
14341 struct triple_reg_set *enclose, *set;
14342 int closure_idx, pvals, i;
14344 #if DEBUG_EXPLICIT_CLOSURES
14345 FILE *fp = state->dbgout;
14346 fprintf(fp, "\ndisplay_func(me) ptr: %p\n", fcall);
14347 display_func(state, fp, MISC(fcall, 0));
14348 display_func(state, fp, me);
14349 fprintf(fp, "__________ %s _________ done\n\n", __FUNCTION__);
14350 #endif
14352 /* Find the triples */
14353 func = MISC(fcall, 0);
14354 func_first = RHS(func, 0);
14355 retvar = fretaddr(state, func);
14356 func_last = func_first->prev;
14357 first = fcall->next;
14359 /* Find what I need to enclose */
14360 compute_closure_variables(state, me, fcall, &enclose);
14362 /* Compute the closure type */
14363 closure_type = new_type(TYPE_TUPLE, 0, 0);
14364 closure_type->elements = 0;
14365 closure_next = &closure_type->left;
14366 for(set = enclose; set ; set = set->next) {
14367 struct type *type;
14368 type = &void_type;
14369 if (set->member) {
14370 type = set->member->type;
14372 if (!*closure_next) {
14373 *closure_next = type;
14374 } else {
14375 *closure_next = new_type(TYPE_PRODUCT, *closure_next,
14376 type);
14377 closure_next = &(*closure_next)->right;
14379 closure_type->elements += 1;
14381 if (closure_type->elements == 0) {
14382 closure_type->type = TYPE_VOID;
14386 #if DEBUG_EXPLICIT_CLOSURES
14387 fprintf(state->dbgout, "closure type: ");
14388 name_of(state->dbgout, closure_type);
14389 fprintf(state->dbgout, "\n");
14390 #endif
14392 /* Update the called functions closure variable */
14393 closure_idx = add_closure_type(state, func, closure_type);
14394 free(closure_type);
14395 closure_type = NULL;
14397 /* Generate some needed triples */
14398 ret_loc = label(state);
14399 ret_addr = triple(state, OP_ADDRCONST, &void_ptr_type, ret_loc, 0);
14401 /* Pass the parameters to the new function */
14402 ptype = func->type->right;
14403 pvals = fcall->rhs;
14404 for(i = 0; i < pvals; i++) {
14405 struct type *atype;
14406 struct triple *arg, *param;
14407 atype = ptype;
14408 if ((ptype->type & TYPE_MASK) == TYPE_PRODUCT) {
14409 atype = ptype->left;
14411 param = farg(state, func, i);
14412 if ((param->type->type & TYPE_MASK) != (atype->type & TYPE_MASK)) {
14413 internal_error(state, fcall, "param type mismatch");
14415 arg = RHS(fcall, i);
14416 flatten(state, first, write_expr(state, param, arg));
14417 ptype = ptype->right;
14419 rtype = func->type->left;
14421 /* Thread the triples together */
14422 ret_loc = flatten(state, first, ret_loc);
14424 /* Save the active variables in the result variable */
14425 for(i = 0, set = enclose; set ; set = set->next, i++) {
14426 if (!set->member) {
14427 continue;
14429 flatten(state, ret_loc,
14430 write_expr(state,
14431 closure_expr(state, func, closure_idx, i),
14432 read_expr(state, set->member)));
14435 /* Initialize the return value */
14436 if ((rtype->type & TYPE_MASK) != TYPE_VOID) {
14437 flatten(state, ret_loc,
14438 write_expr(state,
14439 deref_index(state, fresult(state, func), 1),
14440 new_triple(state, OP_UNKNOWNVAL, rtype, 0, 0)));
14443 ret_addr = flatten(state, ret_loc, ret_addr);
14444 flatten(state, ret_loc, write_expr(state, retvar, ret_addr));
14445 flatten(state, ret_loc,
14446 call(state, retvar, ret_addr, func_first, func_last));
14448 /* Find the result */
14449 if ((rtype->type & TYPE_MASK) != TYPE_VOID) {
14450 struct triple * result;
14451 result = flatten(state, first,
14452 read_expr(state,
14453 deref_index(state, fresult(state, func), 1)));
14455 propagate_use(state, fcall, result);
14458 /* Release the original fcall instruction */
14459 release_triple(state, fcall);
14461 /* Restore the active variables from the result variable */
14462 for(i = 0, set = enclose; set ; set = set->next, i++) {
14463 struct triple_set *use, *next;
14464 struct triple *new;
14465 struct basic_blocks bb;
14466 if (!set->member || (set->member == fcall)) {
14467 continue;
14469 /* Generate an expression for the value */
14470 new = flatten(state, first,
14471 read_expr(state,
14472 closure_expr(state, func, closure_idx, i)));
14475 /* If the original is an lvalue restore the preserved value */
14476 if (is_lvalue(state, set->member)) {
14477 flatten(state, first,
14478 write_expr(state, set->member, new));
14479 continue;
14482 * If the original is a value update the dominated uses.
14485 /* Analyze the basic blocks so I can see who dominates whom */
14486 bb.func = me;
14487 bb.first = RHS(me, 0);
14488 if (!triple_is_ret(state, bb.first->prev)) {
14489 bb.func = 0;
14491 analyze_basic_blocks(state, &bb);
14494 #if DEBUG_EXPLICIT_CLOSURES
14495 fprintf(state->errout, "Updating domindated uses: %p -> %p\n",
14496 set->member, new);
14497 #endif
14498 /* If fcall dominates the use update the expression */
14499 for(use = set->member->use; use; use = next) {
14500 /* Replace use modifies the use chain and
14501 * removes use, so I must take a copy of the
14502 * next entry early.
14504 next = use->next;
14505 if (!tdominates(state, fcall, use->member)) {
14506 continue;
14508 replace_use(state, set->member, new, use->member);
14511 /* Release the basic blocks, the instructions will be
14512 * different next time, and flatten/insert_triple does
14513 * not update the block values so I can't cache the analysis.
14515 free_basic_blocks(state, &bb);
14518 /* Release the closure variable list */
14519 free_closure_variables(state, &enclose);
14521 if (state->compiler->debug & DEBUG_INLINE) {
14522 FILE *fp = state->dbgout;
14523 fprintf(fp, "\n");
14524 loc(fp, state, 0);
14525 fprintf(fp, "\n__________ %s _________\n", __FUNCTION__);
14526 display_func(state, fp, func);
14527 display_func(state, fp, me);
14528 fprintf(fp, "__________ %s _________ done\n\n", __FUNCTION__);
14531 return;
14534 static int do_inline(struct compile_state *state, struct triple *func)
14536 int do_inline;
14537 int policy;
14539 policy = state->compiler->flags & COMPILER_INLINE_MASK;
14540 switch(policy) {
14541 case COMPILER_INLINE_ALWAYS:
14542 do_inline = 1;
14543 if (func->type->type & ATTRIB_NOINLINE) {
14544 error(state, func, "noinline with always_inline compiler option");
14546 break;
14547 case COMPILER_INLINE_NEVER:
14548 do_inline = 0;
14549 if (func->type->type & ATTRIB_ALWAYS_INLINE) {
14550 error(state, func, "always_inline with noinline compiler option");
14552 break;
14553 case COMPILER_INLINE_DEFAULTON:
14554 switch(func->type->type & STOR_MASK) {
14555 case STOR_STATIC | STOR_INLINE:
14556 case STOR_LOCAL | STOR_INLINE:
14557 case STOR_EXTERN | STOR_INLINE:
14558 do_inline = 1;
14559 break;
14560 default:
14561 do_inline = 1;
14562 break;
14564 break;
14565 case COMPILER_INLINE_DEFAULTOFF:
14566 switch(func->type->type & STOR_MASK) {
14567 case STOR_STATIC | STOR_INLINE:
14568 case STOR_LOCAL | STOR_INLINE:
14569 case STOR_EXTERN | STOR_INLINE:
14570 do_inline = 1;
14571 break;
14572 default:
14573 do_inline = 0;
14574 break;
14576 break;
14577 case COMPILER_INLINE_NOPENALTY:
14578 switch(func->type->type & STOR_MASK) {
14579 case STOR_STATIC | STOR_INLINE:
14580 case STOR_LOCAL | STOR_INLINE:
14581 case STOR_EXTERN | STOR_INLINE:
14582 do_inline = 1;
14583 break;
14584 default:
14585 do_inline = (func->u.cval == 1);
14586 break;
14588 break;
14589 default:
14590 internal_error(state, 0, "Unimplemented inline policy");
14591 break;
14593 /* Force inlining */
14594 if (func->type->type & ATTRIB_NOINLINE) {
14595 do_inline = 0;
14597 if (func->type->type & ATTRIB_ALWAYS_INLINE) {
14598 do_inline = 1;
14600 return do_inline;
14603 static void inline_function(struct compile_state *state, struct triple *me, void *arg)
14605 struct triple *first, *ptr, *next;
14606 /* If the function is not used don't bother */
14607 if (me->u.cval <= 0) {
14608 return;
14610 if (state->compiler->debug & DEBUG_CALLS2) {
14611 FILE *fp = state->dbgout;
14612 fprintf(fp, "in: %s\n",
14613 me->type->type_ident->name);
14616 first = RHS(me, 0);
14617 next = first;
14618 do {
14619 struct triple *func, *prev;
14620 ptr = next;
14621 prev = ptr->prev;
14622 next = ptr->next;
14623 if (ptr->op != OP_FCALL) {
14624 continue;
14626 func = MISC(ptr, 0);
14627 /* See if the function should be inlined */
14628 if (!do_inline(state, func)) {
14629 /* Put a label after the fcall */
14630 post_triple(state, ptr, OP_LABEL, &void_type, 0, 0);
14631 continue;
14633 if (state->compiler->debug & DEBUG_CALLS) {
14634 FILE *fp = state->dbgout;
14635 if (state->compiler->debug & DEBUG_CALLS2) {
14636 loc(fp, state, ptr);
14638 fprintf(fp, "inlining %s\n",
14639 func->type->type_ident->name);
14640 fflush(fp);
14643 /* Update the function use counts */
14644 func->u.cval -= 1;
14646 /* Replace the fcall with the called function */
14647 expand_inline_call(state, me, ptr);
14649 next = prev->next;
14650 } while (next != first);
14652 next = first;
14653 do {
14654 struct triple *prev, *func;
14655 ptr = next;
14656 prev = ptr->prev;
14657 next = ptr->next;
14658 if (ptr->op != OP_FCALL) {
14659 continue;
14661 func = MISC(ptr, 0);
14662 if (state->compiler->debug & DEBUG_CALLS) {
14663 FILE *fp = state->dbgout;
14664 if (state->compiler->debug & DEBUG_CALLS2) {
14665 loc(fp, state, ptr);
14667 fprintf(fp, "calling %s\n",
14668 func->type->type_ident->name);
14669 fflush(fp);
14671 /* Replace the fcall with the instruction sequence
14672 * needed to make the call.
14674 expand_function_call(state, me, ptr);
14675 next = prev->next;
14676 } while(next != first);
14679 static void inline_functions(struct compile_state *state, struct triple *func)
14681 inline_function(state, func, 0);
14682 reverse_walk_functions(state, inline_function, 0);
14685 static void insert_function(struct compile_state *state,
14686 struct triple *func, void *arg)
14688 struct triple *first, *end, *ffirst, *fend;
14690 if (state->compiler->debug & DEBUG_INLINE) {
14691 FILE *fp = state->errout;
14692 fprintf(fp, "%s func count: %d\n",
14693 func->type->type_ident->name, func->u.cval);
14695 if (func->u.cval == 0) {
14696 return;
14699 /* Find the end points of the lists */
14700 first = arg;
14701 end = first->prev;
14702 ffirst = RHS(func, 0);
14703 fend = ffirst->prev;
14705 /* splice the lists together */
14706 end->next = ffirst;
14707 ffirst->prev = end;
14708 fend->next = first;
14709 first->prev = fend;
14712 struct triple *input_asm(struct compile_state *state)
14714 struct asm_info *info;
14715 struct triple *def;
14716 int i, out;
14718 info = xcmalloc(sizeof(*info), "asm_info");
14719 info->str = "";
14721 out = sizeof(arch_input_regs)/sizeof(arch_input_regs[0]);
14722 memcpy(&info->tmpl.lhs, arch_input_regs, sizeof(arch_input_regs));
14724 def = new_triple(state, OP_ASM, &void_type, out, 0);
14725 def->u.ainfo = info;
14726 def->id |= TRIPLE_FLAG_VOLATILE;
14728 for(i = 0; i < out; i++) {
14729 struct triple *piece;
14730 piece = triple(state, OP_PIECE, &int_type, def, 0);
14731 piece->u.cval = i;
14732 LHS(def, i) = piece;
14735 return def;
14738 struct triple *output_asm(struct compile_state *state)
14740 struct asm_info *info;
14741 struct triple *def;
14742 int in;
14744 info = xcmalloc(sizeof(*info), "asm_info");
14745 info->str = "";
14747 in = sizeof(arch_output_regs)/sizeof(arch_output_regs[0]);
14748 memcpy(&info->tmpl.rhs, arch_output_regs, sizeof(arch_output_regs));
14750 def = new_triple(state, OP_ASM, &void_type, 0, in);
14751 def->u.ainfo = info;
14752 def->id |= TRIPLE_FLAG_VOLATILE;
14754 return def;
14757 static void join_functions(struct compile_state *state)
14759 struct triple *start, *end, *call, *in, *out, *func;
14760 struct file_state file;
14761 struct type *pnext, *param;
14762 struct type *result_type, *args_type;
14763 int idx;
14765 /* Be clear the functions have not been joined yet */
14766 state->functions_joined = 0;
14768 /* Dummy file state to get debug handing right */
14769 memset(&file, 0, sizeof(file));
14770 file.basename = "";
14771 file.line = 0;
14772 file.report_line = 0;
14773 file.report_name = file.basename;
14774 file.prev = state->file;
14775 state->file = &file;
14776 state->function = "";
14778 if (!state->main_function) {
14779 error(state, 0, "No functions to compile\n");
14782 /* The type of arguments */
14783 args_type = state->main_function->type->right;
14784 /* The return type without any specifiers */
14785 result_type = clone_type(0, state->main_function->type->left);
14788 /* Verify the external arguments */
14789 if (registers_of(state, args_type) > ARCH_INPUT_REGS) {
14790 error(state, state->main_function,
14791 "Too many external input arguments");
14793 if (registers_of(state, result_type) > ARCH_OUTPUT_REGS) {
14794 error(state, state->main_function,
14795 "Too many external output arguments");
14798 /* Lay down the basic program structure */
14799 end = label(state);
14800 start = label(state);
14801 start = flatten(state, state->first, start);
14802 end = flatten(state, state->first, end);
14803 in = input_asm(state);
14804 out = output_asm(state);
14805 call = new_triple(state, OP_FCALL, result_type, -1, registers_of(state, args_type));
14806 MISC(call, 0) = state->main_function;
14807 in = flatten(state, state->first, in);
14808 call = flatten(state, state->first, call);
14809 out = flatten(state, state->first, out);
14812 /* Read the external input arguments */
14813 pnext = args_type;
14814 idx = 0;
14815 while(pnext && ((pnext->type & TYPE_MASK) != TYPE_VOID)) {
14816 struct triple *expr;
14817 param = pnext;
14818 pnext = 0;
14819 if ((param->type & TYPE_MASK) == TYPE_PRODUCT) {
14820 pnext = param->right;
14821 param = param->left;
14823 if (registers_of(state, param) != 1) {
14824 error(state, state->main_function,
14825 "Arg: %d %s requires multiple registers",
14826 idx + 1, param->field_ident->name);
14828 expr = read_expr(state, LHS(in, idx));
14829 RHS(call, idx) = expr;
14830 expr = flatten(state, call, expr);
14831 use_triple(expr, call);
14833 idx++;
14837 /* Write the external output arguments */
14838 pnext = result_type;
14839 if ((pnext->type & TYPE_MASK) == TYPE_STRUCT) {
14840 pnext = result_type->left;
14842 for(idx = 0; idx < out->rhs; idx++) {
14843 struct triple *expr;
14844 param = pnext;
14845 pnext = 0;
14846 if (param && ((param->type & TYPE_MASK) == TYPE_PRODUCT)) {
14847 pnext = param->right;
14848 param = param->left;
14850 if (param && ((param->type & TYPE_MASK) == TYPE_VOID)) {
14851 param = 0;
14853 if (param) {
14854 if (registers_of(state, param) != 1) {
14855 error(state, state->main_function,
14856 "Result: %d %s requires multiple registers",
14857 idx, param->field_ident->name);
14859 expr = read_expr(state, call);
14860 if ((result_type->type & TYPE_MASK) == TYPE_STRUCT) {
14861 expr = deref_field(state, expr, param->field_ident);
14863 } else {
14864 expr = triple(state, OP_UNKNOWNVAL, &int_type, 0, 0);
14866 flatten(state, out, expr);
14867 RHS(out, idx) = expr;
14868 use_triple(expr, out);
14871 /* Allocate a dummy containing function */
14872 func = triple(state, OP_LIST,
14873 new_type(TYPE_FUNCTION, &void_type, &void_type), 0, 0);
14874 func->type->type_ident = lookup(state, "", 0);
14875 RHS(func, 0) = state->first;
14876 func->u.cval = 1;
14878 /* See which functions are called, and how often */
14879 mark_live_functions(state);
14880 inline_functions(state, func);
14881 walk_functions(state, insert_function, end);
14883 if (start->next != end) {
14884 flatten(state, start, branch(state, end, 0));
14887 /* OK now the functions have been joined. */
14888 state->functions_joined = 1;
14890 /* Done now cleanup */
14891 state->file = file.prev;
14892 state->function = 0;
14896 * Data structurs for optimation.
14900 static int do_use_block(
14901 struct block *used, struct block_set **head, struct block *user,
14902 int front)
14904 struct block_set **ptr, *new;
14905 if (!used)
14906 return 0;
14907 if (!user)
14908 return 0;
14909 ptr = head;
14910 while(*ptr) {
14911 if ((*ptr)->member == user) {
14912 return 0;
14914 ptr = &(*ptr)->next;
14916 new = xcmalloc(sizeof(*new), "block_set");
14917 new->member = user;
14918 if (front) {
14919 new->next = *head;
14920 *head = new;
14922 else {
14923 new->next = 0;
14924 *ptr = new;
14926 return 1;
14928 static int do_unuse_block(
14929 struct block *used, struct block_set **head, struct block *unuser)
14931 struct block_set *use, **ptr;
14932 int count;
14933 count = 0;
14934 ptr = head;
14935 while(*ptr) {
14936 use = *ptr;
14937 if (use->member == unuser) {
14938 *ptr = use->next;
14939 memset(use, -1, sizeof(*use));
14940 xfree(use);
14941 count += 1;
14943 else {
14944 ptr = &use->next;
14947 return count;
14950 static void use_block(struct block *used, struct block *user)
14952 int count;
14953 /* Append new to the head of the list, print_block
14954 * depends on this.
14956 count = do_use_block(used, &used->use, user, 1);
14957 used->users += count;
14959 static void unuse_block(struct block *used, struct block *unuser)
14961 int count;
14962 count = do_unuse_block(used, &used->use, unuser);
14963 used->users -= count;
14966 static void add_block_edge(struct block *block, struct block *edge, int front)
14968 int count;
14969 count = do_use_block(block, &block->edges, edge, front);
14970 block->edge_count += count;
14973 static void remove_block_edge(struct block *block, struct block *edge)
14975 int count;
14976 count = do_unuse_block(block, &block->edges, edge);
14977 block->edge_count -= count;
14980 static void idom_block(struct block *idom, struct block *user)
14982 do_use_block(idom, &idom->idominates, user, 0);
14985 static void unidom_block(struct block *idom, struct block *unuser)
14987 do_unuse_block(idom, &idom->idominates, unuser);
14990 static void domf_block(struct block *block, struct block *domf)
14992 do_use_block(block, &block->domfrontier, domf, 0);
14995 static void undomf_block(struct block *block, struct block *undomf)
14997 do_unuse_block(block, &block->domfrontier, undomf);
15000 static void ipdom_block(struct block *ipdom, struct block *user)
15002 do_use_block(ipdom, &ipdom->ipdominates, user, 0);
15005 static void unipdom_block(struct block *ipdom, struct block *unuser)
15007 do_unuse_block(ipdom, &ipdom->ipdominates, unuser);
15010 static void ipdomf_block(struct block *block, struct block *ipdomf)
15012 do_use_block(block, &block->ipdomfrontier, ipdomf, 0);
15015 static void unipdomf_block(struct block *block, struct block *unipdomf)
15017 do_unuse_block(block, &block->ipdomfrontier, unipdomf);
15020 static int walk_triples(
15021 struct compile_state *state,
15022 int (*cb)(struct compile_state *state, struct triple *ptr, void *arg),
15023 void *arg)
15025 struct triple *ptr;
15026 int result;
15027 ptr = state->first;
15028 do {
15029 result = cb(state, ptr, arg);
15030 if (ptr->next->prev != ptr) {
15031 internal_error(state, ptr->next, "bad prev");
15033 ptr = ptr->next;
15034 } while((result == 0) && (ptr != state->first));
15035 return result;
15038 #define PRINT_LIST 1
15039 static int do_print_triple(struct compile_state *state, struct triple *ins, void *arg)
15041 FILE *fp = arg;
15042 int op;
15043 op = ins->op;
15044 if (op == OP_LIST) {
15045 #if !PRINT_LIST
15046 return 0;
15047 #endif
15049 if ((op == OP_LABEL) && (ins->use)) {
15050 fprintf(fp, "\n%p:\n", ins);
15052 display_triple(fp, ins);
15054 if (triple_is_branch(state, ins) && ins->use &&
15055 (ins->op != OP_RET) && (ins->op != OP_FCALL)) {
15056 internal_error(state, ins, "branch used?");
15058 if (triple_is_branch(state, ins)) {
15059 fprintf(fp, "\n");
15061 return 0;
15064 static void print_triples(struct compile_state *state)
15066 if (state->compiler->debug & DEBUG_TRIPLES) {
15067 FILE *fp = state->dbgout;
15068 fprintf(fp, "--------------- triples ---------------\n");
15069 walk_triples(state, do_print_triple, fp);
15070 fprintf(fp, "\n");
15074 struct cf_block {
15075 struct block *block;
15077 static void find_cf_blocks(struct cf_block *cf, struct block *block)
15079 struct block_set *edge;
15080 if (!block || (cf[block->vertex].block == block)) {
15081 return;
15083 cf[block->vertex].block = block;
15084 for(edge = block->edges; edge; edge = edge->next) {
15085 find_cf_blocks(cf, edge->member);
15089 static void print_control_flow(struct compile_state *state,
15090 FILE *fp, struct basic_blocks *bb)
15092 struct cf_block *cf;
15093 int i;
15094 fprintf(fp, "\ncontrol flow\n");
15095 cf = xcmalloc(sizeof(*cf) * (bb->last_vertex + 1), "cf_block");
15096 find_cf_blocks(cf, bb->first_block);
15098 for(i = 1; i <= bb->last_vertex; i++) {
15099 struct block *block;
15100 struct block_set *edge;
15101 block = cf[i].block;
15102 if (!block)
15103 continue;
15104 fprintf(fp, "(%p) %d:", block, block->vertex);
15105 for(edge = block->edges; edge; edge = edge->next) {
15106 fprintf(fp, " %d", edge->member->vertex);
15108 fprintf(fp, "\n");
15111 xfree(cf);
15114 static void free_basic_block(struct compile_state *state, struct block *block)
15116 struct block_set *edge, *entry;
15117 struct block *child;
15118 if (!block) {
15119 return;
15121 if (block->vertex == -1) {
15122 return;
15124 block->vertex = -1;
15125 for(edge = block->edges; edge; edge = edge->next) {
15126 if (edge->member) {
15127 unuse_block(edge->member, block);
15130 if (block->idom) {
15131 unidom_block(block->idom, block);
15133 block->idom = 0;
15134 if (block->ipdom) {
15135 unipdom_block(block->ipdom, block);
15137 block->ipdom = 0;
15138 while((entry = block->use)) {
15139 child = entry->member;
15140 unuse_block(block, child);
15141 if (child && (child->vertex != -1)) {
15142 for(edge = child->edges; edge; edge = edge->next) {
15143 edge->member = 0;
15147 while((entry = block->idominates)) {
15148 child = entry->member;
15149 unidom_block(block, child);
15150 if (child && (child->vertex != -1)) {
15151 child->idom = 0;
15154 while((entry = block->domfrontier)) {
15155 child = entry->member;
15156 undomf_block(block, child);
15158 while((entry = block->ipdominates)) {
15159 child = entry->member;
15160 unipdom_block(block, child);
15161 if (child && (child->vertex != -1)) {
15162 child->ipdom = 0;
15165 while((entry = block->ipdomfrontier)) {
15166 child = entry->member;
15167 unipdomf_block(block, child);
15169 if (block->users != 0) {
15170 internal_error(state, 0, "block still has users");
15172 while((edge = block->edges)) {
15173 child = edge->member;
15174 remove_block_edge(block, child);
15176 if (child && (child->vertex != -1)) {
15177 free_basic_block(state, child);
15180 memset(block, -1, sizeof(*block));
15183 static void free_basic_blocks(struct compile_state *state,
15184 struct basic_blocks *bb)
15186 struct triple *first, *ins;
15187 free_basic_block(state, bb->first_block);
15188 bb->last_vertex = 0;
15189 bb->first_block = bb->last_block = 0;
15190 first = bb->first;
15191 ins = first;
15192 do {
15193 if (triple_stores_block(state, ins)) {
15194 ins->u.block = 0;
15196 ins = ins->next;
15197 } while(ins != first);
15201 static struct block *basic_block(struct compile_state *state,
15202 struct basic_blocks *bb, struct triple *first)
15204 struct block *block;
15205 struct triple *ptr;
15206 if (!triple_is_label(state, first)) {
15207 internal_error(state, first, "block does not start with a label");
15209 /* See if this basic block has already been setup */
15210 if (first->u.block != 0) {
15211 return first->u.block;
15213 /* Allocate another basic block structure */
15214 bb->last_vertex += 1;
15215 block = xcmalloc(sizeof(*block), "block");
15216 block->first = block->last = first;
15217 block->vertex = bb->last_vertex;
15218 ptr = first;
15219 do {
15220 if ((ptr != first) && triple_is_label(state, ptr) && (ptr->use)) {
15221 break;
15223 block->last = ptr;
15224 /* If ptr->u is not used remember where the baic block is */
15225 if (triple_stores_block(state, ptr)) {
15226 ptr->u.block = block;
15228 if (triple_is_branch(state, ptr)) {
15229 break;
15231 ptr = ptr->next;
15232 } while (ptr != bb->first);
15233 if ((ptr == bb->first) ||
15234 ((ptr->next == bb->first) && (
15235 triple_is_end(state, ptr) ||
15236 triple_is_ret(state, ptr))))
15238 /* The block has no outflowing edges */
15240 else if (triple_is_label(state, ptr)) {
15241 struct block *next;
15242 next = basic_block(state, bb, ptr);
15243 add_block_edge(block, next, 0);
15244 use_block(next, block);
15246 else if (triple_is_branch(state, ptr)) {
15247 struct triple **expr, *first;
15248 struct block *child;
15249 /* Find the branch targets.
15250 * I special case the first branch as that magically
15251 * avoids some difficult cases for the register allocator.
15253 expr = triple_edge_targ(state, ptr, 0);
15254 if (!expr) {
15255 internal_error(state, ptr, "branch without targets");
15257 first = *expr;
15258 expr = triple_edge_targ(state, ptr, expr);
15259 for(; expr; expr = triple_edge_targ(state, ptr, expr)) {
15260 if (!*expr) continue;
15261 child = basic_block(state, bb, *expr);
15262 use_block(child, block);
15263 add_block_edge(block, child, 0);
15265 if (first) {
15266 child = basic_block(state, bb, first);
15267 use_block(child, block);
15268 add_block_edge(block, child, 1);
15270 /* Be certain the return block of a call is
15271 * in a basic block. When it is not find
15272 * start of the block, insert a label if
15273 * necessary and build the basic block.
15274 * Then add a fake edge from the start block
15275 * to the return block of the function.
15277 if (state->functions_joined && triple_is_call(state, ptr)
15278 && !block_of_triple(state, MISC(ptr, 0))) {
15279 struct block *tail;
15280 struct triple *start;
15281 start = triple_to_block_start(state, MISC(ptr, 0));
15282 if (!triple_is_label(state, start)) {
15283 start = pre_triple(state,
15284 start, OP_LABEL, &void_type, 0, 0);
15286 tail = basic_block(state, bb, start);
15287 add_block_edge(child, tail, 0);
15288 use_block(tail, child);
15292 else {
15293 internal_error(state, 0, "Bad basic block split");
15295 #if 0
15297 struct block_set *edge;
15298 FILE *fp = state->errout;
15299 fprintf(fp, "basic_block: %10p [%2d] ( %10p - %10p )",
15300 block, block->vertex,
15301 block->first, block->last);
15302 for(edge = block->edges; edge; edge = edge->next) {
15303 fprintf(fp, " %10p [%2d]",
15304 edge->member ? edge->member->first : 0,
15305 edge->member ? edge->member->vertex : -1);
15307 fprintf(fp, "\n");
15309 #endif
15310 return block;
15314 static void walk_blocks(struct compile_state *state, struct basic_blocks *bb,
15315 void (*cb)(struct compile_state *state, struct block *block, void *arg),
15316 void *arg)
15318 struct triple *ptr, *first;
15319 struct block *last_block;
15320 last_block = 0;
15321 first = bb->first;
15322 ptr = first;
15323 do {
15324 if (triple_stores_block(state, ptr)) {
15325 struct block *block;
15326 block = ptr->u.block;
15327 if (block && (block != last_block)) {
15328 cb(state, block, arg);
15330 last_block = block;
15332 ptr = ptr->next;
15333 } while(ptr != first);
15336 static void print_block(
15337 struct compile_state *state, struct block *block, void *arg)
15339 struct block_set *user, *edge;
15340 struct triple *ptr;
15341 FILE *fp = arg;
15343 fprintf(fp, "\nblock: %p (%d) ",
15344 block,
15345 block->vertex);
15347 for(edge = block->edges; edge; edge = edge->next) {
15348 fprintf(fp, " %p<-%p",
15349 edge->member,
15350 (edge->member && edge->member->use)?
15351 edge->member->use->member : 0);
15353 fprintf(fp, "\n");
15354 if (block->first->op == OP_LABEL) {
15355 fprintf(fp, "%p:\n", block->first);
15357 for(ptr = block->first; ; ) {
15358 display_triple(fp, ptr);
15359 if (ptr == block->last)
15360 break;
15361 ptr = ptr->next;
15362 if (ptr == block->first) {
15363 internal_error(state, 0, "missing block last?");
15366 fprintf(fp, "users %d: ", block->users);
15367 for(user = block->use; user; user = user->next) {
15368 fprintf(fp, "%p (%d) ",
15369 user->member,
15370 user->member->vertex);
15372 fprintf(fp,"\n\n");
15376 static void romcc_print_blocks(struct compile_state *state, FILE *fp)
15378 fprintf(fp, "--------------- blocks ---------------\n");
15379 walk_blocks(state, &state->bb, print_block, fp);
15381 static void print_blocks(struct compile_state *state, const char *func, FILE *fp)
15383 if (state->compiler->debug & DEBUG_BASIC_BLOCKS) {
15384 fprintf(fp, "After %s\n", func);
15385 romcc_print_blocks(state, fp);
15386 if (state->compiler->debug & DEBUG_FDOMINATORS) {
15387 print_dominators(state, fp, &state->bb);
15388 print_dominance_frontiers(state, fp, &state->bb);
15390 print_control_flow(state, fp, &state->bb);
15394 static void prune_nonblock_triples(struct compile_state *state,
15395 struct basic_blocks *bb)
15397 struct block *block;
15398 struct triple *first, *ins, *next;
15399 /* Delete the triples not in a basic block */
15400 block = 0;
15401 first = bb->first;
15402 ins = first;
15403 do {
15404 next = ins->next;
15405 if (ins->op == OP_LABEL) {
15406 block = ins->u.block;
15408 if (!block) {
15409 struct triple_set *use;
15410 for(use = ins->use; use; use = use->next) {
15411 struct block *block;
15412 block = block_of_triple(state, use->member);
15413 if (block != 0) {
15414 internal_error(state, ins, "pruning used ins?");
15417 release_triple(state, ins);
15419 if (block && block->last == ins) {
15420 block = 0;
15422 ins = next;
15423 } while(ins != first);
15426 static void setup_basic_blocks(struct compile_state *state,
15427 struct basic_blocks *bb)
15429 if (!triple_stores_block(state, bb->first)) {
15430 internal_error(state, 0, "ins will not store block?");
15432 /* Initialize the state */
15433 bb->first_block = bb->last_block = 0;
15434 bb->last_vertex = 0;
15435 free_basic_blocks(state, bb);
15437 /* Find the basic blocks */
15438 bb->first_block = basic_block(state, bb, bb->first);
15440 /* Be certain the last instruction of a function, or the
15441 * entire program is in a basic block. When it is not find
15442 * the start of the block, insert a label if necessary and build
15443 * basic block. Then add a fake edge from the start block
15444 * to the final block.
15446 if (!block_of_triple(state, bb->first->prev)) {
15447 struct triple *start;
15448 struct block *tail;
15449 start = triple_to_block_start(state, bb->first->prev);
15450 if (!triple_is_label(state, start)) {
15451 start = pre_triple(state,
15452 start, OP_LABEL, &void_type, 0, 0);
15454 tail = basic_block(state, bb, start);
15455 add_block_edge(bb->first_block, tail, 0);
15456 use_block(tail, bb->first_block);
15459 /* Find the last basic block.
15461 bb->last_block = block_of_triple(state, bb->first->prev);
15463 /* Delete the triples not in a basic block */
15464 prune_nonblock_triples(state, bb);
15466 #if 0
15467 /* If we are debugging print what I have just done */
15468 if (state->compiler->debug & DEBUG_BASIC_BLOCKS) {
15469 print_blocks(state, state->dbgout);
15470 print_control_flow(state, bb);
15472 #endif
15476 struct sdom_block {
15477 struct block *block;
15478 struct sdom_block *sdominates;
15479 struct sdom_block *sdom_next;
15480 struct sdom_block *sdom;
15481 struct sdom_block *label;
15482 struct sdom_block *parent;
15483 struct sdom_block *ancestor;
15484 int vertex;
15488 static void unsdom_block(struct sdom_block *block)
15490 struct sdom_block **ptr;
15491 if (!block->sdom_next) {
15492 return;
15494 ptr = &block->sdom->sdominates;
15495 while(*ptr) {
15496 if ((*ptr) == block) {
15497 *ptr = block->sdom_next;
15498 return;
15500 ptr = &(*ptr)->sdom_next;
15504 static void sdom_block(struct sdom_block *sdom, struct sdom_block *block)
15506 unsdom_block(block);
15507 block->sdom = sdom;
15508 block->sdom_next = sdom->sdominates;
15509 sdom->sdominates = block;
15514 static int initialize_sdblock(struct sdom_block *sd,
15515 struct block *parent, struct block *block, int vertex)
15517 struct block_set *edge;
15518 if (!block || (sd[block->vertex].block == block)) {
15519 return vertex;
15521 vertex += 1;
15522 /* Renumber the blocks in a convenient fashion */
15523 block->vertex = vertex;
15524 sd[vertex].block = block;
15525 sd[vertex].sdom = &sd[vertex];
15526 sd[vertex].label = &sd[vertex];
15527 sd[vertex].parent = parent? &sd[parent->vertex] : 0;
15528 sd[vertex].ancestor = 0;
15529 sd[vertex].vertex = vertex;
15530 for(edge = block->edges; edge; edge = edge->next) {
15531 vertex = initialize_sdblock(sd, block, edge->member, vertex);
15533 return vertex;
15536 static int initialize_spdblock(
15537 struct compile_state *state, struct sdom_block *sd,
15538 struct block *parent, struct block *block, int vertex)
15540 struct block_set *user;
15541 if (!block || (sd[block->vertex].block == block)) {
15542 return vertex;
15544 vertex += 1;
15545 /* Renumber the blocks in a convenient fashion */
15546 block->vertex = vertex;
15547 sd[vertex].block = block;
15548 sd[vertex].sdom = &sd[vertex];
15549 sd[vertex].label = &sd[vertex];
15550 sd[vertex].parent = parent? &sd[parent->vertex] : 0;
15551 sd[vertex].ancestor = 0;
15552 sd[vertex].vertex = vertex;
15553 for(user = block->use; user; user = user->next) {
15554 vertex = initialize_spdblock(state, sd, block, user->member, vertex);
15556 return vertex;
15559 static int setup_spdblocks(struct compile_state *state,
15560 struct basic_blocks *bb, struct sdom_block *sd)
15562 struct block *block;
15563 int vertex;
15564 /* Setup as many sdpblocks as possible without using fake edges */
15565 vertex = initialize_spdblock(state, sd, 0, bb->last_block, 0);
15567 /* Walk through the graph and find unconnected blocks. Add a
15568 * fake edge from the unconnected blocks to the end of the
15569 * graph.
15571 block = bb->first_block->last->next->u.block;
15572 for(; block && block != bb->first_block; block = block->last->next->u.block) {
15573 if (sd[block->vertex].block == block) {
15574 continue;
15576 #if DEBUG_SDP_BLOCKS
15578 FILE *fp = state->errout;
15579 fprintf(fp, "Adding %d\n", vertex +1);
15581 #endif
15582 add_block_edge(block, bb->last_block, 0);
15583 use_block(bb->last_block, block);
15585 vertex = initialize_spdblock(state, sd, bb->last_block, block, vertex);
15587 return vertex;
15590 static void compress_ancestors(struct sdom_block *v)
15592 /* This procedure assumes ancestor(v) != 0 */
15593 /* if (ancestor(ancestor(v)) != 0) {
15594 * compress(ancestor(ancestor(v)));
15595 * if (semi(label(ancestor(v))) < semi(label(v))) {
15596 * label(v) = label(ancestor(v));
15598 * ancestor(v) = ancestor(ancestor(v));
15601 if (!v->ancestor) {
15602 return;
15604 if (v->ancestor->ancestor) {
15605 compress_ancestors(v->ancestor->ancestor);
15606 if (v->ancestor->label->sdom->vertex < v->label->sdom->vertex) {
15607 v->label = v->ancestor->label;
15609 v->ancestor = v->ancestor->ancestor;
15613 static void compute_sdom(struct compile_state *state,
15614 struct basic_blocks *bb, struct sdom_block *sd)
15616 int i;
15617 /* // step 2
15618 * for each v <= pred(w) {
15619 * u = EVAL(v);
15620 * if (semi[u] < semi[w] {
15621 * semi[w] = semi[u];
15624 * add w to bucket(vertex(semi[w]));
15625 * LINK(parent(w), w);
15627 * // step 3
15628 * for each v <= bucket(parent(w)) {
15629 * delete v from bucket(parent(w));
15630 * u = EVAL(v);
15631 * dom(v) = (semi[u] < semi[v]) ? u : parent(w);
15634 for(i = bb->last_vertex; i >= 2; i--) {
15635 struct sdom_block *v, *parent, *next;
15636 struct block_set *user;
15637 struct block *block;
15638 block = sd[i].block;
15639 parent = sd[i].parent;
15640 /* Step 2 */
15641 for(user = block->use; user; user = user->next) {
15642 struct sdom_block *v, *u;
15643 v = &sd[user->member->vertex];
15644 u = !(v->ancestor)? v : (compress_ancestors(v), v->label);
15645 if (u->sdom->vertex < sd[i].sdom->vertex) {
15646 sd[i].sdom = u->sdom;
15649 sdom_block(sd[i].sdom, &sd[i]);
15650 sd[i].ancestor = parent;
15651 /* Step 3 */
15652 for(v = parent->sdominates; v; v = next) {
15653 struct sdom_block *u;
15654 next = v->sdom_next;
15655 unsdom_block(v);
15656 u = (!v->ancestor) ? v : (compress_ancestors(v), v->label);
15657 v->block->idom = (u->sdom->vertex < v->sdom->vertex)?
15658 u->block : parent->block;
15663 static void compute_spdom(struct compile_state *state,
15664 struct basic_blocks *bb, struct sdom_block *sd)
15666 int i;
15667 /* // step 2
15668 * for each v <= pred(w) {
15669 * u = EVAL(v);
15670 * if (semi[u] < semi[w] {
15671 * semi[w] = semi[u];
15674 * add w to bucket(vertex(semi[w]));
15675 * LINK(parent(w), w);
15677 * // step 3
15678 * for each v <= bucket(parent(w)) {
15679 * delete v from bucket(parent(w));
15680 * u = EVAL(v);
15681 * dom(v) = (semi[u] < semi[v]) ? u : parent(w);
15684 for(i = bb->last_vertex; i >= 2; i--) {
15685 struct sdom_block *u, *v, *parent, *next;
15686 struct block_set *edge;
15687 struct block *block;
15688 block = sd[i].block;
15689 parent = sd[i].parent;
15690 /* Step 2 */
15691 for(edge = block->edges; edge; edge = edge->next) {
15692 v = &sd[edge->member->vertex];
15693 u = !(v->ancestor)? v : (compress_ancestors(v), v->label);
15694 if (u->sdom->vertex < sd[i].sdom->vertex) {
15695 sd[i].sdom = u->sdom;
15698 sdom_block(sd[i].sdom, &sd[i]);
15699 sd[i].ancestor = parent;
15700 /* Step 3 */
15701 for(v = parent->sdominates; v; v = next) {
15702 struct sdom_block *u;
15703 next = v->sdom_next;
15704 unsdom_block(v);
15705 u = (!v->ancestor) ? v : (compress_ancestors(v), v->label);
15706 v->block->ipdom = (u->sdom->vertex < v->sdom->vertex)?
15707 u->block : parent->block;
15712 static void compute_idom(struct compile_state *state,
15713 struct basic_blocks *bb, struct sdom_block *sd)
15715 int i;
15716 for(i = 2; i <= bb->last_vertex; i++) {
15717 struct block *block;
15718 block = sd[i].block;
15719 if (block->idom->vertex != sd[i].sdom->vertex) {
15720 block->idom = block->idom->idom;
15722 idom_block(block->idom, block);
15724 sd[1].block->idom = 0;
15727 static void compute_ipdom(struct compile_state *state,
15728 struct basic_blocks *bb, struct sdom_block *sd)
15730 int i;
15731 for(i = 2; i <= bb->last_vertex; i++) {
15732 struct block *block;
15733 block = sd[i].block;
15734 if (block->ipdom->vertex != sd[i].sdom->vertex) {
15735 block->ipdom = block->ipdom->ipdom;
15737 ipdom_block(block->ipdom, block);
15739 sd[1].block->ipdom = 0;
15742 /* Theorem 1:
15743 * Every vertex of a flowgraph G = (V, E, r) except r has
15744 * a unique immediate dominator.
15745 * The edges {(idom(w), w) |w <= V - {r}} form a directed tree
15746 * rooted at r, called the dominator tree of G, such that
15747 * v dominates w if and only if v is a proper ancestor of w in
15748 * the dominator tree.
15750 /* Lemma 1:
15751 * If v and w are vertices of G such that v <= w,
15752 * than any path from v to w must contain a common ancestor
15753 * of v and w in T.
15755 /* Lemma 2: For any vertex w != r, idom(w) -> w */
15756 /* Lemma 3: For any vertex w != r, sdom(w) -> w */
15757 /* Lemma 4: For any vertex w != r, idom(w) -> sdom(w) */
15758 /* Theorem 2:
15759 * Let w != r. Suppose every u for which sdom(w) -> u -> w satisfies
15760 * sdom(u) >= sdom(w). Then idom(w) = sdom(w).
15762 /* Theorem 3:
15763 * Let w != r and let u be a vertex for which sdom(u) is
15764 * minimum among vertices u satisfying sdom(w) -> u -> w.
15765 * Then sdom(u) <= sdom(w) and idom(u) = idom(w).
15767 /* Lemma 5: Let vertices v,w satisfy v -> w.
15768 * Then v -> idom(w) or idom(w) -> idom(v)
15771 static void find_immediate_dominators(struct compile_state *state,
15772 struct basic_blocks *bb)
15774 struct sdom_block *sd;
15775 /* w->sdom = min{v| there is a path v = v0,v1,...,vk = w such that:
15776 * vi > w for (1 <= i <= k - 1}
15778 /* Theorem 4:
15779 * For any vertex w != r.
15780 * sdom(w) = min(
15781 * {v|(v,w) <= E and v < w } U
15782 * {sdom(u) | u > w and there is an edge (v, w) such that u -> v})
15784 /* Corollary 1:
15785 * Let w != r and let u be a vertex for which sdom(u) is
15786 * minimum among vertices u satisfying sdom(w) -> u -> w.
15787 * Then:
15788 * { sdom(w) if sdom(w) = sdom(u),
15789 * idom(w) = {
15790 * { idom(u) otherwise
15792 /* The algorithm consists of the following 4 steps.
15793 * Step 1. Carry out a depth-first search of the problem graph.
15794 * Number the vertices from 1 to N as they are reached during
15795 * the search. Initialize the variables used in succeeding steps.
15796 * Step 2. Compute the semidominators of all vertices by applying
15797 * theorem 4. Carry out the computation vertex by vertex in
15798 * decreasing order by number.
15799 * Step 3. Implicitly define the immediate dominator of each vertex
15800 * by applying Corollary 1.
15801 * Step 4. Explicitly define the immediate dominator of each vertex,
15802 * carrying out the computation vertex by vertex in increasing order
15803 * by number.
15805 /* Step 1 initialize the basic block information */
15806 sd = xcmalloc(sizeof(*sd) * (bb->last_vertex + 1), "sdom_state");
15807 initialize_sdblock(sd, 0, bb->first_block, 0);
15808 #if 0
15809 sd[1].size = 0;
15810 sd[1].label = 0;
15811 sd[1].sdom = 0;
15812 #endif
15813 /* Step 2 compute the semidominators */
15814 /* Step 3 implicitly define the immediate dominator of each vertex */
15815 compute_sdom(state, bb, sd);
15816 /* Step 4 explicitly define the immediate dominator of each vertex */
15817 compute_idom(state, bb, sd);
15818 xfree(sd);
15821 static void find_post_dominators(struct compile_state *state,
15822 struct basic_blocks *bb)
15824 struct sdom_block *sd;
15825 int vertex;
15826 /* Step 1 initialize the basic block information */
15827 sd = xcmalloc(sizeof(*sd) * (bb->last_vertex + 1), "sdom_state");
15829 vertex = setup_spdblocks(state, bb, sd);
15830 if (vertex != bb->last_vertex) {
15831 internal_error(state, 0, "missing %d blocks",
15832 bb->last_vertex - vertex);
15835 /* Step 2 compute the semidominators */
15836 /* Step 3 implicitly define the immediate dominator of each vertex */
15837 compute_spdom(state, bb, sd);
15838 /* Step 4 explicitly define the immediate dominator of each vertex */
15839 compute_ipdom(state, bb, sd);
15840 xfree(sd);
15845 static void find_block_domf(struct compile_state *state, struct block *block)
15847 struct block *child;
15848 struct block_set *user, *edge;
15849 if (block->domfrontier != 0) {
15850 internal_error(state, block->first, "domfrontier present?");
15852 for(user = block->idominates; user; user = user->next) {
15853 child = user->member;
15854 if (child->idom != block) {
15855 internal_error(state, block->first, "bad idom");
15857 find_block_domf(state, child);
15859 for(edge = block->edges; edge; edge = edge->next) {
15860 if (edge->member->idom != block) {
15861 domf_block(block, edge->member);
15864 for(user = block->idominates; user; user = user->next) {
15865 struct block_set *frontier;
15866 child = user->member;
15867 for(frontier = child->domfrontier; frontier; frontier = frontier->next) {
15868 if (frontier->member->idom != block) {
15869 domf_block(block, frontier->member);
15875 static void find_block_ipdomf(struct compile_state *state, struct block *block)
15877 struct block *child;
15878 struct block_set *user;
15879 if (block->ipdomfrontier != 0) {
15880 internal_error(state, block->first, "ipdomfrontier present?");
15882 for(user = block->ipdominates; user; user = user->next) {
15883 child = user->member;
15884 if (child->ipdom != block) {
15885 internal_error(state, block->first, "bad ipdom");
15887 find_block_ipdomf(state, child);
15889 for(user = block->use; user; user = user->next) {
15890 if (user->member->ipdom != block) {
15891 ipdomf_block(block, user->member);
15894 for(user = block->ipdominates; user; user = user->next) {
15895 struct block_set *frontier;
15896 child = user->member;
15897 for(frontier = child->ipdomfrontier; frontier; frontier = frontier->next) {
15898 if (frontier->member->ipdom != block) {
15899 ipdomf_block(block, frontier->member);
15905 static void print_dominated(
15906 struct compile_state *state, struct block *block, void *arg)
15908 struct block_set *user;
15909 FILE *fp = arg;
15911 fprintf(fp, "%d:", block->vertex);
15912 for(user = block->idominates; user; user = user->next) {
15913 fprintf(fp, " %d", user->member->vertex);
15914 if (user->member->idom != block) {
15915 internal_error(state, user->member->first, "bad idom");
15918 fprintf(fp,"\n");
15921 static void print_dominated2(
15922 struct compile_state *state, FILE *fp, int depth, struct block *block)
15924 struct block_set *user;
15925 struct triple *ins;
15926 struct occurrence *ptr, *ptr2;
15927 const char *filename1, *filename2;
15928 int equal_filenames;
15929 int i;
15930 for(i = 0; i < depth; i++) {
15931 fprintf(fp, " ");
15933 fprintf(fp, "%3d: %p (%p - %p) @",
15934 block->vertex, block, block->first, block->last);
15935 ins = block->first;
15936 while(ins != block->last && (ins->occurrence->line == 0)) {
15937 ins = ins->next;
15939 ptr = ins->occurrence;
15940 ptr2 = block->last->occurrence;
15941 filename1 = ptr->filename? ptr->filename : "";
15942 filename2 = ptr2->filename? ptr2->filename : "";
15943 equal_filenames = (strcmp(filename1, filename2) == 0);
15944 if ((ptr == ptr2) || (equal_filenames && ptr->line == ptr2->line)) {
15945 fprintf(fp, " %s:%d", ptr->filename, ptr->line);
15946 } else if (equal_filenames) {
15947 fprintf(fp, " %s:(%d - %d)",
15948 ptr->filename, ptr->line, ptr2->line);
15949 } else {
15950 fprintf(fp, " (%s:%d - %s:%d)",
15951 ptr->filename, ptr->line,
15952 ptr2->filename, ptr2->line);
15954 fprintf(fp, "\n");
15955 for(user = block->idominates; user; user = user->next) {
15956 print_dominated2(state, fp, depth + 1, user->member);
15960 static void print_dominators(struct compile_state *state, FILE *fp, struct basic_blocks *bb)
15962 fprintf(fp, "\ndominates\n");
15963 walk_blocks(state, bb, print_dominated, fp);
15964 fprintf(fp, "dominates\n");
15965 print_dominated2(state, fp, 0, bb->first_block);
15969 static int print_frontiers(
15970 struct compile_state *state, FILE *fp, struct block *block, int vertex)
15972 struct block_set *user, *edge;
15974 if (!block || (block->vertex != vertex + 1)) {
15975 return vertex;
15977 vertex += 1;
15979 fprintf(fp, "%d:", block->vertex);
15980 for(user = block->domfrontier; user; user = user->next) {
15981 fprintf(fp, " %d", user->member->vertex);
15983 fprintf(fp, "\n");
15985 for(edge = block->edges; edge; edge = edge->next) {
15986 vertex = print_frontiers(state, fp, edge->member, vertex);
15988 return vertex;
15990 static void print_dominance_frontiers(struct compile_state *state,
15991 FILE *fp, struct basic_blocks *bb)
15993 fprintf(fp, "\ndominance frontiers\n");
15994 print_frontiers(state, fp, bb->first_block, 0);
15998 static void analyze_idominators(struct compile_state *state, struct basic_blocks *bb)
16000 /* Find the immediate dominators */
16001 find_immediate_dominators(state, bb);
16002 /* Find the dominance frontiers */
16003 find_block_domf(state, bb->first_block);
16004 /* If debuging print the print what I have just found */
16005 if (state->compiler->debug & DEBUG_FDOMINATORS) {
16006 print_dominators(state, state->dbgout, bb);
16007 print_dominance_frontiers(state, state->dbgout, bb);
16008 print_control_flow(state, state->dbgout, bb);
16013 static void print_ipdominated(
16014 struct compile_state *state, struct block *block, void *arg)
16016 struct block_set *user;
16017 FILE *fp = arg;
16019 fprintf(fp, "%d:", block->vertex);
16020 for(user = block->ipdominates; user; user = user->next) {
16021 fprintf(fp, " %d", user->member->vertex);
16022 if (user->member->ipdom != block) {
16023 internal_error(state, user->member->first, "bad ipdom");
16026 fprintf(fp, "\n");
16029 static void print_ipdominators(struct compile_state *state, FILE *fp,
16030 struct basic_blocks *bb)
16032 fprintf(fp, "\nipdominates\n");
16033 walk_blocks(state, bb, print_ipdominated, fp);
16036 static int print_pfrontiers(
16037 struct compile_state *state, FILE *fp, struct block *block, int vertex)
16039 struct block_set *user;
16041 if (!block || (block->vertex != vertex + 1)) {
16042 return vertex;
16044 vertex += 1;
16046 fprintf(fp, "%d:", block->vertex);
16047 for(user = block->ipdomfrontier; user; user = user->next) {
16048 fprintf(fp, " %d", user->member->vertex);
16050 fprintf(fp, "\n");
16051 for(user = block->use; user; user = user->next) {
16052 vertex = print_pfrontiers(state, fp, user->member, vertex);
16054 return vertex;
16056 static void print_ipdominance_frontiers(struct compile_state *state,
16057 FILE *fp, struct basic_blocks *bb)
16059 fprintf(fp, "\nipdominance frontiers\n");
16060 print_pfrontiers(state, fp, bb->last_block, 0);
16064 static void analyze_ipdominators(struct compile_state *state,
16065 struct basic_blocks *bb)
16067 /* Find the post dominators */
16068 find_post_dominators(state, bb);
16069 /* Find the control dependencies (post dominance frontiers) */
16070 find_block_ipdomf(state, bb->last_block);
16071 /* If debuging print the print what I have just found */
16072 if (state->compiler->debug & DEBUG_RDOMINATORS) {
16073 print_ipdominators(state, state->dbgout, bb);
16074 print_ipdominance_frontiers(state, state->dbgout, bb);
16075 print_control_flow(state, state->dbgout, bb);
16079 static int bdominates(struct compile_state *state,
16080 struct block *dom, struct block *sub)
16082 while(sub && (sub != dom)) {
16083 sub = sub->idom;
16085 return sub == dom;
16088 static int tdominates(struct compile_state *state,
16089 struct triple *dom, struct triple *sub)
16091 struct block *bdom, *bsub;
16092 int result;
16093 bdom = block_of_triple(state, dom);
16094 bsub = block_of_triple(state, sub);
16095 if (bdom != bsub) {
16096 result = bdominates(state, bdom, bsub);
16098 else {
16099 struct triple *ins;
16100 if (!bdom || !bsub) {
16101 internal_error(state, dom, "huh?");
16103 ins = sub;
16104 while((ins != bsub->first) && (ins != dom)) {
16105 ins = ins->prev;
16107 result = (ins == dom);
16109 return result;
16112 static void analyze_basic_blocks(
16113 struct compile_state *state, struct basic_blocks *bb)
16115 setup_basic_blocks(state, bb);
16116 analyze_idominators(state, bb);
16117 analyze_ipdominators(state, bb);
16120 static void insert_phi_operations(struct compile_state *state)
16122 size_t size;
16123 struct triple *first;
16124 int *has_already, *work;
16125 struct block *work_list, **work_list_tail;
16126 int iter;
16127 struct triple *var, *vnext;
16129 size = sizeof(int) * (state->bb.last_vertex + 1);
16130 has_already = xcmalloc(size, "has_already");
16131 work = xcmalloc(size, "work");
16132 iter = 0;
16134 first = state->first;
16135 for(var = first->next; var != first ; var = vnext) {
16136 struct block *block;
16137 struct triple_set *user, *unext;
16138 vnext = var->next;
16140 if (!triple_is_auto_var(state, var) || !var->use) {
16141 continue;
16144 iter += 1;
16145 work_list = 0;
16146 work_list_tail = &work_list;
16147 for(user = var->use; user; user = unext) {
16148 unext = user->next;
16149 if (MISC(var, 0) == user->member) {
16150 continue;
16152 if (user->member->op == OP_READ) {
16153 continue;
16155 if (user->member->op != OP_WRITE) {
16156 internal_error(state, user->member,
16157 "bad variable access");
16159 block = user->member->u.block;
16160 if (!block) {
16161 warning(state, user->member, "dead code");
16162 release_triple(state, user->member);
16163 continue;
16165 if (work[block->vertex] >= iter) {
16166 continue;
16168 work[block->vertex] = iter;
16169 *work_list_tail = block;
16170 block->work_next = 0;
16171 work_list_tail = &block->work_next;
16173 for(block = work_list; block; block = block->work_next) {
16174 struct block_set *df;
16175 for(df = block->domfrontier; df; df = df->next) {
16176 struct triple *phi;
16177 struct block *front;
16178 int in_edges;
16179 front = df->member;
16181 if (has_already[front->vertex] >= iter) {
16182 continue;
16184 /* Count how many edges flow into this block */
16185 in_edges = front->users;
16186 /* Insert a phi function for this variable */
16187 get_occurrence(var->occurrence);
16188 phi = alloc_triple(
16189 state, OP_PHI, var->type, -1, in_edges,
16190 var->occurrence);
16191 phi->u.block = front;
16192 MISC(phi, 0) = var;
16193 use_triple(var, phi);
16194 #if 1
16195 if (phi->rhs != in_edges) {
16196 internal_error(state, phi, "phi->rhs: %d != in_edges: %d",
16197 phi->rhs, in_edges);
16199 #endif
16200 /* Insert the phi functions immediately after the label */
16201 insert_triple(state, front->first->next, phi);
16202 if (front->first == front->last) {
16203 front->last = front->first->next;
16205 has_already[front->vertex] = iter;
16206 transform_to_arch_instruction(state, phi);
16208 /* If necessary plan to visit the basic block */
16209 if (work[front->vertex] >= iter) {
16210 continue;
16212 work[front->vertex] = iter;
16213 *work_list_tail = front;
16214 front->work_next = 0;
16215 work_list_tail = &front->work_next;
16219 xfree(has_already);
16220 xfree(work);
16224 struct stack {
16225 struct triple_set *top;
16226 unsigned orig_id;
16229 static int count_auto_vars(struct compile_state *state)
16231 struct triple *first, *ins;
16232 int auto_vars = 0;
16233 first = state->first;
16234 ins = first;
16235 do {
16236 if (triple_is_auto_var(state, ins)) {
16237 auto_vars += 1;
16239 ins = ins->next;
16240 } while(ins != first);
16241 return auto_vars;
16244 static void number_auto_vars(struct compile_state *state, struct stack *stacks)
16246 struct triple *first, *ins;
16247 int auto_vars = 0;
16248 first = state->first;
16249 ins = first;
16250 do {
16251 if (triple_is_auto_var(state, ins)) {
16252 auto_vars += 1;
16253 stacks[auto_vars].orig_id = ins->id;
16254 ins->id = auto_vars;
16256 ins = ins->next;
16257 } while(ins != first);
16260 static void restore_auto_vars(struct compile_state *state, struct stack *stacks)
16262 struct triple *first, *ins;
16263 first = state->first;
16264 ins = first;
16265 do {
16266 if (triple_is_auto_var(state, ins)) {
16267 ins->id = stacks[ins->id].orig_id;
16269 ins = ins->next;
16270 } while(ins != first);
16273 static struct triple *peek_triple(struct stack *stacks, struct triple *var)
16275 struct triple_set *head;
16276 struct triple *top_val;
16277 top_val = 0;
16278 head = stacks[var->id].top;
16279 if (head) {
16280 top_val = head->member;
16282 return top_val;
16285 static void push_triple(struct stack *stacks, struct triple *var, struct triple *val)
16287 struct triple_set *new;
16288 /* Append new to the head of the list,
16289 * it's the only sensible behavoir for a stack.
16291 new = xcmalloc(sizeof(*new), "triple_set");
16292 new->member = val;
16293 new->next = stacks[var->id].top;
16294 stacks[var->id].top = new;
16297 static void pop_triple(struct stack *stacks, struct triple *var, struct triple *oldval)
16299 struct triple_set *set, **ptr;
16300 ptr = &stacks[var->id].top;
16301 while(*ptr) {
16302 set = *ptr;
16303 if (set->member == oldval) {
16304 *ptr = set->next;
16305 xfree(set);
16306 /* Only free one occurrence from the stack */
16307 return;
16309 else {
16310 ptr = &set->next;
16316 * C(V)
16317 * S(V)
16319 static void fixup_block_phi_variables(
16320 struct compile_state *state, struct stack *stacks, struct block *parent, struct block *block)
16322 struct block_set *set;
16323 struct triple *ptr;
16324 int edge;
16325 if (!parent || !block)
16326 return;
16327 /* Find the edge I am coming in on */
16328 edge = 0;
16329 for(set = block->use; set; set = set->next, edge++) {
16330 if (set->member == parent) {
16331 break;
16334 if (!set) {
16335 internal_error(state, 0, "phi input is not on a control predecessor");
16337 for(ptr = block->first; ; ptr = ptr->next) {
16338 if (ptr->op == OP_PHI) {
16339 struct triple *var, *val, **slot;
16340 var = MISC(ptr, 0);
16341 if (!var) {
16342 internal_error(state, ptr, "no var???");
16344 /* Find the current value of the variable */
16345 val = peek_triple(stacks, var);
16346 if (val && ((val->op == OP_WRITE) || (val->op == OP_READ))) {
16347 internal_error(state, val, "bad value in phi");
16349 if (edge >= ptr->rhs) {
16350 internal_error(state, ptr, "edges > phi rhs");
16352 slot = &RHS(ptr, edge);
16353 if ((*slot != 0) && (*slot != val)) {
16354 internal_error(state, ptr, "phi already bound on this edge");
16356 *slot = val;
16357 use_triple(val, ptr);
16359 if (ptr == block->last) {
16360 break;
16366 static void rename_block_variables(
16367 struct compile_state *state, struct stack *stacks, struct block *block)
16369 struct block_set *user, *edge;
16370 struct triple *ptr, *next, *last;
16371 int done;
16372 if (!block)
16373 return;
16374 last = block->first;
16375 done = 0;
16376 for(ptr = block->first; !done; ptr = next) {
16377 next = ptr->next;
16378 if (ptr == block->last) {
16379 done = 1;
16381 /* RHS(A) */
16382 if (ptr->op == OP_READ) {
16383 struct triple *var, *val;
16384 var = RHS(ptr, 0);
16385 if (!triple_is_auto_var(state, var)) {
16386 internal_error(state, ptr, "read of non auto var!");
16388 unuse_triple(var, ptr);
16389 /* Find the current value of the variable */
16390 val = peek_triple(stacks, var);
16391 if (!val) {
16392 /* Let the optimizer at variables that are not initially
16393 * set. But give it a bogus value so things seem to
16394 * work by accident. This is useful for bitfields because
16395 * setting them always involves a read-modify-write.
16397 if (TYPE_ARITHMETIC(ptr->type->type)) {
16398 val = pre_triple(state, ptr, OP_INTCONST, ptr->type, 0, 0);
16399 val->u.cval = 0xdeadbeaf;
16400 } else {
16401 val = pre_triple(state, ptr, OP_UNKNOWNVAL, ptr->type, 0, 0);
16404 if (!val) {
16405 error(state, ptr, "variable used without being set");
16407 if ((val->op == OP_WRITE) || (val->op == OP_READ)) {
16408 internal_error(state, val, "bad value in read");
16410 propagate_use(state, ptr, val);
16411 release_triple(state, ptr);
16412 continue;
16414 /* LHS(A) */
16415 if (ptr->op == OP_WRITE) {
16416 struct triple *var, *val, *tval;
16417 var = MISC(ptr, 0);
16418 if (!triple_is_auto_var(state, var)) {
16419 internal_error(state, ptr, "write to non auto var!");
16421 tval = val = RHS(ptr, 0);
16422 if ((val->op == OP_WRITE) || (val->op == OP_READ) ||
16423 triple_is_auto_var(state, val)) {
16424 internal_error(state, ptr, "bad value in write");
16426 /* Insert a cast if the types differ */
16427 if (!is_subset_type(ptr->type, val->type)) {
16428 if (val->op == OP_INTCONST) {
16429 tval = pre_triple(state, ptr, OP_INTCONST, ptr->type, 0, 0);
16430 tval->u.cval = val->u.cval;
16432 else {
16433 tval = pre_triple(state, ptr, OP_CONVERT, ptr->type, val, 0);
16434 use_triple(val, tval);
16436 transform_to_arch_instruction(state, tval);
16437 unuse_triple(val, ptr);
16438 RHS(ptr, 0) = tval;
16439 use_triple(tval, ptr);
16441 propagate_use(state, ptr, tval);
16442 unuse_triple(var, ptr);
16443 /* Push OP_WRITE ptr->right onto a stack of variable uses */
16444 push_triple(stacks, var, tval);
16446 if (ptr->op == OP_PHI) {
16447 struct triple *var;
16448 var = MISC(ptr, 0);
16449 if (!triple_is_auto_var(state, var)) {
16450 internal_error(state, ptr, "phi references non auto var!");
16452 /* Push OP_PHI onto a stack of variable uses */
16453 push_triple(stacks, var, ptr);
16455 last = ptr;
16457 block->last = last;
16459 /* Fixup PHI functions in the cf successors */
16460 for(edge = block->edges; edge; edge = edge->next) {
16461 fixup_block_phi_variables(state, stacks, block, edge->member);
16463 /* rename variables in the dominated nodes */
16464 for(user = block->idominates; user; user = user->next) {
16465 rename_block_variables(state, stacks, user->member);
16467 /* pop the renamed variable stack */
16468 last = block->first;
16469 done = 0;
16470 for(ptr = block->first; !done ; ptr = next) {
16471 next = ptr->next;
16472 if (ptr == block->last) {
16473 done = 1;
16475 if (ptr->op == OP_WRITE) {
16476 struct triple *var;
16477 var = MISC(ptr, 0);
16478 /* Pop OP_WRITE ptr->right from the stack of variable uses */
16479 pop_triple(stacks, var, RHS(ptr, 0));
16480 release_triple(state, ptr);
16481 continue;
16483 if (ptr->op == OP_PHI) {
16484 struct triple *var;
16485 var = MISC(ptr, 0);
16486 /* Pop OP_WRITE ptr->right from the stack of variable uses */
16487 pop_triple(stacks, var, ptr);
16489 last = ptr;
16491 block->last = last;
16494 static void rename_variables(struct compile_state *state)
16496 struct stack *stacks;
16497 int auto_vars;
16499 /* Allocate stacks for the Variables */
16500 auto_vars = count_auto_vars(state);
16501 stacks = xcmalloc(sizeof(stacks[0])*(auto_vars + 1), "auto var stacks");
16503 /* Give each auto_var a stack */
16504 number_auto_vars(state, stacks);
16506 /* Rename the variables */
16507 rename_block_variables(state, stacks, state->bb.first_block);
16509 /* Remove the stacks from the auto_vars */
16510 restore_auto_vars(state, stacks);
16511 xfree(stacks);
16514 static void prune_block_variables(struct compile_state *state,
16515 struct block *block)
16517 struct block_set *user;
16518 struct triple *next, *ptr;
16519 int done;
16521 done = 0;
16522 for(ptr = block->first; !done; ptr = next) {
16523 /* Be extremely careful I am deleting the list
16524 * as I walk trhough it.
16526 next = ptr->next;
16527 if (ptr == block->last) {
16528 done = 1;
16530 if (triple_is_auto_var(state, ptr)) {
16531 struct triple_set *user, *next;
16532 for(user = ptr->use; user; user = next) {
16533 struct triple *use;
16534 next = user->next;
16535 use = user->member;
16536 if (MISC(ptr, 0) == user->member) {
16537 continue;
16539 if (use->op != OP_PHI) {
16540 internal_error(state, use, "decl still used");
16542 if (MISC(use, 0) != ptr) {
16543 internal_error(state, use, "bad phi use of decl");
16545 unuse_triple(ptr, use);
16546 MISC(use, 0) = 0;
16548 if ((ptr->u.cval == 0) && (MISC(ptr, 0)->lhs == 1)) {
16549 /* Delete the adecl */
16550 release_triple(state, MISC(ptr, 0));
16551 /* And the piece */
16552 release_triple(state, ptr);
16554 continue;
16557 for(user = block->idominates; user; user = user->next) {
16558 prune_block_variables(state, user->member);
16562 struct phi_triple {
16563 struct triple *phi;
16564 unsigned orig_id;
16565 int alive;
16568 static void keep_phi(struct compile_state *state, struct phi_triple *live, struct triple *phi)
16570 struct triple **slot;
16571 int zrhs, i;
16572 if (live[phi->id].alive) {
16573 return;
16575 live[phi->id].alive = 1;
16576 zrhs = phi->rhs;
16577 slot = &RHS(phi, 0);
16578 for(i = 0; i < zrhs; i++) {
16579 struct triple *used;
16580 used = slot[i];
16581 if (used && (used->op == OP_PHI)) {
16582 keep_phi(state, live, used);
16587 static void prune_unused_phis(struct compile_state *state)
16589 struct triple *first, *phi;
16590 struct phi_triple *live;
16591 int phis, i;
16593 /* Find the first instruction */
16594 first = state->first;
16596 /* Count how many phi functions I need to process */
16597 phis = 0;
16598 for(phi = first->next; phi != first; phi = phi->next) {
16599 if (phi->op == OP_PHI) {
16600 phis += 1;
16604 /* Mark them all dead */
16605 live = xcmalloc(sizeof(*live) * (phis + 1), "phi_triple");
16606 phis = 0;
16607 for(phi = first->next; phi != first; phi = phi->next) {
16608 if (phi->op != OP_PHI) {
16609 continue;
16611 live[phis].alive = 0;
16612 live[phis].orig_id = phi->id;
16613 live[phis].phi = phi;
16614 phi->id = phis;
16615 phis += 1;
16618 /* Mark phis alive that are used by non phis */
16619 for(i = 0; i < phis; i++) {
16620 struct triple_set *set;
16621 for(set = live[i].phi->use; !live[i].alive && set; set = set->next) {
16622 if (set->member->op != OP_PHI) {
16623 keep_phi(state, live, live[i].phi);
16624 break;
16629 /* Delete the extraneous phis */
16630 for(i = 0; i < phis; i++) {
16631 struct triple **slot;
16632 int zrhs, j;
16633 if (!live[i].alive) {
16634 release_triple(state, live[i].phi);
16635 continue;
16637 phi = live[i].phi;
16638 slot = &RHS(phi, 0);
16639 zrhs = phi->rhs;
16640 for(j = 0; j < zrhs; j++) {
16641 if(!slot[j]) {
16642 struct triple *unknown;
16643 get_occurrence(phi->occurrence);
16644 unknown = flatten(state, state->global_pool,
16645 alloc_triple(state, OP_UNKNOWNVAL,
16646 phi->type, 0, 0, phi->occurrence));
16647 slot[j] = unknown;
16648 use_triple(unknown, phi);
16649 transform_to_arch_instruction(state, unknown);
16650 #if 0
16651 warning(state, phi, "variable not set at index %d on all paths to use", j);
16652 #endif
16656 xfree(live);
16659 static void transform_to_ssa_form(struct compile_state *state)
16661 insert_phi_operations(state);
16662 rename_variables(state);
16664 prune_block_variables(state, state->bb.first_block);
16665 prune_unused_phis(state);
16667 print_blocks(state, __func__, state->dbgout);
16671 static void clear_vertex(
16672 struct compile_state *state, struct block *block, void *arg)
16674 /* Clear the current blocks vertex and the vertex of all
16675 * of the current blocks neighbors in case there are malformed
16676 * blocks with now instructions at this point.
16678 struct block_set *user, *edge;
16679 block->vertex = 0;
16680 for(edge = block->edges; edge; edge = edge->next) {
16681 edge->member->vertex = 0;
16683 for(user = block->use; user; user = user->next) {
16684 user->member->vertex = 0;
16688 static void mark_live_block(
16689 struct compile_state *state, struct block *block, int *next_vertex)
16691 /* See if this is a block that has not been marked */
16692 if (block->vertex != 0) {
16693 return;
16695 block->vertex = *next_vertex;
16696 *next_vertex += 1;
16697 if (triple_is_branch(state, block->last)) {
16698 struct triple **targ;
16699 targ = triple_edge_targ(state, block->last, 0);
16700 for(; targ; targ = triple_edge_targ(state, block->last, targ)) {
16701 if (!*targ) {
16702 continue;
16704 if (!triple_stores_block(state, *targ)) {
16705 internal_error(state, 0, "bad targ");
16707 mark_live_block(state, (*targ)->u.block, next_vertex);
16709 /* Ensure the last block of a function remains alive */
16710 if (triple_is_call(state, block->last)) {
16711 mark_live_block(state, MISC(block->last, 0)->u.block, next_vertex);
16714 else if (block->last->next != state->first) {
16715 struct triple *ins;
16716 ins = block->last->next;
16717 if (!triple_stores_block(state, ins)) {
16718 internal_error(state, 0, "bad block start");
16720 mark_live_block(state, ins->u.block, next_vertex);
16724 static void transform_from_ssa_form(struct compile_state *state)
16726 /* To get out of ssa form we insert moves on the incoming
16727 * edges to blocks containting phi functions.
16729 struct triple *first;
16730 struct triple *phi, *var, *next;
16731 int next_vertex;
16733 /* Walk the control flow to see which blocks remain alive */
16734 walk_blocks(state, &state->bb, clear_vertex, 0);
16735 next_vertex = 1;
16736 mark_live_block(state, state->bb.first_block, &next_vertex);
16738 /* Walk all of the operations to find the phi functions */
16739 first = state->first;
16740 for(phi = first->next; phi != first ; phi = next) {
16741 struct block_set *set;
16742 struct block *block;
16743 struct triple **slot;
16744 struct triple *var;
16745 struct triple_set *use, *use_next;
16746 int edge, writers, readers;
16747 next = phi->next;
16748 if (phi->op != OP_PHI) {
16749 continue;
16752 block = phi->u.block;
16753 slot = &RHS(phi, 0);
16755 /* If this phi is in a dead block just forget it */
16756 if (block->vertex == 0) {
16757 release_triple(state, phi);
16758 continue;
16761 /* Forget uses from code in dead blocks */
16762 for(use = phi->use; use; use = use_next) {
16763 struct block *ublock;
16764 struct triple **expr;
16765 use_next = use->next;
16766 ublock = block_of_triple(state, use->member);
16767 if ((use->member == phi) || (ublock->vertex != 0)) {
16768 continue;
16770 expr = triple_rhs(state, use->member, 0);
16771 for(; expr; expr = triple_rhs(state, use->member, expr)) {
16772 if (*expr == phi) {
16773 *expr = 0;
16776 unuse_triple(phi, use->member);
16778 /* A variable to replace the phi function */
16779 if (registers_of(state, phi->type) != 1) {
16780 internal_error(state, phi, "phi->type does not fit in a single register!");
16782 var = post_triple(state, phi, OP_ADECL, phi->type, 0, 0);
16783 var = var->next; /* point at the var */
16785 /* Replaces use of phi with var */
16786 propagate_use(state, phi, var);
16788 /* Count the readers */
16789 readers = 0;
16790 for(use = var->use; use; use = use->next) {
16791 if (use->member != MISC(var, 0)) {
16792 readers++;
16796 /* Walk all of the incoming edges/blocks and insert moves.
16798 writers = 0;
16799 for(edge = 0, set = block->use; set; set = set->next, edge++) {
16800 struct block *eblock, *vblock;
16801 struct triple *move;
16802 struct triple *val, *base;
16803 eblock = set->member;
16804 val = slot[edge];
16805 slot[edge] = 0;
16806 unuse_triple(val, phi);
16807 vblock = block_of_triple(state, val);
16809 /* If we don't have a value that belongs in an OP_WRITE
16810 * continue on.
16812 if (!val || (val == &unknown_triple) || (val == phi)
16813 || (vblock && (vblock->vertex == 0))) {
16814 continue;
16816 /* If the value should never occur error */
16817 if (!vblock) {
16818 internal_error(state, val, "no vblock?");
16819 continue;
16822 /* If the value occurs in a dead block see if a replacement
16823 * block can be found.
16825 while(eblock && (eblock->vertex == 0)) {
16826 eblock = eblock->idom;
16828 /* If not continue on with the next value. */
16829 if (!eblock || (eblock->vertex == 0)) {
16830 continue;
16833 /* If we have an empty incoming block ignore it. */
16834 if (!eblock->first) {
16835 internal_error(state, 0, "empty block?");
16838 /* Make certain the write is placed in the edge block... */
16839 /* Walk through the edge block backwards to find an
16840 * appropriate location for the OP_WRITE.
16842 for(base = eblock->last; base != eblock->first; base = base->prev) {
16843 struct triple **expr;
16844 if (base->op == OP_PIECE) {
16845 base = MISC(base, 0);
16847 if ((base == var) || (base == val)) {
16848 goto out;
16850 expr = triple_lhs(state, base, 0);
16851 for(; expr; expr = triple_lhs(state, base, expr)) {
16852 if ((*expr) == val) {
16853 goto out;
16856 expr = triple_rhs(state, base, 0);
16857 for(; expr; expr = triple_rhs(state, base, expr)) {
16858 if ((*expr) == var) {
16859 goto out;
16863 out:
16864 if (triple_is_branch(state, base)) {
16865 internal_error(state, base,
16866 "Could not insert write to phi");
16868 move = post_triple(state, base, OP_WRITE, var->type, val, var);
16869 use_triple(val, move);
16870 use_triple(var, move);
16871 writers++;
16873 if (!writers && readers) {
16874 internal_error(state, var, "no value written to in use phi?");
16876 /* If var is not used free it */
16877 if (!writers) {
16878 release_triple(state, MISC(var, 0));
16879 release_triple(state, var);
16881 /* Release the phi function */
16882 release_triple(state, phi);
16885 /* Walk all of the operations to find the adecls */
16886 for(var = first->next; var != first ; var = var->next) {
16887 struct triple_set *use, *use_next;
16888 if (!triple_is_auto_var(state, var)) {
16889 continue;
16892 /* Walk through all of the rhs uses of var and
16893 * replace them with read of var.
16895 for(use = var->use; use; use = use_next) {
16896 struct triple *read, *user;
16897 struct triple **slot;
16898 int zrhs, i, used;
16899 use_next = use->next;
16900 user = use->member;
16902 /* Generate a read of var */
16903 read = pre_triple(state, user, OP_READ, var->type, var, 0);
16904 use_triple(var, read);
16906 /* Find the rhs uses and see if they need to be replaced */
16907 used = 0;
16908 zrhs = user->rhs;
16909 slot = &RHS(user, 0);
16910 for(i = 0; i < zrhs; i++) {
16911 if (slot[i] == var) {
16912 slot[i] = read;
16913 used = 1;
16916 /* If we did use it cleanup the uses */
16917 if (used) {
16918 unuse_triple(var, user);
16919 use_triple(read, user);
16921 /* If we didn't use it release the extra triple */
16922 else {
16923 release_triple(state, read);
16929 #define HI() if (state->compiler->debug & DEBUG_REBUILD_SSA_FORM) { \
16930 FILE *fp = state->dbgout; \
16931 fprintf(fp, "@ %s:%d\n", __FILE__, __LINE__); romcc_print_blocks(state, fp); \
16934 static void rebuild_ssa_form(struct compile_state *state)
16936 HI();
16937 transform_from_ssa_form(state);
16938 HI();
16939 state->bb.first = state->first;
16940 free_basic_blocks(state, &state->bb);
16941 analyze_basic_blocks(state, &state->bb);
16942 HI();
16943 insert_phi_operations(state);
16944 HI();
16945 rename_variables(state);
16946 HI();
16948 prune_block_variables(state, state->bb.first_block);
16949 HI();
16950 prune_unused_phis(state);
16951 HI();
16953 #undef HI
16956 * Register conflict resolution
16957 * =========================================================
16960 static struct reg_info find_def_color(
16961 struct compile_state *state, struct triple *def)
16963 struct triple_set *set;
16964 struct reg_info info;
16965 info.reg = REG_UNSET;
16966 info.regcm = 0;
16967 if (!triple_is_def(state, def)) {
16968 return info;
16970 info = arch_reg_lhs(state, def, 0);
16971 if (info.reg >= MAX_REGISTERS) {
16972 info.reg = REG_UNSET;
16974 for(set = def->use; set; set = set->next) {
16975 struct reg_info tinfo;
16976 int i;
16977 i = find_rhs_use(state, set->member, def);
16978 if (i < 0) {
16979 continue;
16981 tinfo = arch_reg_rhs(state, set->member, i);
16982 if (tinfo.reg >= MAX_REGISTERS) {
16983 tinfo.reg = REG_UNSET;
16985 if ((tinfo.reg != REG_UNSET) &&
16986 (info.reg != REG_UNSET) &&
16987 (tinfo.reg != info.reg)) {
16988 internal_error(state, def, "register conflict");
16990 if ((info.regcm & tinfo.regcm) == 0) {
16991 internal_error(state, def, "regcm conflict %x & %x == 0",
16992 info.regcm, tinfo.regcm);
16994 if (info.reg == REG_UNSET) {
16995 info.reg = tinfo.reg;
16997 info.regcm &= tinfo.regcm;
16999 if (info.reg >= MAX_REGISTERS) {
17000 internal_error(state, def, "register out of range");
17002 return info;
17005 static struct reg_info find_lhs_pre_color(
17006 struct compile_state *state, struct triple *ins, int index)
17008 struct reg_info info;
17009 int zlhs, zrhs, i;
17010 zrhs = ins->rhs;
17011 zlhs = ins->lhs;
17012 if (!zlhs && triple_is_def(state, ins)) {
17013 zlhs = 1;
17015 if (index >= zlhs) {
17016 internal_error(state, ins, "Bad lhs %d", index);
17018 info = arch_reg_lhs(state, ins, index);
17019 for(i = 0; i < zrhs; i++) {
17020 struct reg_info rinfo;
17021 rinfo = arch_reg_rhs(state, ins, i);
17022 if ((info.reg == rinfo.reg) &&
17023 (rinfo.reg >= MAX_REGISTERS)) {
17024 struct reg_info tinfo;
17025 tinfo = find_lhs_pre_color(state, RHS(ins, index), 0);
17026 info.reg = tinfo.reg;
17027 info.regcm &= tinfo.regcm;
17028 break;
17031 if (info.reg >= MAX_REGISTERS) {
17032 info.reg = REG_UNSET;
17034 return info;
17037 static struct reg_info find_rhs_post_color(
17038 struct compile_state *state, struct triple *ins, int index);
17040 static struct reg_info find_lhs_post_color(
17041 struct compile_state *state, struct triple *ins, int index)
17043 struct triple_set *set;
17044 struct reg_info info;
17045 struct triple *lhs;
17046 #if DEBUG_TRIPLE_COLOR
17047 fprintf(state->errout, "find_lhs_post_color(%p, %d)\n",
17048 ins, index);
17049 #endif
17050 if ((index == 0) && triple_is_def(state, ins)) {
17051 lhs = ins;
17053 else if (index < ins->lhs) {
17054 lhs = LHS(ins, index);
17056 else {
17057 internal_error(state, ins, "Bad lhs %d", index);
17058 lhs = 0;
17060 info = arch_reg_lhs(state, ins, index);
17061 if (info.reg >= MAX_REGISTERS) {
17062 info.reg = REG_UNSET;
17064 for(set = lhs->use; set; set = set->next) {
17065 struct reg_info rinfo;
17066 struct triple *user;
17067 int zrhs, i;
17068 user = set->member;
17069 zrhs = user->rhs;
17070 for(i = 0; i < zrhs; i++) {
17071 if (RHS(user, i) != lhs) {
17072 continue;
17074 rinfo = find_rhs_post_color(state, user, i);
17075 if ((info.reg != REG_UNSET) &&
17076 (rinfo.reg != REG_UNSET) &&
17077 (info.reg != rinfo.reg)) {
17078 internal_error(state, ins, "register conflict");
17080 if ((info.regcm & rinfo.regcm) == 0) {
17081 internal_error(state, ins, "regcm conflict %x & %x == 0",
17082 info.regcm, rinfo.regcm);
17084 if (info.reg == REG_UNSET) {
17085 info.reg = rinfo.reg;
17087 info.regcm &= rinfo.regcm;
17090 #if DEBUG_TRIPLE_COLOR
17091 fprintf(state->errout, "find_lhs_post_color(%p, %d) -> ( %d, %x)\n",
17092 ins, index, info.reg, info.regcm);
17093 #endif
17094 return info;
17097 static struct reg_info find_rhs_post_color(
17098 struct compile_state *state, struct triple *ins, int index)
17100 struct reg_info info, rinfo;
17101 int zlhs, i;
17102 #if DEBUG_TRIPLE_COLOR
17103 fprintf(state->errout, "find_rhs_post_color(%p, %d)\n",
17104 ins, index);
17105 #endif
17106 rinfo = arch_reg_rhs(state, ins, index);
17107 zlhs = ins->lhs;
17108 if (!zlhs && triple_is_def(state, ins)) {
17109 zlhs = 1;
17111 info = rinfo;
17112 if (info.reg >= MAX_REGISTERS) {
17113 info.reg = REG_UNSET;
17115 for(i = 0; i < zlhs; i++) {
17116 struct reg_info linfo;
17117 linfo = arch_reg_lhs(state, ins, i);
17118 if ((linfo.reg == rinfo.reg) &&
17119 (linfo.reg >= MAX_REGISTERS)) {
17120 struct reg_info tinfo;
17121 tinfo = find_lhs_post_color(state, ins, i);
17122 if (tinfo.reg >= MAX_REGISTERS) {
17123 tinfo.reg = REG_UNSET;
17125 info.regcm &= linfo.regcm;
17126 info.regcm &= tinfo.regcm;
17127 if (info.reg != REG_UNSET) {
17128 internal_error(state, ins, "register conflict");
17130 if (info.regcm == 0) {
17131 internal_error(state, ins, "regcm conflict");
17133 info.reg = tinfo.reg;
17136 #if DEBUG_TRIPLE_COLOR
17137 fprintf(state->errout, "find_rhs_post_color(%p, %d) -> ( %d, %x)\n",
17138 ins, index, info.reg, info.regcm);
17139 #endif
17140 return info;
17143 static struct reg_info find_lhs_color(
17144 struct compile_state *state, struct triple *ins, int index)
17146 struct reg_info pre, post, info;
17147 #if DEBUG_TRIPLE_COLOR
17148 fprintf(state->errout, "find_lhs_color(%p, %d)\n",
17149 ins, index);
17150 #endif
17151 pre = find_lhs_pre_color(state, ins, index);
17152 post = find_lhs_post_color(state, ins, index);
17153 if ((pre.reg != post.reg) &&
17154 (pre.reg != REG_UNSET) &&
17155 (post.reg != REG_UNSET)) {
17156 internal_error(state, ins, "register conflict");
17158 info.regcm = pre.regcm & post.regcm;
17159 info.reg = pre.reg;
17160 if (info.reg == REG_UNSET) {
17161 info.reg = post.reg;
17163 #if DEBUG_TRIPLE_COLOR
17164 fprintf(state->errout, "find_lhs_color(%p, %d) -> ( %d, %x) ... (%d, %x) (%d, %x)\n",
17165 ins, index, info.reg, info.regcm,
17166 pre.reg, pre.regcm, post.reg, post.regcm);
17167 #endif
17168 return info;
17171 static struct triple *post_copy(struct compile_state *state, struct triple *ins)
17173 struct triple_set *entry, *next;
17174 struct triple *out;
17175 struct reg_info info, rinfo;
17177 info = arch_reg_lhs(state, ins, 0);
17178 out = post_triple(state, ins, OP_COPY, ins->type, ins, 0);
17179 use_triple(RHS(out, 0), out);
17180 /* Get the users of ins to use out instead */
17181 for(entry = ins->use; entry; entry = next) {
17182 int i;
17183 next = entry->next;
17184 if (entry->member == out) {
17185 continue;
17187 i = find_rhs_use(state, entry->member, ins);
17188 if (i < 0) {
17189 continue;
17191 rinfo = arch_reg_rhs(state, entry->member, i);
17192 if ((info.reg == REG_UNNEEDED) && (rinfo.reg == REG_UNNEEDED)) {
17193 continue;
17195 replace_rhs_use(state, ins, out, entry->member);
17197 transform_to_arch_instruction(state, out);
17198 return out;
17201 static struct triple *typed_pre_copy(
17202 struct compile_state *state, struct type *type, struct triple *ins, int index)
17204 /* Carefully insert enough operations so that I can
17205 * enter any operation with a GPR32.
17207 struct triple *in;
17208 struct triple **expr;
17209 unsigned classes;
17210 struct reg_info info;
17211 int op;
17212 if (ins->op == OP_PHI) {
17213 internal_error(state, ins, "pre_copy on a phi?");
17215 classes = arch_type_to_regcm(state, type);
17216 info = arch_reg_rhs(state, ins, index);
17217 expr = &RHS(ins, index);
17218 if ((info.regcm & classes) == 0) {
17219 FILE *fp = state->errout;
17220 fprintf(fp, "src_type: ");
17221 name_of(fp, ins->type);
17222 fprintf(fp, "\ndst_type: ");
17223 name_of(fp, type);
17224 fprintf(fp, "\n");
17225 internal_error(state, ins, "pre_copy with no register classes");
17227 op = OP_COPY;
17228 if (!equiv_types(type, (*expr)->type)) {
17229 op = OP_CONVERT;
17231 in = pre_triple(state, ins, op, type, *expr, 0);
17232 unuse_triple(*expr, ins);
17233 *expr = in;
17234 use_triple(RHS(in, 0), in);
17235 use_triple(in, ins);
17236 transform_to_arch_instruction(state, in);
17237 return in;
17240 static struct triple *pre_copy(
17241 struct compile_state *state, struct triple *ins, int index)
17243 return typed_pre_copy(state, RHS(ins, index)->type, ins, index);
17247 static void insert_copies_to_phi(struct compile_state *state)
17249 /* To get out of ssa form we insert moves on the incoming
17250 * edges to blocks containting phi functions.
17252 struct triple *first;
17253 struct triple *phi;
17255 /* Walk all of the operations to find the phi functions */
17256 first = state->first;
17257 for(phi = first->next; phi != first ; phi = phi->next) {
17258 struct block_set *set;
17259 struct block *block;
17260 struct triple **slot, *copy;
17261 int edge;
17262 if (phi->op != OP_PHI) {
17263 continue;
17265 phi->id |= TRIPLE_FLAG_POST_SPLIT;
17266 block = phi->u.block;
17267 slot = &RHS(phi, 0);
17268 /* Phi's that feed into mandatory live range joins
17269 * cause nasty complications. Insert a copy of
17270 * the phi value so I never have to deal with
17271 * that in the rest of the code.
17273 copy = post_copy(state, phi);
17274 copy->id |= TRIPLE_FLAG_PRE_SPLIT;
17275 /* Walk all of the incoming edges/blocks and insert moves.
17277 for(edge = 0, set = block->use; set; set = set->next, edge++) {
17278 struct block *eblock;
17279 struct triple *move;
17280 struct triple *val;
17281 struct triple *ptr;
17282 eblock = set->member;
17283 val = slot[edge];
17285 if (val == phi) {
17286 continue;
17289 get_occurrence(val->occurrence);
17290 move = build_triple(state, OP_COPY, val->type, val, 0,
17291 val->occurrence);
17292 move->u.block = eblock;
17293 move->id |= TRIPLE_FLAG_PRE_SPLIT;
17294 use_triple(val, move);
17296 slot[edge] = move;
17297 unuse_triple(val, phi);
17298 use_triple(move, phi);
17300 /* Walk up the dominator tree until I have found the appropriate block */
17301 while(eblock && !tdominates(state, val, eblock->last)) {
17302 eblock = eblock->idom;
17304 if (!eblock) {
17305 internal_error(state, phi, "Cannot find block dominated by %p",
17306 val);
17309 /* Walk through the block backwards to find
17310 * an appropriate location for the OP_COPY.
17312 for(ptr = eblock->last; ptr != eblock->first; ptr = ptr->prev) {
17313 struct triple **expr;
17314 if (ptr->op == OP_PIECE) {
17315 ptr = MISC(ptr, 0);
17317 if ((ptr == phi) || (ptr == val)) {
17318 goto out;
17320 expr = triple_lhs(state, ptr, 0);
17321 for(;expr; expr = triple_lhs(state, ptr, expr)) {
17322 if ((*expr) == val) {
17323 goto out;
17326 expr = triple_rhs(state, ptr, 0);
17327 for(;expr; expr = triple_rhs(state, ptr, expr)) {
17328 if ((*expr) == phi) {
17329 goto out;
17333 out:
17334 if (triple_is_branch(state, ptr)) {
17335 internal_error(state, ptr,
17336 "Could not insert write to phi");
17338 insert_triple(state, after_lhs(state, ptr), move);
17339 if (eblock->last == after_lhs(state, ptr)->prev) {
17340 eblock->last = move;
17342 transform_to_arch_instruction(state, move);
17345 print_blocks(state, __func__, state->dbgout);
17348 struct triple_reg_set;
17349 struct reg_block;
17352 static int do_triple_set(struct triple_reg_set **head,
17353 struct triple *member, struct triple *new_member)
17355 struct triple_reg_set **ptr, *new;
17356 if (!member)
17357 return 0;
17358 ptr = head;
17359 while(*ptr) {
17360 if ((*ptr)->member == member) {
17361 return 0;
17363 ptr = &(*ptr)->next;
17365 new = xcmalloc(sizeof(*new), "triple_set");
17366 new->member = member;
17367 new->new = new_member;
17368 new->next = *head;
17369 *head = new;
17370 return 1;
17373 static void do_triple_unset(struct triple_reg_set **head, struct triple *member)
17375 struct triple_reg_set *entry, **ptr;
17376 ptr = head;
17377 while(*ptr) {
17378 entry = *ptr;
17379 if (entry->member == member) {
17380 *ptr = entry->next;
17381 xfree(entry);
17382 return;
17384 else {
17385 ptr = &entry->next;
17390 static int in_triple(struct reg_block *rb, struct triple *in)
17392 return do_triple_set(&rb->in, in, 0);
17395 #if DEBUG_ROMCC_WARNING
17396 static void unin_triple(struct reg_block *rb, struct triple *unin)
17398 do_triple_unset(&rb->in, unin);
17400 #endif
17402 static int out_triple(struct reg_block *rb, struct triple *out)
17404 return do_triple_set(&rb->out, out, 0);
17406 #if DEBUG_ROMCC_WARNING
17407 static void unout_triple(struct reg_block *rb, struct triple *unout)
17409 do_triple_unset(&rb->out, unout);
17411 #endif
17413 static int initialize_regblock(struct reg_block *blocks,
17414 struct block *block, int vertex)
17416 struct block_set *user;
17417 if (!block || (blocks[block->vertex].block == block)) {
17418 return vertex;
17420 vertex += 1;
17421 /* Renumber the blocks in a convenient fashion */
17422 block->vertex = vertex;
17423 blocks[vertex].block = block;
17424 blocks[vertex].vertex = vertex;
17425 for(user = block->use; user; user = user->next) {
17426 vertex = initialize_regblock(blocks, user->member, vertex);
17428 return vertex;
17431 static struct triple *part_to_piece(struct compile_state *state, struct triple *ins)
17433 /* Part to piece is a best attempt and it cannot be correct all by
17434 * itself. If various values are read as different sizes in different
17435 * parts of the code this function cannot work. Or rather it cannot
17436 * work in conjunction with compute_variable_liftimes. As the
17437 * analysis will get confused.
17439 struct triple *base;
17440 unsigned reg;
17441 if (!is_lvalue(state, ins)) {
17442 return ins;
17444 base = 0;
17445 reg = 0;
17446 while(ins && triple_is_part(state, ins) && (ins->op != OP_PIECE)) {
17447 base = MISC(ins, 0);
17448 switch(ins->op) {
17449 case OP_INDEX:
17450 reg += index_reg_offset(state, base->type, ins->u.cval)/REG_SIZEOF_REG;
17451 break;
17452 case OP_DOT:
17453 reg += field_reg_offset(state, base->type, ins->u.field)/REG_SIZEOF_REG;
17454 break;
17455 default:
17456 internal_error(state, ins, "unhandled part");
17457 break;
17459 ins = base;
17461 if (base) {
17462 if (reg > base->lhs) {
17463 internal_error(state, base, "part out of range?");
17465 ins = LHS(base, reg);
17467 return ins;
17470 static int this_def(struct compile_state *state,
17471 struct triple *ins, struct triple *other)
17473 if (ins == other) {
17474 return 1;
17476 if (ins->op == OP_WRITE) {
17477 ins = part_to_piece(state, MISC(ins, 0));
17479 return ins == other;
17482 static int phi_in(struct compile_state *state, struct reg_block *blocks,
17483 struct reg_block *rb, struct block *suc)
17485 /* Read the conditional input set of a successor block
17486 * (i.e. the input to the phi nodes) and place it in the
17487 * current blocks output set.
17489 struct block_set *set;
17490 struct triple *ptr;
17491 int edge;
17492 int done, change;
17493 change = 0;
17494 /* Find the edge I am coming in on */
17495 for(edge = 0, set = suc->use; set; set = set->next, edge++) {
17496 if (set->member == rb->block) {
17497 break;
17500 if (!set) {
17501 internal_error(state, 0, "Not coming on a control edge?");
17503 for(done = 0, ptr = suc->first; !done; ptr = ptr->next) {
17504 struct triple **slot, *expr, *ptr2;
17505 int out_change, done2;
17506 done = (ptr == suc->last);
17507 if (ptr->op != OP_PHI) {
17508 continue;
17510 slot = &RHS(ptr, 0);
17511 expr = slot[edge];
17512 out_change = out_triple(rb, expr);
17513 if (!out_change) {
17514 continue;
17516 /* If we don't define the variable also plast it
17517 * in the current blocks input set.
17519 ptr2 = rb->block->first;
17520 for(done2 = 0; !done2; ptr2 = ptr2->next) {
17521 if (this_def(state, ptr2, expr)) {
17522 break;
17524 done2 = (ptr2 == rb->block->last);
17526 if (!done2) {
17527 continue;
17529 change |= in_triple(rb, expr);
17531 return change;
17534 static int reg_in(struct compile_state *state, struct reg_block *blocks,
17535 struct reg_block *rb, struct block *suc)
17537 struct triple_reg_set *in_set;
17538 int change;
17539 change = 0;
17540 /* Read the input set of a successor block
17541 * and place it in the current blocks output set.
17543 in_set = blocks[suc->vertex].in;
17544 for(; in_set; in_set = in_set->next) {
17545 int out_change, done;
17546 struct triple *first, *last, *ptr;
17547 out_change = out_triple(rb, in_set->member);
17548 if (!out_change) {
17549 continue;
17551 /* If we don't define the variable also place it
17552 * in the current blocks input set.
17554 first = rb->block->first;
17555 last = rb->block->last;
17556 done = 0;
17557 for(ptr = first; !done; ptr = ptr->next) {
17558 if (this_def(state, ptr, in_set->member)) {
17559 break;
17561 done = (ptr == last);
17563 if (!done) {
17564 continue;
17566 change |= in_triple(rb, in_set->member);
17568 change |= phi_in(state, blocks, rb, suc);
17569 return change;
17572 static int use_in(struct compile_state *state, struct reg_block *rb)
17574 /* Find the variables we use but don't define and add
17575 * it to the current blocks input set.
17577 #if DEBUG_ROMCC_WARNINGS
17578 #warning "FIXME is this O(N^2) algorithm bad?"
17579 #endif
17580 struct block *block;
17581 struct triple *ptr;
17582 int done;
17583 int change;
17584 block = rb->block;
17585 change = 0;
17586 for(done = 0, ptr = block->last; !done; ptr = ptr->prev) {
17587 struct triple **expr;
17588 done = (ptr == block->first);
17589 /* The variable a phi function uses depends on the
17590 * control flow, and is handled in phi_in, not
17591 * here.
17593 if (ptr->op == OP_PHI) {
17594 continue;
17596 expr = triple_rhs(state, ptr, 0);
17597 for(;expr; expr = triple_rhs(state, ptr, expr)) {
17598 struct triple *rhs, *test;
17599 int tdone;
17600 rhs = part_to_piece(state, *expr);
17601 if (!rhs) {
17602 continue;
17605 /* See if rhs is defined in this block.
17606 * A write counts as a definition.
17608 for(tdone = 0, test = ptr; !tdone; test = test->prev) {
17609 tdone = (test == block->first);
17610 if (this_def(state, test, rhs)) {
17611 rhs = 0;
17612 break;
17615 /* If I still have a valid rhs add it to in */
17616 change |= in_triple(rb, rhs);
17619 return change;
17622 static struct reg_block *compute_variable_lifetimes(
17623 struct compile_state *state, struct basic_blocks *bb)
17625 struct reg_block *blocks;
17626 int change;
17627 blocks = xcmalloc(
17628 sizeof(*blocks)*(bb->last_vertex + 1), "reg_block");
17629 initialize_regblock(blocks, bb->last_block, 0);
17630 do {
17631 int i;
17632 change = 0;
17633 for(i = 1; i <= bb->last_vertex; i++) {
17634 struct block_set *edge;
17635 struct reg_block *rb;
17636 rb = &blocks[i];
17637 /* Add the all successor's input set to in */
17638 for(edge = rb->block->edges; edge; edge = edge->next) {
17639 change |= reg_in(state, blocks, rb, edge->member);
17641 /* Add use to in... */
17642 change |= use_in(state, rb);
17644 } while(change);
17645 return blocks;
17648 static void free_variable_lifetimes(struct compile_state *state,
17649 struct basic_blocks *bb, struct reg_block *blocks)
17651 int i;
17652 /* free in_set && out_set on each block */
17653 for(i = 1; i <= bb->last_vertex; i++) {
17654 struct triple_reg_set *entry, *next;
17655 struct reg_block *rb;
17656 rb = &blocks[i];
17657 for(entry = rb->in; entry ; entry = next) {
17658 next = entry->next;
17659 do_triple_unset(&rb->in, entry->member);
17661 for(entry = rb->out; entry; entry = next) {
17662 next = entry->next;
17663 do_triple_unset(&rb->out, entry->member);
17666 xfree(blocks);
17670 typedef void (*wvl_cb_t)(
17671 struct compile_state *state,
17672 struct reg_block *blocks, struct triple_reg_set *live,
17673 struct reg_block *rb, struct triple *ins, void *arg);
17675 static void walk_variable_lifetimes(struct compile_state *state,
17676 struct basic_blocks *bb, struct reg_block *blocks,
17677 wvl_cb_t cb, void *arg)
17679 int i;
17681 for(i = 1; i <= state->bb.last_vertex; i++) {
17682 struct triple_reg_set *live;
17683 struct triple_reg_set *entry, *next;
17684 struct triple *ptr, *prev;
17685 struct reg_block *rb;
17686 struct block *block;
17687 int done;
17689 /* Get the blocks */
17690 rb = &blocks[i];
17691 block = rb->block;
17693 /* Copy out into live */
17694 live = 0;
17695 for(entry = rb->out; entry; entry = next) {
17696 next = entry->next;
17697 do_triple_set(&live, entry->member, entry->new);
17699 /* Walk through the basic block calculating live */
17700 for(done = 0, ptr = block->last; !done; ptr = prev) {
17701 struct triple **expr;
17703 prev = ptr->prev;
17704 done = (ptr == block->first);
17706 /* Ensure the current definition is in live */
17707 if (triple_is_def(state, ptr)) {
17708 do_triple_set(&live, ptr, 0);
17711 /* Inform the callback function of what is
17712 * going on.
17714 cb(state, blocks, live, rb, ptr, arg);
17716 /* Remove the current definition from live */
17717 do_triple_unset(&live, ptr);
17719 /* Add the current uses to live.
17721 * It is safe to skip phi functions because they do
17722 * not have any block local uses, and the block
17723 * output sets already properly account for what
17724 * control flow depedent uses phi functions do have.
17726 if (ptr->op == OP_PHI) {
17727 continue;
17729 expr = triple_rhs(state, ptr, 0);
17730 for(;expr; expr = triple_rhs(state, ptr, expr)) {
17731 /* If the triple is not a definition skip it. */
17732 if (!*expr || !triple_is_def(state, *expr)) {
17733 continue;
17735 do_triple_set(&live, *expr, 0);
17738 /* Free live */
17739 for(entry = live; entry; entry = next) {
17740 next = entry->next;
17741 do_triple_unset(&live, entry->member);
17746 struct print_live_variable_info {
17747 struct reg_block *rb;
17748 FILE *fp;
17750 #if DEBUG_EXPLICIT_CLOSURES
17751 static void print_live_variables_block(
17752 struct compile_state *state, struct block *block, void *arg)
17755 struct print_live_variable_info *info = arg;
17756 struct block_set *edge;
17757 FILE *fp = info->fp;
17758 struct reg_block *rb;
17759 struct triple *ptr;
17760 int phi_present;
17761 int done;
17762 rb = &info->rb[block->vertex];
17764 fprintf(fp, "\nblock: %p (%d),",
17765 block, block->vertex);
17766 for(edge = block->edges; edge; edge = edge->next) {
17767 fprintf(fp, " %p<-%p",
17768 edge->member,
17769 edge->member && edge->member->use?edge->member->use->member : 0);
17771 fprintf(fp, "\n");
17772 if (rb->in) {
17773 struct triple_reg_set *in_set;
17774 fprintf(fp, " in:");
17775 for(in_set = rb->in; in_set; in_set = in_set->next) {
17776 fprintf(fp, " %-10p", in_set->member);
17778 fprintf(fp, "\n");
17780 phi_present = 0;
17781 for(done = 0, ptr = block->first; !done; ptr = ptr->next) {
17782 done = (ptr == block->last);
17783 if (ptr->op == OP_PHI) {
17784 phi_present = 1;
17785 break;
17788 if (phi_present) {
17789 int edge;
17790 for(edge = 0; edge < block->users; edge++) {
17791 fprintf(fp, " in(%d):", edge);
17792 for(done = 0, ptr = block->first; !done; ptr = ptr->next) {
17793 struct triple **slot;
17794 done = (ptr == block->last);
17795 if (ptr->op != OP_PHI) {
17796 continue;
17798 slot = &RHS(ptr, 0);
17799 fprintf(fp, " %-10p", slot[edge]);
17801 fprintf(fp, "\n");
17804 if (block->first->op == OP_LABEL) {
17805 fprintf(fp, "%p:\n", block->first);
17807 for(done = 0, ptr = block->first; !done; ptr = ptr->next) {
17808 done = (ptr == block->last);
17809 display_triple(fp, ptr);
17811 if (rb->out) {
17812 struct triple_reg_set *out_set;
17813 fprintf(fp, " out:");
17814 for(out_set = rb->out; out_set; out_set = out_set->next) {
17815 fprintf(fp, " %-10p", out_set->member);
17817 fprintf(fp, "\n");
17819 fprintf(fp, "\n");
17822 static void print_live_variables(struct compile_state *state,
17823 struct basic_blocks *bb, struct reg_block *rb, FILE *fp)
17825 struct print_live_variable_info info;
17826 info.rb = rb;
17827 info.fp = fp;
17828 fprintf(fp, "\nlive variables by block\n");
17829 walk_blocks(state, bb, print_live_variables_block, &info);
17832 #endif
17834 static int count_triples(struct compile_state *state)
17836 struct triple *first, *ins;
17837 int triples = 0;
17838 first = state->first;
17839 ins = first;
17840 do {
17841 triples++;
17842 ins = ins->next;
17843 } while (ins != first);
17844 return triples;
17848 struct dead_triple {
17849 struct triple *triple;
17850 struct dead_triple *work_next;
17851 struct block *block;
17852 int old_id;
17853 int flags;
17854 #define TRIPLE_FLAG_ALIVE 1
17855 #define TRIPLE_FLAG_FREE 1
17858 static void print_dead_triples(struct compile_state *state,
17859 struct dead_triple *dtriple)
17861 struct triple *first, *ins;
17862 struct dead_triple *dt;
17863 FILE *fp;
17864 if (!(state->compiler->debug & DEBUG_TRIPLES)) {
17865 return;
17867 fp = state->dbgout;
17868 fprintf(fp, "--------------- dtriples ---------------\n");
17869 first = state->first;
17870 ins = first;
17871 do {
17872 dt = &dtriple[ins->id];
17873 if ((ins->op == OP_LABEL) && (ins->use)) {
17874 fprintf(fp, "\n%p:\n", ins);
17876 fprintf(fp, "%c",
17877 (dt->flags & TRIPLE_FLAG_ALIVE)?' ': '-');
17878 display_triple(fp, ins);
17879 if (triple_is_branch(state, ins)) {
17880 fprintf(fp, "\n");
17882 ins = ins->next;
17883 } while(ins != first);
17884 fprintf(fp, "\n");
17888 static void awaken(
17889 struct compile_state *state,
17890 struct dead_triple *dtriple, struct triple **expr,
17891 struct dead_triple ***work_list_tail)
17893 struct triple *triple;
17894 struct dead_triple *dt;
17895 if (!expr) {
17896 return;
17898 triple = *expr;
17899 if (!triple) {
17900 return;
17902 if (triple->id <= 0) {
17903 internal_error(state, triple, "bad triple id: %d",
17904 triple->id);
17906 if (triple->op == OP_NOOP) {
17907 internal_error(state, triple, "awakening noop?");
17908 return;
17910 dt = &dtriple[triple->id];
17911 if (!(dt->flags & TRIPLE_FLAG_ALIVE)) {
17912 dt->flags |= TRIPLE_FLAG_ALIVE;
17913 if (!dt->work_next) {
17914 **work_list_tail = dt;
17915 *work_list_tail = &dt->work_next;
17920 static void eliminate_inefectual_code(struct compile_state *state)
17922 struct dead_triple *dtriple, *work_list, **work_list_tail, *dt;
17923 int triples, i;
17924 struct triple *first, *ins;
17926 if (!(state->compiler->flags & COMPILER_ELIMINATE_INEFECTUAL_CODE)) {
17927 return;
17930 /* Setup the work list */
17931 work_list = 0;
17932 work_list_tail = &work_list;
17934 first = state->first;
17936 /* Count how many triples I have */
17937 triples = count_triples(state);
17939 /* Now put then in an array and mark all of the triples dead */
17940 dtriple = xcmalloc(sizeof(*dtriple) * (triples + 1), "dtriples");
17942 ins = first;
17943 i = 1;
17944 do {
17945 dtriple[i].triple = ins;
17946 dtriple[i].block = block_of_triple(state, ins);
17947 dtriple[i].flags = 0;
17948 dtriple[i].old_id = ins->id;
17949 ins->id = i;
17950 /* See if it is an operation we always keep */
17951 if (!triple_is_pure(state, ins, dtriple[i].old_id)) {
17952 awaken(state, dtriple, &ins, &work_list_tail);
17954 i++;
17955 ins = ins->next;
17956 } while(ins != first);
17957 while(work_list) {
17958 struct block *block;
17959 struct dead_triple *dt;
17960 struct block_set *user;
17961 struct triple **expr;
17962 dt = work_list;
17963 work_list = dt->work_next;
17964 if (!work_list) {
17965 work_list_tail = &work_list;
17967 /* Make certain the block the current instruction is in lives */
17968 block = block_of_triple(state, dt->triple);
17969 awaken(state, dtriple, &block->first, &work_list_tail);
17970 if (triple_is_branch(state, block->last)) {
17971 awaken(state, dtriple, &block->last, &work_list_tail);
17972 } else {
17973 awaken(state, dtriple, &block->last->next, &work_list_tail);
17976 /* Wake up the data depencencies of this triple */
17977 expr = 0;
17978 do {
17979 expr = triple_rhs(state, dt->triple, expr);
17980 awaken(state, dtriple, expr, &work_list_tail);
17981 } while(expr);
17982 do {
17983 expr = triple_lhs(state, dt->triple, expr);
17984 awaken(state, dtriple, expr, &work_list_tail);
17985 } while(expr);
17986 do {
17987 expr = triple_misc(state, dt->triple, expr);
17988 awaken(state, dtriple, expr, &work_list_tail);
17989 } while(expr);
17990 /* Wake up the forward control dependencies */
17991 do {
17992 expr = triple_targ(state, dt->triple, expr);
17993 awaken(state, dtriple, expr, &work_list_tail);
17994 } while(expr);
17995 /* Wake up the reverse control dependencies of this triple */
17996 for(user = dt->block->ipdomfrontier; user; user = user->next) {
17997 struct triple *last;
17998 last = user->member->last;
17999 while((last->op == OP_NOOP) && (last != user->member->first)) {
18000 #if DEBUG_ROMCC_WARNINGS
18001 #warning "Should we bring the awakening noops back?"
18002 #endif
18003 // internal_warning(state, last, "awakening noop?");
18004 last = last->prev;
18006 awaken(state, dtriple, &last, &work_list_tail);
18009 print_dead_triples(state, dtriple);
18010 for(dt = &dtriple[1]; dt <= &dtriple[triples]; dt++) {
18011 if ((dt->triple->op == OP_NOOP) &&
18012 (dt->flags & TRIPLE_FLAG_ALIVE)) {
18013 internal_error(state, dt->triple, "noop effective?");
18015 dt->triple->id = dt->old_id; /* Restore the color */
18016 if (!(dt->flags & TRIPLE_FLAG_ALIVE)) {
18017 release_triple(state, dt->triple);
18020 xfree(dtriple);
18022 rebuild_ssa_form(state);
18024 print_blocks(state, __func__, state->dbgout);
18028 static void insert_mandatory_copies(struct compile_state *state)
18030 struct triple *ins, *first;
18032 /* The object is with a minimum of inserted copies,
18033 * to resolve in fundamental register conflicts between
18034 * register value producers and consumers.
18035 * Theoretically we may be greater than minimal when we
18036 * are inserting copies before instructions but that
18037 * case should be rare.
18039 first = state->first;
18040 ins = first;
18041 do {
18042 struct triple_set *entry, *next;
18043 struct triple *tmp;
18044 struct reg_info info;
18045 unsigned reg, regcm;
18046 int do_post_copy, do_pre_copy;
18047 tmp = 0;
18048 if (!triple_is_def(state, ins)) {
18049 goto next;
18051 /* Find the architecture specific color information */
18052 info = find_lhs_pre_color(state, ins, 0);
18053 if (info.reg >= MAX_REGISTERS) {
18054 info.reg = REG_UNSET;
18057 reg = REG_UNSET;
18058 regcm = arch_type_to_regcm(state, ins->type);
18059 do_pre_copy = 0;
18061 /* Walk through the uses of ins and check for conflicts */
18062 for(entry = ins->use; entry; entry = next) {
18063 struct reg_info rinfo;
18064 int i;
18065 next = entry->next;
18066 i = find_rhs_use(state, entry->member, ins);
18067 if (i < 0) {
18068 continue;
18071 /* Find the users color requirements */
18072 rinfo = arch_reg_rhs(state, entry->member, i);
18073 if (rinfo.reg >= MAX_REGISTERS) {
18074 rinfo.reg = REG_UNSET;
18077 /* See if I need a pre_copy */
18078 if (rinfo.reg != REG_UNSET) {
18079 if ((reg != REG_UNSET) && (reg != rinfo.reg)) {
18080 do_pre_copy = 1;
18082 reg = rinfo.reg;
18084 regcm &= rinfo.regcm;
18085 regcm = arch_regcm_normalize(state, regcm);
18086 if (regcm == 0) {
18087 do_pre_copy = 1;
18089 /* Always use pre_copies for constants.
18090 * They do not take up any registers until a
18091 * copy places them in one.
18093 if ((info.reg == REG_UNNEEDED) &&
18094 (rinfo.reg != REG_UNNEEDED)) {
18095 do_pre_copy = 1;
18098 do_post_copy =
18099 !do_pre_copy &&
18100 (((info.reg != REG_UNSET) &&
18101 (reg != REG_UNSET) &&
18102 (info.reg != reg)) ||
18103 ((info.regcm & regcm) == 0));
18105 reg = info.reg;
18106 regcm = info.regcm;
18107 /* Walk through the uses of ins and do a pre_copy or see if a post_copy is warranted */
18108 for(entry = ins->use; entry; entry = next) {
18109 struct reg_info rinfo;
18110 int i;
18111 next = entry->next;
18112 i = find_rhs_use(state, entry->member, ins);
18113 if (i < 0) {
18114 continue;
18117 /* Find the users color requirements */
18118 rinfo = arch_reg_rhs(state, entry->member, i);
18119 if (rinfo.reg >= MAX_REGISTERS) {
18120 rinfo.reg = REG_UNSET;
18123 /* Now see if it is time to do the pre_copy */
18124 if (rinfo.reg != REG_UNSET) {
18125 if (((reg != REG_UNSET) && (reg != rinfo.reg)) ||
18126 ((regcm & rinfo.regcm) == 0) ||
18127 /* Don't let a mandatory coalesce sneak
18128 * into a operation that is marked to prevent
18129 * coalescing.
18131 ((reg != REG_UNNEEDED) &&
18132 ((ins->id & TRIPLE_FLAG_POST_SPLIT) ||
18133 (entry->member->id & TRIPLE_FLAG_PRE_SPLIT)))
18135 if (do_pre_copy) {
18136 struct triple *user;
18137 user = entry->member;
18138 if (RHS(user, i) != ins) {
18139 internal_error(state, user, "bad rhs");
18141 tmp = pre_copy(state, user, i);
18142 tmp->id |= TRIPLE_FLAG_PRE_SPLIT;
18143 continue;
18144 } else {
18145 do_post_copy = 1;
18148 reg = rinfo.reg;
18150 if ((regcm & rinfo.regcm) == 0) {
18151 if (do_pre_copy) {
18152 struct triple *user;
18153 user = entry->member;
18154 if (RHS(user, i) != ins) {
18155 internal_error(state, user, "bad rhs");
18157 tmp = pre_copy(state, user, i);
18158 tmp->id |= TRIPLE_FLAG_PRE_SPLIT;
18159 continue;
18160 } else {
18161 do_post_copy = 1;
18164 regcm &= rinfo.regcm;
18167 if (do_post_copy) {
18168 struct reg_info pre, post;
18169 tmp = post_copy(state, ins);
18170 tmp->id |= TRIPLE_FLAG_PRE_SPLIT;
18171 pre = arch_reg_lhs(state, ins, 0);
18172 post = arch_reg_lhs(state, tmp, 0);
18173 if ((pre.reg == post.reg) && (pre.regcm == post.regcm)) {
18174 internal_error(state, tmp, "useless copy");
18177 next:
18178 ins = ins->next;
18179 } while(ins != first);
18181 print_blocks(state, __func__, state->dbgout);
18185 struct live_range_edge;
18186 struct live_range_def;
18187 struct live_range {
18188 struct live_range_edge *edges;
18189 struct live_range_def *defs;
18190 /* Note. The list pointed to by defs is kept in order.
18191 * That is baring splits in the flow control
18192 * defs dominates defs->next wich dominates defs->next->next
18193 * etc.
18195 unsigned color;
18196 unsigned classes;
18197 unsigned degree;
18198 unsigned length;
18199 struct live_range *group_next, **group_prev;
18202 struct live_range_edge {
18203 struct live_range_edge *next;
18204 struct live_range *node;
18207 struct live_range_def {
18208 struct live_range_def *next;
18209 struct live_range_def *prev;
18210 struct live_range *lr;
18211 struct triple *def;
18212 unsigned orig_id;
18215 #define LRE_HASH_SIZE 2048
18216 struct lre_hash {
18217 struct lre_hash *next;
18218 struct live_range *left;
18219 struct live_range *right;
18223 struct reg_state {
18224 struct lre_hash *hash[LRE_HASH_SIZE];
18225 struct reg_block *blocks;
18226 struct live_range_def *lrd;
18227 struct live_range *lr;
18228 struct live_range *low, **low_tail;
18229 struct live_range *high, **high_tail;
18230 unsigned defs;
18231 unsigned ranges;
18232 int passes, max_passes;
18236 struct print_interference_block_info {
18237 struct reg_state *rstate;
18238 FILE *fp;
18239 int need_edges;
18241 static void print_interference_block(
18242 struct compile_state *state, struct block *block, void *arg)
18245 struct print_interference_block_info *info = arg;
18246 struct reg_state *rstate = info->rstate;
18247 struct block_set *edge;
18248 FILE *fp = info->fp;
18249 struct reg_block *rb;
18250 struct triple *ptr;
18251 int phi_present;
18252 int done;
18253 rb = &rstate->blocks[block->vertex];
18255 fprintf(fp, "\nblock: %p (%d),",
18256 block, block->vertex);
18257 for(edge = block->edges; edge; edge = edge->next) {
18258 fprintf(fp, " %p<-%p",
18259 edge->member,
18260 edge->member && edge->member->use?edge->member->use->member : 0);
18262 fprintf(fp, "\n");
18263 if (rb->in) {
18264 struct triple_reg_set *in_set;
18265 fprintf(fp, " in:");
18266 for(in_set = rb->in; in_set; in_set = in_set->next) {
18267 fprintf(fp, " %-10p", in_set->member);
18269 fprintf(fp, "\n");
18271 phi_present = 0;
18272 for(done = 0, ptr = block->first; !done; ptr = ptr->next) {
18273 done = (ptr == block->last);
18274 if (ptr->op == OP_PHI) {
18275 phi_present = 1;
18276 break;
18279 if (phi_present) {
18280 int edge;
18281 for(edge = 0; edge < block->users; edge++) {
18282 fprintf(fp, " in(%d):", edge);
18283 for(done = 0, ptr = block->first; !done; ptr = ptr->next) {
18284 struct triple **slot;
18285 done = (ptr == block->last);
18286 if (ptr->op != OP_PHI) {
18287 continue;
18289 slot = &RHS(ptr, 0);
18290 fprintf(fp, " %-10p", slot[edge]);
18292 fprintf(fp, "\n");
18295 if (block->first->op == OP_LABEL) {
18296 fprintf(fp, "%p:\n", block->first);
18298 for(done = 0, ptr = block->first; !done; ptr = ptr->next) {
18299 struct live_range *lr;
18300 unsigned id;
18301 done = (ptr == block->last);
18302 lr = rstate->lrd[ptr->id].lr;
18304 id = ptr->id;
18305 ptr->id = rstate->lrd[id].orig_id;
18306 SET_REG(ptr->id, lr->color);
18307 display_triple(fp, ptr);
18308 ptr->id = id;
18310 if (triple_is_def(state, ptr) && (lr->defs == 0)) {
18311 internal_error(state, ptr, "lr has no defs!");
18313 if (info->need_edges) {
18314 if (lr->defs) {
18315 struct live_range_def *lrd;
18316 fprintf(fp, " range:");
18317 lrd = lr->defs;
18318 do {
18319 fprintf(fp, " %-10p", lrd->def);
18320 lrd = lrd->next;
18321 } while(lrd != lr->defs);
18322 fprintf(fp, "\n");
18324 if (lr->edges > 0) {
18325 struct live_range_edge *edge;
18326 fprintf(fp, " edges:");
18327 for(edge = lr->edges; edge; edge = edge->next) {
18328 struct live_range_def *lrd;
18329 lrd = edge->node->defs;
18330 do {
18331 fprintf(fp, " %-10p", lrd->def);
18332 lrd = lrd->next;
18333 } while(lrd != edge->node->defs);
18334 fprintf(fp, "|");
18336 fprintf(fp, "\n");
18339 /* Do a bunch of sanity checks */
18340 valid_ins(state, ptr);
18341 if (ptr->id > rstate->defs) {
18342 internal_error(state, ptr, "Invalid triple id: %d",
18343 ptr->id);
18346 if (rb->out) {
18347 struct triple_reg_set *out_set;
18348 fprintf(fp, " out:");
18349 for(out_set = rb->out; out_set; out_set = out_set->next) {
18350 fprintf(fp, " %-10p", out_set->member);
18352 fprintf(fp, "\n");
18354 fprintf(fp, "\n");
18357 static void print_interference_blocks(
18358 struct compile_state *state, struct reg_state *rstate, FILE *fp, int need_edges)
18360 struct print_interference_block_info info;
18361 info.rstate = rstate;
18362 info.fp = fp;
18363 info.need_edges = need_edges;
18364 fprintf(fp, "\nlive variables by block\n");
18365 walk_blocks(state, &state->bb, print_interference_block, &info);
18369 static unsigned regc_max_size(struct compile_state *state, int classes)
18371 unsigned max_size;
18372 int i;
18373 max_size = 0;
18374 for(i = 0; i < MAX_REGC; i++) {
18375 if (classes & (1 << i)) {
18376 unsigned size;
18377 size = arch_regc_size(state, i);
18378 if (size > max_size) {
18379 max_size = size;
18383 return max_size;
18386 static int reg_is_reg(struct compile_state *state, int reg1, int reg2)
18388 unsigned equivs[MAX_REG_EQUIVS];
18389 int i;
18390 if ((reg1 < 0) || (reg1 >= MAX_REGISTERS)) {
18391 internal_error(state, 0, "invalid register");
18393 if ((reg2 < 0) || (reg2 >= MAX_REGISTERS)) {
18394 internal_error(state, 0, "invalid register");
18396 arch_reg_equivs(state, equivs, reg1);
18397 for(i = 0; (i < MAX_REG_EQUIVS) && equivs[i] != REG_UNSET; i++) {
18398 if (equivs[i] == reg2) {
18399 return 1;
18402 return 0;
18405 static void reg_fill_used(struct compile_state *state, char *used, int reg)
18407 unsigned equivs[MAX_REG_EQUIVS];
18408 int i;
18409 if (reg == REG_UNNEEDED) {
18410 return;
18412 arch_reg_equivs(state, equivs, reg);
18413 for(i = 0; (i < MAX_REG_EQUIVS) && equivs[i] != REG_UNSET; i++) {
18414 used[equivs[i]] = 1;
18416 return;
18419 static void reg_inc_used(struct compile_state *state, char *used, int reg)
18421 unsigned equivs[MAX_REG_EQUIVS];
18422 int i;
18423 if (reg == REG_UNNEEDED) {
18424 return;
18426 arch_reg_equivs(state, equivs, reg);
18427 for(i = 0; (i < MAX_REG_EQUIVS) && equivs[i] != REG_UNSET; i++) {
18428 used[equivs[i]] += 1;
18430 return;
18433 static unsigned int hash_live_edge(
18434 struct live_range *left, struct live_range *right)
18436 unsigned int hash, val;
18437 unsigned long lval, rval;
18438 lval = ((unsigned long)left)/sizeof(struct live_range);
18439 rval = ((unsigned long)right)/sizeof(struct live_range);
18440 hash = 0;
18441 while(lval) {
18442 val = lval & 0xff;
18443 lval >>= 8;
18444 hash = (hash *263) + val;
18446 while(rval) {
18447 val = rval & 0xff;
18448 rval >>= 8;
18449 hash = (hash *263) + val;
18451 hash = hash & (LRE_HASH_SIZE - 1);
18452 return hash;
18455 static struct lre_hash **lre_probe(struct reg_state *rstate,
18456 struct live_range *left, struct live_range *right)
18458 struct lre_hash **ptr;
18459 unsigned int index;
18460 /* Ensure left <= right */
18461 if (left > right) {
18462 struct live_range *tmp;
18463 tmp = left;
18464 left = right;
18465 right = tmp;
18467 index = hash_live_edge(left, right);
18469 ptr = &rstate->hash[index];
18470 while(*ptr) {
18471 if (((*ptr)->left == left) && ((*ptr)->right == right)) {
18472 break;
18474 ptr = &(*ptr)->next;
18476 return ptr;
18479 static int interfere(struct reg_state *rstate,
18480 struct live_range *left, struct live_range *right)
18482 struct lre_hash **ptr;
18483 ptr = lre_probe(rstate, left, right);
18484 return ptr && *ptr;
18487 static void add_live_edge(struct reg_state *rstate,
18488 struct live_range *left, struct live_range *right)
18490 /* FIXME the memory allocation overhead is noticeable here... */
18491 struct lre_hash **ptr, *new_hash;
18492 struct live_range_edge *edge;
18494 if (left == right) {
18495 return;
18497 if ((left == &rstate->lr[0]) || (right == &rstate->lr[0])) {
18498 return;
18500 /* Ensure left <= right */
18501 if (left > right) {
18502 struct live_range *tmp;
18503 tmp = left;
18504 left = right;
18505 right = tmp;
18507 ptr = lre_probe(rstate, left, right);
18508 if (*ptr) {
18509 return;
18511 #if 0
18512 fprintf(state->errout, "new_live_edge(%p, %p)\n",
18513 left, right);
18514 #endif
18515 new_hash = xmalloc(sizeof(*new_hash), "lre_hash");
18516 new_hash->next = *ptr;
18517 new_hash->left = left;
18518 new_hash->right = right;
18519 *ptr = new_hash;
18521 edge = xmalloc(sizeof(*edge), "live_range_edge");
18522 edge->next = left->edges;
18523 edge->node = right;
18524 left->edges = edge;
18525 left->degree += 1;
18527 edge = xmalloc(sizeof(*edge), "live_range_edge");
18528 edge->next = right->edges;
18529 edge->node = left;
18530 right->edges = edge;
18531 right->degree += 1;
18534 static void remove_live_edge(struct reg_state *rstate,
18535 struct live_range *left, struct live_range *right)
18537 struct live_range_edge *edge, **ptr;
18538 struct lre_hash **hptr, *entry;
18539 hptr = lre_probe(rstate, left, right);
18540 if (!hptr || !*hptr) {
18541 return;
18543 entry = *hptr;
18544 *hptr = entry->next;
18545 xfree(entry);
18547 for(ptr = &left->edges; *ptr; ptr = &(*ptr)->next) {
18548 edge = *ptr;
18549 if (edge->node == right) {
18550 *ptr = edge->next;
18551 memset(edge, 0, sizeof(*edge));
18552 xfree(edge);
18553 right->degree--;
18554 break;
18557 for(ptr = &right->edges; *ptr; ptr = &(*ptr)->next) {
18558 edge = *ptr;
18559 if (edge->node == left) {
18560 *ptr = edge->next;
18561 memset(edge, 0, sizeof(*edge));
18562 xfree(edge);
18563 left->degree--;
18564 break;
18569 static void remove_live_edges(struct reg_state *rstate, struct live_range *range)
18571 struct live_range_edge *edge, *next;
18572 for(edge = range->edges; edge; edge = next) {
18573 next = edge->next;
18574 remove_live_edge(rstate, range, edge->node);
18578 static void transfer_live_edges(struct reg_state *rstate,
18579 struct live_range *dest, struct live_range *src)
18581 struct live_range_edge *edge, *next;
18582 for(edge = src->edges; edge; edge = next) {
18583 struct live_range *other;
18584 next = edge->next;
18585 other = edge->node;
18586 remove_live_edge(rstate, src, other);
18587 add_live_edge(rstate, dest, other);
18592 /* Interference graph...
18594 * new(n) --- Return a graph with n nodes but no edges.
18595 * add(g,x,y) --- Return a graph including g with an between x and y
18596 * interfere(g, x, y) --- Return true if there exists an edge between the nodes
18597 * x and y in the graph g
18598 * degree(g, x) --- Return the degree of the node x in the graph g
18599 * neighbors(g, x, f) --- Apply function f to each neighbor of node x in the graph g
18601 * Implement with a hash table && a set of adjcency vectors.
18602 * The hash table supports constant time implementations of add and interfere.
18603 * The adjacency vectors support an efficient implementation of neighbors.
18607 * +---------------------------------------------------+
18608 * | +--------------+ |
18609 * v v | |
18610 * renumber -> build graph -> colalesce -> spill_costs -> simplify -> select
18612 * -- In simplify implment optimistic coloring... (No backtracking)
18613 * -- Implement Rematerialization it is the only form of spilling we can perform
18614 * Essentially this means dropping a constant from a register because
18615 * we can regenerate it later.
18617 * --- Very conservative colalescing (don't colalesce just mark the opportunities)
18618 * coalesce at phi points...
18619 * --- Bias coloring if at all possible do the coalesing a compile time.
18624 #if DEBUG_ROMCC_WARNING
18625 static void different_colored(
18626 struct compile_state *state, struct reg_state *rstate,
18627 struct triple *parent, struct triple *ins)
18629 struct live_range *lr;
18630 struct triple **expr;
18631 lr = rstate->lrd[ins->id].lr;
18632 expr = triple_rhs(state, ins, 0);
18633 for(;expr; expr = triple_rhs(state, ins, expr)) {
18634 struct live_range *lr2;
18635 if (!*expr || (*expr == parent) || (*expr == ins)) {
18636 continue;
18638 lr2 = rstate->lrd[(*expr)->id].lr;
18639 if (lr->color == lr2->color) {
18640 internal_error(state, ins, "live range too big");
18644 #endif
18646 static struct live_range *coalesce_ranges(
18647 struct compile_state *state, struct reg_state *rstate,
18648 struct live_range *lr1, struct live_range *lr2)
18650 struct live_range_def *head, *mid1, *mid2, *end, *lrd;
18651 unsigned color;
18652 unsigned classes;
18653 if (lr1 == lr2) {
18654 return lr1;
18656 if (!lr1->defs || !lr2->defs) {
18657 internal_error(state, 0,
18658 "cannot coalese dead live ranges");
18660 if ((lr1->color == REG_UNNEEDED) ||
18661 (lr2->color == REG_UNNEEDED)) {
18662 internal_error(state, 0,
18663 "cannot coalesce live ranges without a possible color");
18665 if ((lr1->color != lr2->color) &&
18666 (lr1->color != REG_UNSET) &&
18667 (lr2->color != REG_UNSET)) {
18668 internal_error(state, lr1->defs->def,
18669 "cannot coalesce live ranges of different colors");
18671 color = lr1->color;
18672 if (color == REG_UNSET) {
18673 color = lr2->color;
18675 classes = lr1->classes & lr2->classes;
18676 if (!classes) {
18677 internal_error(state, lr1->defs->def,
18678 "cannot coalesce live ranges with dissimilar register classes");
18680 if (state->compiler->debug & DEBUG_COALESCING) {
18681 FILE *fp = state->errout;
18682 fprintf(fp, "coalescing:");
18683 lrd = lr1->defs;
18684 do {
18685 fprintf(fp, " %p", lrd->def);
18686 lrd = lrd->next;
18687 } while(lrd != lr1->defs);
18688 fprintf(fp, " |");
18689 lrd = lr2->defs;
18690 do {
18691 fprintf(fp, " %p", lrd->def);
18692 lrd = lrd->next;
18693 } while(lrd != lr2->defs);
18694 fprintf(fp, "\n");
18696 /* If there is a clear dominate live range put it in lr1,
18697 * For purposes of this test phi functions are
18698 * considered dominated by the definitions that feed into
18699 * them.
18701 if ((lr1->defs->prev->def->op == OP_PHI) ||
18702 ((lr2->defs->prev->def->op != OP_PHI) &&
18703 tdominates(state, lr2->defs->def, lr1->defs->def))) {
18704 struct live_range *tmp;
18705 tmp = lr1;
18706 lr1 = lr2;
18707 lr2 = tmp;
18709 #if 0
18710 if (lr1->defs->orig_id & TRIPLE_FLAG_POST_SPLIT) {
18711 fprintf(state->errout, "lr1 post\n");
18713 if (lr1->defs->orig_id & TRIPLE_FLAG_PRE_SPLIT) {
18714 fprintf(state->errout, "lr1 pre\n");
18716 if (lr2->defs->orig_id & TRIPLE_FLAG_POST_SPLIT) {
18717 fprintf(state->errout, "lr2 post\n");
18719 if (lr2->defs->orig_id & TRIPLE_FLAG_PRE_SPLIT) {
18720 fprintf(state->errout, "lr2 pre\n");
18722 #endif
18723 #if 0
18724 fprintf(state->errout, "coalesce color1(%p): %3d color2(%p) %3d\n",
18725 lr1->defs->def,
18726 lr1->color,
18727 lr2->defs->def,
18728 lr2->color);
18729 #endif
18731 /* Append lr2 onto lr1 */
18732 #if DEBUG_ROMCC_WARNINGS
18733 #warning "FIXME should this be a merge instead of a splice?"
18734 #endif
18735 /* This FIXME item applies to the correctness of live_range_end
18736 * and to the necessity of making multiple passes of coalesce_live_ranges.
18737 * A failure to find some coalesce opportunities in coaleace_live_ranges
18738 * does not impact the correct of the compiler just the efficiency with
18739 * which registers are allocated.
18741 head = lr1->defs;
18742 mid1 = lr1->defs->prev;
18743 mid2 = lr2->defs;
18744 end = lr2->defs->prev;
18746 head->prev = end;
18747 end->next = head;
18749 mid1->next = mid2;
18750 mid2->prev = mid1;
18752 /* Fixup the live range in the added live range defs */
18753 lrd = head;
18754 do {
18755 lrd->lr = lr1;
18756 lrd = lrd->next;
18757 } while(lrd != head);
18759 /* Mark lr2 as free. */
18760 lr2->defs = 0;
18761 lr2->color = REG_UNNEEDED;
18762 lr2->classes = 0;
18764 if (!lr1->defs) {
18765 internal_error(state, 0, "lr1->defs == 0 ?");
18768 lr1->color = color;
18769 lr1->classes = classes;
18771 /* Keep the graph in sync by transferring the edges from lr2 to lr1 */
18772 transfer_live_edges(rstate, lr1, lr2);
18774 return lr1;
18777 static struct live_range_def *live_range_head(
18778 struct compile_state *state, struct live_range *lr,
18779 struct live_range_def *last)
18781 struct live_range_def *result;
18782 result = 0;
18783 if (last == 0) {
18784 result = lr->defs;
18786 else if (!tdominates(state, lr->defs->def, last->next->def)) {
18787 result = last->next;
18789 return result;
18792 static struct live_range_def *live_range_end(
18793 struct compile_state *state, struct live_range *lr,
18794 struct live_range_def *last)
18796 struct live_range_def *result;
18797 result = 0;
18798 if (last == 0) {
18799 result = lr->defs->prev;
18801 else if (!tdominates(state, last->prev->def, lr->defs->prev->def)) {
18802 result = last->prev;
18804 return result;
18808 static void initialize_live_ranges(
18809 struct compile_state *state, struct reg_state *rstate)
18811 struct triple *ins, *first;
18812 size_t count, size;
18813 int i, j;
18815 first = state->first;
18816 /* First count how many instructions I have.
18818 count = count_triples(state);
18819 /* Potentially I need one live range definitions for each
18820 * instruction.
18822 rstate->defs = count;
18823 /* Potentially I need one live range for each instruction
18824 * plus an extra for the dummy live range.
18826 rstate->ranges = count + 1;
18827 size = sizeof(rstate->lrd[0]) * rstate->defs;
18828 rstate->lrd = xcmalloc(size, "live_range_def");
18829 size = sizeof(rstate->lr[0]) * rstate->ranges;
18830 rstate->lr = xcmalloc(size, "live_range");
18832 /* Setup the dummy live range */
18833 rstate->lr[0].classes = 0;
18834 rstate->lr[0].color = REG_UNSET;
18835 rstate->lr[0].defs = 0;
18836 i = j = 0;
18837 ins = first;
18838 do {
18839 /* If the triple is a variable give it a live range */
18840 if (triple_is_def(state, ins)) {
18841 struct reg_info info;
18842 /* Find the architecture specific color information */
18843 info = find_def_color(state, ins);
18844 i++;
18845 rstate->lr[i].defs = &rstate->lrd[j];
18846 rstate->lr[i].color = info.reg;
18847 rstate->lr[i].classes = info.regcm;
18848 rstate->lr[i].degree = 0;
18849 rstate->lrd[j].lr = &rstate->lr[i];
18851 /* Otherwise give the triple the dummy live range. */
18852 else {
18853 rstate->lrd[j].lr = &rstate->lr[0];
18856 /* Initialize the live_range_def */
18857 rstate->lrd[j].next = &rstate->lrd[j];
18858 rstate->lrd[j].prev = &rstate->lrd[j];
18859 rstate->lrd[j].def = ins;
18860 rstate->lrd[j].orig_id = ins->id;
18861 ins->id = j;
18863 j++;
18864 ins = ins->next;
18865 } while(ins != first);
18866 rstate->ranges = i;
18868 /* Make a second pass to handle architecture specific register
18869 * constraints.
18871 ins = first;
18872 do {
18873 int zlhs, zrhs, i, j;
18874 if (ins->id > rstate->defs) {
18875 internal_error(state, ins, "bad id");
18878 /* Walk through the template of ins and coalesce live ranges */
18879 zlhs = ins->lhs;
18880 if ((zlhs == 0) && triple_is_def(state, ins)) {
18881 zlhs = 1;
18883 zrhs = ins->rhs;
18885 if (state->compiler->debug & DEBUG_COALESCING2) {
18886 fprintf(state->errout, "mandatory coalesce: %p %d %d\n",
18887 ins, zlhs, zrhs);
18890 for(i = 0; i < zlhs; i++) {
18891 struct reg_info linfo;
18892 struct live_range_def *lhs;
18893 linfo = arch_reg_lhs(state, ins, i);
18894 if (linfo.reg < MAX_REGISTERS) {
18895 continue;
18897 if (triple_is_def(state, ins)) {
18898 lhs = &rstate->lrd[ins->id];
18899 } else {
18900 lhs = &rstate->lrd[LHS(ins, i)->id];
18903 if (state->compiler->debug & DEBUG_COALESCING2) {
18904 fprintf(state->errout, "coalesce lhs(%d): %p %d\n",
18905 i, lhs, linfo.reg);
18908 for(j = 0; j < zrhs; j++) {
18909 struct reg_info rinfo;
18910 struct live_range_def *rhs;
18911 rinfo = arch_reg_rhs(state, ins, j);
18912 if (rinfo.reg < MAX_REGISTERS) {
18913 continue;
18915 rhs = &rstate->lrd[RHS(ins, j)->id];
18917 if (state->compiler->debug & DEBUG_COALESCING2) {
18918 fprintf(state->errout, "coalesce rhs(%d): %p %d\n",
18919 j, rhs, rinfo.reg);
18922 if (rinfo.reg == linfo.reg) {
18923 coalesce_ranges(state, rstate,
18924 lhs->lr, rhs->lr);
18928 ins = ins->next;
18929 } while(ins != first);
18932 static void graph_ins(
18933 struct compile_state *state,
18934 struct reg_block *blocks, struct triple_reg_set *live,
18935 struct reg_block *rb, struct triple *ins, void *arg)
18937 struct reg_state *rstate = arg;
18938 struct live_range *def;
18939 struct triple_reg_set *entry;
18941 /* If the triple is not a definition
18942 * we do not have a definition to add to
18943 * the interference graph.
18945 if (!triple_is_def(state, ins)) {
18946 return;
18948 def = rstate->lrd[ins->id].lr;
18950 /* Create an edge between ins and everything that is
18951 * alive, unless the live_range cannot share
18952 * a physical register with ins.
18954 for(entry = live; entry; entry = entry->next) {
18955 struct live_range *lr;
18956 if (entry->member->id > rstate->defs) {
18957 internal_error(state, 0, "bad entry?");
18959 lr = rstate->lrd[entry->member->id].lr;
18960 if (def == lr) {
18961 continue;
18963 if (!arch_regcm_intersect(def->classes, lr->classes)) {
18964 continue;
18966 add_live_edge(rstate, def, lr);
18968 return;
18971 #if DEBUG_CONSISTENCY > 1
18972 static struct live_range *get_verify_live_range(
18973 struct compile_state *state, struct reg_state *rstate, struct triple *ins)
18975 struct live_range *lr;
18976 struct live_range_def *lrd;
18977 int ins_found;
18978 if ((ins->id < 0) || (ins->id > rstate->defs)) {
18979 internal_error(state, ins, "bad ins?");
18981 lr = rstate->lrd[ins->id].lr;
18982 ins_found = 0;
18983 lrd = lr->defs;
18984 do {
18985 if (lrd->def == ins) {
18986 ins_found = 1;
18988 lrd = lrd->next;
18989 } while(lrd != lr->defs);
18990 if (!ins_found) {
18991 internal_error(state, ins, "ins not in live range");
18993 return lr;
18996 static void verify_graph_ins(
18997 struct compile_state *state,
18998 struct reg_block *blocks, struct triple_reg_set *live,
18999 struct reg_block *rb, struct triple *ins, void *arg)
19001 struct reg_state *rstate = arg;
19002 struct triple_reg_set *entry1, *entry2;
19005 /* Compare live against edges and make certain the code is working */
19006 for(entry1 = live; entry1; entry1 = entry1->next) {
19007 struct live_range *lr1;
19008 lr1 = get_verify_live_range(state, rstate, entry1->member);
19009 for(entry2 = live; entry2; entry2 = entry2->next) {
19010 struct live_range *lr2;
19011 struct live_range_edge *edge2;
19012 int lr1_found;
19013 int lr2_degree;
19014 if (entry2 == entry1) {
19015 continue;
19017 lr2 = get_verify_live_range(state, rstate, entry2->member);
19018 if (lr1 == lr2) {
19019 internal_error(state, entry2->member,
19020 "live range with 2 values simultaneously alive");
19022 if (!arch_regcm_intersect(lr1->classes, lr2->classes)) {
19023 continue;
19025 if (!interfere(rstate, lr1, lr2)) {
19026 internal_error(state, entry2->member,
19027 "edges don't interfere?");
19030 lr1_found = 0;
19031 lr2_degree = 0;
19032 for(edge2 = lr2->edges; edge2; edge2 = edge2->next) {
19033 lr2_degree++;
19034 if (edge2->node == lr1) {
19035 lr1_found = 1;
19038 if (lr2_degree != lr2->degree) {
19039 internal_error(state, entry2->member,
19040 "computed degree: %d does not match reported degree: %d\n",
19041 lr2_degree, lr2->degree);
19043 if (!lr1_found) {
19044 internal_error(state, entry2->member, "missing edge");
19048 return;
19050 #endif
19052 static void print_interference_ins(
19053 struct compile_state *state,
19054 struct reg_block *blocks, struct triple_reg_set *live,
19055 struct reg_block *rb, struct triple *ins, void *arg)
19057 struct reg_state *rstate = arg;
19058 struct live_range *lr;
19059 unsigned id;
19060 FILE *fp = state->dbgout;
19062 lr = rstate->lrd[ins->id].lr;
19063 id = ins->id;
19064 ins->id = rstate->lrd[id].orig_id;
19065 SET_REG(ins->id, lr->color);
19066 display_triple(state->dbgout, ins);
19067 ins->id = id;
19069 if (lr->defs) {
19070 struct live_range_def *lrd;
19071 fprintf(fp, " range:");
19072 lrd = lr->defs;
19073 do {
19074 fprintf(fp, " %-10p", lrd->def);
19075 lrd = lrd->next;
19076 } while(lrd != lr->defs);
19077 fprintf(fp, "\n");
19079 if (live) {
19080 struct triple_reg_set *entry;
19081 fprintf(fp, " live:");
19082 for(entry = live; entry; entry = entry->next) {
19083 fprintf(fp, " %-10p", entry->member);
19085 fprintf(fp, "\n");
19087 if (lr->edges) {
19088 struct live_range_edge *entry;
19089 fprintf(fp, " edges:");
19090 for(entry = lr->edges; entry; entry = entry->next) {
19091 struct live_range_def *lrd;
19092 lrd = entry->node->defs;
19093 do {
19094 fprintf(fp, " %-10p", lrd->def);
19095 lrd = lrd->next;
19096 } while(lrd != entry->node->defs);
19097 fprintf(fp, "|");
19099 fprintf(fp, "\n");
19101 if (triple_is_branch(state, ins)) {
19102 fprintf(fp, "\n");
19104 return;
19107 static int coalesce_live_ranges(
19108 struct compile_state *state, struct reg_state *rstate)
19110 /* At the point where a value is moved from one
19111 * register to another that value requires two
19112 * registers, thus increasing register pressure.
19113 * Live range coaleescing reduces the register
19114 * pressure by keeping a value in one register
19115 * longer.
19117 * In the case of a phi function all paths leading
19118 * into it must be allocated to the same register
19119 * otherwise the phi function may not be removed.
19121 * Forcing a value to stay in a single register
19122 * for an extended period of time does have
19123 * limitations when applied to non homogenous
19124 * register pool.
19126 * The two cases I have identified are:
19127 * 1) Two forced register assignments may
19128 * collide.
19129 * 2) Registers may go unused because they
19130 * are only good for storing the value
19131 * and not manipulating it.
19133 * Because of this I need to split live ranges,
19134 * even outside of the context of coalesced live
19135 * ranges. The need to split live ranges does
19136 * impose some constraints on live range coalescing.
19138 * - Live ranges may not be coalesced across phi
19139 * functions. This creates a 2 headed live
19140 * range that cannot be sanely split.
19142 * - phi functions (coalesced in initialize_live_ranges)
19143 * are handled as pre split live ranges so we will
19144 * never attempt to split them.
19146 int coalesced;
19147 int i;
19149 coalesced = 0;
19150 for(i = 0; i <= rstate->ranges; i++) {
19151 struct live_range *lr1;
19152 struct live_range_def *lrd1;
19153 lr1 = &rstate->lr[i];
19154 if (!lr1->defs) {
19155 continue;
19157 lrd1 = live_range_end(state, lr1, 0);
19158 for(; lrd1; lrd1 = live_range_end(state, lr1, lrd1)) {
19159 struct triple_set *set;
19160 if (lrd1->def->op != OP_COPY) {
19161 continue;
19163 /* Skip copies that are the result of a live range split. */
19164 if (lrd1->orig_id & TRIPLE_FLAG_POST_SPLIT) {
19165 continue;
19167 for(set = lrd1->def->use; set; set = set->next) {
19168 struct live_range_def *lrd2;
19169 struct live_range *lr2, *res;
19171 lrd2 = &rstate->lrd[set->member->id];
19173 /* Don't coalesce with instructions
19174 * that are the result of a live range
19175 * split.
19177 if (lrd2->orig_id & TRIPLE_FLAG_PRE_SPLIT) {
19178 continue;
19180 lr2 = rstate->lrd[set->member->id].lr;
19181 if (lr1 == lr2) {
19182 continue;
19184 if ((lr1->color != lr2->color) &&
19185 (lr1->color != REG_UNSET) &&
19186 (lr2->color != REG_UNSET)) {
19187 continue;
19189 if ((lr1->classes & lr2->classes) == 0) {
19190 continue;
19193 if (interfere(rstate, lr1, lr2)) {
19194 continue;
19197 res = coalesce_ranges(state, rstate, lr1, lr2);
19198 coalesced += 1;
19199 if (res != lr1) {
19200 goto next;
19204 next:
19207 return coalesced;
19211 static void fix_coalesce_conflicts(struct compile_state *state,
19212 struct reg_block *blocks, struct triple_reg_set *live,
19213 struct reg_block *rb, struct triple *ins, void *arg)
19215 int *conflicts = arg;
19216 int zlhs, zrhs, i, j;
19218 /* See if we have a mandatory coalesce operation between
19219 * a lhs and a rhs value. If so and the rhs value is also
19220 * alive then this triple needs to be pre copied. Otherwise
19221 * we would have two definitions in the same live range simultaneously
19222 * alive.
19224 zlhs = ins->lhs;
19225 if ((zlhs == 0) && triple_is_def(state, ins)) {
19226 zlhs = 1;
19228 zrhs = ins->rhs;
19229 for(i = 0; i < zlhs; i++) {
19230 struct reg_info linfo;
19231 linfo = arch_reg_lhs(state, ins, i);
19232 if (linfo.reg < MAX_REGISTERS) {
19233 continue;
19235 for(j = 0; j < zrhs; j++) {
19236 struct reg_info rinfo;
19237 struct triple *rhs;
19238 struct triple_reg_set *set;
19239 int found;
19240 found = 0;
19241 rinfo = arch_reg_rhs(state, ins, j);
19242 if (rinfo.reg != linfo.reg) {
19243 continue;
19245 rhs = RHS(ins, j);
19246 for(set = live; set && !found; set = set->next) {
19247 if (set->member == rhs) {
19248 found = 1;
19251 if (found) {
19252 struct triple *copy;
19253 copy = pre_copy(state, ins, j);
19254 copy->id |= TRIPLE_FLAG_PRE_SPLIT;
19255 (*conflicts)++;
19259 return;
19262 static int correct_coalesce_conflicts(
19263 struct compile_state *state, struct reg_block *blocks)
19265 int conflicts;
19266 conflicts = 0;
19267 walk_variable_lifetimes(state, &state->bb, blocks,
19268 fix_coalesce_conflicts, &conflicts);
19269 return conflicts;
19272 static void replace_set_use(struct compile_state *state,
19273 struct triple_reg_set *head, struct triple *orig, struct triple *new)
19275 struct triple_reg_set *set;
19276 for(set = head; set; set = set->next) {
19277 if (set->member == orig) {
19278 set->member = new;
19283 static void replace_block_use(struct compile_state *state,
19284 struct reg_block *blocks, struct triple *orig, struct triple *new)
19286 int i;
19287 #if DEBUG_ROMCC_WARNINGS
19288 #warning "WISHLIST visit just those blocks that need it *"
19289 #endif
19290 for(i = 1; i <= state->bb.last_vertex; i++) {
19291 struct reg_block *rb;
19292 rb = &blocks[i];
19293 replace_set_use(state, rb->in, orig, new);
19294 replace_set_use(state, rb->out, orig, new);
19298 static void color_instructions(struct compile_state *state)
19300 struct triple *ins, *first;
19301 first = state->first;
19302 ins = first;
19303 do {
19304 if (triple_is_def(state, ins)) {
19305 struct reg_info info;
19306 info = find_lhs_color(state, ins, 0);
19307 if (info.reg >= MAX_REGISTERS) {
19308 info.reg = REG_UNSET;
19310 SET_INFO(ins->id, info);
19312 ins = ins->next;
19313 } while(ins != first);
19316 static struct reg_info read_lhs_color(
19317 struct compile_state *state, struct triple *ins, int index)
19319 struct reg_info info;
19320 if ((index == 0) && triple_is_def(state, ins)) {
19321 info.reg = ID_REG(ins->id);
19322 info.regcm = ID_REGCM(ins->id);
19324 else if (index < ins->lhs) {
19325 info = read_lhs_color(state, LHS(ins, index), 0);
19327 else {
19328 internal_error(state, ins, "Bad lhs %d", index);
19329 info.reg = REG_UNSET;
19330 info.regcm = 0;
19332 return info;
19335 static struct triple *resolve_tangle(
19336 struct compile_state *state, struct triple *tangle)
19338 struct reg_info info, uinfo;
19339 struct triple_set *set, *next;
19340 struct triple *copy;
19342 #if DEBUG_ROMCC_WARNINGS
19343 #warning "WISHLIST recalculate all affected instructions colors"
19344 #endif
19345 info = find_lhs_color(state, tangle, 0);
19346 for(set = tangle->use; set; set = next) {
19347 struct triple *user;
19348 int i, zrhs;
19349 next = set->next;
19350 user = set->member;
19351 zrhs = user->rhs;
19352 for(i = 0; i < zrhs; i++) {
19353 if (RHS(user, i) != tangle) {
19354 continue;
19356 uinfo = find_rhs_post_color(state, user, i);
19357 if (uinfo.reg == info.reg) {
19358 copy = pre_copy(state, user, i);
19359 copy->id |= TRIPLE_FLAG_PRE_SPLIT;
19360 SET_INFO(copy->id, uinfo);
19364 copy = 0;
19365 uinfo = find_lhs_pre_color(state, tangle, 0);
19366 if (uinfo.reg == info.reg) {
19367 struct reg_info linfo;
19368 copy = post_copy(state, tangle);
19369 copy->id |= TRIPLE_FLAG_PRE_SPLIT;
19370 linfo = find_lhs_color(state, copy, 0);
19371 SET_INFO(copy->id, linfo);
19373 info = find_lhs_color(state, tangle, 0);
19374 SET_INFO(tangle->id, info);
19376 return copy;
19380 static void fix_tangles(struct compile_state *state,
19381 struct reg_block *blocks, struct triple_reg_set *live,
19382 struct reg_block *rb, struct triple *ins, void *arg)
19384 int *tangles = arg;
19385 struct triple *tangle;
19386 do {
19387 char used[MAX_REGISTERS];
19388 struct triple_reg_set *set;
19389 tangle = 0;
19391 /* Find out which registers have multiple uses at this point */
19392 memset(used, 0, sizeof(used));
19393 for(set = live; set; set = set->next) {
19394 struct reg_info info;
19395 info = read_lhs_color(state, set->member, 0);
19396 if (info.reg == REG_UNSET) {
19397 continue;
19399 reg_inc_used(state, used, info.reg);
19402 /* Now find the least dominated definition of a register in
19403 * conflict I have seen so far.
19405 for(set = live; set; set = set->next) {
19406 struct reg_info info;
19407 info = read_lhs_color(state, set->member, 0);
19408 if (used[info.reg] < 2) {
19409 continue;
19411 /* Changing copies that feed into phi functions
19412 * is incorrect.
19414 if (set->member->use &&
19415 (set->member->use->member->op == OP_PHI)) {
19416 continue;
19418 if (!tangle || tdominates(state, set->member, tangle)) {
19419 tangle = set->member;
19422 /* If I have found a tangle resolve it */
19423 if (tangle) {
19424 struct triple *post_copy;
19425 (*tangles)++;
19426 post_copy = resolve_tangle(state, tangle);
19427 if (post_copy) {
19428 replace_block_use(state, blocks, tangle, post_copy);
19430 if (post_copy && (tangle != ins)) {
19431 replace_set_use(state, live, tangle, post_copy);
19434 } while(tangle);
19435 return;
19438 static int correct_tangles(
19439 struct compile_state *state, struct reg_block *blocks)
19441 int tangles;
19442 tangles = 0;
19443 color_instructions(state);
19444 walk_variable_lifetimes(state, &state->bb, blocks,
19445 fix_tangles, &tangles);
19446 return tangles;
19450 static void ids_from_rstate(struct compile_state *state, struct reg_state *rstate);
19451 static void cleanup_rstate(struct compile_state *state, struct reg_state *rstate);
19453 struct triple *find_constrained_def(
19454 struct compile_state *state, struct live_range *range, struct triple *constrained)
19456 struct live_range_def *lrd, *lrd_next;
19457 lrd_next = range->defs;
19458 do {
19459 struct reg_info info;
19460 unsigned regcm;
19462 lrd = lrd_next;
19463 lrd_next = lrd->next;
19465 regcm = arch_type_to_regcm(state, lrd->def->type);
19466 info = find_lhs_color(state, lrd->def, 0);
19467 regcm = arch_regcm_reg_normalize(state, regcm);
19468 info.regcm = arch_regcm_reg_normalize(state, info.regcm);
19469 /* If the 2 register class masks are equal then
19470 * the current register class is not constrained.
19472 if (regcm == info.regcm) {
19473 continue;
19476 /* If there is just one use.
19477 * That use cannot accept a larger register class.
19478 * There are no intervening definitions except
19479 * definitions that feed into that use.
19480 * Then a triple is not constrained.
19481 * FIXME handle this case!
19483 #if DEBUG_ROMCC_WARNINGS
19484 #warning "FIXME ignore cases that cannot be fixed (a definition followed by a use)"
19485 #endif
19488 /* Of the constrained live ranges deal with the
19489 * least dominated one first.
19491 if (state->compiler->debug & DEBUG_RANGE_CONFLICTS) {
19492 fprintf(state->errout, "canidate: %p %-8s regcm: %x %x\n",
19493 lrd->def, tops(lrd->def->op), regcm, info.regcm);
19495 if (!constrained ||
19496 tdominates(state, lrd->def, constrained))
19498 constrained = lrd->def;
19500 } while(lrd_next != range->defs);
19501 return constrained;
19504 static int split_constrained_ranges(
19505 struct compile_state *state, struct reg_state *rstate,
19506 struct live_range *range)
19508 /* Walk through the edges in conflict and our current live
19509 * range, and find definitions that are more severly constrained
19510 * than they type of data they contain require.
19512 * Then pick one of those ranges and relax the constraints.
19514 struct live_range_edge *edge;
19515 struct triple *constrained;
19517 constrained = 0;
19518 for(edge = range->edges; edge; edge = edge->next) {
19519 constrained = find_constrained_def(state, edge->node, constrained);
19521 #if DEBUG_ROMCC_WARNINGS
19522 #warning "FIXME should I call find_constrained_def here only if no previous constrained def was found?"
19523 #endif
19524 if (!constrained) {
19525 constrained = find_constrained_def(state, range, constrained);
19528 if (state->compiler->debug & DEBUG_RANGE_CONFLICTS) {
19529 fprintf(state->errout, "constrained: ");
19530 display_triple(state->errout, constrained);
19532 if (constrained) {
19533 ids_from_rstate(state, rstate);
19534 cleanup_rstate(state, rstate);
19535 resolve_tangle(state, constrained);
19537 return !!constrained;
19540 static int split_ranges(
19541 struct compile_state *state, struct reg_state *rstate,
19542 char *used, struct live_range *range)
19544 int split;
19545 if (state->compiler->debug & DEBUG_RANGE_CONFLICTS) {
19546 fprintf(state->errout, "split_ranges %d %s %p\n",
19547 rstate->passes, tops(range->defs->def->op), range->defs->def);
19549 if ((range->color == REG_UNNEEDED) ||
19550 (rstate->passes >= rstate->max_passes)) {
19551 return 0;
19553 split = split_constrained_ranges(state, rstate, range);
19555 /* Ideally I would split the live range that will not be used
19556 * for the longest period of time in hopes that this will
19557 * (a) allow me to spill a register or
19558 * (b) allow me to place a value in another register.
19560 * So far I don't have a test case for this, the resolving
19561 * of mandatory constraints has solved all of my
19562 * know issues. So I have chosen not to write any
19563 * code until I cat get a better feel for cases where
19564 * it would be useful to have.
19567 #if DEBUG_ROMCC_WARNINGS
19568 #warning "WISHLIST implement live range splitting..."
19569 #endif
19571 if (!split && (state->compiler->debug & DEBUG_RANGE_CONFLICTS2)) {
19572 FILE *fp = state->errout;
19573 print_interference_blocks(state, rstate, fp, 0);
19574 print_dominators(state, fp, &state->bb);
19576 return split;
19579 static FILE *cgdebug_fp(struct compile_state *state)
19581 FILE *fp;
19582 fp = 0;
19583 if (!fp && (state->compiler->debug & DEBUG_COLOR_GRAPH2)) {
19584 fp = state->errout;
19586 if (!fp && (state->compiler->debug & DEBUG_COLOR_GRAPH)) {
19587 fp = state->dbgout;
19589 return fp;
19592 static void cgdebug_printf(struct compile_state *state, const char *fmt, ...)
19594 FILE *fp;
19595 fp = cgdebug_fp(state);
19596 if (fp) {
19597 va_list args;
19598 va_start(args, fmt);
19599 vfprintf(fp, fmt, args);
19600 va_end(args);
19604 static void cgdebug_flush(struct compile_state *state)
19606 FILE *fp;
19607 fp = cgdebug_fp(state);
19608 if (fp) {
19609 fflush(fp);
19613 static void cgdebug_loc(struct compile_state *state, struct triple *ins)
19615 FILE *fp;
19616 fp = cgdebug_fp(state);
19617 if (fp) {
19618 loc(fp, state, ins);
19622 static int select_free_color(struct compile_state *state,
19623 struct reg_state *rstate, struct live_range *range)
19625 struct triple_set *entry;
19626 struct live_range_def *lrd;
19627 struct live_range_def *phi;
19628 struct live_range_edge *edge;
19629 char used[MAX_REGISTERS];
19630 struct triple **expr;
19632 /* Instead of doing just the trivial color select here I try
19633 * a few extra things because a good color selection will help reduce
19634 * copies.
19637 /* Find the registers currently in use */
19638 memset(used, 0, sizeof(used));
19639 for(edge = range->edges; edge; edge = edge->next) {
19640 if (edge->node->color == REG_UNSET) {
19641 continue;
19643 reg_fill_used(state, used, edge->node->color);
19646 if (state->compiler->debug & DEBUG_COLOR_GRAPH2) {
19647 int i;
19648 i = 0;
19649 for(edge = range->edges; edge; edge = edge->next) {
19650 i++;
19652 cgdebug_printf(state, "\n%s edges: %d",
19653 tops(range->defs->def->op), i);
19654 cgdebug_loc(state, range->defs->def);
19655 cgdebug_printf(state, "\n");
19656 for(i = 0; i < MAX_REGISTERS; i++) {
19657 if (used[i]) {
19658 cgdebug_printf(state, "used: %s\n",
19659 arch_reg_str(i));
19664 /* If a color is already assigned see if it will work */
19665 if (range->color != REG_UNSET) {
19666 struct live_range_def *lrd;
19667 if (!used[range->color]) {
19668 return 1;
19670 for(edge = range->edges; edge; edge = edge->next) {
19671 if (edge->node->color != range->color) {
19672 continue;
19674 warning(state, edge->node->defs->def, "edge: ");
19675 lrd = edge->node->defs;
19676 do {
19677 warning(state, lrd->def, " %p %s",
19678 lrd->def, tops(lrd->def->op));
19679 lrd = lrd->next;
19680 } while(lrd != edge->node->defs);
19682 lrd = range->defs;
19683 warning(state, range->defs->def, "def: ");
19684 do {
19685 warning(state, lrd->def, " %p %s",
19686 lrd->def, tops(lrd->def->op));
19687 lrd = lrd->next;
19688 } while(lrd != range->defs);
19689 internal_error(state, range->defs->def,
19690 "live range with already used color %s",
19691 arch_reg_str(range->color));
19694 /* If I feed into an expression reuse it's color.
19695 * This should help remove copies in the case of 2 register instructions
19696 * and phi functions.
19698 phi = 0;
19699 lrd = live_range_end(state, range, 0);
19700 for(; (range->color == REG_UNSET) && lrd ; lrd = live_range_end(state, range, lrd)) {
19701 entry = lrd->def->use;
19702 for(;(range->color == REG_UNSET) && entry; entry = entry->next) {
19703 struct live_range_def *insd;
19704 unsigned regcm;
19705 insd = &rstate->lrd[entry->member->id];
19706 if (insd->lr->defs == 0) {
19707 continue;
19709 if (!phi && (insd->def->op == OP_PHI) &&
19710 !interfere(rstate, range, insd->lr)) {
19711 phi = insd;
19713 if (insd->lr->color == REG_UNSET) {
19714 continue;
19716 regcm = insd->lr->classes;
19717 if (((regcm & range->classes) == 0) ||
19718 (used[insd->lr->color])) {
19719 continue;
19721 if (interfere(rstate, range, insd->lr)) {
19722 continue;
19724 range->color = insd->lr->color;
19727 /* If I feed into a phi function reuse it's color or the color
19728 * of something else that feeds into the phi function.
19730 if (phi) {
19731 if (phi->lr->color != REG_UNSET) {
19732 if (used[phi->lr->color]) {
19733 range->color = phi->lr->color;
19736 else {
19737 expr = triple_rhs(state, phi->def, 0);
19738 for(; expr; expr = triple_rhs(state, phi->def, expr)) {
19739 struct live_range *lr;
19740 unsigned regcm;
19741 if (!*expr) {
19742 continue;
19744 lr = rstate->lrd[(*expr)->id].lr;
19745 if (lr->color == REG_UNSET) {
19746 continue;
19748 regcm = lr->classes;
19749 if (((regcm & range->classes) == 0) ||
19750 (used[lr->color])) {
19751 continue;
19753 if (interfere(rstate, range, lr)) {
19754 continue;
19756 range->color = lr->color;
19760 /* If I don't interfere with a rhs node reuse it's color */
19761 lrd = live_range_head(state, range, 0);
19762 for(; (range->color == REG_UNSET) && lrd ; lrd = live_range_head(state, range, lrd)) {
19763 expr = triple_rhs(state, lrd->def, 0);
19764 for(; expr; expr = triple_rhs(state, lrd->def, expr)) {
19765 struct live_range *lr;
19766 unsigned regcm;
19767 if (!*expr) {
19768 continue;
19770 lr = rstate->lrd[(*expr)->id].lr;
19771 if (lr->color == REG_UNSET) {
19772 continue;
19774 regcm = lr->classes;
19775 if (((regcm & range->classes) == 0) ||
19776 (used[lr->color])) {
19777 continue;
19779 if (interfere(rstate, range, lr)) {
19780 continue;
19782 range->color = lr->color;
19783 break;
19786 /* If I have not opportunitically picked a useful color
19787 * pick the first color that is free.
19789 if (range->color == REG_UNSET) {
19790 range->color =
19791 arch_select_free_register(state, used, range->classes);
19793 if (range->color == REG_UNSET) {
19794 struct live_range_def *lrd;
19795 int i;
19796 if (split_ranges(state, rstate, used, range)) {
19797 return 0;
19799 for(edge = range->edges; edge; edge = edge->next) {
19800 warning(state, edge->node->defs->def, "edge reg %s",
19801 arch_reg_str(edge->node->color));
19802 lrd = edge->node->defs;
19803 do {
19804 warning(state, lrd->def, " %s %p",
19805 tops(lrd->def->op), lrd->def);
19806 lrd = lrd->next;
19807 } while(lrd != edge->node->defs);
19809 warning(state, range->defs->def, "range: ");
19810 lrd = range->defs;
19811 do {
19812 warning(state, lrd->def, " %s %p",
19813 tops(lrd->def->op), lrd->def);
19814 lrd = lrd->next;
19815 } while(lrd != range->defs);
19817 warning(state, range->defs->def, "classes: %x",
19818 range->classes);
19819 for(i = 0; i < MAX_REGISTERS; i++) {
19820 if (used[i]) {
19821 warning(state, range->defs->def, "used: %s",
19822 arch_reg_str(i));
19825 error(state, range->defs->def, "too few registers");
19827 range->classes &= arch_reg_regcm(state, range->color);
19828 if ((range->color == REG_UNSET) || (range->classes == 0)) {
19829 internal_error(state, range->defs->def, "select_free_color did not?");
19831 return 1;
19834 static int color_graph(struct compile_state *state, struct reg_state *rstate)
19836 int colored;
19837 struct live_range_edge *edge;
19838 struct live_range *range;
19839 if (rstate->low) {
19840 cgdebug_printf(state, "Lo: ");
19841 range = rstate->low;
19842 if (*range->group_prev != range) {
19843 internal_error(state, 0, "lo: *prev != range?");
19845 *range->group_prev = range->group_next;
19846 if (range->group_next) {
19847 range->group_next->group_prev = range->group_prev;
19849 if (&range->group_next == rstate->low_tail) {
19850 rstate->low_tail = range->group_prev;
19852 if (rstate->low == range) {
19853 internal_error(state, 0, "low: next != prev?");
19856 else if (rstate->high) {
19857 cgdebug_printf(state, "Hi: ");
19858 range = rstate->high;
19859 if (*range->group_prev != range) {
19860 internal_error(state, 0, "hi: *prev != range?");
19862 *range->group_prev = range->group_next;
19863 if (range->group_next) {
19864 range->group_next->group_prev = range->group_prev;
19866 if (&range->group_next == rstate->high_tail) {
19867 rstate->high_tail = range->group_prev;
19869 if (rstate->high == range) {
19870 internal_error(state, 0, "high: next != prev?");
19873 else {
19874 return 1;
19876 cgdebug_printf(state, " %td\n", range - rstate->lr);
19877 range->group_prev = 0;
19878 for(edge = range->edges; edge; edge = edge->next) {
19879 struct live_range *node;
19880 node = edge->node;
19881 /* Move nodes from the high to the low list */
19882 if (node->group_prev && (node->color == REG_UNSET) &&
19883 (node->degree == regc_max_size(state, node->classes))) {
19884 if (*node->group_prev != node) {
19885 internal_error(state, 0, "move: *prev != node?");
19887 *node->group_prev = node->group_next;
19888 if (node->group_next) {
19889 node->group_next->group_prev = node->group_prev;
19891 if (&node->group_next == rstate->high_tail) {
19892 rstate->high_tail = node->group_prev;
19894 cgdebug_printf(state, "Moving...%td to low\n", node - rstate->lr);
19895 node->group_prev = rstate->low_tail;
19896 node->group_next = 0;
19897 *rstate->low_tail = node;
19898 rstate->low_tail = &node->group_next;
19899 if (*node->group_prev != node) {
19900 internal_error(state, 0, "move2: *prev != node?");
19903 node->degree -= 1;
19905 colored = color_graph(state, rstate);
19906 if (colored) {
19907 cgdebug_printf(state, "Coloring %td @", range - rstate->lr);
19908 cgdebug_loc(state, range->defs->def);
19909 cgdebug_flush(state);
19910 colored = select_free_color(state, rstate, range);
19911 if (colored) {
19912 cgdebug_printf(state, " %s\n", arch_reg_str(range->color));
19915 return colored;
19918 static void verify_colors(struct compile_state *state, struct reg_state *rstate)
19920 struct live_range *lr;
19921 struct live_range_edge *edge;
19922 struct triple *ins, *first;
19923 char used[MAX_REGISTERS];
19924 first = state->first;
19925 ins = first;
19926 do {
19927 if (triple_is_def(state, ins)) {
19928 if (ins->id > rstate->defs) {
19929 internal_error(state, ins,
19930 "triple without a live range def");
19932 lr = rstate->lrd[ins->id].lr;
19933 if (lr->color == REG_UNSET) {
19934 internal_error(state, ins,
19935 "triple without a color");
19937 /* Find the registers used by the edges */
19938 memset(used, 0, sizeof(used));
19939 for(edge = lr->edges; edge; edge = edge->next) {
19940 if (edge->node->color == REG_UNSET) {
19941 internal_error(state, 0,
19942 "live range without a color");
19944 reg_fill_used(state, used, edge->node->color);
19946 if (used[lr->color]) {
19947 internal_error(state, ins,
19948 "triple with already used color");
19951 ins = ins->next;
19952 } while(ins != first);
19955 static void color_triples(struct compile_state *state, struct reg_state *rstate)
19957 struct live_range_def *lrd;
19958 struct live_range *lr;
19959 struct triple *first, *ins;
19960 first = state->first;
19961 ins = first;
19962 do {
19963 if (ins->id > rstate->defs) {
19964 internal_error(state, ins,
19965 "triple without a live range");
19967 lrd = &rstate->lrd[ins->id];
19968 lr = lrd->lr;
19969 ins->id = lrd->orig_id;
19970 SET_REG(ins->id, lr->color);
19971 ins = ins->next;
19972 } while (ins != first);
19975 static struct live_range *merge_sort_lr(
19976 struct live_range *first, struct live_range *last)
19978 struct live_range *mid, *join, **join_tail, *pick;
19979 size_t size;
19980 size = (last - first) + 1;
19981 if (size >= 2) {
19982 mid = first + size/2;
19983 first = merge_sort_lr(first, mid -1);
19984 mid = merge_sort_lr(mid, last);
19986 join = 0;
19987 join_tail = &join;
19988 /* merge the two lists */
19989 while(first && mid) {
19990 if ((first->degree < mid->degree) ||
19991 ((first->degree == mid->degree) &&
19992 (first->length < mid->length))) {
19993 pick = first;
19994 first = first->group_next;
19995 if (first) {
19996 first->group_prev = 0;
19999 else {
20000 pick = mid;
20001 mid = mid->group_next;
20002 if (mid) {
20003 mid->group_prev = 0;
20006 pick->group_next = 0;
20007 pick->group_prev = join_tail;
20008 *join_tail = pick;
20009 join_tail = &pick->group_next;
20011 /* Splice the remaining list */
20012 pick = (first)? first : mid;
20013 *join_tail = pick;
20014 if (pick) {
20015 pick->group_prev = join_tail;
20018 else {
20019 if (!first->defs) {
20020 first = 0;
20022 join = first;
20024 return join;
20027 static void ids_from_rstate(struct compile_state *state,
20028 struct reg_state *rstate)
20030 struct triple *ins, *first;
20031 if (!rstate->defs) {
20032 return;
20034 /* Display the graph if desired */
20035 if (state->compiler->debug & DEBUG_INTERFERENCE) {
20036 FILE *fp = state->dbgout;
20037 print_interference_blocks(state, rstate, fp, 0);
20038 print_control_flow(state, fp, &state->bb);
20039 fflush(fp);
20041 first = state->first;
20042 ins = first;
20043 do {
20044 if (ins->id) {
20045 struct live_range_def *lrd;
20046 lrd = &rstate->lrd[ins->id];
20047 ins->id = lrd->orig_id;
20049 ins = ins->next;
20050 } while(ins != first);
20053 static void cleanup_live_edges(struct reg_state *rstate)
20055 int i;
20056 /* Free the edges on each node */
20057 for(i = 1; i <= rstate->ranges; i++) {
20058 remove_live_edges(rstate, &rstate->lr[i]);
20062 static void cleanup_rstate(struct compile_state *state, struct reg_state *rstate)
20064 cleanup_live_edges(rstate);
20065 xfree(rstate->lrd);
20066 xfree(rstate->lr);
20068 /* Free the variable lifetime information */
20069 if (rstate->blocks) {
20070 free_variable_lifetimes(state, &state->bb, rstate->blocks);
20072 rstate->defs = 0;
20073 rstate->ranges = 0;
20074 rstate->lrd = 0;
20075 rstate->lr = 0;
20076 rstate->blocks = 0;
20079 static void verify_consistency(struct compile_state *state);
20080 static void allocate_registers(struct compile_state *state)
20082 struct reg_state rstate;
20083 int colored;
20085 /* Clear out the reg_state */
20086 memset(&rstate, 0, sizeof(rstate));
20087 rstate.max_passes = state->compiler->max_allocation_passes;
20089 do {
20090 struct live_range **point, **next;
20091 int tangles;
20092 int coalesced;
20094 if (state->compiler->debug & DEBUG_RANGE_CONFLICTS) {
20095 FILE *fp = state->errout;
20096 fprintf(fp, "pass: %d\n", rstate.passes);
20097 fflush(fp);
20100 /* Restore ids */
20101 ids_from_rstate(state, &rstate);
20103 /* Cleanup the temporary data structures */
20104 cleanup_rstate(state, &rstate);
20106 /* Compute the variable lifetimes */
20107 rstate.blocks = compute_variable_lifetimes(state, &state->bb);
20109 /* Fix invalid mandatory live range coalesce conflicts */
20110 correct_coalesce_conflicts(state, rstate.blocks);
20112 /* Fix two simultaneous uses of the same register.
20113 * In a few pathlogical cases a partial untangle moves
20114 * the tangle to a part of the graph we won't revisit.
20115 * So we keep looping until we have no more tangle fixes
20116 * to apply.
20118 do {
20119 tangles = correct_tangles(state, rstate.blocks);
20120 } while(tangles);
20123 print_blocks(state, "resolve_tangles", state->dbgout);
20124 verify_consistency(state);
20126 /* Allocate and initialize the live ranges */
20127 initialize_live_ranges(state, &rstate);
20129 /* Note currently doing coalescing in a loop appears to
20130 * buys me nothing. The code is left this way in case
20131 * there is some value in it. Or if a future bugfix
20132 * yields some benefit.
20134 do {
20135 if (state->compiler->debug & DEBUG_COALESCING) {
20136 fprintf(state->errout, "coalescing\n");
20139 /* Remove any previous live edge calculations */
20140 cleanup_live_edges(&rstate);
20142 /* Compute the interference graph */
20143 walk_variable_lifetimes(
20144 state, &state->bb, rstate.blocks,
20145 graph_ins, &rstate);
20147 /* Display the interference graph if desired */
20148 if (state->compiler->debug & DEBUG_INTERFERENCE) {
20149 print_interference_blocks(state, &rstate, state->dbgout, 1);
20150 fprintf(state->dbgout, "\nlive variables by instruction\n");
20151 walk_variable_lifetimes(
20152 state, &state->bb, rstate.blocks,
20153 print_interference_ins, &rstate);
20156 coalesced = coalesce_live_ranges(state, &rstate);
20158 if (state->compiler->debug & DEBUG_COALESCING) {
20159 fprintf(state->errout, "coalesced: %d\n", coalesced);
20161 } while(coalesced);
20163 #if DEBUG_CONSISTENCY > 1
20164 # if 0
20165 fprintf(state->errout, "verify_graph_ins...\n");
20166 # endif
20167 /* Verify the interference graph */
20168 walk_variable_lifetimes(
20169 state, &state->bb, rstate.blocks,
20170 verify_graph_ins, &rstate);
20171 # if 0
20172 fprintf(state->errout, "verify_graph_ins done\n");
20173 #endif
20174 #endif
20176 /* Build the groups low and high. But with the nodes
20177 * first sorted by degree order.
20179 rstate.low_tail = &rstate.low;
20180 rstate.high_tail = &rstate.high;
20181 rstate.high = merge_sort_lr(&rstate.lr[1], &rstate.lr[rstate.ranges]);
20182 if (rstate.high) {
20183 rstate.high->group_prev = &rstate.high;
20185 for(point = &rstate.high; *point; point = &(*point)->group_next)
20187 rstate.high_tail = point;
20188 /* Walk through the high list and move everything that needs
20189 * to be onto low.
20191 for(point = &rstate.high; *point; point = next) {
20192 struct live_range *range;
20193 next = &(*point)->group_next;
20194 range = *point;
20196 /* If it has a low degree or it already has a color
20197 * place the node in low.
20199 if ((range->degree < regc_max_size(state, range->classes)) ||
20200 (range->color != REG_UNSET)) {
20201 cgdebug_printf(state, "Lo: %5td degree %5d%s\n",
20202 range - rstate.lr, range->degree,
20203 (range->color != REG_UNSET) ? " (colored)": "");
20204 *range->group_prev = range->group_next;
20205 if (range->group_next) {
20206 range->group_next->group_prev = range->group_prev;
20208 if (&range->group_next == rstate.high_tail) {
20209 rstate.high_tail = range->group_prev;
20211 range->group_prev = rstate.low_tail;
20212 range->group_next = 0;
20213 *rstate.low_tail = range;
20214 rstate.low_tail = &range->group_next;
20215 next = point;
20217 else {
20218 cgdebug_printf(state, "hi: %5td degree %5d%s\n",
20219 range - rstate.lr, range->degree,
20220 (range->color != REG_UNSET) ? " (colored)": "");
20223 /* Color the live_ranges */
20224 colored = color_graph(state, &rstate);
20225 rstate.passes++;
20226 } while (!colored);
20228 /* Verify the graph was properly colored */
20229 verify_colors(state, &rstate);
20231 /* Move the colors from the graph to the triples */
20232 color_triples(state, &rstate);
20234 /* Cleanup the temporary data structures */
20235 cleanup_rstate(state, &rstate);
20237 /* Display the new graph */
20238 print_blocks(state, __func__, state->dbgout);
20241 /* Sparce Conditional Constant Propogation
20242 * =========================================
20244 struct ssa_edge;
20245 struct flow_block;
20246 struct lattice_node {
20247 unsigned old_id;
20248 struct triple *def;
20249 struct ssa_edge *out;
20250 struct flow_block *fblock;
20251 struct triple *val;
20252 /* lattice high val == def
20253 * lattice const is_const(val)
20254 * lattice low other
20257 struct ssa_edge {
20258 struct lattice_node *src;
20259 struct lattice_node *dst;
20260 struct ssa_edge *work_next;
20261 struct ssa_edge *work_prev;
20262 struct ssa_edge *out_next;
20264 struct flow_edge {
20265 struct flow_block *src;
20266 struct flow_block *dst;
20267 struct flow_edge *work_next;
20268 struct flow_edge *work_prev;
20269 struct flow_edge *in_next;
20270 struct flow_edge *out_next;
20271 int executable;
20273 #define MAX_FLOW_BLOCK_EDGES 3
20274 struct flow_block {
20275 struct block *block;
20276 struct flow_edge *in;
20277 struct flow_edge *out;
20278 struct flow_edge *edges;
20281 struct scc_state {
20282 int ins_count;
20283 struct lattice_node *lattice;
20284 struct ssa_edge *ssa_edges;
20285 struct flow_block *flow_blocks;
20286 struct flow_edge *flow_work_list;
20287 struct ssa_edge *ssa_work_list;
20291 static int is_scc_const(struct compile_state *state, struct triple *ins)
20293 return ins && (triple_is_ubranch(state, ins) || is_const(ins));
20296 static int is_lattice_hi(struct compile_state *state, struct lattice_node *lnode)
20298 return !is_scc_const(state, lnode->val) && (lnode->val == lnode->def);
20301 static int is_lattice_const(struct compile_state *state, struct lattice_node *lnode)
20303 return is_scc_const(state, lnode->val);
20306 static int is_lattice_lo(struct compile_state *state, struct lattice_node *lnode)
20308 return (lnode->val != lnode->def) && !is_scc_const(state, lnode->val);
20311 static void scc_add_fedge(struct compile_state *state, struct scc_state *scc,
20312 struct flow_edge *fedge)
20314 if (state->compiler->debug & DEBUG_SCC_TRANSFORM2) {
20315 fprintf(state->errout, "adding fedge: %p (%4d -> %5d)\n",
20316 fedge,
20317 fedge->src->block?fedge->src->block->last->id: 0,
20318 fedge->dst->block?fedge->dst->block->first->id: 0);
20320 if ((fedge == scc->flow_work_list) ||
20321 (fedge->work_next != fedge) ||
20322 (fedge->work_prev != fedge)) {
20324 if (state->compiler->debug & DEBUG_SCC_TRANSFORM2) {
20325 fprintf(state->errout, "dupped fedge: %p\n",
20326 fedge);
20328 return;
20330 if (!scc->flow_work_list) {
20331 scc->flow_work_list = fedge;
20332 fedge->work_next = fedge->work_prev = fedge;
20334 else {
20335 struct flow_edge *ftail;
20336 ftail = scc->flow_work_list->work_prev;
20337 fedge->work_next = ftail->work_next;
20338 fedge->work_prev = ftail;
20339 fedge->work_next->work_prev = fedge;
20340 fedge->work_prev->work_next = fedge;
20344 static struct flow_edge *scc_next_fedge(
20345 struct compile_state *state, struct scc_state *scc)
20347 struct flow_edge *fedge;
20348 fedge = scc->flow_work_list;
20349 if (fedge) {
20350 fedge->work_next->work_prev = fedge->work_prev;
20351 fedge->work_prev->work_next = fedge->work_next;
20352 if (fedge->work_next != fedge) {
20353 scc->flow_work_list = fedge->work_next;
20354 } else {
20355 scc->flow_work_list = 0;
20357 fedge->work_next = fedge->work_prev = fedge;
20359 return fedge;
20362 static void scc_add_sedge(struct compile_state *state, struct scc_state *scc,
20363 struct ssa_edge *sedge)
20365 if (state->compiler->debug & DEBUG_SCC_TRANSFORM2) {
20366 fprintf(state->errout, "adding sedge: %5ld (%4d -> %5d)\n",
20367 (long)(sedge - scc->ssa_edges),
20368 sedge->src->def->id,
20369 sedge->dst->def->id);
20371 if ((sedge == scc->ssa_work_list) ||
20372 (sedge->work_next != sedge) ||
20373 (sedge->work_prev != sedge)) {
20375 if (state->compiler->debug & DEBUG_SCC_TRANSFORM2) {
20376 fprintf(state->errout, "dupped sedge: %5ld\n",
20377 (long)(sedge - scc->ssa_edges));
20379 return;
20381 if (!scc->ssa_work_list) {
20382 scc->ssa_work_list = sedge;
20383 sedge->work_next = sedge->work_prev = sedge;
20385 else {
20386 struct ssa_edge *stail;
20387 stail = scc->ssa_work_list->work_prev;
20388 sedge->work_next = stail->work_next;
20389 sedge->work_prev = stail;
20390 sedge->work_next->work_prev = sedge;
20391 sedge->work_prev->work_next = sedge;
20395 static struct ssa_edge *scc_next_sedge(
20396 struct compile_state *state, struct scc_state *scc)
20398 struct ssa_edge *sedge;
20399 sedge = scc->ssa_work_list;
20400 if (sedge) {
20401 sedge->work_next->work_prev = sedge->work_prev;
20402 sedge->work_prev->work_next = sedge->work_next;
20403 if (sedge->work_next != sedge) {
20404 scc->ssa_work_list = sedge->work_next;
20405 } else {
20406 scc->ssa_work_list = 0;
20408 sedge->work_next = sedge->work_prev = sedge;
20410 return sedge;
20413 static void initialize_scc_state(
20414 struct compile_state *state, struct scc_state *scc)
20416 int ins_count, ssa_edge_count;
20417 int ins_index, ssa_edge_index, fblock_index;
20418 struct triple *first, *ins;
20419 struct block *block;
20420 struct flow_block *fblock;
20422 memset(scc, 0, sizeof(*scc));
20424 /* Inialize pass zero find out how much memory we need */
20425 first = state->first;
20426 ins = first;
20427 ins_count = ssa_edge_count = 0;
20428 do {
20429 struct triple_set *edge;
20430 ins_count += 1;
20431 for(edge = ins->use; edge; edge = edge->next) {
20432 ssa_edge_count++;
20434 ins = ins->next;
20435 } while(ins != first);
20436 if (state->compiler->debug & DEBUG_SCC_TRANSFORM) {
20437 fprintf(state->errout, "ins_count: %d ssa_edge_count: %d vertex_count: %d\n",
20438 ins_count, ssa_edge_count, state->bb.last_vertex);
20440 scc->ins_count = ins_count;
20441 scc->lattice =
20442 xcmalloc(sizeof(*scc->lattice)*(ins_count + 1), "lattice");
20443 scc->ssa_edges =
20444 xcmalloc(sizeof(*scc->ssa_edges)*(ssa_edge_count + 1), "ssa_edges");
20445 scc->flow_blocks =
20446 xcmalloc(sizeof(*scc->flow_blocks)*(state->bb.last_vertex + 1),
20447 "flow_blocks");
20449 /* Initialize pass one collect up the nodes */
20450 fblock = 0;
20451 block = 0;
20452 ins_index = ssa_edge_index = fblock_index = 0;
20453 ins = first;
20454 do {
20455 if ((ins->op == OP_LABEL) && (block != ins->u.block)) {
20456 block = ins->u.block;
20457 if (!block) {
20458 internal_error(state, ins, "label without block");
20460 fblock_index += 1;
20461 block->vertex = fblock_index;
20462 fblock = &scc->flow_blocks[fblock_index];
20463 fblock->block = block;
20464 fblock->edges = xcmalloc(sizeof(*fblock->edges)*block->edge_count,
20465 "flow_edges");
20468 struct lattice_node *lnode;
20469 ins_index += 1;
20470 lnode = &scc->lattice[ins_index];
20471 lnode->def = ins;
20472 lnode->out = 0;
20473 lnode->fblock = fblock;
20474 lnode->val = ins; /* LATTICE HIGH */
20475 if (lnode->val->op == OP_UNKNOWNVAL) {
20476 lnode->val = 0; /* LATTICE LOW by definition */
20478 lnode->old_id = ins->id;
20479 ins->id = ins_index;
20481 ins = ins->next;
20482 } while(ins != first);
20483 /* Initialize pass two collect up the edges */
20484 block = 0;
20485 fblock = 0;
20486 ins = first;
20487 do {
20489 struct triple_set *edge;
20490 struct ssa_edge **stail;
20491 struct lattice_node *lnode;
20492 lnode = &scc->lattice[ins->id];
20493 lnode->out = 0;
20494 stail = &lnode->out;
20495 for(edge = ins->use; edge; edge = edge->next) {
20496 struct ssa_edge *sedge;
20497 ssa_edge_index += 1;
20498 sedge = &scc->ssa_edges[ssa_edge_index];
20499 *stail = sedge;
20500 stail = &sedge->out_next;
20501 sedge->src = lnode;
20502 sedge->dst = &scc->lattice[edge->member->id];
20503 sedge->work_next = sedge->work_prev = sedge;
20504 sedge->out_next = 0;
20507 if ((ins->op == OP_LABEL) && (block != ins->u.block)) {
20508 struct flow_edge *fedge, **ftail;
20509 struct block_set *bedge;
20510 block = ins->u.block;
20511 fblock = &scc->flow_blocks[block->vertex];
20512 fblock->in = 0;
20513 fblock->out = 0;
20514 ftail = &fblock->out;
20516 fedge = fblock->edges;
20517 bedge = block->edges;
20518 for(; bedge; bedge = bedge->next, fedge++) {
20519 fedge->dst = &scc->flow_blocks[bedge->member->vertex];
20520 if (fedge->dst->block != bedge->member) {
20521 internal_error(state, 0, "block mismatch");
20523 *ftail = fedge;
20524 ftail = &fedge->out_next;
20525 fedge->out_next = 0;
20527 for(fedge = fblock->out; fedge; fedge = fedge->out_next) {
20528 fedge->src = fblock;
20529 fedge->work_next = fedge->work_prev = fedge;
20530 fedge->executable = 0;
20533 ins = ins->next;
20534 } while (ins != first);
20535 block = 0;
20536 fblock = 0;
20537 ins = first;
20538 do {
20539 if ((ins->op == OP_LABEL) && (block != ins->u.block)) {
20540 struct flow_edge **ftail;
20541 struct block_set *bedge;
20542 block = ins->u.block;
20543 fblock = &scc->flow_blocks[block->vertex];
20544 ftail = &fblock->in;
20545 for(bedge = block->use; bedge; bedge = bedge->next) {
20546 struct block *src_block;
20547 struct flow_block *sfblock;
20548 struct flow_edge *sfedge;
20549 src_block = bedge->member;
20550 sfblock = &scc->flow_blocks[src_block->vertex];
20551 for(sfedge = sfblock->out; sfedge; sfedge = sfedge->out_next) {
20552 if (sfedge->dst == fblock) {
20553 break;
20556 if (!sfedge) {
20557 internal_error(state, 0, "edge mismatch");
20559 *ftail = sfedge;
20560 ftail = &sfedge->in_next;
20561 sfedge->in_next = 0;
20564 ins = ins->next;
20565 } while(ins != first);
20566 /* Setup a dummy block 0 as a node above the start node */
20568 struct flow_block *fblock, *dst;
20569 struct flow_edge *fedge;
20570 fblock = &scc->flow_blocks[0];
20571 fblock->block = 0;
20572 fblock->edges = xcmalloc(sizeof(*fblock->edges)*1, "flow_edges");
20573 fblock->in = 0;
20574 fblock->out = fblock->edges;
20575 dst = &scc->flow_blocks[state->bb.first_block->vertex];
20576 fedge = fblock->edges;
20577 fedge->src = fblock;
20578 fedge->dst = dst;
20579 fedge->work_next = fedge;
20580 fedge->work_prev = fedge;
20581 fedge->in_next = fedge->dst->in;
20582 fedge->out_next = 0;
20583 fedge->executable = 0;
20584 fedge->dst->in = fedge;
20586 /* Initialize the work lists */
20587 scc->flow_work_list = 0;
20588 scc->ssa_work_list = 0;
20589 scc_add_fedge(state, scc, fedge);
20591 if (state->compiler->debug & DEBUG_SCC_TRANSFORM) {
20592 fprintf(state->errout, "ins_index: %d ssa_edge_index: %d fblock_index: %d\n",
20593 ins_index, ssa_edge_index, fblock_index);
20598 static void free_scc_state(
20599 struct compile_state *state, struct scc_state *scc)
20601 int i;
20602 for(i = 0; i < state->bb.last_vertex + 1; i++) {
20603 struct flow_block *fblock;
20604 fblock = &scc->flow_blocks[i];
20605 if (fblock->edges) {
20606 xfree(fblock->edges);
20607 fblock->edges = 0;
20610 xfree(scc->flow_blocks);
20611 xfree(scc->ssa_edges);
20612 xfree(scc->lattice);
20616 static struct lattice_node *triple_to_lattice(
20617 struct compile_state *state, struct scc_state *scc, struct triple *ins)
20619 if (ins->id <= 0) {
20620 internal_error(state, ins, "bad id");
20622 return &scc->lattice[ins->id];
20625 static struct triple *preserve_lval(
20626 struct compile_state *state, struct lattice_node *lnode)
20628 struct triple *old;
20629 /* Preserve the original value */
20630 if (lnode->val) {
20631 old = dup_triple(state, lnode->val);
20632 if (lnode->val != lnode->def) {
20633 xfree(lnode->val);
20635 lnode->val = 0;
20636 } else {
20637 old = 0;
20639 return old;
20642 static int lval_changed(struct compile_state *state,
20643 struct triple *old, struct lattice_node *lnode)
20645 int changed;
20646 /* See if the lattice value has changed */
20647 changed = 1;
20648 if (!old && !lnode->val) {
20649 changed = 0;
20651 if (changed &&
20652 lnode->val && old &&
20653 (memcmp(lnode->val->param, old->param,
20654 TRIPLE_SIZE(lnode->val) * sizeof(lnode->val->param[0])) == 0) &&
20655 (memcmp(&lnode->val->u, &old->u, sizeof(old->u)) == 0)) {
20656 changed = 0;
20658 if (old) {
20659 xfree(old);
20661 return changed;
20665 static void scc_debug_lnode(
20666 struct compile_state *state, struct scc_state *scc,
20667 struct lattice_node *lnode, int changed)
20669 if ((state->compiler->debug & DEBUG_SCC_TRANSFORM2) && lnode->val) {
20670 display_triple_changes(state->errout, lnode->val, lnode->def);
20672 if (state->compiler->debug & DEBUG_SCC_TRANSFORM) {
20673 FILE *fp = state->errout;
20674 struct triple *val, **expr;
20675 val = lnode->val? lnode->val : lnode->def;
20676 fprintf(fp, "%p %s %3d %10s (",
20677 lnode->def,
20678 ((lnode->def->op == OP_PHI)? "phi: ": "expr:"),
20679 lnode->def->id,
20680 tops(lnode->def->op));
20681 expr = triple_rhs(state, lnode->def, 0);
20682 for(;expr;expr = triple_rhs(state, lnode->def, expr)) {
20683 if (*expr) {
20684 fprintf(fp, " %d", (*expr)->id);
20687 if (val->op == OP_INTCONST) {
20688 fprintf(fp, " <0x%08lx>", (unsigned long)(val->u.cval));
20690 fprintf(fp, " ) -> %s %s\n",
20691 (is_lattice_hi(state, lnode)? "hi":
20692 is_lattice_const(state, lnode)? "const" : "lo"),
20693 changed? "changed" : ""
20698 static int compute_lnode_val(struct compile_state *state, struct scc_state *scc,
20699 struct lattice_node *lnode)
20701 int changed;
20702 struct triple *old, *scratch;
20703 struct triple **dexpr, **vexpr;
20704 int count, i;
20706 /* Store the original value */
20707 old = preserve_lval(state, lnode);
20709 /* Reinitialize the value */
20710 lnode->val = scratch = dup_triple(state, lnode->def);
20711 scratch->id = lnode->old_id;
20712 scratch->next = scratch;
20713 scratch->prev = scratch;
20714 scratch->use = 0;
20716 count = TRIPLE_SIZE(scratch);
20717 for(i = 0; i < count; i++) {
20718 dexpr = &lnode->def->param[i];
20719 vexpr = &scratch->param[i];
20720 *vexpr = *dexpr;
20721 if (((i < TRIPLE_MISC_OFF(scratch)) ||
20722 (i >= TRIPLE_TARG_OFF(scratch))) &&
20723 *dexpr) {
20724 struct lattice_node *tmp;
20725 tmp = triple_to_lattice(state, scc, *dexpr);
20726 *vexpr = (tmp->val)? tmp->val : tmp->def;
20729 if (triple_is_branch(state, scratch)) {
20730 scratch->next = lnode->def->next;
20732 /* Recompute the value */
20733 #if DEBUG_ROMCC_WARNINGS
20734 #warning "FIXME see if simplify does anything bad"
20735 #endif
20736 /* So far it looks like only the strength reduction
20737 * optimization are things I need to worry about.
20739 simplify(state, scratch);
20740 /* Cleanup my value */
20741 if (scratch->use) {
20742 internal_error(state, lnode->def, "scratch used?");
20744 if ((scratch->prev != scratch) ||
20745 ((scratch->next != scratch) &&
20746 (!triple_is_branch(state, lnode->def) ||
20747 (scratch->next != lnode->def->next)))) {
20748 internal_error(state, lnode->def, "scratch in list?");
20750 /* undo any uses... */
20751 count = TRIPLE_SIZE(scratch);
20752 for(i = 0; i < count; i++) {
20753 vexpr = &scratch->param[i];
20754 if (*vexpr) {
20755 unuse_triple(*vexpr, scratch);
20758 if (lnode->val->op == OP_UNKNOWNVAL) {
20759 lnode->val = 0; /* Lattice low by definition */
20761 /* Find the case when I am lattice high */
20762 if (lnode->val &&
20763 (lnode->val->op == lnode->def->op) &&
20764 (memcmp(lnode->val->param, lnode->def->param,
20765 count * sizeof(lnode->val->param[0])) == 0) &&
20766 (memcmp(&lnode->val->u, &lnode->def->u, sizeof(lnode->def->u)) == 0)) {
20767 lnode->val = lnode->def;
20769 /* Only allow lattice high when all of my inputs
20770 * are also lattice high. Occasionally I can
20771 * have constants with a lattice low input, so
20772 * I do not need to check that case.
20774 if (is_lattice_hi(state, lnode)) {
20775 struct lattice_node *tmp;
20776 int rhs;
20777 rhs = lnode->val->rhs;
20778 for(i = 0; i < rhs; i++) {
20779 tmp = triple_to_lattice(state, scc, RHS(lnode->val, i));
20780 if (!is_lattice_hi(state, tmp)) {
20781 lnode->val = 0;
20782 break;
20786 /* Find the cases that are always lattice lo */
20787 if (lnode->val &&
20788 triple_is_def(state, lnode->val) &&
20789 !triple_is_pure(state, lnode->val, lnode->old_id)) {
20790 lnode->val = 0;
20792 /* See if the lattice value has changed */
20793 changed = lval_changed(state, old, lnode);
20794 /* See if this value should not change */
20795 if ((lnode->val != lnode->def) &&
20796 (( !triple_is_def(state, lnode->def) &&
20797 !triple_is_cbranch(state, lnode->def)) ||
20798 (lnode->def->op == OP_PIECE))) {
20799 #if DEBUG_ROMCC_WARNINGS
20800 #warning "FIXME constant propagate through expressions with multiple left hand sides"
20801 #endif
20802 if (changed) {
20803 internal_warning(state, lnode->def, "non def changes value?");
20805 lnode->val = 0;
20808 /* See if we need to free the scratch value */
20809 if (lnode->val != scratch) {
20810 xfree(scratch);
20813 return changed;
20817 static void scc_visit_cbranch(struct compile_state *state, struct scc_state *scc,
20818 struct lattice_node *lnode)
20820 struct lattice_node *cond;
20821 struct flow_edge *left, *right;
20822 int changed;
20824 /* Update the branch value */
20825 changed = compute_lnode_val(state, scc, lnode);
20826 scc_debug_lnode(state, scc, lnode, changed);
20828 /* This only applies to conditional branches */
20829 if (!triple_is_cbranch(state, lnode->def)) {
20830 internal_error(state, lnode->def, "not a conditional branch");
20833 if (state->compiler->debug & DEBUG_SCC_TRANSFORM) {
20834 struct flow_edge *fedge;
20835 FILE *fp = state->errout;
20836 fprintf(fp, "%s: %d (",
20837 tops(lnode->def->op),
20838 lnode->def->id);
20840 for(fedge = lnode->fblock->out; fedge; fedge = fedge->out_next) {
20841 fprintf(fp, " %d", fedge->dst->block->vertex);
20843 fprintf(fp, " )");
20844 if (lnode->def->rhs > 0) {
20845 fprintf(fp, " <- %d",
20846 RHS(lnode->def, 0)->id);
20848 fprintf(fp, "\n");
20850 cond = triple_to_lattice(state, scc, RHS(lnode->def,0));
20851 for(left = cond->fblock->out; left; left = left->out_next) {
20852 if (left->dst->block->first == lnode->def->next) {
20853 break;
20856 if (!left) {
20857 internal_error(state, lnode->def, "Cannot find left branch edge");
20859 for(right = cond->fblock->out; right; right = right->out_next) {
20860 if (right->dst->block->first == TARG(lnode->def, 0)) {
20861 break;
20864 if (!right) {
20865 internal_error(state, lnode->def, "Cannot find right branch edge");
20867 /* I should only come here if the controlling expressions value
20868 * has changed, which means it must be either a constant or lo.
20870 if (is_lattice_hi(state, cond)) {
20871 internal_error(state, cond->def, "condition high?");
20872 return;
20874 if (is_lattice_lo(state, cond)) {
20875 scc_add_fedge(state, scc, left);
20876 scc_add_fedge(state, scc, right);
20878 else if (cond->val->u.cval) {
20879 scc_add_fedge(state, scc, right);
20880 } else {
20881 scc_add_fedge(state, scc, left);
20887 static void scc_add_sedge_dst(struct compile_state *state,
20888 struct scc_state *scc, struct ssa_edge *sedge)
20890 if (triple_is_cbranch(state, sedge->dst->def)) {
20891 scc_visit_cbranch(state, scc, sedge->dst);
20893 else if (triple_is_def(state, sedge->dst->def)) {
20894 scc_add_sedge(state, scc, sedge);
20898 static void scc_visit_phi(struct compile_state *state, struct scc_state *scc,
20899 struct lattice_node *lnode)
20901 struct lattice_node *tmp;
20902 struct triple **slot, *old;
20903 struct flow_edge *fedge;
20904 int changed;
20905 int index;
20906 if (lnode->def->op != OP_PHI) {
20907 internal_error(state, lnode->def, "not phi");
20909 /* Store the original value */
20910 old = preserve_lval(state, lnode);
20912 /* default to lattice high */
20913 lnode->val = lnode->def;
20914 slot = &RHS(lnode->def, 0);
20915 index = 0;
20916 for(fedge = lnode->fblock->in; fedge; index++, fedge = fedge->in_next) {
20917 if (state->compiler->debug & DEBUG_SCC_TRANSFORM) {
20918 fprintf(state->errout, "Examining edge: %d vertex: %d executable: %d\n",
20919 index,
20920 fedge->dst->block->vertex,
20921 fedge->executable
20924 if (!fedge->executable) {
20925 continue;
20927 if (!slot[index]) {
20928 internal_error(state, lnode->def, "no phi value");
20930 tmp = triple_to_lattice(state, scc, slot[index]);
20931 /* meet(X, lattice low) = lattice low */
20932 if (is_lattice_lo(state, tmp)) {
20933 lnode->val = 0;
20935 /* meet(X, lattice high) = X */
20936 else if (is_lattice_hi(state, tmp)) {
20938 /* meet(lattice high, X) = X */
20939 else if (is_lattice_hi(state, lnode)) {
20940 lnode->val = dup_triple(state, tmp->val);
20941 /* Only change the type if necessary */
20942 if (!is_subset_type(lnode->def->type, tmp->val->type)) {
20943 lnode->val->type = lnode->def->type;
20946 /* meet(const, const) = const or lattice low */
20947 else if (lnode->val != 0 &&
20948 !constants_equal(state, lnode->val, tmp->val)) {
20949 lnode->val = 0;
20952 /* meet(lattice low, X) = lattice low */
20953 if (is_lattice_lo(state, lnode)) {
20954 lnode->val = 0;
20955 break;
20958 changed = lval_changed(state, old, lnode);
20959 scc_debug_lnode(state, scc, lnode, changed);
20961 /* If the lattice value has changed update the work lists. */
20962 if (changed) {
20963 struct ssa_edge *sedge;
20964 for(sedge = lnode->out; sedge; sedge = sedge->out_next) {
20965 scc_add_sedge_dst(state, scc, sedge);
20971 static void scc_visit_expr(struct compile_state *state, struct scc_state *scc,
20972 struct lattice_node *lnode)
20974 int changed;
20976 if (!triple_is_def(state, lnode->def)) {
20977 internal_warning(state, lnode->def, "not visiting an expression?");
20979 changed = compute_lnode_val(state, scc, lnode);
20980 scc_debug_lnode(state, scc, lnode, changed);
20982 if (changed) {
20983 struct ssa_edge *sedge;
20984 for(sedge = lnode->out; sedge; sedge = sedge->out_next) {
20985 scc_add_sedge_dst(state, scc, sedge);
20990 static void scc_writeback_values(
20991 struct compile_state *state, struct scc_state *scc)
20993 struct triple *first, *ins;
20994 first = state->first;
20995 ins = first;
20996 do {
20997 struct lattice_node *lnode;
20998 lnode = triple_to_lattice(state, scc, ins);
20999 if (state->compiler->debug & DEBUG_SCC_TRANSFORM) {
21000 if (is_lattice_hi(state, lnode) &&
21001 (lnode->val->op != OP_NOOP))
21003 struct flow_edge *fedge;
21004 int executable;
21005 executable = 0;
21006 for(fedge = lnode->fblock->in;
21007 !executable && fedge; fedge = fedge->in_next) {
21008 executable |= fedge->executable;
21010 if (executable) {
21011 internal_warning(state, lnode->def,
21012 "lattice node %d %s->%s still high?",
21013 ins->id,
21014 tops(lnode->def->op),
21015 tops(lnode->val->op));
21020 /* Restore id */
21021 ins->id = lnode->old_id;
21022 if (lnode->val && (lnode->val != ins)) {
21023 /* See if it something I know how to write back */
21024 switch(lnode->val->op) {
21025 case OP_INTCONST:
21026 mkconst(state, ins, lnode->val->u.cval);
21027 break;
21028 case OP_ADDRCONST:
21029 mkaddr_const(state, ins,
21030 MISC(lnode->val, 0), lnode->val->u.cval);
21031 break;
21032 default:
21033 /* By default don't copy the changes,
21034 * recompute them in place instead.
21036 simplify(state, ins);
21037 break;
21039 if (is_const(lnode->val) &&
21040 !constants_equal(state, lnode->val, ins)) {
21041 internal_error(state, 0, "constants not equal");
21043 /* Free the lattice nodes */
21044 xfree(lnode->val);
21045 lnode->val = 0;
21047 ins = ins->next;
21048 } while(ins != first);
21051 static void scc_transform(struct compile_state *state)
21053 struct scc_state scc;
21054 if (!(state->compiler->flags & COMPILER_SCC_TRANSFORM)) {
21055 return;
21058 initialize_scc_state(state, &scc);
21060 while(scc.flow_work_list || scc.ssa_work_list) {
21061 struct flow_edge *fedge;
21062 struct ssa_edge *sedge;
21063 struct flow_edge *fptr;
21064 while((fedge = scc_next_fedge(state, &scc))) {
21065 struct block *block;
21066 struct triple *ptr;
21067 struct flow_block *fblock;
21068 int reps;
21069 int done;
21070 if (fedge->executable) {
21071 continue;
21073 if (!fedge->dst) {
21074 internal_error(state, 0, "fedge without dst");
21076 if (!fedge->src) {
21077 internal_error(state, 0, "fedge without src");
21079 fedge->executable = 1;
21080 fblock = fedge->dst;
21081 block = fblock->block;
21082 reps = 0;
21083 for(fptr = fblock->in; fptr; fptr = fptr->in_next) {
21084 if (fptr->executable) {
21085 reps++;
21089 if (state->compiler->debug & DEBUG_SCC_TRANSFORM) {
21090 fprintf(state->errout, "vertex: %d reps: %d\n",
21091 block->vertex, reps);
21094 done = 0;
21095 for(ptr = block->first; !done; ptr = ptr->next) {
21096 struct lattice_node *lnode;
21097 done = (ptr == block->last);
21098 lnode = &scc.lattice[ptr->id];
21099 if (ptr->op == OP_PHI) {
21100 scc_visit_phi(state, &scc, lnode);
21102 else if ((reps == 1) && triple_is_def(state, ptr))
21104 scc_visit_expr(state, &scc, lnode);
21107 /* Add unconditional branch edges */
21108 if (!triple_is_cbranch(state, fblock->block->last)) {
21109 struct flow_edge *out;
21110 for(out = fblock->out; out; out = out->out_next) {
21111 scc_add_fedge(state, &scc, out);
21115 while((sedge = scc_next_sedge(state, &scc))) {
21116 struct lattice_node *lnode;
21117 struct flow_block *fblock;
21118 lnode = sedge->dst;
21119 fblock = lnode->fblock;
21121 if (state->compiler->debug & DEBUG_SCC_TRANSFORM) {
21122 fprintf(state->errout, "sedge: %5ld (%5d -> %5d)\n",
21123 (unsigned long)sedge - (unsigned long)scc.ssa_edges,
21124 sedge->src->def->id,
21125 sedge->dst->def->id);
21128 if (lnode->def->op == OP_PHI) {
21129 scc_visit_phi(state, &scc, lnode);
21131 else {
21132 for(fptr = fblock->in; fptr; fptr = fptr->in_next) {
21133 if (fptr->executable) {
21134 break;
21137 if (fptr) {
21138 scc_visit_expr(state, &scc, lnode);
21144 scc_writeback_values(state, &scc);
21145 free_scc_state(state, &scc);
21146 rebuild_ssa_form(state);
21148 print_blocks(state, __func__, state->dbgout);
21152 static void transform_to_arch_instructions(struct compile_state *state)
21154 struct triple *ins, *first;
21155 first = state->first;
21156 ins = first;
21157 do {
21158 ins = transform_to_arch_instruction(state, ins);
21159 } while(ins != first);
21161 print_blocks(state, __func__, state->dbgout);
21164 #if DEBUG_CONSISTENCY
21165 static void verify_uses(struct compile_state *state)
21167 struct triple *first, *ins;
21168 struct triple_set *set;
21169 first = state->first;
21170 ins = first;
21171 do {
21172 struct triple **expr;
21173 expr = triple_rhs(state, ins, 0);
21174 for(; expr; expr = triple_rhs(state, ins, expr)) {
21175 struct triple *rhs;
21176 rhs = *expr;
21177 for(set = rhs?rhs->use:0; set; set = set->next) {
21178 if (set->member == ins) {
21179 break;
21182 if (!set) {
21183 internal_error(state, ins, "rhs not used");
21186 expr = triple_lhs(state, ins, 0);
21187 for(; expr; expr = triple_lhs(state, ins, expr)) {
21188 struct triple *lhs;
21189 lhs = *expr;
21190 for(set = lhs?lhs->use:0; set; set = set->next) {
21191 if (set->member == ins) {
21192 break;
21195 if (!set) {
21196 internal_error(state, ins, "lhs not used");
21199 expr = triple_misc(state, ins, 0);
21200 if (ins->op != OP_PHI) {
21201 for(; expr; expr = triple_targ(state, ins, expr)) {
21202 struct triple *misc;
21203 misc = *expr;
21204 for(set = misc?misc->use:0; set; set = set->next) {
21205 if (set->member == ins) {
21206 break;
21209 if (!set) {
21210 internal_error(state, ins, "misc not used");
21214 if (!triple_is_ret(state, ins)) {
21215 expr = triple_targ(state, ins, 0);
21216 for(; expr; expr = triple_targ(state, ins, expr)) {
21217 struct triple *targ;
21218 targ = *expr;
21219 for(set = targ?targ->use:0; set; set = set->next) {
21220 if (set->member == ins) {
21221 break;
21224 if (!set) {
21225 internal_error(state, ins, "targ not used");
21229 ins = ins->next;
21230 } while(ins != first);
21233 static void verify_blocks_present(struct compile_state *state)
21235 struct triple *first, *ins;
21236 if (!state->bb.first_block) {
21237 return;
21239 first = state->first;
21240 ins = first;
21241 do {
21242 valid_ins(state, ins);
21243 if (triple_stores_block(state, ins)) {
21244 if (!ins->u.block) {
21245 internal_error(state, ins,
21246 "%p not in a block?", ins);
21249 ins = ins->next;
21250 } while(ins != first);
21255 static int edge_present(struct compile_state *state, struct block *block, struct triple *edge)
21257 struct block_set *bedge;
21258 struct block *targ;
21259 targ = block_of_triple(state, edge);
21260 for(bedge = block->edges; bedge; bedge = bedge->next) {
21261 if (bedge->member == targ) {
21262 return 1;
21265 return 0;
21268 static void verify_blocks(struct compile_state *state)
21270 struct triple *ins;
21271 struct block *block;
21272 int blocks;
21273 block = state->bb.first_block;
21274 if (!block) {
21275 return;
21277 blocks = 0;
21278 do {
21279 int users;
21280 struct block_set *user, *edge;
21281 blocks++;
21282 for(ins = block->first; ins != block->last->next; ins = ins->next) {
21283 if (triple_stores_block(state, ins) && (ins->u.block != block)) {
21284 internal_error(state, ins, "inconsitent block specified");
21286 valid_ins(state, ins);
21288 users = 0;
21289 for(user = block->use; user; user = user->next) {
21290 users++;
21291 if (!user->member->first) {
21292 internal_error(state, block->first, "user is empty");
21294 if ((block == state->bb.last_block) &&
21295 (user->member == state->bb.first_block)) {
21296 continue;
21298 for(edge = user->member->edges; edge; edge = edge->next) {
21299 if (edge->member == block) {
21300 break;
21303 if (!edge) {
21304 internal_error(state, user->member->first,
21305 "user does not use block");
21308 if (triple_is_branch(state, block->last)) {
21309 struct triple **expr;
21310 expr = triple_edge_targ(state, block->last, 0);
21311 for(;expr; expr = triple_edge_targ(state, block->last, expr)) {
21312 if (*expr && !edge_present(state, block, *expr)) {
21313 internal_error(state, block->last, "no edge to targ");
21317 if (!triple_is_ubranch(state, block->last) &&
21318 (block != state->bb.last_block) &&
21319 !edge_present(state, block, block->last->next)) {
21320 internal_error(state, block->last, "no edge to block->last->next");
21322 for(edge = block->edges; edge; edge = edge->next) {
21323 for(user = edge->member->use; user; user = user->next) {
21324 if (user->member == block) {
21325 break;
21328 if (!user || user->member != block) {
21329 internal_error(state, block->first,
21330 "block does not use edge");
21332 if (!edge->member->first) {
21333 internal_error(state, block->first, "edge block is empty");
21336 if (block->users != users) {
21337 internal_error(state, block->first,
21338 "computed users %d != stored users %d",
21339 users, block->users);
21341 if (!(block->last->next) || !(block->last->next->u.block)) {
21342 internal_error(state, block->last,
21343 "bad next block");
21345 if (!triple_stores_block(state, block->last->next)) {
21346 internal_error(state, block->last->next,
21347 "cannot find next block");
21349 block = block->last->next->u.block;
21350 } while(block != state->bb.first_block);
21351 if (blocks != state->bb.last_vertex) {
21352 internal_error(state, 0, "computed blocks: %d != stored blocks %d",
21353 blocks, state->bb.last_vertex);
21357 static void verify_domination(struct compile_state *state)
21359 struct triple *first, *ins;
21360 struct triple_set *set;
21361 if (!state->bb.first_block) {
21362 return;
21365 first = state->first;
21366 ins = first;
21367 do {
21368 for(set = ins->use; set; set = set->next) {
21369 struct triple **slot;
21370 struct triple *use_point;
21371 int i, zrhs;
21372 use_point = 0;
21373 zrhs = set->member->rhs;
21374 slot = &RHS(set->member, 0);
21375 /* See if the use is on the right hand side */
21376 for(i = 0; i < zrhs; i++) {
21377 if (slot[i] == ins) {
21378 break;
21381 if (i < zrhs) {
21382 use_point = set->member;
21383 if (set->member->op == OP_PHI) {
21384 struct block_set *bset;
21385 int edge;
21386 bset = set->member->u.block->use;
21387 for(edge = 0; bset && (edge < i); edge++) {
21388 bset = bset->next;
21390 if (!bset) {
21391 internal_error(state, set->member,
21392 "no edge for phi rhs %d", i);
21394 use_point = bset->member->last;
21397 if (use_point &&
21398 !tdominates(state, ins, use_point)) {
21399 if (is_const(ins)) {
21400 internal_warning(state, ins,
21401 "non dominated rhs use point %p?", use_point);
21403 else {
21404 internal_error(state, ins,
21405 "non dominated rhs use point %p?", use_point);
21409 ins = ins->next;
21410 } while(ins != first);
21413 static void verify_rhs(struct compile_state *state)
21415 struct triple *first, *ins;
21416 first = state->first;
21417 ins = first;
21418 do {
21419 struct triple **slot;
21420 int zrhs, i;
21421 zrhs = ins->rhs;
21422 slot = &RHS(ins, 0);
21423 for(i = 0; i < zrhs; i++) {
21424 if (slot[i] == 0) {
21425 internal_error(state, ins,
21426 "missing rhs %d on %s",
21427 i, tops(ins->op));
21429 if ((ins->op != OP_PHI) && (slot[i] == ins)) {
21430 internal_error(state, ins,
21431 "ins == rhs[%d] on %s",
21432 i, tops(ins->op));
21435 ins = ins->next;
21436 } while(ins != first);
21439 static void verify_piece(struct compile_state *state)
21441 struct triple *first, *ins;
21442 first = state->first;
21443 ins = first;
21444 do {
21445 struct triple *ptr;
21446 int lhs, i;
21447 lhs = ins->lhs;
21448 for(ptr = ins->next, i = 0; i < lhs; i++, ptr = ptr->next) {
21449 if (ptr != LHS(ins, i)) {
21450 internal_error(state, ins, "malformed lhs on %s",
21451 tops(ins->op));
21453 if (ptr->op != OP_PIECE) {
21454 internal_error(state, ins, "bad lhs op %s at %d on %s",
21455 tops(ptr->op), i, tops(ins->op));
21457 if (ptr->u.cval != i) {
21458 internal_error(state, ins, "bad u.cval of %d %d expected",
21459 ptr->u.cval, i);
21462 ins = ins->next;
21463 } while(ins != first);
21466 static void verify_ins_colors(struct compile_state *state)
21468 struct triple *first, *ins;
21470 first = state->first;
21471 ins = first;
21472 do {
21473 ins = ins->next;
21474 } while(ins != first);
21477 static void verify_unknown(struct compile_state *state)
21479 struct triple *first, *ins;
21480 if ( (unknown_triple.next != &unknown_triple) ||
21481 (unknown_triple.prev != &unknown_triple) ||
21482 #if 0
21483 (unknown_triple.use != 0) ||
21484 #endif
21485 (unknown_triple.op != OP_UNKNOWNVAL) ||
21486 (unknown_triple.lhs != 0) ||
21487 (unknown_triple.rhs != 0) ||
21488 (unknown_triple.misc != 0) ||
21489 (unknown_triple.targ != 0) ||
21490 (unknown_triple.template_id != 0) ||
21491 (unknown_triple.id != -1) ||
21492 (unknown_triple.type != &unknown_type) ||
21493 (unknown_triple.occurrence != &dummy_occurrence) ||
21494 (unknown_triple.param[0] != 0) ||
21495 (unknown_triple.param[1] != 0)) {
21496 internal_error(state, &unknown_triple, "unknown_triple corrupted!");
21498 if ( (dummy_occurrence.count != 2) ||
21499 (strcmp(dummy_occurrence.filename, __FILE__) != 0) ||
21500 (strcmp(dummy_occurrence.function, "") != 0) ||
21501 (dummy_occurrence.col != 0) ||
21502 (dummy_occurrence.parent != 0)) {
21503 internal_error(state, &unknown_triple, "dummy_occurrence corrupted!");
21505 if ( (unknown_type.type != TYPE_UNKNOWN)) {
21506 internal_error(state, &unknown_triple, "unknown_type corrupted!");
21508 first = state->first;
21509 ins = first;
21510 do {
21511 int params, i;
21512 if (ins == &unknown_triple) {
21513 internal_error(state, ins, "unknown triple in list");
21515 params = TRIPLE_SIZE(ins);
21516 for(i = 0; i < params; i++) {
21517 if (ins->param[i] == &unknown_triple) {
21518 internal_error(state, ins, "unknown triple used!");
21521 ins = ins->next;
21522 } while(ins != first);
21525 static void verify_types(struct compile_state *state)
21527 struct triple *first, *ins;
21528 first = state->first;
21529 ins = first;
21530 do {
21531 struct type *invalid;
21532 invalid = invalid_type(state, ins->type);
21533 if (invalid) {
21534 FILE *fp = state->errout;
21535 fprintf(fp, "type: ");
21536 name_of(fp, ins->type);
21537 fprintf(fp, "\n");
21538 fprintf(fp, "invalid type: ");
21539 name_of(fp, invalid);
21540 fprintf(fp, "\n");
21541 internal_error(state, ins, "invalid ins type");
21543 } while(ins != first);
21546 static void verify_copy(struct compile_state *state)
21548 struct triple *first, *ins, *next;
21549 first = state->first;
21550 next = ins = first;
21551 do {
21552 ins = next;
21553 next = ins->next;
21554 if (ins->op != OP_COPY) {
21555 continue;
21557 if (!equiv_types(ins->type, RHS(ins, 0)->type)) {
21558 FILE *fp = state->errout;
21559 fprintf(fp, "src type: ");
21560 name_of(fp, RHS(ins, 0)->type);
21561 fprintf(fp, "\n");
21562 fprintf(fp, "dst type: ");
21563 name_of(fp, ins->type);
21564 fprintf(fp, "\n");
21565 internal_error(state, ins, "type mismatch in copy");
21567 } while(next != first);
21570 static void verify_consistency(struct compile_state *state)
21572 verify_unknown(state);
21573 verify_uses(state);
21574 verify_blocks_present(state);
21575 verify_blocks(state);
21576 verify_domination(state);
21577 verify_rhs(state);
21578 verify_piece(state);
21579 verify_ins_colors(state);
21580 verify_types(state);
21581 verify_copy(state);
21582 if (state->compiler->debug & DEBUG_VERIFICATION) {
21583 fprintf(state->dbgout, "consistency verified\n");
21586 #else
21587 static void verify_consistency(struct compile_state *state) {}
21588 #endif /* DEBUG_CONSISTENCY */
21590 static void optimize(struct compile_state *state)
21592 /* Join all of the functions into one giant function */
21593 join_functions(state);
21595 /* Dump what the instruction graph intially looks like */
21596 print_triples(state);
21598 /* Replace structures with simpler data types */
21599 decompose_compound_types(state);
21600 print_triples(state);
21602 verify_consistency(state);
21603 /* Analyze the intermediate code */
21604 state->bb.first = state->first;
21605 analyze_basic_blocks(state, &state->bb);
21607 /* Transform the code to ssa form. */
21609 * The transformation to ssa form puts a phi function
21610 * on each of edge of a dominance frontier where that
21611 * phi function might be needed. At -O2 if we don't
21612 * eleminate the excess phi functions we can get an
21613 * exponential code size growth. So I kill the extra
21614 * phi functions early and I kill them often.
21616 transform_to_ssa_form(state);
21617 verify_consistency(state);
21619 /* Remove dead code */
21620 eliminate_inefectual_code(state);
21621 verify_consistency(state);
21623 /* Do strength reduction and simple constant optimizations */
21624 simplify_all(state);
21625 verify_consistency(state);
21626 /* Propagate constants throughout the code */
21627 scc_transform(state);
21628 verify_consistency(state);
21629 #if DEBUG_ROMCC_WARNINGS
21630 #warning "WISHLIST implement single use constants (least possible register pressure)"
21631 #warning "WISHLIST implement induction variable elimination"
21632 #endif
21633 /* Select architecture instructions and an initial partial
21634 * coloring based on architecture constraints.
21636 transform_to_arch_instructions(state);
21637 verify_consistency(state);
21639 /* Remove dead code */
21640 eliminate_inefectual_code(state);
21641 verify_consistency(state);
21643 /* Color all of the variables to see if they will fit in registers */
21644 insert_copies_to_phi(state);
21645 verify_consistency(state);
21647 insert_mandatory_copies(state);
21648 verify_consistency(state);
21650 allocate_registers(state);
21651 verify_consistency(state);
21653 /* Remove the optimization information.
21654 * This is more to check for memory consistency than to free memory.
21656 free_basic_blocks(state, &state->bb);
21659 static void print_op_asm(struct compile_state *state,
21660 struct triple *ins, FILE *fp)
21662 struct asm_info *info;
21663 const char *ptr;
21664 unsigned lhs, rhs, i;
21665 info = ins->u.ainfo;
21666 lhs = ins->lhs;
21667 rhs = ins->rhs;
21668 /* Don't count the clobbers in lhs */
21669 for(i = 0; i < lhs; i++) {
21670 if (LHS(ins, i)->type == &void_type) {
21671 break;
21674 lhs = i;
21675 fprintf(fp, "#ASM\n");
21676 fputc('\t', fp);
21677 for(ptr = info->str; *ptr; ptr++) {
21678 char *next;
21679 unsigned long param;
21680 struct triple *piece;
21681 if (*ptr != '%') {
21682 fputc(*ptr, fp);
21683 continue;
21685 ptr++;
21686 if (*ptr == '%') {
21687 fputc('%', fp);
21688 continue;
21690 param = strtoul(ptr, &next, 10);
21691 if (ptr == next) {
21692 error(state, ins, "Invalid asm template");
21694 if (param >= (lhs + rhs)) {
21695 error(state, ins, "Invalid param %%%u in asm template",
21696 param);
21698 piece = (param < lhs)? LHS(ins, param) : RHS(ins, param - lhs);
21699 fprintf(fp, "%s",
21700 arch_reg_str(ID_REG(piece->id)));
21701 ptr = next -1;
21703 fprintf(fp, "\n#NOT ASM\n");
21707 /* Only use the low x86 byte registers. This allows me
21708 * allocate the entire register when a byte register is used.
21710 #define X86_4_8BIT_GPRS 1
21712 /* x86 featrues */
21713 #define X86_MMX_REGS (1<<0)
21714 #define X86_XMM_REGS (1<<1)
21715 #define X86_NOOP_COPY (1<<2)
21717 /* The x86 register classes */
21718 #define REGC_FLAGS 0
21719 #define REGC_GPR8 1
21720 #define REGC_GPR16 2
21721 #define REGC_GPR32 3
21722 #define REGC_DIVIDEND64 4
21723 #define REGC_DIVIDEND32 5
21724 #define REGC_MMX 6
21725 #define REGC_XMM 7
21726 #define REGC_GPR32_8 8
21727 #define REGC_GPR16_8 9
21728 #define REGC_GPR8_LO 10
21729 #define REGC_IMM32 11
21730 #define REGC_IMM16 12
21731 #define REGC_IMM8 13
21732 #define LAST_REGC REGC_IMM8
21733 #if LAST_REGC >= MAX_REGC
21734 #error "MAX_REGC is to low"
21735 #endif
21737 /* Register class masks */
21738 #define REGCM_FLAGS (1 << REGC_FLAGS)
21739 #define REGCM_GPR8 (1 << REGC_GPR8)
21740 #define REGCM_GPR16 (1 << REGC_GPR16)
21741 #define REGCM_GPR32 (1 << REGC_GPR32)
21742 #define REGCM_DIVIDEND64 (1 << REGC_DIVIDEND64)
21743 #define REGCM_DIVIDEND32 (1 << REGC_DIVIDEND32)
21744 #define REGCM_MMX (1 << REGC_MMX)
21745 #define REGCM_XMM (1 << REGC_XMM)
21746 #define REGCM_GPR32_8 (1 << REGC_GPR32_8)
21747 #define REGCM_GPR16_8 (1 << REGC_GPR16_8)
21748 #define REGCM_GPR8_LO (1 << REGC_GPR8_LO)
21749 #define REGCM_IMM32 (1 << REGC_IMM32)
21750 #define REGCM_IMM16 (1 << REGC_IMM16)
21751 #define REGCM_IMM8 (1 << REGC_IMM8)
21752 #define REGCM_ALL ((1 << (LAST_REGC + 1)) - 1)
21753 #define REGCM_IMMALL (REGCM_IMM32 | REGCM_IMM16 | REGCM_IMM8)
21755 /* The x86 registers */
21756 #define REG_EFLAGS 2
21757 #define REGC_FLAGS_FIRST REG_EFLAGS
21758 #define REGC_FLAGS_LAST REG_EFLAGS
21759 #define REG_AL 3
21760 #define REG_BL 4
21761 #define REG_CL 5
21762 #define REG_DL 6
21763 #define REG_AH 7
21764 #define REG_BH 8
21765 #define REG_CH 9
21766 #define REG_DH 10
21767 #define REGC_GPR8_LO_FIRST REG_AL
21768 #define REGC_GPR8_LO_LAST REG_DL
21769 #define REGC_GPR8_FIRST REG_AL
21770 #define REGC_GPR8_LAST REG_DH
21771 #define REG_AX 11
21772 #define REG_BX 12
21773 #define REG_CX 13
21774 #define REG_DX 14
21775 #define REG_SI 15
21776 #define REG_DI 16
21777 #define REG_BP 17
21778 #define REG_SP 18
21779 #define REGC_GPR16_FIRST REG_AX
21780 #define REGC_GPR16_LAST REG_SP
21781 #define REG_EAX 19
21782 #define REG_EBX 20
21783 #define REG_ECX 21
21784 #define REG_EDX 22
21785 #define REG_ESI 23
21786 #define REG_EDI 24
21787 #define REG_EBP 25
21788 #define REG_ESP 26
21789 #define REGC_GPR32_FIRST REG_EAX
21790 #define REGC_GPR32_LAST REG_ESP
21791 #define REG_EDXEAX 27
21792 #define REGC_DIVIDEND64_FIRST REG_EDXEAX
21793 #define REGC_DIVIDEND64_LAST REG_EDXEAX
21794 #define REG_DXAX 28
21795 #define REGC_DIVIDEND32_FIRST REG_DXAX
21796 #define REGC_DIVIDEND32_LAST REG_DXAX
21797 #define REG_MMX0 29
21798 #define REG_MMX1 30
21799 #define REG_MMX2 31
21800 #define REG_MMX3 32
21801 #define REG_MMX4 33
21802 #define REG_MMX5 34
21803 #define REG_MMX6 35
21804 #define REG_MMX7 36
21805 #define REGC_MMX_FIRST REG_MMX0
21806 #define REGC_MMX_LAST REG_MMX7
21807 #define REG_XMM0 37
21808 #define REG_XMM1 38
21809 #define REG_XMM2 39
21810 #define REG_XMM3 40
21811 #define REG_XMM4 41
21812 #define REG_XMM5 42
21813 #define REG_XMM6 43
21814 #define REG_XMM7 44
21815 #define REGC_XMM_FIRST REG_XMM0
21816 #define REGC_XMM_LAST REG_XMM7
21818 #if DEBUG_ROMCC_WARNINGS
21819 #warning "WISHLIST figure out how to use pinsrw and pextrw to better use extended regs"
21820 #endif
21822 #define LAST_REG REG_XMM7
21824 #define REGC_GPR32_8_FIRST REG_EAX
21825 #define REGC_GPR32_8_LAST REG_EDX
21826 #define REGC_GPR16_8_FIRST REG_AX
21827 #define REGC_GPR16_8_LAST REG_DX
21829 #define REGC_IMM8_FIRST -1
21830 #define REGC_IMM8_LAST -1
21831 #define REGC_IMM16_FIRST -2
21832 #define REGC_IMM16_LAST -1
21833 #define REGC_IMM32_FIRST -4
21834 #define REGC_IMM32_LAST -1
21836 #if LAST_REG >= MAX_REGISTERS
21837 #error "MAX_REGISTERS to low"
21838 #endif
21841 static unsigned regc_size[LAST_REGC +1] = {
21842 [REGC_FLAGS] = REGC_FLAGS_LAST - REGC_FLAGS_FIRST + 1,
21843 [REGC_GPR8] = REGC_GPR8_LAST - REGC_GPR8_FIRST + 1,
21844 [REGC_GPR16] = REGC_GPR16_LAST - REGC_GPR16_FIRST + 1,
21845 [REGC_GPR32] = REGC_GPR32_LAST - REGC_GPR32_FIRST + 1,
21846 [REGC_DIVIDEND64] = REGC_DIVIDEND64_LAST - REGC_DIVIDEND64_FIRST + 1,
21847 [REGC_DIVIDEND32] = REGC_DIVIDEND32_LAST - REGC_DIVIDEND32_FIRST + 1,
21848 [REGC_MMX] = REGC_MMX_LAST - REGC_MMX_FIRST + 1,
21849 [REGC_XMM] = REGC_XMM_LAST - REGC_XMM_FIRST + 1,
21850 [REGC_GPR32_8] = REGC_GPR32_8_LAST - REGC_GPR32_8_FIRST + 1,
21851 [REGC_GPR16_8] = REGC_GPR16_8_LAST - REGC_GPR16_8_FIRST + 1,
21852 [REGC_GPR8_LO] = REGC_GPR8_LO_LAST - REGC_GPR8_LO_FIRST + 1,
21853 [REGC_IMM32] = 0,
21854 [REGC_IMM16] = 0,
21855 [REGC_IMM8] = 0,
21858 static const struct {
21859 int first, last;
21860 } regcm_bound[LAST_REGC + 1] = {
21861 [REGC_FLAGS] = { REGC_FLAGS_FIRST, REGC_FLAGS_LAST },
21862 [REGC_GPR8] = { REGC_GPR8_FIRST, REGC_GPR8_LAST },
21863 [REGC_GPR16] = { REGC_GPR16_FIRST, REGC_GPR16_LAST },
21864 [REGC_GPR32] = { REGC_GPR32_FIRST, REGC_GPR32_LAST },
21865 [REGC_DIVIDEND64] = { REGC_DIVIDEND64_FIRST, REGC_DIVIDEND64_LAST },
21866 [REGC_DIVIDEND32] = { REGC_DIVIDEND32_FIRST, REGC_DIVIDEND32_LAST },
21867 [REGC_MMX] = { REGC_MMX_FIRST, REGC_MMX_LAST },
21868 [REGC_XMM] = { REGC_XMM_FIRST, REGC_XMM_LAST },
21869 [REGC_GPR32_8] = { REGC_GPR32_8_FIRST, REGC_GPR32_8_LAST },
21870 [REGC_GPR16_8] = { REGC_GPR16_8_FIRST, REGC_GPR16_8_LAST },
21871 [REGC_GPR8_LO] = { REGC_GPR8_LO_FIRST, REGC_GPR8_LO_LAST },
21872 [REGC_IMM32] = { REGC_IMM32_FIRST, REGC_IMM32_LAST },
21873 [REGC_IMM16] = { REGC_IMM16_FIRST, REGC_IMM16_LAST },
21874 [REGC_IMM8] = { REGC_IMM8_FIRST, REGC_IMM8_LAST },
21877 #if ARCH_INPUT_REGS != 4
21878 #error ARCH_INPUT_REGS size mismatch
21879 #endif
21880 static const struct reg_info arch_input_regs[ARCH_INPUT_REGS] = {
21881 { .reg = REG_EAX, .regcm = REGCM_GPR32 },
21882 { .reg = REG_EBX, .regcm = REGCM_GPR32 },
21883 { .reg = REG_ECX, .regcm = REGCM_GPR32 },
21884 { .reg = REG_EDX, .regcm = REGCM_GPR32 },
21887 #if ARCH_OUTPUT_REGS != 4
21888 #error ARCH_INPUT_REGS size mismatch
21889 #endif
21890 static const struct reg_info arch_output_regs[ARCH_OUTPUT_REGS] = {
21891 { .reg = REG_EAX, .regcm = REGCM_GPR32 },
21892 { .reg = REG_EBX, .regcm = REGCM_GPR32 },
21893 { .reg = REG_ECX, .regcm = REGCM_GPR32 },
21894 { .reg = REG_EDX, .regcm = REGCM_GPR32 },
21897 static void init_arch_state(struct arch_state *arch)
21899 memset(arch, 0, sizeof(*arch));
21900 arch->features = 0;
21903 static const struct compiler_flag arch_flags[] = {
21904 { "mmx", X86_MMX_REGS },
21905 { "sse", X86_XMM_REGS },
21906 { "noop-copy", X86_NOOP_COPY },
21907 { 0, 0 },
21909 static const struct compiler_flag arch_cpus[] = {
21910 { "i386", 0 },
21911 { "p2", X86_MMX_REGS },
21912 { "p3", X86_MMX_REGS | X86_XMM_REGS },
21913 { "p4", X86_MMX_REGS | X86_XMM_REGS },
21914 { "k7", X86_MMX_REGS },
21915 { "k8", X86_MMX_REGS | X86_XMM_REGS },
21916 { "c3", X86_MMX_REGS },
21917 { "c3-2", X86_MMX_REGS | X86_XMM_REGS }, /* Nehemiah */
21918 { 0, 0 }
21920 static int arch_encode_flag(struct arch_state *arch, const char *flag)
21922 int result;
21923 int act;
21925 act = 1;
21926 if (strncmp(flag, "no-", 3) == 0) {
21927 flag += 3;
21928 act = 0;
21930 if (act && strncmp(flag, "cpu=", 4) == 0) {
21931 flag += 4;
21932 result = set_flag(arch_cpus, &arch->features, 1, flag);
21934 else {
21935 result = set_flag(arch_flags, &arch->features, act, flag);
21937 return result;
21940 static void arch_usage(FILE *fp)
21942 flag_usage(fp, arch_flags, "-m", "-mno-");
21943 flag_usage(fp, arch_cpus, "-mcpu=", 0);
21946 static unsigned arch_regc_size(struct compile_state *state, int class)
21948 if ((class < 0) || (class > LAST_REGC)) {
21949 return 0;
21951 return regc_size[class];
21954 static int arch_regcm_intersect(unsigned regcm1, unsigned regcm2)
21956 /* See if two register classes may have overlapping registers */
21957 unsigned gpr_mask = REGCM_GPR8 | REGCM_GPR8_LO | REGCM_GPR16_8 | REGCM_GPR16 |
21958 REGCM_GPR32_8 | REGCM_GPR32 |
21959 REGCM_DIVIDEND32 | REGCM_DIVIDEND64;
21961 /* Special case for the immediates */
21962 if ((regcm1 & (REGCM_IMM32 | REGCM_IMM16 | REGCM_IMM8)) &&
21963 ((regcm1 & ~(REGCM_IMM32 | REGCM_IMM16 | REGCM_IMM8)) == 0) &&
21964 (regcm2 & (REGCM_IMM32 | REGCM_IMM16 | REGCM_IMM8)) &&
21965 ((regcm2 & ~(REGCM_IMM32 | REGCM_IMM16 | REGCM_IMM8)) == 0)) {
21966 return 0;
21968 return (regcm1 & regcm2) ||
21969 ((regcm1 & gpr_mask) && (regcm2 & gpr_mask));
21972 static void arch_reg_equivs(
21973 struct compile_state *state, unsigned *equiv, int reg)
21975 if ((reg < 0) || (reg > LAST_REG)) {
21976 internal_error(state, 0, "invalid register");
21978 *equiv++ = reg;
21979 switch(reg) {
21980 case REG_AL:
21981 #if X86_4_8BIT_GPRS
21982 *equiv++ = REG_AH;
21983 #endif
21984 *equiv++ = REG_AX;
21985 *equiv++ = REG_EAX;
21986 *equiv++ = REG_DXAX;
21987 *equiv++ = REG_EDXEAX;
21988 break;
21989 case REG_AH:
21990 #if X86_4_8BIT_GPRS
21991 *equiv++ = REG_AL;
21992 #endif
21993 *equiv++ = REG_AX;
21994 *equiv++ = REG_EAX;
21995 *equiv++ = REG_DXAX;
21996 *equiv++ = REG_EDXEAX;
21997 break;
21998 case REG_BL:
21999 #if X86_4_8BIT_GPRS
22000 *equiv++ = REG_BH;
22001 #endif
22002 *equiv++ = REG_BX;
22003 *equiv++ = REG_EBX;
22004 break;
22006 case REG_BH:
22007 #if X86_4_8BIT_GPRS
22008 *equiv++ = REG_BL;
22009 #endif
22010 *equiv++ = REG_BX;
22011 *equiv++ = REG_EBX;
22012 break;
22013 case REG_CL:
22014 #if X86_4_8BIT_GPRS
22015 *equiv++ = REG_CH;
22016 #endif
22017 *equiv++ = REG_CX;
22018 *equiv++ = REG_ECX;
22019 break;
22021 case REG_CH:
22022 #if X86_4_8BIT_GPRS
22023 *equiv++ = REG_CL;
22024 #endif
22025 *equiv++ = REG_CX;
22026 *equiv++ = REG_ECX;
22027 break;
22028 case REG_DL:
22029 #if X86_4_8BIT_GPRS
22030 *equiv++ = REG_DH;
22031 #endif
22032 *equiv++ = REG_DX;
22033 *equiv++ = REG_EDX;
22034 *equiv++ = REG_DXAX;
22035 *equiv++ = REG_EDXEAX;
22036 break;
22037 case REG_DH:
22038 #if X86_4_8BIT_GPRS
22039 *equiv++ = REG_DL;
22040 #endif
22041 *equiv++ = REG_DX;
22042 *equiv++ = REG_EDX;
22043 *equiv++ = REG_DXAX;
22044 *equiv++ = REG_EDXEAX;
22045 break;
22046 case REG_AX:
22047 *equiv++ = REG_AL;
22048 *equiv++ = REG_AH;
22049 *equiv++ = REG_EAX;
22050 *equiv++ = REG_DXAX;
22051 *equiv++ = REG_EDXEAX;
22052 break;
22053 case REG_BX:
22054 *equiv++ = REG_BL;
22055 *equiv++ = REG_BH;
22056 *equiv++ = REG_EBX;
22057 break;
22058 case REG_CX:
22059 *equiv++ = REG_CL;
22060 *equiv++ = REG_CH;
22061 *equiv++ = REG_ECX;
22062 break;
22063 case REG_DX:
22064 *equiv++ = REG_DL;
22065 *equiv++ = REG_DH;
22066 *equiv++ = REG_EDX;
22067 *equiv++ = REG_DXAX;
22068 *equiv++ = REG_EDXEAX;
22069 break;
22070 case REG_SI:
22071 *equiv++ = REG_ESI;
22072 break;
22073 case REG_DI:
22074 *equiv++ = REG_EDI;
22075 break;
22076 case REG_BP:
22077 *equiv++ = REG_EBP;
22078 break;
22079 case REG_SP:
22080 *equiv++ = REG_ESP;
22081 break;
22082 case REG_EAX:
22083 *equiv++ = REG_AL;
22084 *equiv++ = REG_AH;
22085 *equiv++ = REG_AX;
22086 *equiv++ = REG_DXAX;
22087 *equiv++ = REG_EDXEAX;
22088 break;
22089 case REG_EBX:
22090 *equiv++ = REG_BL;
22091 *equiv++ = REG_BH;
22092 *equiv++ = REG_BX;
22093 break;
22094 case REG_ECX:
22095 *equiv++ = REG_CL;
22096 *equiv++ = REG_CH;
22097 *equiv++ = REG_CX;
22098 break;
22099 case REG_EDX:
22100 *equiv++ = REG_DL;
22101 *equiv++ = REG_DH;
22102 *equiv++ = REG_DX;
22103 *equiv++ = REG_DXAX;
22104 *equiv++ = REG_EDXEAX;
22105 break;
22106 case REG_ESI:
22107 *equiv++ = REG_SI;
22108 break;
22109 case REG_EDI:
22110 *equiv++ = REG_DI;
22111 break;
22112 case REG_EBP:
22113 *equiv++ = REG_BP;
22114 break;
22115 case REG_ESP:
22116 *equiv++ = REG_SP;
22117 break;
22118 case REG_DXAX:
22119 *equiv++ = REG_AL;
22120 *equiv++ = REG_AH;
22121 *equiv++ = REG_DL;
22122 *equiv++ = REG_DH;
22123 *equiv++ = REG_AX;
22124 *equiv++ = REG_DX;
22125 *equiv++ = REG_EAX;
22126 *equiv++ = REG_EDX;
22127 *equiv++ = REG_EDXEAX;
22128 break;
22129 case REG_EDXEAX:
22130 *equiv++ = REG_AL;
22131 *equiv++ = REG_AH;
22132 *equiv++ = REG_DL;
22133 *equiv++ = REG_DH;
22134 *equiv++ = REG_AX;
22135 *equiv++ = REG_DX;
22136 *equiv++ = REG_EAX;
22137 *equiv++ = REG_EDX;
22138 *equiv++ = REG_DXAX;
22139 break;
22141 *equiv++ = REG_UNSET;
22144 static unsigned arch_avail_mask(struct compile_state *state)
22146 unsigned avail_mask;
22147 /* REGCM_GPR8 is not available */
22148 avail_mask = REGCM_GPR8_LO | REGCM_GPR16_8 | REGCM_GPR16 |
22149 REGCM_GPR32 | REGCM_GPR32_8 |
22150 REGCM_DIVIDEND32 | REGCM_DIVIDEND64 |
22151 REGCM_IMM32 | REGCM_IMM16 | REGCM_IMM8 | REGCM_FLAGS;
22152 if (state->arch->features & X86_MMX_REGS) {
22153 avail_mask |= REGCM_MMX;
22155 if (state->arch->features & X86_XMM_REGS) {
22156 avail_mask |= REGCM_XMM;
22158 return avail_mask;
22161 static unsigned arch_regcm_normalize(struct compile_state *state, unsigned regcm)
22163 unsigned mask, result;
22164 int class, class2;
22165 result = regcm;
22167 for(class = 0, mask = 1; mask; mask <<= 1, class++) {
22168 if ((result & mask) == 0) {
22169 continue;
22171 if (class > LAST_REGC) {
22172 result &= ~mask;
22173 continue;
22175 for(class2 = 0; class2 <= LAST_REGC; class2++) {
22176 if ((regcm_bound[class2].first >= regcm_bound[class].first) &&
22177 (regcm_bound[class2].last <= regcm_bound[class].last)) {
22178 result |= (1 << class2);
22182 result &= arch_avail_mask(state);
22183 return result;
22186 static unsigned arch_regcm_reg_normalize(struct compile_state *state, unsigned regcm)
22188 /* Like arch_regcm_normalize except immediate register classes are excluded */
22189 regcm = arch_regcm_normalize(state, regcm);
22190 /* Remove the immediate register classes */
22191 regcm &= ~(REGCM_IMM32 | REGCM_IMM16 | REGCM_IMM8);
22192 return regcm;
22196 static unsigned arch_reg_regcm(struct compile_state *state, int reg)
22198 unsigned mask;
22199 int class;
22200 mask = 0;
22201 for(class = 0; class <= LAST_REGC; class++) {
22202 if ((reg >= regcm_bound[class].first) &&
22203 (reg <= regcm_bound[class].last)) {
22204 mask |= (1 << class);
22207 if (!mask) {
22208 internal_error(state, 0, "reg %d not in any class", reg);
22210 return mask;
22213 static struct reg_info arch_reg_constraint(
22214 struct compile_state *state, struct type *type, const char *constraint)
22216 static const struct {
22217 char class;
22218 unsigned int mask;
22219 unsigned int reg;
22220 } constraints[] = {
22221 { 'r', REGCM_GPR32, REG_UNSET },
22222 { 'g', REGCM_GPR32, REG_UNSET },
22223 { 'p', REGCM_GPR32, REG_UNSET },
22224 { 'q', REGCM_GPR8_LO, REG_UNSET },
22225 { 'Q', REGCM_GPR32_8, REG_UNSET },
22226 { 'x', REGCM_XMM, REG_UNSET },
22227 { 'y', REGCM_MMX, REG_UNSET },
22228 { 'a', REGCM_GPR32, REG_EAX },
22229 { 'b', REGCM_GPR32, REG_EBX },
22230 { 'c', REGCM_GPR32, REG_ECX },
22231 { 'd', REGCM_GPR32, REG_EDX },
22232 { 'D', REGCM_GPR32, REG_EDI },
22233 { 'S', REGCM_GPR32, REG_ESI },
22234 { '\0', 0, REG_UNSET },
22236 unsigned int regcm;
22237 unsigned int mask, reg;
22238 struct reg_info result;
22239 const char *ptr;
22240 regcm = arch_type_to_regcm(state, type);
22241 reg = REG_UNSET;
22242 mask = 0;
22243 for(ptr = constraint; *ptr; ptr++) {
22244 int i;
22245 if (*ptr == ' ') {
22246 continue;
22248 for(i = 0; constraints[i].class != '\0'; i++) {
22249 if (constraints[i].class == *ptr) {
22250 break;
22253 if (constraints[i].class == '\0') {
22254 error(state, 0, "invalid register constraint ``%c''", *ptr);
22255 break;
22257 if ((constraints[i].mask & regcm) == 0) {
22258 error(state, 0, "invalid register class %c specified",
22259 *ptr);
22261 mask |= constraints[i].mask;
22262 if (constraints[i].reg != REG_UNSET) {
22263 if ((reg != REG_UNSET) && (reg != constraints[i].reg)) {
22264 error(state, 0, "Only one register may be specified");
22266 reg = constraints[i].reg;
22269 result.reg = reg;
22270 result.regcm = mask;
22271 return result;
22274 static struct reg_info arch_reg_clobber(
22275 struct compile_state *state, const char *clobber)
22277 struct reg_info result;
22278 if (strcmp(clobber, "memory") == 0) {
22279 result.reg = REG_UNSET;
22280 result.regcm = 0;
22282 else if (strcmp(clobber, "eax") == 0) {
22283 result.reg = REG_EAX;
22284 result.regcm = REGCM_GPR32;
22286 else if (strcmp(clobber, "ebx") == 0) {
22287 result.reg = REG_EBX;
22288 result.regcm = REGCM_GPR32;
22290 else if (strcmp(clobber, "ecx") == 0) {
22291 result.reg = REG_ECX;
22292 result.regcm = REGCM_GPR32;
22294 else if (strcmp(clobber, "edx") == 0) {
22295 result.reg = REG_EDX;
22296 result.regcm = REGCM_GPR32;
22298 else if (strcmp(clobber, "esi") == 0) {
22299 result.reg = REG_ESI;
22300 result.regcm = REGCM_GPR32;
22302 else if (strcmp(clobber, "edi") == 0) {
22303 result.reg = REG_EDI;
22304 result.regcm = REGCM_GPR32;
22306 else if (strcmp(clobber, "ebp") == 0) {
22307 result.reg = REG_EBP;
22308 result.regcm = REGCM_GPR32;
22310 else if (strcmp(clobber, "esp") == 0) {
22311 result.reg = REG_ESP;
22312 result.regcm = REGCM_GPR32;
22314 else if (strcmp(clobber, "cc") == 0) {
22315 result.reg = REG_EFLAGS;
22316 result.regcm = REGCM_FLAGS;
22318 else if ((strncmp(clobber, "xmm", 3) == 0) &&
22319 octdigitp(clobber[3]) && (clobber[4] == '\0')) {
22320 result.reg = REG_XMM0 + octdigval(clobber[3]);
22321 result.regcm = REGCM_XMM;
22323 else if ((strncmp(clobber, "mm", 2) == 0) &&
22324 octdigitp(clobber[3]) && (clobber[4] == '\0')) {
22325 result.reg = REG_MMX0 + octdigval(clobber[3]);
22326 result.regcm = REGCM_MMX;
22328 else {
22329 error(state, 0, "unknown register name `%s' in asm",
22330 clobber);
22331 result.reg = REG_UNSET;
22332 result.regcm = 0;
22334 return result;
22337 static int do_select_reg(struct compile_state *state,
22338 char *used, int reg, unsigned classes)
22340 unsigned mask;
22341 if (used[reg]) {
22342 return REG_UNSET;
22344 mask = arch_reg_regcm(state, reg);
22345 return (classes & mask) ? reg : REG_UNSET;
22348 static int arch_select_free_register(
22349 struct compile_state *state, char *used, int classes)
22351 /* Live ranges with the most neighbors are colored first.
22353 * Generally it does not matter which colors are given
22354 * as the register allocator attempts to color live ranges
22355 * in an order where you are guaranteed not to run out of colors.
22357 * Occasionally the register allocator cannot find an order
22358 * of register selection that will find a free color. To
22359 * increase the odds the register allocator will work when
22360 * it guesses first give out registers from register classes
22361 * least likely to run out of registers.
22364 int i, reg;
22365 reg = REG_UNSET;
22366 for(i = REGC_XMM_FIRST; (reg == REG_UNSET) && (i <= REGC_XMM_LAST); i++) {
22367 reg = do_select_reg(state, used, i, classes);
22369 for(i = REGC_MMX_FIRST; (reg == REG_UNSET) && (i <= REGC_MMX_LAST); i++) {
22370 reg = do_select_reg(state, used, i, classes);
22372 for(i = REGC_GPR32_LAST; (reg == REG_UNSET) && (i >= REGC_GPR32_FIRST); i--) {
22373 reg = do_select_reg(state, used, i, classes);
22375 for(i = REGC_GPR16_FIRST; (reg == REG_UNSET) && (i <= REGC_GPR16_LAST); i++) {
22376 reg = do_select_reg(state, used, i, classes);
22378 for(i = REGC_GPR8_FIRST; (reg == REG_UNSET) && (i <= REGC_GPR8_LAST); i++) {
22379 reg = do_select_reg(state, used, i, classes);
22381 for(i = REGC_GPR8_LO_FIRST; (reg == REG_UNSET) && (i <= REGC_GPR8_LO_LAST); i++) {
22382 reg = do_select_reg(state, used, i, classes);
22384 for(i = REGC_DIVIDEND32_FIRST; (reg == REG_UNSET) && (i <= REGC_DIVIDEND32_LAST); i++) {
22385 reg = do_select_reg(state, used, i, classes);
22387 for(i = REGC_DIVIDEND64_FIRST; (reg == REG_UNSET) && (i <= REGC_DIVIDEND64_LAST); i++) {
22388 reg = do_select_reg(state, used, i, classes);
22390 for(i = REGC_FLAGS_FIRST; (reg == REG_UNSET) && (i <= REGC_FLAGS_LAST); i++) {
22391 reg = do_select_reg(state, used, i, classes);
22393 return reg;
22397 static unsigned arch_type_to_regcm(struct compile_state *state, struct type *type)
22400 #if DEBUG_ROMCC_WARNINGS
22401 #warning "FIXME force types smaller (if legal) before I get here"
22402 #endif
22403 unsigned mask;
22404 switch(type->type & TYPE_MASK) {
22405 case TYPE_ARRAY:
22406 case TYPE_VOID:
22407 mask = 0;
22408 break;
22409 case TYPE_CHAR:
22410 case TYPE_UCHAR:
22411 mask = REGCM_GPR8 | REGCM_GPR8_LO |
22412 REGCM_GPR16 | REGCM_GPR16_8 |
22413 REGCM_GPR32 | REGCM_GPR32_8 |
22414 REGCM_DIVIDEND32 | REGCM_DIVIDEND64 |
22415 REGCM_MMX | REGCM_XMM |
22416 REGCM_IMM32 | REGCM_IMM16 | REGCM_IMM8;
22417 break;
22418 case TYPE_SHORT:
22419 case TYPE_USHORT:
22420 mask = REGCM_GPR16 | REGCM_GPR16_8 |
22421 REGCM_GPR32 | REGCM_GPR32_8 |
22422 REGCM_DIVIDEND32 | REGCM_DIVIDEND64 |
22423 REGCM_MMX | REGCM_XMM |
22424 REGCM_IMM32 | REGCM_IMM16;
22425 break;
22426 case TYPE_ENUM:
22427 case TYPE_INT:
22428 case TYPE_UINT:
22429 case TYPE_LONG:
22430 case TYPE_ULONG:
22431 case TYPE_POINTER:
22432 mask = REGCM_GPR32 | REGCM_GPR32_8 |
22433 REGCM_DIVIDEND32 | REGCM_DIVIDEND64 |
22434 REGCM_MMX | REGCM_XMM |
22435 REGCM_IMM32;
22436 break;
22437 case TYPE_JOIN:
22438 case TYPE_UNION:
22439 mask = arch_type_to_regcm(state, type->left);
22440 break;
22441 case TYPE_OVERLAP:
22442 mask = arch_type_to_regcm(state, type->left) &
22443 arch_type_to_regcm(state, type->right);
22444 break;
22445 case TYPE_BITFIELD:
22446 mask = arch_type_to_regcm(state, type->left);
22447 break;
22448 default:
22449 fprintf(state->errout, "type: ");
22450 name_of(state->errout, type);
22451 fprintf(state->errout, "\n");
22452 internal_error(state, 0, "no register class for type");
22453 break;
22455 mask = arch_regcm_normalize(state, mask);
22456 return mask;
22459 static int is_imm32(struct triple *imm)
22461 // second condition commented out to prevent compiler warning:
22462 // imm->u.cval is always 32bit unsigned, so the comparison is
22463 // always true.
22464 return ((imm->op == OP_INTCONST) /* && (imm->u.cval <= 0xffffffffUL) */ ) ||
22465 (imm->op == OP_ADDRCONST);
22468 static int is_imm16(struct triple *imm)
22470 return ((imm->op == OP_INTCONST) && (imm->u.cval <= 0xffff));
22472 static int is_imm8(struct triple *imm)
22474 return ((imm->op == OP_INTCONST) && (imm->u.cval <= 0xff));
22477 static int get_imm32(struct triple *ins, struct triple **expr)
22479 struct triple *imm;
22480 imm = *expr;
22481 while(imm->op == OP_COPY) {
22482 imm = RHS(imm, 0);
22484 if (!is_imm32(imm)) {
22485 return 0;
22487 unuse_triple(*expr, ins);
22488 use_triple(imm, ins);
22489 *expr = imm;
22490 return 1;
22493 static int get_imm8(struct triple *ins, struct triple **expr)
22495 struct triple *imm;
22496 imm = *expr;
22497 while(imm->op == OP_COPY) {
22498 imm = RHS(imm, 0);
22500 if (!is_imm8(imm)) {
22501 return 0;
22503 unuse_triple(*expr, ins);
22504 use_triple(imm, ins);
22505 *expr = imm;
22506 return 1;
22509 #define TEMPLATE_NOP 0
22510 #define TEMPLATE_INTCONST8 1
22511 #define TEMPLATE_INTCONST32 2
22512 #define TEMPLATE_UNKNOWNVAL 3
22513 #define TEMPLATE_COPY8_REG 5
22514 #define TEMPLATE_COPY16_REG 6
22515 #define TEMPLATE_COPY32_REG 7
22516 #define TEMPLATE_COPY_IMM8 8
22517 #define TEMPLATE_COPY_IMM16 9
22518 #define TEMPLATE_COPY_IMM32 10
22519 #define TEMPLATE_PHI8 11
22520 #define TEMPLATE_PHI16 12
22521 #define TEMPLATE_PHI32 13
22522 #define TEMPLATE_STORE8 14
22523 #define TEMPLATE_STORE16 15
22524 #define TEMPLATE_STORE32 16
22525 #define TEMPLATE_LOAD8 17
22526 #define TEMPLATE_LOAD16 18
22527 #define TEMPLATE_LOAD32 19
22528 #define TEMPLATE_BINARY8_REG 20
22529 #define TEMPLATE_BINARY16_REG 21
22530 #define TEMPLATE_BINARY32_REG 22
22531 #define TEMPLATE_BINARY8_IMM 23
22532 #define TEMPLATE_BINARY16_IMM 24
22533 #define TEMPLATE_BINARY32_IMM 25
22534 #define TEMPLATE_SL8_CL 26
22535 #define TEMPLATE_SL16_CL 27
22536 #define TEMPLATE_SL32_CL 28
22537 #define TEMPLATE_SL8_IMM 29
22538 #define TEMPLATE_SL16_IMM 30
22539 #define TEMPLATE_SL32_IMM 31
22540 #define TEMPLATE_UNARY8 32
22541 #define TEMPLATE_UNARY16 33
22542 #define TEMPLATE_UNARY32 34
22543 #define TEMPLATE_CMP8_REG 35
22544 #define TEMPLATE_CMP16_REG 36
22545 #define TEMPLATE_CMP32_REG 37
22546 #define TEMPLATE_CMP8_IMM 38
22547 #define TEMPLATE_CMP16_IMM 39
22548 #define TEMPLATE_CMP32_IMM 40
22549 #define TEMPLATE_TEST8 41
22550 #define TEMPLATE_TEST16 42
22551 #define TEMPLATE_TEST32 43
22552 #define TEMPLATE_SET 44
22553 #define TEMPLATE_JMP 45
22554 #define TEMPLATE_RET 46
22555 #define TEMPLATE_INB_DX 47
22556 #define TEMPLATE_INB_IMM 48
22557 #define TEMPLATE_INW_DX 49
22558 #define TEMPLATE_INW_IMM 50
22559 #define TEMPLATE_INL_DX 51
22560 #define TEMPLATE_INL_IMM 52
22561 #define TEMPLATE_OUTB_DX 53
22562 #define TEMPLATE_OUTB_IMM 54
22563 #define TEMPLATE_OUTW_DX 55
22564 #define TEMPLATE_OUTW_IMM 56
22565 #define TEMPLATE_OUTL_DX 57
22566 #define TEMPLATE_OUTL_IMM 58
22567 #define TEMPLATE_BSF 59
22568 #define TEMPLATE_RDMSR 60
22569 #define TEMPLATE_WRMSR 61
22570 #define TEMPLATE_UMUL8 62
22571 #define TEMPLATE_UMUL16 63
22572 #define TEMPLATE_UMUL32 64
22573 #define TEMPLATE_DIV8 65
22574 #define TEMPLATE_DIV16 66
22575 #define TEMPLATE_DIV32 67
22576 #define LAST_TEMPLATE TEMPLATE_DIV32
22577 #if LAST_TEMPLATE >= MAX_TEMPLATES
22578 #error "MAX_TEMPLATES to low"
22579 #endif
22581 #define COPY8_REGCM (REGCM_DIVIDEND64 | REGCM_DIVIDEND32 | REGCM_GPR32 | REGCM_GPR16 | REGCM_GPR8_LO | REGCM_MMX | REGCM_XMM)
22582 #define COPY16_REGCM (REGCM_DIVIDEND64 | REGCM_DIVIDEND32 | REGCM_GPR32 | REGCM_GPR16 | REGCM_MMX | REGCM_XMM)
22583 #define COPY32_REGCM (REGCM_DIVIDEND64 | REGCM_DIVIDEND32 | REGCM_GPR32 | REGCM_MMX | REGCM_XMM)
22586 static struct ins_template templates[] = {
22587 [TEMPLATE_NOP] = {
22588 .lhs = {
22589 [ 0] = { REG_UNNEEDED, REGCM_IMMALL },
22590 [ 1] = { REG_UNNEEDED, REGCM_IMMALL },
22591 [ 2] = { REG_UNNEEDED, REGCM_IMMALL },
22592 [ 3] = { REG_UNNEEDED, REGCM_IMMALL },
22593 [ 4] = { REG_UNNEEDED, REGCM_IMMALL },
22594 [ 5] = { REG_UNNEEDED, REGCM_IMMALL },
22595 [ 6] = { REG_UNNEEDED, REGCM_IMMALL },
22596 [ 7] = { REG_UNNEEDED, REGCM_IMMALL },
22597 [ 8] = { REG_UNNEEDED, REGCM_IMMALL },
22598 [ 9] = { REG_UNNEEDED, REGCM_IMMALL },
22599 [10] = { REG_UNNEEDED, REGCM_IMMALL },
22600 [11] = { REG_UNNEEDED, REGCM_IMMALL },
22601 [12] = { REG_UNNEEDED, REGCM_IMMALL },
22602 [13] = { REG_UNNEEDED, REGCM_IMMALL },
22603 [14] = { REG_UNNEEDED, REGCM_IMMALL },
22604 [15] = { REG_UNNEEDED, REGCM_IMMALL },
22605 [16] = { REG_UNNEEDED, REGCM_IMMALL },
22606 [17] = { REG_UNNEEDED, REGCM_IMMALL },
22607 [18] = { REG_UNNEEDED, REGCM_IMMALL },
22608 [19] = { REG_UNNEEDED, REGCM_IMMALL },
22609 [20] = { REG_UNNEEDED, REGCM_IMMALL },
22610 [21] = { REG_UNNEEDED, REGCM_IMMALL },
22611 [22] = { REG_UNNEEDED, REGCM_IMMALL },
22612 [23] = { REG_UNNEEDED, REGCM_IMMALL },
22613 [24] = { REG_UNNEEDED, REGCM_IMMALL },
22614 [25] = { REG_UNNEEDED, REGCM_IMMALL },
22615 [26] = { REG_UNNEEDED, REGCM_IMMALL },
22616 [27] = { REG_UNNEEDED, REGCM_IMMALL },
22617 [28] = { REG_UNNEEDED, REGCM_IMMALL },
22618 [29] = { REG_UNNEEDED, REGCM_IMMALL },
22619 [30] = { REG_UNNEEDED, REGCM_IMMALL },
22620 [31] = { REG_UNNEEDED, REGCM_IMMALL },
22621 [32] = { REG_UNNEEDED, REGCM_IMMALL },
22622 [33] = { REG_UNNEEDED, REGCM_IMMALL },
22623 [34] = { REG_UNNEEDED, REGCM_IMMALL },
22624 [35] = { REG_UNNEEDED, REGCM_IMMALL },
22625 [36] = { REG_UNNEEDED, REGCM_IMMALL },
22626 [37] = { REG_UNNEEDED, REGCM_IMMALL },
22627 [38] = { REG_UNNEEDED, REGCM_IMMALL },
22628 [39] = { REG_UNNEEDED, REGCM_IMMALL },
22629 [40] = { REG_UNNEEDED, REGCM_IMMALL },
22630 [41] = { REG_UNNEEDED, REGCM_IMMALL },
22631 [42] = { REG_UNNEEDED, REGCM_IMMALL },
22632 [43] = { REG_UNNEEDED, REGCM_IMMALL },
22633 [44] = { REG_UNNEEDED, REGCM_IMMALL },
22634 [45] = { REG_UNNEEDED, REGCM_IMMALL },
22635 [46] = { REG_UNNEEDED, REGCM_IMMALL },
22636 [47] = { REG_UNNEEDED, REGCM_IMMALL },
22637 [48] = { REG_UNNEEDED, REGCM_IMMALL },
22638 [49] = { REG_UNNEEDED, REGCM_IMMALL },
22639 [50] = { REG_UNNEEDED, REGCM_IMMALL },
22640 [51] = { REG_UNNEEDED, REGCM_IMMALL },
22641 [52] = { REG_UNNEEDED, REGCM_IMMALL },
22642 [53] = { REG_UNNEEDED, REGCM_IMMALL },
22643 [54] = { REG_UNNEEDED, REGCM_IMMALL },
22644 [55] = { REG_UNNEEDED, REGCM_IMMALL },
22645 [56] = { REG_UNNEEDED, REGCM_IMMALL },
22646 [57] = { REG_UNNEEDED, REGCM_IMMALL },
22647 [58] = { REG_UNNEEDED, REGCM_IMMALL },
22648 [59] = { REG_UNNEEDED, REGCM_IMMALL },
22649 [60] = { REG_UNNEEDED, REGCM_IMMALL },
22650 [61] = { REG_UNNEEDED, REGCM_IMMALL },
22651 [62] = { REG_UNNEEDED, REGCM_IMMALL },
22652 [63] = { REG_UNNEEDED, REGCM_IMMALL },
22655 [TEMPLATE_INTCONST8] = {
22656 .lhs = { [0] = { REG_UNNEEDED, REGCM_IMM8 } },
22658 [TEMPLATE_INTCONST32] = {
22659 .lhs = { [0] = { REG_UNNEEDED, REGCM_IMM32 } },
22661 [TEMPLATE_UNKNOWNVAL] = {
22662 .lhs = { [0] = { REG_UNSET, COPY32_REGCM } },
22664 [TEMPLATE_COPY8_REG] = {
22665 .lhs = { [0] = { REG_UNSET, COPY8_REGCM } },
22666 .rhs = { [0] = { REG_UNSET, COPY8_REGCM } },
22668 [TEMPLATE_COPY16_REG] = {
22669 .lhs = { [0] = { REG_UNSET, COPY16_REGCM } },
22670 .rhs = { [0] = { REG_UNSET, COPY16_REGCM } },
22672 [TEMPLATE_COPY32_REG] = {
22673 .lhs = { [0] = { REG_UNSET, COPY32_REGCM } },
22674 .rhs = { [0] = { REG_UNSET, COPY32_REGCM } },
22676 [TEMPLATE_COPY_IMM8] = {
22677 .lhs = { [0] = { REG_UNSET, COPY8_REGCM } },
22678 .rhs = { [0] = { REG_UNNEEDED, REGCM_IMM8 } },
22680 [TEMPLATE_COPY_IMM16] = {
22681 .lhs = { [0] = { REG_UNSET, COPY16_REGCM } },
22682 .rhs = { [0] = { REG_UNNEEDED, REGCM_IMM16 | REGCM_IMM8 } },
22684 [TEMPLATE_COPY_IMM32] = {
22685 .lhs = { [0] = { REG_UNSET, COPY32_REGCM } },
22686 .rhs = { [0] = { REG_UNNEEDED, REGCM_IMM32 | REGCM_IMM16 | REGCM_IMM8 } },
22688 [TEMPLATE_PHI8] = {
22689 .lhs = { [0] = { REG_VIRT0, COPY8_REGCM } },
22690 .rhs = { [0] = { REG_VIRT0, COPY8_REGCM } },
22692 [TEMPLATE_PHI16] = {
22693 .lhs = { [0] = { REG_VIRT0, COPY16_REGCM } },
22694 .rhs = { [0] = { REG_VIRT0, COPY16_REGCM } },
22696 [TEMPLATE_PHI32] = {
22697 .lhs = { [0] = { REG_VIRT0, COPY32_REGCM } },
22698 .rhs = { [0] = { REG_VIRT0, COPY32_REGCM } },
22700 [TEMPLATE_STORE8] = {
22701 .rhs = {
22702 [0] = { REG_UNSET, REGCM_GPR32 },
22703 [1] = { REG_UNSET, REGCM_GPR8_LO },
22706 [TEMPLATE_STORE16] = {
22707 .rhs = {
22708 [0] = { REG_UNSET, REGCM_GPR32 },
22709 [1] = { REG_UNSET, REGCM_GPR16 },
22712 [TEMPLATE_STORE32] = {
22713 .rhs = {
22714 [0] = { REG_UNSET, REGCM_GPR32 },
22715 [1] = { REG_UNSET, REGCM_GPR32 },
22718 [TEMPLATE_LOAD8] = {
22719 .lhs = { [0] = { REG_UNSET, REGCM_GPR8_LO } },
22720 .rhs = { [0] = { REG_UNSET, REGCM_GPR32 } },
22722 [TEMPLATE_LOAD16] = {
22723 .lhs = { [0] = { REG_UNSET, REGCM_GPR16 } },
22724 .rhs = { [0] = { REG_UNSET, REGCM_GPR32 } },
22726 [TEMPLATE_LOAD32] = {
22727 .lhs = { [0] = { REG_UNSET, REGCM_GPR32 } },
22728 .rhs = { [0] = { REG_UNSET, REGCM_GPR32 } },
22730 [TEMPLATE_BINARY8_REG] = {
22731 .lhs = { [0] = { REG_VIRT0, REGCM_GPR8_LO } },
22732 .rhs = {
22733 [0] = { REG_VIRT0, REGCM_GPR8_LO },
22734 [1] = { REG_UNSET, REGCM_GPR8_LO },
22737 [TEMPLATE_BINARY16_REG] = {
22738 .lhs = { [0] = { REG_VIRT0, REGCM_GPR16 } },
22739 .rhs = {
22740 [0] = { REG_VIRT0, REGCM_GPR16 },
22741 [1] = { REG_UNSET, REGCM_GPR16 },
22744 [TEMPLATE_BINARY32_REG] = {
22745 .lhs = { [0] = { REG_VIRT0, REGCM_GPR32 } },
22746 .rhs = {
22747 [0] = { REG_VIRT0, REGCM_GPR32 },
22748 [1] = { REG_UNSET, REGCM_GPR32 },
22751 [TEMPLATE_BINARY8_IMM] = {
22752 .lhs = { [0] = { REG_VIRT0, REGCM_GPR8_LO } },
22753 .rhs = {
22754 [0] = { REG_VIRT0, REGCM_GPR8_LO },
22755 [1] = { REG_UNNEEDED, REGCM_IMM8 },
22758 [TEMPLATE_BINARY16_IMM] = {
22759 .lhs = { [0] = { REG_VIRT0, REGCM_GPR16 } },
22760 .rhs = {
22761 [0] = { REG_VIRT0, REGCM_GPR16 },
22762 [1] = { REG_UNNEEDED, REGCM_IMM16 },
22765 [TEMPLATE_BINARY32_IMM] = {
22766 .lhs = { [0] = { REG_VIRT0, REGCM_GPR32 } },
22767 .rhs = {
22768 [0] = { REG_VIRT0, REGCM_GPR32 },
22769 [1] = { REG_UNNEEDED, REGCM_IMM32 },
22772 [TEMPLATE_SL8_CL] = {
22773 .lhs = { [0] = { REG_VIRT0, REGCM_GPR8_LO } },
22774 .rhs = {
22775 [0] = { REG_VIRT0, REGCM_GPR8_LO },
22776 [1] = { REG_CL, REGCM_GPR8_LO },
22779 [TEMPLATE_SL16_CL] = {
22780 .lhs = { [0] = { REG_VIRT0, REGCM_GPR16 } },
22781 .rhs = {
22782 [0] = { REG_VIRT0, REGCM_GPR16 },
22783 [1] = { REG_CL, REGCM_GPR8_LO },
22786 [TEMPLATE_SL32_CL] = {
22787 .lhs = { [0] = { REG_VIRT0, REGCM_GPR32 } },
22788 .rhs = {
22789 [0] = { REG_VIRT0, REGCM_GPR32 },
22790 [1] = { REG_CL, REGCM_GPR8_LO },
22793 [TEMPLATE_SL8_IMM] = {
22794 .lhs = { [0] = { REG_VIRT0, REGCM_GPR8_LO } },
22795 .rhs = {
22796 [0] = { REG_VIRT0, REGCM_GPR8_LO },
22797 [1] = { REG_UNNEEDED, REGCM_IMM8 },
22800 [TEMPLATE_SL16_IMM] = {
22801 .lhs = { [0] = { REG_VIRT0, REGCM_GPR16 } },
22802 .rhs = {
22803 [0] = { REG_VIRT0, REGCM_GPR16 },
22804 [1] = { REG_UNNEEDED, REGCM_IMM8 },
22807 [TEMPLATE_SL32_IMM] = {
22808 .lhs = { [0] = { REG_VIRT0, REGCM_GPR32 } },
22809 .rhs = {
22810 [0] = { REG_VIRT0, REGCM_GPR32 },
22811 [1] = { REG_UNNEEDED, REGCM_IMM8 },
22814 [TEMPLATE_UNARY8] = {
22815 .lhs = { [0] = { REG_VIRT0, REGCM_GPR8_LO } },
22816 .rhs = { [0] = { REG_VIRT0, REGCM_GPR8_LO } },
22818 [TEMPLATE_UNARY16] = {
22819 .lhs = { [0] = { REG_VIRT0, REGCM_GPR16 } },
22820 .rhs = { [0] = { REG_VIRT0, REGCM_GPR16 } },
22822 [TEMPLATE_UNARY32] = {
22823 .lhs = { [0] = { REG_VIRT0, REGCM_GPR32 } },
22824 .rhs = { [0] = { REG_VIRT0, REGCM_GPR32 } },
22826 [TEMPLATE_CMP8_REG] = {
22827 .lhs = { [0] = { REG_EFLAGS, REGCM_FLAGS } },
22828 .rhs = {
22829 [0] = { REG_UNSET, REGCM_GPR8_LO },
22830 [1] = { REG_UNSET, REGCM_GPR8_LO },
22833 [TEMPLATE_CMP16_REG] = {
22834 .lhs = { [0] = { REG_EFLAGS, REGCM_FLAGS } },
22835 .rhs = {
22836 [0] = { REG_UNSET, REGCM_GPR16 },
22837 [1] = { REG_UNSET, REGCM_GPR16 },
22840 [TEMPLATE_CMP32_REG] = {
22841 .lhs = { [0] = { REG_EFLAGS, REGCM_FLAGS } },
22842 .rhs = {
22843 [0] = { REG_UNSET, REGCM_GPR32 },
22844 [1] = { REG_UNSET, REGCM_GPR32 },
22847 [TEMPLATE_CMP8_IMM] = {
22848 .lhs = { [0] = { REG_EFLAGS, REGCM_FLAGS } },
22849 .rhs = {
22850 [0] = { REG_UNSET, REGCM_GPR8_LO },
22851 [1] = { REG_UNNEEDED, REGCM_IMM8 },
22854 [TEMPLATE_CMP16_IMM] = {
22855 .lhs = { [0] = { REG_EFLAGS, REGCM_FLAGS } },
22856 .rhs = {
22857 [0] = { REG_UNSET, REGCM_GPR16 },
22858 [1] = { REG_UNNEEDED, REGCM_IMM16 },
22861 [TEMPLATE_CMP32_IMM] = {
22862 .lhs = { [0] = { REG_EFLAGS, REGCM_FLAGS } },
22863 .rhs = {
22864 [0] = { REG_UNSET, REGCM_GPR32 },
22865 [1] = { REG_UNNEEDED, REGCM_IMM32 },
22868 [TEMPLATE_TEST8] = {
22869 .lhs = { [0] = { REG_EFLAGS, REGCM_FLAGS } },
22870 .rhs = { [0] = { REG_UNSET, REGCM_GPR8_LO } },
22872 [TEMPLATE_TEST16] = {
22873 .lhs = { [0] = { REG_EFLAGS, REGCM_FLAGS } },
22874 .rhs = { [0] = { REG_UNSET, REGCM_GPR16 } },
22876 [TEMPLATE_TEST32] = {
22877 .lhs = { [0] = { REG_EFLAGS, REGCM_FLAGS } },
22878 .rhs = { [0] = { REG_UNSET, REGCM_GPR32 } },
22880 [TEMPLATE_SET] = {
22881 .lhs = { [0] = { REG_UNSET, REGCM_GPR8_LO } },
22882 .rhs = { [0] = { REG_EFLAGS, REGCM_FLAGS } },
22884 [TEMPLATE_JMP] = {
22885 .rhs = { [0] = { REG_EFLAGS, REGCM_FLAGS } },
22887 [TEMPLATE_RET] = {
22888 .rhs = { [0] = { REG_UNSET, REGCM_GPR32 } },
22890 [TEMPLATE_INB_DX] = {
22891 .lhs = { [0] = { REG_AL, REGCM_GPR8_LO } },
22892 .rhs = { [0] = { REG_DX, REGCM_GPR16 } },
22894 [TEMPLATE_INB_IMM] = {
22895 .lhs = { [0] = { REG_AL, REGCM_GPR8_LO } },
22896 .rhs = { [0] = { REG_UNNEEDED, REGCM_IMM8 } },
22898 [TEMPLATE_INW_DX] = {
22899 .lhs = { [0] = { REG_AX, REGCM_GPR16 } },
22900 .rhs = { [0] = { REG_DX, REGCM_GPR16 } },
22902 [TEMPLATE_INW_IMM] = {
22903 .lhs = { [0] = { REG_AX, REGCM_GPR16 } },
22904 .rhs = { [0] = { REG_UNNEEDED, REGCM_IMM8 } },
22906 [TEMPLATE_INL_DX] = {
22907 .lhs = { [0] = { REG_EAX, REGCM_GPR32 } },
22908 .rhs = { [0] = { REG_DX, REGCM_GPR16 } },
22910 [TEMPLATE_INL_IMM] = {
22911 .lhs = { [0] = { REG_EAX, REGCM_GPR32 } },
22912 .rhs = { [0] = { REG_UNNEEDED, REGCM_IMM8 } },
22914 [TEMPLATE_OUTB_DX] = {
22915 .rhs = {
22916 [0] = { REG_AL, REGCM_GPR8_LO },
22917 [1] = { REG_DX, REGCM_GPR16 },
22920 [TEMPLATE_OUTB_IMM] = {
22921 .rhs = {
22922 [0] = { REG_AL, REGCM_GPR8_LO },
22923 [1] = { REG_UNNEEDED, REGCM_IMM8 },
22926 [TEMPLATE_OUTW_DX] = {
22927 .rhs = {
22928 [0] = { REG_AX, REGCM_GPR16 },
22929 [1] = { REG_DX, REGCM_GPR16 },
22932 [TEMPLATE_OUTW_IMM] = {
22933 .rhs = {
22934 [0] = { REG_AX, REGCM_GPR16 },
22935 [1] = { REG_UNNEEDED, REGCM_IMM8 },
22938 [TEMPLATE_OUTL_DX] = {
22939 .rhs = {
22940 [0] = { REG_EAX, REGCM_GPR32 },
22941 [1] = { REG_DX, REGCM_GPR16 },
22944 [TEMPLATE_OUTL_IMM] = {
22945 .rhs = {
22946 [0] = { REG_EAX, REGCM_GPR32 },
22947 [1] = { REG_UNNEEDED, REGCM_IMM8 },
22950 [TEMPLATE_BSF] = {
22951 .lhs = { [0] = { REG_UNSET, REGCM_GPR32 } },
22952 .rhs = { [0] = { REG_UNSET, REGCM_GPR32 } },
22954 [TEMPLATE_RDMSR] = {
22955 .lhs = {
22956 [0] = { REG_EAX, REGCM_GPR32 },
22957 [1] = { REG_EDX, REGCM_GPR32 },
22959 .rhs = { [0] = { REG_ECX, REGCM_GPR32 } },
22961 [TEMPLATE_WRMSR] = {
22962 .rhs = {
22963 [0] = { REG_ECX, REGCM_GPR32 },
22964 [1] = { REG_EAX, REGCM_GPR32 },
22965 [2] = { REG_EDX, REGCM_GPR32 },
22968 [TEMPLATE_UMUL8] = {
22969 .lhs = { [0] = { REG_AX, REGCM_GPR16 } },
22970 .rhs = {
22971 [0] = { REG_AL, REGCM_GPR8_LO },
22972 [1] = { REG_UNSET, REGCM_GPR8_LO },
22975 [TEMPLATE_UMUL16] = {
22976 .lhs = { [0] = { REG_DXAX, REGCM_DIVIDEND32 } },
22977 .rhs = {
22978 [0] = { REG_AX, REGCM_GPR16 },
22979 [1] = { REG_UNSET, REGCM_GPR16 },
22982 [TEMPLATE_UMUL32] = {
22983 .lhs = { [0] = { REG_EDXEAX, REGCM_DIVIDEND64 } },
22984 .rhs = {
22985 [0] = { REG_EAX, REGCM_GPR32 },
22986 [1] = { REG_UNSET, REGCM_GPR32 },
22989 [TEMPLATE_DIV8] = {
22990 .lhs = {
22991 [0] = { REG_AL, REGCM_GPR8_LO },
22992 [1] = { REG_AH, REGCM_GPR8 },
22994 .rhs = {
22995 [0] = { REG_AX, REGCM_GPR16 },
22996 [1] = { REG_UNSET, REGCM_GPR8_LO },
22999 [TEMPLATE_DIV16] = {
23000 .lhs = {
23001 [0] = { REG_AX, REGCM_GPR16 },
23002 [1] = { REG_DX, REGCM_GPR16 },
23004 .rhs = {
23005 [0] = { REG_DXAX, REGCM_DIVIDEND32 },
23006 [1] = { REG_UNSET, REGCM_GPR16 },
23009 [TEMPLATE_DIV32] = {
23010 .lhs = {
23011 [0] = { REG_EAX, REGCM_GPR32 },
23012 [1] = { REG_EDX, REGCM_GPR32 },
23014 .rhs = {
23015 [0] = { REG_EDXEAX, REGCM_DIVIDEND64 },
23016 [1] = { REG_UNSET, REGCM_GPR32 },
23021 static void fixup_branch(struct compile_state *state,
23022 struct triple *branch, int jmp_op, int cmp_op, struct type *cmp_type,
23023 struct triple *left, struct triple *right)
23025 struct triple *test;
23026 if (!left) {
23027 internal_error(state, branch, "no branch test?");
23029 test = pre_triple(state, branch,
23030 cmp_op, cmp_type, left, right);
23031 test->template_id = TEMPLATE_TEST32;
23032 if (cmp_op == OP_CMP) {
23033 test->template_id = TEMPLATE_CMP32_REG;
23034 if (get_imm32(test, &RHS(test, 1))) {
23035 test->template_id = TEMPLATE_CMP32_IMM;
23038 use_triple(RHS(test, 0), test);
23039 use_triple(RHS(test, 1), test);
23040 unuse_triple(RHS(branch, 0), branch);
23041 RHS(branch, 0) = test;
23042 branch->op = jmp_op;
23043 branch->template_id = TEMPLATE_JMP;
23044 use_triple(RHS(branch, 0), branch);
23047 static void fixup_branches(struct compile_state *state,
23048 struct triple *cmp, struct triple *use, int jmp_op)
23050 struct triple_set *entry, *next;
23051 for(entry = use->use; entry; entry = next) {
23052 next = entry->next;
23053 if (entry->member->op == OP_COPY) {
23054 fixup_branches(state, cmp, entry->member, jmp_op);
23056 else if (entry->member->op == OP_CBRANCH) {
23057 struct triple *branch;
23058 struct triple *left, *right;
23059 left = right = 0;
23060 left = RHS(cmp, 0);
23061 if (cmp->rhs > 1) {
23062 right = RHS(cmp, 1);
23064 branch = entry->member;
23065 fixup_branch(state, branch, jmp_op,
23066 cmp->op, cmp->type, left, right);
23071 static void bool_cmp(struct compile_state *state,
23072 struct triple *ins, int cmp_op, int jmp_op, int set_op)
23074 struct triple_set *entry, *next;
23075 struct triple *set, *convert;
23077 /* Put a barrier up before the cmp which preceeds the
23078 * copy instruction. If a set actually occurs this gives
23079 * us a chance to move variables in registers out of the way.
23082 /* Modify the comparison operator */
23083 ins->op = cmp_op;
23084 ins->template_id = TEMPLATE_TEST32;
23085 if (cmp_op == OP_CMP) {
23086 ins->template_id = TEMPLATE_CMP32_REG;
23087 if (get_imm32(ins, &RHS(ins, 1))) {
23088 ins->template_id = TEMPLATE_CMP32_IMM;
23091 /* Generate the instruction sequence that will transform the
23092 * result of the comparison into a logical value.
23094 set = post_triple(state, ins, set_op, &uchar_type, ins, 0);
23095 use_triple(ins, set);
23096 set->template_id = TEMPLATE_SET;
23098 convert = set;
23099 if (!equiv_types(ins->type, set->type)) {
23100 convert = post_triple(state, set, OP_CONVERT, ins->type, set, 0);
23101 use_triple(set, convert);
23102 convert->template_id = TEMPLATE_COPY32_REG;
23105 for(entry = ins->use; entry; entry = next) {
23106 next = entry->next;
23107 if (entry->member == set) {
23108 continue;
23110 replace_rhs_use(state, ins, convert, entry->member);
23112 fixup_branches(state, ins, convert, jmp_op);
23115 struct reg_info arch_reg_lhs(struct compile_state *state, struct triple *ins, int index)
23117 struct ins_template *template;
23118 struct reg_info result;
23119 int zlhs;
23120 if (ins->op == OP_PIECE) {
23121 index = ins->u.cval;
23122 ins = MISC(ins, 0);
23124 zlhs = ins->lhs;
23125 if (triple_is_def(state, ins)) {
23126 zlhs = 1;
23128 if (index >= zlhs) {
23129 internal_error(state, ins, "index %d out of range for %s",
23130 index, tops(ins->op));
23132 switch(ins->op) {
23133 case OP_ASM:
23134 template = &ins->u.ainfo->tmpl;
23135 break;
23136 default:
23137 if (ins->template_id > LAST_TEMPLATE) {
23138 internal_error(state, ins, "bad template number %d",
23139 ins->template_id);
23141 template = &templates[ins->template_id];
23142 break;
23144 result = template->lhs[index];
23145 result.regcm = arch_regcm_normalize(state, result.regcm);
23146 if (result.reg != REG_UNNEEDED) {
23147 result.regcm &= ~(REGCM_IMM32 | REGCM_IMM16 | REGCM_IMM8);
23149 if (result.regcm == 0) {
23150 internal_error(state, ins, "lhs %d regcm == 0", index);
23152 return result;
23155 struct reg_info arch_reg_rhs(struct compile_state *state, struct triple *ins, int index)
23157 struct reg_info result;
23158 struct ins_template *template;
23159 if ((index > ins->rhs) ||
23160 (ins->op == OP_PIECE)) {
23161 internal_error(state, ins, "index %d out of range for %s\n",
23162 index, tops(ins->op));
23164 switch(ins->op) {
23165 case OP_ASM:
23166 template = &ins->u.ainfo->tmpl;
23167 break;
23168 case OP_PHI:
23169 index = 0;
23170 /* Fall through */
23171 default:
23172 if (ins->template_id > LAST_TEMPLATE) {
23173 internal_error(state, ins, "bad template number %d",
23174 ins->template_id);
23176 template = &templates[ins->template_id];
23177 break;
23179 result = template->rhs[index];
23180 result.regcm = arch_regcm_normalize(state, result.regcm);
23181 if (result.regcm == 0) {
23182 internal_error(state, ins, "rhs %d regcm == 0", index);
23184 return result;
23187 static struct triple *mod_div(struct compile_state *state,
23188 struct triple *ins, int div_op, int index)
23190 struct triple *div, *piece1;
23192 /* Generate the appropriate division instruction */
23193 div = post_triple(state, ins, div_op, ins->type, 0, 0);
23194 RHS(div, 0) = RHS(ins, 0);
23195 RHS(div, 1) = RHS(ins, 1);
23196 piece1 = LHS(div, 1);
23197 div->template_id = TEMPLATE_DIV32;
23198 use_triple(RHS(div, 0), div);
23199 use_triple(RHS(div, 1), div);
23200 use_triple(LHS(div, 0), div);
23201 use_triple(LHS(div, 1), div);
23203 /* Replate uses of ins with the appropriate piece of the div */
23204 propagate_use(state, ins, LHS(div, index));
23205 release_triple(state, ins);
23207 /* Return the address of the next instruction */
23208 return piece1->next;
23211 static int noop_adecl(struct triple *adecl)
23213 struct triple_set *use;
23214 /* It's a noop if it doesn't specify stoorage */
23215 if (adecl->lhs == 0) {
23216 return 1;
23218 /* Is the adecl used? If not it's a noop */
23219 for(use = adecl->use; use ; use = use->next) {
23220 if ((use->member->op != OP_PIECE) ||
23221 (MISC(use->member, 0) != adecl)) {
23222 return 0;
23225 return 1;
23228 static struct triple *x86_deposit(struct compile_state *state, struct triple *ins)
23230 struct triple *mask, *nmask, *shift;
23231 struct triple *val, *val_mask, *val_shift;
23232 struct triple *targ, *targ_mask;
23233 struct triple *new;
23234 ulong_t the_mask, the_nmask;
23236 targ = RHS(ins, 0);
23237 val = RHS(ins, 1);
23239 /* Get constant for the mask value */
23240 the_mask = 1;
23241 the_mask <<= ins->u.bitfield.size;
23242 the_mask -= 1;
23243 the_mask <<= ins->u.bitfield.offset;
23244 mask = pre_triple(state, ins, OP_INTCONST, &uint_type, 0, 0);
23245 mask->u.cval = the_mask;
23247 /* Get the inverted mask value */
23248 the_nmask = ~the_mask;
23249 nmask = pre_triple(state, ins, OP_INTCONST, &uint_type, 0, 0);
23250 nmask->u.cval = the_nmask;
23252 /* Get constant for the shift value */
23253 shift = pre_triple(state, ins, OP_INTCONST, &uint_type, 0, 0);
23254 shift->u.cval = ins->u.bitfield.offset;
23256 /* Shift and mask the source value */
23257 val_shift = val;
23258 if (shift->u.cval != 0) {
23259 val_shift = pre_triple(state, ins, OP_SL, val->type, val, shift);
23260 use_triple(val, val_shift);
23261 use_triple(shift, val_shift);
23263 val_mask = val_shift;
23264 if (is_signed(val->type)) {
23265 val_mask = pre_triple(state, ins, OP_AND, val->type, val_shift, mask);
23266 use_triple(val_shift, val_mask);
23267 use_triple(mask, val_mask);
23270 /* Mask the target value */
23271 targ_mask = pre_triple(state, ins, OP_AND, targ->type, targ, nmask);
23272 use_triple(targ, targ_mask);
23273 use_triple(nmask, targ_mask);
23275 /* Now combined them together */
23276 new = pre_triple(state, ins, OP_OR, targ->type, targ_mask, val_mask);
23277 use_triple(targ_mask, new);
23278 use_triple(val_mask, new);
23280 /* Move all of the users over to the new expression */
23281 propagate_use(state, ins, new);
23283 /* Delete the original triple */
23284 release_triple(state, ins);
23286 /* Restart the transformation at mask */
23287 return mask;
23290 static struct triple *x86_extract(struct compile_state *state, struct triple *ins)
23292 struct triple *mask, *shift;
23293 struct triple *val, *val_mask, *val_shift;
23294 ulong_t the_mask;
23296 val = RHS(ins, 0);
23298 /* Get constant for the mask value */
23299 the_mask = 1;
23300 the_mask <<= ins->u.bitfield.size;
23301 the_mask -= 1;
23302 mask = pre_triple(state, ins, OP_INTCONST, &int_type, 0, 0);
23303 mask->u.cval = the_mask;
23305 /* Get constant for the right shift value */
23306 shift = pre_triple(state, ins, OP_INTCONST, &int_type, 0, 0);
23307 shift->u.cval = ins->u.bitfield.offset;
23309 /* Shift arithmetic right, to correct the sign */
23310 val_shift = val;
23311 if (shift->u.cval != 0) {
23312 int op;
23313 if (ins->op == OP_SEXTRACT) {
23314 op = OP_SSR;
23315 } else {
23316 op = OP_USR;
23318 val_shift = pre_triple(state, ins, op, val->type, val, shift);
23319 use_triple(val, val_shift);
23320 use_triple(shift, val_shift);
23323 /* Finally mask the value */
23324 val_mask = pre_triple(state, ins, OP_AND, ins->type, val_shift, mask);
23325 use_triple(val_shift, val_mask);
23326 use_triple(mask, val_mask);
23328 /* Move all of the users over to the new expression */
23329 propagate_use(state, ins, val_mask);
23331 /* Release the original instruction */
23332 release_triple(state, ins);
23334 return mask;
23338 static struct triple *transform_to_arch_instruction(
23339 struct compile_state *state, struct triple *ins)
23341 /* Transform from generic 3 address instructions
23342 * to archtecture specific instructions.
23343 * And apply architecture specific constraints to instructions.
23344 * Copies are inserted to preserve the register flexibility
23345 * of 3 address instructions.
23347 struct triple *next, *value;
23348 size_t size;
23349 next = ins->next;
23350 switch(ins->op) {
23351 case OP_INTCONST:
23352 ins->template_id = TEMPLATE_INTCONST32;
23353 if (ins->u.cval < 256) {
23354 ins->template_id = TEMPLATE_INTCONST8;
23356 break;
23357 case OP_ADDRCONST:
23358 ins->template_id = TEMPLATE_INTCONST32;
23359 break;
23360 case OP_UNKNOWNVAL:
23361 ins->template_id = TEMPLATE_UNKNOWNVAL;
23362 break;
23363 case OP_NOOP:
23364 case OP_SDECL:
23365 case OP_BLOBCONST:
23366 case OP_LABEL:
23367 ins->template_id = TEMPLATE_NOP;
23368 break;
23369 case OP_COPY:
23370 case OP_CONVERT:
23371 size = size_of(state, ins->type);
23372 value = RHS(ins, 0);
23373 if (is_imm8(value) && (size <= SIZEOF_I8)) {
23374 ins->template_id = TEMPLATE_COPY_IMM8;
23376 else if (is_imm16(value) && (size <= SIZEOF_I16)) {
23377 ins->template_id = TEMPLATE_COPY_IMM16;
23379 else if (is_imm32(value) && (size <= SIZEOF_I32)) {
23380 ins->template_id = TEMPLATE_COPY_IMM32;
23382 else if (is_const(value)) {
23383 internal_error(state, ins, "bad constant passed to copy");
23385 else if (size <= SIZEOF_I8) {
23386 ins->template_id = TEMPLATE_COPY8_REG;
23388 else if (size <= SIZEOF_I16) {
23389 ins->template_id = TEMPLATE_COPY16_REG;
23391 else if (size <= SIZEOF_I32) {
23392 ins->template_id = TEMPLATE_COPY32_REG;
23394 else {
23395 internal_error(state, ins, "bad type passed to copy");
23397 break;
23398 case OP_PHI:
23399 size = size_of(state, ins->type);
23400 if (size <= SIZEOF_I8) {
23401 ins->template_id = TEMPLATE_PHI8;
23403 else if (size <= SIZEOF_I16) {
23404 ins->template_id = TEMPLATE_PHI16;
23406 else if (size <= SIZEOF_I32) {
23407 ins->template_id = TEMPLATE_PHI32;
23409 else {
23410 internal_error(state, ins, "bad type passed to phi");
23412 break;
23413 case OP_ADECL:
23414 /* Adecls should always be treated as dead code and
23415 * removed. If we are not optimizing they may linger.
23417 if (!noop_adecl(ins)) {
23418 internal_error(state, ins, "adecl remains?");
23420 ins->template_id = TEMPLATE_NOP;
23421 next = after_lhs(state, ins);
23422 break;
23423 case OP_STORE:
23424 switch(ins->type->type & TYPE_MASK) {
23425 case TYPE_CHAR: case TYPE_UCHAR:
23426 ins->template_id = TEMPLATE_STORE8;
23427 break;
23428 case TYPE_SHORT: case TYPE_USHORT:
23429 ins->template_id = TEMPLATE_STORE16;
23430 break;
23431 case TYPE_INT: case TYPE_UINT:
23432 case TYPE_LONG: case TYPE_ULONG:
23433 case TYPE_POINTER:
23434 ins->template_id = TEMPLATE_STORE32;
23435 break;
23436 default:
23437 internal_error(state, ins, "unknown type in store");
23438 break;
23440 break;
23441 case OP_LOAD:
23442 switch(ins->type->type & TYPE_MASK) {
23443 case TYPE_CHAR: case TYPE_UCHAR:
23444 case TYPE_SHORT: case TYPE_USHORT:
23445 case TYPE_INT: case TYPE_UINT:
23446 case TYPE_LONG: case TYPE_ULONG:
23447 case TYPE_POINTER:
23448 break;
23449 default:
23450 internal_error(state, ins, "unknown type in load");
23451 break;
23453 ins->template_id = TEMPLATE_LOAD32;
23454 break;
23455 case OP_ADD:
23456 case OP_SUB:
23457 case OP_AND:
23458 case OP_XOR:
23459 case OP_OR:
23460 case OP_SMUL:
23461 ins->template_id = TEMPLATE_BINARY32_REG;
23462 if (get_imm32(ins, &RHS(ins, 1))) {
23463 ins->template_id = TEMPLATE_BINARY32_IMM;
23465 break;
23466 case OP_SDIVT:
23467 case OP_UDIVT:
23468 ins->template_id = TEMPLATE_DIV32;
23469 next = after_lhs(state, ins);
23470 break;
23471 case OP_UMUL:
23472 ins->template_id = TEMPLATE_UMUL32;
23473 break;
23474 case OP_UDIV:
23475 next = mod_div(state, ins, OP_UDIVT, 0);
23476 break;
23477 case OP_SDIV:
23478 next = mod_div(state, ins, OP_SDIVT, 0);
23479 break;
23480 case OP_UMOD:
23481 next = mod_div(state, ins, OP_UDIVT, 1);
23482 break;
23483 case OP_SMOD:
23484 next = mod_div(state, ins, OP_SDIVT, 1);
23485 break;
23486 case OP_SL:
23487 case OP_SSR:
23488 case OP_USR:
23489 ins->template_id = TEMPLATE_SL32_CL;
23490 if (get_imm8(ins, &RHS(ins, 1))) {
23491 ins->template_id = TEMPLATE_SL32_IMM;
23492 } else if (size_of(state, RHS(ins, 1)->type) > SIZEOF_CHAR) {
23493 typed_pre_copy(state, &uchar_type, ins, 1);
23495 break;
23496 case OP_INVERT:
23497 case OP_NEG:
23498 ins->template_id = TEMPLATE_UNARY32;
23499 break;
23500 case OP_EQ:
23501 bool_cmp(state, ins, OP_CMP, OP_JMP_EQ, OP_SET_EQ);
23502 break;
23503 case OP_NOTEQ:
23504 bool_cmp(state, ins, OP_CMP, OP_JMP_NOTEQ, OP_SET_NOTEQ);
23505 break;
23506 case OP_SLESS:
23507 bool_cmp(state, ins, OP_CMP, OP_JMP_SLESS, OP_SET_SLESS);
23508 break;
23509 case OP_ULESS:
23510 bool_cmp(state, ins, OP_CMP, OP_JMP_ULESS, OP_SET_ULESS);
23511 break;
23512 case OP_SMORE:
23513 bool_cmp(state, ins, OP_CMP, OP_JMP_SMORE, OP_SET_SMORE);
23514 break;
23515 case OP_UMORE:
23516 bool_cmp(state, ins, OP_CMP, OP_JMP_UMORE, OP_SET_UMORE);
23517 break;
23518 case OP_SLESSEQ:
23519 bool_cmp(state, ins, OP_CMP, OP_JMP_SLESSEQ, OP_SET_SLESSEQ);
23520 break;
23521 case OP_ULESSEQ:
23522 bool_cmp(state, ins, OP_CMP, OP_JMP_ULESSEQ, OP_SET_ULESSEQ);
23523 break;
23524 case OP_SMOREEQ:
23525 bool_cmp(state, ins, OP_CMP, OP_JMP_SMOREEQ, OP_SET_SMOREEQ);
23526 break;
23527 case OP_UMOREEQ:
23528 bool_cmp(state, ins, OP_CMP, OP_JMP_UMOREEQ, OP_SET_UMOREEQ);
23529 break;
23530 case OP_LTRUE:
23531 bool_cmp(state, ins, OP_TEST, OP_JMP_NOTEQ, OP_SET_NOTEQ);
23532 break;
23533 case OP_LFALSE:
23534 bool_cmp(state, ins, OP_TEST, OP_JMP_EQ, OP_SET_EQ);
23535 break;
23536 case OP_BRANCH:
23537 ins->op = OP_JMP;
23538 ins->template_id = TEMPLATE_NOP;
23539 break;
23540 case OP_CBRANCH:
23541 fixup_branch(state, ins, OP_JMP_NOTEQ, OP_TEST,
23542 RHS(ins, 0)->type, RHS(ins, 0), 0);
23543 break;
23544 case OP_CALL:
23545 ins->template_id = TEMPLATE_NOP;
23546 break;
23547 case OP_RET:
23548 ins->template_id = TEMPLATE_RET;
23549 break;
23550 case OP_INB:
23551 case OP_INW:
23552 case OP_INL:
23553 switch(ins->op) {
23554 case OP_INB: ins->template_id = TEMPLATE_INB_DX; break;
23555 case OP_INW: ins->template_id = TEMPLATE_INW_DX; break;
23556 case OP_INL: ins->template_id = TEMPLATE_INL_DX; break;
23558 if (get_imm8(ins, &RHS(ins, 0))) {
23559 ins->template_id += 1;
23561 break;
23562 case OP_OUTB:
23563 case OP_OUTW:
23564 case OP_OUTL:
23565 switch(ins->op) {
23566 case OP_OUTB: ins->template_id = TEMPLATE_OUTB_DX; break;
23567 case OP_OUTW: ins->template_id = TEMPLATE_OUTW_DX; break;
23568 case OP_OUTL: ins->template_id = TEMPLATE_OUTL_DX; break;
23570 if (get_imm8(ins, &RHS(ins, 1))) {
23571 ins->template_id += 1;
23573 break;
23574 case OP_BSF:
23575 case OP_BSR:
23576 ins->template_id = TEMPLATE_BSF;
23577 break;
23578 case OP_RDMSR:
23579 ins->template_id = TEMPLATE_RDMSR;
23580 next = after_lhs(state, ins);
23581 break;
23582 case OP_WRMSR:
23583 ins->template_id = TEMPLATE_WRMSR;
23584 break;
23585 case OP_HLT:
23586 ins->template_id = TEMPLATE_NOP;
23587 break;
23588 case OP_ASM:
23589 ins->template_id = TEMPLATE_NOP;
23590 next = after_lhs(state, ins);
23591 break;
23592 /* Already transformed instructions */
23593 case OP_TEST:
23594 ins->template_id = TEMPLATE_TEST32;
23595 break;
23596 case OP_CMP:
23597 ins->template_id = TEMPLATE_CMP32_REG;
23598 if (get_imm32(ins, &RHS(ins, 1))) {
23599 ins->template_id = TEMPLATE_CMP32_IMM;
23601 break;
23602 case OP_JMP:
23603 ins->template_id = TEMPLATE_NOP;
23604 break;
23605 case OP_JMP_EQ: case OP_JMP_NOTEQ:
23606 case OP_JMP_SLESS: case OP_JMP_ULESS:
23607 case OP_JMP_SMORE: case OP_JMP_UMORE:
23608 case OP_JMP_SLESSEQ: case OP_JMP_ULESSEQ:
23609 case OP_JMP_SMOREEQ: case OP_JMP_UMOREEQ:
23610 ins->template_id = TEMPLATE_JMP;
23611 break;
23612 case OP_SET_EQ: case OP_SET_NOTEQ:
23613 case OP_SET_SLESS: case OP_SET_ULESS:
23614 case OP_SET_SMORE: case OP_SET_UMORE:
23615 case OP_SET_SLESSEQ: case OP_SET_ULESSEQ:
23616 case OP_SET_SMOREEQ: case OP_SET_UMOREEQ:
23617 ins->template_id = TEMPLATE_SET;
23618 break;
23619 case OP_DEPOSIT:
23620 next = x86_deposit(state, ins);
23621 break;
23622 case OP_SEXTRACT:
23623 case OP_UEXTRACT:
23624 next = x86_extract(state, ins);
23625 break;
23626 /* Unhandled instructions */
23627 case OP_PIECE:
23628 default:
23629 internal_error(state, ins, "unhandled ins: %d %s",
23630 ins->op, tops(ins->op));
23631 break;
23633 return next;
23636 static long next_label(struct compile_state *state)
23638 static long label_counter = 1000;
23639 return ++label_counter;
23641 static void generate_local_labels(struct compile_state *state)
23643 struct triple *first, *label;
23644 first = state->first;
23645 label = first;
23646 do {
23647 if ((label->op == OP_LABEL) ||
23648 (label->op == OP_SDECL)) {
23649 if (label->use) {
23650 label->u.cval = next_label(state);
23651 } else {
23652 label->u.cval = 0;
23656 label = label->next;
23657 } while(label != first);
23660 static int check_reg(struct compile_state *state,
23661 struct triple *triple, int classes)
23663 unsigned mask;
23664 int reg;
23665 reg = ID_REG(triple->id);
23666 if (reg == REG_UNSET) {
23667 internal_error(state, triple, "register not set");
23669 mask = arch_reg_regcm(state, reg);
23670 if (!(classes & mask)) {
23671 internal_error(state, triple, "reg %d in wrong class",
23672 reg);
23674 return reg;
23678 #if REG_XMM7 != 44
23679 #error "Registers have renumberd fix arch_reg_str"
23680 #endif
23681 static const char *arch_regs[] = {
23682 "%unset",
23683 "%unneeded",
23684 "%eflags",
23685 "%al", "%bl", "%cl", "%dl", "%ah", "%bh", "%ch", "%dh",
23686 "%ax", "%bx", "%cx", "%dx", "%si", "%di", "%bp", "%sp",
23687 "%eax", "%ebx", "%ecx", "%edx", "%esi", "%edi", "%ebp", "%esp",
23688 "%edx:%eax",
23689 "%dx:%ax",
23690 "%mm0", "%mm1", "%mm2", "%mm3", "%mm4", "%mm5", "%mm6", "%mm7",
23691 "%xmm0", "%xmm1", "%xmm2", "%xmm3",
23692 "%xmm4", "%xmm5", "%xmm6", "%xmm7",
23694 static const char *arch_reg_str(int reg)
23696 if (!((reg >= REG_EFLAGS) && (reg <= REG_XMM7))) {
23697 reg = 0;
23699 return arch_regs[reg];
23702 static const char *reg(struct compile_state *state, struct triple *triple,
23703 int classes)
23705 int reg;
23706 reg = check_reg(state, triple, classes);
23707 return arch_reg_str(reg);
23710 static int arch_reg_size(int reg)
23712 int size;
23713 size = 0;
23714 if (reg == REG_EFLAGS) {
23715 size = 32;
23717 else if ((reg >= REG_AL) && (reg <= REG_DH)) {
23718 size = 8;
23720 else if ((reg >= REG_AX) && (reg <= REG_SP)) {
23721 size = 16;
23723 else if ((reg >= REG_EAX) && (reg <= REG_ESP)) {
23724 size = 32;
23726 else if (reg == REG_EDXEAX) {
23727 size = 64;
23729 else if (reg == REG_DXAX) {
23730 size = 32;
23732 else if ((reg >= REG_MMX0) && (reg <= REG_MMX7)) {
23733 size = 64;
23735 else if ((reg >= REG_XMM0) && (reg <= REG_XMM7)) {
23736 size = 128;
23738 return size;
23741 static int reg_size(struct compile_state *state, struct triple *ins)
23743 int reg;
23744 reg = ID_REG(ins->id);
23745 if (reg == REG_UNSET) {
23746 internal_error(state, ins, "register not set");
23748 return arch_reg_size(reg);
23753 const char *type_suffix(struct compile_state *state, struct type *type)
23755 const char *suffix;
23756 switch(size_of(state, type)) {
23757 case SIZEOF_I8: suffix = "b"; break;
23758 case SIZEOF_I16: suffix = "w"; break;
23759 case SIZEOF_I32: suffix = "l"; break;
23760 default:
23761 internal_error(state, 0, "unknown suffix");
23762 suffix = 0;
23763 break;
23765 return suffix;
23768 static void print_const_val(
23769 struct compile_state *state, struct triple *ins, FILE *fp)
23771 switch(ins->op) {
23772 case OP_INTCONST:
23773 fprintf(fp, " $%ld ",
23774 (long)(ins->u.cval));
23775 break;
23776 case OP_ADDRCONST:
23777 if ((MISC(ins, 0)->op != OP_SDECL) &&
23778 (MISC(ins, 0)->op != OP_LABEL))
23780 internal_error(state, ins, "bad base for addrconst");
23782 if (MISC(ins, 0)->u.cval <= 0) {
23783 internal_error(state, ins, "unlabeled constant");
23785 fprintf(fp, " $L%s%lu+%lu ",
23786 state->compiler->label_prefix,
23787 (unsigned long)(MISC(ins, 0)->u.cval),
23788 (unsigned long)(ins->u.cval));
23789 break;
23790 default:
23791 internal_error(state, ins, "unknown constant type");
23792 break;
23796 static void print_const(struct compile_state *state,
23797 struct triple *ins, FILE *fp)
23799 switch(ins->op) {
23800 case OP_INTCONST:
23801 switch(ins->type->type & TYPE_MASK) {
23802 case TYPE_CHAR:
23803 case TYPE_UCHAR:
23804 fprintf(fp, ".byte 0x%02lx\n",
23805 (unsigned long)(ins->u.cval));
23806 break;
23807 case TYPE_SHORT:
23808 case TYPE_USHORT:
23809 fprintf(fp, ".short 0x%04lx\n",
23810 (unsigned long)(ins->u.cval));
23811 break;
23812 case TYPE_INT:
23813 case TYPE_UINT:
23814 case TYPE_LONG:
23815 case TYPE_ULONG:
23816 case TYPE_POINTER:
23817 fprintf(fp, ".int %lu\n",
23818 (unsigned long)(ins->u.cval));
23819 break;
23820 default:
23821 fprintf(state->errout, "type: ");
23822 name_of(state->errout, ins->type);
23823 fprintf(state->errout, "\n");
23824 internal_error(state, ins, "Unknown constant type. Val: %lu",
23825 (unsigned long)(ins->u.cval));
23828 break;
23829 case OP_ADDRCONST:
23830 if ((MISC(ins, 0)->op != OP_SDECL) &&
23831 (MISC(ins, 0)->op != OP_LABEL)) {
23832 internal_error(state, ins, "bad base for addrconst");
23834 if (MISC(ins, 0)->u.cval <= 0) {
23835 internal_error(state, ins, "unlabeled constant");
23837 fprintf(fp, ".int L%s%lu+%lu\n",
23838 state->compiler->label_prefix,
23839 (unsigned long)(MISC(ins, 0)->u.cval),
23840 (unsigned long)(ins->u.cval));
23841 break;
23842 case OP_BLOBCONST:
23844 unsigned char *blob;
23845 size_t size, i;
23846 size = size_of_in_bytes(state, ins->type);
23847 blob = ins->u.blob;
23848 for(i = 0; i < size; i++) {
23849 fprintf(fp, ".byte 0x%02x\n",
23850 blob[i]);
23852 break;
23854 default:
23855 internal_error(state, ins, "Unknown constant type");
23856 break;
23860 #define TEXT_SECTION ".rom.text"
23861 #define DATA_SECTION ".rom.data"
23863 static long get_const_pool_ref(
23864 struct compile_state *state, struct triple *ins, size_t size, FILE *fp)
23866 size_t fill_bytes;
23867 long ref;
23868 ref = next_label(state);
23869 fprintf(fp, ".section \"" DATA_SECTION "\"\n");
23870 fprintf(fp, ".balign %ld\n", (long int)align_of_in_bytes(state, ins->type));
23871 fprintf(fp, "L%s%lu:\n", state->compiler->label_prefix, ref);
23872 print_const(state, ins, fp);
23873 fill_bytes = bits_to_bytes(size - size_of(state, ins->type));
23874 if (fill_bytes) {
23875 fprintf(fp, ".fill %ld, 1, 0\n", (long int)fill_bytes);
23877 fprintf(fp, ".section \"" TEXT_SECTION "\"\n");
23878 return ref;
23881 static long get_mask_pool_ref(
23882 struct compile_state *state, struct triple *ins, unsigned long mask, FILE *fp)
23884 long ref;
23885 if (mask == 0xff) {
23886 ref = 1;
23888 else if (mask == 0xffff) {
23889 ref = 2;
23891 else {
23892 internal_error(state, ins, "unhandled mask value");
23894 return ref;
23897 static void print_binary_op(struct compile_state *state,
23898 const char *op, struct triple *ins, FILE *fp)
23900 unsigned mask;
23901 mask = REGCM_GPR32 | REGCM_GPR16 | REGCM_GPR8_LO;
23902 if (ID_REG(RHS(ins, 0)->id) != ID_REG(ins->id)) {
23903 internal_error(state, ins, "invalid register assignment");
23905 if (is_const(RHS(ins, 1))) {
23906 fprintf(fp, "\t%s ", op);
23907 print_const_val(state, RHS(ins, 1), fp);
23908 fprintf(fp, ", %s\n",
23909 reg(state, RHS(ins, 0), mask));
23911 else {
23912 unsigned lmask, rmask;
23913 int lreg, rreg;
23914 lreg = check_reg(state, RHS(ins, 0), mask);
23915 rreg = check_reg(state, RHS(ins, 1), mask);
23916 lmask = arch_reg_regcm(state, lreg);
23917 rmask = arch_reg_regcm(state, rreg);
23918 mask = lmask & rmask;
23919 fprintf(fp, "\t%s %s, %s\n",
23921 reg(state, RHS(ins, 1), mask),
23922 reg(state, RHS(ins, 0), mask));
23925 static void print_unary_op(struct compile_state *state,
23926 const char *op, struct triple *ins, FILE *fp)
23928 unsigned mask;
23929 mask = REGCM_GPR32 | REGCM_GPR16 | REGCM_GPR8_LO;
23930 fprintf(fp, "\t%s %s\n",
23932 reg(state, RHS(ins, 0), mask));
23935 static void print_op_shift(struct compile_state *state,
23936 const char *op, struct triple *ins, FILE *fp)
23938 unsigned mask;
23939 mask = REGCM_GPR32 | REGCM_GPR16 | REGCM_GPR8_LO;
23940 if (ID_REG(RHS(ins, 0)->id) != ID_REG(ins->id)) {
23941 internal_error(state, ins, "invalid register assignment");
23943 if (is_const(RHS(ins, 1))) {
23944 fprintf(fp, "\t%s ", op);
23945 print_const_val(state, RHS(ins, 1), fp);
23946 fprintf(fp, ", %s\n",
23947 reg(state, RHS(ins, 0), mask));
23949 else {
23950 fprintf(fp, "\t%s %s, %s\n",
23952 reg(state, RHS(ins, 1), REGCM_GPR8_LO),
23953 reg(state, RHS(ins, 0), mask));
23957 static void print_op_in(struct compile_state *state, struct triple *ins, FILE *fp)
23959 const char *op;
23960 int mask;
23961 int dreg;
23962 switch(ins->op) {
23963 case OP_INB: op = "inb", mask = REGCM_GPR8_LO; break;
23964 case OP_INW: op = "inw", mask = REGCM_GPR16; break;
23965 case OP_INL: op = "inl", mask = REGCM_GPR32; break;
23966 default:
23967 internal_error(state, ins, "not an in operation");
23968 op = 0;
23969 break;
23971 dreg = check_reg(state, ins, mask);
23972 if (!reg_is_reg(state, dreg, REG_EAX)) {
23973 internal_error(state, ins, "dst != %%eax");
23975 if (is_const(RHS(ins, 0))) {
23976 fprintf(fp, "\t%s ", op);
23977 print_const_val(state, RHS(ins, 0), fp);
23978 fprintf(fp, ", %s\n",
23979 reg(state, ins, mask));
23981 else {
23982 int addr_reg;
23983 addr_reg = check_reg(state, RHS(ins, 0), REGCM_GPR16);
23984 if (!reg_is_reg(state, addr_reg, REG_DX)) {
23985 internal_error(state, ins, "src != %%dx");
23987 fprintf(fp, "\t%s %s, %s\n",
23989 reg(state, RHS(ins, 0), REGCM_GPR16),
23990 reg(state, ins, mask));
23994 static void print_op_out(struct compile_state *state, struct triple *ins, FILE *fp)
23996 const char *op;
23997 int mask;
23998 int lreg;
23999 switch(ins->op) {
24000 case OP_OUTB: op = "outb", mask = REGCM_GPR8_LO; break;
24001 case OP_OUTW: op = "outw", mask = REGCM_GPR16; break;
24002 case OP_OUTL: op = "outl", mask = REGCM_GPR32; break;
24003 default:
24004 internal_error(state, ins, "not an out operation");
24005 op = 0;
24006 break;
24008 lreg = check_reg(state, RHS(ins, 0), mask);
24009 if (!reg_is_reg(state, lreg, REG_EAX)) {
24010 internal_error(state, ins, "src != %%eax");
24012 if (is_const(RHS(ins, 1))) {
24013 fprintf(fp, "\t%s %s,",
24014 op, reg(state, RHS(ins, 0), mask));
24015 print_const_val(state, RHS(ins, 1), fp);
24016 fprintf(fp, "\n");
24018 else {
24019 int addr_reg;
24020 addr_reg = check_reg(state, RHS(ins, 1), REGCM_GPR16);
24021 if (!reg_is_reg(state, addr_reg, REG_DX)) {
24022 internal_error(state, ins, "dst != %%dx");
24024 fprintf(fp, "\t%s %s, %s\n",
24026 reg(state, RHS(ins, 0), mask),
24027 reg(state, RHS(ins, 1), REGCM_GPR16));
24031 static void print_op_move(struct compile_state *state,
24032 struct triple *ins, FILE *fp)
24034 /* op_move is complex because there are many types
24035 * of registers we can move between.
24036 * Because OP_COPY will be introduced in arbitrary locations
24037 * OP_COPY must not affect flags.
24038 * OP_CONVERT can change the flags and it is the only operation
24039 * where it is expected the types in the registers can change.
24041 int omit_copy = 1; /* Is it o.k. to omit a noop copy? */
24042 struct triple *dst, *src;
24043 if (state->arch->features & X86_NOOP_COPY) {
24044 omit_copy = 0;
24046 if ((ins->op == OP_COPY) || (ins->op == OP_CONVERT)) {
24047 src = RHS(ins, 0);
24048 dst = ins;
24050 else {
24051 internal_error(state, ins, "unknown move operation");
24052 src = dst = 0;
24054 if (reg_size(state, dst) < size_of(state, dst->type)) {
24055 internal_error(state, ins, "Invalid destination register");
24057 if (!equiv_types(src->type, dst->type) && (dst->op == OP_COPY)) {
24058 fprintf(state->errout, "src type: ");
24059 name_of(state->errout, src->type);
24060 fprintf(state->errout, "\n");
24061 fprintf(state->errout, "dst type: ");
24062 name_of(state->errout, dst->type);
24063 fprintf(state->errout, "\n");
24064 internal_error(state, ins, "Type mismatch for OP_COPY");
24067 if (!is_const(src)) {
24068 int src_reg, dst_reg;
24069 int src_regcm, dst_regcm;
24070 src_reg = ID_REG(src->id);
24071 dst_reg = ID_REG(dst->id);
24072 src_regcm = arch_reg_regcm(state, src_reg);
24073 dst_regcm = arch_reg_regcm(state, dst_reg);
24074 /* If the class is the same just move the register */
24075 if (src_regcm & dst_regcm &
24076 (REGCM_GPR8_LO | REGCM_GPR16 | REGCM_GPR32)) {
24077 if ((src_reg != dst_reg) || !omit_copy) {
24078 fprintf(fp, "\tmov %s, %s\n",
24079 reg(state, src, src_regcm),
24080 reg(state, dst, dst_regcm));
24083 /* Move 32bit to 16bit */
24084 else if ((src_regcm & REGCM_GPR32) &&
24085 (dst_regcm & REGCM_GPR16)) {
24086 src_reg = (src_reg - REGC_GPR32_FIRST) + REGC_GPR16_FIRST;
24087 if ((src_reg != dst_reg) || !omit_copy) {
24088 fprintf(fp, "\tmovw %s, %s\n",
24089 arch_reg_str(src_reg),
24090 arch_reg_str(dst_reg));
24093 /* Move from 32bit gprs to 16bit gprs */
24094 else if ((src_regcm & REGCM_GPR32) &&
24095 (dst_regcm & REGCM_GPR16)) {
24096 dst_reg = (dst_reg - REGC_GPR16_FIRST) + REGC_GPR32_FIRST;
24097 if ((src_reg != dst_reg) || !omit_copy) {
24098 fprintf(fp, "\tmov %s, %s\n",
24099 arch_reg_str(src_reg),
24100 arch_reg_str(dst_reg));
24103 /* Move 32bit to 8bit */
24104 else if ((src_regcm & REGCM_GPR32_8) &&
24105 (dst_regcm & REGCM_GPR8_LO))
24107 src_reg = (src_reg - REGC_GPR32_8_FIRST) + REGC_GPR8_FIRST;
24108 if ((src_reg != dst_reg) || !omit_copy) {
24109 fprintf(fp, "\tmovb %s, %s\n",
24110 arch_reg_str(src_reg),
24111 arch_reg_str(dst_reg));
24114 /* Move 16bit to 8bit */
24115 else if ((src_regcm & REGCM_GPR16_8) &&
24116 (dst_regcm & REGCM_GPR8_LO))
24118 src_reg = (src_reg - REGC_GPR16_8_FIRST) + REGC_GPR8_FIRST;
24119 if ((src_reg != dst_reg) || !omit_copy) {
24120 fprintf(fp, "\tmovb %s, %s\n",
24121 arch_reg_str(src_reg),
24122 arch_reg_str(dst_reg));
24125 /* Move 8/16bit to 16/32bit */
24126 else if ((src_regcm & (REGCM_GPR8_LO | REGCM_GPR16)) &&
24127 (dst_regcm & (REGCM_GPR16 | REGCM_GPR32))) {
24128 const char *op;
24129 op = is_signed(src->type)? "movsx": "movzx";
24130 fprintf(fp, "\t%s %s, %s\n",
24132 reg(state, src, src_regcm),
24133 reg(state, dst, dst_regcm));
24135 /* Move between sse registers */
24136 else if ((src_regcm & dst_regcm & REGCM_XMM)) {
24137 if ((src_reg != dst_reg) || !omit_copy) {
24138 fprintf(fp, "\tmovdqa %s, %s\n",
24139 reg(state, src, src_regcm),
24140 reg(state, dst, dst_regcm));
24143 /* Move between mmx registers */
24144 else if ((src_regcm & dst_regcm & REGCM_MMX)) {
24145 if ((src_reg != dst_reg) || !omit_copy) {
24146 fprintf(fp, "\tmovq %s, %s\n",
24147 reg(state, src, src_regcm),
24148 reg(state, dst, dst_regcm));
24151 /* Move from sse to mmx registers */
24152 else if ((src_regcm & REGCM_XMM) && (dst_regcm & REGCM_MMX)) {
24153 fprintf(fp, "\tmovdq2q %s, %s\n",
24154 reg(state, src, src_regcm),
24155 reg(state, dst, dst_regcm));
24157 /* Move from mmx to sse registers */
24158 else if ((src_regcm & REGCM_MMX) && (dst_regcm & REGCM_XMM)) {
24159 fprintf(fp, "\tmovq2dq %s, %s\n",
24160 reg(state, src, src_regcm),
24161 reg(state, dst, dst_regcm));
24163 /* Move between 32bit gprs & mmx/sse registers */
24164 else if ((src_regcm & (REGCM_GPR32 | REGCM_MMX | REGCM_XMM)) &&
24165 (dst_regcm & (REGCM_GPR32 | REGCM_MMX | REGCM_XMM))) {
24166 fprintf(fp, "\tmovd %s, %s\n",
24167 reg(state, src, src_regcm),
24168 reg(state, dst, dst_regcm));
24170 /* Move from 16bit gprs & mmx/sse registers */
24171 else if ((src_regcm & REGCM_GPR16) &&
24172 (dst_regcm & (REGCM_MMX | REGCM_XMM))) {
24173 const char *op;
24174 int mid_reg;
24175 op = is_signed(src->type)? "movsx":"movzx";
24176 mid_reg = (src_reg - REGC_GPR16_FIRST) + REGC_GPR32_FIRST;
24177 fprintf(fp, "\t%s %s, %s\n\tmovd %s, %s\n",
24179 arch_reg_str(src_reg),
24180 arch_reg_str(mid_reg),
24181 arch_reg_str(mid_reg),
24182 arch_reg_str(dst_reg));
24184 /* Move from mmx/sse registers to 16bit gprs */
24185 else if ((src_regcm & (REGCM_MMX | REGCM_XMM)) &&
24186 (dst_regcm & REGCM_GPR16)) {
24187 dst_reg = (dst_reg - REGC_GPR16_FIRST) + REGC_GPR32_FIRST;
24188 fprintf(fp, "\tmovd %s, %s\n",
24189 arch_reg_str(src_reg),
24190 arch_reg_str(dst_reg));
24192 /* Move from gpr to 64bit dividend */
24193 else if ((src_regcm & (REGCM_GPR32 | REGCM_GPR16 | REGCM_GPR8_LO)) &&
24194 (dst_regcm & REGCM_DIVIDEND64)) {
24195 const char *extend;
24196 extend = is_signed(src->type)? "cltd":"movl $0, %edx";
24197 fprintf(fp, "\tmov %s, %%eax\n\t%s\n",
24198 arch_reg_str(src_reg),
24199 extend);
24201 /* Move from 64bit gpr to gpr */
24202 else if ((src_regcm & REGCM_DIVIDEND64) &&
24203 (dst_regcm & (REGCM_GPR32 | REGCM_GPR16 | REGCM_GPR8_LO))) {
24204 if (dst_regcm & REGCM_GPR32) {
24205 src_reg = REG_EAX;
24207 else if (dst_regcm & REGCM_GPR16) {
24208 src_reg = REG_AX;
24210 else if (dst_regcm & REGCM_GPR8_LO) {
24211 src_reg = REG_AL;
24213 fprintf(fp, "\tmov %s, %s\n",
24214 arch_reg_str(src_reg),
24215 arch_reg_str(dst_reg));
24217 /* Move from mmx/sse registers to 64bit gpr */
24218 else if ((src_regcm & (REGCM_MMX | REGCM_XMM)) &&
24219 (dst_regcm & REGCM_DIVIDEND64)) {
24220 const char *extend;
24221 extend = is_signed(src->type)? "cltd": "movl $0, %edx";
24222 fprintf(fp, "\tmovd %s, %%eax\n\t%s\n",
24223 arch_reg_str(src_reg),
24224 extend);
24226 /* Move from 64bit gpr to mmx/sse register */
24227 else if ((src_regcm & REGCM_DIVIDEND64) &&
24228 (dst_regcm & (REGCM_XMM | REGCM_MMX))) {
24229 fprintf(fp, "\tmovd %%eax, %s\n",
24230 arch_reg_str(dst_reg));
24232 #if X86_4_8BIT_GPRS
24233 /* Move from 8bit gprs to mmx/sse registers */
24234 else if ((src_regcm & REGCM_GPR8_LO) && (src_reg <= REG_DL) &&
24235 (dst_regcm & (REGCM_MMX | REGCM_XMM))) {
24236 const char *op;
24237 int mid_reg;
24238 op = is_signed(src->type)? "movsx":"movzx";
24239 mid_reg = (src_reg - REGC_GPR8_FIRST) + REGC_GPR32_FIRST;
24240 fprintf(fp, "\t%s %s, %s\n\tmovd %s, %s\n",
24242 reg(state, src, src_regcm),
24243 arch_reg_str(mid_reg),
24244 arch_reg_str(mid_reg),
24245 reg(state, dst, dst_regcm));
24247 /* Move from mmx/sse registers and 8bit gprs */
24248 else if ((src_regcm & (REGCM_MMX | REGCM_XMM)) &&
24249 (dst_regcm & REGCM_GPR8_LO) && (dst_reg <= REG_DL)) {
24250 int mid_reg;
24251 mid_reg = (dst_reg - REGC_GPR8_FIRST) + REGC_GPR32_FIRST;
24252 fprintf(fp, "\tmovd %s, %s\n",
24253 reg(state, src, src_regcm),
24254 arch_reg_str(mid_reg));
24256 /* Move from 32bit gprs to 8bit gprs */
24257 else if ((src_regcm & REGCM_GPR32) &&
24258 (dst_regcm & REGCM_GPR8_LO)) {
24259 dst_reg = (dst_reg - REGC_GPR8_FIRST) + REGC_GPR32_FIRST;
24260 if ((src_reg != dst_reg) || !omit_copy) {
24261 fprintf(fp, "\tmov %s, %s\n",
24262 arch_reg_str(src_reg),
24263 arch_reg_str(dst_reg));
24266 /* Move from 16bit gprs to 8bit gprs */
24267 else if ((src_regcm & REGCM_GPR16) &&
24268 (dst_regcm & REGCM_GPR8_LO)) {
24269 dst_reg = (dst_reg - REGC_GPR8_FIRST) + REGC_GPR16_FIRST;
24270 if ((src_reg != dst_reg) || !omit_copy) {
24271 fprintf(fp, "\tmov %s, %s\n",
24272 arch_reg_str(src_reg),
24273 arch_reg_str(dst_reg));
24276 #endif /* X86_4_8BIT_GPRS */
24277 /* Move from %eax:%edx to %eax:%edx */
24278 else if ((src_regcm & REGCM_DIVIDEND64) &&
24279 (dst_regcm & REGCM_DIVIDEND64) &&
24280 (src_reg == dst_reg)) {
24281 if (!omit_copy) {
24282 fprintf(fp, "\t/*mov %s, %s*/\n",
24283 arch_reg_str(src_reg),
24284 arch_reg_str(dst_reg));
24287 else {
24288 if ((src_regcm & ~REGCM_FLAGS) == 0) {
24289 internal_error(state, ins, "attempt to copy from %%eflags!");
24291 internal_error(state, ins, "unknown copy type");
24294 else {
24295 size_t dst_size;
24296 int dst_reg;
24297 int dst_regcm;
24298 dst_size = size_of(state, dst->type);
24299 dst_reg = ID_REG(dst->id);
24300 dst_regcm = arch_reg_regcm(state, dst_reg);
24301 if (dst_regcm & (REGCM_GPR32 | REGCM_GPR16 | REGCM_GPR8_LO)) {
24302 fprintf(fp, "\tmov ");
24303 print_const_val(state, src, fp);
24304 fprintf(fp, ", %s\n",
24305 reg(state, dst, REGCM_GPR32 | REGCM_GPR16 | REGCM_GPR8_LO));
24307 else if (dst_regcm & REGCM_DIVIDEND64) {
24308 if (dst_size > SIZEOF_I32) {
24309 internal_error(state, ins, "%dbit constant...", dst_size);
24311 fprintf(fp, "\tmov $0, %%edx\n");
24312 fprintf(fp, "\tmov ");
24313 print_const_val(state, src, fp);
24314 fprintf(fp, ", %%eax\n");
24316 else if (dst_regcm & REGCM_DIVIDEND32) {
24317 if (dst_size > SIZEOF_I16) {
24318 internal_error(state, ins, "%dbit constant...", dst_size);
24320 fprintf(fp, "\tmov $0, %%dx\n");
24321 fprintf(fp, "\tmov ");
24322 print_const_val(state, src, fp);
24323 fprintf(fp, ", %%ax");
24325 else if (dst_regcm & (REGCM_XMM | REGCM_MMX)) {
24326 long ref;
24327 if (dst_size > SIZEOF_I32) {
24328 internal_error(state, ins, "%d bit constant...", dst_size);
24330 ref = get_const_pool_ref(state, src, SIZEOF_I32, fp);
24331 fprintf(fp, "\tmovd L%s%lu, %s\n",
24332 state->compiler->label_prefix, ref,
24333 reg(state, dst, (REGCM_XMM | REGCM_MMX)));
24335 else {
24336 internal_error(state, ins, "unknown copy immediate type");
24339 /* Leave now if this is not a type conversion */
24340 if (ins->op != OP_CONVERT) {
24341 return;
24343 /* Now make certain I have not logically overflowed the destination */
24344 if ((size_of(state, src->type) > size_of(state, dst->type)) &&
24345 (size_of(state, dst->type) < reg_size(state, dst)))
24347 unsigned long mask;
24348 int dst_reg;
24349 int dst_regcm;
24350 if (size_of(state, dst->type) >= 32) {
24351 fprintf(state->errout, "dst type: ");
24352 name_of(state->errout, dst->type);
24353 fprintf(state->errout, "\n");
24354 internal_error(state, dst, "unhandled dst type size");
24356 mask = 1;
24357 mask <<= size_of(state, dst->type);
24358 mask -= 1;
24360 dst_reg = ID_REG(dst->id);
24361 dst_regcm = arch_reg_regcm(state, dst_reg);
24363 if (dst_regcm & (REGCM_GPR32 | REGCM_GPR16 | REGCM_GPR8_LO)) {
24364 fprintf(fp, "\tand $0x%lx, %s\n",
24365 mask, reg(state, dst, REGCM_GPR32 | REGCM_GPR16 | REGCM_GPR8_LO));
24367 else if (dst_regcm & REGCM_MMX) {
24368 long ref;
24369 ref = get_mask_pool_ref(state, dst, mask, fp);
24370 fprintf(fp, "\tpand L%s%lu, %s\n",
24371 state->compiler->label_prefix, ref,
24372 reg(state, dst, REGCM_MMX));
24374 else if (dst_regcm & REGCM_XMM) {
24375 long ref;
24376 ref = get_mask_pool_ref(state, dst, mask, fp);
24377 fprintf(fp, "\tpand L%s%lu, %s\n",
24378 state->compiler->label_prefix, ref,
24379 reg(state, dst, REGCM_XMM));
24381 else {
24382 fprintf(state->errout, "dst type: ");
24383 name_of(state->errout, dst->type);
24384 fprintf(state->errout, "\n");
24385 fprintf(state->errout, "dst: %s\n", reg(state, dst, REGCM_ALL));
24386 internal_error(state, dst, "failed to trunc value: mask %lx", mask);
24389 /* Make certain I am properly sign extended */
24390 if ((size_of(state, src->type) < size_of(state, dst->type)) &&
24391 (is_signed(src->type)))
24393 int reg_bits, shift_bits;
24394 int dst_reg;
24395 int dst_regcm;
24397 reg_bits = reg_size(state, dst);
24398 if (reg_bits > 32) {
24399 reg_bits = 32;
24401 shift_bits = reg_bits - size_of(state, src->type);
24402 dst_reg = ID_REG(dst->id);
24403 dst_regcm = arch_reg_regcm(state, dst_reg);
24405 if (shift_bits < 0) {
24406 internal_error(state, dst, "negative shift?");
24409 if (dst_regcm & (REGCM_GPR32 | REGCM_GPR16 | REGCM_GPR8_LO)) {
24410 fprintf(fp, "\tshl $%d, %s\n",
24411 shift_bits,
24412 reg(state, dst, REGCM_GPR32 | REGCM_GPR16 | REGCM_GPR8_LO));
24413 fprintf(fp, "\tsar $%d, %s\n",
24414 shift_bits,
24415 reg(state, dst, REGCM_GPR32 | REGCM_GPR16 | REGCM_GPR8_LO));
24417 else if (dst_regcm & (REGCM_MMX | REGCM_XMM)) {
24418 fprintf(fp, "\tpslld $%d, %s\n",
24419 shift_bits,
24420 reg(state, dst, REGCM_MMX | REGCM_XMM));
24421 fprintf(fp, "\tpsrad $%d, %s\n",
24422 shift_bits,
24423 reg(state, dst, REGCM_MMX | REGCM_XMM));
24425 else {
24426 fprintf(state->errout, "dst type: ");
24427 name_of(state->errout, dst->type);
24428 fprintf(state->errout, "\n");
24429 fprintf(state->errout, "dst: %s\n", reg(state, dst, REGCM_ALL));
24430 internal_error(state, dst, "failed to signed extend value");
24435 static void print_op_load(struct compile_state *state,
24436 struct triple *ins, FILE *fp)
24438 struct triple *dst, *src;
24439 const char *op;
24440 dst = ins;
24441 src = RHS(ins, 0);
24442 if (is_const(src) || is_const(dst)) {
24443 internal_error(state, ins, "unknown load operation");
24445 switch(ins->type->type & TYPE_MASK) {
24446 case TYPE_CHAR: op = "movsbl"; break;
24447 case TYPE_UCHAR: op = "movzbl"; break;
24448 case TYPE_SHORT: op = "movswl"; break;
24449 case TYPE_USHORT: op = "movzwl"; break;
24450 case TYPE_INT: case TYPE_UINT:
24451 case TYPE_LONG: case TYPE_ULONG:
24452 case TYPE_POINTER:
24453 op = "movl";
24454 break;
24455 default:
24456 internal_error(state, ins, "unknown type in load");
24457 op = "<invalid opcode>";
24458 break;
24460 fprintf(fp, "\t%s (%s), %s\n",
24462 reg(state, src, REGCM_GPR32),
24463 reg(state, dst, REGCM_GPR32));
24467 static void print_op_store(struct compile_state *state,
24468 struct triple *ins, FILE *fp)
24470 struct triple *dst, *src;
24471 dst = RHS(ins, 0);
24472 src = RHS(ins, 1);
24473 if (is_const(src) && (src->op == OP_INTCONST)) {
24474 long_t value;
24475 value = (long_t)(src->u.cval);
24476 fprintf(fp, "\tmov%s $%ld, (%s)\n",
24477 type_suffix(state, src->type),
24478 (long)(value),
24479 reg(state, dst, REGCM_GPR32));
24481 else if (is_const(dst) && (dst->op == OP_INTCONST)) {
24482 fprintf(fp, "\tmov%s %s, 0x%08lx\n",
24483 type_suffix(state, src->type),
24484 reg(state, src, REGCM_GPR8_LO | REGCM_GPR16 | REGCM_GPR32),
24485 (unsigned long)(dst->u.cval));
24487 else {
24488 if (is_const(src) || is_const(dst)) {
24489 internal_error(state, ins, "unknown store operation");
24491 fprintf(fp, "\tmov%s %s, (%s)\n",
24492 type_suffix(state, src->type),
24493 reg(state, src, REGCM_GPR8_LO | REGCM_GPR16 | REGCM_GPR32),
24494 reg(state, dst, REGCM_GPR32));
24500 static void print_op_smul(struct compile_state *state,
24501 struct triple *ins, FILE *fp)
24503 if (!is_const(RHS(ins, 1))) {
24504 fprintf(fp, "\timul %s, %s\n",
24505 reg(state, RHS(ins, 1), REGCM_GPR32),
24506 reg(state, RHS(ins, 0), REGCM_GPR32));
24508 else {
24509 fprintf(fp, "\timul ");
24510 print_const_val(state, RHS(ins, 1), fp);
24511 fprintf(fp, ", %s\n", reg(state, RHS(ins, 0), REGCM_GPR32));
24515 static void print_op_cmp(struct compile_state *state,
24516 struct triple *ins, FILE *fp)
24518 unsigned mask;
24519 int dreg;
24520 mask = REGCM_GPR32 | REGCM_GPR16 | REGCM_GPR8_LO;
24521 dreg = check_reg(state, ins, REGCM_FLAGS);
24522 if (!reg_is_reg(state, dreg, REG_EFLAGS)) {
24523 internal_error(state, ins, "bad dest register for cmp");
24525 if (is_const(RHS(ins, 1))) {
24526 fprintf(fp, "\tcmp ");
24527 print_const_val(state, RHS(ins, 1), fp);
24528 fprintf(fp, ", %s\n", reg(state, RHS(ins, 0), mask));
24530 else {
24531 unsigned lmask, rmask;
24532 int lreg, rreg;
24533 lreg = check_reg(state, RHS(ins, 0), mask);
24534 rreg = check_reg(state, RHS(ins, 1), mask);
24535 lmask = arch_reg_regcm(state, lreg);
24536 rmask = arch_reg_regcm(state, rreg);
24537 mask = lmask & rmask;
24538 fprintf(fp, "\tcmp %s, %s\n",
24539 reg(state, RHS(ins, 1), mask),
24540 reg(state, RHS(ins, 0), mask));
24544 static void print_op_test(struct compile_state *state,
24545 struct triple *ins, FILE *fp)
24547 unsigned mask;
24548 mask = REGCM_GPR32 | REGCM_GPR16 | REGCM_GPR8_LO;
24549 fprintf(fp, "\ttest %s, %s\n",
24550 reg(state, RHS(ins, 0), mask),
24551 reg(state, RHS(ins, 0), mask));
24554 static void print_op_branch(struct compile_state *state,
24555 struct triple *branch, FILE *fp)
24557 const char *bop = "j";
24558 if ((branch->op == OP_JMP) || (branch->op == OP_CALL)) {
24559 if (branch->rhs != 0) {
24560 internal_error(state, branch, "jmp with condition?");
24562 bop = "jmp";
24564 else {
24565 struct triple *ptr;
24566 if (branch->rhs != 1) {
24567 internal_error(state, branch, "jmpcc without condition?");
24569 check_reg(state, RHS(branch, 0), REGCM_FLAGS);
24570 if ((RHS(branch, 0)->op != OP_CMP) &&
24571 (RHS(branch, 0)->op != OP_TEST)) {
24572 internal_error(state, branch, "bad branch test");
24574 #if DEBUG_ROMCC_WARNINGS
24575 #warning "FIXME I have observed instructions between the test and branch instructions"
24576 #endif
24577 for(ptr = RHS(branch, 0)->next; ptr != branch; ptr = ptr->next) {
24578 if (ptr->op != OP_COPY) {
24579 internal_error(state, branch, "branch does not follow test");
24582 switch(branch->op) {
24583 case OP_JMP_EQ: bop = "jz"; break;
24584 case OP_JMP_NOTEQ: bop = "jnz"; break;
24585 case OP_JMP_SLESS: bop = "jl"; break;
24586 case OP_JMP_ULESS: bop = "jb"; break;
24587 case OP_JMP_SMORE: bop = "jg"; break;
24588 case OP_JMP_UMORE: bop = "ja"; break;
24589 case OP_JMP_SLESSEQ: bop = "jle"; break;
24590 case OP_JMP_ULESSEQ: bop = "jbe"; break;
24591 case OP_JMP_SMOREEQ: bop = "jge"; break;
24592 case OP_JMP_UMOREEQ: bop = "jae"; break;
24593 default:
24594 internal_error(state, branch, "Invalid branch op");
24595 break;
24599 #if 1
24600 if (branch->op == OP_CALL) {
24601 fprintf(fp, "\t/* call */\n");
24603 #endif
24604 fprintf(fp, "\t%s L%s%lu\n",
24605 bop,
24606 state->compiler->label_prefix,
24607 (unsigned long)(TARG(branch, 0)->u.cval));
24610 static void print_op_ret(struct compile_state *state,
24611 struct triple *branch, FILE *fp)
24613 fprintf(fp, "\tjmp *%s\n",
24614 reg(state, RHS(branch, 0), REGCM_GPR32));
24617 static void print_op_set(struct compile_state *state,
24618 struct triple *set, FILE *fp)
24620 const char *sop = "set";
24621 if (set->rhs != 1) {
24622 internal_error(state, set, "setcc without condition?");
24624 check_reg(state, RHS(set, 0), REGCM_FLAGS);
24625 if ((RHS(set, 0)->op != OP_CMP) &&
24626 (RHS(set, 0)->op != OP_TEST)) {
24627 internal_error(state, set, "bad set test");
24629 if (RHS(set, 0)->next != set) {
24630 internal_error(state, set, "set does not follow test");
24632 switch(set->op) {
24633 case OP_SET_EQ: sop = "setz"; break;
24634 case OP_SET_NOTEQ: sop = "setnz"; break;
24635 case OP_SET_SLESS: sop = "setl"; break;
24636 case OP_SET_ULESS: sop = "setb"; break;
24637 case OP_SET_SMORE: sop = "setg"; break;
24638 case OP_SET_UMORE: sop = "seta"; break;
24639 case OP_SET_SLESSEQ: sop = "setle"; break;
24640 case OP_SET_ULESSEQ: sop = "setbe"; break;
24641 case OP_SET_SMOREEQ: sop = "setge"; break;
24642 case OP_SET_UMOREEQ: sop = "setae"; break;
24643 default:
24644 internal_error(state, set, "Invalid set op");
24645 break;
24647 fprintf(fp, "\t%s %s\n",
24648 sop, reg(state, set, REGCM_GPR8_LO));
24651 static void print_op_bit_scan(struct compile_state *state,
24652 struct triple *ins, FILE *fp)
24654 const char *op;
24655 switch(ins->op) {
24656 case OP_BSF: op = "bsf"; break;
24657 case OP_BSR: op = "bsr"; break;
24658 default:
24659 internal_error(state, ins, "unknown bit scan");
24660 op = 0;
24661 break;
24663 fprintf(fp,
24664 "\t%s %s, %s\n"
24665 "\tjnz 1f\n"
24666 "\tmovl $-1, %s\n"
24667 "1:\n",
24669 reg(state, RHS(ins, 0), REGCM_GPR32),
24670 reg(state, ins, REGCM_GPR32),
24671 reg(state, ins, REGCM_GPR32));
24675 static void print_sdecl(struct compile_state *state,
24676 struct triple *ins, FILE *fp)
24678 fprintf(fp, ".section \"" DATA_SECTION "\"\n");
24679 fprintf(fp, ".balign %ld\n", (long int)align_of_in_bytes(state, ins->type));
24680 fprintf(fp, "L%s%lu:\n",
24681 state->compiler->label_prefix, (unsigned long)(ins->u.cval));
24682 print_const(state, MISC(ins, 0), fp);
24683 fprintf(fp, ".section \"" TEXT_SECTION "\"\n");
24687 static void print_instruction(struct compile_state *state,
24688 struct triple *ins, FILE *fp)
24690 /* Assumption: after I have exted the register allocator
24691 * everything is in a valid register.
24693 switch(ins->op) {
24694 case OP_ASM:
24695 print_op_asm(state, ins, fp);
24696 break;
24697 case OP_ADD: print_binary_op(state, "add", ins, fp); break;
24698 case OP_SUB: print_binary_op(state, "sub", ins, fp); break;
24699 case OP_AND: print_binary_op(state, "and", ins, fp); break;
24700 case OP_XOR: print_binary_op(state, "xor", ins, fp); break;
24701 case OP_OR: print_binary_op(state, "or", ins, fp); break;
24702 case OP_SL: print_op_shift(state, "shl", ins, fp); break;
24703 case OP_USR: print_op_shift(state, "shr", ins, fp); break;
24704 case OP_SSR: print_op_shift(state, "sar", ins, fp); break;
24705 case OP_POS: break;
24706 case OP_NEG: print_unary_op(state, "neg", ins, fp); break;
24707 case OP_INVERT: print_unary_op(state, "not", ins, fp); break;
24708 case OP_NOOP:
24709 case OP_INTCONST:
24710 case OP_ADDRCONST:
24711 case OP_BLOBCONST:
24712 /* Don't generate anything here for constants */
24713 case OP_PHI:
24714 /* Don't generate anything for variable declarations. */
24715 break;
24716 case OP_UNKNOWNVAL:
24717 fprintf(fp, " /* unknown %s */\n",
24718 reg(state, ins, REGCM_ALL));
24719 break;
24720 case OP_SDECL:
24721 print_sdecl(state, ins, fp);
24722 break;
24723 case OP_COPY:
24724 case OP_CONVERT:
24725 print_op_move(state, ins, fp);
24726 break;
24727 case OP_LOAD:
24728 print_op_load(state, ins, fp);
24729 break;
24730 case OP_STORE:
24731 print_op_store(state, ins, fp);
24732 break;
24733 case OP_SMUL:
24734 print_op_smul(state, ins, fp);
24735 break;
24736 case OP_CMP: print_op_cmp(state, ins, fp); break;
24737 case OP_TEST: print_op_test(state, ins, fp); break;
24738 case OP_JMP:
24739 case OP_JMP_EQ: case OP_JMP_NOTEQ:
24740 case OP_JMP_SLESS: case OP_JMP_ULESS:
24741 case OP_JMP_SMORE: case OP_JMP_UMORE:
24742 case OP_JMP_SLESSEQ: case OP_JMP_ULESSEQ:
24743 case OP_JMP_SMOREEQ: case OP_JMP_UMOREEQ:
24744 case OP_CALL:
24745 print_op_branch(state, ins, fp);
24746 break;
24747 case OP_RET:
24748 print_op_ret(state, ins, fp);
24749 break;
24750 case OP_SET_EQ: case OP_SET_NOTEQ:
24751 case OP_SET_SLESS: case OP_SET_ULESS:
24752 case OP_SET_SMORE: case OP_SET_UMORE:
24753 case OP_SET_SLESSEQ: case OP_SET_ULESSEQ:
24754 case OP_SET_SMOREEQ: case OP_SET_UMOREEQ:
24755 print_op_set(state, ins, fp);
24756 break;
24757 case OP_INB: case OP_INW: case OP_INL:
24758 print_op_in(state, ins, fp);
24759 break;
24760 case OP_OUTB: case OP_OUTW: case OP_OUTL:
24761 print_op_out(state, ins, fp);
24762 break;
24763 case OP_BSF:
24764 case OP_BSR:
24765 print_op_bit_scan(state, ins, fp);
24766 break;
24767 case OP_RDMSR:
24768 after_lhs(state, ins);
24769 fprintf(fp, "\trdmsr\n");
24770 break;
24771 case OP_WRMSR:
24772 fprintf(fp, "\twrmsr\n");
24773 break;
24774 case OP_HLT:
24775 fprintf(fp, "\thlt\n");
24776 break;
24777 case OP_SDIVT:
24778 fprintf(fp, "\tidiv %s\n", reg(state, RHS(ins, 1), REGCM_GPR32));
24779 break;
24780 case OP_UDIVT:
24781 fprintf(fp, "\tdiv %s\n", reg(state, RHS(ins, 1), REGCM_GPR32));
24782 break;
24783 case OP_UMUL:
24784 fprintf(fp, "\tmul %s\n", reg(state, RHS(ins, 1), REGCM_GPR32));
24785 break;
24786 case OP_LABEL:
24787 if (!ins->use) {
24788 return;
24790 fprintf(fp, "L%s%lu:\n",
24791 state->compiler->label_prefix, (unsigned long)(ins->u.cval));
24792 break;
24793 case OP_ADECL:
24794 /* Ignore adecls with no registers error otherwise */
24795 if (!noop_adecl(ins)) {
24796 internal_error(state, ins, "adecl remains?");
24798 break;
24799 /* Ignore OP_PIECE */
24800 case OP_PIECE:
24801 break;
24802 /* Operations that should never get here */
24803 case OP_SDIV: case OP_UDIV:
24804 case OP_SMOD: case OP_UMOD:
24805 case OP_LTRUE: case OP_LFALSE: case OP_EQ: case OP_NOTEQ:
24806 case OP_SLESS: case OP_ULESS: case OP_SMORE: case OP_UMORE:
24807 case OP_SLESSEQ: case OP_ULESSEQ: case OP_SMOREEQ: case OP_UMOREEQ:
24808 default:
24809 internal_error(state, ins, "unknown op: %d %s",
24810 ins->op, tops(ins->op));
24811 break;
24815 static void print_instructions(struct compile_state *state)
24817 struct triple *first, *ins;
24818 int print_location;
24819 struct occurrence *last_occurrence;
24820 FILE *fp;
24821 int max_inline_depth;
24822 max_inline_depth = 0;
24823 print_location = 1;
24824 last_occurrence = 0;
24825 fp = state->output;
24826 /* Masks for common sizes */
24827 fprintf(fp, ".section \"" DATA_SECTION "\"\n");
24828 fprintf(fp, ".balign 16\n");
24829 fprintf(fp, "L%s1:\n", state->compiler->label_prefix);
24830 fprintf(fp, ".int 0xff, 0, 0, 0\n");
24831 fprintf(fp, "L%s2:\n", state->compiler->label_prefix);
24832 fprintf(fp, ".int 0xffff, 0, 0, 0\n");
24833 fprintf(fp, ".section \"" TEXT_SECTION "\"\n");
24834 first = state->first;
24835 ins = first;
24836 do {
24837 if (print_location &&
24838 last_occurrence != ins->occurrence) {
24839 if (!ins->occurrence->parent) {
24840 fprintf(fp, "\t/* %s,%s:%d.%d */\n",
24841 ins->occurrence->function?ins->occurrence->function:"(null)",
24842 ins->occurrence->filename?ins->occurrence->filename:"(null)",
24843 ins->occurrence->line,
24844 ins->occurrence->col);
24846 else {
24847 struct occurrence *ptr;
24848 int inline_depth;
24849 fprintf(fp, "\t/*\n");
24850 inline_depth = 0;
24851 for(ptr = ins->occurrence; ptr; ptr = ptr->parent) {
24852 inline_depth++;
24853 fprintf(fp, "\t * %s,%s:%d.%d\n",
24854 ptr->function,
24855 ptr->filename,
24856 ptr->line,
24857 ptr->col);
24859 fprintf(fp, "\t */\n");
24860 if (inline_depth > max_inline_depth) {
24861 max_inline_depth = inline_depth;
24864 if (last_occurrence) {
24865 put_occurrence(last_occurrence);
24867 get_occurrence(ins->occurrence);
24868 last_occurrence = ins->occurrence;
24871 print_instruction(state, ins, fp);
24872 ins = ins->next;
24873 } while(ins != first);
24874 if (print_location) {
24875 fprintf(fp, "/* max inline depth %d */\n",
24876 max_inline_depth);
24880 static void generate_code(struct compile_state *state)
24882 generate_local_labels(state);
24883 print_instructions(state);
24887 static void print_preprocessed_tokens(struct compile_state *state)
24889 int tok;
24890 FILE *fp;
24891 int line;
24892 const char *filename;
24893 fp = state->output;
24894 filename = 0;
24895 line = 0;
24896 for(;;) {
24897 struct file_state *file;
24898 struct token *tk;
24899 const char *token_str;
24900 tok = peek(state);
24901 if (tok == TOK_EOF) {
24902 break;
24904 tk = eat(state, tok);
24905 token_str =
24906 tk->ident ? tk->ident->name :
24907 tk->str_len ? tk->val.str :
24908 tokens[tk->tok];
24910 file = state->file;
24911 while(file->macro && file->prev) {
24912 file = file->prev;
24914 if (!file->macro &&
24915 ((file->line != line) || (file->basename != filename)))
24917 int i, col;
24918 if ((file->basename == filename) &&
24919 (line < file->line)) {
24920 while(line < file->line) {
24921 fprintf(fp, "\n");
24922 line++;
24925 else {
24926 fprintf(fp, "\n#line %d \"%s\"\n",
24927 file->line, file->basename);
24929 line = file->line;
24930 filename = file->basename;
24931 col = get_col(file) - strlen(token_str);
24932 for(i = 0; i < col; i++) {
24933 fprintf(fp, " ");
24937 fprintf(fp, "%s ", token_str);
24939 if (state->compiler->debug & DEBUG_TOKENS) {
24940 loc(state->dbgout, state, 0);
24941 fprintf(state->dbgout, "%s <- `%s'\n",
24942 tokens[tok], token_str);
24947 static void compile(const char *filename,
24948 struct compiler_state *compiler, struct arch_state *arch)
24950 int i;
24951 struct compile_state state;
24952 struct triple *ptr;
24953 struct filelist *includes = include_filelist;
24954 memset(&state, 0, sizeof(state));
24955 state.compiler = compiler;
24956 state.arch = arch;
24957 state.file = 0;
24958 for(i = 0; i < sizeof(state.token)/sizeof(state.token[0]); i++) {
24959 memset(&state.token[i], 0, sizeof(state.token[i]));
24960 state.token[i].tok = -1;
24962 /* Remember the output descriptors */
24963 state.errout = stderr;
24964 state.dbgout = stdout;
24965 /* Remember the output filename */
24966 if ((state.compiler->flags & COMPILER_PP_ONLY) && (strcmp("auto.inc",state.compiler->ofilename) == 0)) {
24967 state.output = stdout;
24968 } else {
24969 state.output = fopen(state.compiler->ofilename, "w");
24970 if (!state.output) {
24971 error(&state, 0, "Cannot open output file %s\n",
24972 state.compiler->ofilename);
24975 /* Make certain a good cleanup happens */
24976 exit_state = &state;
24977 atexit(exit_cleanup);
24979 /* Prep the preprocessor */
24980 state.if_depth = 0;
24981 memset(state.if_bytes, 0, sizeof(state.if_bytes));
24982 /* register the C keywords */
24983 register_keywords(&state);
24984 /* register the keywords the macro preprocessor knows */
24985 register_macro_keywords(&state);
24986 /* generate some builtin macros */
24987 register_builtin_macros(&state);
24988 /* Memorize where some special keywords are. */
24989 state.i_switch = lookup(&state, "switch", 6);
24990 state.i_case = lookup(&state, "case", 4);
24991 state.i_continue = lookup(&state, "continue", 8);
24992 state.i_break = lookup(&state, "break", 5);
24993 state.i_default = lookup(&state, "default", 7);
24994 state.i_return = lookup(&state, "return", 6);
24995 /* Memorize where predefined macros are. */
24996 state.i___VA_ARGS__ = lookup(&state, "__VA_ARGS__", 11);
24997 state.i___FILE__ = lookup(&state, "__FILE__", 8);
24998 state.i___LINE__ = lookup(&state, "__LINE__", 8);
24999 /* Memorize where predefined identifiers are. */
25000 state.i___func__ = lookup(&state, "__func__", 8);
25001 /* Memorize where some attribute keywords are. */
25002 state.i_noinline = lookup(&state, "noinline", 8);
25003 state.i_always_inline = lookup(&state, "always_inline", 13);
25004 state.i_noreturn = lookup(&state, "noreturn", 8);
25005 state.i_unused = lookup(&state, "unused", 6);
25006 state.i_packed = lookup(&state, "packed", 6);
25008 /* Process the command line macros */
25009 process_cmdline_macros(&state);
25011 /* Allocate beginning bounding labels for the function list */
25012 state.first = label(&state);
25013 state.first->id |= TRIPLE_FLAG_VOLATILE;
25014 use_triple(state.first, state.first);
25015 ptr = label(&state);
25016 ptr->id |= TRIPLE_FLAG_VOLATILE;
25017 use_triple(ptr, ptr);
25018 flatten(&state, state.first, ptr);
25020 /* Allocate a label for the pool of global variables */
25021 state.global_pool = label(&state);
25022 state.global_pool->id |= TRIPLE_FLAG_VOLATILE;
25023 flatten(&state, state.first, state.global_pool);
25025 /* Enter the globl definition scope */
25026 start_scope(&state);
25027 register_builtins(&state);
25029 compile_file(&state, filename, 1);
25031 while (includes) {
25032 compile_file(&state, includes->filename, 1);
25033 includes=includes->next;
25036 /* Stop if all we want is preprocessor output */
25037 if (state.compiler->flags & COMPILER_PP_ONLY) {
25038 print_preprocessed_tokens(&state);
25039 return;
25042 decls(&state);
25044 /* Exit the global definition scope */
25045 end_scope(&state);
25047 /* Now that basic compilation has happened
25048 * optimize the intermediate code
25050 optimize(&state);
25052 generate_code(&state);
25053 if (state.compiler->debug) {
25054 fprintf(state.errout, "done\n");
25056 exit_state = 0;
25059 static void version(FILE *fp)
25061 fprintf(fp, "romcc " VERSION " released " RELEASE_DATE "\n");
25064 static void usage(void)
25066 FILE *fp = stdout;
25067 version(fp);
25068 fprintf(fp,
25069 "\nUsage: romcc [options] <source>.c\n"
25070 "Compile a C source file generating a binary that does not implicilty use RAM\n"
25071 "Options:\n"
25072 "-o <output file name>\n"
25073 "-f<option> Specify a generic compiler option\n"
25074 "-m<option> Specify a arch dependent option\n"
25075 "-- Specify this is the last option\n"
25076 "\nGeneric compiler options:\n"
25078 compiler_usage(fp);
25079 fprintf(fp,
25080 "\nArchitecture compiler options:\n"
25082 arch_usage(fp);
25083 fprintf(fp,
25084 "\n"
25088 static void arg_error(char *fmt, ...)
25090 va_list args;
25091 va_start(args, fmt);
25092 vfprintf(stderr, fmt, args);
25093 va_end(args);
25094 usage();
25095 exit(1);
25098 static void arg_warning(char *fmt, ...)
25100 va_list args;
25102 va_start(args, fmt);
25103 vfprintf(stderr, fmt, args);
25104 va_end(args);
25107 int main(int argc, char **argv)
25109 const char *filename;
25110 struct compiler_state compiler;
25111 struct arch_state arch;
25112 int all_opts;
25115 /* I don't want any surprises */
25116 setlocale(LC_ALL, "C");
25118 init_compiler_state(&compiler);
25119 init_arch_state(&arch);
25120 filename = 0;
25121 all_opts = 0;
25122 while(argc > 1) {
25123 if (!all_opts && (strcmp(argv[1], "-o") == 0) && (argc > 2)) {
25124 compiler.ofilename = argv[2];
25125 argv += 2;
25126 argc -= 2;
25128 else if (!all_opts && argv[1][0] == '-') {
25129 int result;
25130 result = -1;
25131 if (strcmp(argv[1], "--") == 0) {
25132 result = 0;
25133 all_opts = 1;
25135 else if (strncmp(argv[1], "-E", 2) == 0) {
25136 result = compiler_encode_flag(&compiler, argv[1]);
25138 else if (strncmp(argv[1], "-O", 2) == 0) {
25139 result = compiler_encode_flag(&compiler, argv[1]);
25141 else if (strncmp(argv[1], "-I", 2) == 0) {
25142 result = compiler_encode_flag(&compiler, argv[1]);
25144 else if (strncmp(argv[1], "-D", 2) == 0) {
25145 result = compiler_encode_flag(&compiler, argv[1]);
25147 else if (strncmp(argv[1], "-U", 2) == 0) {
25148 result = compiler_encode_flag(&compiler, argv[1]);
25150 else if (strncmp(argv[1], "--label-prefix=", 15) == 0) {
25151 result = compiler_encode_flag(&compiler, argv[1]+2);
25153 else if (strncmp(argv[1], "-f", 2) == 0) {
25154 result = compiler_encode_flag(&compiler, argv[1]+2);
25156 else if (strncmp(argv[1], "-m", 2) == 0) {
25157 result = arch_encode_flag(&arch, argv[1]+2);
25159 else if (strncmp(argv[1], "-c", 2) == 0) {
25160 result = 0;
25162 else if (strncmp(argv[1], "-S", 2) == 0) {
25163 result = 0;
25165 else if (strncmp(argv[1], "-include", 10) == 0) {
25166 struct filelist *old_head = include_filelist;
25167 include_filelist = malloc(sizeof(struct filelist));
25168 if (!include_filelist) {
25169 die("Out of memory.\n");
25171 argv++;
25172 argc--;
25173 include_filelist->filename = strdup(argv[1]);
25174 include_filelist->next = old_head;
25175 result = 0;
25177 if (result < 0) {
25178 arg_error("Invalid option specified: %s\n",
25179 argv[1]);
25181 argv++;
25182 argc--;
25184 else {
25185 if (filename) {
25186 arg_error("Only one filename may be specified\n");
25188 filename = argv[1];
25189 argv++;
25190 argc--;
25193 if (!filename) {
25194 arg_error("No filename specified\n");
25196 compile(filename, &compiler, &arch);
25198 return 0;