5 #define VERSION_MAJOR "0"
6 #define VERSION_MINOR "80"
7 #define RELEASE_DATE "18 November 2015"
8 #define VERSION VERSION_MAJOR "." VERSION_MINOR
15 #include <sys/types.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"
62 /* Control flow graph of a loop without goto.
73 * |\ GGG HHH | continue;
101 * DFlocal(X) = { Y <- Succ(X) | idom(Y) != X }
102 * DFup(Z) = { Y <- DF(Z) | idom(Y) != X }
105 * [] == DFlocal(X) U DF(X)
108 * Dominator graph of the same nodes.
112 * BBB JJJ BBB: [ JJJ ] ( JJJ ) JJJ: [ ] ()
114 * CCC CCC: [ ] ( BBB, JJJ )
116 * DDD EEE DDD: [ ] ( BBB ) EEE: [ JJJ ] ()
118 * FFF FFF: [ ] ( BBB )
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.
131 const char *filename
;
132 struct filelist
*next
;
135 struct filelist
*include_filelist
= NULL
;
137 static void __attribute__((noreturn
)) die(char *fmt
, ...)
142 vfprintf(stderr
, fmt
, args
);
149 static void *xmalloc(size_t size
, const char *name
)
154 die("Cannot malloc %ld bytes to hold %s: %s\n",
155 size
+ 0UL, name
, strerror(errno
));
160 static void *xcmalloc(size_t size
, const char *name
)
163 buf
= xmalloc(size
, name
);
164 memset(buf
, 0, size
);
168 static void *xrealloc(void *ptr
, size_t size
, const char *name
)
171 buf
= realloc(ptr
, size
);
173 die("Cannot realloc %ld bytes to hold %s: %s\n",
174 size
+ 0UL, name
, strerror(errno
));
179 static void xfree(const void *ptr
)
184 static char *xstrdup(const char *str
)
189 new = xmalloc(len
+ 1, "xstrdup string");
190 memcpy(new, str
, len
);
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
];
208 if (getcwd(cwd
, sizeof(cwd
)) == 0) {
209 die("cwd buffer to small");
213 if (chdir(dirname
) != 0) {
216 if (does_exist
&& (access(filename
, O_RDONLY
) < 0)) {
217 if ((errno
!= EACCES
) && (errno
!= EROFS
)) {
225 static off_t
get_file_size(FILE *f
)
229 if (fd
== -1) return -1;
230 if (fstat(fd
, &s
) == -1) return -1;
234 static char *slurp_file(const char *dirname
, const char *filename
, off_t
*r_size
)
236 char cwd
[MAX_CWD_SIZE
];
238 off_t size
, progress
;
246 if (getcwd(cwd
, sizeof(cwd
)) == 0) {
247 die("cwd buffer to small");
250 file
= fopen(filename
, "rb");
253 die("Cannot open '%s' : %s\n",
254 filename
, strerror(errno
));
256 size
= get_file_size(file
);
258 die("Could not fetch size of '%s': %s\n", filename
, strerror(errno
));
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 */
265 while(progress
< size
) {
266 result
= fread(buf
+ progress
, 1, size
- progress
, file
);
268 if ((errno
== EINTR
) || (errno
== EAGAIN
))
270 die("read on %s of %ld bytes failed: %s\n",
271 filename
, (size
- progress
)+ 0UL, strerror(errno
));
279 /* Types on the destination platform */
280 #if DEBUG_ROMCC_WARNINGS
281 #warning "FIXME this assumes 32bit x86 is the destination"
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
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
348 struct file_state
*prev
;
349 const char *basename
;
355 const char *line_start
;
357 const char *report_name
;
358 const char *report_dir
;
366 struct hash_entry
*ident
;
376 /* I have two classes of types:
378 * Logical types. (The type the C standard says the operation is of)
380 * The operational types are:
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.
421 #define OP_POS 16 /* Dummy positive operator don't use it */
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 */
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
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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
567 * ???? registers ????
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
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.
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.
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
629 /* OP_LABEL is a triple that establishes an target for branches.
630 * ->use is the list of all branches that use this label.
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
646 /* OP_SDECL is a triple that establishes a variable of static
648 * ->use is a list of statements that use the variable.
649 * MISC(0) holds the initializer expression.
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.
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.
708 /* Architecture specific instructions */
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
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 */
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) { \
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..."
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"),
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"),
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"),
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";
909 if (index
>= OP_MAX
) {
912 return table_ops
[index
].name
;
919 struct triple_set
*next
;
920 struct triple
*member
;
930 const char *filename
;
931 const char *function
;
934 struct occurrence
*parent
;
941 struct triple
*next
, *prev
;
942 struct triple_set
*use
;
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
;
972 struct bitfield bitfield
;
975 struct hash_entry
*field
;
976 struct asm_info
*ainfo
;
978 struct symbol
*symbol
;
980 struct triple
*param
[2];
987 struct ins_template
{
988 struct reg_info lhs
[MAX_LHS
+ 1], rhs
[MAX_RHS
+ 1];
992 struct ins_template tmpl
;
997 struct block_set
*next
;
998 struct block
*member
;
1001 struct block
*work_next
;
1002 struct triple
*first
, *last
;
1004 struct block_set
*edges
;
1006 struct block_set
*use
;
1007 struct block_set
*idominates
;
1008 struct block_set
*domfrontier
;
1010 struct block_set
*ipdominates
;
1011 struct block_set
*ipdomfrontier
;
1012 struct block
*ipdom
;
1018 struct symbol
*next
;
1019 struct hash_entry
*ident
;
1026 struct macro_arg
*next
;
1027 struct hash_entry
*ident
;
1030 struct hash_entry
*ident
;
1033 struct macro_arg
*args
;
1038 struct hash_entry
*next
;
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
;
1064 const char **undefs
;
1067 unsigned long features
;
1069 struct basic_blocks
{
1070 struct triple
*func
;
1071 struct triple
*first
;
1072 struct block
*first_block
, *last_block
;
1075 #define MAX_PP_IF_DEPTH 63
1076 struct compile_state
{
1077 struct compiler_state
*compiler
;
1078 struct arch_state
*arch
;
1082 struct file_state
*file
;
1083 struct occurrence
*last_occurrence
;
1084 const char *function
;
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
;
1108 unsigned char if_bytes
[(MAX_PP_IF_DEPTH
+ CHAR_BIT
-1)/CHAR_BIT
];
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
1126 #define STOR_GLOBAL 0x0001
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
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
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
1254 struct type
*left
, *right
;
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
1264 #define MAX_REGISTERS 75
1265 #define REGISTER_BITS 7
1266 #define MAX_VIRT_REGISTERS (1<<REGISTER_BITS)
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"
1284 #if (MAX_REGC + REGISTER_BITS) >= 26
1285 #error "Too many id bits used"
1288 /* Provision for 8 register classes */
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 | \
1365 #define DEBUG_ALL ( \
1366 DEBUG_ABORT_ON_ERROR | \
1367 DEBUG_BASIC_BLOCKS | \
1368 DEBUG_FDOMINATORS | \
1369 DEBUG_RDOMINATORS | \
1371 DEBUG_INTERFERENCE | \
1372 DEBUG_SCC_TRANSFORM | \
1373 DEBUG_SCC_TRANSFORM2 | \
1374 DEBUG_REBUILD_SSA_FORM | \
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 | \
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
{
1455 struct compiler_arg
{
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
)
1466 for(; ptr
->name
; ptr
++) {
1467 if (strcmp(ptr
->name
, flag
) == 0) {
1473 *flags
&= ~(ptr
->flag
);
1475 *flags
|= ptr
->flag
;
1482 const struct compiler_arg
*ptr
, unsigned long *flags
, const char *arg
)
1487 val
= strchr(arg
, '=');
1491 for(; ptr
->name
; ptr
++) {
1492 if (strncmp(ptr
->name
, arg
, len
) == 0) {
1497 *flags
&= ~ptr
->mask
;
1498 result
= set_flag(&ptr
->flags
[0], flags
, 1, val
);
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
,
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
,
1533 *vec
= xrealloc(*vec
, sizeof(char *)*count
, "name");
1534 (*vec
)[count
-1] = 0;
1535 (*vec
)[count
-2] = str
;
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
)
1546 if (!exists(str
, ".")) {
1547 arg_warning("Warning: Nonexistent include path: `%s'\n",
1550 result
= append_string(&compiler
->include_path_count
,
1551 &compiler
->include_paths
, str
, "include_paths");
1555 static int append_define(struct compiler_state
*compiler
, const char *str
)
1557 const char *end
, *rest
;
1560 end
= strchr(str
, '=');
1562 end
= str
+ strlen(str
);
1564 rest
= identifier(str
, end
);
1566 int len
= end
- str
- 1;
1567 arg_error("Invalid name cannot define macro: `%*.*s'\n",
1570 result
= append_string(&compiler
->define_count
,
1571 &compiler
->defines
, str
, "defines");
1575 static int append_undef(struct compiler_state
*compiler
, const char *str
)
1577 const char *end
, *rest
;
1580 end
= str
+ strlen(str
);
1581 rest
= identifier(str
, end
);
1583 int len
= end
- str
- 1;
1584 arg_error("Invalid name cannot undefine macro: `%*.*s'\n",
1587 result
= append_string(&compiler
->undef_count
,
1588 &compiler
->undefs
, str
, "undefs");
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
},
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
, },
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
},
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
},
1654 static int compiler_encode_flag(
1655 struct compiler_state
*compiler
, const char *flag
)
1662 if (strncmp(flag
, "no-", 3) == 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) {
1683 compiler
->label_prefix
= flag
+ 13;
1685 else if (act
&& strncmp(flag
, "max-allocation-passes=", 22) == 0) {
1686 unsigned long max_passes
;
1688 max_passes
= strtoul(flag
+ 22, &end
, 10);
1689 if (end
[0] == '\0') {
1691 compiler
->max_allocation_passes
= max_passes
;
1694 else if (act
&& strcmp(flag
, "debug") == 0) {
1696 compiler
->debug
|= DEBUG_DEFAULT
;
1698 else if (strncmp(flag
, "debug-", 6) == 0) {
1700 result
= set_flag(romcc_debug_flags
, &compiler
->debug
, act
, flag
);
1703 result
= set_flag(romcc_flags
, &compiler
->flags
, act
, flag
);
1705 result
= set_arg(romcc_args
, &compiler
->flags
, flag
);
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
);
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)
1743 do_cleanup(exit_state
);
1747 static int get_col(struct file_state
*file
)
1750 const char *ptr
, *end
;
1751 ptr
= file
->line_start
;
1753 for(col
= 0; ptr
< end
; ptr
++) {
1758 col
= (col
& ~7) + 8;
1764 static void loc(FILE *fp
, struct compile_state
*state
, struct triple
*triple
)
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
);
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
;
1788 va_start(args
, fmt
);
1789 loc(fp
, state
, ptr
);
1792 fprintf(fp
, "%p %-10s ", ptr
, tops(ptr
->op
));
1794 fprintf(fp
, "Internal compiler error: ");
1795 vfprintf(fp
, fmt
, args
);
1803 static void internal_warning(struct compile_state
*state
, struct triple
*ptr
,
1804 const char *fmt
, ...)
1806 FILE *fp
= state
->errout
;
1808 va_start(args
, fmt
);
1809 loc(fp
, state
, ptr
);
1811 fprintf(fp
, "%p %-10s ", ptr
, tops(ptr
->op
));
1813 fprintf(fp
, "Internal compiler warning: ");
1814 vfprintf(fp
, fmt
, args
);
1821 static void __attribute__ ((noreturn
)) error(struct compile_state
*state
, struct triple
*ptr
,
1822 const char *fmt
, ...)
1824 FILE *fp
= state
->errout
;
1826 va_start(args
, fmt
);
1827 loc(fp
, state
, ptr
);
1829 if (ptr
&& (state
->compiler
->debug
& DEBUG_ABORT_ON_ERROR
)) {
1830 fprintf(fp
, "%p %-10s ", ptr
, tops(ptr
->op
));
1832 vfprintf(fp
, fmt
, args
);
1836 if (state
->compiler
->debug
& DEBUG_ABORT_ON_ERROR
) {
1842 static void warning(struct compile_state
*state
, struct triple
*ptr
,
1843 const char *fmt
, ...)
1845 FILE *fp
= state
->errout
;
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
);
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";
1864 internal_error(state
, 0, fmt
, op
);
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");
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;
1912 if ((*ptr
)->member
== user
) {
1915 ptr
= &(*ptr
)->next
;
1917 /* Append new to the head of the list,
1918 * copy_func and rename_block_variables
1921 new = xcmalloc(sizeof(*new), "triple_set");
1923 new->next
= used
->use
;
1927 static void unuse_triple(struct triple
*used
, struct triple
*unuser
)
1929 struct triple_set
*use
, **ptr
;
1936 if (use
->member
== unuser
) {
1946 static void put_occurrence(struct occurrence
*occurrence
)
1949 occurrence
->count
-= 1;
1950 if (occurrence
->count
<= 0) {
1951 if (occurrence
->parent
) {
1952 put_occurrence(occurrence
->parent
);
1959 static void get_occurrence(struct occurrence
*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
;
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
;
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
);
1998 state
->last_occurrence
= 0;
1999 put_occurrence(last
);
2001 result
= xmalloc(sizeof(*result
), "occurrence");
2003 result
->filename
= filename
;
2004 result
->function
= function
;
2005 result
->line
= line
;
2008 state
->last_occurrence
= result
;
2012 static struct occurrence
*inline_occurrence(struct compile_state
*state
,
2013 struct occurrence
*base
, struct occurrence
*top
)
2015 struct occurrence
*result
, *last
;
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) &&
2022 (base
->line
== 0) &&
2023 (base
->function
[0] == '\0') &&
2024 (base
->filename
[0] == '\0')) {
2027 /* See if I can reuse the last occurrence I had */
2028 last
= state
->last_occurrence
;
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
);
2038 /* I can't reuse the last occurrence so free it */
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");
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
;
2056 static struct occurrence dummy_occurrence
= {
2058 .filename
= __FILE__
,
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
,
2073 .op
= OP_UNKNOWNVAL
,
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
;
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
;
2111 lhs
= registers_of(state
, type
);
2114 lhs
= registers_of(state
, type
);
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");
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?");
2164 struct triple
*dup_triple(struct compile_state
*state
, struct triple
*src
)
2167 int src_lhs
, src_rhs
, src_size
;
2170 src_size
= TRIPLE_SIZE(src
);
2171 get_occurrence(src
->occurrence
);
2172 dup
= alloc_triple(state
, src
->op
, src
->type
, src_lhs
, src_rhs
,
2174 memcpy(dup
, src
, sizeof(*src
));
2175 memcpy(dup
->param
, src
->param
, src_size
* sizeof(src
->param
[0]));
2179 static struct triple
*copy_triple(struct compile_state
*state
, struct triple
*src
)
2181 struct triple
*copy
;
2182 copy
= dup_triple(state
, src
);
2184 copy
->next
= copy
->prev
= copy
;
2188 static struct triple
*new_triple(struct compile_state
*state
,
2189 int op
, struct type
*type
, int lhs
, int rhs
)
2192 struct occurrence
*occurrence
;
2193 occurrence
= new_occurrence(state
);
2194 ret
= alloc_triple(state
, op
, type
, lhs
, rhs
, occurrence
);
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
)
2204 ret
= alloc_triple(state
, op
, type
, -1, -1, occurrence
);
2205 count
= TRIPLE_SIZE(ret
);
2207 ret
->param
[0] = left
;
2210 ret
->param
[1] = right
;
2215 static struct triple
*triple(struct compile_state
*state
,
2216 int op
, struct type
*type
, struct triple
*left
, struct triple
*right
)
2220 ret
= new_triple(state
, op
, type
, -1, -1);
2221 count
= TRIPLE_SIZE(ret
);
2223 ret
->param
[0] = left
;
2226 ret
->param
[1] = right
;
2231 static struct triple
*branch(struct compile_state
*state
,
2232 struct triple
*targ
, struct triple
*test
)
2236 ret
= new_triple(state
, OP_CBRANCH
, &void_type
, -1, 1);
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");
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
)
2256 if ((ptr
->id
& TRIPLE_FLAG_FLATTENED
) || (ptr
->next
!= ptr
)) {
2257 internal_error(state
, ptr
, "expression already used");
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.
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
,
2287 struct triple
*first
;
2288 if (!ins
|| ins
== &unknown_triple
) {
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?");
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
;
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
)) {
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
;
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 */
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
;
2361 insert_triple(state
, next
, ret
);
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
)) {
2373 block
->last
= LHS(ret
, zlhs
- 1);
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
;
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
);
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
)
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);
2425 static struct triple
*mkprog(struct compile_state
*state
, ...)
2427 struct triple
*prog
, *head
, *arg
;
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
);
2436 while((arg
= va_arg(args
, struct triple
*)) != 0) {
2438 internal_error(state
, 0, "too many arguments to mkprog");
2440 flatten(state
, head
, arg
);
2443 prog
->type
= head
->prev
->type
;
2446 static void name_of(FILE *fp
, struct type
*type
);
2447 static void display_triple(FILE *fp
, struct triple
*ins
)
2449 struct occurrence
*ptr
;
2451 char pre
, post
, vol
;
2452 pre
= post
= vol
= ' ';
2454 if (ins
->id
& TRIPLE_FLAG_PRE_SPLIT
) {
2457 if (ins
->id
& TRIPLE_FLAG_POST_SPLIT
) {
2460 if (ins
->id
& TRIPLE_FLAG_VOLATILE
) {
2463 reg
= arch_reg_str(ID_REG(ins
->id
));
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
));
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
]);
2507 struct triple_set
*user
;
2508 #if DEBUG_DISPLAY_TYPES
2510 name_of(fp
, ins
->type
);
2513 #if DEBUG_DISPLAY_USES
2515 for(user
= ins
->use
; user
; user
= user
->next
) {
2516 fprintf(fp
, " %-10p", user
->member
);
2521 for(ptr
= ins
->occurrence
; ptr
; ptr
= ptr
->parent
) {
2522 fprintf(fp
, " %s,%s:%d.%d",
2528 if (ins
->op
== OP_ASM
) {
2529 fprintf(fp
, "\n\t%s", ins
->u
.ainfo
->str
);
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
));
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",
2569 fprintf(fp
, " [%-10p %-10p]",
2575 for(; i
< orig_count
; i
++) {
2576 fprintf(fp
, " [%-9p]", orig
->param
[i
]);
2579 for(; i
< new_count
; i
++) {
2580 fprintf(fp
, " [%-9p]", new->param
[i
]);
2583 if ((new->op
== OP_INTCONST
)||
2584 (new->op
== OP_ADDRCONST
)) {
2585 fprintf(fp
, " <0x%08lx>",
2586 (unsigned long)(new->u
.cval
));
2589 for(;indent
< 36; indent
++) {
2593 #if DEBUG_DISPLAY_TYPES
2595 name_of(fp
, new->type
);
2596 if (!equiv_types(new->type
, orig
->type
)) {
2597 fprintf(fp
, " -- ");
2598 name_of(fp
, orig
->type
);
2604 for(ptr
= orig
->occurrence
; ptr
; ptr
= ptr
->parent
) {
2605 fprintf(fp
, " %s,%s:%d.%d",
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.
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",
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? */
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
2680 return triple_is_branch_type(state
, ins
, UBRANCH
);
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
;
2705 static int triple_is_def(struct compile_state
*state
, struct triple
*ins
)
2707 /* This function is used to determine which triples need
2711 valid_ins(state
, ins
);
2712 is_def
= (table_ops
[ins
->op
].flags
& DEF
) == DEF
;
2713 if (ins
->lhs
>= 1) {
2719 static int triple_is_structural(struct compile_state
*state
, struct triple
*ins
)
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
)
2730 valid_ins(state
, ins
);
2731 is_part
= (table_ops
[ins
->op
].flags
& PART
) == 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
;
2750 else if ((last
>= vector
) && (last
< (vector
+ count
- 1))) {
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),
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),
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),
2779 static struct triple
**do_triple_targ(struct compile_state
*state
,
2780 struct triple
*ins
, struct triple
**last
, int call_edges
, int next_edges
)
2783 struct triple
**ret
, **vector
;
2788 if (triple_is_cbranch(state
, ins
)) {
2791 if (!call_edges
&& triple_is_call(state
, ins
)) {
2794 if (next_edges
&& triple_is_call(state
, ins
)) {
2797 vector
= &TARG(ins
, 0);
2798 if (!ret
&& next_is_targ
) {
2801 } else if (last
== &ins
->next
) {
2805 if (!ret
&& count
) {
2809 else if ((last
>= vector
) && (last
< (vector
+ count
- 1))) {
2812 else if (last
== vector
+ count
- 1) {
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
)) {
2823 ret
= &use
->member
->next
;
2826 else if (last
== &use
->member
->next
) {
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
;
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",
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",
2873 /* Function piece accessor functions */
2874 static struct triple
*do_farg(struct compile_state
*state
,
2875 struct triple
*func
, unsigned index
)
2878 struct triple
*first
, *arg
;
2882 if(index
>= (ftype
->elements
+ 2)) {
2883 internal_error(state
, func
, "bad argument index: %d", index
);
2885 first
= RHS(func
, 0);
2887 for(i
= 0; i
< index
; i
++, arg
= after_lhs(state
, arg
)) {
2890 if (arg
->op
!= OP_ADECL
) {
2891 internal_error(state
, 0, "arg not adecl?");
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);
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
)) {
2924 if (ins
->next
->prev
!= ins
) {
2925 internal_error(state
, ins
->next
, "bad prev");
2928 } while(ins
!= first
);
2931 static void verify_use(struct compile_state
*state
,
2932 struct triple
*user
, struct triple
*used
)
2935 size
= TRIPLE_SIZE(user
);
2936 for(i
= 0; i
< size
; i
++) {
2937 if (user
->param
[i
] == used
) {
2941 if (triple_is_branch(state
, user
)) {
2942 if (user
->next
== used
) {
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
;
2957 verify_use(state
, user
, used
);
2959 #if DEBUG_ROMCC_WARNINGS
2960 #warning "AUDIT ME ->rhs"
2963 param
= &RHS(user
, 0);
2964 for(i
= 0; i
< size
; i
++) {
2965 if (param
[i
] == used
) {
2972 static void free_triple(struct compile_state
*state
, struct triple
*ptr
)
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
;
2980 internal_error(state
, ptr
, "ptr->use != 0");
2982 put_occurrence(ptr
->occurrence
);
2983 memset(ptr
, -1, size
);
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
) {
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
);
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
)) {
3013 unuse_triple(*expr
, ptr
);
3016 expr
= triple_lhs(state
, ptr
, 0);
3017 for(; expr
; expr
= triple_lhs(state
, ptr
, expr
)) {
3019 unuse_triple(*expr
, ptr
);
3022 expr
= triple_misc(state
, ptr
, 0);
3023 for(; expr
; expr
= triple_misc(state
, ptr
, expr
)) {
3025 unuse_triple(*expr
, ptr
);
3028 expr
= triple_targ(state
, ptr
, 0);
3029 for(; expr
; expr
= triple_targ(state
, ptr
, expr
)) {
3031 unuse_triple(*expr
, ptr
);
3034 /* Reomve ptr from use chains where it is used */
3035 for(set
= ptr
->use
; set
; 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
)) {
3041 *expr
= &unknown_triple
;
3044 expr
= triple_lhs(state
, set
->member
, 0);
3045 for(; expr
; expr
= triple_lhs(state
, set
->member
, expr
)) {
3047 *expr
= &unknown_triple
;
3050 expr
= triple_misc(state
, set
->member
, 0);
3051 for(; expr
; expr
= triple_misc(state
, set
->member
, expr
)) {
3053 *expr
= &unknown_triple
;
3056 expr
= triple_targ(state
, set
->member
, 0);
3057 for(; expr
; expr
= triple_targ(state
, set
->member
, expr
)) {
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
3073 #define TOK_LBRACE 3
3074 #define TOK_RBRACE 4
3078 #define TOK_LBRACKET 8
3079 #define TOK_RBRACKET 9
3080 #define TOK_LPAREN 10
3081 #define TOK_RPAREN 11
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
3093 #define TOK_ANDEQ 23
3094 #define TOK_XOREQ 24
3097 #define TOK_NOTEQ 27
3098 #define TOK_QUEST 28
3099 #define TOK_LOGOR 29
3100 #define TOK_LOGAND 30
3104 #define TOK_LESSEQ 34
3105 #define TOK_MOREEQ 35
3109 #define TOK_MINUS 39
3112 #define TOK_PLUSPLUS 42
3113 #define TOK_MINUSMINUS 43
3115 #define TOK_ARROW 45
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
3131 #define TOK_BREAK 59
3134 #define TOK_CONST 62
3135 #define TOK_CONTINUE 63
3136 #define TOK_DEFAULT 64
3138 #define TOK_DOUBLE 66
3141 #define TOK_EXTERN 69
3142 #define TOK_FLOAT 70
3146 #define TOK_INLINE 74
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
3162 #define TOK_VOLATILE 90
3163 #define TOK_WHILE 91
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
3187 #define TOK_MELSE 113
3188 #define TOK_MIDENT 114
3193 static const char *tokens
[] = {
3194 [TOK_UNKNOWN
] = ":unknown:",
3195 [TOK_SPACE
] = ":space:",
3197 [TOK_LBRACE
] = "{",
3198 [TOK_RBRACE
] = "}",
3202 [TOK_LBRACKET
] = "[",
3203 [TOK_RBRACKET
] = "]",
3204 [TOK_LPAREN
] = "(",
3205 [TOK_RPAREN
] = ")",
3207 [TOK_DOTS
] = "...",
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
] = "^=",
3221 [TOK_NOTEQ
] = "!=",
3223 [TOK_LOGOR
] = "||",
3224 [TOK_LOGAND
] = "&&",
3228 [TOK_LESSEQ
] = "<=",
3229 [TOK_MOREEQ
] = ">=",
3236 [TOK_PLUSPLUS
] = "++",
3237 [TOK_MINUSMINUS
] = "--",
3239 [TOK_ARROW
] = "->",
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:",
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",
3259 [TOK_DOUBLE
] = "double",
3260 [TOK_ELSE
] = "else",
3261 [TOK_ENUM
] = "enum",
3262 [TOK_EXTERN
] = "extern",
3263 [TOK_FLOAT
] = "float",
3265 [TOK_GOTO
] = "goto",
3267 [TOK_INLINE
] = "inline",
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",
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",
3303 [TOK_MELSE
] = "#else",
3304 [TOK_MIDENT
] = "#:ident:",
3309 static unsigned int hash(const char *str
, int str_len
)
3313 end
= str
+ str_len
;
3315 for(; str
< end
; str
++) {
3316 hash
= (hash
*263) + *str
;
3318 hash
= hash
& (HASH_TABLE_SIZE
-1);
3322 static struct hash_entry
*lookup(
3323 struct compile_state
*state
, const char *name
, int name_len
)
3325 struct hash_entry
*entry
;
3327 index
= hash(name
, name_len
);
3328 entry
= state
->hash_table
[index
];
3330 ((entry
->name_len
!= name_len
) ||
3331 (memcmp(entry
->name
, name
, name_len
) != 0))) {
3332 entry
= entry
->next
;
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
;
3353 static void ident_to_keyword(struct compile_state
*state
, struct token
*tk
)
3355 struct hash_entry
*entry
;
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
;
3371 if ((entry
->tok
>= TOK_FIRST_MACRO
) && (entry
->tok
<= TOK_LAST_MACRO
)) {
3372 tk
->tok
= entry
->tok
;
3374 else if (entry
->tok
== TOK_IF
) {
3377 else if (entry
->tok
== TOK_ELSE
) {
3378 tk
->tok
= TOK_MELSE
;
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
);
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
)
3401 if (*chain
&& ((*chain
)->scope_depth
>= depth
)) {
3402 error(state
, 0, "%s already defined", ident
->name
);
3404 sym
= xcmalloc(sizeof(*sym
), "symbol");
3408 sym
->scope_depth
= depth
;
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
;
3445 while(sym
&& (sym
->scope_depth
== depth
)) {
3453 static void end_scope(struct compile_state
*state
)
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
];
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
;
3550 /* Free the macro buffer */
3553 /* Now free the macro itself */
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
;
3566 /* Find the length of the body */
3567 body_len
= strlen(body
);
3568 macro
= ident
->sym_define
;
3570 int identical_bodies
, identical_args
;
3571 struct macro_arg
*oarg
;
3572 /* Explicitly allow identical redfinitions of the same macro */
3574 (macro
->buf_len
== body_len
) &&
3575 (memcmp(macro
->buf
, body
, body_len
) == 0);
3576 identical_args
= macro
->argc
== argc
;
3579 while(identical_args
&& arg
) {
3580 identical_args
= oarg
->ident
== arg
->ident
;
3584 if (identical_bodies
&& identical_args
) {
3588 error(state
, 0, "macro %s already defined\n", ident
->name
);
3591 fprintf(state
->errout
, "#define %s: `%*.*s'\n",
3592 ident
->name
, body_len
, body_len
, body
);
3594 macro
= xmalloc(sizeof(*macro
), "macro");
3595 macro
->ident
= ident
;
3597 macro
->buf_len
= body_len
;
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
)
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
)
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
++) {
3666 name_len
= strlen(name
);
3667 body
= strchr(name
, '=');
3671 name_len
= body
- name
;
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
)
3698 static int digitp(int c
)
3702 case '0': case '1': case '2': case '3': case '4':
3703 case '5': case '6': case '7': case '8': case '9':
3709 static int digval(int c
)
3712 if ((c
>= '0') && (c
<= '9')) {
3718 static int hexdigitp(int 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':
3731 static int hexdigval(int c
)
3734 if ((c
>= '0') && (c
<= '9')) {
3737 else if ((c
>= 'A') && (c
<= 'F')) {
3738 val
= 10 + (c
- 'A');
3740 else if ((c
>= 'a') && (c
<= 'f')) {
3741 val
= 10 + (c
- 'a');
3746 static int octdigitp(int c
)
3750 case '0': case '1': case '2': case '3':
3751 case '4': case '5': case '6': case '7':
3757 static int octdigval(int c
)
3760 if ((c
>= '0') && (c
<= '7')) {
3766 static int letterp(int 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':
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':
3789 static const char *identifier(const char *str
, const char *end
)
3791 if (letterp(*str
)) {
3792 for(; str
< end
; str
++) {
3795 if (!letterp(c
) && !digitp(c
)) {
3803 static int char_value(struct compile_state
*state
,
3804 const signed char **strp
, const signed char *end
)
3806 const signed char *str
;
3810 if ((c
== '\\') && (str
< end
)) {
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;
3826 while((str
< end
) && hexdigitp(*str
)) {
3828 c
+= hexdigval(*str
);
3832 case '0': case '1': case '2': case '3':
3833 case '4': case '5': case '6': case '7':
3835 while((str
< end
) && octdigitp(*str
)) {
3837 c
+= octdigval(*str
);
3842 error(state
, 0, "Invalid character constant");
3850 static const char *next_char(struct file_state
*file
, const char *pos
, int index
)
3852 const char *end
= file
->buf
+ file
->size
;
3854 /* Lookup the character */
3857 /* Is this a trigraph? */
3858 if (file
->trigraphs
&&
3859 (c
== '?') && ((end
- pos
) >= 3) && (pos
[1] == '?'))
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;
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
) {
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) {
3893 /* Process a normal character */
3902 static int get_char(struct file_state
*file
, const char *pos
)
3904 const char *end
= file
->buf
+ file
->size
;
3907 pos
= next_char(file
, pos
, 0);
3909 /* Lookup the character */
3911 /* If it is a trigraph get the trigraph value */
3912 if (file
->trigraphs
&&
3913 (c
== '?') && ((end
- pos
) >= 3) && (pos
[1] == '?'))
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;
3931 static void eat_chars(struct file_state
*file
, const char *targ
)
3933 const char *pos
= file
->pos
;
3935 /* Do we have a newline? */
3936 if (pos
[0] == '\n') {
3938 file
->report_line
++;
3939 file
->line_start
= pos
+ 1;
3947 static size_t char_strlen(struct file_state
*file
, const char *src
, const char *end
)
3952 src
= next_char(file
, src
, 1);
3958 static void char_strcpy(char *dest
,
3959 struct file_state
*file
, const char *src
, const char *end
)
3963 c
= get_char(file
, src
);
3964 src
= next_char(file
, src
, 1);
3969 static char *char_strdup(struct file_state
*file
,
3970 const char *start
, const char *end
, const char *id
)
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';
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);
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);
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);
4005 static const char *after_alnums(struct file_state
*file
, const char *ptr
)
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
);
4016 static void save_string(struct file_state
*file
,
4017 struct token
*tk
, const char *start
, const char *end
, const char *id
)
4021 /* Create a private copy of the string */
4022 str
= char_strdup(file
, start
, end
, id
);
4024 /* Store the copy in the token */
4026 tk
->str_len
= strlen(str
);
4029 static void raw_next_token(struct compile_state
*state
,
4030 struct file_state
*file
, struct token
*tk
)
4040 token
= tokp
= next_char(file
, file
->pos
, 0);
4042 c
= get_char(file
, tokp
);
4043 tokp
= next_char(file
, tokp
, 1);
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 */
4054 else if (spacep(c
)) {
4056 while (spacep(get_char(file
, tokp
))) {
4057 tokp
= next_char(file
, tokp
, 1);
4061 else if ((c
== '/') && (c1
== '/')) {
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.
4073 tokp
= next_char(file
, tokp
, 1);
4077 else if ((c
== '/') && (c1
== '*')) {
4078 tokp
= next_char(file
, tokp
, 2);
4080 while((c1
= get_char(file
, tokp
)) != -1) {
4081 tokp
= next_char(file
, tokp
, 1);
4082 if ((c
== '*') && (c1
== '/')) {
4088 if (tok
== TOK_UNKNOWN
) {
4089 error(state
, 0, "unterminated comment");
4092 /* string constants */
4093 else if ((c
== '"') || ((c
== 'L') && (c1
== '"'))) {
4098 tokp
= next_char(file
, tokp
, 1);
4100 while((c
= get_char(file
, tokp
)) != -1) {
4101 tokp
= next_char(file
, tokp
, 1);
4105 else if (c
== '\\') {
4106 tokp
= next_char(file
, tokp
, 1);
4108 else if (c
== '"') {
4109 tok
= TOK_LIT_STRING
;
4113 if (tok
== TOK_UNKNOWN
) {
4114 error(state
, 0, "unterminated string constant");
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
== '\''))) {
4129 tokp
= next_char(file
, tokp
, 1);
4131 while((c
= get_char(file
, tokp
)) != -1) {
4132 tokp
= next_char(file
, tokp
, 1);
4136 else if (c
== '\\') {
4137 tokp
= next_char(file
, tokp
, 1);
4139 else if (c
== '\'') {
4144 if (tok
== TOK_UNKNOWN
) {
4145 error(state
, 0, "unterminated character constant");
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
4160 * Floating constants
4161 * {digits}.{digits}[Ee][+-]?{digits}
4163 * {digits}[Ee][+-]?{digits}
4164 * .{digits}[Ee][+-]?{digits}
4167 else if (digitp(c
) || ((c
== '.') && (digitp(c1
)))) {
4173 next
= after_digits(file
, tokp
);
4178 cn
= get_char(file
, next
);
4180 next
= next_char(file
, next
, 1);
4181 next
= after_digits(file
, next
);
4184 cn
= get_char(file
, next
);
4185 if ((cn
== 'e') || (cn
== 'E')) {
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
);
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
)) {
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
);
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);
4242 /* Save the integer/floating point value */
4243 save_string(file
, tk
, token
, tokp
, "literal number");
4246 else if (letterp(c
)) {
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 */
4260 /* See if this identifier can be macro expanded */
4261 tk
->val
.notmacro
= 0;
4262 c
= get_char(file
, tokp
);
4264 tokp
= next_char(file
, tokp
, 1);
4265 tk
->val
.notmacro
= 1;
4268 /* C99 alternate macro characters */
4269 else if ((c
== '%') && (c1
== ':') && (c2
== '%') && (c3
== ':')) {
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
);
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
];
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
;
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
;
4362 if (macro
->argc
== 0) {
4364 raw_next_token(state
, file
, tk
);
4365 } while(tk
->tok
== TOK_SPACE
);
4368 argv
= xcmalloc(sizeof(*argv
) * macro
->argc
, "macro args");
4369 for(i
= 0, arg
= macro
->args
; arg
; arg
= arg
->next
, i
++) {
4372 argv
[i
].ident
= arg
->ident
;
4381 raw_next_token(state
, file
, tk
);
4383 if (!paren_depth
&& (tk
->tok
== TOK_COMMA
) &&
4384 (argv
[i
].ident
!= state
->i___VA_ARGS__
))
4387 if (i
>= macro
->argc
) {
4388 error(state
, 0, "too many args to %s\n",
4389 macro
->ident
->name
);
4394 if (tk
->tok
== TOK_LPAREN
) {
4398 if (tk
->tok
== TOK_RPAREN
) {
4399 if (paren_depth
== 0) {
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
);
4414 if (i
!= macro
->argc
-1) {
4415 error(state
, 0, "missing %s arg %d\n",
4416 macro
->ident
->name
, i
+2);
4422 static void free_macro_args(struct macro
*macro
, struct macro_arg_value
*argv
)
4425 for(i
= 0; i
< macro
->argc
; i
++) {
4426 xfree(argv
[i
].value
);
4436 static void grow_macro_buf(struct compile_state
*state
,
4437 const char *id
, struct macro_buf
*buf
,
4440 if ((buf
->pos
+ grow
) >= buf
->len
) {
4441 buf
->str
= xrealloc(buf
->str
, buf
->len
+ grow
, id
);
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
);
4453 fprintf(state
->errout
, "append: `%*.*s' `%*.*s'\n",
4454 buf
->pos
, buf
->pos
, buf
->str
,
4455 flen
, flen
, buf
->str
+ buf
->pos
);
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
)
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
);
4470 fprintf(state
->errout
, "append: `%*.*s' `%*.*s'\n",
4471 buf
->pos
, buf
->pos
, buf
->str
,
4472 flen
, flen
, buf
->str
+ buf
->pos
);
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
)
4485 for(i
= 0; i
< macro
->argc
; i
++) {
4486 struct file_state fmacro
, *file
;
4487 struct macro_buf buf
;
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
;
4496 fmacro
.line_start
= fmacro
.buf
;
4497 fmacro
.report_line
= 1;
4498 fmacro
.report_name
= fmacro
.basename
;
4499 fmacro
.report_dir
= fmacro
.dirname
;
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
);
4510 raw_next_token(state
, file
, tk
);
4512 /* If we have recursed into another macro body
4515 if (tk
->tok
== TOK_EOF
) {
4516 struct file_state
*old
;
4522 /* old->basename is used keep it */
4523 xfree(old
->dirname
);
4528 else if (tk
->ident
&& tk
->ident
->sym_define
) {
4529 if (compile_macro(state
, &file
, tk
)) {
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
;
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
[] = " ";
4555 /* Place the macro body in a dummy file */
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
;
4563 fmacro
.line_start
= fmacro
.buf
;
4564 fmacro
.report_line
= 1;
4565 fmacro
.report_name
= fmacro
.basename
;
4566 fmacro
.report_dir
= fmacro
.dirname
;
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
);
4576 fstart
= fmacro
.pos
;
4577 raw_next_token(state
, &fmacro
, tk
);
4578 while(tk
->tok
!= TOK_EOF
) {
4579 flen
= fmacro
.pos
- fstart
;
4582 if (macro
->argc
< 0) {
4585 for(i
= 0; i
< macro
->argc
; i
++) {
4586 if (argv
[i
].ident
== tk
->ident
) {
4590 if (i
>= macro
->argc
) {
4593 /* Substitute macro parameter */
4594 fstart
= argv
[i
].value
;
4598 if (macro
->argc
< 0) {
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
) {
4610 if (i
>= macro
->argc
) {
4611 error(state
, 0, "parameter `%s' not found",
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
;
4623 else if (*str
== '"') {
4627 append_macro_text(state
, macro
->ident
->name
, buf
, str
, len
);
4629 append_macro_text(state
, macro
->ident
->name
, buf
, "\"", 1);
4633 case TOK_CONCATENATE
:
4634 /* Concatenate tokens */
4635 /* Delete the previous whitespace token */
4636 if (buf
->str
[buf
->pos
- 1] == ' ') {
4639 /* Skip the next sequence of whitspace tokens */
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.
4650 /* Collapse multiple spaces into one */
4651 if (buf
->str
[buf
->pos
- 1] != ' ') {
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
,
4674 /* Guard all instances of the macro name in the replacement
4675 * text from further macro expansion.
4677 struct file_state fmacro
;
4681 /* Put the old macro expansion buffer in a file */
4683 fmacro
.basename
= macro
->ident
->name
;
4684 fmacro
.dirname
= "";
4685 fmacro
.buf
= buf
->str
;
4686 fmacro
.size
= buf
->pos
;
4687 fmacro
.pos
= fmacro
.buf
;
4689 fmacro
.line_start
= fmacro
.buf
;
4690 fmacro
.report_line
= 1;
4691 fmacro
.report_name
= fmacro
.basename
;
4692 fmacro
.report_dir
= fmacro
.dirname
;
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
);
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
);
4715 append_macro_text(state
, macro
->ident
->name
, buf
, fstart
, flen
);
4717 fstart
= fmacro
.pos
;
4718 raw_next_token(state
, &fmacro
, tk
);
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
;
4733 fprintf(state
->errout
, "macro: %s\n", tk
->ident
->name
);
4736 macro
= ident
->sym_define
;
4738 /* If this token comes from a macro expansion ignore it */
4739 if (tk
->val
.notmacro
) {
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
) != '(')) {
4749 /* Read in the macro arguments */
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
);
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__
) {
4773 buf
.str
= xmalloc(buf
.len
, ident
->name
);
4774 sprintf(buf
.str
, "%d", state
->file
->line
);
4775 buf
.pos
= strlen(buf
.str
);
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
);
4786 fprintf(state
->errout
, "%s: %d -> `%*.*s'\n",
4787 ident
->name
, buf
.pos
, buf
.pos
, (int)(buf
.pos
), buf
.str
);
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
;
4800 file
->line_start
= file
->pos
;
4801 file
->report_line
= 1;
4802 file
->report_name
= file
->basename
;
4803 file
->report_dir
= file
->dirname
;
4805 file
->trigraphs
= 0;
4806 file
->join_lines
= 0;
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
)
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
)
4833 index
= state
->if_depth
/ CHAR_BIT
;
4834 offset
= state
->if_depth
% CHAR_BIT
;
4836 state
->if_bytes
[index
] &= ~(1 << offset
);
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
)
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
)
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
)
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
;
4888 raw_next_token(state
, file
, tk
);
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
);
4902 raw_next_token(state
, state
->file
, tk
);
4908 static void pp_token(struct compile_state
*state
, struct token
*tk
)
4912 raw_token(state
, tk
);
4915 if (tk
->tok
== TOK_SPACE
) {
4916 raw_token(state
, tk
);
4919 else if (tk
->tok
== TOK_IDENT
) {
4920 if (state
->token_base
== 0) {
4921 ident_to_keyword(state
, tk
);
4923 ident_to_macro(state
, tk
);
4929 static void preprocess(struct compile_state
*state
, struct token
*tk
);
4931 static void token(struct compile_state
*state
, struct token
*tk
)
4934 pp_token(state
, tk
);
4937 /* Process a macro directive */
4938 if (tk
->tok
== TOK_MACRO
) {
4939 /* Only match preprocessor directives at the start of a line */
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
);
4952 /* Expand a macro call */
4953 else if (tk
->ident
&& tk
->ident
->sym_define
) {
4954 rescan
= compile_macro(state
, &state
->file
, tk
);
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
);
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
);
4971 /* Error on unknown tokens */
4972 else if (tk
->tok
== TOK_UNKNOWN
) {
4973 error(state
, 0, "unknown token");
4979 static inline struct token
*get_token(struct compile_state
*state
, int offset
)
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
)
4993 check_tok(state
, get_token(state
, 1), tok
);
4995 /* Free the old token value */
4996 tk
= get_token(state
, 0);
4998 memset((void *)tk
->val
.str
, -1, tk
->str_len
);
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 */
5013 static int raw_peek(struct compile_state
*state
)
5016 tk1
= get_token(state
, 1);
5017 if (tk1
->tok
== -1) {
5018 raw_token(state
, tk1
);
5023 static struct token
*raw_eat(struct compile_state
*state
, int tok
)
5026 return do_eat_token(state
, tok
);
5029 static int pp_peek(struct compile_state
*state
)
5032 tk1
= get_token(state
, 1);
5033 if (tk1
->tok
== -1) {
5034 pp_token(state
, tk1
);
5039 static struct token
*pp_eat(struct compile_state
*state
, int tok
)
5042 return do_eat_token(state
, tok
);
5045 static int peek(struct compile_state
*state
)
5048 tk1
= get_token(state
, 1);
5049 if (tk1
->tok
== -1) {
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) {
5063 if (tk2
->tok
== -1) {
5069 static struct token
*eat(struct compile_state
*state
, int tok
)
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
;
5080 struct file_state
*file
;
5082 file
= xmalloc(sizeof(*file
), "file_state");
5084 base
= strrchr(filename
, '/');
5087 subdir_len
= base
- filename
;
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';
5110 /* Find the appropriate directory... */
5112 if (!state
->file
&& exists(cwd
, filename
)) {
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
)) {
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
;
5139 file
->report_line
= 1;
5140 file
->report_name
= file
->basename
;
5141 file
->report_dir
= file
->dirname
;
5143 file
->trigraphs
= (state
->compiler
->flags
& COMPILER_TRIGRAPHS
)? 1: 0;
5144 file
->join_lines
= 1;
5146 file
->prev
= state
->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.
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
);
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
;
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;
5197 dir_len
= base
- token
;
5199 name_len
-= 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;
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
;
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;
5232 dir_len
= base
- token
;
5234 name_len
-= 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;
5252 struct hash_entry
*ident
;
5253 pp_eat(state
, TOK_MUNDEF
);
5254 if (if_eat(state
)) /* quit early when #if'd out */
5257 ident
= pp_eat(state
, TOK_MIDENT
)->ident
;
5259 undef_macro(state
, ident
);
5263 pp_eat(state
, TOK_MPRAGMA
);
5264 if (if_eat(state
)) /* quit early when #if'd out */
5266 warning(state
, 0, "Ignoring pragma");
5269 pp_eat(state
, TOK_MELIF
);
5270 reenter_if(state
, "#elif");
5271 if (if_eat(state
)) /* quit early when #if'd out */
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
5281 set_if_value(state
, mcexpr(state
));
5282 if (!if_value(state
)) {
5283 eat_tokens(state
, TOK_MELSE
);
5288 pp_eat(state
, TOK_MIF
);
5290 if (if_eat(state
)) /* quit early when #if'd out */
5292 set_if_value(state
, mcexpr(state
));
5293 if (!if_value(state
)) {
5294 eat_tokens(state
, TOK_MELSE
);
5299 struct hash_entry
*ident
;
5301 pp_eat(state
, TOK_MIFNDEF
);
5303 if (if_eat(state
)) /* quit early when #if'd out */
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
);
5314 struct hash_entry
*ident
;
5315 pp_eat(state
, TOK_MIFDEF
);
5317 if (if_eat(state
)) /* quit early when #if'd out */
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
);
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
);
5334 pp_eat(state
, TOK_MENDIF
);
5335 exit_if(state
, "#endif");
5339 struct hash_entry
*ident
;
5340 struct macro_arg
*args
, **larg
;
5341 const char *mstart
, *mend
;
5344 pp_eat(state
, TOK_MDEFINE
);
5345 if (if_eat(state
)) /* quit early when #if'd out */
5347 ident
= pp_eat(state
, TOK_MIDENT
)->ident
;
5352 /* Parse macro parameters */
5353 if (raw_peek(state
) == TOK_LPAREN
) {
5354 raw_eat(state
, TOK_LPAREN
);
5358 struct macro_arg
*narg
, *arg
;
5359 struct hash_entry
*aident
;
5362 tok
= pp_peek(state
);
5363 if (!args
&& (tok
== TOK_RPAREN
)) {
5366 else if (tok
== TOK_DOTS
) {
5367 pp_eat(state
, TOK_DOTS
);
5368 aident
= state
->i___VA_ARGS__
;
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'",
5384 /* Add the new argument to the end of the list */
5389 if ((aident
== state
->i___VA_ARGS__
) ||
5390 (pp_peek(state
) != TOK_COMMA
)) {
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 */
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 */
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"),
5424 const char *start
, *end
;
5427 pp_eat(state
, TOK_MERROR
);
5428 /* Find the start of the line */
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
;
5438 if (!if_eat(state
)) {
5439 error(state
, 0, "%*.*s", len
, len
, start
);
5445 const char *start
, *end
;
5448 pp_eat(state
, TOK_MWARNING
);
5450 /* Find the start of the line */
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
;
5460 if (!if_eat(state
)) {
5461 warning(state
, 0, "%*.*s", len
, len
, start
);
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
);
5480 if (tok
== TOK_LIT_STRING
) {
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
== '"') {
5492 memcpy(name
, token
, name_len
);
5493 name
[name_len
] = '\0';
5496 else if (tok
== TOK_LESS
) {
5497 struct macro_buf buf
;
5498 eat(state
, TOK_LESS
);
5501 buf
.str
= xmalloc(buf
.len
, "include");
5505 while((tok
!= TOK_MORE
) &&
5506 (tok
!= TOK_EOL
) && (tok
!= TOK_EOF
))
5509 tk
= eat(state
, tok
);
5510 append_macro_chars(state
, "include", &buf
,
5511 state
->file
, tk
->pos
, state
->file
->pos
);
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
);
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
);
5536 /* Ignore # without a following ident */
5540 const char *name1
, *name2
;
5541 name1
= tokens
[tok
];
5543 if (tok
== TOK_MIDENT
) {
5544 name2
= get_token(state
, 1)->ident
->name
;
5546 error(state
, 0, "Invalid preprocessor directive: %s %s",
5551 /* Consume the rest of the macro line */
5553 tok
= pp_peek(state
);
5555 } while((tok
!= TOK_EOF
) && (tok
!= TOK_EOL
));
5556 state
->token_base
= old_token_base
;
5557 state
->macro_file
= NULL
;
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;
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
;
5587 static struct type
*dup_type(struct compile_state
*state
, struct type
*orig
)
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
;
5596 new->left
= dup_type(state
, orig
->left
);
5599 new->right
= dup_type(state
, orig
->right
);
5605 static struct type
*invalid_type(struct compile_state
*state
, struct type
*type
)
5607 struct type
*invalid
, *member
;
5610 internal_error(state
, 0, "type missing?");
5612 switch(type
->type
& TYPE_MASK
) {
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
:
5623 invalid
= invalid_type(state
, type
->left
);
5626 invalid
= invalid_type(state
, type
->left
);
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
;
5637 invalid
= invalid_type(state
, member
);
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
;
5649 invalid
= invalid_type(state
, member
);
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
};
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
,
5678 #if DEBUG_ROMCC_WARNING
5679 static struct type void_func_type
= {
5680 .type
= TYPE_FUNCTION
,
5682 .right
= &void_type
,
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
);
5699 result
= triple(state
, OP_SDECL
, type
, 0, 0);
5704 static void stor_of(FILE *fp
, struct type
*type
)
5706 switch(type
->type
& STOR_MASK
) {
5708 fprintf(fp
, "auto ");
5711 fprintf(fp
, "static ");
5714 fprintf(fp
, "local ");
5717 fprintf(fp
, "extern ");
5720 fprintf(fp
, "register ");
5723 fprintf(fp
, "typedef ");
5725 case STOR_INLINE
| STOR_LOCAL
:
5726 fprintf(fp
, "inline ");
5728 case STOR_INLINE
| STOR_STATIC
:
5729 fprintf(fp
, "static inline");
5731 case STOR_INLINE
| STOR_EXTERN
:
5732 fprintf(fp
, "extern inline");
5735 fprintf(fp
, "stor:%x", type
->type
& STOR_MASK
);
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
)) {
5761 fprintf(fp
, "void");
5765 fprintf(fp
, "signed char");
5769 fprintf(fp
, "unsigned char");
5773 fprintf(fp
, "signed short");
5777 fprintf(fp
, "unsigned short");
5781 fprintf(fp
, "signed int");
5785 fprintf(fp
, "unsigned int");
5789 fprintf(fp
, "signed long");
5793 fprintf(fp
, "unsigned long");
5797 name_of(fp
, type
->left
);
5802 name_of(fp
, type
->left
);
5804 name_of(fp
, type
->right
);
5807 name_of(fp
, type
->left
);
5809 name_of(fp
, type
->right
);
5812 fprintf(fp
, "enum %s",
5813 (type
->type_ident
)? type
->type_ident
->name
: "");
5817 fprintf(fp
, "struct %s { ",
5818 (type
->type_ident
)? type
->type_ident
->name
: "");
5819 name_of(fp
, type
->left
);
5824 fprintf(fp
, "union %s { ",
5825 (type
->type_ident
)? type
->type_ident
->name
: "");
5826 name_of(fp
, type
->left
);
5831 name_of(fp
, type
->left
);
5832 fprintf(fp
, " (*)(");
5833 name_of(fp
, type
->right
);
5837 name_of(fp
, type
->left
);
5838 fprintf(fp
, " [%ld]", (long)(type
->elements
));
5841 fprintf(fp
, "tuple { ");
5842 name_of(fp
, type
->left
);
5847 fprintf(fp
, "join { ");
5848 name_of(fp
, type
->left
);
5853 name_of(fp
, type
->left
);
5854 fprintf(fp
, " : %d ", type
->elements
);
5858 fprintf(fp
, "unknown_t");
5861 fprintf(fp
, "????: %x", base_type
);
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
)
5872 switch(type
->type
& TYPE_MASK
) {
5881 align
= ALIGNOF_CHAR
;
5885 align
= ALIGNOF_SHORT
;
5890 align
= ALIGNOF_INT
;
5894 align
= ALIGNOF_LONG
;
5897 align
= ALIGNOF_POINTER
;
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
;
5909 align
= align_of(state
, type
->left
);
5915 align
= align_of(state
, type
->left
);
5918 error(state
, 0, "alignof not yet defined for type\n");
5924 static size_t reg_align_of(struct compile_state
*state
, struct type
*type
)
5927 switch(type
->type
& TYPE_MASK
) {
5936 align
= REG_ALIGNOF_CHAR
;
5940 align
= REG_ALIGNOF_SHORT
;
5945 align
= REG_ALIGNOF_INT
;
5949 align
= REG_ALIGNOF_LONG
;
5952 align
= REG_ALIGNOF_POINTER
;
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
;
5964 align
= reg_align_of(state
, type
->left
);
5970 align
= reg_align_of(state
, type
->left
);
5973 error(state
, 0, "alignof not yet defined for type\n");
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
) {
5996 size
= size_of(state
, type
);
5997 if ((offset
+ type
->elements
)/size
!= offset
/size
) {
6002 if (offset
% align
) {
6003 padding
= align
- (offset
% align
);
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
;
6022 if (offset
% align
) {
6023 padding
= align
- (offset
% align
);
6028 static size_t size_of(struct compile_state
*state
, struct type
*type
)
6031 switch(type
->type
& TYPE_MASK
) {
6036 size
= type
->elements
;
6044 size
= SIZEOF_SHORT
;
6056 size
= SIZEOF_POINTER
;
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
);
6067 pad
= needed_padding(state
, type
, size
);
6068 size
= size
+ pad
+ size_of(state
, type
);
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
;
6080 if (type
->elements
== ELEMENT_COUNT_UNSPECIFIED
) {
6081 internal_error(state
, 0, "Invalid array type");
6083 size
= size_of(state
, type
->left
) * type
->elements
;
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
);
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
);
6107 internal_error(state
, 0, "sizeof not yet defined for type");
6113 static size_t reg_size_of(struct compile_state
*state
, struct type
*type
)
6116 switch(type
->type
& TYPE_MASK
) {
6121 size
= type
->elements
;
6125 size
= REG_SIZEOF_CHAR
;
6129 size
= REG_SIZEOF_SHORT
;
6134 size
= REG_SIZEOF_INT
;
6138 size
= REG_SIZEOF_LONG
;
6141 size
= REG_SIZEOF_POINTER
;
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
);
6152 pad
= reg_needed_padding(state
, type
, size
);
6153 size
= size
+ pad
+ reg_size_of(state
, type
);
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
;
6165 if (type
->elements
== ELEMENT_COUNT_UNSPECIFIED
) {
6166 internal_error(state
, 0, "Invalid array type");
6168 size
= reg_size_of(state
, type
->left
) * type
->elements
;
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
);
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
);
6192 internal_error(state
, 0, "sizeof not yet defined for type");
6198 static size_t registers_of(struct compile_state
*state
, struct type
*type
)
6201 registers
= reg_size_of(state
, type
);
6202 registers
+= REG_SIZEOF_REG
- 1;
6203 registers
/= REG_SIZEOF_REG
;
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
;
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
;
6228 size
+= size_of(state
, member
->left
);
6229 member
= member
->right
;
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
;
6242 member
= member
->right
;
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
);
6255 static size_t field_reg_offset(struct compile_state
*state
,
6256 struct type
*type
, struct hash_entry
*field
)
6258 struct type
*member
;
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
;
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
;
6282 member
= member
->right
;
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
);
6296 static struct type
*field_type(struct compile_state
*state
,
6297 struct type
*type
, struct hash_entry
*field
)
6299 struct type
*member
;
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
;
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
;
6319 member
= member
->right
;
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
);
6332 static size_t index_offset(struct compile_state
*state
,
6333 struct type
*type
, ulong_t index
)
6335 struct type
*member
;
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
) {
6343 member
= type
->left
;
6345 while(member
&& ((member
->type
& TYPE_MASK
) == TYPE_PRODUCT
)) {
6346 size
+= needed_padding(state
, member
->left
, size
);
6348 member
= member
->left
;
6351 size
+= size_of(state
, member
->left
);
6353 member
= member
->right
;
6356 internal_error(state
, 0, "Member is NULL");
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
) {
6365 member
= type
->left
;
6367 while(member
&& ((member
->type
& TYPE_MASK
) == TYPE_OVERLAP
)) {
6372 member
= member
->right
;
6375 internal_error(state
, 0, "Missing member index: %u", index
);
6379 internal_error(state
, 0,
6380 "request for index %u in something not an array, tuple or join",
6386 static size_t index_reg_offset(struct compile_state
*state
,
6387 struct type
*type
, ulong_t index
)
6389 struct type
*member
;
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
) {
6397 member
= type
->left
;
6399 while(member
&& ((member
->type
& TYPE_MASK
) == TYPE_PRODUCT
)) {
6400 size
+= reg_needed_padding(state
, member
->left
, size
);
6402 member
= member
->left
;
6405 size
+= reg_size_of(state
, member
->left
);
6407 member
= member
->right
;
6410 internal_error(state
, 0, "Member is NULL");
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
) {
6419 member
= type
->left
;
6421 while(member
&& ((member
->type
& TYPE_MASK
) == TYPE_OVERLAP
)) {
6426 member
= member
->right
;
6429 internal_error(state
, 0, "Missing member index: %u", index
);
6433 internal_error(state
, 0,
6434 "request for index %u in something not an array, tuple or join",
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
) {
6452 member
= type
->left
;
6454 while(member
&& ((member
->type
& TYPE_MASK
) == TYPE_PRODUCT
)) {
6456 member
= member
->left
;
6460 member
= member
->right
;
6463 internal_error(state
, 0, "Missing member index: %u", index
);
6466 else if ((type
->type
& TYPE_MASK
) == TYPE_JOIN
) {
6468 member
= type
->left
;
6470 while(member
&& ((member
->type
& TYPE_MASK
) == TYPE_OVERLAP
)) {
6472 member
= member
->left
;
6476 member
= member
->right
;
6479 internal_error(state
, 0, "Missing member index: %u", index
);
6484 internal_error(state
, 0,
6485 "request for index %u in something not an array, tuple or join",
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
;
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
) {
6503 /* Get out early if I don't need any registers for this type */
6507 /* Loop until I have no more layers I can remove */
6510 switch(type
->type
& TYPE_MASK
) {
6512 /* If I have a single element the unpacked type
6515 if (type
->elements
== 1) {
6521 /* If I have a single element the unpacked type
6524 if (type
->elements
== 1) {
6527 /* If I have multiple elements the unpacked
6528 * type is the non-void element.
6531 struct type
*next
, *member
;
6532 struct type
*sub_type
;
6538 if ((member
->type
& TYPE_MASK
) == TYPE_PRODUCT
) {
6539 next
= member
->right
;
6540 member
= member
->left
;
6542 if (reg_size_of(state
, member
) > 0) {
6544 internal_error(state
, 0, "true compound type in a register");
6557 /* If I have a single element the unpacked type
6560 if (type
->elements
== 1) {
6563 /* I can't in general unpack union types */
6566 /* If I'm not a compound type I can't unpack it */
6569 } while(start_type
!= type
);
6570 switch(type
->type
& TYPE_MASK
) {
6574 internal_error(state
, 0, "irredicible 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
;
6589 struct type
*invalid
;
6590 invalid
= invalid_type(state
, type
);
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?");
6602 size
= reg_size_of(state
, type
);
6603 if (reg_offset
> size
) {
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");
6611 switch(type
->type
& TYPE_MASK
) {
6612 /* Don't do anything with the basic types */
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
:
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
);
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
;
6647 member
= member
->right
;
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
);
6658 struct type
*join
, **jnext
, *mnext
;
6659 join
= new_type(TYPE_JOIN
, 0, 0);
6660 jnext
= &join
->left
;
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 */
6677 struct type
*test
= hunt
;
6679 if ((test
->type
& TYPE_MASK
) == TYPE_OVERLAP
) {
6683 if (equiv_types(part
, test
)) {
6691 *jnext
= new_type(TYPE_OVERLAP
, *jnext
, part
);
6692 jnext
= &(*jnext
)->right
;
6699 if (join
->elements
== 0) {
6700 internal_error(state
, 0, "No elements?");
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");
6724 invalid
= invalid_type(state
, member
);
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?");
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
) {
6748 member
= member
->left
;
6751 if (member
->left
== prev_member
) {
6754 member
= member
->right
;
6756 if (member
== prev_member
) {
6760 internal_error(state
, 0, "prev_member %s not present",
6761 prev_member
->field_ident
->name
);
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
)
6779 if ((type
->type
& TYPE_MASK
) != TYPE_STRUCT
) {
6780 internal_error(state
, 0, "walk_struct_fields only works on structures");
6783 for(i
= 0; i
< type
->elements
; i
++) {
6786 if ((mtype
->type
& TYPE_MASK
) == TYPE_PRODUCT
) {
6787 mtype
= mtype
->left
;
6789 walk_type_fields(state
, mtype
,
6791 field_reg_offset(state
, type
, mtype
->field_ident
),
6793 field_offset(state
, type
, mtype
->field_ident
),
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
) {
6806 walk_struct_fields(state
, type
, reg_offset
, mem_offset
, cb
, arg
);
6816 cb(state
, type
, reg_offset
, mem_offset
, arg
);
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
)
6838 basic
= type
->type
& TYPE_MASK
;
6839 /* Convert enums to ints */
6840 if (basic
== TYPE_ENUM
) {
6843 /* Convert bitfields to standard types */
6844 else if (basic
== TYPE_BITFIELD
) {
6845 if (type
->elements
<= SIZEOF_CHAR
) {
6848 else if (type
->elements
<= SIZEOF_SHORT
) {
6851 else if (type
->elements
<= SIZEOF_INT
) {
6854 else if (type
->elements
<= SIZEOF_LONG
) {
6857 if (!TYPE_SIGNED(type
->left
->type
)) {
6864 static unsigned int do_integral_promotion(unsigned int type
)
6866 if (TYPE_INTEGER(type
) && (TYPE_RANK(type
) < TYPE_RANK(TYPE_INT
))) {
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
)) {
6881 else if ((left
== TYPE_FLOAT
) || (right
== 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
) {
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
))) {
6898 else if (TYPE_SIGNED(right
) && (TYPE_RANK(right
) > TYPE_RANK(left
))) {
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
);
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
)
6914 /* Error if the basic types do not match */
6915 if ((left
->type
& TYPE_MASK
) != (right
->type
& TYPE_MASK
)) {
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
) {
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
)) {
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
);
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
)) {
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
)) {
6996 type
= left
->type
& TYPE_MASK
;
6997 qual_type
= (left
->type
& ~STOR_MASK
) | (right
->type
& ~STOR_MASK
);
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
);
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
) {
7016 /* test for union equality */
7017 else if (type
== TYPE_UNION
) {
7018 if (left
->type_ident
== right
->type_ident
) {
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
);
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
);
7037 result
= new_type(qual_type
, lf
, rf
);
7041 /* Nothing else is compatible */
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
)) {
7052 if ((left
->type
& TYPE_MASK
) == TYPE_JOIN
) {
7053 struct type
*member
, *mnext
;
7058 if ((member
->type
& TYPE_MASK
) == TYPE_OVERLAP
) {
7059 mnext
= member
->right
;
7060 member
= member
->left
;
7062 if (is_subset_type( member
, right
)) {
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
)) {
7077 result
= compatible_types(left
->left
, right
->left
);
7079 unsigned int qual_type
;
7080 qual_type
= (left
->type
& ~STOR_MASK
) | (right
->type
& ~STOR_MASK
);
7081 result
= new_type(qual_type
, result
, 0);
7086 static struct triple
*integral_promotion(
7087 struct compile_state
*state
, struct triple
*def
)
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);
7104 def
= triple(state
, OP_CONVERT
,
7105 new_type(int_type
, 0, 0), def
, 0);
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
) {
7153 return !!TYPE_SIGNED(type
->type
);
7155 static int is_compound_type(struct type
*type
)
7158 switch((type
->type
& TYPE_MASK
)) {
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
)
7177 if (def
->op
== OP_ADECL
) {
7180 else if ((def
->op
== OP_SDECL
) || (def
->op
== OP_DEREF
)) {
7183 else if (triple_is_part(state
, def
)) {
7184 in_reg
= is_in_reg(state
, MISC(def
, 0));
7187 internal_error(state
, def
, "unknown expr storage location");
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
)
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
)) {
7210 else if (triple_is_part(state
, def
)) {
7211 ret
= is_lvalue(state
, MISC(def
, 0));
7216 static void clvalue(struct compile_state
*state
, struct triple
*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
) {
7251 case TYPE_INT
: case TYPE_UINT
:
7252 case TYPE_LONG
: case TYPE_ULONG
:
7255 internal_error(state
, 0, "constant for unknown type");
7257 result
= triple(state
, OP_INTCONST
, type
, 0, 0);
7258 result
->u
.cval
= value
;
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
);
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
,
7290 int_const(state
, &ulong_type
, offset
));
7292 else if (expr
->op
== OP_BLOBCONST
) {
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
;
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
));
7312 internal_error(state
, part
, "unhandled part type");
7314 result
= do_mk_addr_expr(state
, expr
, type
, offset
);
7317 internal_error(state
, expr
, "cannot take address of expression");
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
) {
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
;
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);
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
;
7376 internal_error(state
, 0, "No field passed to deref_field");
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",
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
);
7393 /* Find the variable for the field I want. */
7394 result
= triple(state
, OP_DOT
, member
, expr
, 0);
7395 result
->u
.field
= field
;
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
;
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
);
7417 result
= triple(state
, OP_INDEX
, member
, expr
, 0);
7418 result
->u
.cval
= index
;
7423 static struct triple
*read_expr(struct compile_state
*state
, struct triple
*def
)
7429 #if DEBUG_ROMCC_WARNINGS
7430 #warning "CHECK_ME is this the only place I need to do lvalue conversions?"
7432 /* Transform lvalues into something we can read */
7433 def
= lvalue_conversion(state
, def
);
7434 if (!is_lvalue(state
, def
)) {
7437 if (is_in_reg(state
, def
)) {
7440 if (def
->op
== OP_SDECL
) {
7441 def
= mk_addr_expr(state
, def
, 0);
7442 def
= mk_deref_expr(state
, def
);
7446 def
= triple(state
, op
, def
->type
, def
, 0);
7447 if (def
->type
->type
& QUAL_VOLATILE
) {
7448 def
->id
|= TRIPLE_FLAG_VOLATILE
;
7453 int is_write_compatible(struct compile_state
*state
,
7454 struct type
*dest
, struct type
*rval
)
7457 /* Both operands have arithmetic type */
7458 if (TYPE_ARITHMETIC(dest
->type
) && TYPE_ARITHMETIC(rval
->type
)) {
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
))) {
7468 /* If both types are the same without qualifiers we are good */
7469 else if (equiv_ptrs(dest
, rval
)) {
7472 /* test for struct/union equality */
7473 else if (equiv_types(dest
, rval
)) {
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: ");
7486 fprintf(fp
,"\nrval: ");
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
)
7497 if (is_write_compatible(state
, dest
, rval
)) {
7500 else if (equiv_types(dest
, rval
)) {
7506 static struct triple
*write_expr(
7507 struct compile_state
*state
, struct triple
*dest
, struct triple
*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?");
7541 def
= triple(state
, OP_STORE
, dest
->type
, dest
, rval
);
7543 if (def
->type
->type
& QUAL_VOLATILE
) {
7544 def
->id
|= TRIPLE_FLAG_VOLATILE
;
7549 static struct triple
*init_expr(
7550 struct compile_state
*state
, struct triple
*dest
, struct triple
*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
);
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
);
7581 struct type
*arithmetic_result(
7582 struct compile_state
*state
, struct triple
*left
, struct triple
*right
)
7585 /* Sanity checks to ensure I am working with arithmetic types */
7586 arithmetic(state
, left
);
7587 arithmetic(state
, right
);
7589 do_arithmetic_conversion(
7590 get_basic_type(left
->type
),
7591 get_basic_type(right
->type
)),
7596 struct type
*ptr_arithmetic_result(
7597 struct compile_state
*state
, struct triple
*left
, struct triple
*right
)
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
)) {
7611 internal_error(state
, 0, "huh?");
7617 /* boolean helper function */
7619 static struct triple
*ltrue_expr(struct compile_state
*state
,
7620 struct triple
*expr
)
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 */
7629 expr
= triple(state
, OP_LTRUE
, &int_type
, expr
, 0);
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 */
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
)));
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);
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 */
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
));
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);
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
;
7709 left_type
= left
->type
->type
;
7710 right_type
= right
->type
->type
;
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
;
7738 error(state
, 0, "Incompatible types in conditional expression");
7740 /* Generate some intermediate triples */
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
)));
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);
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"
7775 if (!ins
|| (ins
->id
& TRIPLE_FLAG_FLATTENED
)) {
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 */
7789 struct triple
**expr
;
7790 expr
= triple_rhs(state
, ins
, 0);
7791 for(;expr
; expr
= triple_rhs(state
, ins
, expr
)) {
7794 depth
= expr_depth(state
, *expr
);
7795 if (depth
> count
) {
7804 static struct triple
*flatten_generic(
7805 struct compile_state
*state
, struct triple
*first
, struct triple
*ptr
,
7810 struct triple
**ins
;
7813 /* Only operations with just a rhs and a lhs should come here */
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
++) {
7828 for(j
= i
+ 1; j
< rhs
; j
++ ) {
7829 if (vector
[j
].depth
> vector
[max
].depth
) {
7834 struct rhs_vector tmp
;
7836 vector
[i
] = vector
[max
];
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
);
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
);
7860 static struct triple
*flatten_prog(
7861 struct compile_state
*state
, struct triple
*first
, struct triple
*ptr
)
7863 struct triple
*head
, *body
, *val
;
7868 release_triple(state
, head
);
7869 release_triple(state
, ptr
);
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?");
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
;
7912 /* Only flatten triples once */
7913 if (ptr
->id
& TRIPLE_FLAG_FLATTENED
) {
7918 RHS(ptr
, 0) = flatten(state
, first
, RHS(ptr
, 0));
7919 return MISC(ptr
, 0);
7922 ptr
= flatten_prog(state
, first
, ptr
);
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
);
7935 RHS(ptr
, 0) = flatten(state
, first
, RHS(ptr
, 0));
7936 use_triple(RHS(ptr
, 0), ptr
);
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
);
7944 use_triple(TARG(ptr
, 0), ptr
);
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
);
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
);
7969 RHS(ptr
, 0) = flatten(state
, first
, RHS(ptr
, 0));
7970 use_triple(RHS(ptr
, 0), ptr
);
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
);
7980 /* Since OP_DEREF is just a marker delete it when I flatten it */
7982 RHS(orig_ptr
, 0) = 0;
7983 free_triple(state
, orig_ptr
);
7986 if (RHS(ptr
, 0)->op
== OP_DEREF
) {
7987 struct triple
*base
, *left
;
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
);
7998 ptr
= flatten_part(state
, first
, ptr
);
8002 if (RHS(ptr
, 0)->op
== OP_DEREF
) {
8003 struct triple
*base
, *left
;
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
);
8014 ptr
= flatten_part(state
, first
, ptr
);
8018 ptr
= flatten_part(state
, first
, ptr
);
8019 use_triple(ptr
, MISC(ptr
, 0));
8022 MISC(ptr
, 0) = flatten(state
, first
, MISC(ptr
, 0));
8023 use_triple(MISC(ptr
, 0), ptr
);
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
;
8034 ptr
= flatten_generic(state
, first
, ptr
, 0);
8037 /* Flatten the easy cases we don't override */
8038 ptr
= flatten_generic(state
, first
, ptr
, 0);
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
;
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
;
8067 expr
= triple_rhs(state
, use
, 0);
8068 for(;expr
; expr
= triple_rhs(state
, use
, expr
)) {
8069 if (*expr
== orig
) {
8075 unuse_triple(orig
, use
);
8076 use_triple(new, use
);
8081 static int replace_lhs_use(struct compile_state
*state
,
8082 struct triple
*orig
, struct triple
*new, struct triple
*use
)
8084 struct triple
**expr
;
8087 expr
= triple_lhs(state
, use
, 0);
8088 for(;expr
; expr
= triple_lhs(state
, use
, expr
)) {
8089 if (*expr
== orig
) {
8095 unuse_triple(orig
, use
);
8096 use_triple(new, use
);
8101 static int replace_misc_use(struct compile_state
*state
,
8102 struct triple
*orig
, struct triple
*new, struct triple
*use
)
8104 struct triple
**expr
;
8107 expr
= triple_misc(state
, use
, 0);
8108 for(;expr
; expr
= triple_misc(state
, use
, expr
)) {
8109 if (*expr
== orig
) {
8115 unuse_triple(orig
, use
);
8116 use_triple(new, use
);
8121 static int replace_targ_use(struct compile_state
*state
,
8122 struct triple
*orig
, struct triple
*new, struct triple
*use
)
8124 struct triple
**expr
;
8127 expr
= triple_targ(state
, use
, 0);
8128 for(;expr
; expr
= triple_targ(state
, use
, expr
)) {
8129 if (*expr
== orig
) {
8135 unuse_triple(orig
, use
);
8136 use_triple(new, use
);
8141 static void replace_use(struct compile_state
*state
,
8142 struct triple
*orig
, struct triple
*new, struct triple
*use
)
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
);
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
8165 replace_use(state
, orig
, new, user
->member
);
8168 internal_error(state
, orig
, "used after propagate_use");
8174 * ===========================
8177 static struct triple
*mk_cast_expr(
8178 struct compile_state
*state
, struct type
*type
, struct triple
*expr
)
8181 def
= read_expr(state
, expr
);
8182 def
= triple(state
, OP_CONVERT
, type
, def
, 0);
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
)) {
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
;
8203 if (is_signed(right
->type
)) {
8204 ptr_math
= &long_type
;
8207 ptr_math
= &ulong_type
;
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
;
8230 if (is_signed(right
->type
)) {
8231 ptr_math
= &long_type
;
8234 ptr_math
= &ulong_type
;
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
)
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
),
8258 static struct triple
*mk_pre_dec_expr(
8259 struct compile_state
*state
, struct triple
*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
),
8269 static struct triple
*mk_post_inc_expr(
8270 struct compile_state
*state
, struct triple
*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)))
8281 static struct triple
*mk_post_dec_expr(
8282 struct compile_state
*state
, struct triple
*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)))
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
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
)
8328 if ((left
->op
== OP_UNKNOWNVAL
) || (right
->op
== OP_UNKNOWNVAL
)) {
8331 else if (!is_const(left
) || !is_const(right
)) {
8334 else if (left
->op
!= right
->op
) {
8337 else if (!equiv_types(left
->type
, right
->type
)) {
8344 if (left
->u
.cval
== right
->u
.cval
) {
8350 size_t lsize
, rsize
, bytes
;
8351 lsize
= size_of(state
, left
->type
);
8352 rsize
= size_of(state
, right
->type
);
8353 if (lsize
!= rsize
) {
8356 bytes
= bits_to_bytes(lsize
);
8357 if (memcmp(left
->u
.blob
, right
->u
.blob
, bytes
) == 0) {
8363 if ((MISC(left
, 0) == MISC(right
, 0)) &&
8364 (left
->u
.cval
== right
->u
.cval
)) {
8369 internal_error(state
, left
, "uknown constant type");
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
)
8392 for(i
= (sizeof(ulong_t
)*8) -1; i
>= 0; i
--) {
8405 static long_t
bsr(ulong_t value
)
8408 for(i
= (sizeof(ulong_t
)*8) -1; i
>= 0; i
--) {
8419 static long_t
bsf(ulong_t value
)
8422 for(i
= 0; i
< (sizeof(ulong_t
)*8); i
++) {
8433 static long_t
ilog2(ulong_t 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
;
8447 if (!is_const(ins
)) {
8450 value
= ins
->u
.cval
;
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
) {
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");
8482 if (!is_simple_const(rhs
)) {
8483 internal_error(state
, rhs
, "bad op to read_const");
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
)
8506 if (!is_const(left
) || !is_const(right
)) {
8507 internal_warning(state
, ins
, "non const passed to const_eq");
8510 else if (left
== right
) {
8513 else if (is_simple_const(left
) && is_simple_const(right
)) {
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
);
8525 internal_warning(state
, ins
, "incomparable constants passed to const_eq");
8532 int const_ucmp(struct compile_state
*state
, struct triple
*ins
,
8533 struct triple
*left
, struct triple
*right
)
8536 if (!is_const(left
) || !is_const(right
)) {
8537 internal_warning(state
, ins
, "non const past to const_ucmp");
8540 else if (left
== right
) {
8543 else if (is_simple_const(left
) && is_simple_const(right
)) {
8545 lval
= read_const(state
, ins
, left
);
8546 rval
= read_const(state
, ins
, right
);
8550 } else if (rval
> lval
) {
8554 else if ((left
->op
== OP_ADDRCONST
) &&
8555 (right
->op
== OP_ADDRCONST
) &&
8556 (MISC(left
, 0) == MISC(right
, 0))) {
8558 if (left
->u
.cval
> right
->u
.cval
) {
8560 } else if (left
->u
.cval
< right
->u
.cval
) {
8565 internal_warning(state
, ins
, "incomparable constants passed to const_ucmp");
8571 int const_scmp(struct compile_state
*state
, struct triple
*ins
,
8572 struct triple
*left
, struct triple
*right
)
8575 if (!is_const(left
) || !is_const(right
)) {
8576 internal_warning(state
, ins
, "non const past to ucmp_const");
8579 else if (left
== right
) {
8582 else if (is_simple_const(left
) && is_simple_const(right
)) {
8584 lval
= read_sconst(state
, ins
, left
);
8585 rval
= read_sconst(state
, ins
, right
);
8589 } else if (rval
> lval
) {
8594 internal_warning(state
, ins
, "incomparable constants passed to const_scmp");
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
)) {
8606 unuse_triple(*expr
, ins
);
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
);
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
);
8633 static void unuse_targ(struct compile_state
*state
, struct triple
*ins
)
8636 struct triple
**slot
;
8637 slot
= &TARG(ins
, 0);
8638 for(i
= 0; i
< ins
->targ
; i
++) {
8639 unuse_triple(slot
[i
], ins
);
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");
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
)) {
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
);
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
);
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
);
8720 internal_error(state
, ins
, "mkcopy type mismatch");
8722 block
= block_of_triple(state
, ins
);
8723 wipe_ins(state
, ins
);
8726 ins
->u
.block
= block
;
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",
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
;
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
);
8776 static struct triple
*decompose_with_tuple(struct compile_state
*state
,
8777 struct triple
*ins
, struct triple
*tuple
)
8779 struct triple
*next
;
8781 flatten(state
, next
, tuple
);
8782 #if DEBUG_DECOMPOSE_PRINT_TUPLES
8783 print_tuple(state
, ins
, tuple
);
8786 if (!is_compound_type(tuple
->type
) && (tuple
->lhs
> 0)) {
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
);
8796 propagate_use(state
, ins
, tuple
);
8797 release_triple(state
, ins
);
8802 static struct triple
*decompose_unknownval(struct compile_state
*state
,
8805 struct triple
*tuple
;
8808 #if DEBUG_DECOMPOSE_HIRES
8809 FILE *fp
= state
->dbgout
;
8810 fprintf(fp
, "unknown type: ");
8811 name_of(fp
, ins
->type
);
8815 get_occurrence(ins
->occurrence
);
8816 tuple
= alloc_triple(state
, OP_TUPLE
, ins
->type
, -1, -1,
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,
8827 LHS(tuple
, i
) = unknown
;
8829 return decompose_with_tuple(state
, ins
, tuple
);
8833 static struct triple
*decompose_read(struct compile_state
*state
,
8836 struct triple
*tuple
, *lval
;
8841 if (lval
->op
== OP_PIECE
) {
8844 get_occurrence(ins
->occurrence
);
8845 tuple
= alloc_triple(state
, OP_TUPLE
, lval
->type
, -1, -1,
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
);
8861 /* See if the piece is really a bitref */
8863 if (piece
->op
== OP_BITREF
) {
8865 piece
= RHS(bitref
, 0);
8868 get_occurrence(tuple
->occurrence
);
8869 read
= alloc_triple(state
, OP_READ
, piece
->type
, -1, -1,
8871 RHS(read
, 0) = piece
;
8874 struct triple
*extract
;
8876 if (is_signed(bitref
->type
->left
)) {
8881 get_occurrence(tuple
->occurrence
);
8882 extract
= alloc_triple(state
, op
, bitref
->type
, -1, -1,
8884 RHS(extract
, 0) = read
;
8885 extract
->u
.bitfield
.size
= bitref
->u
.bitfield
.size
;
8886 extract
->u
.bitfield
.offset
= bitref
->u
.bitfield
.offset
;
8891 LHS(tuple
, i
) = read
;
8893 return decompose_with_tuple(state
, ins
, tuple
);
8896 static struct triple
*decompose_write(struct compile_state
*state
,
8899 struct triple
*tuple
, *lval
, *val
;
8902 lval
= MISC(ins
, 0);
8904 get_occurrence(ins
->occurrence
);
8905 tuple
= alloc_triple(state
, OP_TUPLE
, ins
->type
, -1, -1,
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
);
8920 if ((i
== 0) && (tuple
->lhs
== 1) && (val
->lhs
== 0)) {
8925 internal_error(state
, ins
, "lhs size inconsistency?");
8930 /* See if the piece is really a bitref */
8932 if (piece
->op
== OP_BITREF
) {
8933 struct triple
*read
, *deposit
;
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,
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,
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 */
8956 get_occurrence(tuple
->occurrence
);
8957 write
= alloc_triple(state
, OP_WRITE
, piece
->type
, -1, -1,
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
,
8989 struct triple
*tuple
;
8990 struct decompose_load_info info
;
8992 if (!is_compound_type(ins
->type
)) {
8995 get_occurrence(ins
->occurrence
);
8996 tuple
= alloc_triple(state
, OP_TUPLE
, ins
->type
, -1, -1,
8999 info
.occurrence
= ins
->occurrence
;
9000 info
.lval
= RHS(ins
, 0);
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
;
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
,
9033 struct triple
*tuple
;
9034 struct decompose_store_info info
;
9036 if (!is_compound_type(ins
->type
)) {
9039 get_occurrence(ins
->occurrence
);
9040 tuple
= alloc_triple(state
, OP_TUPLE
, ins
->type
, -1, -1,
9043 info
.occurrence
= ins
->occurrence
;
9044 info
.lval
= RHS(ins
, 0);
9045 info
.val
= RHS(ins
, 1);
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
,
9055 struct triple
*tuple
, *lval
;
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: ");
9073 get_occurrence(ins
->occurrence
);
9074 tuple
= alloc_triple(state
, OP_TUPLE
, type
, -1, -1,
9077 if (((ins
->type
->type
& TYPE_MASK
) == TYPE_BITFIELD
) &&
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
);
9092 internal_error(state
, ins
, "bad reg_offset into def");
9095 internal_error(state
, ins
, "bad reg count from def");
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,
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
,
9122 struct triple
*tuple
, *lval
;
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: ");
9138 get_occurrence(ins
->occurrence
);
9139 tuple
= alloc_triple(state
, OP_TUPLE
, type
, -1, -1,
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
);
9151 internal_error(state
, ins
, "bad reg_offset into def");
9154 internal_error(state
, ins
, "bad reg count from def");
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.
9177 next
= decompose_unknownval(state
, ins
);
9181 next
= decompose_read(state
, ins
);
9185 next
= decompose_write(state
, ins
);
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.
9194 next
= decompose_load(state
, ins
);
9197 next
= decompose_store(state
, ins
);
9201 next
= decompose_dot(state
, ins
);
9204 next
= decompose_index(state
, ins
);
9208 #if DEBUG_DECOMPOSE_HIRES
9209 fprintf(fp
, "decompose next: %p\n", next
);
9211 fprintf(fp
, "next->op: %d %s\n",
9212 next
->op
, tops(next
->op
));
9213 /* High resolution debugging mode */
9214 print_triples(state
);
9216 } while (next
!= first
);
9218 /* Pass two remove the tuples.
9223 if (ins
->op
== OP_TUPLE
) {
9225 internal_error(state
, ins
, "tuple used");
9228 release_triple(state
, ins
);
9232 } while(ins
!= first
);
9236 if (ins
->op
== OP_BITREF
) {
9238 internal_error(state
, ins
, "bitref used");
9241 release_triple(state
, ins
);
9245 } while(ins
!= first
);
9247 /* Pass three verify the state and set ->id to 0.
9253 ins
->id
&= ~TRIPLE_FLAG_FLATTENED
;
9254 if (triple_stores_block(state
, ins
)) {
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
)
9283 static void simplify_smul(struct compile_state
*state
, struct triple
*ins
)
9285 if (is_const(RHS(ins
, 0)) && !is_const(RHS(ins
, 1))) {
9288 RHS(ins
, 0) = RHS(ins
, 1);
9291 if (is_const(RHS(ins
, 0)) && is_const(RHS(ins
, 1))) {
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))) {
9305 val
= int_const(state
, ins
->type
, tlog2(RHS(ins
, 1)));
9307 insert_triple(state
, state
->global_pool
, val
);
9308 unuse_triple(RHS(ins
, 1), ins
);
9309 use_triple(val
, ins
);
9314 static void simplify_umul(struct compile_state
*state
, struct triple
*ins
)
9316 if (is_const(RHS(ins
, 0)) && !is_const(RHS(ins
, 1))) {
9319 RHS(ins
, 0) = RHS(ins
, 1);
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))) {
9336 val
= int_const(state
, ins
->type
, tlog2(RHS(ins
, 1)));
9338 insert_triple(state
, state
->global_pool
, val
);
9339 unuse_triple(RHS(ins
, 1), ins
);
9340 use_triple(val
, ins
);
9345 static void simplify_sdiv(struct compile_state
*state
, struct triple
*ins
)
9347 if (is_const(RHS(ins
, 0)) && is_const(RHS(ins
, 1))) {
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))) {
9364 val
= int_const(state
, ins
->type
, tlog2(RHS(ins
, 1)));
9366 insert_triple(state
, state
->global_pool
, val
);
9367 unuse_triple(RHS(ins
, 1), ins
);
9368 use_triple(val
, ins
);
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))) {
9392 val
= int_const(state
, ins
->type
, tlog2(RHS(ins
, 1)));
9394 insert_triple(state
, state
->global_pool
, val
);
9395 unuse_triple(RHS(ins
, 1), ins
);
9396 use_triple(val
, ins
);
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))) {
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))) {
9420 val
= int_const(state
, ins
->type
, RHS(ins
, 1)->u
.cval
- 1);
9422 insert_triple(state
, state
->global_pool
, val
);
9423 unuse_triple(RHS(ins
, 1), ins
);
9424 use_triple(val
, ins
);
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))) {
9448 val
= int_const(state
, ins
->type
, RHS(ins
, 1)->u
.cval
- 1);
9450 insert_triple(state
, state
->global_pool
, val
);
9451 unuse_triple(RHS(ins
, 1), ins
);
9452 use_triple(val
, ins
);
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))) {
9463 RHS(ins
, 0) = RHS(ins
, 1);
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
);
9482 internal_warning(state
, ins
, "Optimize me!");
9485 else if (is_const(RHS(ins
, 0)) && !is_const(RHS(ins
, 1))) {
9488 RHS(ins
, 1) = RHS(ins
, 0);
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
);
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))) {
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))) {
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))) {
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))) {
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
;
9571 right
= RHS(ins
, 1);
9573 if (is_simple_const(left
) && is_simple_const(right
)) {
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
;
9588 right
= RHS(ins
, 1);
9590 if (is_simple_const(left
) && is_simple_const(right
)) {
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
);
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
);
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))) {
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))) {
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
;
9651 right
= RHS(ins
, 1);
9653 if (is_const(left
) && is_const(right
)) {
9655 val
= const_eq(state
, ins
, left
, right
);
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
;
9669 right
= RHS(ins
, 1);
9671 if (is_const(left
) && is_const(right
)) {
9673 val
= const_eq(state
, ins
, left
, right
);
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
;
9687 right
= RHS(ins
, 1);
9689 if (is_const(left
) && is_const(right
)) {
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
;
9705 right
= RHS(ins
, 1);
9707 if (is_const(left
) && is_const(right
)) {
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
;
9726 right
= RHS(ins
, 1);
9728 if (is_const(left
) && is_const(right
)) {
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
;
9744 right
= RHS(ins
, 1);
9746 if (is_const(left
) && is_const(right
)) {
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
;
9766 right
= RHS(ins
, 1);
9768 if (is_const(left
) && is_const(right
)) {
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
;
9784 right
= RHS(ins
, 1);
9786 if (is_const(left
) && is_const(right
)) {
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
;
9805 right
= RHS(ins
, 1);
9807 if (is_const(left
) && is_const(right
)) {
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
;
9823 right
= RHS(ins
, 1);
9825 if (is_const(left
) && is_const(right
)) {
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
)
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)) {
9852 /* Invert a boolean operation */
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;
9871 mkcopy(state
, ins
, rhs
);
9876 static void simplify_ltrue (struct compile_state
*state
, struct triple
*ins
)
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.
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
;
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
);
9914 end
+= bits_to_bytes(size_of(state
, sdecl
->type
));
9916 src
+= addr
->u
.cval
;
9919 error(state
, ins
, "Load address out of bounds");
9922 memset(buffer
, 0, sizeof(buffer
));
9923 memcpy(buffer
, src
, bits_to_bytes(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;
9931 internal_error(state
, ins
, "mem_size: %d not handled",
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))) {
9945 val
= read_const(state
, ins
, RHS(ins
, 0));
9947 mask
<<= ins
->u
.bitfield
.size
;
9949 val
>>= ins
->u
.bitfield
.offset
;
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))) {
9961 val
= read_const(state
, ins
, RHS(ins
, 0));
9963 mask
<<= ins
->u
.bitfield
.size
;
9965 val
>>= ins
->u
.bitfield
.offset
;
9967 val
<<= (SIZEOF_LONG
- ins
->u
.bitfield
.size
);
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))) {
9979 targ
= read_const(state
, ins
, RHS(ins
, 0));
9980 val
= read_const(state
, ins
, RHS(ins
, 1));
9982 mask
<<= ins
->u
.bitfield
.size
;
9984 mask
<<= ins
->u
.bitfield
.offset
;
9986 val
<<= ins
->u
.bitfield
.offset
;
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 */
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
;
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
) {
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
)) {
10024 mask
<<= size_of(state
, ins
->type
);
10028 /* Ensure I am properly sign extended */
10029 if (size_of(state
, right
->type
) < size_of(state
, ins
->type
) &&
10030 is_signed(right
->type
)) {
10033 shift
= SIZEOF_LONG
- size_of(state
, right
->type
);
10037 left
= (ulong_t
)val
;
10039 mkconst(state
, ins
, left
);
10043 internal_error(state
, ins
, "uknown constant");
10049 static int phi_present(struct block
*block
)
10051 struct triple
*ptr
;
10055 ptr
= block
->first
;
10057 if (ptr
->op
== OP_PHI
) {
10061 } while(ptr
!= block
->last
);
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.
10072 struct block_set
*edge
;
10073 for(edge
= block
->edges
; edge
; edge
= edge
->next
) {
10074 if (phi_present(edge
->member
)) {
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
10090 while(triple_is_structural(state
, targ
) &&
10091 (targ
->next
!= targ
) && (targ
->next
!= state
->first
)) {
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
10116 * Also only do this a limited number of times so
10117 * we don't get into an infinite loop.
10121 struct triple
*targ
;
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
);
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
;
10140 value
= read_const(state
, ins
, RHS(ins
, 0));
10141 unuse_triple(RHS(ins
, 0), ins
);
10142 targ
= TARG(ins
, 0);
10145 ins
->op
= OP_BRANCH
;
10147 unuse_triple(ins
->next
, ins
);
10148 TARG(ins
, 0) = targ
;
10151 unuse_triple(targ
, ins
);
10152 TARG(ins
, 0) = ins
->next
;
10156 /* If we have a branch to the next instruction,
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
);
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
)) {
10182 if (ins
->use
== 0) {
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
;
10193 for(user
= ins
->use
; user
; user
= next
) {
10194 struct triple
*use
, **expr
;
10196 use
= user
->member
;
10197 expr
= triple_targ(state
, use
, 0);
10198 for(;expr
; expr
= triple_targ(state
, use
, expr
)) {
10199 if (*expr
== ins
) {
10201 unuse_triple(ins
, use
);
10202 use_triple(ins
->prev
, 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
;
10220 slot
= &RHS(ins
, 0);
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
++) {
10230 !is_simple_const(slot
[i
]) ||
10231 !equiv_types(slot
[0]->type
, slot
[i
]->type
) ||
10232 (cvalue
!= read_const(state
, ins
, slot
[i
]))) {
10237 mkconst(state
, ins
, cvalue
);
10242 /* See if all of rhs members of a phi are the same */
10244 for(i
= 1; i
< zrhs
; i
++) {
10245 if (slot
[i
] != value
) {
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
);
10265 static void simplify_bsf(struct compile_state
*state
, struct triple
*ins
)
10267 if (is_simple_const(RHS(ins
, 0))) {
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))) {
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
{
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
);
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
);
10392 static void simplify(struct compile_state
*state
, struct triple
*ins
)
10395 simplify_t do_simplify
;
10396 if (ins
== &unknown_triple
) {
10397 internal_error(state
, ins
, "simplifying the unknown triple?");
10402 if ((op
< 0) || (op
>= sizeof(table_simplify
)/sizeof(table_simplify
[0]))) {
10406 do_simplify
= table_simplify
[op
].func
;
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",
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
)) {
10433 first
= state
->first
;
10436 simplify(state
, ins
);
10438 } while(ins
!= first
->prev
);
10441 simplify(state
, ins
);
10443 }while(ins
!= first
);
10444 rebuild_ssa_form(state
);
10446 print_blocks(state
, __func__
, state
->dbgout
);
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
;
10466 /* Dummy file state to get debug handling right */
10467 memset(&file
, 0, sizeof(file
));
10468 file
.basename
= "<built-in>";
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
*);
10493 *next
= new_type(TYPE_PRODUCT
, *next
, atype
);
10494 next
= &((*next
)->right
);
10498 *next
= &void_type
;
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
;
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
;
10552 insert_triple(state
, state
->functions
, def
);
10554 if (state
->compiler
->debug
& DEBUG_INLINE
) {
10555 FILE *fp
= state
->dbgout
;
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
;
10578 result
= new_type(TYPE_PRODUCT
, result
, rest
);
10583 static struct type
*register_builtin_type(struct compile_state
*state
,
10584 const char *name
, struct type
*type
)
10586 struct hash_entry
*ident
;
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
) {
10599 field
= field
->right
;
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
;
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
,
10642 register_builtin_function(state
, "__builtin_inw", OP_INW
, &ushort_type
,
10644 register_builtin_function(state
, "__builtin_inl", OP_INL
, &uint_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
,
10656 register_builtin_function(state
, "__builtin_bsr", OP_BSR
, &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
,
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
,
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
);
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
;
10706 while((param
->type
& TYPE_MASK
) == TYPE_PRODUCT
) {
10708 param
= param
->right
;
10710 if ((param
->type
& TYPE_MASK
) != TYPE_VOID
) {
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
));
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
);
10737 static struct triple
*character_constant(struct compile_state
*state
)
10739 struct triple
*def
;
10741 const signed char *str
, *end
;
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
);
10753 error(state
, 0, "multibyte character constant not supported");
10755 def
= int_const(state
, &char_type
, (ulong_t
)((long_t
)c
));
10759 static struct triple
*string_constant(struct compile_state
*state
)
10761 struct triple
*def
;
10764 const signed char *str
, *end
;
10765 signed char *buf
, *ptr
;
10769 type
= new_type(TYPE_ARRAY
, &char_type
, 0);
10770 type
->elements
= 0;
10771 /* The while loop handles string concatenation */
10773 tk
= eat(state
, TOK_LIT_STRING
);
10774 str
= (signed char *)tk
->val
.str
+ 1;
10775 str_len
= tk
->str_len
- 2;
10777 error(state
, 0, "negative string constant length");
10779 /* ignore empty string tokens */
10780 if ('"' == *str
&& 0 == str
[1])
10782 end
= str
+ str_len
;
10784 buf
= xmalloc(type
->elements
+ str_len
+ 1, "string_constant");
10785 memcpy(buf
, ptr
, type
->elements
);
10787 ptr
= buf
+ type
->elements
;
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. */
10798 buf
= xmalloc(1, "string_constant");
10803 type
->elements
+= 1;
10804 def
= triple(state
, OP_BLOBCONST
, type
, 0, 0);
10811 static struct triple
*integer_constant(struct compile_state
*state
)
10813 struct triple
*def
;
10820 tk
= eat(state
, TOK_LIT_INT
);
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");
10828 if ((*end
== 'u') || (*end
== 'U')) {
10832 if ((*end
== 'l') || (*end
== 'L')) {
10836 if ((*end
== 'u') || (*end
== 'U')) {
10841 error(state
, 0, "Junk at end of integer constant");
10844 type
= &ulong_type
;
10848 if (!decimal
&& (val
> LONG_T_MAX
)) {
10849 type
= &ulong_type
;
10854 if (val
> UINT_T_MAX
) {
10855 type
= &ulong_type
;
10860 if (!decimal
&& (val
> INT_T_MAX
) && (val
<= UINT_T_MAX
)) {
10863 else if (!decimal
&& (val
> LONG_T_MAX
)) {
10864 type
= &ulong_type
;
10866 else if (val
> INT_T_MAX
) {
10870 def
= int_const(state
, type
, val
);
10874 static struct triple
*primary_expr(struct compile_state
*state
)
10876 struct triple
*def
;
10882 struct hash_entry
*ident
;
10883 /* Here ident is either:
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
;
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
;
10907 struct hash_entry
*ident
;
10908 ident
= eat(state
, TOK_MIDENT
)->ident
;
10909 warning(state
, 0, "Replacing undefined macro: %s with 0",
10911 def
= int_const(state
, &int_type
, 0);
10915 eat(state
, TOK_LPAREN
);
10917 eat(state
, TOK_RPAREN
);
10920 def
= integer_constant(state
);
10922 case TOK_LIT_FLOAT
:
10923 eat(state
, TOK_LIT_FLOAT
);
10924 error(state
, 0, "Floating point constants not supported");
10929 def
= character_constant(state
);
10931 case TOK_LIT_STRING
:
10932 def
= string_constant(state
);
10936 error(state
, 0, "Unexpected token: %s\n", tokens
[tok
]);
10941 static struct triple
*postfix_expr(struct compile_state
*state
)
10943 struct triple
*def
;
10945 def
= primary_expr(state
);
10947 struct triple
*left
;
10951 switch((tok
= peek(state
))) {
10953 eat(state
, TOK_LBRACKET
);
10954 def
= mk_subscript_expr(state
, left
, expr(state
));
10955 eat(state
, TOK_RBRACKET
);
10958 def
= call_expr(state
, def
);
10962 struct hash_entry
*field
;
10963 eat(state
, TOK_DOT
);
10964 field
= eat(state
, TOK_IDENT
)->ident
;
10965 def
= deref_field(state
, def
, field
);
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
);
10978 eat(state
, TOK_PLUSPLUS
);
10979 def
= mk_post_inc_expr(state
, left
);
10981 case TOK_MINUSMINUS
:
10982 eat(state
, TOK_MINUSMINUS
);
10983 def
= mk_post_dec_expr(state
, left
);
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
;
10999 switch((tok
= peek(state
))) {
11001 eat(state
, TOK_PLUSPLUS
);
11002 def
= mk_pre_inc_expr(state
, unary_expr(state
));
11004 case TOK_MINUSMINUS
:
11005 eat(state
, TOK_MINUSMINUS
);
11006 def
= mk_pre_dec_expr(state
, unary_expr(state
));
11009 eat(state
, TOK_AND
);
11010 def
= mk_addr_expr(state
, cast_expr(state
), 0);
11013 eat(state
, TOK_STAR
);
11014 def
= mk_deref_expr(state
, read_expr(state
, cast_expr(state
)));
11017 eat(state
, TOK_PLUS
);
11018 right
= read_expr(state
, cast_expr(state
));
11019 arithmetic(state
, right
);
11020 def
= integral_promotion(state
, right
);
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);
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);
11037 eat(state
, TOK_BANG
);
11038 right
= read_expr(state
, cast_expr(state
));
11039 bool(state
, right
);
11040 def
= lfalse_expr(state
, right
);
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
);
11055 struct triple
*expr
;
11056 expr
= unary_expr(state
);
11058 release_expr(state
, expr
);
11060 def
= int_const(state
, &ulong_type
, size_of_in_bytes(state
, type
));
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
);
11076 struct triple
*expr
;
11077 expr
= unary_expr(state
);
11079 release_expr(state
, expr
);
11081 def
= int_const(state
, &ulong_type
, align_of_in_bytes(state
, type
));
11086 /* We only come here if we are called from the preprocessor */
11087 struct hash_entry
*ident
;
11089 eat(state
, TOK_MDEFINED
);
11091 if (pp_peek(state
) == TOK_LPAREN
) {
11092 pp_eat(state
, TOK_LPAREN
);
11095 ident
= pp_eat(state
, TOK_MIDENT
)->ident
;
11097 eat(state
, TOK_RPAREN
);
11099 def
= int_const(state
, &int_type
, ident
->sym_define
!= 0);
11103 def
= postfix_expr(state
);
11109 static struct triple
*cast_expr(struct compile_state
*state
)
11111 struct triple
*def
;
11113 tok1
= peek(state
);
11114 tok2
= peek2(state
);
11115 if ((tok1
== TOK_LPAREN
) && istype(tok2
)) {
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
));
11123 def
= unary_expr(state
);
11128 static struct triple
*mult_expr(struct compile_state
*state
)
11130 struct triple
*def
;
11132 def
= cast_expr(state
);
11134 struct triple
*left
, *right
;
11135 struct type
*result_type
;
11143 left
= read_expr(state
, def
);
11144 arithmetic(state
, left
);
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
);
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
);
11169 static struct triple
*add_expr(struct compile_state
*state
)
11171 struct triple
*def
;
11173 def
= mult_expr(state
);
11176 switch( peek(state
)) {
11178 eat(state
, TOK_PLUS
);
11179 def
= mk_add_expr(state
, def
, mult_expr(state
));
11182 eat(state
, TOK_MINUS
);
11183 def
= mk_sub_expr(state
, def
, mult_expr(state
));
11193 static struct triple
*shift_expr(struct compile_state
*state
)
11195 struct triple
*def
;
11197 def
= add_expr(state
);
11199 struct triple
*left
, *right
;
11202 switch((tok
= peek(state
))) {
11205 left
= read_expr(state
, def
);
11206 integral(state
, left
);
11207 left
= integral_promotion(state
, left
);
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
);
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"
11233 struct triple
*def
;
11235 def
= shift_expr(state
);
11237 struct triple
*left
, *right
;
11238 struct type
*arg_type
;
11241 switch((tok
= peek(state
))) {
11246 left
= read_expr(state
, def
);
11247 arithmetic(state
, left
);
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
);
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
);
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"
11279 struct triple
*def
;
11281 def
= relational_expr(state
);
11283 struct triple
*left
, *right
;
11286 switch((tok
= peek(state
))) {
11289 left
= read_expr(state
, def
);
11290 arithmetic(state
, left
);
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
);
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
);
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
);
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
);
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
);
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
));
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
);
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
));
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
;
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
);
11416 struct triple
*val
;
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
)) {
11442 /* If we don't start out as a constant simplify into one */
11443 struct triple
*head
, *ptr
;
11444 struct cv_triple
*cv
;
11446 head
= label(state
); /* dummy initial triple */
11447 flatten(state
, head
, expr
);
11449 for(ptr
= head
->next
; ptr
!= head
; ptr
= ptr
->next
) {
11452 cv
= xcmalloc(sizeof(struct cv_triple
)*count
, "const value vector");
11454 for(ptr
= head
->next
; ptr
!= head
; ptr
= ptr
->next
) {
11456 cv
[i
].id
= ptr
->id
;
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",
11468 else if (ptr
->op
== OP_LIST
) {
11470 else if (triple_is_structural(state
, ptr
)) {
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) {
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
));
11503 else if (ptr
->op
== OP_READ
) {
11504 set_cv(state
, cv
, ptr
,
11506 get_cv(state
, cv
, RHS(ptr
, 0))));
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
)) {
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
);
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
++) {
11536 free_triple(state
, cv
[i
].val
);
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");
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
;
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
);
11581 switch((tok
= peek(state
))) {
11583 lvalue(state
, left
);
11584 eat(state
, TOK_EQ
);
11585 def
= write_expr(state
, left
,
11586 read_expr(state
, assignment_expr(state
)));
11591 lvalue(state
, left
);
11592 arithmetic(state
, left
);
11594 right
= read_expr(state
, assignment_expr(state
));
11595 arithmetic(state
, right
);
11597 sign
= is_signed(left
->type
);
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
));
11609 lvalue(state
, left
);
11610 eat(state
, TOK_PLUSEQ
);
11611 def
= write_expr(state
, left
,
11612 mk_add_expr(state
, left
, assignment_expr(state
)));
11615 lvalue(state
, left
);
11616 eat(state
, TOK_MINUSEQ
);
11617 def
= write_expr(state
, left
,
11618 mk_sub_expr(state
, left
, assignment_expr(state
)));
11625 lvalue(state
, left
);
11626 integral(state
, left
);
11628 right
= read_expr(state
, assignment_expr(state
));
11629 integral(state
, right
);
11630 right
= integral_promotion(state
, right
);
11631 sign
= is_signed(left
->type
);
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
));
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);
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
);
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
);
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
);
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
);
11735 jmp1
= branch(state
, label3
, 0);
11736 jmp2
= branch(state
, label1
, test
);
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 */
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
);
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 */
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 */
11817 /* Eat the rest of the loop */
11818 eat(state
, TOK_WHILE
);
11819 eat(state
, TOK_LPAREN
);
11820 test
= read_expr(state
, expr(state
));
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
;
11837 eat(state
, TOK_RETURN
);
11839 #if DEBUG_ROMCC_WARNINGS
11840 #warning "FIXME implement a more general excess branch elimination"
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
;
11859 /* If needed generate a jump instruction */
11861 jmp
= branch(state
, dest
, 0);
11863 /* If needed generate an assignment instruction */
11865 mv
= write_expr(state
, deref_index(state
, var
, 1), val
);
11867 /* Now put the code together */
11869 flatten(state
, first
, mv
);
11870 flatten(state
, first
, 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
);
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 */
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
) {
12006 if (RHS(ptr
, 1)->u
.cval
== cvalue
->u
.cval
) {
12007 error(state
, 0, "duplicate case %d statement",
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
;
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
;
12071 eat(state
, TOK_ASM
);
12072 /* For now ignore the qualifiers */
12073 switch(peek(state
)) {
12075 eat(state
, TOK_CONST
);
12078 eat(state
, TOK_VOLATILE
);
12079 flags
|= TRIPLE_FLAG_VOLATILE
;
12082 eat(state
, TOK_LPAREN
);
12083 asm_str
= string_constant(state
);
12086 out
= in
= clobbers
= 0;
12088 if ((colons
== 0) && (peek(state
) == TOK_COLON
)) {
12089 eat(state
, TOK_COLON
);
12091 more
= (peek(state
) == TOK_LIT_STRING
);
12093 struct triple
*var
;
12094 struct triple
*constraint
;
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
);
12121 if ((colons
== 1) && (peek(state
) == TOK_COLON
)) {
12122 eat(state
, TOK_COLON
);
12124 more
= (peek(state
) == TOK_LIT_STRING
);
12126 struct triple
*val
;
12127 struct triple
*constraint
;
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')) {
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
);
12157 if ((colons
== 2) && (peek(state
) == TOK_COLON
)) {
12158 eat(state
, TOK_COLON
);
12160 more
= (peek(state
) == TOK_LIT_STRING
);
12162 struct triple
*clobber
;
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
);
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
;
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
;
12206 constraint
= in_param
[i
].constraint
;
12207 str
= constraint
->u
.blob
;
12208 if (digitp(str
[0]) && str
[1] == '\0') {
12209 struct reg_info cinfo
;
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
;
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
++) {
12238 struct triple
*piece
;
12240 type
= out_param
[i
].expr
->type
;
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
) {
12249 else if (size
>= SIZEOF_SHORT
) {
12250 type
= &ushort_type
;
12253 type
= &uchar_type
;
12256 piece
= triple(state
, OP_PIECE
, type
, def
, 0);
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
)
12294 case TOK_TYPE_NAME
: /* typedef name */
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
);
12311 eat(state
, TOK_RBRACE
);
12314 static void statement(struct compile_state
*state
, struct triple
*first
)
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
);
12365 expr_statement(state
, first
);
12369 static struct type
*param_decl(struct compile_state
*state
)
12372 struct hash_entry
*ident
;
12373 /* Cheat so the declarator will know we are not global */
12374 start_scope(state
);
12376 type
= decl_specifiers(state
);
12377 type
= declarator(state
, type
, &ident
, 0);
12378 type
->field_ident
= ident
;
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");
12396 *next
= new_type(TYPE_PRODUCT
, *next
, param_decl(state
));
12397 next
= &((*next
)->right
);
12404 static struct type
*type_name(struct compile_state
*state
)
12407 type
= specifier_qualifier_list(state
);
12408 /* abstract-declarator (may consume no tokens) */
12409 type
= declarator(state
, type
, 0, 0);
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
;
12421 arrays_complete(state
, type
);
12422 switch(peek(state
)) {
12424 ident
= eat(state
, TOK_IDENT
)->ident
;
12426 error(state
, 0, "Unexpected identifier found");
12428 /* The name of what we are declaring */
12432 eat(state
, TOK_LPAREN
);
12433 outer
= declarator(state
, type
, pident
, need_ident
);
12434 eat(state
, TOK_RPAREN
);
12438 error(state
, 0, "Identifier expected");
12444 arrays_complete(state
, type
);
12445 switch(peek(state
)) {
12447 eat(state
, TOK_LPAREN
);
12448 type
= param_type_list(state
, type
);
12449 eat(state
, TOK_RPAREN
);
12453 unsigned int qualifiers
;
12454 struct triple
*value
;
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);
12466 type
->elements
= value
->u
.cval
;
12467 free_triple(state
, value
);
12469 type
->elements
= ELEMENT_COUNT_UNSPECIFIED
;
12480 struct type
*inner
;
12481 arrays_complete(state
, type
);
12483 for(inner
= outer
; inner
->left
; inner
= inner
->left
)
12485 inner
->left
= 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
);
12503 static struct type
*typedef_name(
12504 struct compile_state
*state
, unsigned int specifiers
)
12506 struct hash_entry
*ident
;
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
);
12518 static struct type
*enum_specifier(
12519 struct compile_state
*state
, unsigned int spec
)
12521 struct hash_entry
*ident
;
12524 struct type
*enum_type
;
12527 eat(state
, TOK_ENUM
);
12529 if ((tok
== TOK_IDENT
) || (tok
== TOK_ENUM_CONST
) || (tok
== TOK_TYPE_NAME
)) {
12530 ident
= eat(state
, tok
)->ident
;
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
;
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",
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
;
12561 next
= &entry
->right
;
12563 if (peek(state
) == TOK_COMMA
) {
12564 eat(state
, TOK_COMMA
);
12566 } while(peek(state
) != TOK_RBRACE
);
12567 eat(state
, TOK_RBRACE
);
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
);
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
;
12605 type
= clone_type(0, 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
;
12620 switch(peek(state
)) {
12622 eat(state
, TOK_STRUCT
);
12623 type_main
= TYPE_STRUCT
;
12624 type_join
= TYPE_PRODUCT
;
12627 eat(state
, TOK_UNION
);
12628 type_main
= TYPE_UNION
;
12629 type_join
= TYPE_OVERLAP
;
12632 eat(state
, TOK_STRUCT
);
12633 type_main
= TYPE_STRUCT
;
12634 type_join
= TYPE_PRODUCT
;
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
)) {
12643 struct type
**next
;
12645 eat(state
, TOK_LBRACE
);
12646 next
= &struct_type
;
12648 struct type
*base_type
;
12650 base_type
= specifier_qualifier_list(state
);
12653 struct hash_entry
*fident
;
12655 type
= struct_declarator(state
, base_type
, &fident
);
12657 if (peek(state
) == TOK_COMMA
) {
12659 eat(state
, TOK_COMMA
);
12661 type
->field_ident
= fident
;
12663 *next
= new_type(type_join
, *next
, type
);
12664 next
= &((*next
)->right
);
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
;
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",
12689 return struct_type
;
12692 static unsigned int storage_class_specifier_opt(struct compile_state
*state
)
12694 unsigned int specifiers
;
12695 switch(peek(state
)) {
12697 eat(state
, TOK_AUTO
);
12698 specifiers
= STOR_AUTO
;
12701 eat(state
, TOK_REGISTER
);
12702 specifiers
= STOR_REGISTER
;
12705 eat(state
, TOK_STATIC
);
12706 specifiers
= STOR_STATIC
;
12709 eat(state
, TOK_EXTERN
);
12710 specifiers
= STOR_EXTERN
;
12713 eat(state
, TOK_TYPEDEF
);
12714 specifiers
= STOR_TYPEDEF
;
12717 if (state
->scope_depth
<= GLOBAL_SCOPE_DEPTH
) {
12718 specifiers
= STOR_LOCAL
;
12721 specifiers
= STOR_AUTO
;
12727 static unsigned int function_specifier_opt(struct compile_state
*state
)
12729 /* Ignore the inline keyword */
12730 unsigned int specifiers
;
12732 switch(peek(state
)) {
12734 eat(state
, TOK_INLINE
);
12735 specifiers
= STOR_INLINE
;
12740 static unsigned int attrib(struct compile_state
*state
, unsigned int attributes
)
12742 int tok
= peek(state
);
12746 /* The empty attribute ignore it */
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?)
12777 error(state
, 0, "Unknown attribute:%s", ident
->name
);
12782 error(state
, 0, "Unexpected token: %s\n", tokens
[tok
]);
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
);
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
);
12811 static unsigned int type_qualifiers(struct compile_state
*state
)
12813 unsigned int specifiers
;
12816 specifiers
= QUAL_NONE
;
12818 switch(peek(state
)) {
12820 eat(state
, TOK_CONST
);
12821 specifiers
|= QUAL_CONST
;
12824 eat(state
, TOK_VOLATILE
);
12825 specifiers
|= QUAL_VOLATILE
;
12828 eat(state
, TOK_RESTRICT
);
12829 specifiers
|= QUAL_RESTRICT
;
12839 static struct type
*type_specifier(
12840 struct compile_state
*state
, unsigned int spec
)
12845 switch((tok
= peek(state
))) {
12847 eat(state
, TOK_VOID
);
12848 type
= new_type(TYPE_VOID
| spec
, 0, 0);
12851 eat(state
, TOK_CHAR
);
12852 type
= new_type(TYPE_CHAR
| spec
, 0, 0);
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);
12862 eat(state
, TOK_INT
);
12863 type
= new_type(TYPE_INT
| spec
, 0, 0);
12866 eat(state
, TOK_LONG
);
12867 switch(peek(state
)) {
12869 eat(state
, TOK_LONG
);
12870 error(state
, 0, "long long not supported");
12873 eat(state
, TOK_DOUBLE
);
12874 error(state
, 0, "long double not supported");
12877 eat(state
, TOK_INT
);
12878 type
= new_type(TYPE_LONG
| spec
, 0, 0);
12881 type
= new_type(TYPE_LONG
| spec
, 0, 0);
12886 eat(state
, TOK_FLOAT
);
12887 error(state
, 0, "type float not supported");
12890 eat(state
, TOK_DOUBLE
);
12891 error(state
, 0, "type double not supported");
12894 eat(state
, TOK_SIGNED
);
12895 switch(peek(state
)) {
12897 eat(state
, TOK_LONG
);
12898 switch(peek(state
)) {
12900 eat(state
, TOK_LONG
);
12901 error(state
, 0, "type long long not supported");
12904 eat(state
, TOK_INT
);
12905 type
= new_type(TYPE_LONG
| spec
, 0, 0);
12908 type
= new_type(TYPE_LONG
| spec
, 0, 0);
12913 eat(state
, TOK_INT
);
12914 type
= new_type(TYPE_INT
| spec
, 0, 0);
12917 eat(state
, TOK_SHORT
);
12918 type
= new_type(TYPE_SHORT
| spec
, 0, 0);
12921 eat(state
, TOK_CHAR
);
12922 type
= new_type(TYPE_CHAR
| spec
, 0, 0);
12925 type
= new_type(TYPE_INT
| spec
, 0, 0);
12930 eat(state
, TOK_UNSIGNED
);
12931 switch(peek(state
)) {
12933 eat(state
, TOK_LONG
);
12934 switch(peek(state
)) {
12936 eat(state
, TOK_LONG
);
12937 error(state
, 0, "unsigned long long not supported");
12940 eat(state
, TOK_INT
);
12941 type
= new_type(TYPE_ULONG
| spec
, 0, 0);
12944 type
= new_type(TYPE_ULONG
| spec
, 0, 0);
12949 eat(state
, TOK_INT
);
12950 type
= new_type(TYPE_UINT
| spec
, 0, 0);
12953 eat(state
, TOK_SHORT
);
12954 type
= new_type(TYPE_USHORT
| spec
, 0, 0);
12957 eat(state
, TOK_CHAR
);
12958 type
= new_type(TYPE_UCHAR
| spec
, 0, 0);
12961 type
= new_type(TYPE_UINT
| spec
, 0, 0);
12965 /* struct or union specifier */
12968 type
= struct_or_union_specifier(state
, spec
);
12970 /* enum-spefifier */
12972 type
= enum_specifier(state
, spec
);
12975 case TOK_TYPE_NAME
:
12976 type
= typedef_name(state
, spec
);
12979 error(state
, 0, "bad type specifier %s",
12986 static int istype(int tok
)
13004 case TOK_TYPE_NAME
:
13012 static struct type
*specifier_qualifier_list(struct compile_state
*state
)
13015 unsigned int specifiers
= 0;
13017 /* type qualifiers */
13018 specifiers
|= type_qualifiers(state
);
13020 /* type specifier */
13021 type
= type_specifier(state
, specifiers
);
13026 #if DEBUG_ROMCC_WARNING
13027 static int isdecl_specifier(int tok
)
13030 /* storage class specifier */
13036 /* type qualifier */
13040 /* type specifiers */
13050 /* struct or union specifier */
13053 /* enum-spefifier */
13056 case TOK_TYPE_NAME
:
13057 /* function specifiers */
13066 static struct type
*decl_specifiers(struct compile_state
*state
)
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.
13076 /* storage class specifier */
13077 specifiers
|= storage_class_specifier_opt(state
);
13079 /* function-specifier */
13080 specifiers
|= function_specifier_opt(state
);
13083 specifiers
|= attributes_opt(state
, 0);
13085 /* type qualifier */
13086 specifiers
|= type_qualifiers(state
);
13088 /* type specifier */
13089 type
= type_specifier(state
, specifiers
);
13093 struct field_info
{
13098 static struct field_info
designator(struct compile_state
*state
, struct type
*type
)
13101 struct field_info info
;
13105 switch(peek(state
)) {
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
);
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
);
13135 error(state
, 0, "Invalid designator");
13138 } while((tok
== TOK_LBRACKET
) || (tok
== TOK_DOT
));
13139 eat(state
, TOK_EQ
);
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?"
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
);
13175 struct field_info info
;
13177 if (((type
->type
& TYPE_MASK
) != TYPE_ARRAY
) &&
13178 ((type
->type
& TYPE_MASK
) != TYPE_STRUCT
)) {
13179 internal_error(state
, 0, "unknown initializer type");
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
) {
13189 max_offset
= size_of(state
, type
);
13191 buf
= xcmalloc(bits_to_bytes(max_offset
), "initializer");
13192 eat(state
, TOK_LBRACE
);
13194 struct triple
*value
;
13195 struct type
*value_type
;
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
)) {
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
));
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",
13227 bits_to_bytes(max_offset
),
13228 bits_to_bytes(value_size
),
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);
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;
13247 internal_error(state
, 0, "unhandled constant initializer");
13249 free_triple(state
, value
);
13250 if (peek(state
) == TOK_COMMA
) {
13251 eat(state
, TOK_COMMA
);
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
;
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.
13280 struct triple
*ins
;
13281 /* Also error on branches that do not use their targets */
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
;
13291 for(set
= targ
?targ
->use
:0; set
; set
= set
->next
) {
13292 if (set
->member
== ins
) {
13297 internal_error(state
, ins
, "targ not used");
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
) {
13311 ins
= entry
->sym_label
->def
;
13312 if (!(ins
->id
& TRIPLE_FLAG_FLATTENED
)) {
13313 error(state
, ins
, "label `%s' used but not defined",
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
;
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
;
13341 while((param
->type
& TYPE_MASK
) == TYPE_PRODUCT
) {
13343 if (!param
->left
->field_ident
) {
13344 error(state
, 0, "No identifier for parameter %d\n", i
);
13346 param
= param
->right
;
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
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 */
13435 /* Remember I have defined a function */
13436 if (!state
->functions
) {
13437 state
->functions
= def
;
13439 insert_triple(state
, state
->functions
, def
);
13441 if (state
->compiler
->debug
& DEBUG_INLINE
) {
13442 FILE *fp
= state
->dbgout
;
13445 fprintf(fp
, "\n__________ %s _________\n", __FUNCTION__
);
13446 display_func(state
, fp
, def
);
13447 fprintf(fp
, "__________ %s _________ done\n\n", __FUNCTION__
);
13453 static struct triple
*do_decl(struct compile_state
*state
,
13454 struct type
*type
, struct hash_entry
*ident
)
13456 struct triple
*def
;
13458 /* Clean up the storage types used */
13459 switch (type
->type
& STOR_MASK
) {
13462 /* These are the good types I am aiming for */
13464 case STOR_REGISTER
:
13465 type
->type
&= ~STOR_MASK
;
13466 type
->type
|= STOR_AUTO
;
13470 type
->type
&= ~STOR_MASK
;
13471 type
->type
|= STOR_STATIC
;
13475 error(state
, 0, "typedef without name");
13477 symbol(state
, ident
, &ident
->sym_ident
, 0, type
);
13478 ident
->tok
= TOK_TYPE_NAME
;
13482 internal_error(state
, 0, "Undefined storage class");
13484 if ((type
->type
& TYPE_MASK
) == TYPE_FUNCTION
) {
13485 // ignore function prototypes
13489 ((type
->type
& TYPE_MASK
) == TYPE_ARRAY
) &&
13490 ((type
->type
& STOR_MASK
) != STOR_STATIC
))
13491 error(state
, 0, "non static arrays not supported");
13493 ((type
->type
& STOR_MASK
) == STOR_STATIC
) &&
13494 ((type
->type
& QUAL_CONST
) == 0)) {
13495 error(state
, 0, "non const static variables not supported");
13498 def
= variable(state
, type
);
13499 var_symbol(state
, ident
, 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
;
13510 global
= (state
->scope_depth
<= GLOBAL_SCOPE_DEPTH
);
13511 base_type
= decl_specifiers(state
);
13513 type
= declarator(state
, base_type
, &ident
, 0);
13514 type
->type
= attributes_opt(state
, type
->type
);
13515 if (global
&& ident
&& (peek(state
) == TOK_LBRACE
)) {
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;
13525 flatten(state
, first
, do_decl(state
, type
, ident
));
13526 /* type or variable definition */
13529 if (peek(state
) == TOK_EQ
) {
13531 error(state
, 0, "cannot assign to a type");
13533 eat(state
, TOK_EQ
);
13534 flatten(state
, first
,
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
);
13543 type
= declarator(state
, base_type
, &ident
, 0);
13544 flatten(state
, first
, do_decl(state
, type
, ident
));
13548 eat(state
, TOK_SEMI
);
13552 static void decls(struct compile_state
*state
)
13554 struct triple
*list
;
13556 list
= label(state
);
13559 if (tok
== TOK_EOF
) {
13562 if (tok
== TOK_SPACE
) {
13563 eat(state
, TOK_SPACE
);
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;
13581 struct block
*block
;
13582 struct triple_reg_set
*in
;
13583 struct triple_reg_set
*out
;
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
),
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
);
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");
13631 static void walk_functions(struct compile_state
*state
,
13632 void (*cb
)(struct compile_state
*state
, struct triple
*func
, void *arg
),
13635 struct triple
*func
, *first
;
13636 func
= first
= state
->functions
;
13638 cb(state
, func
, arg
);
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
),
13647 struct triple
*func
, *first
;
13648 func
= first
= state
->functions
;
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) {
13662 ptr
= first
= RHS(func
, 0);
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
;
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
);
13706 FILE *fp
= state
->errout
;
13707 fprintf(fp
, "global: ");
13708 display_triple(fp
, ins
);
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
;
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);
13733 ofirst
= old
= RHS(ofunc
, 0);
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
,
13746 if (!triple_stores_block(state
, new)) {
13747 memcpy(&new->u
, &old
->u
, sizeof(new->u
));
13750 RHS(nfunc
, 0) = nfirst
= new;
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
;
13764 } while(old
!= ofirst
);
13766 /* Make a second pass to fix up any unresolved references */
13770 struct triple
**oexpr
, **nexpr
;
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
)) {
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
);
13795 } while((old
!= ofirst
) && (new != nfirst
));
13797 /* Make a third pass to cleanup the extra useses */
13801 unuse_triple(old
, new);
13802 /* Forget which instructions are local */
13803 old
->id
&= ~TRIPLE_FLAG_LOCAL
;
13806 } while ((old
!= ofirst
) && (new != nfirst
));
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
;
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
;
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
;
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
;
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 */
13892 free_triple(state
, nfunc
);
13894 /* Append the new function list onto the return list */
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 */
13904 result
= flatten(state
, fcall
, result
);
13905 propagate_use(state
, fcall
, result
);
13908 /* Release the original fcall instruction */
13909 release_triple(state
, fcall
);
13916 * Type of the result variable.
13920 * +----------+------------+
13922 * union of closures result_type
13924 * +------------------+---------------+
13926 * closure1 ... closuerN
13928 * +----+--+-+--------+-----+ +----+----+---+-----+
13929 * | | | | | | | | |
13930 * var1 var2 var3 ... varN result var1 var2 ... varN result
13932 * +--------+---------+
13934 * union of closures result_type
13936 * +-----+-------------------+
13938 * closure1 ... closureN
13940 * +-----+---+----+----+ +----+---+----+-----+
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
;
13953 FILE *fp
= state
->errout
;
13954 fprintf(fp
, "original_type: ");
13955 name_of(fp
, fresult(state
, func
)->type
);
13958 /* find the original type */
13959 var
= fresult(state
, func
);
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;
13975 fprintf(fp
, "new_type: ");
13978 fprintf(fp
, "ctype: %p %d bits: %d ",
13979 ctype
, ctype
->elements
, reg_size_of(state
, ctype
));
13980 name_of(fp
, ctype
);
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
,
14009 deref_index(state
, fresult(state
, func
), 0),
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
;
14026 static int ordered_triple_set(
14027 struct triple_reg_set
**head
, struct triple
*member
)
14029 struct triple_reg_set
**ptr
;
14034 if (member
== (*ptr
)->member
) {
14037 /* keep the list ordered */
14038 if (member
->id
< (*ptr
)->member
->id
) {
14041 ptr
= &(*ptr
)->next
;
14043 insert_triple_set(ptr
, member
);
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);
14065 struct triple
*result
;
14066 struct triple
*index0
, *index1
, *index2
, *read
, *write
;
14069 if (ins
->op
!= OP_CALL
) {
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
)) {
14084 * 0 index result < 0 >
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
);
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
;
14133 uint64_t used_indices
;
14135 #define MAX_INDICES (sizeof(used_indices)*CHAR_BIT)
14136 #define ID_BITS(X) ((X) & (TRIPLE_FLAG_LOCAL -1))
14143 /* Find the basic blocks of this function */
14145 bb
.first
= RHS(me
, 0);
14147 if (!triple_is_ret(state
, bb
.first
->prev
)) {
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
);
14168 /* Count the number of triples in the function */
14169 first
= RHS(me
, 0);
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);
14185 info
[idx
].id
= ins
->id
;
14186 ins
->id
= TRIPLE_FLAG_LOCAL
| idx
;
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.
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
)) {
14215 if ((set
->member
== fcall
) || (set
->member
== old_result
)) {
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 */
14227 for(set
= vars
; set
; set
= set
->next
) {
14228 struct triple
*ins
;
14231 index
= lookup_closure_index(state
, me
, ins
);
14232 info
[ID_BITS(ins
->id
)].index
= index
;
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
) {
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
;
14256 index
= info
[ID_BITS(ins
->id
)].index
;
14260 /* Find the lowest unused index value */
14261 for(index
= 0; index
< MAX_INDICES
; index
++) {
14262 if (!(used_indices
& ((uint64_t)1 << index
))) {
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
) {
14277 /* Build the return list of variables with positions matching
14281 last_var
= enclose
;
14282 for(i
= 0; i
<= max_index
; i
++) {
14283 struct triple
*var
;
14285 if (used_indices
& ((uint64_t)1 << i
)) {
14286 for(set
= vars
; set
; set
= set
->next
) {
14288 index
= info
[ID_BITS(set
->member
->id
)].index
;
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
);
14312 /* Clear the marks */
14315 ins
->id
= info
[ID_BITS(ins
->id
)].id
;
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 */
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__
);
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
) {
14370 type
= set
->member
->type
;
14372 if (!*closure_next
) {
14373 *closure_next
= type
;
14375 *closure_next
= new_type(TYPE_PRODUCT
, *closure_next
,
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");
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
;
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
) {
14429 flatten(state
, ret_loc
,
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
,
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
,
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
)) {
14469 /* Generate an expression for the value */
14470 new = flatten(state
, first
,
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));
14482 * If the original is a value update the dominated uses.
14485 /* Analyze the basic blocks so I can see who dominates whom */
14487 bb
.first
= RHS(me
, 0);
14488 if (!triple_is_ret(state
, bb
.first
->prev
)) {
14491 analyze_basic_blocks(state
, &bb
);
14494 #if DEBUG_EXPLICIT_CLOSURES
14495 fprintf(state
->errout
, "Updating domindated uses: %p -> %p\n",
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.
14505 if (!tdominates(state
, fcall
, use
->member
)) {
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
;
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__
);
14534 static int do_inline(struct compile_state
*state
, struct triple
*func
)
14539 policy
= state
->compiler
->flags
& COMPILER_INLINE_MASK
;
14541 case COMPILER_INLINE_ALWAYS
:
14543 if (func
->type
->type
& ATTRIB_NOINLINE
) {
14544 error(state
, func
, "noinline with always_inline compiler option");
14547 case COMPILER_INLINE_NEVER
:
14549 if (func
->type
->type
& ATTRIB_ALWAYS_INLINE
) {
14550 error(state
, func
, "always_inline with noinline compiler option");
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
:
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
:
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
:
14585 do_inline
= (func
->u
.cval
== 1);
14590 internal_error(state
, 0, "Unimplemented inline policy");
14593 /* Force inlining */
14594 if (func
->type
->type
& ATTRIB_NOINLINE
) {
14597 if (func
->type
->type
& ATTRIB_ALWAYS_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) {
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);
14619 struct triple
*func
, *prev
;
14623 if (ptr
->op
!= OP_FCALL
) {
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);
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
);
14643 /* Update the function use counts */
14646 /* Replace the fcall with the called function */
14647 expand_inline_call(state
, me
, ptr
);
14650 } while (next
!= first
);
14654 struct triple
*prev
, *func
;
14658 if (ptr
->op
!= OP_FCALL
) {
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
);
14671 /* Replace the fcall with the instruction sequence
14672 * needed to make the call.
14674 expand_function_call(state
, me
, ptr
);
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) {
14699 /* Find the end points of the lists */
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
;
14718 info
= xcmalloc(sizeof(*info
), "asm_info");
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);
14732 LHS(def
, i
) = piece
;
14738 struct triple
*output_asm(struct compile_state
*state
)
14740 struct asm_info
*info
;
14741 struct triple
*def
;
14744 info
= xcmalloc(sizeof(*info
), "asm_info");
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
;
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
;
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
= "";
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 */
14815 while(pnext
&& ((pnext
->type
& TYPE_MASK
) != TYPE_VOID
)) {
14816 struct triple
*expr
;
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
);
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
;
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
)) {
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
);
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
;
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
,
14904 struct block_set
**ptr
, *new;
14911 if ((*ptr
)->member
== user
) {
14914 ptr
= &(*ptr
)->next
;
14916 new = xcmalloc(sizeof(*new), "block_set");
14917 new->member
= user
;
14928 static int do_unuse_block(
14929 struct block
*used
, struct block_set
**head
, struct block
*unuser
)
14931 struct block_set
*use
, **ptr
;
14937 if (use
->member
== unuser
) {
14939 memset(use
, -1, sizeof(*use
));
14950 static void use_block(struct block
*used
, struct block
*user
)
14953 /* Append new to the head of the list, print_block
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
)
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
)
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
)
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
),
15025 struct triple
*ptr
;
15027 ptr
= state
->first
;
15029 result
= cb(state
, ptr
, arg
);
15030 if (ptr
->next
->prev
!= ptr
) {
15031 internal_error(state
, ptr
->next
, "bad prev");
15034 } while((result
== 0) && (ptr
!= state
->first
));
15038 #define PRINT_LIST 1
15039 static int do_print_triple(struct compile_state
*state
, struct triple
*ins
, void *arg
)
15044 if (op
== OP_LIST
) {
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
)) {
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
);
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
)) {
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
;
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
;
15104 fprintf(fp
, "(%p) %d:", block
, block
->vertex
);
15105 for(edge
= block
->edges
; edge
; edge
= edge
->next
) {
15106 fprintf(fp
, " %d", edge
->member
->vertex
);
15114 static void free_basic_block(struct compile_state
*state
, struct block
*block
)
15116 struct block_set
*edge
, *entry
;
15117 struct block
*child
;
15121 if (block
->vertex
== -1) {
15124 block
->vertex
= -1;
15125 for(edge
= block
->edges
; edge
; edge
= edge
->next
) {
15126 if (edge
->member
) {
15127 unuse_block(edge
->member
, block
);
15131 unidom_block(block
->idom
, block
);
15134 if (block
->ipdom
) {
15135 unipdom_block(block
->ipdom
, block
);
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
) {
15147 while((entry
= block
->idominates
)) {
15148 child
= entry
->member
;
15149 unidom_block(block
, child
);
15150 if (child
&& (child
->vertex
!= -1)) {
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)) {
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;
15193 if (triple_stores_block(state
, ins
)) {
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
;
15220 if ((ptr
!= first
) && triple_is_label(state
, ptr
) && (ptr
->use
)) {
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
)) {
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);
15255 internal_error(state
, ptr
, "branch without targets");
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);
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
);
15293 internal_error(state
, 0, "Bad basic block split");
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);
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
),
15318 struct triple
*ptr
, *first
;
15319 struct block
*last_block
;
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
;
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
;
15343 fprintf(fp
, "\nblock: %p (%d) ",
15347 for(edge
= block
->edges
; edge
; edge
= edge
->next
) {
15348 fprintf(fp
, " %p<-%p",
15350 (edge
->member
&& edge
->member
->use
)?
15351 edge
->member
->use
->member
: 0);
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
)
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) ",
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 */
15405 if (ins
->op
== OP_LABEL
) {
15406 block
= ins
->u
.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
);
15414 internal_error(state
, ins
, "pruning used ins?");
15417 release_triple(state
, ins
);
15419 if (block
&& block
->last
== ins
) {
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
);
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
);
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
;
15488 static void unsdom_block(struct sdom_block
*block
)
15490 struct sdom_block
**ptr
;
15491 if (!block
->sdom_next
) {
15494 ptr
= &block
->sdom
->sdominates
;
15496 if ((*ptr
) == block
) {
15497 *ptr
= block
->sdom_next
;
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
)) {
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
);
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
)) {
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
);
15559 static int setup_spdblocks(struct compile_state
*state
,
15560 struct basic_blocks
*bb
, struct sdom_block
*sd
)
15562 struct block
*block
;
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
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
) {
15576 #if DEBUG_SDP_BLOCKS
15578 FILE *fp
= state
->errout
;
15579 fprintf(fp
, "Adding %d\n", vertex
+1);
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
);
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
) {
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
)
15618 * for each v <= pred(w) {
15620 * if (semi[u] < semi[w] {
15621 * semi[w] = semi[u];
15624 * add w to bucket(vertex(semi[w]));
15625 * LINK(parent(w), w);
15628 * for each v <= bucket(parent(w)) {
15629 * delete v from bucket(parent(w));
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
;
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
;
15652 for(v
= parent
->sdominates
; v
; v
= next
) {
15653 struct sdom_block
*u
;
15654 next
= v
->sdom_next
;
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
)
15668 * for each v <= pred(w) {
15670 * if (semi[u] < semi[w] {
15671 * semi[w] = semi[u];
15674 * add w to bucket(vertex(semi[w]));
15675 * LINK(parent(w), w);
15678 * for each v <= bucket(parent(w)) {
15679 * delete v from bucket(parent(w));
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
;
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
;
15701 for(v
= parent
->sdominates
; v
; v
= next
) {
15702 struct sdom_block
*u
;
15703 next
= v
->sdom_next
;
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
)
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
)
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;
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.
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
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) */
15759 * Let w != r. Suppose every u for which sdom(w) -> u -> w satisfies
15760 * sdom(u) >= sdom(w). Then idom(w) = sdom(w).
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}
15779 * For any vertex w != r.
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})
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.
15788 * { sdom(w) if sdom(w) = sdom(u),
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
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);
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
);
15821 static void find_post_dominators(struct compile_state
*state
,
15822 struct basic_blocks
*bb
)
15824 struct sdom_block
*sd
;
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
);
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
;
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");
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
;
15930 for(i
= 0; i
< depth
; i
++) {
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)) {
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
);
15950 fprintf(fp
, " (%s:%d - %s:%d)",
15951 ptr
->filename
, ptr
->line
,
15952 ptr2
->filename
, ptr2
->line
);
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)) {
15979 fprintf(fp
, "%d:", block
->vertex
);
15980 for(user
= block
->domfrontier
; user
; user
= user
->next
) {
15981 fprintf(fp
, " %d", user
->member
->vertex
);
15985 for(edge
= block
->edges
; edge
; edge
= edge
->next
) {
15986 vertex
= print_frontiers(state
, fp
, edge
->member
, 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
;
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");
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)) {
16046 fprintf(fp
, "%d:", block
->vertex
);
16047 for(user
= block
->ipdomfrontier
; user
; user
= user
->next
) {
16048 fprintf(fp
, " %d", user
->member
->vertex
);
16051 for(user
= block
->use
; user
; user
= user
->next
) {
16052 vertex
= print_pfrontiers(state
, fp
, user
->member
, 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
)) {
16088 static int tdominates(struct compile_state
*state
,
16089 struct triple
*dom
, struct triple
*sub
)
16091 struct block
*bdom
, *bsub
;
16093 bdom
= block_of_triple(state
, dom
);
16094 bsub
= block_of_triple(state
, sub
);
16095 if (bdom
!= bsub
) {
16096 result
= bdominates(state
, bdom
, bsub
);
16099 struct triple
*ins
;
16100 if (!bdom
|| !bsub
) {
16101 internal_error(state
, dom
, "huh?");
16104 while((ins
!= bsub
->first
) && (ins
!= dom
)) {
16107 result
= (ins
== dom
);
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
)
16123 struct triple
*first
;
16124 int *has_already
, *work
;
16125 struct block
*work_list
, **work_list_tail
;
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");
16134 first
= state
->first
;
16135 for(var
= first
->next
; var
!= first
; var
= vnext
) {
16136 struct block
*block
;
16137 struct triple_set
*user
, *unext
;
16140 if (!triple_is_auto_var(state
, var
) || !var
->use
) {
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
) {
16152 if (user
->member
->op
== OP_READ
) {
16155 if (user
->member
->op
!= OP_WRITE
) {
16156 internal_error(state
, user
->member
,
16157 "bad variable access");
16159 block
= user
->member
->u
.block
;
16161 warning(state
, user
->member
, "dead code");
16162 release_triple(state
, user
->member
);
16165 if (work
[block
->vertex
] >= iter
) {
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
;
16179 front
= df
->member
;
16181 if (has_already
[front
->vertex
] >= iter
) {
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
,
16191 phi
->u
.block
= front
;
16192 MISC(phi
, 0) = var
;
16193 use_triple(var
, phi
);
16195 if (phi
->rhs
!= in_edges
) {
16196 internal_error(state
, phi
, "phi->rhs: %d != in_edges: %d",
16197 phi
->rhs
, in_edges
);
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
) {
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
);
16225 struct triple_set
*top
;
16229 static int count_auto_vars(struct compile_state
*state
)
16231 struct triple
*first
, *ins
;
16233 first
= state
->first
;
16236 if (triple_is_auto_var(state
, ins
)) {
16240 } while(ins
!= first
);
16244 static void number_auto_vars(struct compile_state
*state
, struct stack
*stacks
)
16246 struct triple
*first
, *ins
;
16248 first
= state
->first
;
16251 if (triple_is_auto_var(state
, ins
)) {
16253 stacks
[auto_vars
].orig_id
= ins
->id
;
16254 ins
->id
= auto_vars
;
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
;
16266 if (triple_is_auto_var(state
, ins
)) {
16267 ins
->id
= stacks
[ins
->id
].orig_id
;
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
;
16278 head
= stacks
[var
->id
].top
;
16280 top_val
= head
->member
;
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");
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
;
16303 if (set
->member
== oldval
) {
16306 /* Only free one occurrence from the stack */
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
;
16325 if (!parent
|| !block
)
16327 /* Find the edge I am coming in on */
16329 for(set
= block
->use
; set
; set
= set
->next
, edge
++) {
16330 if (set
->member
== parent
) {
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);
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");
16357 use_triple(val
, ptr
);
16359 if (ptr
== block
->last
) {
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
;
16374 last
= block
->first
;
16376 for(ptr
= block
->first
; !done
; ptr
= next
) {
16378 if (ptr
== block
->last
) {
16382 if (ptr
->op
== OP_READ
) {
16383 struct triple
*var
, *val
;
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
);
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;
16401 val
= pre_triple(state
, ptr
, OP_UNKNOWNVAL
, ptr
->type
, 0, 0);
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
);
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
;
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
);
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
;
16470 for(ptr
= block
->first
; !done
; ptr
= next
) {
16472 if (ptr
== block
->last
) {
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
);
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
);
16491 block
->last
= last
;
16494 static void rename_variables(struct compile_state
*state
)
16496 struct stack
*stacks
;
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
);
16514 static void prune_block_variables(struct compile_state
*state
,
16515 struct block
*block
)
16517 struct block_set
*user
;
16518 struct triple
*next
, *ptr
;
16522 for(ptr
= block
->first
; !done
; ptr
= next
) {
16523 /* Be extremely careful I am deleting the list
16524 * as I walk trhough it.
16527 if (ptr
== block
->last
) {
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
;
16535 use
= user
->member
;
16536 if (MISC(ptr
, 0) == user
->member
) {
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
);
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
);
16557 for(user
= block
->idominates
; user
; user
= user
->next
) {
16558 prune_block_variables(state
, user
->member
);
16562 struct phi_triple
{
16563 struct triple
*phi
;
16568 static void keep_phi(struct compile_state
*state
, struct phi_triple
*live
, struct triple
*phi
)
16570 struct triple
**slot
;
16572 if (live
[phi
->id
].alive
) {
16575 live
[phi
->id
].alive
= 1;
16577 slot
= &RHS(phi
, 0);
16578 for(i
= 0; i
< zrhs
; i
++) {
16579 struct triple
*used
;
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
;
16593 /* Find the first instruction */
16594 first
= state
->first
;
16596 /* Count how many phi functions I need to process */
16598 for(phi
= first
->next
; phi
!= first
; phi
= phi
->next
) {
16599 if (phi
->op
== OP_PHI
) {
16604 /* Mark them all dead */
16605 live
= xcmalloc(sizeof(*live
) * (phis
+ 1), "phi_triple");
16607 for(phi
= first
->next
; phi
!= first
; phi
= phi
->next
) {
16608 if (phi
->op
!= OP_PHI
) {
16611 live
[phis
].alive
= 0;
16612 live
[phis
].orig_id
= phi
->id
;
16613 live
[phis
].phi
= phi
;
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
);
16629 /* Delete the extraneous phis */
16630 for(i
= 0; i
< phis
; i
++) {
16631 struct triple
**slot
;
16633 if (!live
[i
].alive
) {
16634 release_triple(state
, live
[i
].phi
);
16638 slot
= &RHS(phi
, 0);
16640 for(j
= 0; j
< zrhs
; 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
));
16648 use_triple(unknown
, phi
);
16649 transform_to_arch_instruction(state
, unknown
);
16651 warning(state
, phi
, "variable not set at index %d on all paths to use", j
);
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
;
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) {
16695 block
->vertex
= *next_vertex
;
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
)) {
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
;
16733 /* Walk the control flow to see which blocks remain alive */
16734 walk_blocks(state
, &state
->bb
, clear_vertex
, 0);
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
;
16748 if (phi
->op
!= OP_PHI
) {
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
);
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)) {
16770 expr
= triple_rhs(state
, use
->member
, 0);
16771 for(; expr
; expr
= triple_rhs(state
, use
->member
, expr
)) {
16772 if (*expr
== phi
) {
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 */
16790 for(use
= var
->use
; use
; use
= use
->next
) {
16791 if (use
->member
!= MISC(var
, 0)) {
16796 /* Walk all of the incoming edges/blocks and insert moves.
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
;
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
16812 if (!val
|| (val
== &unknown_triple
) || (val
== phi
)
16813 || (vblock
&& (vblock
->vertex
== 0))) {
16816 /* If the value should never occur error */
16818 internal_error(state
, val
, "no vblock?");
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)) {
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
)) {
16850 expr
= triple_lhs(state
, base
, 0);
16851 for(; expr
; expr
= triple_lhs(state
, base
, expr
)) {
16852 if ((*expr
) == val
) {
16856 expr
= triple_rhs(state
, base
, 0);
16857 for(; expr
; expr
= triple_rhs(state
, base
, expr
)) {
16858 if ((*expr
) == var
) {
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
);
16873 if (!writers
&& readers
) {
16874 internal_error(state
, var
, "no value written to in use phi?");
16876 /* If var is not used free it */
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
)) {
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
;
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 */
16909 slot
= &RHS(user
, 0);
16910 for(i
= 0; i
< zrhs
; i
++) {
16911 if (slot
[i
] == var
) {
16916 /* If we did use it cleanup the uses */
16918 unuse_triple(var
, user
);
16919 use_triple(read
, user
);
16921 /* If we didn't use it release the extra triple */
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
)
16937 transform_from_ssa_form(state
);
16939 state
->bb
.first
= state
->first
;
16940 free_basic_blocks(state
, &state
->bb
);
16941 analyze_basic_blocks(state
, &state
->bb
);
16943 insert_phi_operations(state
);
16945 rename_variables(state
);
16948 prune_block_variables(state
, state
->bb
.first_block
);
16950 prune_unused_phis(state
);
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
;
16967 if (!triple_is_def(state
, def
)) {
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
;
16977 i
= find_rhs_use(state
, set
->member
, def
);
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");
17005 static struct reg_info
find_lhs_pre_color(
17006 struct compile_state
*state
, struct triple
*ins
, int index
)
17008 struct reg_info info
;
17012 if (!zlhs
&& triple_is_def(state
, ins
)) {
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
;
17031 if (info
.reg
>= MAX_REGISTERS
) {
17032 info
.reg
= REG_UNSET
;
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",
17050 if ((index
== 0) && triple_is_def(state
, ins
)) {
17053 else if (index
< ins
->lhs
) {
17054 lhs
= LHS(ins
, index
);
17057 internal_error(state
, ins
, "Bad lhs %d", index
);
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
;
17068 user
= set
->member
;
17070 for(i
= 0; i
< zrhs
; i
++) {
17071 if (RHS(user
, i
) != lhs
) {
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
);
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
;
17102 #if DEBUG_TRIPLE_COLOR
17103 fprintf(state
->errout
, "find_rhs_post_color(%p, %d)\n",
17106 rinfo
= arch_reg_rhs(state
, ins
, index
);
17108 if (!zlhs
&& triple_is_def(state
, ins
)) {
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
);
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",
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
);
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
) {
17183 next
= entry
->next
;
17184 if (entry
->member
== out
) {
17187 i
= find_rhs_use(state
, entry
->member
, ins
);
17191 rinfo
= arch_reg_rhs(state
, entry
->member
, i
);
17192 if ((info
.reg
== REG_UNNEEDED
) && (rinfo
.reg
== REG_UNNEEDED
)) {
17195 replace_rhs_use(state
, ins
, out
, entry
->member
);
17197 transform_to_arch_instruction(state
, 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.
17208 struct triple
**expr
;
17210 struct reg_info info
;
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: ");
17225 internal_error(state
, ins
, "pre_copy with no register classes");
17228 if (!equiv_types(type
, (*expr
)->type
)) {
17231 in
= pre_triple(state
, ins
, op
, type
, *expr
, 0);
17232 unuse_triple(*expr
, ins
);
17234 use_triple(RHS(in
, 0), in
);
17235 use_triple(in
, ins
);
17236 transform_to_arch_instruction(state
, 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
;
17262 if (phi
->op
!= OP_PHI
) {
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
;
17289 get_occurrence(val
->occurrence
);
17290 move
= build_triple(state
, OP_COPY
, val
->type
, val
, 0,
17292 move
->u
.block
= eblock
;
17293 move
->id
|= TRIPLE_FLAG_PRE_SPLIT
;
17294 use_triple(val
, 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
;
17305 internal_error(state
, phi
, "Cannot find block dominated by %p",
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
)) {
17320 expr
= triple_lhs(state
, ptr
, 0);
17321 for(;expr
; expr
= triple_lhs(state
, ptr
, expr
)) {
17322 if ((*expr
) == val
) {
17326 expr
= triple_rhs(state
, ptr
, 0);
17327 for(;expr
; expr
= triple_rhs(state
, ptr
, expr
)) {
17328 if ((*expr
) == phi
) {
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
;
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;
17360 if ((*ptr
)->member
== member
) {
17363 ptr
= &(*ptr
)->next
;
17365 new = xcmalloc(sizeof(*new), "triple_set");
17366 new->member
= member
;
17367 new->new = new_member
;
17373 static void do_triple_unset(struct triple_reg_set
**head
, struct triple
*member
)
17375 struct triple_reg_set
*entry
, **ptr
;
17379 if (entry
->member
== member
) {
17380 *ptr
= entry
->next
;
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
);
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
);
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
)) {
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
);
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
;
17441 if (!is_lvalue(state
, ins
)) {
17446 while(ins
&& triple_is_part(state
, ins
) && (ins
->op
!= OP_PIECE
)) {
17447 base
= MISC(ins
, 0);
17450 reg
+= index_reg_offset(state
, base
->type
, ins
->u
.cval
)/REG_SIZEOF_REG
;
17453 reg
+= field_reg_offset(state
, base
->type
, ins
->u
.field
)/REG_SIZEOF_REG
;
17456 internal_error(state
, ins
, "unhandled part");
17462 if (reg
> base
->lhs
) {
17463 internal_error(state
, base
, "part out of range?");
17465 ins
= LHS(base
, reg
);
17470 static int this_def(struct compile_state
*state
,
17471 struct triple
*ins
, struct triple
*other
)
17473 if (ins
== other
) {
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
;
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
) {
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
) {
17510 slot
= &RHS(ptr
, 0);
17512 out_change
= out_triple(rb
, expr
);
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
)) {
17524 done2
= (ptr2
== rb
->block
->last
);
17529 change
|= in_triple(rb
, expr
);
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
;
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
);
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
;
17557 for(ptr
= first
; !done
; ptr
= ptr
->next
) {
17558 if (this_def(state
, ptr
, in_set
->member
)) {
17561 done
= (ptr
== last
);
17566 change
|= in_triple(rb
, in_set
->member
);
17568 change
|= phi_in(state
, blocks
, rb
, suc
);
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?"
17580 struct block
*block
;
17581 struct triple
*ptr
;
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
17593 if (ptr
->op
== OP_PHI
) {
17596 expr
= triple_rhs(state
, ptr
, 0);
17597 for(;expr
; expr
= triple_rhs(state
, ptr
, expr
)) {
17598 struct triple
*rhs
, *test
;
17600 rhs
= part_to_piece(state
, *expr
);
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
)) {
17615 /* If I still have a valid rhs add it to in */
17616 change
|= in_triple(rb
, rhs
);
17622 static struct reg_block
*compute_variable_lifetimes(
17623 struct compile_state
*state
, struct basic_blocks
*bb
)
17625 struct reg_block
*blocks
;
17628 sizeof(*blocks
)*(bb
->last_vertex
+ 1), "reg_block");
17629 initialize_regblock(blocks
, bb
->last_block
, 0);
17633 for(i
= 1; i
<= bb
->last_vertex
; i
++) {
17634 struct block_set
*edge
;
17635 struct reg_block
*rb
;
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
);
17648 static void free_variable_lifetimes(struct compile_state
*state
,
17649 struct basic_blocks
*bb
, struct reg_block
*blocks
)
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
;
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
);
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
)
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
;
17689 /* Get the blocks */
17693 /* Copy out into live */
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
;
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
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
) {
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
)) {
17735 do_triple_set(&live
, *expr
, 0);
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
;
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
;
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",
17769 edge
->member
&& edge
->member
->use
?edge
->member
->use
->member
: 0);
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
);
17781 for(done
= 0, ptr
= block
->first
; !done
; ptr
= ptr
->next
) {
17782 done
= (ptr
== block
->last
);
17783 if (ptr
->op
== OP_PHI
) {
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
) {
17798 slot
= &RHS(ptr
, 0);
17799 fprintf(fp
, " %-10p", slot
[edge
]);
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
);
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
);
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
;
17828 fprintf(fp
, "\nlive variables by block\n");
17829 walk_blocks(state
, bb
, print_live_variables_block
, &info
);
17834 static int count_triples(struct compile_state
*state
)
17836 struct triple
*first
, *ins
;
17838 first
= state
->first
;
17843 } while (ins
!= first
);
17848 struct dead_triple
{
17849 struct triple
*triple
;
17850 struct dead_triple
*work_next
;
17851 struct block
*block
;
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
;
17864 if (!(state
->compiler
->debug
& DEBUG_TRIPLES
)) {
17867 fp
= state
->dbgout
;
17868 fprintf(fp
, "--------------- dtriples ---------------\n");
17869 first
= state
->first
;
17872 dt
= &dtriple
[ins
->id
];
17873 if ((ins
->op
== OP_LABEL
) && (ins
->use
)) {
17874 fprintf(fp
, "\n%p:\n", ins
);
17877 (dt
->flags
& TRIPLE_FLAG_ALIVE
)?' ': '-');
17878 display_triple(fp
, ins
);
17879 if (triple_is_branch(state
, ins
)) {
17883 } while(ins
!= first
);
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
;
17902 if (triple
->id
<= 0) {
17903 internal_error(state
, triple
, "bad triple id: %d",
17906 if (triple
->op
== OP_NOOP
) {
17907 internal_error(state
, triple
, "awakening noop?");
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
;
17924 struct triple
*first
, *ins
;
17926 if (!(state
->compiler
->flags
& COMPILER_ELIMINATE_INEFECTUAL_CODE
)) {
17930 /* Setup the work list */
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");
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
;
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
);
17956 } while(ins
!= first
);
17958 struct block
*block
;
17959 struct dead_triple
*dt
;
17960 struct block_set
*user
;
17961 struct triple
**expr
;
17963 work_list
= dt
->work_next
;
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
);
17973 awaken(state
, dtriple
, &block
->last
->next
, &work_list_tail
);
17976 /* Wake up the data depencencies of this triple */
17979 expr
= triple_rhs(state
, dt
->triple
, expr
);
17980 awaken(state
, dtriple
, expr
, &work_list_tail
);
17983 expr
= triple_lhs(state
, dt
->triple
, expr
);
17984 awaken(state
, dtriple
, expr
, &work_list_tail
);
17987 expr
= triple_misc(state
, dt
->triple
, expr
);
17988 awaken(state
, dtriple
, expr
, &work_list_tail
);
17990 /* Wake up the forward control dependencies */
17992 expr
= triple_targ(state
, dt
->triple
, expr
);
17993 awaken(state
, dtriple
, expr
, &work_list_tail
);
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?"
18003 // internal_warning(state, last, "awakening noop?");
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
);
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
;
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
;
18048 if (!triple_is_def(state
, ins
)) {
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
;
18058 regcm
= arch_type_to_regcm(state
, ins
->type
);
18061 /* Walk through the uses of ins and check for conflicts */
18062 for(entry
= ins
->use
; entry
; entry
= next
) {
18063 struct reg_info rinfo
;
18065 next
= entry
->next
;
18066 i
= find_rhs_use(state
, entry
->member
, ins
);
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
)) {
18084 regcm
&= rinfo
.regcm
;
18085 regcm
= arch_regcm_normalize(state
, regcm
);
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
)) {
18100 (((info
.reg
!= REG_UNSET
) &&
18101 (reg
!= REG_UNSET
) &&
18102 (info
.reg
!= reg
)) ||
18103 ((info
.regcm
& regcm
) == 0));
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
;
18111 next
= entry
->next
;
18112 i
= find_rhs_use(state
, entry
->member
, ins
);
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
18131 ((reg
!= REG_UNNEEDED
) &&
18132 ((ins
->id
& TRIPLE_FLAG_POST_SPLIT
) ||
18133 (entry
->member
->id
& TRIPLE_FLAG_PRE_SPLIT
)))
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
;
18150 if ((regcm
& rinfo
.regcm
) == 0) {
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
;
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");
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
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
;
18215 #define LRE_HASH_SIZE 2048
18217 struct lre_hash
*next
;
18218 struct live_range
*left
;
18219 struct live_range
*right
;
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
;
18232 int passes
, max_passes
;
18236 struct print_interference_block_info
{
18237 struct reg_state
*rstate
;
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
;
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",
18260 edge
->member
&& edge
->member
->use
?edge
->member
->use
->member
: 0);
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
);
18272 for(done
= 0, ptr
= block
->first
; !done
; ptr
= ptr
->next
) {
18273 done
= (ptr
== block
->last
);
18274 if (ptr
->op
== OP_PHI
) {
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
) {
18289 slot
= &RHS(ptr
, 0);
18290 fprintf(fp
, " %-10p", slot
[edge
]);
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
;
18301 done
= (ptr
== block
->last
);
18302 lr
= rstate
->lrd
[ptr
->id
].lr
;
18305 ptr
->id
= rstate
->lrd
[id
].orig_id
;
18306 SET_REG(ptr
->id
, lr
->color
);
18307 display_triple(fp
, ptr
);
18310 if (triple_is_def(state
, ptr
) && (lr
->defs
== 0)) {
18311 internal_error(state
, ptr
, "lr has no defs!");
18313 if (info
->need_edges
) {
18315 struct live_range_def
*lrd
;
18316 fprintf(fp
, " range:");
18319 fprintf(fp
, " %-10p", lrd
->def
);
18321 } while(lrd
!= lr
->defs
);
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
;
18331 fprintf(fp
, " %-10p", lrd
->def
);
18333 } while(lrd
!= edge
->node
->defs
);
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",
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
);
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
;
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
)
18374 for(i
= 0; i
< MAX_REGC
; i
++) {
18375 if (classes
& (1 << i
)) {
18377 size
= arch_regc_size(state
, i
);
18378 if (size
> max_size
) {
18386 static int reg_is_reg(struct compile_state
*state
, int reg1
, int reg2
)
18388 unsigned equivs
[MAX_REG_EQUIVS
];
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
) {
18405 static void reg_fill_used(struct compile_state
*state
, char *used
, int reg
)
18407 unsigned equivs
[MAX_REG_EQUIVS
];
18409 if (reg
== REG_UNNEEDED
) {
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;
18419 static void reg_inc_used(struct compile_state
*state
, char *used
, int reg
)
18421 unsigned equivs
[MAX_REG_EQUIVS
];
18423 if (reg
== REG_UNNEEDED
) {
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;
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
);
18444 hash
= (hash
*263) + val
;
18449 hash
= (hash
*263) + val
;
18451 hash
= hash
& (LRE_HASH_SIZE
- 1);
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
;
18467 index
= hash_live_edge(left
, right
);
18469 ptr
= &rstate
->hash
[index
];
18471 if (((*ptr
)->left
== left
) && ((*ptr
)->right
== right
)) {
18474 ptr
= &(*ptr
)->next
;
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
) {
18497 if ((left
== &rstate
->lr
[0]) || (right
== &rstate
->lr
[0])) {
18500 /* Ensure left <= right */
18501 if (left
> right
) {
18502 struct live_range
*tmp
;
18507 ptr
= lre_probe(rstate
, left
, right
);
18512 fprintf(state
->errout
, "new_live_edge(%p, %p)\n",
18515 new_hash
= xmalloc(sizeof(*new_hash
), "lre_hash");
18516 new_hash
->next
= *ptr
;
18517 new_hash
->left
= left
;
18518 new_hash
->right
= right
;
18521 edge
= xmalloc(sizeof(*edge
), "live_range_edge");
18522 edge
->next
= left
->edges
;
18523 edge
->node
= right
;
18524 left
->edges
= edge
;
18527 edge
= xmalloc(sizeof(*edge
), "live_range_edge");
18528 edge
->next
= right
->edges
;
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
) {
18544 *hptr
= entry
->next
;
18547 for(ptr
= &left
->edges
; *ptr
; ptr
= &(*ptr
)->next
) {
18549 if (edge
->node
== right
) {
18551 memset(edge
, 0, sizeof(*edge
));
18557 for(ptr
= &right
->edges
; *ptr
; ptr
= &(*ptr
)->next
) {
18559 if (edge
->node
== left
) {
18561 memset(edge
, 0, sizeof(*edge
));
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
) {
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
;
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 * | +--------------+ |
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
)) {
18638 lr2
= rstate
->lrd
[(*expr
)->id
].lr
;
18639 if (lr
->color
== lr2
->color
) {
18640 internal_error(state
, ins
, "live range too big");
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
;
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
;
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:");
18685 fprintf(fp
, " %p", lrd
->def
);
18687 } while(lrd
!= lr1
->defs
);
18691 fprintf(fp
, " %p", lrd
->def
);
18693 } while(lrd
!= lr2
->defs
);
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
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
;
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");
18724 fprintf(state
->errout
, "coalesce color1(%p): %3d color2(%p) %3d\n",
18731 /* Append lr2 onto lr1 */
18732 #if DEBUG_ROMCC_WARNINGS
18733 #warning "FIXME should this be a merge instead of a splice?"
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.
18742 mid1
= lr1
->defs
->prev
;
18744 end
= lr2
->defs
->prev
;
18752 /* Fixup the live range in the added live range defs */
18757 } while(lrd
!= head
);
18759 /* Mark lr2 as free. */
18761 lr2
->color
= REG_UNNEEDED
;
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
);
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
;
18786 else if (!tdominates(state
, lr
->defs
->def
, last
->next
->def
)) {
18787 result
= last
->next
;
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
;
18799 result
= lr
->defs
->prev
;
18801 else if (!tdominates(state
, last
->prev
->def
, lr
->defs
->prev
->def
)) {
18802 result
= last
->prev
;
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
;
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
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;
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
);
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. */
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
;
18865 } while(ins
!= first
);
18866 rstate
->ranges
= i
;
18868 /* Make a second pass to handle architecture specific register
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 */
18880 if ((zlhs
== 0) && triple_is_def(state
, ins
)) {
18885 if (state
->compiler
->debug
& DEBUG_COALESCING2
) {
18886 fprintf(state
->errout
, "mandatory coalesce: %p %d %d\n",
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
) {
18897 if (triple_is_def(state
, ins
)) {
18898 lhs
= &rstate
->lrd
[ins
->id
];
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
) {
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
,
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
)) {
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
;
18963 if (!arch_regcm_intersect(def
->classes
, lr
->classes
)) {
18966 add_live_edge(rstate
, def
, lr
);
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
;
18978 if ((ins
->id
< 0) || (ins
->id
> rstate
->defs
)) {
18979 internal_error(state
, ins
, "bad ins?");
18981 lr
= rstate
->lrd
[ins
->id
].lr
;
18985 if (lrd
->def
== ins
) {
18989 } while(lrd
!= lr
->defs
);
18991 internal_error(state
, ins
, "ins not in live range");
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
;
19014 if (entry2
== entry1
) {
19017 lr2
= get_verify_live_range(state
, rstate
, entry2
->member
);
19019 internal_error(state
, entry2
->member
,
19020 "live range with 2 values simultaneously alive");
19022 if (!arch_regcm_intersect(lr1
->classes
, lr2
->classes
)) {
19025 if (!interfere(rstate
, lr1
, lr2
)) {
19026 internal_error(state
, entry2
->member
,
19027 "edges don't interfere?");
19032 for(edge2
= lr2
->edges
; edge2
; edge2
= edge2
->next
) {
19034 if (edge2
->node
== lr1
) {
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
);
19044 internal_error(state
, entry2
->member
, "missing edge");
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
;
19060 FILE *fp
= state
->dbgout
;
19062 lr
= rstate
->lrd
[ins
->id
].lr
;
19064 ins
->id
= rstate
->lrd
[id
].orig_id
;
19065 SET_REG(ins
->id
, lr
->color
);
19066 display_triple(state
->dbgout
, ins
);
19070 struct live_range_def
*lrd
;
19071 fprintf(fp
, " range:");
19074 fprintf(fp
, " %-10p", lrd
->def
);
19076 } while(lrd
!= lr
->defs
);
19080 struct triple_reg_set
*entry
;
19081 fprintf(fp
, " live:");
19082 for(entry
= live
; entry
; entry
= entry
->next
) {
19083 fprintf(fp
, " %-10p", entry
->member
);
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
;
19094 fprintf(fp
, " %-10p", lrd
->def
);
19096 } while(lrd
!= entry
->node
->defs
);
19101 if (triple_is_branch(state
, ins
)) {
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
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
19126 * The two cases I have identified are:
19127 * 1) Two forced register assignments may
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.
19150 for(i
= 0; i
<= rstate
->ranges
; i
++) {
19151 struct live_range
*lr1
;
19152 struct live_range_def
*lrd1
;
19153 lr1
= &rstate
->lr
[i
];
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
) {
19163 /* Skip copies that are the result of a live range split. */
19164 if (lrd1
->orig_id
& TRIPLE_FLAG_POST_SPLIT
) {
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
19177 if (lrd2
->orig_id
& TRIPLE_FLAG_PRE_SPLIT
) {
19180 lr2
= rstate
->lrd
[set
->member
->id
].lr
;
19184 if ((lr1
->color
!= lr2
->color
) &&
19185 (lr1
->color
!= REG_UNSET
) &&
19186 (lr2
->color
!= REG_UNSET
)) {
19189 if ((lr1
->classes
& lr2
->classes
) == 0) {
19193 if (interfere(rstate
, lr1
, lr2
)) {
19197 res
= coalesce_ranges(state
, rstate
, lr1
, lr2
);
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
19225 if ((zlhs
== 0) && triple_is_def(state
, ins
)) {
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
) {
19235 for(j
= 0; j
< zrhs
; j
++) {
19236 struct reg_info rinfo
;
19237 struct triple
*rhs
;
19238 struct triple_reg_set
*set
;
19241 rinfo
= arch_reg_rhs(state
, ins
, j
);
19242 if (rinfo
.reg
!= linfo
.reg
) {
19246 for(set
= live
; set
&& !found
; set
= set
->next
) {
19247 if (set
->member
== rhs
) {
19252 struct triple
*copy
;
19253 copy
= pre_copy(state
, ins
, j
);
19254 copy
->id
|= TRIPLE_FLAG_PRE_SPLIT
;
19262 static int correct_coalesce_conflicts(
19263 struct compile_state
*state
, struct reg_block
*blocks
)
19267 walk_variable_lifetimes(state
, &state
->bb
, blocks
,
19268 fix_coalesce_conflicts
, &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
) {
19283 static void replace_block_use(struct compile_state
*state
,
19284 struct reg_block
*blocks
, struct triple
*orig
, struct triple
*new)
19287 #if DEBUG_ROMCC_WARNINGS
19288 #warning "WISHLIST visit just those blocks that need it *"
19290 for(i
= 1; i
<= state
->bb
.last_vertex
; i
++) {
19291 struct reg_block
*rb
;
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
;
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
);
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);
19328 internal_error(state
, ins
, "Bad lhs %d", index
);
19329 info
.reg
= REG_UNSET
;
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"
19345 info
= find_lhs_color(state
, tangle
, 0);
19346 for(set
= tangle
->use
; set
; set
= next
) {
19347 struct triple
*user
;
19350 user
= set
->member
;
19352 for(i
= 0; i
< zrhs
; i
++) {
19353 if (RHS(user
, i
) != tangle
) {
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
);
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
);
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
;
19387 char used
[MAX_REGISTERS
];
19388 struct triple_reg_set
*set
;
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
) {
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) {
19411 /* Changing copies that feed into phi functions
19414 if (set
->member
->use
&&
19415 (set
->member
->use
->member
->op
== OP_PHI
)) {
19418 if (!tangle
|| tdominates(state
, set
->member
, tangle
)) {
19419 tangle
= set
->member
;
19422 /* If I have found a tangle resolve it */
19424 struct triple
*post_copy
;
19426 post_copy
= resolve_tangle(state
, tangle
);
19428 replace_block_use(state
, blocks
, tangle
, post_copy
);
19430 if (post_copy
&& (tangle
!= ins
)) {
19431 replace_set_use(state
, live
, tangle
, post_copy
);
19438 static int correct_tangles(
19439 struct compile_state
*state
, struct reg_block
*blocks
)
19443 color_instructions(state
);
19444 walk_variable_lifetimes(state
, &state
->bb
, blocks
,
19445 fix_tangles
, &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
;
19459 struct reg_info info
;
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
) {
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)"
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
;
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?"
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
);
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
)
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
)) {
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..."
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
);
19579 static FILE *cgdebug_fp(struct compile_state
*state
)
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
;
19592 static void cgdebug_printf(struct compile_state
*state
, const char *fmt
, ...)
19595 fp
= cgdebug_fp(state
);
19598 va_start(args
, fmt
);
19599 vfprintf(fp
, fmt
, args
);
19604 static void cgdebug_flush(struct compile_state
*state
)
19607 fp
= cgdebug_fp(state
);
19613 static void cgdebug_loc(struct compile_state
*state
, struct triple
*ins
)
19616 fp
= cgdebug_fp(state
);
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
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
) {
19643 reg_fill_used(state
, used
, edge
->node
->color
);
19646 if (state
->compiler
->debug
& DEBUG_COLOR_GRAPH2
) {
19649 for(edge
= range
->edges
; edge
; edge
= edge
->next
) {
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
++) {
19658 cgdebug_printf(state
, "used: %s\n",
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
]) {
19670 for(edge
= range
->edges
; edge
; edge
= edge
->next
) {
19671 if (edge
->node
->color
!= range
->color
) {
19674 warning(state
, edge
->node
->defs
->def
, "edge: ");
19675 lrd
= edge
->node
->defs
;
19677 warning(state
, lrd
->def
, " %p %s",
19678 lrd
->def
, tops(lrd
->def
->op
));
19680 } while(lrd
!= edge
->node
->defs
);
19683 warning(state
, range
->defs
->def
, "def: ");
19685 warning(state
, lrd
->def
, " %p %s",
19686 lrd
->def
, tops(lrd
->def
->op
));
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.
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
;
19705 insd
= &rstate
->lrd
[entry
->member
->id
];
19706 if (insd
->lr
->defs
== 0) {
19709 if (!phi
&& (insd
->def
->op
== OP_PHI
) &&
19710 !interfere(rstate
, range
, insd
->lr
)) {
19713 if (insd
->lr
->color
== REG_UNSET
) {
19716 regcm
= insd
->lr
->classes
;
19717 if (((regcm
& range
->classes
) == 0) ||
19718 (used
[insd
->lr
->color
])) {
19721 if (interfere(rstate
, range
, insd
->lr
)) {
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.
19731 if (phi
->lr
->color
!= REG_UNSET
) {
19732 if (used
[phi
->lr
->color
]) {
19733 range
->color
= phi
->lr
->color
;
19737 expr
= triple_rhs(state
, phi
->def
, 0);
19738 for(; expr
; expr
= triple_rhs(state
, phi
->def
, expr
)) {
19739 struct live_range
*lr
;
19744 lr
= rstate
->lrd
[(*expr
)->id
].lr
;
19745 if (lr
->color
== REG_UNSET
) {
19748 regcm
= lr
->classes
;
19749 if (((regcm
& range
->classes
) == 0) ||
19750 (used
[lr
->color
])) {
19753 if (interfere(rstate
, range
, lr
)) {
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
;
19770 lr
= rstate
->lrd
[(*expr
)->id
].lr
;
19771 if (lr
->color
== REG_UNSET
) {
19774 regcm
= lr
->classes
;
19775 if (((regcm
& range
->classes
) == 0) ||
19776 (used
[lr
->color
])) {
19779 if (interfere(rstate
, range
, lr
)) {
19782 range
->color
= lr
->color
;
19786 /* If I have not opportunitically picked a useful color
19787 * pick the first color that is free.
19789 if (range
->color
== REG_UNSET
) {
19791 arch_select_free_register(state
, used
, range
->classes
);
19793 if (range
->color
== REG_UNSET
) {
19794 struct live_range_def
*lrd
;
19796 if (split_ranges(state
, rstate
, used
, range
)) {
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
;
19804 warning(state
, lrd
->def
, " %s %p",
19805 tops(lrd
->def
->op
), lrd
->def
);
19807 } while(lrd
!= edge
->node
->defs
);
19809 warning(state
, range
->defs
->def
, "range: ");
19812 warning(state
, lrd
->def
, " %s %p",
19813 tops(lrd
->def
->op
), lrd
->def
);
19815 } while(lrd
!= range
->defs
);
19817 warning(state
, range
->defs
->def
, "classes: %x",
19819 for(i
= 0; i
< MAX_REGISTERS
; i
++) {
19821 warning(state
, range
->defs
->def
, "used: %s",
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?");
19834 static int color_graph(struct compile_state
*state
, struct reg_state
*rstate
)
19837 struct live_range_edge
*edge
;
19838 struct live_range
*range
;
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?");
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
;
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?");
19905 colored
= color_graph(state
, rstate
);
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
);
19912 cgdebug_printf(state
, " %s\n", arch_reg_str(range
->color
));
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
;
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");
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
;
19963 if (ins
->id
> rstate
->defs
) {
19964 internal_error(state
, ins
,
19965 "triple without a live range");
19967 lrd
= &rstate
->lrd
[ins
->id
];
19969 ins
->id
= lrd
->orig_id
;
19970 SET_REG(ins
->id
, lr
->color
);
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
;
19980 size
= (last
- first
) + 1;
19982 mid
= first
+ size
/2;
19983 first
= merge_sort_lr(first
, mid
-1);
19984 mid
= merge_sort_lr(mid
, last
);
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
))) {
19994 first
= first
->group_next
;
19996 first
->group_prev
= 0;
20001 mid
= mid
->group_next
;
20003 mid
->group_prev
= 0;
20006 pick
->group_next
= 0;
20007 pick
->group_prev
= join_tail
;
20009 join_tail
= &pick
->group_next
;
20011 /* Splice the remaining list */
20012 pick
= (first
)? first
: mid
;
20015 pick
->group_prev
= join_tail
;
20019 if (!first
->defs
) {
20027 static void ids_from_rstate(struct compile_state
*state
,
20028 struct reg_state
*rstate
)
20030 struct triple
*ins
, *first
;
20031 if (!rstate
->defs
) {
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
);
20041 first
= state
->first
;
20045 struct live_range_def
*lrd
;
20046 lrd
= &rstate
->lrd
[ins
->id
];
20047 ins
->id
= lrd
->orig_id
;
20050 } while(ins
!= first
);
20053 static void cleanup_live_edges(struct reg_state
*rstate
)
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
);
20068 /* Free the variable lifetime information */
20069 if (rstate
->blocks
) {
20070 free_variable_lifetimes(state
, &state
->bb
, rstate
->blocks
);
20073 rstate
->ranges
= 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
;
20085 /* Clear out the reg_state */
20086 memset(&rstate
, 0, sizeof(rstate
));
20087 rstate
.max_passes
= state
->compiler
->max_allocation_passes
;
20090 struct live_range
**point
, **next
;
20094 if (state
->compiler
->debug
& DEBUG_RANGE_CONFLICTS
) {
20095 FILE *fp
= state
->errout
;
20096 fprintf(fp
, "pass: %d\n", rstate
.passes
);
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
20119 tangles
= correct_tangles(state
, rstate
.blocks
);
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.
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
20165 fprintf(state
->errout
, "verify_graph_ins...\n");
20167 /* Verify the interference graph */
20168 walk_variable_lifetimes(
20169 state
, &state
->bb
, rstate
.blocks
,
20170 verify_graph_ins
, &rstate
);
20172 fprintf(state
->errout
, "verify_graph_ins done\n");
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
]);
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
20191 for(point
= &rstate
.high
; *point
; point
= next
) {
20192 struct live_range
*range
;
20193 next
= &(*point
)->group_next
;
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
;
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
);
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 * =========================================
20246 struct lattice_node
{
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
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
;
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
;
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
;
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",
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",
20330 if (!scc
->flow_work_list
) {
20331 scc
->flow_work_list
= fedge
;
20332 fedge
->work_next
= fedge
->work_prev
= fedge
;
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
;
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
;
20355 scc
->flow_work_list
= 0;
20357 fedge
->work_next
= fedge
->work_prev
= 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
));
20381 if (!scc
->ssa_work_list
) {
20382 scc
->ssa_work_list
= sedge
;
20383 sedge
->work_next
= sedge
->work_prev
= sedge
;
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
;
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
;
20406 scc
->ssa_work_list
= 0;
20408 sedge
->work_next
= sedge
->work_prev
= 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
;
20427 ins_count
= ssa_edge_count
= 0;
20429 struct triple_set
*edge
;
20431 for(edge
= ins
->use
; edge
; edge
= edge
->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
;
20442 xcmalloc(sizeof(*scc
->lattice
)*(ins_count
+ 1), "lattice");
20444 xcmalloc(sizeof(*scc
->ssa_edges
)*(ssa_edge_count
+ 1), "ssa_edges");
20446 xcmalloc(sizeof(*scc
->flow_blocks
)*(state
->bb
.last_vertex
+ 1),
20449 /* Initialize pass one collect up the nodes */
20452 ins_index
= ssa_edge_index
= fblock_index
= 0;
20455 if ((ins
->op
== OP_LABEL
) && (block
!= ins
->u
.block
)) {
20456 block
= ins
->u
.block
;
20458 internal_error(state
, ins
, "label without block");
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
,
20468 struct lattice_node
*lnode
;
20470 lnode
= &scc
->lattice
[ins_index
];
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
;
20482 } while(ins
!= first
);
20483 /* Initialize pass two collect up the edges */
20489 struct triple_set
*edge
;
20490 struct ssa_edge
**stail
;
20491 struct lattice_node
*lnode
;
20492 lnode
= &scc
->lattice
[ins
->id
];
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
];
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
];
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");
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;
20534 } while (ins
!= first
);
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
) {
20557 internal_error(state
, 0, "edge mismatch");
20560 ftail
= &sfedge
->in_next
;
20561 sfedge
->in_next
= 0;
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];
20572 fblock
->edges
= xcmalloc(sizeof(*fblock
->edges
)*1, "flow_edges");
20574 fblock
->out
= fblock
->edges
;
20575 dst
= &scc
->flow_blocks
[state
->bb
.first_block
->vertex
];
20576 fedge
= fblock
->edges
;
20577 fedge
->src
= fblock
;
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
)
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
);
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 */
20631 old
= dup_triple(state
, lnode
->val
);
20632 if (lnode
->val
!= lnode
->def
) {
20642 static int lval_changed(struct compile_state
*state
,
20643 struct triple
*old
, struct lattice_node
*lnode
)
20646 /* See if the lattice value has changed */
20648 if (!old
&& !lnode
->val
) {
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)) {
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 (",
20678 ((lnode
->def
->op
== OP_PHI
)? "phi: ": "expr:"),
20680 tops(lnode
->def
->op
));
20681 expr
= triple_rhs(state
, lnode
->def
, 0);
20682 for(;expr
;expr
= triple_rhs(state
, lnode
->def
, 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
)
20702 struct triple
*old
, *scratch
;
20703 struct triple
**dexpr
, **vexpr
;
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
;
20716 count
= TRIPLE_SIZE(scratch
);
20717 for(i
= 0; i
< count
; i
++) {
20718 dexpr
= &lnode
->def
->param
[i
];
20719 vexpr
= &scratch
->param
[i
];
20721 if (((i
< TRIPLE_MISC_OFF(scratch
)) ||
20722 (i
>= TRIPLE_TARG_OFF(scratch
))) &&
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"
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
];
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 */
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
;
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
)) {
20786 /* Find the cases that are always lattice lo */
20788 triple_is_def(state
, lnode
->val
) &&
20789 !triple_is_pure(state
, lnode
->val
, lnode
->old_id
)) {
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"
20803 internal_warning(state
, lnode
->def
, "non def changes value?");
20808 /* See if we need to free the scratch value */
20809 if (lnode
->val
!= scratch
) {
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
;
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
),
20840 for(fedge
= lnode
->fblock
->out
; fedge
; fedge
= fedge
->out_next
) {
20841 fprintf(fp
, " %d", fedge
->dst
->block
->vertex
);
20844 if (lnode
->def
->rhs
> 0) {
20845 fprintf(fp
, " <- %d",
20846 RHS(lnode
->def
, 0)->id
);
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
) {
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)) {
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?");
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
);
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
;
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);
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",
20920 fedge
->dst
->block
->vertex
,
20924 if (!fedge
->executable
) {
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
)) {
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
)) {
20952 /* meet(lattice low, X) = lattice low */
20953 if (is_lattice_lo(state
, lnode
)) {
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. */
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
)
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
);
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
;
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
;
21006 for(fedge
= lnode
->fblock
->in
;
21007 !executable
&& fedge
; fedge
= fedge
->in_next
) {
21008 executable
|= fedge
->executable
;
21011 internal_warning(state
, lnode
->def
,
21012 "lattice node %d %s->%s still high?",
21014 tops(lnode
->def
->op
),
21015 tops(lnode
->val
->op
));
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
) {
21026 mkconst(state
, ins
, lnode
->val
->u
.cval
);
21029 mkaddr_const(state
, ins
,
21030 MISC(lnode
->val
, 0), lnode
->val
->u
.cval
);
21033 /* By default don't copy the changes,
21034 * recompute them in place instead.
21036 simplify(state
, ins
);
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 */
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
)) {
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
;
21070 if (fedge
->executable
) {
21074 internal_error(state
, 0, "fedge without dst");
21077 internal_error(state
, 0, "fedge without src");
21079 fedge
->executable
= 1;
21080 fblock
= fedge
->dst
;
21081 block
= fblock
->block
;
21083 for(fptr
= fblock
->in
; fptr
; fptr
= fptr
->in_next
) {
21084 if (fptr
->executable
) {
21089 if (state
->compiler
->debug
& DEBUG_SCC_TRANSFORM
) {
21090 fprintf(state
->errout
, "vertex: %d reps: %d\n",
21091 block
->vertex
, reps
);
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
);
21132 for(fptr
= fblock
->in
; fptr
; fptr
= fptr
->in_next
) {
21133 if (fptr
->executable
) {
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
;
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
;
21172 struct triple
**expr
;
21173 expr
= triple_rhs(state
, ins
, 0);
21174 for(; expr
; expr
= triple_rhs(state
, ins
, expr
)) {
21175 struct triple
*rhs
;
21177 for(set
= rhs
?rhs
->use
:0; set
; set
= set
->next
) {
21178 if (set
->member
== ins
) {
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
;
21190 for(set
= lhs
?lhs
->use
:0; set
; set
= set
->next
) {
21191 if (set
->member
== ins
) {
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
;
21204 for(set
= misc
?misc
->use
:0; set
; set
= set
->next
) {
21205 if (set
->member
== ins
) {
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
;
21219 for(set
= targ
?targ
->use
:0; set
; set
= set
->next
) {
21220 if (set
->member
== ins
) {
21225 internal_error(state
, ins
, "targ not used");
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
) {
21239 first
= state
->first
;
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
);
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
) {
21268 static void verify_blocks(struct compile_state
*state
)
21270 struct triple
*ins
;
21271 struct block
*block
;
21273 block
= state
->bb
.first_block
;
21280 struct block_set
*user
, *edge
;
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
);
21289 for(user
= block
->use
; user
; user
= user
->next
) {
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
)) {
21298 for(edge
= user
->member
->edges
; edge
; edge
= edge
->next
) {
21299 if (edge
->member
== block
) {
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
) {
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
,
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
) {
21365 first
= state
->first
;
21368 for(set
= ins
->use
; set
; set
= set
->next
) {
21369 struct triple
**slot
;
21370 struct triple
*use_point
;
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
) {
21382 use_point
= set
->member
;
21383 if (set
->member
->op
== OP_PHI
) {
21384 struct block_set
*bset
;
21386 bset
= set
->member
->u
.block
->use
;
21387 for(edge
= 0; bset
&& (edge
< i
); edge
++) {
21391 internal_error(state
, set
->member
,
21392 "no edge for phi rhs %d", i
);
21394 use_point
= bset
->member
->last
;
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
);
21404 internal_error(state
, ins
,
21405 "non dominated rhs use point %p?", use_point
);
21410 } while(ins
!= first
);
21413 static void verify_rhs(struct compile_state
*state
)
21415 struct triple
*first
, *ins
;
21416 first
= state
->first
;
21419 struct triple
**slot
;
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",
21429 if ((ins
->op
!= OP_PHI
) && (slot
[i
] == ins
)) {
21430 internal_error(state
, ins
,
21431 "ins == rhs[%d] on %s",
21436 } while(ins
!= first
);
21439 static void verify_piece(struct compile_state
*state
)
21441 struct triple
*first
, *ins
;
21442 first
= state
->first
;
21445 struct triple
*ptr
;
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",
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",
21463 } while(ins
!= first
);
21466 static void verify_ins_colors(struct compile_state
*state
)
21468 struct triple
*first
, *ins
;
21470 first
= state
->first
;
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
) ||
21483 (unknown_triple
.use
!= 0) ||
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
;
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!");
21522 } while(ins
!= first
);
21525 static void verify_types(struct compile_state
*state
)
21527 struct triple
*first
, *ins
;
21528 first
= state
->first
;
21531 struct type
*invalid
;
21532 invalid
= invalid_type(state
, ins
->type
);
21534 FILE *fp
= state
->errout
;
21535 fprintf(fp
, "type: ");
21536 name_of(fp
, ins
->type
);
21538 fprintf(fp
, "invalid type: ");
21539 name_of(fp
, invalid
);
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
;
21554 if (ins
->op
!= OP_COPY
) {
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
);
21562 fprintf(fp
, "dst type: ");
21563 name_of(fp
, ins
->type
);
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
);
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");
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"
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
;
21664 unsigned lhs
, rhs
, i
;
21665 info
= ins
->u
.ainfo
;
21668 /* Don't count the clobbers in lhs */
21669 for(i
= 0; i
< lhs
; i
++) {
21670 if (LHS(ins
, i
)->type
== &void_type
) {
21675 fprintf(fp
, "#ASM\n");
21677 for(ptr
= info
->str
; *ptr
; ptr
++) {
21679 unsigned long param
;
21680 struct triple
*piece
;
21690 param
= strtoul(ptr
, &next
, 10);
21692 error(state
, ins
, "Invalid asm template");
21694 if (param
>= (lhs
+ rhs
)) {
21695 error(state
, ins
, "Invalid param %%%u in asm template",
21698 piece
= (param
< lhs
)? LHS(ins
, param
) : RHS(ins
, param
- lhs
);
21700 arch_reg_str(ID_REG(piece
->id
)));
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
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
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"
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
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
21779 #define REGC_GPR16_FIRST REG_AX
21780 #define REGC_GPR16_LAST REG_SP
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"
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"
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,
21858 static const struct {
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
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
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
},
21909 static const struct compiler_flag arch_cpus
[] = {
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 */
21920 static int arch_encode_flag(struct arch_state
*arch
, const char *flag
)
21926 if (strncmp(flag
, "no-", 3) == 0) {
21930 if (act
&& strncmp(flag
, "cpu=", 4) == 0) {
21932 result
= set_flag(arch_cpus
, &arch
->features
, 1, flag
);
21935 result
= set_flag(arch_flags
, &arch
->features
, act
, flag
);
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
)) {
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)) {
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");
21981 #if X86_4_8BIT_GPRS
21985 *equiv
++ = REG_EAX
;
21986 *equiv
++ = REG_DXAX
;
21987 *equiv
++ = REG_EDXEAX
;
21990 #if X86_4_8BIT_GPRS
21994 *equiv
++ = REG_EAX
;
21995 *equiv
++ = REG_DXAX
;
21996 *equiv
++ = REG_EDXEAX
;
21999 #if X86_4_8BIT_GPRS
22003 *equiv
++ = REG_EBX
;
22007 #if X86_4_8BIT_GPRS
22011 *equiv
++ = REG_EBX
;
22014 #if X86_4_8BIT_GPRS
22018 *equiv
++ = REG_ECX
;
22022 #if X86_4_8BIT_GPRS
22026 *equiv
++ = REG_ECX
;
22029 #if X86_4_8BIT_GPRS
22033 *equiv
++ = REG_EDX
;
22034 *equiv
++ = REG_DXAX
;
22035 *equiv
++ = REG_EDXEAX
;
22038 #if X86_4_8BIT_GPRS
22042 *equiv
++ = REG_EDX
;
22043 *equiv
++ = REG_DXAX
;
22044 *equiv
++ = REG_EDXEAX
;
22049 *equiv
++ = REG_EAX
;
22050 *equiv
++ = REG_DXAX
;
22051 *equiv
++ = REG_EDXEAX
;
22056 *equiv
++ = REG_EBX
;
22061 *equiv
++ = REG_ECX
;
22066 *equiv
++ = REG_EDX
;
22067 *equiv
++ = REG_DXAX
;
22068 *equiv
++ = REG_EDXEAX
;
22071 *equiv
++ = REG_ESI
;
22074 *equiv
++ = REG_EDI
;
22077 *equiv
++ = REG_EBP
;
22080 *equiv
++ = REG_ESP
;
22086 *equiv
++ = REG_DXAX
;
22087 *equiv
++ = REG_EDXEAX
;
22103 *equiv
++ = REG_DXAX
;
22104 *equiv
++ = REG_EDXEAX
;
22125 *equiv
++ = REG_EAX
;
22126 *equiv
++ = REG_EDX
;
22127 *equiv
++ = REG_EDXEAX
;
22136 *equiv
++ = REG_EAX
;
22137 *equiv
++ = REG_EDX
;
22138 *equiv
++ = REG_DXAX
;
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
;
22161 static unsigned arch_regcm_normalize(struct compile_state
*state
, unsigned regcm
)
22163 unsigned mask
, result
;
22167 for(class = 0, mask
= 1; mask
; mask
<<= 1, class++) {
22168 if ((result
& mask
) == 0) {
22171 if (class > LAST_REGC
) {
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
);
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
);
22196 static unsigned arch_reg_regcm(struct compile_state
*state
, int reg
)
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);
22208 internal_error(state
, 0, "reg %d not in any class", reg
);
22213 static struct reg_info
arch_reg_constraint(
22214 struct compile_state
*state
, struct type
*type
, const char *constraint
)
22216 static const struct {
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
;
22240 regcm
= arch_type_to_regcm(state
, type
);
22243 for(ptr
= constraint
; *ptr
; ptr
++) {
22248 for(i
= 0; constraints
[i
].class != '\0'; i
++) {
22249 if (constraints
[i
].class == *ptr
) {
22253 if (constraints
[i
].class == '\0') {
22254 error(state
, 0, "invalid register constraint ``%c''", *ptr
);
22257 if ((constraints
[i
].mask
& regcm
) == 0) {
22258 error(state
, 0, "invalid register class %c specified",
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
;
22270 result
.regcm
= mask
;
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
;
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
;
22329 error(state
, 0, "unknown register name `%s' in asm",
22331 result
.reg
= REG_UNSET
;
22337 static int do_select_reg(struct compile_state
*state
,
22338 char *used
, int reg
, unsigned classes
)
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.
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
);
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"
22404 switch(type
->type
& TYPE_MASK
) {
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
;
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
;
22432 mask
= REGCM_GPR32
| REGCM_GPR32_8
|
22433 REGCM_DIVIDEND32
| REGCM_DIVIDEND64
|
22434 REGCM_MMX
| REGCM_XMM
|
22439 mask
= arch_type_to_regcm(state
, type
->left
);
22442 mask
= arch_type_to_regcm(state
, type
->left
) &
22443 arch_type_to_regcm(state
, type
->right
);
22445 case TYPE_BITFIELD
:
22446 mask
= arch_type_to_regcm(state
, type
->left
);
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");
22455 mask
= arch_regcm_normalize(state
, 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
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
;
22481 while(imm
->op
== OP_COPY
) {
22484 if (!is_imm32(imm
)) {
22487 unuse_triple(*expr
, ins
);
22488 use_triple(imm
, ins
);
22493 static int get_imm8(struct triple
*ins
, struct triple
**expr
)
22495 struct triple
*imm
;
22497 while(imm
->op
== OP_COPY
) {
22500 if (!is_imm8(imm
)) {
22503 unuse_triple(*expr
, ins
);
22504 use_triple(imm
, ins
);
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"
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
[] = {
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
] = {
22702 [0] = { REG_UNSET
, REGCM_GPR32
},
22703 [1] = { REG_UNSET
, REGCM_GPR8_LO
},
22706 [TEMPLATE_STORE16
] = {
22708 [0] = { REG_UNSET
, REGCM_GPR32
},
22709 [1] = { REG_UNSET
, REGCM_GPR16
},
22712 [TEMPLATE_STORE32
] = {
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
} },
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
} },
22740 [0] = { REG_VIRT0
, REGCM_GPR16
},
22741 [1] = { REG_UNSET
, REGCM_GPR16
},
22744 [TEMPLATE_BINARY32_REG
] = {
22745 .lhs
= { [0] = { REG_VIRT0
, REGCM_GPR32
} },
22747 [0] = { REG_VIRT0
, REGCM_GPR32
},
22748 [1] = { REG_UNSET
, REGCM_GPR32
},
22751 [TEMPLATE_BINARY8_IMM
] = {
22752 .lhs
= { [0] = { REG_VIRT0
, REGCM_GPR8_LO
} },
22754 [0] = { REG_VIRT0
, REGCM_GPR8_LO
},
22755 [1] = { REG_UNNEEDED
, REGCM_IMM8
},
22758 [TEMPLATE_BINARY16_IMM
] = {
22759 .lhs
= { [0] = { REG_VIRT0
, REGCM_GPR16
} },
22761 [0] = { REG_VIRT0
, REGCM_GPR16
},
22762 [1] = { REG_UNNEEDED
, REGCM_IMM16
},
22765 [TEMPLATE_BINARY32_IMM
] = {
22766 .lhs
= { [0] = { REG_VIRT0
, REGCM_GPR32
} },
22768 [0] = { REG_VIRT0
, REGCM_GPR32
},
22769 [1] = { REG_UNNEEDED
, REGCM_IMM32
},
22772 [TEMPLATE_SL8_CL
] = {
22773 .lhs
= { [0] = { REG_VIRT0
, REGCM_GPR8_LO
} },
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
} },
22782 [0] = { REG_VIRT0
, REGCM_GPR16
},
22783 [1] = { REG_CL
, REGCM_GPR8_LO
},
22786 [TEMPLATE_SL32_CL
] = {
22787 .lhs
= { [0] = { REG_VIRT0
, REGCM_GPR32
} },
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
} },
22796 [0] = { REG_VIRT0
, REGCM_GPR8_LO
},
22797 [1] = { REG_UNNEEDED
, REGCM_IMM8
},
22800 [TEMPLATE_SL16_IMM
] = {
22801 .lhs
= { [0] = { REG_VIRT0
, REGCM_GPR16
} },
22803 [0] = { REG_VIRT0
, REGCM_GPR16
},
22804 [1] = { REG_UNNEEDED
, REGCM_IMM8
},
22807 [TEMPLATE_SL32_IMM
] = {
22808 .lhs
= { [0] = { REG_VIRT0
, REGCM_GPR32
} },
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
} },
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
} },
22836 [0] = { REG_UNSET
, REGCM_GPR16
},
22837 [1] = { REG_UNSET
, REGCM_GPR16
},
22840 [TEMPLATE_CMP32_REG
] = {
22841 .lhs
= { [0] = { REG_EFLAGS
, REGCM_FLAGS
} },
22843 [0] = { REG_UNSET
, REGCM_GPR32
},
22844 [1] = { REG_UNSET
, REGCM_GPR32
},
22847 [TEMPLATE_CMP8_IMM
] = {
22848 .lhs
= { [0] = { REG_EFLAGS
, REGCM_FLAGS
} },
22850 [0] = { REG_UNSET
, REGCM_GPR8_LO
},
22851 [1] = { REG_UNNEEDED
, REGCM_IMM8
},
22854 [TEMPLATE_CMP16_IMM
] = {
22855 .lhs
= { [0] = { REG_EFLAGS
, REGCM_FLAGS
} },
22857 [0] = { REG_UNSET
, REGCM_GPR16
},
22858 [1] = { REG_UNNEEDED
, REGCM_IMM16
},
22861 [TEMPLATE_CMP32_IMM
] = {
22862 .lhs
= { [0] = { REG_EFLAGS
, REGCM_FLAGS
} },
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
} },
22881 .lhs
= { [0] = { REG_UNSET
, REGCM_GPR8_LO
} },
22882 .rhs
= { [0] = { REG_EFLAGS
, REGCM_FLAGS
} },
22885 .rhs
= { [0] = { REG_EFLAGS
, REGCM_FLAGS
} },
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
] = {
22916 [0] = { REG_AL
, REGCM_GPR8_LO
},
22917 [1] = { REG_DX
, REGCM_GPR16
},
22920 [TEMPLATE_OUTB_IMM
] = {
22922 [0] = { REG_AL
, REGCM_GPR8_LO
},
22923 [1] = { REG_UNNEEDED
, REGCM_IMM8
},
22926 [TEMPLATE_OUTW_DX
] = {
22928 [0] = { REG_AX
, REGCM_GPR16
},
22929 [1] = { REG_DX
, REGCM_GPR16
},
22932 [TEMPLATE_OUTW_IMM
] = {
22934 [0] = { REG_AX
, REGCM_GPR16
},
22935 [1] = { REG_UNNEEDED
, REGCM_IMM8
},
22938 [TEMPLATE_OUTL_DX
] = {
22940 [0] = { REG_EAX
, REGCM_GPR32
},
22941 [1] = { REG_DX
, REGCM_GPR16
},
22944 [TEMPLATE_OUTL_IMM
] = {
22946 [0] = { REG_EAX
, REGCM_GPR32
},
22947 [1] = { REG_UNNEEDED
, REGCM_IMM8
},
22951 .lhs
= { [0] = { REG_UNSET
, REGCM_GPR32
} },
22952 .rhs
= { [0] = { REG_UNSET
, REGCM_GPR32
} },
22954 [TEMPLATE_RDMSR
] = {
22956 [0] = { REG_EAX
, REGCM_GPR32
},
22957 [1] = { REG_EDX
, REGCM_GPR32
},
22959 .rhs
= { [0] = { REG_ECX
, REGCM_GPR32
} },
22961 [TEMPLATE_WRMSR
] = {
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
} },
22971 [0] = { REG_AL
, REGCM_GPR8_LO
},
22972 [1] = { REG_UNSET
, REGCM_GPR8_LO
},
22975 [TEMPLATE_UMUL16
] = {
22976 .lhs
= { [0] = { REG_DXAX
, REGCM_DIVIDEND32
} },
22978 [0] = { REG_AX
, REGCM_GPR16
},
22979 [1] = { REG_UNSET
, REGCM_GPR16
},
22982 [TEMPLATE_UMUL32
] = {
22983 .lhs
= { [0] = { REG_EDXEAX
, REGCM_DIVIDEND64
} },
22985 [0] = { REG_EAX
, REGCM_GPR32
},
22986 [1] = { REG_UNSET
, REGCM_GPR32
},
22989 [TEMPLATE_DIV8
] = {
22991 [0] = { REG_AL
, REGCM_GPR8_LO
},
22992 [1] = { REG_AH
, REGCM_GPR8
},
22995 [0] = { REG_AX
, REGCM_GPR16
},
22996 [1] = { REG_UNSET
, REGCM_GPR8_LO
},
22999 [TEMPLATE_DIV16
] = {
23001 [0] = { REG_AX
, REGCM_GPR16
},
23002 [1] = { REG_DX
, REGCM_GPR16
},
23005 [0] = { REG_DXAX
, REGCM_DIVIDEND32
},
23006 [1] = { REG_UNSET
, REGCM_GPR16
},
23009 [TEMPLATE_DIV32
] = {
23011 [0] = { REG_EAX
, REGCM_GPR32
},
23012 [1] = { REG_EDX
, REGCM_GPR32
},
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
;
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
;
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 */
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
;
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
) {
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
;
23120 if (ins
->op
== OP_PIECE
) {
23121 index
= ins
->u
.cval
;
23122 ins
= MISC(ins
, 0);
23125 if (triple_is_def(state
, ins
)) {
23128 if (index
>= zlhs
) {
23129 internal_error(state
, ins
, "index %d out of range for %s",
23130 index
, tops(ins
->op
));
23134 template = &ins
->u
.ainfo
->tmpl
;
23137 if (ins
->template_id
> LAST_TEMPLATE
) {
23138 internal_error(state
, ins
, "bad template number %d",
23141 template = &templates
[ins
->template_id
];
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
);
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
));
23166 template = &ins
->u
.ainfo
->tmpl
;
23172 if (ins
->template_id
> LAST_TEMPLATE
) {
23173 internal_error(state
, ins
, "bad template number %d",
23176 template = &templates
[ins
->template_id
];
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
);
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) {
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
)) {
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);
23239 /* Get constant for the mask value */
23241 the_mask
<<= ins
->u
.bitfield
.size
;
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 */
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 */
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
;
23298 /* Get constant for the mask value */
23300 the_mask
<<= ins
->u
.bitfield
.size
;
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 */
23311 if (shift
->u
.cval
!= 0) {
23313 if (ins
->op
== OP_SEXTRACT
) {
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
);
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
;
23352 ins
->template_id
= TEMPLATE_INTCONST32
;
23353 if (ins
->u
.cval
< 256) {
23354 ins
->template_id
= TEMPLATE_INTCONST8
;
23358 ins
->template_id
= TEMPLATE_INTCONST32
;
23360 case OP_UNKNOWNVAL
:
23361 ins
->template_id
= TEMPLATE_UNKNOWNVAL
;
23367 ins
->template_id
= TEMPLATE_NOP
;
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
;
23395 internal_error(state
, ins
, "bad type passed to copy");
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
;
23410 internal_error(state
, ins
, "bad type passed to phi");
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
);
23424 switch(ins
->type
->type
& TYPE_MASK
) {
23425 case TYPE_CHAR
: case TYPE_UCHAR
:
23426 ins
->template_id
= TEMPLATE_STORE8
;
23428 case TYPE_SHORT
: case TYPE_USHORT
:
23429 ins
->template_id
= TEMPLATE_STORE16
;
23431 case TYPE_INT
: case TYPE_UINT
:
23432 case TYPE_LONG
: case TYPE_ULONG
:
23434 ins
->template_id
= TEMPLATE_STORE32
;
23437 internal_error(state
, ins
, "unknown type in store");
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
:
23450 internal_error(state
, ins
, "unknown type in load");
23453 ins
->template_id
= TEMPLATE_LOAD32
;
23461 ins
->template_id
= TEMPLATE_BINARY32_REG
;
23462 if (get_imm32(ins
, &RHS(ins
, 1))) {
23463 ins
->template_id
= TEMPLATE_BINARY32_IMM
;
23468 ins
->template_id
= TEMPLATE_DIV32
;
23469 next
= after_lhs(state
, ins
);
23472 ins
->template_id
= TEMPLATE_UMUL32
;
23475 next
= mod_div(state
, ins
, OP_UDIVT
, 0);
23478 next
= mod_div(state
, ins
, OP_SDIVT
, 0);
23481 next
= mod_div(state
, ins
, OP_UDIVT
, 1);
23484 next
= mod_div(state
, ins
, OP_SDIVT
, 1);
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);
23498 ins
->template_id
= TEMPLATE_UNARY32
;
23501 bool_cmp(state
, ins
, OP_CMP
, OP_JMP_EQ
, OP_SET_EQ
);
23504 bool_cmp(state
, ins
, OP_CMP
, OP_JMP_NOTEQ
, OP_SET_NOTEQ
);
23507 bool_cmp(state
, ins
, OP_CMP
, OP_JMP_SLESS
, OP_SET_SLESS
);
23510 bool_cmp(state
, ins
, OP_CMP
, OP_JMP_ULESS
, OP_SET_ULESS
);
23513 bool_cmp(state
, ins
, OP_CMP
, OP_JMP_SMORE
, OP_SET_SMORE
);
23516 bool_cmp(state
, ins
, OP_CMP
, OP_JMP_UMORE
, OP_SET_UMORE
);
23519 bool_cmp(state
, ins
, OP_CMP
, OP_JMP_SLESSEQ
, OP_SET_SLESSEQ
);
23522 bool_cmp(state
, ins
, OP_CMP
, OP_JMP_ULESSEQ
, OP_SET_ULESSEQ
);
23525 bool_cmp(state
, ins
, OP_CMP
, OP_JMP_SMOREEQ
, OP_SET_SMOREEQ
);
23528 bool_cmp(state
, ins
, OP_CMP
, OP_JMP_UMOREEQ
, OP_SET_UMOREEQ
);
23531 bool_cmp(state
, ins
, OP_TEST
, OP_JMP_NOTEQ
, OP_SET_NOTEQ
);
23534 bool_cmp(state
, ins
, OP_TEST
, OP_JMP_EQ
, OP_SET_EQ
);
23538 ins
->template_id
= TEMPLATE_NOP
;
23541 fixup_branch(state
, ins
, OP_JMP_NOTEQ
, OP_TEST
,
23542 RHS(ins
, 0)->type
, RHS(ins
, 0), 0);
23545 ins
->template_id
= TEMPLATE_NOP
;
23548 ins
->template_id
= TEMPLATE_RET
;
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;
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;
23576 ins
->template_id
= TEMPLATE_BSF
;
23579 ins
->template_id
= TEMPLATE_RDMSR
;
23580 next
= after_lhs(state
, ins
);
23583 ins
->template_id
= TEMPLATE_WRMSR
;
23586 ins
->template_id
= TEMPLATE_NOP
;
23589 ins
->template_id
= TEMPLATE_NOP
;
23590 next
= after_lhs(state
, ins
);
23592 /* Already transformed instructions */
23594 ins
->template_id
= TEMPLATE_TEST32
;
23597 ins
->template_id
= TEMPLATE_CMP32_REG
;
23598 if (get_imm32(ins
, &RHS(ins
, 1))) {
23599 ins
->template_id
= TEMPLATE_CMP32_IMM
;
23603 ins
->template_id
= TEMPLATE_NOP
;
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
;
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
;
23620 next
= x86_deposit(state
, ins
);
23624 next
= x86_extract(state
, ins
);
23626 /* Unhandled instructions */
23629 internal_error(state
, ins
, "unhandled ins: %d %s",
23630 ins
->op
, tops(ins
->op
));
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
;
23647 if ((label
->op
== OP_LABEL
) ||
23648 (label
->op
== OP_SDECL
)) {
23650 label
->u
.cval
= next_label(state
);
23656 label
= label
->next
;
23657 } while(label
!= first
);
23660 static int check_reg(struct compile_state
*state
,
23661 struct triple
*triple
, int classes
)
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",
23679 #error "Registers have renumberd fix arch_reg_str"
23681 static const char *arch_regs
[] = {
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",
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
))) {
23699 return arch_regs
[reg
];
23702 static const char *reg(struct compile_state
*state
, struct triple
*triple
,
23706 reg
= check_reg(state
, triple
, classes
);
23707 return arch_reg_str(reg
);
23710 static int arch_reg_size(int reg
)
23714 if (reg
== REG_EFLAGS
) {
23717 else if ((reg
>= REG_AL
) && (reg
<= REG_DH
)) {
23720 else if ((reg
>= REG_AX
) && (reg
<= REG_SP
)) {
23723 else if ((reg
>= REG_EAX
) && (reg
<= REG_ESP
)) {
23726 else if (reg
== REG_EDXEAX
) {
23729 else if (reg
== REG_DXAX
) {
23732 else if ((reg
>= REG_MMX0
) && (reg
<= REG_MMX7
)) {
23735 else if ((reg
>= REG_XMM0
) && (reg
<= REG_XMM7
)) {
23741 static int reg_size(struct compile_state
*state
, struct triple
*ins
)
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;
23761 internal_error(state
, 0, "unknown suffix");
23768 static void print_const_val(
23769 struct compile_state
*state
, struct triple
*ins
, FILE *fp
)
23773 fprintf(fp
, " $%ld ",
23774 (long)(ins
->u
.cval
));
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
));
23791 internal_error(state
, ins
, "unknown constant type");
23796 static void print_const(struct compile_state
*state
,
23797 struct triple
*ins
, FILE *fp
)
23801 switch(ins
->type
->type
& TYPE_MASK
) {
23804 fprintf(fp
, ".byte 0x%02lx\n",
23805 (unsigned long)(ins
->u
.cval
));
23809 fprintf(fp
, ".short 0x%04lx\n",
23810 (unsigned long)(ins
->u
.cval
));
23817 fprintf(fp
, ".int %lu\n",
23818 (unsigned long)(ins
->u
.cval
));
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
));
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
));
23844 unsigned char *blob
;
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",
23855 internal_error(state
, ins
, "Unknown constant type");
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
)
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
));
23875 fprintf(fp
, ".fill %ld, 1, 0\n", (long int)fill_bytes
);
23877 fprintf(fp
, ".section \"" TEXT_SECTION
"\"\n");
23881 static long get_mask_pool_ref(
23882 struct compile_state
*state
, struct triple
*ins
, unsigned long mask
, FILE *fp
)
23885 if (mask
== 0xff) {
23888 else if (mask
== 0xffff) {
23892 internal_error(state
, ins
, "unhandled mask value");
23897 static void print_binary_op(struct compile_state
*state
,
23898 const char *op
, struct triple
*ins
, FILE *fp
)
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
));
23912 unsigned lmask
, rmask
;
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
)
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
)
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
));
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
)
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;
23967 internal_error(state
, ins
, "not an in operation");
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
));
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
)
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;
24004 internal_error(state
, ins
, "not an out operation");
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
);
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
) {
24046 if ((ins
->op
== OP_COPY
) || (ins
->op
== OP_CONVERT
)) {
24051 internal_error(state
, ins
, "unknown move operation");
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
))) {
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
))) {
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
),
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
) {
24207 else if (dst_regcm
& REGCM_GPR16
) {
24210 else if (dst_regcm
& REGCM_GPR8_LO
) {
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
),
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
))) {
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
)) {
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
)) {
24282 fprintf(fp
, "\t/*mov %s, %s*/\n",
24283 arch_reg_str(src_reg
),
24284 arch_reg_str(dst_reg
));
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");
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
)) {
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
)));
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
) {
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
;
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");
24357 mask
<<= size_of(state
, dst
->type
);
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
) {
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
) {
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
));
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
;
24397 reg_bits
= reg_size(state
, dst
);
24398 if (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",
24412 reg(state
, dst
, REGCM_GPR32
| REGCM_GPR16
| REGCM_GPR8_LO
));
24413 fprintf(fp
, "\tsar $%d, %s\n",
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",
24420 reg(state
, dst
, REGCM_MMX
| REGCM_XMM
));
24421 fprintf(fp
, "\tpsrad $%d, %s\n",
24423 reg(state
, dst
, REGCM_MMX
| REGCM_XMM
));
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
;
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
:
24456 internal_error(state
, ins
, "unknown type in load");
24457 op
= "<invalid opcode>";
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
;
24473 if (is_const(src
) && (src
->op
== OP_INTCONST
)) {
24475 value
= (long_t
)(src
->u
.cval
);
24476 fprintf(fp
, "\tmov%s $%ld, (%s)\n",
24477 type_suffix(state
, src
->type
),
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
));
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
));
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
)
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
));
24531 unsigned lmask
, rmask
;
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
)
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?");
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"
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;
24594 internal_error(state
, branch
, "Invalid branch op");
24600 if (branch
->op
== OP_CALL
) {
24601 fprintf(fp
, "\t/* call */\n");
24604 fprintf(fp
, "\t%s L%s%lu\n",
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");
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;
24644 internal_error(state
, set
, "Invalid set op");
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
)
24656 case OP_BSF
: op
= "bsf"; break;
24657 case OP_BSR
: op
= "bsr"; break;
24659 internal_error(state
, ins
, "unknown bit scan");
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.
24695 print_op_asm(state
, ins
, fp
);
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;
24712 /* Don't generate anything here for constants */
24714 /* Don't generate anything for variable declarations. */
24716 case OP_UNKNOWNVAL
:
24717 fprintf(fp
, " /* unknown %s */\n",
24718 reg(state
, ins
, REGCM_ALL
));
24721 print_sdecl(state
, ins
, fp
);
24725 print_op_move(state
, ins
, fp
);
24728 print_op_load(state
, ins
, fp
);
24731 print_op_store(state
, ins
, fp
);
24734 print_op_smul(state
, ins
, fp
);
24736 case OP_CMP
: print_op_cmp(state
, ins
, fp
); break;
24737 case OP_TEST
: print_op_test(state
, ins
, fp
); break;
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
:
24745 print_op_branch(state
, ins
, fp
);
24748 print_op_ret(state
, ins
, fp
);
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
);
24757 case OP_INB
: case OP_INW
: case OP_INL
:
24758 print_op_in(state
, ins
, fp
);
24760 case OP_OUTB
: case OP_OUTW
: case OP_OUTL
:
24761 print_op_out(state
, ins
, fp
);
24765 print_op_bit_scan(state
, ins
, fp
);
24768 after_lhs(state
, ins
);
24769 fprintf(fp
, "\trdmsr\n");
24772 fprintf(fp
, "\twrmsr\n");
24775 fprintf(fp
, "\thlt\n");
24778 fprintf(fp
, "\tidiv %s\n", reg(state
, RHS(ins
, 1), REGCM_GPR32
));
24781 fprintf(fp
, "\tdiv %s\n", reg(state
, RHS(ins
, 1), REGCM_GPR32
));
24784 fprintf(fp
, "\tmul %s\n", reg(state
, RHS(ins
, 1), REGCM_GPR32
));
24790 fprintf(fp
, "L%s%lu:\n",
24791 state
->compiler
->label_prefix
, (unsigned long)(ins
->u
.cval
));
24794 /* Ignore adecls with no registers error otherwise */
24795 if (!noop_adecl(ins
)) {
24796 internal_error(state
, ins
, "adecl remains?");
24799 /* Ignore OP_PIECE */
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
:
24809 internal_error(state
, ins
, "unknown op: %d %s",
24810 ins
->op
, tops(ins
->op
));
24815 static void print_instructions(struct compile_state
*state
)
24817 struct triple
*first
, *ins
;
24818 int print_location
;
24819 struct occurrence
*last_occurrence
;
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
;
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
);
24847 struct occurrence
*ptr
;
24849 fprintf(fp
, "\t/*\n");
24851 for(ptr
= ins
->occurrence
; ptr
; ptr
= ptr
->parent
) {
24853 fprintf(fp
, "\t * %s,%s:%d.%d\n",
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
);
24873 } while(ins
!= first
);
24874 if (print_location
) {
24875 fprintf(fp
, "/* max inline depth %d */\n",
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
)
24892 const char *filename
;
24893 fp
= state
->output
;
24897 struct file_state
*file
;
24899 const char *token_str
;
24901 if (tok
== TOK_EOF
) {
24904 tk
= eat(state
, tok
);
24906 tk
->ident
? tk
->ident
->name
:
24907 tk
->str_len
? tk
->val
.str
:
24910 file
= state
->file
;
24911 while(file
->macro
&& file
->prev
) {
24914 if (!file
->macro
&&
24915 ((file
->line
!= line
) || (file
->basename
!= filename
)))
24918 if ((file
->basename
== filename
) &&
24919 (line
< file
->line
)) {
24920 while(line
< file
->line
) {
24926 fprintf(fp
, "\n#line %d \"%s\"\n",
24927 file
->line
, file
->basename
);
24930 filename
= file
->basename
;
24931 col
= get_col(file
) - strlen(token_str
);
24932 for(i
= 0; i
< col
; i
++) {
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
)
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
;
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
;
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);
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
);
25044 /* Exit the global definition scope */
25047 /* Now that basic compilation has happened
25048 * optimize the intermediate code
25052 generate_code(&state
);
25053 if (state
.compiler
->debug
) {
25054 fprintf(state
.errout
, "done\n");
25059 static void version(FILE *fp
)
25061 fprintf(fp
, "romcc " VERSION
" released " RELEASE_DATE
"\n");
25064 static void usage(void)
25069 "\nUsage: romcc [options] <source>.c\n"
25070 "Compile a C source file generating a binary that does not implicilty use RAM\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
);
25080 "\nArchitecture compiler options:\n"
25088 static void arg_error(char *fmt
, ...)
25091 va_start(args
, fmt
);
25092 vfprintf(stderr
, fmt
, args
);
25098 static void arg_warning(char *fmt
, ...)
25102 va_start(args
, fmt
);
25103 vfprintf(stderr
, fmt
, args
);
25107 int main(int argc
, char **argv
)
25109 const char *filename
;
25110 struct compiler_state compiler
;
25111 struct arch_state arch
;
25115 /* I don't want any surprises */
25116 setlocale(LC_ALL
, "C");
25118 init_compiler_state(&compiler
);
25119 init_arch_state(&arch
);
25123 if (!all_opts
&& (strcmp(argv
[1], "-o") == 0) && (argc
> 2)) {
25124 compiler
.ofilename
= argv
[2];
25128 else if (!all_opts
&& argv
[1][0] == '-') {
25131 if (strcmp(argv
[1], "--") == 0) {
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) {
25162 else if (strncmp(argv
[1], "-S", 2) == 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");
25173 include_filelist
->filename
= strdup(argv
[1]);
25174 include_filelist
->next
= old_head
;
25178 arg_error("Invalid option specified: %s\n",
25186 arg_error("Only one filename may be specified\n");
25188 filename
= argv
[1];
25194 arg_error("No filename specified\n");
25196 compile(filename
, &compiler
, &arch
);