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>
25 #define MAX_CWD_SIZE 4096
26 #define MAX_ALLOCATION_PASSES 100
28 /* NOTE: Before you even start thinking to touch anything
29 * in this code, set DEBUG_ROMCC_WARNINGS to 1 to get an
30 * insight on the original author's thoughts. We introduced
31 * this switch as romcc was about the only thing producing
32 * massive warnings in our code..
34 #define DEBUG_ROMCC_WARNINGS 0
36 #define DEBUG_CONSISTENCY 1
37 #define DEBUG_SDP_BLOCKS 0
38 #define DEBUG_TRIPLE_COLOR 0
40 #define DEBUG_DISPLAY_USES 1
41 #define DEBUG_DISPLAY_TYPES 1
42 #define DEBUG_REPLACE_CLOSURE_TYPE_HIRES 0
43 #define DEBUG_DECOMPOSE_PRINT_TUPLES 0
44 #define DEBUG_DECOMPOSE_HIRES 0
45 #define DEBUG_INITIALIZER 0
46 #define DEBUG_UPDATE_CLOSURE_TYPE 0
47 #define DEBUG_LOCAL_TRIPLE 0
48 #define DEBUG_BASIC_BLOCKS_VERBOSE 0
49 #define DEBUG_CPS_RENAME_VARIABLES_HIRES 0
50 #define DEBUG_SIMPLIFY_HIRES 0
51 #define DEBUG_SHRINKING 0
52 #define DEBUG_COALESCE_HITCHES 0
53 #define DEBUG_CODE_ELIMINATION 0
55 #define DEBUG_EXPLICIT_CLOSURES 0
57 #if DEBUG_ROMCC_WARNINGS
58 #warning "FIXME give clear error messages about unused variables"
59 #warning "FIXME properly handle multi dimensional arrays"
60 #warning "FIXME handle multiple register sizes"
63 /* Control flow graph of a loop without goto.
74 * |\ GGG HHH | continue;
102 * DFlocal(X) = { Y <- Succ(X) | idom(Y) != X }
103 * DFup(Z) = { Y <- DF(Z) | idom(Y) != X }
106 * [] == DFlocal(X) U DF(X)
109 * Dominator graph of the same nodes.
113 * BBB JJJ BBB: [ JJJ ] ( JJJ ) JJJ: [ ] ()
115 * CCC CCC: [ ] ( BBB, JJJ )
117 * DDD EEE DDD: [ ] ( BBB ) EEE: [ JJJ ] ()
119 * FFF FFF: [ ] ( BBB )
121 * GGG HHH GGG: [ ] ( BBB ) HHH: [ BBB ] ()
123 * III III: [ BBB ] ()
126 * BBB and JJJ are definitely the dominance frontier.
127 * Where do I place phi functions and how do I make that decision.
132 const char *filename
;
133 struct filelist
*next
;
136 struct filelist
*include_filelist
= NULL
;
138 static void __attribute__((noreturn
)) die(char *fmt
, ...)
143 vfprintf(stderr
, fmt
, args
);
150 static void *xmalloc(size_t size
, const char *name
)
155 die("Cannot malloc %ld bytes to hold %s: %s\n",
156 size
+ 0UL, name
, strerror(errno
));
161 static void *xcmalloc(size_t size
, const char *name
)
164 buf
= xmalloc(size
, name
);
165 memset(buf
, 0, size
);
169 static void *xrealloc(void *ptr
, size_t size
, const char *name
)
172 buf
= realloc(ptr
, size
);
174 die("Cannot realloc %ld bytes to hold %s: %s\n",
175 size
+ 0UL, name
, strerror(errno
));
180 static void xfree(const void *ptr
)
185 static char *xstrdup(const char *str
)
190 new = xmalloc(len
+ 1, "xstrdup string");
191 memcpy(new, str
, len
);
196 static void xchdir(const char *path
)
198 if (chdir(path
) != 0) {
199 die("chdir to `%s' failed: %s\n",
200 path
, strerror(errno
));
204 static int exists(const char *dirname
, const char *filename
)
206 char cwd
[MAX_CWD_SIZE
];
209 if (getcwd(cwd
, sizeof(cwd
)) == 0) {
210 die("cwd buffer to small");
214 if (chdir(dirname
) != 0) {
217 if (does_exist
&& (access(filename
, O_RDONLY
) < 0)) {
218 if ((errno
!= EACCES
) && (errno
!= EROFS
)) {
226 static off_t
get_file_size(FILE *f
)
230 if (fd
== -1) return -1;
231 if (fstat(fd
, &s
) == -1) return -1;
235 static char *slurp_file(const char *dirname
, const char *filename
, off_t
*r_size
)
237 char cwd
[MAX_CWD_SIZE
];
239 off_t size
, progress
;
247 if (getcwd(cwd
, sizeof(cwd
)) == 0) {
248 die("cwd buffer to small");
251 file
= fopen(filename
, "rb");
254 die("Cannot open '%s' : %s\n",
255 filename
, strerror(errno
));
257 size
= get_file_size(file
);
259 die("Could not fetch size of '%s': %s\n", filename
, strerror(errno
));
262 buf
= xmalloc(size
+2, filename
);
263 buf
[size
] = '\n'; /* Make certain the file is newline terminated */
264 buf
[size
+1] = '\0'; /* Null terminate the file for good measure */
266 while(progress
< size
) {
267 result
= fread(buf
+ progress
, 1, size
- progress
, file
);
269 if ((errno
== EINTR
) || (errno
== EAGAIN
))
271 die("read on %s of %ld bytes failed: %s\n",
272 filename
, (size
- progress
)+ 0UL, strerror(errno
));
280 /* Types on the destination platform */
281 #if DEBUG_ROMCC_WARNINGS
282 #warning "FIXME this assumes 32bit x86 is the destination"
284 typedef int8_t schar_t
;
285 typedef uint8_t uchar_t
;
286 typedef int8_t char_t
;
287 typedef int16_t short_t
;
288 typedef uint16_t ushort_t
;
289 typedef int32_t int_t
;
290 typedef uint32_t uint_t
;
291 typedef int32_t long_t
;
292 #define ulong_t uint32_t
294 #define SCHAR_T_MIN (-128)
295 #define SCHAR_T_MAX 127
296 #define UCHAR_T_MAX 255
297 #define CHAR_T_MIN SCHAR_T_MIN
298 #define CHAR_T_MAX SCHAR_T_MAX
299 #define SHRT_T_MIN (-32768)
300 #define SHRT_T_MAX 32767
301 #define USHRT_T_MAX 65535
302 #define INT_T_MIN (-LONG_T_MAX - 1)
303 #define INT_T_MAX 2147483647
304 #define UINT_T_MAX 4294967295U
305 #define LONG_T_MIN (-LONG_T_MAX - 1)
306 #define LONG_T_MAX 2147483647
307 #define ULONG_T_MAX 4294967295U
310 #define SIZEOF_I16 16
311 #define SIZEOF_I32 32
312 #define SIZEOF_I64 64
314 #define SIZEOF_CHAR 8
315 #define SIZEOF_SHORT 16
316 #define SIZEOF_INT 32
317 #define SIZEOF_LONG (sizeof(long_t)*SIZEOF_CHAR)
320 #define ALIGNOF_CHAR 8
321 #define ALIGNOF_SHORT 16
322 #define ALIGNOF_INT 32
323 #define ALIGNOF_LONG (sizeof(long_t)*SIZEOF_CHAR)
325 #define REG_SIZEOF_REG 32
326 #define REG_SIZEOF_CHAR REG_SIZEOF_REG
327 #define REG_SIZEOF_SHORT REG_SIZEOF_REG
328 #define REG_SIZEOF_INT REG_SIZEOF_REG
329 #define REG_SIZEOF_LONG REG_SIZEOF_REG
331 #define REG_ALIGNOF_REG REG_SIZEOF_REG
332 #define REG_ALIGNOF_CHAR REG_SIZEOF_REG
333 #define REG_ALIGNOF_SHORT REG_SIZEOF_REG
334 #define REG_ALIGNOF_INT REG_SIZEOF_REG
335 #define REG_ALIGNOF_LONG REG_SIZEOF_REG
337 /* Additional definitions for clarity.
338 * I currently assume a long is the largest native
339 * machine word and that a pointer fits into it.
341 #define SIZEOF_WORD SIZEOF_LONG
342 #define SIZEOF_POINTER SIZEOF_LONG
343 #define ALIGNOF_WORD ALIGNOF_LONG
344 #define ALIGNOF_POINTER ALIGNOF_LONG
345 #define REG_SIZEOF_POINTER REG_SIZEOF_LONG
346 #define REG_ALIGNOF_POINTER REG_ALIGNOF_LONG
349 struct file_state
*prev
;
350 const char *basename
;
356 const char *line_start
;
358 const char *report_name
;
359 const char *report_dir
;
367 struct hash_entry
*ident
;
377 /* I have two classes of types:
379 * Logical types. (The type the C standard says the operation is of)
381 * The operational types are:
396 * No memory is useable by the compiler.
397 * There is no floating point support.
398 * All operations take place in general purpose registers.
399 * There is one type of general purpose register.
400 * Unsigned longs are stored in that general purpose register.
403 /* Operations on general purpose registers.
422 #define OP_POS 16 /* Dummy positive operator don't use it */
432 #define OP_SLESSEQ 26
433 #define OP_ULESSEQ 27
434 #define OP_SMOREEQ 28
435 #define OP_UMOREEQ 29
437 #define OP_LFALSE 30 /* Test if the expression is logically false */
438 #define OP_LTRUE 31 /* Test if the expression is logcially true */
442 /* For OP_STORE ->type holds the type
443 * RHS(0) holds the destination address
444 * RHS(1) holds the value to store.
447 #define OP_UEXTRACT 34
448 /* OP_UEXTRACT extracts an unsigned bitfield from a pseudo register
449 * RHS(0) holds the psuedo register to extract from
450 * ->type holds the size of the bitfield.
451 * ->u.bitfield.size holds the size of the bitfield.
452 * ->u.bitfield.offset holds the offset to extract from
454 #define OP_SEXTRACT 35
455 /* OP_SEXTRACT extracts a signed bitfield from a pseudo register
456 * RHS(0) holds the psuedo register to extract from
457 * ->type holds the size of the bitfield.
458 * ->u.bitfield.size holds the size of the bitfield.
459 * ->u.bitfield.offset holds the offset to extract from
461 #define OP_DEPOSIT 36
462 /* OP_DEPOSIT replaces a bitfield with a new value.
463 * RHS(0) holds the value to replace a bitifield in.
464 * RHS(1) holds the replacement value
465 * ->u.bitfield.size holds the size of the bitfield.
466 * ->u.bitfield.offset holds the deposit into
471 #define OP_MIN_CONST 50
472 #define OP_MAX_CONST 58
473 #define IS_CONST_OP(X) (((X) >= OP_MIN_CONST) && ((X) <= OP_MAX_CONST))
474 #define OP_INTCONST 50
475 /* For OP_INTCONST ->type holds the type.
476 * ->u.cval holds the constant value.
478 #define OP_BLOBCONST 51
479 /* For OP_BLOBCONST ->type holds the layout and size
480 * information. u.blob holds a pointer to the raw binary
481 * data for the constant initializer.
483 #define OP_ADDRCONST 52
484 /* For OP_ADDRCONST ->type holds the type.
485 * MISC(0) holds the reference to the static variable.
486 * ->u.cval holds an offset from that value.
488 #define OP_UNKNOWNVAL 59
489 /* For OP_UNKNOWNAL ->type holds the type.
490 * For some reason we don't know what value this type has.
491 * This allows for variables that have don't have values
492 * assigned yet, or variables whose value we simply do not know.
496 /* OP_WRITE moves one pseudo register to another.
497 * MISC(0) holds the destination pseudo register, which must be an OP_DECL.
498 * RHS(0) holds the psuedo to move.
502 /* OP_READ reads the value of a variable and makes
503 * it available for the pseudo operation.
504 * Useful for things like def-use chains.
505 * RHS(0) holds points to the triple to read from.
508 /* OP_COPY makes a copy of the pseudo register or constant in RHS(0).
510 #define OP_CONVERT 63
511 /* OP_CONVERT makes a copy of the pseudo register or constant in RHS(0).
512 * And then the type is converted appropriately.
515 /* OP_PIECE returns one piece of a instruction that returns a structure.
516 * MISC(0) is the instruction
517 * u.cval is the LHS piece of the instruction to return.
520 /* OP_ASM holds a sequence of assembly instructions, the result
521 * of a C asm directive.
522 * RHS(x) holds input value x to the assembly sequence.
523 * LHS(x) holds the output value x from the assembly sequence.
524 * u.blob holds the string of assembly instructions.
528 /* OP_DEREF generates an lvalue from a pointer.
529 * RHS(0) holds the pointer value.
530 * OP_DEREF serves as a place holder to indicate all necessary
531 * checks have been done to indicate a value is an lvalue.
534 /* OP_DOT references a submember of a structure lvalue.
535 * MISC(0) holds the lvalue.
536 * ->u.field holds the name of the field we want.
538 * Not seen after structures are flattened.
541 /* OP_INDEX references a submember of a tuple or array lvalue.
542 * MISC(0) holds the lvalue.
543 * ->u.cval holds the index into the lvalue.
545 * Not seen after structures are flattened.
548 /* OP_VAL returns the value of a subexpression of the current expression.
549 * Useful for operators that have side effects.
550 * RHS(0) holds the expression.
551 * MISC(0) holds the subexpression of RHS(0) that is the
552 * value of the expression.
554 * Not seen outside of expressions.
558 /* OP_TUPLE is an array of triples that are either variable
559 * or values for a structure or an array. It is used as
560 * a place holder when flattening compound types.
561 * The value represented by an OP_TUPLE is held in N registers.
562 * LHS(0..N-1) refer to those registers.
563 * ->use is a list of statements that use the value.
565 * Although OP_TUPLE always has register sized pieces they are not
566 * used until structures are flattened/decomposed into their register
568 * ???? registers ????
572 /* OP_BITREF describes a bitfield as an lvalue.
573 * RHS(0) holds the register value.
574 * ->type holds the type of the bitfield.
575 * ->u.bitfield.size holds the size of the bitfield.
576 * ->u.bitfield.offset holds the offset of the bitfield in the register
581 /* OP_FCALL performs a procedure call.
582 * MISC(0) holds a pointer to the OP_LIST of a function
583 * RHS(x) holds argument x of a function
585 * Currently not seen outside of expressions.
588 /* OP_PROG is an expression that holds a list of statements, or
589 * expressions. The final expression is the value of the expression.
590 * RHS(0) holds the start of the list.
595 /* OP_LIST Holds a list of statements that compose a function, and a result value.
596 * RHS(0) holds the list of statements.
597 * A list of all functions is maintained.
600 #define OP_BRANCH 81 /* an unconditional branch */
601 /* For branch instructions
602 * TARG(0) holds the branch target.
603 * ->next holds where to branch to if the branch is not taken.
604 * The branch target can only be a label
607 #define OP_CBRANCH 82 /* a conditional branch */
608 /* For conditional branch instructions
609 * RHS(0) holds the branch condition.
610 * TARG(0) holds the branch target.
611 * ->next holds where to branch to if the branch is not taken.
612 * The branch target can only be a label
615 #define OP_CALL 83 /* an uncontional branch that will return */
616 /* For call instructions
617 * MISC(0) holds the OP_RET that returns from the branch
618 * TARG(0) holds the branch target.
619 * ->next holds where to branch to if the branch is not taken.
620 * The branch target can only be a label
623 #define OP_RET 84 /* an uncontinonal branch through a variable back to an OP_CALL */
624 /* For call instructions
625 * RHS(0) holds the variable with the return address
626 * The branch target can only be a label
630 /* OP_LABEL is a triple that establishes an target for branches.
631 * ->use is the list of all branches that use this label.
635 /* OP_ADECL is a triple that establishes an lvalue for assignments.
636 * A variable takes N registers to contain.
637 * LHS(0..N-1) refer to an OP_PIECE triple that represents
638 * the Xth register that the variable is stored in.
639 * ->use is a list of statements that use the variable.
641 * Although OP_ADECL always has register sized pieces they are not
642 * used until structures are flattened/decomposed into their register
647 /* OP_SDECL is a triple that establishes a variable of static
649 * ->use is a list of statements that use the variable.
650 * MISC(0) holds the initializer expression.
655 /* OP_PHI is a triple used in SSA form code.
656 * It is used when multiple code paths merge and a variable needs
657 * a single assignment from any of those code paths.
658 * The operation is a cross between OP_DECL and OP_WRITE, which
659 * is what OP_PHI is generated from.
661 * RHS(x) points to the value from code path x
662 * The number of RHS entries is the number of control paths into the block
663 * in which OP_PHI resides. The elements of the array point to point
664 * to the variables OP_PHI is derived from.
666 * MISC(0) holds a pointer to the orginal OP_DECL node.
670 /* continuation helpers
672 #define OP_CPS_BRANCH 90 /* an unconditional branch */
673 /* OP_CPS_BRANCH calls a continuation
674 * RHS(x) holds argument x of the function
675 * TARG(0) holds OP_CPS_START target
677 #define OP_CPS_CBRANCH 91 /* a conditional branch */
678 /* OP_CPS_CBRANCH conditionally calls one of two continuations
679 * RHS(0) holds the branch condition
680 * RHS(x + 1) holds argument x of the function
681 * TARG(0) holds the OP_CPS_START to jump to when true
682 * ->next holds the OP_CPS_START to jump to when false
684 #define OP_CPS_CALL 92 /* an uncontional branch that will return */
685 /* For OP_CPS_CALL instructions
686 * RHS(x) holds argument x of the function
687 * MISC(0) holds the OP_CPS_RET that returns from the branch
688 * TARG(0) holds the branch target.
689 * ->next holds where the OP_CPS_RET will return to.
691 #define OP_CPS_RET 93
692 /* OP_CPS_RET conditionally calls one of two continuations
693 * RHS(0) holds the variable with the return function address
694 * RHS(x + 1) holds argument x of the function
695 * The branch target may be any OP_CPS_START
697 #define OP_CPS_END 94
698 /* OP_CPS_END is the triple at the end of the program.
699 * For most practical purposes it is a branch.
701 #define OP_CPS_START 95
702 /* OP_CPS_START is a triple at the start of a continuation
703 * The arguments variables takes N registers to contain.
704 * LHS(0..N-1) refer to an OP_PIECE triple that represents
705 * the Xth register that the arguments are stored in.
709 /* Architecture specific instructions */
712 #define OP_SET_EQ 102
713 #define OP_SET_NOTEQ 103
714 #define OP_SET_SLESS 104
715 #define OP_SET_ULESS 105
716 #define OP_SET_SMORE 106
717 #define OP_SET_UMORE 107
718 #define OP_SET_SLESSEQ 108
719 #define OP_SET_ULESSEQ 109
720 #define OP_SET_SMOREEQ 110
721 #define OP_SET_UMOREEQ 111
724 #define OP_JMP_EQ 113
725 #define OP_JMP_NOTEQ 114
726 #define OP_JMP_SLESS 115
727 #define OP_JMP_ULESS 116
728 #define OP_JMP_SMORE 117
729 #define OP_JMP_UMORE 118
730 #define OP_JMP_SLESSEQ 119
731 #define OP_JMP_ULESSEQ 120
732 #define OP_JMP_SMOREEQ 121
733 #define OP_JMP_UMOREEQ 122
735 /* Builtin operators that it is just simpler to use the compiler for */
751 #define PURE 0x001 /* Triple has no side effects */
752 #define IMPURE 0x002 /* Triple has side effects */
753 #define PURE_BITS(FLAGS) ((FLAGS) & 0x3)
754 #define DEF 0x004 /* Triple is a variable definition */
755 #define BLOCK 0x008 /* Triple stores the current block */
756 #define STRUCTURAL 0x010 /* Triple does not generate a machine instruction */
757 #define BRANCH_BITS(FLAGS) ((FLAGS) & 0xe0 )
758 #define UBRANCH 0x020 /* Triple is an unconditional branch instruction */
759 #define CBRANCH 0x040 /* Triple is a conditional branch instruction */
760 #define RETBRANCH 0x060 /* Triple is a return instruction */
761 #define CALLBRANCH 0x080 /* Triple is a call instruction */
762 #define ENDBRANCH 0x0a0 /* Triple is an end instruction */
763 #define PART 0x100 /* Triple is really part of another triple */
764 #define BITFIELD 0x200 /* Triple manipulates a bitfield */
765 signed char lhs
, rhs
, misc
, targ
;
768 #define OP(LHS, RHS, MISC, TARG, FLAGS, NAME) { \
776 static const struct op_info table_ops
[] = {
777 [OP_SDIVT
] = OP( 2, 2, 0, 0, PURE
| BLOCK
, "sdivt"),
778 [OP_UDIVT
] = OP( 2, 2, 0, 0, PURE
| BLOCK
, "udivt"),
779 [OP_SMUL
] = OP( 0, 2, 0, 0, PURE
| DEF
| BLOCK
, "smul"),
780 [OP_UMUL
] = OP( 0, 2, 0, 0, PURE
| DEF
| BLOCK
, "umul"),
781 [OP_SDIV
] = OP( 0, 2, 0, 0, PURE
| DEF
| BLOCK
, "sdiv"),
782 [OP_UDIV
] = OP( 0, 2, 0, 0, PURE
| DEF
| BLOCK
, "udiv"),
783 [OP_SMOD
] = OP( 0, 2, 0, 0, PURE
| DEF
| BLOCK
, "smod"),
784 [OP_UMOD
] = OP( 0, 2, 0, 0, PURE
| DEF
| BLOCK
, "umod"),
785 [OP_ADD
] = OP( 0, 2, 0, 0, PURE
| DEF
| BLOCK
, "add"),
786 [OP_SUB
] = OP( 0, 2, 0, 0, PURE
| DEF
| BLOCK
, "sub"),
787 [OP_SL
] = OP( 0, 2, 0, 0, PURE
| DEF
| BLOCK
, "sl"),
788 [OP_USR
] = OP( 0, 2, 0, 0, PURE
| DEF
| BLOCK
, "usr"),
789 [OP_SSR
] = OP( 0, 2, 0, 0, PURE
| DEF
| BLOCK
, "ssr"),
790 [OP_AND
] = OP( 0, 2, 0, 0, PURE
| DEF
| BLOCK
, "and"),
791 [OP_XOR
] = OP( 0, 2, 0, 0, PURE
| DEF
| BLOCK
, "xor"),
792 [OP_OR
] = OP( 0, 2, 0, 0, PURE
| DEF
| BLOCK
, "or"),
793 [OP_POS
] = OP( 0, 1, 0, 0, PURE
| DEF
| BLOCK
, "pos"),
794 [OP_NEG
] = OP( 0, 1, 0, 0, PURE
| DEF
| BLOCK
, "neg"),
795 [OP_INVERT
] = OP( 0, 1, 0, 0, PURE
| DEF
| BLOCK
, "invert"),
797 [OP_EQ
] = OP( 0, 2, 0, 0, PURE
| DEF
| BLOCK
, "eq"),
798 [OP_NOTEQ
] = OP( 0, 2, 0, 0, PURE
| DEF
| BLOCK
, "noteq"),
799 [OP_SLESS
] = OP( 0, 2, 0, 0, PURE
| DEF
| BLOCK
, "sless"),
800 [OP_ULESS
] = OP( 0, 2, 0, 0, PURE
| DEF
| BLOCK
, "uless"),
801 [OP_SMORE
] = OP( 0, 2, 0, 0, PURE
| DEF
| BLOCK
, "smore"),
802 [OP_UMORE
] = OP( 0, 2, 0, 0, PURE
| DEF
| BLOCK
, "umore"),
803 [OP_SLESSEQ
] = OP( 0, 2, 0, 0, PURE
| DEF
| BLOCK
, "slesseq"),
804 [OP_ULESSEQ
] = OP( 0, 2, 0, 0, PURE
| DEF
| BLOCK
, "ulesseq"),
805 [OP_SMOREEQ
] = OP( 0, 2, 0, 0, PURE
| DEF
| BLOCK
, "smoreeq"),
806 [OP_UMOREEQ
] = OP( 0, 2, 0, 0, PURE
| DEF
| BLOCK
, "umoreeq"),
807 [OP_LFALSE
] = OP( 0, 1, 0, 0, PURE
| DEF
| BLOCK
, "lfalse"),
808 [OP_LTRUE
] = OP( 0, 1, 0, 0, PURE
| DEF
| BLOCK
, "ltrue"),
810 [OP_LOAD
] = OP( 0, 1, 0, 0, PURE
| DEF
| BLOCK
, "load"),
811 [OP_STORE
] = OP( 0, 2, 0, 0, PURE
| BLOCK
, "store"),
813 [OP_UEXTRACT
] = OP( 0, 1, 0, 0, PURE
| DEF
| BITFIELD
, "uextract"),
814 [OP_SEXTRACT
] = OP( 0, 1, 0, 0, PURE
| DEF
| BITFIELD
, "sextract"),
815 [OP_DEPOSIT
] = OP( 0, 2, 0, 0, PURE
| DEF
| BITFIELD
, "deposit"),
817 [OP_NOOP
] = OP( 0, 0, 0, 0, PURE
| BLOCK
| STRUCTURAL
, "noop"),
819 [OP_INTCONST
] = OP( 0, 0, 0, 0, PURE
| DEF
, "intconst"),
820 [OP_BLOBCONST
] = OP( 0, 0, 0, 0, PURE
, "blobconst"),
821 [OP_ADDRCONST
] = OP( 0, 0, 1, 0, PURE
| DEF
, "addrconst"),
822 [OP_UNKNOWNVAL
] = OP( 0, 0, 0, 0, PURE
| DEF
, "unknown"),
824 #if DEBUG_ROMCC_WARNINGS
825 #warning "FIXME is it correct for OP_WRITE to be a def? I currently use it as one..."
827 [OP_WRITE
] = OP( 0, 1, 1, 0, PURE
| DEF
| BLOCK
, "write"),
828 [OP_READ
] = OP( 0, 1, 0, 0, PURE
| DEF
| BLOCK
, "read"),
829 [OP_COPY
] = OP( 0, 1, 0, 0, PURE
| DEF
| BLOCK
, "copy"),
830 [OP_CONVERT
] = OP( 0, 1, 0, 0, PURE
| DEF
| BLOCK
, "convert"),
831 [OP_PIECE
] = OP( 0, 0, 1, 0, PURE
| DEF
| STRUCTURAL
| PART
, "piece"),
832 [OP_ASM
] = OP(-1, -1, 0, 0, PURE
, "asm"),
833 [OP_DEREF
] = OP( 0, 1, 0, 0, 0 | DEF
| BLOCK
, "deref"),
834 [OP_DOT
] = OP( 0, 0, 1, 0, PURE
| DEF
| PART
, "dot"),
835 [OP_INDEX
] = OP( 0, 0, 1, 0, PURE
| DEF
| PART
, "index"),
837 [OP_VAL
] = OP( 0, 1, 1, 0, 0 | DEF
| BLOCK
, "val"),
838 [OP_TUPLE
] = OP(-1, 0, 0, 0, 0 | PURE
| BLOCK
| STRUCTURAL
, "tuple"),
839 [OP_BITREF
] = OP( 0, 1, 0, 0, 0 | DEF
| PURE
| STRUCTURAL
| BITFIELD
, "bitref"),
840 /* Call is special most it can stand in for anything so it depends on context */
841 [OP_FCALL
] = OP( 0, -1, 1, 0, 0 | BLOCK
| CALLBRANCH
, "fcall"),
842 [OP_PROG
] = OP( 0, 1, 0, 0, 0 | IMPURE
| BLOCK
| STRUCTURAL
, "prog"),
843 /* The sizes of OP_FCALL depends upon context */
845 [OP_LIST
] = OP( 0, 1, 1, 0, 0 | DEF
| STRUCTURAL
, "list"),
846 [OP_BRANCH
] = OP( 0, 0, 0, 1, PURE
| BLOCK
| UBRANCH
, "branch"),
847 [OP_CBRANCH
] = OP( 0, 1, 0, 1, PURE
| BLOCK
| CBRANCH
, "cbranch"),
848 [OP_CALL
] = OP( 0, 0, 1, 1, PURE
| BLOCK
| CALLBRANCH
, "call"),
849 [OP_RET
] = OP( 0, 1, 0, 0, PURE
| BLOCK
| RETBRANCH
, "ret"),
850 [OP_LABEL
] = OP( 0, 0, 0, 0, PURE
| BLOCK
| STRUCTURAL
, "label"),
851 [OP_ADECL
] = OP( 0, 0, 0, 0, PURE
| BLOCK
| STRUCTURAL
, "adecl"),
852 [OP_SDECL
] = OP( 0, 0, 1, 0, PURE
| BLOCK
| STRUCTURAL
, "sdecl"),
853 /* The number of RHS elements of OP_PHI depend upon context */
854 [OP_PHI
] = OP( 0, -1, 1, 0, PURE
| DEF
| BLOCK
, "phi"),
857 [OP_CPS_BRANCH
] = OP( 0, -1, 0, 1, PURE
| BLOCK
| UBRANCH
, "cps_branch"),
858 [OP_CPS_CBRANCH
] = OP( 0, -1, 0, 1, PURE
| BLOCK
| CBRANCH
, "cps_cbranch"),
859 [OP_CPS_CALL
] = OP( 0, -1, 1, 1, PURE
| BLOCK
| CALLBRANCH
, "cps_call"),
860 [OP_CPS_RET
] = OP( 0, -1, 0, 0, PURE
| BLOCK
| RETBRANCH
, "cps_ret"),
861 [OP_CPS_END
] = OP( 0, -1, 0, 0, IMPURE
| BLOCK
| ENDBRANCH
, "cps_end"),
862 [OP_CPS_START
] = OP( -1, 0, 0, 0, PURE
| BLOCK
| STRUCTURAL
, "cps_start"),
865 [OP_CMP
] = OP( 0, 2, 0, 0, PURE
| DEF
| BLOCK
, "cmp"),
866 [OP_TEST
] = OP( 0, 1, 0, 0, PURE
| DEF
| BLOCK
, "test"),
867 [OP_SET_EQ
] = OP( 0, 1, 0, 0, PURE
| DEF
| BLOCK
, "set_eq"),
868 [OP_SET_NOTEQ
] = OP( 0, 1, 0, 0, PURE
| DEF
| BLOCK
, "set_noteq"),
869 [OP_SET_SLESS
] = OP( 0, 1, 0, 0, PURE
| DEF
| BLOCK
, "set_sless"),
870 [OP_SET_ULESS
] = OP( 0, 1, 0, 0, PURE
| DEF
| BLOCK
, "set_uless"),
871 [OP_SET_SMORE
] = OP( 0, 1, 0, 0, PURE
| DEF
| BLOCK
, "set_smore"),
872 [OP_SET_UMORE
] = OP( 0, 1, 0, 0, PURE
| DEF
| BLOCK
, "set_umore"),
873 [OP_SET_SLESSEQ
] = OP( 0, 1, 0, 0, PURE
| DEF
| BLOCK
, "set_slesseq"),
874 [OP_SET_ULESSEQ
] = OP( 0, 1, 0, 0, PURE
| DEF
| BLOCK
, "set_ulesseq"),
875 [OP_SET_SMOREEQ
] = OP( 0, 1, 0, 0, PURE
| DEF
| BLOCK
, "set_smoreq"),
876 [OP_SET_UMOREEQ
] = OP( 0, 1, 0, 0, PURE
| DEF
| BLOCK
, "set_umoreq"),
877 [OP_JMP
] = OP( 0, 0, 0, 1, PURE
| BLOCK
| UBRANCH
, "jmp"),
878 [OP_JMP_EQ
] = OP( 0, 1, 0, 1, PURE
| BLOCK
| CBRANCH
, "jmp_eq"),
879 [OP_JMP_NOTEQ
] = OP( 0, 1, 0, 1, PURE
| BLOCK
| CBRANCH
, "jmp_noteq"),
880 [OP_JMP_SLESS
] = OP( 0, 1, 0, 1, PURE
| BLOCK
| CBRANCH
, "jmp_sless"),
881 [OP_JMP_ULESS
] = OP( 0, 1, 0, 1, PURE
| BLOCK
| CBRANCH
, "jmp_uless"),
882 [OP_JMP_SMORE
] = OP( 0, 1, 0, 1, PURE
| BLOCK
| CBRANCH
, "jmp_smore"),
883 [OP_JMP_UMORE
] = OP( 0, 1, 0, 1, PURE
| BLOCK
| CBRANCH
, "jmp_umore"),
884 [OP_JMP_SLESSEQ
] = OP( 0, 1, 0, 1, PURE
| BLOCK
| CBRANCH
, "jmp_slesseq"),
885 [OP_JMP_ULESSEQ
] = OP( 0, 1, 0, 1, PURE
| BLOCK
| CBRANCH
, "jmp_ulesseq"),
886 [OP_JMP_SMOREEQ
] = OP( 0, 1, 0, 1, PURE
| BLOCK
| CBRANCH
, "jmp_smoreq"),
887 [OP_JMP_UMOREEQ
] = OP( 0, 1, 0, 1, PURE
| BLOCK
| CBRANCH
, "jmp_umoreq"),
889 [OP_INB
] = OP( 0, 1, 0, 0, IMPURE
| DEF
| BLOCK
, "__inb"),
890 [OP_INW
] = OP( 0, 1, 0, 0, IMPURE
| DEF
| BLOCK
, "__inw"),
891 [OP_INL
] = OP( 0, 1, 0, 0, IMPURE
| DEF
| BLOCK
, "__inl"),
892 [OP_OUTB
] = OP( 0, 2, 0, 0, IMPURE
| BLOCK
, "__outb"),
893 [OP_OUTW
] = OP( 0, 2, 0, 0, IMPURE
| BLOCK
, "__outw"),
894 [OP_OUTL
] = OP( 0, 2, 0, 0, IMPURE
| BLOCK
, "__outl"),
895 [OP_BSF
] = OP( 0, 1, 0, 0, PURE
| DEF
| BLOCK
, "__bsf"),
896 [OP_BSR
] = OP( 0, 1, 0, 0, PURE
| DEF
| BLOCK
, "__bsr"),
897 [OP_RDMSR
] = OP( 2, 1, 0, 0, IMPURE
| BLOCK
, "__rdmsr"),
898 [OP_WRMSR
] = OP( 0, 3, 0, 0, IMPURE
| BLOCK
, "__wrmsr"),
899 [OP_HLT
] = OP( 0, 0, 0, 0, IMPURE
| BLOCK
, "__hlt"),
902 #define OP_MAX (sizeof(table_ops)/sizeof(table_ops[0]))
904 static const char *tops(int index
)
906 static const char unknown
[] = "unknown op";
910 if (index
>= OP_MAX
) {
913 return table_ops
[index
].name
;
920 struct triple_set
*next
;
921 struct triple
*member
;
931 const char *filename
;
932 const char *function
;
935 struct occurance
*parent
;
942 struct triple
*next
, *prev
;
943 struct triple_set
*use
;
946 unsigned int template_id
: 7;
947 unsigned int lhs
: 6;
948 unsigned int rhs
: 7;
949 unsigned int misc
: 2;
950 unsigned int targ
: 1;
951 #define TRIPLE_SIZE(TRIPLE) \
952 ((TRIPLE)->lhs + (TRIPLE)->rhs + (TRIPLE)->misc + (TRIPLE)->targ)
953 #define TRIPLE_LHS_OFF(PTR) (0)
954 #define TRIPLE_RHS_OFF(PTR) (TRIPLE_LHS_OFF(PTR) + (PTR)->lhs)
955 #define TRIPLE_MISC_OFF(PTR) (TRIPLE_RHS_OFF(PTR) + (PTR)->rhs)
956 #define TRIPLE_TARG_OFF(PTR) (TRIPLE_MISC_OFF(PTR) + (PTR)->misc)
957 #define LHS(PTR,INDEX) ((PTR)->param[TRIPLE_LHS_OFF(PTR) + (INDEX)])
958 #define RHS(PTR,INDEX) ((PTR)->param[TRIPLE_RHS_OFF(PTR) + (INDEX)])
959 #define TARG(PTR,INDEX) ((PTR)->param[TRIPLE_TARG_OFF(PTR) + (INDEX)])
960 #define MISC(PTR,INDEX) ((PTR)->param[TRIPLE_MISC_OFF(PTR) + (INDEX)])
961 unsigned id
; /* A scratch value and finally the register */
962 #define TRIPLE_FLAG_FLATTENED (1 << 31)
963 #define TRIPLE_FLAG_PRE_SPLIT (1 << 30)
964 #define TRIPLE_FLAG_POST_SPLIT (1 << 29)
965 #define TRIPLE_FLAG_VOLATILE (1 << 28)
966 #define TRIPLE_FLAG_INLINE (1 << 27) /* ???? */
967 #define TRIPLE_FLAG_LOCAL (1 << 26)
969 #define TRIPLE_FLAG_COPY TRIPLE_FLAG_VOLATILE
970 struct occurance
*occurance
;
973 struct bitfield bitfield
;
976 struct hash_entry
*field
;
977 struct asm_info
*ainfo
;
979 struct symbol
*symbol
;
981 struct triple
*param
[2];
988 struct ins_template
{
989 struct reg_info lhs
[MAX_LHS
+ 1], rhs
[MAX_RHS
+ 1];
993 struct ins_template tmpl
;
998 struct block_set
*next
;
999 struct block
*member
;
1002 struct block
*work_next
;
1003 struct triple
*first
, *last
;
1005 struct block_set
*edges
;
1007 struct block_set
*use
;
1008 struct block_set
*idominates
;
1009 struct block_set
*domfrontier
;
1011 struct block_set
*ipdominates
;
1012 struct block_set
*ipdomfrontier
;
1013 struct block
*ipdom
;
1019 struct symbol
*next
;
1020 struct hash_entry
*ident
;
1027 struct macro_arg
*next
;
1028 struct hash_entry
*ident
;
1031 struct hash_entry
*ident
;
1034 struct macro_arg
*args
;
1039 struct hash_entry
*next
;
1043 struct macro
*sym_define
;
1044 struct symbol
*sym_label
;
1045 struct symbol
*sym_tag
;
1046 struct symbol
*sym_ident
;
1049 #define HASH_TABLE_SIZE 2048
1051 struct compiler_state
{
1052 const char *label_prefix
;
1053 const char *ofilename
;
1054 unsigned long flags
;
1055 unsigned long debug
;
1056 unsigned long max_allocation_passes
;
1058 size_t include_path_count
;
1059 const char **include_paths
;
1061 size_t define_count
;
1062 const char **defines
;
1065 const char **undefs
;
1068 unsigned long features
;
1070 struct basic_blocks
{
1071 struct triple
*func
;
1072 struct triple
*first
;
1073 struct block
*first_block
, *last_block
;
1076 #define MAX_PP_IF_DEPTH 63
1077 struct compile_state
{
1078 struct compiler_state
*compiler
;
1079 struct arch_state
*arch
;
1083 struct file_state
*file
;
1084 struct occurance
*last_occurance
;
1085 const char *function
;
1087 struct token token
[6];
1088 struct hash_entry
*hash_table
[HASH_TABLE_SIZE
];
1089 struct hash_entry
*i_switch
;
1090 struct hash_entry
*i_case
;
1091 struct hash_entry
*i_continue
;
1092 struct hash_entry
*i_break
;
1093 struct hash_entry
*i_default
;
1094 struct hash_entry
*i_return
;
1095 struct hash_entry
*i_noreturn
;
1096 struct hash_entry
*i_unused
;
1097 struct hash_entry
*i_packed
;
1098 /* Additional hash entries for predefined macros */
1099 struct hash_entry
*i_defined
;
1100 struct hash_entry
*i___VA_ARGS__
;
1101 struct hash_entry
*i___FILE__
;
1102 struct hash_entry
*i___LINE__
;
1103 /* Additional hash entries for predefined identifiers */
1104 struct hash_entry
*i___func__
;
1105 /* Additional hash entries for attributes */
1106 struct hash_entry
*i_noinline
;
1107 struct hash_entry
*i_always_inline
;
1109 unsigned char if_bytes
[(MAX_PP_IF_DEPTH
+ CHAR_BIT
-1)/CHAR_BIT
];
1111 int eat_depth
, eat_targ
;
1112 struct file_state
*macro_file
;
1113 struct triple
*functions
;
1114 struct triple
*main_function
;
1115 struct triple
*first
;
1116 struct triple
*global_pool
;
1117 struct basic_blocks bb
;
1118 int functions_joined
;
1121 /* visibility global/local */
1122 /* static/auto duration */
1123 /* typedef, register, inline */
1124 #define STOR_SHIFT 0
1125 #define STOR_MASK 0x001f
1127 #define STOR_GLOBAL 0x0001
1129 #define STOR_PERM 0x0002
1130 /* Definition locality */
1131 #define STOR_NONLOCAL 0x0004 /* The definition is not in this translation unit */
1132 /* Storage specifiers */
1133 #define STOR_AUTO 0x0000
1134 #define STOR_STATIC 0x0002
1135 #define STOR_LOCAL 0x0003
1136 #define STOR_EXTERN 0x0007
1137 #define STOR_INLINE 0x0008
1138 #define STOR_REGISTER 0x0010
1139 #define STOR_TYPEDEF 0x0018
1141 #define QUAL_SHIFT 5
1142 #define QUAL_MASK 0x00e0
1143 #define QUAL_NONE 0x0000
1144 #define QUAL_CONST 0x0020
1145 #define QUAL_VOLATILE 0x0040
1146 #define QUAL_RESTRICT 0x0080
1148 #define TYPE_SHIFT 8
1149 #define TYPE_MASK 0x1f00
1150 #define TYPE_INTEGER(TYPE) ((((TYPE) >= TYPE_CHAR) && ((TYPE) <= TYPE_ULLONG)) || ((TYPE) == TYPE_ENUM) || ((TYPE) == TYPE_BITFIELD))
1151 #define TYPE_ARITHMETIC(TYPE) ((((TYPE) >= TYPE_CHAR) && ((TYPE) <= TYPE_LDOUBLE)) || ((TYPE) == TYPE_ENUM) || ((TYPE) == TYPE_BITFIELD))
1152 #define TYPE_UNSIGNED(TYPE) ((TYPE) & 0x0100)
1153 #define TYPE_SIGNED(TYPE) (!TYPE_UNSIGNED(TYPE))
1154 #define TYPE_MKUNSIGNED(TYPE) (((TYPE) & ~0xF000) | 0x0100)
1155 #define TYPE_RANK(TYPE) ((TYPE) & ~0xF1FF)
1156 #define TYPE_PTR(TYPE) (((TYPE) & TYPE_MASK) == TYPE_POINTER)
1157 #define TYPE_DEFAULT 0x0000
1158 #define TYPE_VOID 0x0100
1159 #define TYPE_CHAR 0x0200
1160 #define TYPE_UCHAR 0x0300
1161 #define TYPE_SHORT 0x0400
1162 #define TYPE_USHORT 0x0500
1163 #define TYPE_INT 0x0600
1164 #define TYPE_UINT 0x0700
1165 #define TYPE_LONG 0x0800
1166 #define TYPE_ULONG 0x0900
1167 #define TYPE_LLONG 0x0a00 /* long long */
1168 #define TYPE_ULLONG 0x0b00
1169 #define TYPE_FLOAT 0x0c00
1170 #define TYPE_DOUBLE 0x0d00
1171 #define TYPE_LDOUBLE 0x0e00 /* long double */
1173 /* Note: TYPE_ENUM is chosen very carefully so TYPE_RANK works */
1174 #define TYPE_ENUM 0x1600
1175 #define TYPE_LIST 0x1700
1176 /* TYPE_LIST is a basic building block when defining enumerations
1177 * type->field_ident holds the name of this enumeration entry.
1178 * type->right holds the entry in the list.
1181 #define TYPE_STRUCT 0x1000
1183 * type->left holds the link list of TYPE_PRODUCT entries that
1184 * make up the structure.
1185 * type->elements hold the length of the linked list
1187 #define TYPE_UNION 0x1100
1189 * type->left holds the link list of TYPE_OVERLAP entries that
1190 * make up the union.
1191 * type->elements hold the length of the linked list
1193 #define TYPE_POINTER 0x1200
1194 /* For TYPE_POINTER:
1195 * type->left holds the type pointed to.
1197 #define TYPE_FUNCTION 0x1300
1198 /* For TYPE_FUNCTION:
1199 * type->left holds the return type.
1200 * type->right holds the type of the arguments
1201 * type->elements holds the count of the arguments
1203 #define TYPE_PRODUCT 0x1400
1204 /* TYPE_PRODUCT is a basic building block when defining structures
1205 * type->left holds the type that appears first in memory.
1206 * type->right holds the type that appears next in memory.
1208 #define TYPE_OVERLAP 0x1500
1209 /* TYPE_OVERLAP is a basic building block when defining unions
1210 * type->left and type->right holds to types that overlap
1211 * each other in memory.
1213 #define TYPE_ARRAY 0x1800
1214 /* TYPE_ARRAY is a basic building block when definitng arrays.
1215 * type->left holds the type we are an array of.
1216 * type->elements holds the number of elements.
1218 #define TYPE_TUPLE 0x1900
1219 /* TYPE_TUPLE is a basic building block when defining
1220 * positionally reference type conglomerations. (i.e. closures)
1221 * In essence it is a wrapper for TYPE_PRODUCT, like TYPE_STRUCT
1222 * except it has no field names.
1223 * type->left holds the liked list of TYPE_PRODUCT entries that
1224 * make up the closure type.
1225 * type->elements hold the number of elements in the closure.
1227 #define TYPE_JOIN 0x1a00
1228 /* TYPE_JOIN is a basic building block when defining
1229 * positionally reference type conglomerations. (i.e. closures)
1230 * In essence it is a wrapper for TYPE_OVERLAP, like TYPE_UNION
1231 * except it has no field names.
1232 * type->left holds the liked list of TYPE_OVERLAP entries that
1233 * make up the closure type.
1234 * type->elements hold the number of elements in the closure.
1236 #define TYPE_BITFIELD 0x1b00
1237 /* TYPE_BITFIED is the type of a bitfield.
1238 * type->left holds the type basic type TYPE_BITFIELD is derived from.
1239 * type->elements holds the number of bits in the bitfield.
1241 #define TYPE_UNKNOWN 0x1c00
1242 /* TYPE_UNKNOWN is the type of an unknown value.
1243 * Used on unknown consts and other places where I don't know the type.
1246 #define ATTRIB_SHIFT 16
1247 #define ATTRIB_MASK 0xffff0000
1248 #define ATTRIB_NOINLINE 0x00010000
1249 #define ATTRIB_ALWAYS_INLINE 0x00020000
1251 #define ELEMENT_COUNT_UNSPECIFIED ULONG_T_MAX
1255 struct type
*left
, *right
;
1257 struct hash_entry
*field_ident
;
1258 struct hash_entry
*type_ident
;
1261 #define TEMPLATE_BITS 7
1262 #define MAX_TEMPLATES (1<<TEMPLATE_BITS)
1263 #define MAX_REG_EQUIVS 16
1265 #define MAX_REGISTERS 75
1266 #define REGISTER_BITS 7
1267 #define MAX_VIRT_REGISTERS (1<<REGISTER_BITS)
1270 #define REG_UNNEEDED 2
1271 #define REG_VIRT0 (MAX_REGISTERS + 0)
1272 #define REG_VIRT1 (MAX_REGISTERS + 1)
1273 #define REG_VIRT2 (MAX_REGISTERS + 2)
1274 #define REG_VIRT3 (MAX_REGISTERS + 3)
1275 #define REG_VIRT4 (MAX_REGISTERS + 4)
1276 #define REG_VIRT5 (MAX_REGISTERS + 5)
1277 #define REG_VIRT6 (MAX_REGISTERS + 6)
1278 #define REG_VIRT7 (MAX_REGISTERS + 7)
1279 #define REG_VIRT8 (MAX_REGISTERS + 8)
1280 #define REG_VIRT9 (MAX_REGISTERS + 9)
1282 #if (MAX_REGISTERS + 9) > MAX_VIRT_REGISTERS
1283 #error "MAX_VIRT_REGISTERS to small"
1285 #if (MAX_REGC + REGISTER_BITS) >= 26
1286 #error "Too many id bits used"
1289 /* Provision for 8 register classes */
1291 #define REGC_SHIFT REGISTER_BITS
1292 #define REGC_MASK (((1 << MAX_REGC) - 1) << REGISTER_BITS)
1293 #define REG_MASK (MAX_VIRT_REGISTERS -1)
1294 #define ID_REG(ID) ((ID) & REG_MASK)
1295 #define SET_REG(ID, REG) ((ID) = (((ID) & ~REG_MASK) | ((REG) & REG_MASK)))
1296 #define ID_REGCM(ID) (((ID) & REGC_MASK) >> REGC_SHIFT)
1297 #define SET_REGCM(ID, REGCM) ((ID) = (((ID) & ~REGC_MASK) | (((REGCM) << REGC_SHIFT) & REGC_MASK)))
1298 #define SET_INFO(ID, INFO) ((ID) = (((ID) & ~(REG_MASK | REGC_MASK)) | \
1299 (((INFO).reg) & REG_MASK) | ((((INFO).regcm) << REGC_SHIFT) & REGC_MASK)))
1301 #define ARCH_INPUT_REGS 4
1302 #define ARCH_OUTPUT_REGS 4
1304 static const struct reg_info arch_input_regs
[ARCH_INPUT_REGS
];
1305 static const struct reg_info arch_output_regs
[ARCH_OUTPUT_REGS
];
1306 static unsigned arch_reg_regcm(struct compile_state
*state
, int reg
);
1307 static unsigned arch_regcm_normalize(struct compile_state
*state
, unsigned regcm
);
1308 static unsigned arch_regcm_reg_normalize(struct compile_state
*state
, unsigned regcm
);
1309 static void arch_reg_equivs(
1310 struct compile_state
*state
, unsigned *equiv
, int reg
);
1311 static int arch_select_free_register(
1312 struct compile_state
*state
, char *used
, int classes
);
1313 static unsigned arch_regc_size(struct compile_state
*state
, int class);
1314 static int arch_regcm_intersect(unsigned regcm1
, unsigned regcm2
);
1315 static unsigned arch_type_to_regcm(struct compile_state
*state
, struct type
*type
);
1316 static const char *arch_reg_str(int reg
);
1317 static struct reg_info
arch_reg_constraint(
1318 struct compile_state
*state
, struct type
*type
, const char *constraint
);
1319 static struct reg_info
arch_reg_clobber(
1320 struct compile_state
*state
, const char *clobber
);
1321 static struct reg_info
arch_reg_lhs(struct compile_state
*state
,
1322 struct triple
*ins
, int index
);
1323 static struct reg_info
arch_reg_rhs(struct compile_state
*state
,
1324 struct triple
*ins
, int index
);
1325 static int arch_reg_size(int reg
);
1326 static struct triple
*transform_to_arch_instruction(
1327 struct compile_state
*state
, struct triple
*ins
);
1328 static struct triple
*flatten(
1329 struct compile_state
*state
, struct triple
*first
, struct triple
*ptr
);
1330 static void print_dominators(struct compile_state
*state
,
1331 FILE *fp
, struct basic_blocks
*bb
);
1332 static void print_dominance_frontiers(struct compile_state
*state
,
1333 FILE *fp
, struct basic_blocks
*bb
);
1337 #define DEBUG_ABORT_ON_ERROR 0x00000001
1338 #define DEBUG_BASIC_BLOCKS 0x00000002
1339 #define DEBUG_FDOMINATORS 0x00000004
1340 #define DEBUG_RDOMINATORS 0x00000008
1341 #define DEBUG_TRIPLES 0x00000010
1342 #define DEBUG_INTERFERENCE 0x00000020
1343 #define DEBUG_SCC_TRANSFORM 0x00000040
1344 #define DEBUG_SCC_TRANSFORM2 0x00000080
1345 #define DEBUG_REBUILD_SSA_FORM 0x00000100
1346 #define DEBUG_INLINE 0x00000200
1347 #define DEBUG_RANGE_CONFLICTS 0x00000400
1348 #define DEBUG_RANGE_CONFLICTS2 0x00000800
1349 #define DEBUG_COLOR_GRAPH 0x00001000
1350 #define DEBUG_COLOR_GRAPH2 0x00002000
1351 #define DEBUG_COALESCING 0x00004000
1352 #define DEBUG_COALESCING2 0x00008000
1353 #define DEBUG_VERIFICATION 0x00010000
1354 #define DEBUG_CALLS 0x00020000
1355 #define DEBUG_CALLS2 0x00040000
1356 #define DEBUG_TOKENS 0x80000000
1358 #define DEBUG_DEFAULT ( \
1359 DEBUG_ABORT_ON_ERROR | \
1360 DEBUG_BASIC_BLOCKS | \
1361 DEBUG_FDOMINATORS | \
1362 DEBUG_RDOMINATORS | \
1366 #define DEBUG_ALL ( \
1367 DEBUG_ABORT_ON_ERROR | \
1368 DEBUG_BASIC_BLOCKS | \
1369 DEBUG_FDOMINATORS | \
1370 DEBUG_RDOMINATORS | \
1372 DEBUG_INTERFERENCE | \
1373 DEBUG_SCC_TRANSFORM | \
1374 DEBUG_SCC_TRANSFORM2 | \
1375 DEBUG_REBUILD_SSA_FORM | \
1377 DEBUG_RANGE_CONFLICTS | \
1378 DEBUG_RANGE_CONFLICTS2 | \
1379 DEBUG_COLOR_GRAPH | \
1380 DEBUG_COLOR_GRAPH2 | \
1381 DEBUG_COALESCING | \
1382 DEBUG_COALESCING2 | \
1383 DEBUG_VERIFICATION | \
1389 #define COMPILER_INLINE_MASK 0x00000007
1390 #define COMPILER_INLINE_ALWAYS 0x00000000
1391 #define COMPILER_INLINE_NEVER 0x00000001
1392 #define COMPILER_INLINE_DEFAULTON 0x00000002
1393 #define COMPILER_INLINE_DEFAULTOFF 0x00000003
1394 #define COMPILER_INLINE_NOPENALTY 0x00000004
1395 #define COMPILER_ELIMINATE_INEFECTUAL_CODE 0x00000008
1396 #define COMPILER_SIMPLIFY 0x00000010
1397 #define COMPILER_SCC_TRANSFORM 0x00000020
1398 #define COMPILER_SIMPLIFY_OP 0x00000040
1399 #define COMPILER_SIMPLIFY_PHI 0x00000080
1400 #define COMPILER_SIMPLIFY_LABEL 0x00000100
1401 #define COMPILER_SIMPLIFY_BRANCH 0x00000200
1402 #define COMPILER_SIMPLIFY_COPY 0x00000400
1403 #define COMPILER_SIMPLIFY_ARITH 0x00000800
1404 #define COMPILER_SIMPLIFY_SHIFT 0x00001000
1405 #define COMPILER_SIMPLIFY_BITWISE 0x00002000
1406 #define COMPILER_SIMPLIFY_LOGICAL 0x00004000
1407 #define COMPILER_SIMPLIFY_BITFIELD 0x00008000
1409 #define COMPILER_TRIGRAPHS 0x40000000
1410 #define COMPILER_PP_ONLY 0x80000000
1412 #define COMPILER_DEFAULT_FLAGS ( \
1413 COMPILER_TRIGRAPHS | \
1414 COMPILER_ELIMINATE_INEFECTUAL_CODE | \
1415 COMPILER_INLINE_DEFAULTON | \
1416 COMPILER_SIMPLIFY_OP | \
1417 COMPILER_SIMPLIFY_PHI | \
1418 COMPILER_SIMPLIFY_LABEL | \
1419 COMPILER_SIMPLIFY_BRANCH | \
1420 COMPILER_SIMPLIFY_COPY | \
1421 COMPILER_SIMPLIFY_ARITH | \
1422 COMPILER_SIMPLIFY_SHIFT | \
1423 COMPILER_SIMPLIFY_BITWISE | \
1424 COMPILER_SIMPLIFY_LOGICAL | \
1425 COMPILER_SIMPLIFY_BITFIELD | \
1428 #define GLOBAL_SCOPE_DEPTH 1
1429 #define FUNCTION_SCOPE_DEPTH (GLOBAL_SCOPE_DEPTH + 1)
1431 static void compile_file(struct compile_state
*old_state
, const char *filename
, int local
);
1435 static void init_compiler_state(struct compiler_state
*compiler
)
1437 memset(compiler
, 0, sizeof(*compiler
));
1438 compiler
->label_prefix
= "";
1439 compiler
->ofilename
= "auto.inc";
1440 compiler
->flags
= COMPILER_DEFAULT_FLAGS
;
1441 compiler
->debug
= 0;
1442 compiler
->max_allocation_passes
= MAX_ALLOCATION_PASSES
;
1443 compiler
->include_path_count
= 1;
1444 compiler
->include_paths
= xcmalloc(sizeof(char *), "include_paths");
1445 compiler
->define_count
= 1;
1446 compiler
->defines
= xcmalloc(sizeof(char *), "defines");
1447 compiler
->undef_count
= 1;
1448 compiler
->undefs
= xcmalloc(sizeof(char *), "undefs");
1451 struct compiler_flag
{
1456 struct compiler_arg
{
1459 struct compiler_flag flags
[16];
1462 static int set_flag(
1463 const struct compiler_flag
*ptr
, unsigned long *flags
,
1464 int act
, const char *flag
)
1467 for(; ptr
->name
; ptr
++) {
1468 if (strcmp(ptr
->name
, flag
) == 0) {
1474 *flags
&= ~(ptr
->flag
);
1476 *flags
|= ptr
->flag
;
1483 const struct compiler_arg
*ptr
, unsigned long *flags
, const char *arg
)
1488 val
= strchr(arg
, '=');
1492 for(; ptr
->name
; ptr
++) {
1493 if (strncmp(ptr
->name
, arg
, len
) == 0) {
1498 *flags
&= ~ptr
->mask
;
1499 result
= set_flag(&ptr
->flags
[0], flags
, 1, val
);
1506 static void flag_usage(FILE *fp
, const struct compiler_flag
*ptr
,
1507 const char *prefix
, const char *invert_prefix
)
1509 for(;ptr
->name
; ptr
++) {
1510 fprintf(fp
, "%s%s\n", prefix
, ptr
->name
);
1511 if (invert_prefix
) {
1512 fprintf(fp
, "%s%s\n", invert_prefix
, ptr
->name
);
1517 static void arg_usage(FILE *fp
, const struct compiler_arg
*ptr
,
1520 for(;ptr
->name
; ptr
++) {
1521 const struct compiler_flag
*flag
;
1522 for(flag
= &ptr
->flags
[0]; flag
->name
; flag
++) {
1523 fprintf(fp
, "%s%s=%s\n",
1524 prefix
, ptr
->name
, flag
->name
);
1529 static int append_string(size_t *max
, const char ***vec
, const char *str
,
1534 *vec
= xrealloc(*vec
, sizeof(char *)*count
, "name");
1535 (*vec
)[count
-1] = 0;
1536 (*vec
)[count
-2] = str
;
1540 static void arg_error(char *fmt
, ...);
1541 static void arg_warning(char *fmt
, ...);
1542 static const char *identifier(const char *str
, const char *end
);
1544 static int append_include_path(struct compiler_state
*compiler
, const char *str
)
1547 if (!exists(str
, ".")) {
1548 arg_warning("Warning: Nonexistent include path: `%s'\n",
1551 result
= append_string(&compiler
->include_path_count
,
1552 &compiler
->include_paths
, str
, "include_paths");
1556 static int append_define(struct compiler_state
*compiler
, const char *str
)
1558 const char *end
, *rest
;
1561 end
= strchr(str
, '=');
1563 end
= str
+ strlen(str
);
1565 rest
= identifier(str
, end
);
1567 int len
= end
- str
- 1;
1568 arg_error("Invalid name cannot define macro: `%*.*s'\n",
1571 result
= append_string(&compiler
->define_count
,
1572 &compiler
->defines
, str
, "defines");
1576 static int append_undef(struct compiler_state
*compiler
, const char *str
)
1578 const char *end
, *rest
;
1581 end
= str
+ strlen(str
);
1582 rest
= identifier(str
, end
);
1584 int len
= end
- str
- 1;
1585 arg_error("Invalid name cannot undefine macro: `%*.*s'\n",
1588 result
= append_string(&compiler
->undef_count
,
1589 &compiler
->undefs
, str
, "undefs");
1593 static const struct compiler_flag romcc_flags
[] = {
1594 { "trigraphs", COMPILER_TRIGRAPHS
},
1595 { "pp-only", COMPILER_PP_ONLY
},
1596 { "eliminate-inefectual-code", COMPILER_ELIMINATE_INEFECTUAL_CODE
},
1597 { "simplify", COMPILER_SIMPLIFY
},
1598 { "scc-transform", COMPILER_SCC_TRANSFORM
},
1599 { "simplify-op", COMPILER_SIMPLIFY_OP
},
1600 { "simplify-phi", COMPILER_SIMPLIFY_PHI
},
1601 { "simplify-label", COMPILER_SIMPLIFY_LABEL
},
1602 { "simplify-branch", COMPILER_SIMPLIFY_BRANCH
},
1603 { "simplify-copy", COMPILER_SIMPLIFY_COPY
},
1604 { "simplify-arith", COMPILER_SIMPLIFY_ARITH
},
1605 { "simplify-shift", COMPILER_SIMPLIFY_SHIFT
},
1606 { "simplify-bitwise", COMPILER_SIMPLIFY_BITWISE
},
1607 { "simplify-logical", COMPILER_SIMPLIFY_LOGICAL
},
1608 { "simplify-bitfield", COMPILER_SIMPLIFY_BITFIELD
},
1611 static const struct compiler_arg romcc_args
[] = {
1612 { "inline-policy", COMPILER_INLINE_MASK
,
1614 { "always", COMPILER_INLINE_ALWAYS
, },
1615 { "never", COMPILER_INLINE_NEVER
, },
1616 { "defaulton", COMPILER_INLINE_DEFAULTON
, },
1617 { "defaultoff", COMPILER_INLINE_DEFAULTOFF
, },
1618 { "nopenalty", COMPILER_INLINE_NOPENALTY
, },
1624 static const struct compiler_flag romcc_opt_flags
[] = {
1625 { "-O", COMPILER_SIMPLIFY
},
1626 { "-O2", COMPILER_SIMPLIFY
| COMPILER_SCC_TRANSFORM
},
1627 { "-E", COMPILER_PP_ONLY
},
1630 static const struct compiler_flag romcc_debug_flags
[] = {
1631 { "all", DEBUG_ALL
},
1632 { "abort-on-error", DEBUG_ABORT_ON_ERROR
},
1633 { "basic-blocks", DEBUG_BASIC_BLOCKS
},
1634 { "fdominators", DEBUG_FDOMINATORS
},
1635 { "rdominators", DEBUG_RDOMINATORS
},
1636 { "triples", DEBUG_TRIPLES
},
1637 { "interference", DEBUG_INTERFERENCE
},
1638 { "scc-transform", DEBUG_SCC_TRANSFORM
},
1639 { "scc-transform2", DEBUG_SCC_TRANSFORM2
},
1640 { "rebuild-ssa-form", DEBUG_REBUILD_SSA_FORM
},
1641 { "inline", DEBUG_INLINE
},
1642 { "live-range-conflicts", DEBUG_RANGE_CONFLICTS
},
1643 { "live-range-conflicts2", DEBUG_RANGE_CONFLICTS2
},
1644 { "color-graph", DEBUG_COLOR_GRAPH
},
1645 { "color-graph2", DEBUG_COLOR_GRAPH2
},
1646 { "coalescing", DEBUG_COALESCING
},
1647 { "coalescing2", DEBUG_COALESCING2
},
1648 { "verification", DEBUG_VERIFICATION
},
1649 { "calls", DEBUG_CALLS
},
1650 { "calls2", DEBUG_CALLS2
},
1651 { "tokens", DEBUG_TOKENS
},
1655 static int compiler_encode_flag(
1656 struct compiler_state
*compiler
, const char *flag
)
1663 if (strncmp(flag
, "no-", 3) == 0) {
1667 if (strncmp(flag
, "-O", 2) == 0) {
1668 result
= set_flag(romcc_opt_flags
, &compiler
->flags
, act
, flag
);
1670 else if (strncmp(flag
, "-E", 2) == 0) {
1671 result
= set_flag(romcc_opt_flags
, &compiler
->flags
, act
, flag
);
1673 else if (strncmp(flag
, "-I", 2) == 0) {
1674 result
= append_include_path(compiler
, flag
+ 2);
1676 else if (strncmp(flag
, "-D", 2) == 0) {
1677 result
= append_define(compiler
, flag
+ 2);
1679 else if (strncmp(flag
, "-U", 2) == 0) {
1680 result
= append_undef(compiler
, flag
+ 2);
1682 else if (act
&& strncmp(flag
, "label-prefix=", 13) == 0) {
1684 compiler
->label_prefix
= flag
+ 13;
1686 else if (act
&& strncmp(flag
, "max-allocation-passes=", 22) == 0) {
1687 unsigned long max_passes
;
1689 max_passes
= strtoul(flag
+ 22, &end
, 10);
1690 if (end
[0] == '\0') {
1692 compiler
->max_allocation_passes
= max_passes
;
1695 else if (act
&& strcmp(flag
, "debug") == 0) {
1697 compiler
->debug
|= DEBUG_DEFAULT
;
1699 else if (strncmp(flag
, "debug-", 6) == 0) {
1701 result
= set_flag(romcc_debug_flags
, &compiler
->debug
, act
, flag
);
1704 result
= set_flag(romcc_flags
, &compiler
->flags
, act
, flag
);
1706 result
= set_arg(romcc_args
, &compiler
->flags
, flag
);
1712 static void compiler_usage(FILE *fp
)
1714 flag_usage(fp
, romcc_opt_flags
, "", 0);
1715 flag_usage(fp
, romcc_flags
, "-f", "-fno-");
1716 arg_usage(fp
, romcc_args
, "-f");
1717 flag_usage(fp
, romcc_debug_flags
, "-fdebug-", "-fno-debug-");
1718 fprintf(fp
, "-flabel-prefix=<prefix for assembly language labels>\n");
1719 fprintf(fp
, "--label-prefix=<prefix for assembly language labels>\n");
1720 fprintf(fp
, "-I<include path>\n");
1721 fprintf(fp
, "-D<macro>[=defn]\n");
1722 fprintf(fp
, "-U<macro>\n");
1725 static void do_cleanup(struct compile_state
*state
)
1727 if (state
->output
) {
1728 fclose(state
->output
);
1729 unlink(state
->compiler
->ofilename
);
1732 if (state
->dbgout
) {
1733 fflush(state
->dbgout
);
1735 if (state
->errout
) {
1736 fflush(state
->errout
);
1740 static struct compile_state
*exit_state
;
1741 static void exit_cleanup(void)
1744 do_cleanup(exit_state
);
1748 static int get_col(struct file_state
*file
)
1751 const char *ptr
, *end
;
1752 ptr
= file
->line_start
;
1754 for(col
= 0; ptr
< end
; ptr
++) {
1759 col
= (col
& ~7) + 8;
1765 static void loc(FILE *fp
, struct compile_state
*state
, struct triple
*triple
)
1768 if (triple
&& triple
->occurance
) {
1769 struct occurance
*spot
;
1770 for(spot
= triple
->occurance
; spot
; spot
= spot
->parent
) {
1771 fprintf(fp
, "%s:%d.%d: ",
1772 spot
->filename
, spot
->line
, spot
->col
);
1779 col
= get_col(state
->file
);
1780 fprintf(fp
, "%s:%d.%d: ",
1781 state
->file
->report_name
, state
->file
->report_line
, col
);
1784 static void __attribute__ ((noreturn
)) internal_error(struct compile_state
*state
, struct triple
*ptr
,
1785 const char *fmt
, ...)
1787 FILE *fp
= state
->errout
;
1789 va_start(args
, fmt
);
1790 loc(fp
, state
, ptr
);
1793 fprintf(fp
, "%p %-10s ", ptr
, tops(ptr
->op
));
1795 fprintf(fp
, "Internal compiler error: ");
1796 vfprintf(fp
, fmt
, args
);
1804 static void internal_warning(struct compile_state
*state
, struct triple
*ptr
,
1805 const char *fmt
, ...)
1807 FILE *fp
= state
->errout
;
1809 va_start(args
, fmt
);
1810 loc(fp
, state
, ptr
);
1812 fprintf(fp
, "%p %-10s ", ptr
, tops(ptr
->op
));
1814 fprintf(fp
, "Internal compiler warning: ");
1815 vfprintf(fp
, fmt
, args
);
1822 static void __attribute__ ((noreturn
)) error(struct compile_state
*state
, struct triple
*ptr
,
1823 const char *fmt
, ...)
1825 FILE *fp
= state
->errout
;
1827 va_start(args
, fmt
);
1828 loc(fp
, state
, ptr
);
1830 if (ptr
&& (state
->compiler
->debug
& DEBUG_ABORT_ON_ERROR
)) {
1831 fprintf(fp
, "%p %-10s ", ptr
, tops(ptr
->op
));
1833 vfprintf(fp
, fmt
, args
);
1837 if (state
->compiler
->debug
& DEBUG_ABORT_ON_ERROR
) {
1843 static void warning(struct compile_state
*state
, struct triple
*ptr
,
1844 const char *fmt
, ...)
1846 FILE *fp
= state
->errout
;
1848 va_start(args
, fmt
);
1849 loc(fp
, state
, ptr
);
1850 fprintf(fp
, "warning: ");
1851 if (ptr
&& (state
->compiler
->debug
& DEBUG_ABORT_ON_ERROR
)) {
1852 fprintf(fp
, "%p %-10s ", ptr
, tops(ptr
->op
));
1854 vfprintf(fp
, fmt
, args
);
1859 #define FINISHME() warning(state, 0, "FINISHME @ %s.%s:%d", __FILE__, __func__, __LINE__)
1861 static void valid_op(struct compile_state
*state
, int op
)
1863 char *fmt
= "invalid op: %d";
1865 internal_error(state
, 0, fmt
, op
);
1868 internal_error(state
, 0, fmt
, op
);
1872 static void valid_ins(struct compile_state
*state
, struct triple
*ptr
)
1874 valid_op(state
, ptr
->op
);
1877 #if DEBUG_ROMCC_WARNING
1878 static void valid_param_count(struct compile_state
*state
, struct triple
*ins
)
1880 int lhs
, rhs
, misc
, targ
;
1881 valid_ins(state
, ins
);
1882 lhs
= table_ops
[ins
->op
].lhs
;
1883 rhs
= table_ops
[ins
->op
].rhs
;
1884 misc
= table_ops
[ins
->op
].misc
;
1885 targ
= table_ops
[ins
->op
].targ
;
1887 if ((lhs
>= 0) && (ins
->lhs
!= lhs
)) {
1888 internal_error(state
, ins
, "Bad lhs count");
1890 if ((rhs
>= 0) && (ins
->rhs
!= rhs
)) {
1891 internal_error(state
, ins
, "Bad rhs count");
1893 if ((misc
>= 0) && (ins
->misc
!= misc
)) {
1894 internal_error(state
, ins
, "Bad misc count");
1896 if ((targ
>= 0) && (ins
->targ
!= targ
)) {
1897 internal_error(state
, ins
, "Bad targ count");
1902 static struct type void_type
;
1903 static struct type unknown_type
;
1904 static void use_triple(struct triple
*used
, struct triple
*user
)
1906 struct triple_set
**ptr
, *new;
1913 if ((*ptr
)->member
== user
) {
1916 ptr
= &(*ptr
)->next
;
1918 /* Append new to the head of the list,
1919 * copy_func and rename_block_variables
1922 new = xcmalloc(sizeof(*new), "triple_set");
1924 new->next
= used
->use
;
1928 static void unuse_triple(struct triple
*used
, struct triple
*unuser
)
1930 struct triple_set
*use
, **ptr
;
1937 if (use
->member
== unuser
) {
1947 static void put_occurance(struct occurance
*occurance
)
1950 occurance
->count
-= 1;
1951 if (occurance
->count
<= 0) {
1952 if (occurance
->parent
) {
1953 put_occurance(occurance
->parent
);
1960 static void get_occurance(struct occurance
*occurance
)
1963 occurance
->count
+= 1;
1968 static struct occurance
*new_occurance(struct compile_state
*state
)
1970 struct occurance
*result
, *last
;
1971 const char *filename
;
1972 const char *function
;
1980 filename
= state
->file
->report_name
;
1981 line
= state
->file
->report_line
;
1982 col
= get_col(state
->file
);
1984 if (state
->function
) {
1985 function
= state
->function
;
1987 last
= state
->last_occurance
;
1989 (last
->col
== col
) &&
1990 (last
->line
== line
) &&
1991 (last
->function
== function
) &&
1992 ((last
->filename
== filename
) ||
1993 (strcmp(last
->filename
, filename
) == 0)))
1995 get_occurance(last
);
1999 state
->last_occurance
= 0;
2000 put_occurance(last
);
2002 result
= xmalloc(sizeof(*result
), "occurance");
2004 result
->filename
= filename
;
2005 result
->function
= function
;
2006 result
->line
= line
;
2009 state
->last_occurance
= result
;
2013 static struct occurance
*inline_occurance(struct compile_state
*state
,
2014 struct occurance
*base
, struct occurance
*top
)
2016 struct occurance
*result
, *last
;
2018 internal_error(state
, 0, "inlining an already inlined function?");
2020 /* If I have a null base treat it that way */
2021 if ((base
->parent
== 0) &&
2023 (base
->line
== 0) &&
2024 (base
->function
[0] == '\0') &&
2025 (base
->filename
[0] == '\0')) {
2028 /* See if I can reuse the last occurance I had */
2029 last
= state
->last_occurance
;
2031 (last
->parent
== base
) &&
2032 (last
->col
== top
->col
) &&
2033 (last
->line
== top
->line
) &&
2034 (last
->function
== top
->function
) &&
2035 (last
->filename
== top
->filename
)) {
2036 get_occurance(last
);
2039 /* I can't reuse the last occurance so free it */
2041 state
->last_occurance
= 0;
2042 put_occurance(last
);
2044 /* Generate a new occurance structure */
2045 get_occurance(base
);
2046 result
= xmalloc(sizeof(*result
), "occurance");
2048 result
->filename
= top
->filename
;
2049 result
->function
= top
->function
;
2050 result
->line
= top
->line
;
2051 result
->col
= top
->col
;
2052 result
->parent
= base
;
2053 state
->last_occurance
= result
;
2057 static struct occurance dummy_occurance
= {
2059 .filename
= __FILE__
,
2066 /* The undef triple is used as a place holder when we are removing pointers
2067 * from a triple. Having allows certain sanity checks to pass even
2068 * when the original triple that was pointed to is gone.
2070 static struct triple unknown_triple
= {
2071 .next
= &unknown_triple
,
2072 .prev
= &unknown_triple
,
2074 .op
= OP_UNKNOWNVAL
,
2079 .type
= &unknown_type
,
2080 .id
= -1, /* An invalid id */
2081 .u
= { .cval
= 0, },
2082 .occurance
= &dummy_occurance
,
2083 .param
= { [0] = 0, [1] = 0, },
2087 static size_t registers_of(struct compile_state
*state
, struct type
*type
);
2089 static struct triple
*alloc_triple(struct compile_state
*state
,
2090 int op
, struct type
*type
, int lhs_wanted
, int rhs_wanted
,
2091 struct occurance
*occurance
)
2093 size_t size
, extra_count
, min_count
;
2094 int lhs
, rhs
, misc
, targ
;
2095 struct triple
*ret
, dummy
;
2097 dummy
.occurance
= occurance
;
2098 valid_op(state
, op
);
2099 lhs
= table_ops
[op
].lhs
;
2100 rhs
= table_ops
[op
].rhs
;
2101 misc
= table_ops
[op
].misc
;
2102 targ
= table_ops
[op
].targ
;
2112 lhs
= registers_of(state
, type
);
2115 lhs
= registers_of(state
, type
);
2122 if ((rhs
< 0) || (rhs
> MAX_RHS
)) {
2123 internal_error(state
, &dummy
, "bad rhs count %d", rhs
);
2125 if ((lhs
< 0) || (lhs
> MAX_LHS
)) {
2126 internal_error(state
, &dummy
, "bad lhs count %d", lhs
);
2128 if ((misc
< 0) || (misc
> MAX_MISC
)) {
2129 internal_error(state
, &dummy
, "bad misc count %d", misc
);
2131 if ((targ
< 0) || (targ
> MAX_TARG
)) {
2132 internal_error(state
, &dummy
, "bad targs count %d", targ
);
2135 min_count
= sizeof(ret
->param
)/sizeof(ret
->param
[0]);
2136 extra_count
= lhs
+ rhs
+ misc
+ targ
;
2137 extra_count
= (extra_count
< min_count
)? 0 : extra_count
- min_count
;
2139 size
= sizeof(*ret
) + sizeof(ret
->param
[0]) * extra_count
;
2140 ret
= xcmalloc(size
, "tripple");
2149 ret
->occurance
= occurance
;
2150 /* A simple sanity check */
2151 if ((ret
->op
!= op
) ||
2152 (ret
->lhs
!= lhs
) ||
2153 (ret
->rhs
!= rhs
) ||
2154 (ret
->misc
!= misc
) ||
2155 (ret
->targ
!= targ
) ||
2156 (ret
->type
!= type
) ||
2157 (ret
->next
!= ret
) ||
2158 (ret
->prev
!= ret
) ||
2159 (ret
->occurance
!= occurance
)) {
2160 internal_error(state
, ret
, "huh?");
2165 struct triple
*dup_triple(struct compile_state
*state
, struct triple
*src
)
2168 int src_lhs
, src_rhs
, src_size
;
2171 src_size
= TRIPLE_SIZE(src
);
2172 get_occurance(src
->occurance
);
2173 dup
= alloc_triple(state
, src
->op
, src
->type
, src_lhs
, src_rhs
,
2175 memcpy(dup
, src
, sizeof(*src
));
2176 memcpy(dup
->param
, src
->param
, src_size
* sizeof(src
->param
[0]));
2180 static struct triple
*copy_triple(struct compile_state
*state
, struct triple
*src
)
2182 struct triple
*copy
;
2183 copy
= dup_triple(state
, src
);
2185 copy
->next
= copy
->prev
= copy
;
2189 static struct triple
*new_triple(struct compile_state
*state
,
2190 int op
, struct type
*type
, int lhs
, int rhs
)
2193 struct occurance
*occurance
;
2194 occurance
= new_occurance(state
);
2195 ret
= alloc_triple(state
, op
, type
, lhs
, rhs
, occurance
);
2199 static struct triple
*build_triple(struct compile_state
*state
,
2200 int op
, struct type
*type
, struct triple
*left
, struct triple
*right
,
2201 struct occurance
*occurance
)
2205 ret
= alloc_triple(state
, op
, type
, -1, -1, occurance
);
2206 count
= TRIPLE_SIZE(ret
);
2208 ret
->param
[0] = left
;
2211 ret
->param
[1] = right
;
2216 static struct triple
*triple(struct compile_state
*state
,
2217 int op
, struct type
*type
, struct triple
*left
, struct triple
*right
)
2221 ret
= new_triple(state
, op
, type
, -1, -1);
2222 count
= TRIPLE_SIZE(ret
);
2224 ret
->param
[0] = left
;
2227 ret
->param
[1] = right
;
2232 static struct triple
*branch(struct compile_state
*state
,
2233 struct triple
*targ
, struct triple
*test
)
2237 ret
= new_triple(state
, OP_CBRANCH
, &void_type
, -1, 1);
2240 ret
= new_triple(state
, OP_BRANCH
, &void_type
, -1, 0);
2242 TARG(ret
, 0) = targ
;
2243 /* record the branch target was used */
2244 if (!targ
|| (targ
->op
!= OP_LABEL
)) {
2245 internal_error(state
, 0, "branch not to label");
2250 static int triple_is_label(struct compile_state
*state
, struct triple
*ins
);
2251 static int triple_is_call(struct compile_state
*state
, struct triple
*ins
);
2252 static int triple_is_cbranch(struct compile_state
*state
, struct triple
*ins
);
2253 static void insert_triple(struct compile_state
*state
,
2254 struct triple
*first
, struct triple
*ptr
)
2257 if ((ptr
->id
& TRIPLE_FLAG_FLATTENED
) || (ptr
->next
!= ptr
)) {
2258 internal_error(state
, ptr
, "expression already used");
2261 ptr
->prev
= first
->prev
;
2262 ptr
->prev
->next
= ptr
;
2263 ptr
->next
->prev
= ptr
;
2265 if (triple_is_cbranch(state
, ptr
->prev
) ||
2266 triple_is_call(state
, ptr
->prev
)) {
2267 unuse_triple(first
, ptr
->prev
);
2268 use_triple(ptr
, ptr
->prev
);
2273 static int triple_stores_block(struct compile_state
*state
, struct triple
*ins
)
2275 /* This function is used to determine if u.block
2276 * is utilized to store the current block number.
2279 valid_ins(state
, ins
);
2280 stores_block
= (table_ops
[ins
->op
].flags
& BLOCK
) == BLOCK
;
2281 return stores_block
;
2284 static int triple_is_branch(struct compile_state
*state
, struct triple
*ins
);
2285 static struct block
*block_of_triple(struct compile_state
*state
,
2288 struct triple
*first
;
2289 if (!ins
|| ins
== &unknown_triple
) {
2292 first
= state
->first
;
2293 while(ins
!= first
&& !triple_is_branch(state
, ins
->prev
) &&
2294 !triple_stores_block(state
, ins
))
2296 if (ins
== ins
->prev
) {
2297 internal_error(state
, ins
, "ins == ins->prev?");
2301 return triple_stores_block(state
, ins
)? ins
->u
.block
: 0;
2304 static void generate_lhs_pieces(struct compile_state
*state
, struct triple
*ins
);
2305 static struct triple
*pre_triple(struct compile_state
*state
,
2306 struct triple
*base
,
2307 int op
, struct type
*type
, struct triple
*left
, struct triple
*right
)
2309 struct block
*block
;
2312 /* If I am an OP_PIECE jump to the real instruction */
2313 if (base
->op
== OP_PIECE
) {
2314 base
= MISC(base
, 0);
2316 block
= block_of_triple(state
, base
);
2317 get_occurance(base
->occurance
);
2318 ret
= build_triple(state
, op
, type
, left
, right
, base
->occurance
);
2319 generate_lhs_pieces(state
, ret
);
2320 if (triple_stores_block(state
, ret
)) {
2321 ret
->u
.block
= block
;
2323 insert_triple(state
, base
, ret
);
2324 for(i
= 0; i
< ret
->lhs
; i
++) {
2325 struct triple
*piece
;
2326 piece
= LHS(ret
, i
);
2327 insert_triple(state
, base
, piece
);
2328 use_triple(ret
, piece
);
2329 use_triple(piece
, ret
);
2331 if (block
&& (block
->first
== base
)) {
2337 static struct triple
*post_triple(struct compile_state
*state
,
2338 struct triple
*base
,
2339 int op
, struct type
*type
, struct triple
*left
, struct triple
*right
)
2341 struct block
*block
;
2342 struct triple
*ret
, *next
;
2344 /* If I am an OP_PIECE jump to the real instruction */
2345 if (base
->op
== OP_PIECE
) {
2346 base
= MISC(base
, 0);
2348 /* If I have a left hand side skip over it */
2351 base
= LHS(base
, zlhs
- 1);
2354 block
= block_of_triple(state
, base
);
2355 get_occurance(base
->occurance
);
2356 ret
= build_triple(state
, op
, type
, left
, right
, base
->occurance
);
2357 generate_lhs_pieces(state
, ret
);
2358 if (triple_stores_block(state
, ret
)) {
2359 ret
->u
.block
= block
;
2362 insert_triple(state
, next
, ret
);
2364 for(i
= 0; i
< zlhs
; i
++) {
2365 struct triple
*piece
;
2366 piece
= LHS(ret
, i
);
2367 insert_triple(state
, next
, piece
);
2368 use_triple(ret
, piece
);
2369 use_triple(piece
, ret
);
2371 if (block
&& (block
->last
== base
)) {
2374 block
->last
= LHS(ret
, zlhs
- 1);
2380 static struct type
*reg_type(
2381 struct compile_state
*state
, struct type
*type
, int reg
);
2383 static void generate_lhs_piece(
2384 struct compile_state
*state
, struct triple
*ins
, int index
)
2386 struct type
*piece_type
;
2387 struct triple
*piece
;
2388 get_occurance(ins
->occurance
);
2389 piece_type
= reg_type(state
, ins
->type
, index
* REG_SIZEOF_REG
);
2391 if ((piece_type
->type
& TYPE_MASK
) == TYPE_BITFIELD
) {
2392 piece_type
= piece_type
->left
;
2396 static void name_of(FILE *fp
, struct type
*type
);
2397 FILE * fp
= state
->errout
;
2398 fprintf(fp
, "piece_type(%d): ", index
);
2399 name_of(fp
, piece_type
);
2403 piece
= alloc_triple(state
, OP_PIECE
, piece_type
, -1, -1, ins
->occurance
);
2404 piece
->u
.cval
= index
;
2405 LHS(ins
, piece
->u
.cval
) = piece
;
2406 MISC(piece
, 0) = ins
;
2409 static void generate_lhs_pieces(struct compile_state
*state
, struct triple
*ins
)
2413 for(i
= 0; i
< zlhs
; i
++) {
2414 generate_lhs_piece(state
, ins
, i
);
2418 static struct triple
*label(struct compile_state
*state
)
2420 /* Labels don't get a type */
2421 struct triple
*result
;
2422 result
= triple(state
, OP_LABEL
, &void_type
, 0, 0);
2426 static struct triple
*mkprog(struct compile_state
*state
, ...)
2428 struct triple
*prog
, *head
, *arg
;
2432 head
= label(state
);
2433 prog
= new_triple(state
, OP_PROG
, &void_type
, -1, -1);
2434 RHS(prog
, 0) = head
;
2435 va_start(args
, state
);
2437 while((arg
= va_arg(args
, struct triple
*)) != 0) {
2439 internal_error(state
, 0, "too many arguments to mkprog");
2441 flatten(state
, head
, arg
);
2444 prog
->type
= head
->prev
->type
;
2447 static void name_of(FILE *fp
, struct type
*type
);
2448 static void display_triple(FILE *fp
, struct triple
*ins
)
2450 struct occurance
*ptr
;
2452 char pre
, post
, vol
;
2453 pre
= post
= vol
= ' ';
2455 if (ins
->id
& TRIPLE_FLAG_PRE_SPLIT
) {
2458 if (ins
->id
& TRIPLE_FLAG_POST_SPLIT
) {
2461 if (ins
->id
& TRIPLE_FLAG_VOLATILE
) {
2464 reg
= arch_reg_str(ID_REG(ins
->id
));
2467 fprintf(fp
, "(%p) <nothing> ", ins
);
2469 else if (ins
->op
== OP_INTCONST
) {
2470 fprintf(fp
, "(%p) %c%c%c %-7s %-2d %-10s <0x%08lx> ",
2471 ins
, pre
, post
, vol
, reg
, ins
->template_id
, tops(ins
->op
),
2472 (unsigned long)(ins
->u
.cval
));
2474 else if (ins
->op
== OP_ADDRCONST
) {
2475 fprintf(fp
, "(%p) %c%c%c %-7s %-2d %-10s %-10p <0x%08lx>",
2476 ins
, pre
, post
, vol
, reg
, ins
->template_id
, tops(ins
->op
),
2477 MISC(ins
, 0), (unsigned long)(ins
->u
.cval
));
2479 else if (ins
->op
== OP_INDEX
) {
2480 fprintf(fp
, "(%p) %c%c%c %-7s %-2d %-10s %-10p <0x%08lx>",
2481 ins
, pre
, post
, vol
, reg
, ins
->template_id
, tops(ins
->op
),
2482 RHS(ins
, 0), (unsigned long)(ins
->u
.cval
));
2484 else if (ins
->op
== OP_PIECE
) {
2485 fprintf(fp
, "(%p) %c%c%c %-7s %-2d %-10s %-10p <0x%08lx>",
2486 ins
, pre
, post
, vol
, reg
, ins
->template_id
, tops(ins
->op
),
2487 MISC(ins
, 0), (unsigned long)(ins
->u
.cval
));
2491 fprintf(fp
, "(%p) %c%c%c %-7s %-2d %-10s",
2492 ins
, pre
, post
, vol
, reg
, ins
->template_id
, tops(ins
->op
));
2493 if (table_ops
[ins
->op
].flags
& BITFIELD
) {
2494 fprintf(fp
, " <%2d-%2d:%2d>",
2495 ins
->u
.bitfield
.offset
,
2496 ins
->u
.bitfield
.offset
+ ins
->u
.bitfield
.size
,
2497 ins
->u
.bitfield
.size
);
2499 count
= TRIPLE_SIZE(ins
);
2500 for(i
= 0; i
< count
; i
++) {
2501 fprintf(fp
, " %-10p", ins
->param
[i
]);
2508 struct triple_set
*user
;
2509 #if DEBUG_DISPLAY_TYPES
2511 name_of(fp
, ins
->type
);
2514 #if DEBUG_DISPLAY_USES
2516 for(user
= ins
->use
; user
; user
= user
->next
) {
2517 fprintf(fp
, " %-10p", user
->member
);
2522 for(ptr
= ins
->occurance
; ptr
; ptr
= ptr
->parent
) {
2523 fprintf(fp
, " %s,%s:%d.%d",
2529 if (ins
->op
== OP_ASM
) {
2530 fprintf(fp
, "\n\t%s", ins
->u
.ainfo
->str
);
2537 static int equiv_types(struct type
*left
, struct type
*right
);
2538 static void display_triple_changes(
2539 FILE *fp
, const struct triple
*new, const struct triple
*orig
)
2542 int new_count
, orig_count
;
2543 new_count
= TRIPLE_SIZE(new);
2544 orig_count
= TRIPLE_SIZE(orig
);
2545 if ((new->op
!= orig
->op
) ||
2546 (new_count
!= orig_count
) ||
2547 (memcmp(orig
->param
, new->param
,
2548 orig_count
* sizeof(orig
->param
[0])) != 0) ||
2549 (memcmp(&orig
->u
, &new->u
, sizeof(orig
->u
)) != 0))
2551 struct occurance
*ptr
;
2552 int i
, min_count
, indent
;
2553 fprintf(fp
, "(%p %p)", new, orig
);
2554 if (orig
->op
== new->op
) {
2555 fprintf(fp
, " %-11s", tops(orig
->op
));
2557 fprintf(fp
, " [%-10s %-10s]",
2558 tops(new->op
), tops(orig
->op
));
2560 min_count
= new_count
;
2561 if (min_count
> orig_count
) {
2562 min_count
= orig_count
;
2564 for(indent
= i
= 0; i
< min_count
; i
++) {
2565 if (orig
->param
[i
] == new->param
[i
]) {
2566 fprintf(fp
, " %-11p",
2570 fprintf(fp
, " [%-10p %-10p]",
2576 for(; i
< orig_count
; i
++) {
2577 fprintf(fp
, " [%-9p]", orig
->param
[i
]);
2580 for(; i
< new_count
; i
++) {
2581 fprintf(fp
, " [%-9p]", new->param
[i
]);
2584 if ((new->op
== OP_INTCONST
)||
2585 (new->op
== OP_ADDRCONST
)) {
2586 fprintf(fp
, " <0x%08lx>",
2587 (unsigned long)(new->u
.cval
));
2590 for(;indent
< 36; indent
++) {
2594 #if DEBUG_DISPLAY_TYPES
2596 name_of(fp
, new->type
);
2597 if (!equiv_types(new->type
, orig
->type
)) {
2598 fprintf(fp
, " -- ");
2599 name_of(fp
, orig
->type
);
2605 for(ptr
= orig
->occurance
; ptr
; ptr
= ptr
->parent
) {
2606 fprintf(fp
, " %s,%s:%d.%d",
2618 static int triple_is_pure(struct compile_state
*state
, struct triple
*ins
, unsigned id
)
2620 /* Does the triple have no side effects.
2621 * I.e. Rexecuting the triple with the same arguments
2622 * gives the same value.
2625 valid_ins(state
, ins
);
2626 pure
= PURE_BITS(table_ops
[ins
->op
].flags
);
2627 if ((pure
!= PURE
) && (pure
!= IMPURE
)) {
2628 internal_error(state
, 0, "Purity of %s not known",
2631 return (pure
== PURE
) && !(id
& TRIPLE_FLAG_VOLATILE
);
2634 static int triple_is_branch_type(struct compile_state
*state
,
2635 struct triple
*ins
, unsigned type
)
2637 /* Is this one of the passed branch types? */
2638 valid_ins(state
, ins
);
2639 return (BRANCH_BITS(table_ops
[ins
->op
].flags
) == type
);
2642 static int triple_is_branch(struct compile_state
*state
, struct triple
*ins
)
2644 /* Is this triple a branch instruction? */
2645 valid_ins(state
, ins
);
2646 return (BRANCH_BITS(table_ops
[ins
->op
].flags
) != 0);
2649 static int triple_is_cbranch(struct compile_state
*state
, struct triple
*ins
)
2651 /* Is this triple a conditional branch instruction? */
2652 return triple_is_branch_type(state
, ins
, CBRANCH
);
2655 static int triple_is_ubranch(struct compile_state
*state
, struct triple
*ins
)
2657 /* Is this triple a unconditional branch instruction? */
2659 valid_ins(state
, ins
);
2660 type
= BRANCH_BITS(table_ops
[ins
->op
].flags
);
2661 return (type
!= 0) && (type
!= CBRANCH
);
2664 static int triple_is_call(struct compile_state
*state
, struct triple
*ins
)
2666 /* Is this triple a call instruction? */
2667 return triple_is_branch_type(state
, ins
, CALLBRANCH
);
2670 static int triple_is_ret(struct compile_state
*state
, struct triple
*ins
)
2672 /* Is this triple a return instruction? */
2673 return triple_is_branch_type(state
, ins
, RETBRANCH
);
2676 #if DEBUG_ROMCC_WARNING
2677 static int triple_is_simple_ubranch(struct compile_state
*state
, struct triple
*ins
)
2679 /* Is this triple an unconditional branch and not a call or a
2681 return triple_is_branch_type(state
, ins
, UBRANCH
);
2685 static int triple_is_end(struct compile_state
*state
, struct triple
*ins
)
2687 return triple_is_branch_type(state
, ins
, ENDBRANCH
);
2690 static int triple_is_label(struct compile_state
*state
, struct triple
*ins
)
2692 valid_ins(state
, ins
);
2693 return (ins
->op
== OP_LABEL
);
2696 static struct triple
*triple_to_block_start(
2697 struct compile_state
*state
, struct triple
*start
)
2699 while(!triple_is_branch(state
, start
->prev
) &&
2700 (!triple_is_label(state
, start
) || !start
->use
)) {
2701 start
= start
->prev
;
2706 static int triple_is_def(struct compile_state
*state
, struct triple
*ins
)
2708 /* This function is used to determine which triples need
2712 valid_ins(state
, ins
);
2713 is_def
= (table_ops
[ins
->op
].flags
& DEF
) == DEF
;
2714 if (ins
->lhs
>= 1) {
2720 static int triple_is_structural(struct compile_state
*state
, struct triple
*ins
)
2723 valid_ins(state
, ins
);
2724 is_structural
= (table_ops
[ins
->op
].flags
& STRUCTURAL
) == STRUCTURAL
;
2725 return is_structural
;
2728 static int triple_is_part(struct compile_state
*state
, struct triple
*ins
)
2731 valid_ins(state
, ins
);
2732 is_part
= (table_ops
[ins
->op
].flags
& PART
) == PART
;
2736 static int triple_is_auto_var(struct compile_state
*state
, struct triple
*ins
)
2738 return (ins
->op
== OP_PIECE
) && (MISC(ins
, 0)->op
== OP_ADECL
);
2741 static struct triple
**triple_iter(struct compile_state
*state
,
2742 size_t count
, struct triple
**vector
,
2743 struct triple
*ins
, struct triple
**last
)
2745 struct triple
**ret
;
2751 else if ((last
>= vector
) && (last
< (vector
+ count
- 1))) {
2759 static struct triple
**triple_lhs(struct compile_state
*state
,
2760 struct triple
*ins
, struct triple
**last
)
2762 return triple_iter(state
, ins
->lhs
, &LHS(ins
,0),
2766 static struct triple
**triple_rhs(struct compile_state
*state
,
2767 struct triple
*ins
, struct triple
**last
)
2769 return triple_iter(state
, ins
->rhs
, &RHS(ins
,0),
2773 static struct triple
**triple_misc(struct compile_state
*state
,
2774 struct triple
*ins
, struct triple
**last
)
2776 return triple_iter(state
, ins
->misc
, &MISC(ins
,0),
2780 static struct triple
**do_triple_targ(struct compile_state
*state
,
2781 struct triple
*ins
, struct triple
**last
, int call_edges
, int next_edges
)
2784 struct triple
**ret
, **vector
;
2789 if (triple_is_cbranch(state
, ins
)) {
2792 if (!call_edges
&& triple_is_call(state
, ins
)) {
2795 if (next_edges
&& triple_is_call(state
, ins
)) {
2798 vector
= &TARG(ins
, 0);
2799 if (!ret
&& next_is_targ
) {
2802 } else if (last
== &ins
->next
) {
2806 if (!ret
&& count
) {
2810 else if ((last
>= vector
) && (last
< (vector
+ count
- 1))) {
2813 else if (last
== vector
+ count
- 1) {
2817 if (!ret
&& triple_is_ret(state
, ins
) && call_edges
) {
2818 struct triple_set
*use
;
2819 for(use
= ins
->use
; use
; use
= use
->next
) {
2820 if (!triple_is_call(state
, use
->member
)) {
2824 ret
= &use
->member
->next
;
2827 else if (last
== &use
->member
->next
) {
2835 static struct triple
**triple_targ(struct compile_state
*state
,
2836 struct triple
*ins
, struct triple
**last
)
2838 return do_triple_targ(state
, ins
, last
, 1, 1);
2841 static struct triple
**triple_edge_targ(struct compile_state
*state
,
2842 struct triple
*ins
, struct triple
**last
)
2844 return do_triple_targ(state
, ins
, last
,
2845 state
->functions_joined
, !state
->functions_joined
);
2848 static struct triple
*after_lhs(struct compile_state
*state
, struct triple
*ins
)
2850 struct triple
*next
;
2854 for(i
= 0; i
< lhs
; i
++) {
2855 struct triple
*piece
;
2856 piece
= LHS(ins
, i
);
2857 if (next
!= piece
) {
2858 internal_error(state
, ins
, "malformed lhs on %s",
2861 if (next
->op
!= OP_PIECE
) {
2862 internal_error(state
, ins
, "bad lhs op %s at %d on %s",
2863 tops(next
->op
), i
, tops(ins
->op
));
2865 if (next
->u
.cval
!= i
) {
2866 internal_error(state
, ins
, "bad u.cval of %d %d expected",
2874 /* Function piece accessor functions */
2875 static struct triple
*do_farg(struct compile_state
*state
,
2876 struct triple
*func
, unsigned index
)
2879 struct triple
*first
, *arg
;
2883 if(index
>= (ftype
->elements
+ 2)) {
2884 internal_error(state
, func
, "bad argument index: %d", index
);
2886 first
= RHS(func
, 0);
2888 for(i
= 0; i
< index
; i
++, arg
= after_lhs(state
, arg
)) {
2891 if (arg
->op
!= OP_ADECL
) {
2892 internal_error(state
, 0, "arg not adecl?");
2896 static struct triple
*fresult(struct compile_state
*state
, struct triple
*func
)
2898 return do_farg(state
, func
, 0);
2900 static struct triple
*fretaddr(struct compile_state
*state
, struct triple
*func
)
2902 return do_farg(state
, func
, 1);
2904 static struct triple
*farg(struct compile_state
*state
,
2905 struct triple
*func
, unsigned index
)
2907 return do_farg(state
, func
, index
+ 2);
2911 static void display_func(struct compile_state
*state
, FILE *fp
, struct triple
*func
)
2913 struct triple
*first
, *ins
;
2914 fprintf(fp
, "display_func %s\n", func
->type
->type_ident
->name
);
2915 first
= ins
= RHS(func
, 0);
2917 if (triple_is_label(state
, ins
) && ins
->use
) {
2918 fprintf(fp
, "%p:\n", ins
);
2920 display_triple(fp
, ins
);
2922 if (triple_is_branch(state
, ins
)) {
2925 if (ins
->next
->prev
!= ins
) {
2926 internal_error(state
, ins
->next
, "bad prev");
2929 } while(ins
!= first
);
2932 static void verify_use(struct compile_state
*state
,
2933 struct triple
*user
, struct triple
*used
)
2936 size
= TRIPLE_SIZE(user
);
2937 for(i
= 0; i
< size
; i
++) {
2938 if (user
->param
[i
] == used
) {
2942 if (triple_is_branch(state
, user
)) {
2943 if (user
->next
== used
) {
2948 internal_error(state
, user
, "%s(%p) does not use %s(%p)",
2949 tops(user
->op
), user
, tops(used
->op
), used
);
2953 static int find_rhs_use(struct compile_state
*state
,
2954 struct triple
*user
, struct triple
*used
)
2956 struct triple
**param
;
2958 verify_use(state
, user
, used
);
2960 #if DEBUG_ROMCC_WARNINGS
2961 #warning "AUDIT ME ->rhs"
2964 param
= &RHS(user
, 0);
2965 for(i
= 0; i
< size
; i
++) {
2966 if (param
[i
] == used
) {
2973 static void free_triple(struct compile_state
*state
, struct triple
*ptr
)
2976 size
= sizeof(*ptr
) - sizeof(ptr
->param
) +
2977 (sizeof(ptr
->param
[0])*TRIPLE_SIZE(ptr
));
2978 ptr
->prev
->next
= ptr
->next
;
2979 ptr
->next
->prev
= ptr
->prev
;
2981 internal_error(state
, ptr
, "ptr->use != 0");
2983 put_occurance(ptr
->occurance
);
2984 memset(ptr
, -1, size
);
2988 static void release_triple(struct compile_state
*state
, struct triple
*ptr
)
2990 struct triple_set
*set
, *next
;
2991 struct triple
**expr
;
2992 struct block
*block
;
2993 if (ptr
== &unknown_triple
) {
2996 valid_ins(state
, ptr
);
2997 /* Make certain the we are not the first or last element of a block */
2998 block
= block_of_triple(state
, ptr
);
3000 if ((block
->last
== ptr
) && (block
->first
== ptr
)) {
3001 block
->last
= block
->first
= 0;
3003 else if (block
->last
== ptr
) {
3004 block
->last
= ptr
->prev
;
3006 else if (block
->first
== ptr
) {
3007 block
->first
= ptr
->next
;
3010 /* Remove ptr from use chains where it is the user */
3011 expr
= triple_rhs(state
, ptr
, 0);
3012 for(; expr
; expr
= triple_rhs(state
, ptr
, expr
)) {
3014 unuse_triple(*expr
, ptr
);
3017 expr
= triple_lhs(state
, ptr
, 0);
3018 for(; expr
; expr
= triple_lhs(state
, ptr
, expr
)) {
3020 unuse_triple(*expr
, ptr
);
3023 expr
= triple_misc(state
, ptr
, 0);
3024 for(; expr
; expr
= triple_misc(state
, ptr
, expr
)) {
3026 unuse_triple(*expr
, ptr
);
3029 expr
= triple_targ(state
, ptr
, 0);
3030 for(; expr
; expr
= triple_targ(state
, ptr
, expr
)) {
3032 unuse_triple(*expr
, ptr
);
3035 /* Reomve ptr from use chains where it is used */
3036 for(set
= ptr
->use
; set
; set
= next
) {
3038 valid_ins(state
, set
->member
);
3039 expr
= triple_rhs(state
, set
->member
, 0);
3040 for(; expr
; expr
= triple_rhs(state
, set
->member
, expr
)) {
3042 *expr
= &unknown_triple
;
3045 expr
= triple_lhs(state
, set
->member
, 0);
3046 for(; expr
; expr
= triple_lhs(state
, set
->member
, expr
)) {
3048 *expr
= &unknown_triple
;
3051 expr
= triple_misc(state
, set
->member
, 0);
3052 for(; expr
; expr
= triple_misc(state
, set
->member
, expr
)) {
3054 *expr
= &unknown_triple
;
3057 expr
= triple_targ(state
, set
->member
, 0);
3058 for(; expr
; expr
= triple_targ(state
, set
->member
, expr
)) {
3060 *expr
= &unknown_triple
;
3063 unuse_triple(ptr
, set
->member
);
3065 free_triple(state
, ptr
);
3068 static void print_triples(struct compile_state
*state
);
3069 static void print_blocks(struct compile_state
*state
, const char *func
, FILE *fp
);
3071 #define TOK_UNKNOWN 0
3074 #define TOK_LBRACE 3
3075 #define TOK_RBRACE 4
3079 #define TOK_LBRACKET 8
3080 #define TOK_RBRACKET 9
3081 #define TOK_LPAREN 10
3082 #define TOK_RPAREN 11
3087 #define TOK_TIMESEQ 16
3088 #define TOK_DIVEQ 17
3089 #define TOK_MODEQ 18
3090 #define TOK_PLUSEQ 19
3091 #define TOK_MINUSEQ 20
3094 #define TOK_ANDEQ 23
3095 #define TOK_XOREQ 24
3098 #define TOK_NOTEQ 27
3099 #define TOK_QUEST 28
3100 #define TOK_LOGOR 29
3101 #define TOK_LOGAND 30
3105 #define TOK_LESSEQ 34
3106 #define TOK_MOREEQ 35
3110 #define TOK_MINUS 39
3113 #define TOK_PLUSPLUS 42
3114 #define TOK_MINUSMINUS 43
3116 #define TOK_ARROW 45
3118 #define TOK_TILDE 47
3119 #define TOK_LIT_STRING 48
3120 #define TOK_LIT_CHAR 49
3121 #define TOK_LIT_INT 50
3122 #define TOK_LIT_FLOAT 51
3123 #define TOK_MACRO 52
3124 #define TOK_CONCATENATE 53
3126 #define TOK_IDENT 54
3127 #define TOK_STRUCT_NAME 55
3128 #define TOK_ENUM_CONST 56
3129 #define TOK_TYPE_NAME 57
3132 #define TOK_BREAK 59
3135 #define TOK_CONST 62
3136 #define TOK_CONTINUE 63
3137 #define TOK_DEFAULT 64
3139 #define TOK_DOUBLE 66
3142 #define TOK_EXTERN 69
3143 #define TOK_FLOAT 70
3147 #define TOK_INLINE 74
3150 #define TOK_REGISTER 77
3151 #define TOK_RESTRICT 78
3152 #define TOK_RETURN 79
3153 #define TOK_SHORT 80
3154 #define TOK_SIGNED 81
3155 #define TOK_SIZEOF 82
3156 #define TOK_STATIC 83
3157 #define TOK_STRUCT 84
3158 #define TOK_SWITCH 85
3159 #define TOK_TYPEDEF 86
3160 #define TOK_UNION 87
3161 #define TOK_UNSIGNED 88
3163 #define TOK_VOLATILE 90
3164 #define TOK_WHILE 91
3166 #define TOK_ATTRIBUTE 93
3167 #define TOK_ALIGNOF 94
3168 #define TOK_FIRST_KEYWORD TOK_AUTO
3169 #define TOK_LAST_KEYWORD TOK_ALIGNOF
3171 #define TOK_MDEFINE 100
3172 #define TOK_MDEFINED 101
3173 #define TOK_MUNDEF 102
3174 #define TOK_MINCLUDE 103
3175 #define TOK_MLINE 104
3176 #define TOK_MERROR 105
3177 #define TOK_MWARNING 106
3178 #define TOK_MPRAGMA 107
3179 #define TOK_MIFDEF 108
3180 #define TOK_MIFNDEF 109
3181 #define TOK_MELIF 110
3182 #define TOK_MENDIF 111
3184 #define TOK_FIRST_MACRO TOK_MDEFINE
3185 #define TOK_LAST_MACRO TOK_MENDIF
3188 #define TOK_MELSE 113
3189 #define TOK_MIDENT 114
3194 static const char *tokens
[] = {
3195 [TOK_UNKNOWN
] = ":unknown:",
3196 [TOK_SPACE
] = ":space:",
3198 [TOK_LBRACE
] = "{",
3199 [TOK_RBRACE
] = "}",
3203 [TOK_LBRACKET
] = "[",
3204 [TOK_RBRACKET
] = "]",
3205 [TOK_LPAREN
] = "(",
3206 [TOK_RPAREN
] = ")",
3208 [TOK_DOTS
] = "...",
3211 [TOK_TIMESEQ
] = "*=",
3212 [TOK_DIVEQ
] = "/=",
3213 [TOK_MODEQ
] = "%=",
3214 [TOK_PLUSEQ
] = "+=",
3215 [TOK_MINUSEQ
] = "-=",
3216 [TOK_SLEQ
] = "<<=",
3217 [TOK_SREQ
] = ">>=",
3218 [TOK_ANDEQ
] = "&=",
3219 [TOK_XOREQ
] = "^=",
3222 [TOK_NOTEQ
] = "!=",
3224 [TOK_LOGOR
] = "||",
3225 [TOK_LOGAND
] = "&&",
3229 [TOK_LESSEQ
] = "<=",
3230 [TOK_MOREEQ
] = ">=",
3237 [TOK_PLUSPLUS
] = "++",
3238 [TOK_MINUSMINUS
] = "--",
3240 [TOK_ARROW
] = "->",
3243 [TOK_LIT_STRING
] = ":string:",
3244 [TOK_IDENT
] = ":ident:",
3245 [TOK_TYPE_NAME
] = ":typename:",
3246 [TOK_LIT_CHAR
] = ":char:",
3247 [TOK_LIT_INT
] = ":integer:",
3248 [TOK_LIT_FLOAT
] = ":float:",
3250 [TOK_CONCATENATE
] = "##",
3252 [TOK_AUTO
] = "auto",
3253 [TOK_BREAK
] = "break",
3254 [TOK_CASE
] = "case",
3255 [TOK_CHAR
] = "char",
3256 [TOK_CONST
] = "const",
3257 [TOK_CONTINUE
] = "continue",
3258 [TOK_DEFAULT
] = "default",
3260 [TOK_DOUBLE
] = "double",
3261 [TOK_ELSE
] = "else",
3262 [TOK_ENUM
] = "enum",
3263 [TOK_EXTERN
] = "extern",
3264 [TOK_FLOAT
] = "float",
3266 [TOK_GOTO
] = "goto",
3268 [TOK_INLINE
] = "inline",
3270 [TOK_LONG
] = "long",
3271 [TOK_REGISTER
] = "register",
3272 [TOK_RESTRICT
] = "restrict",
3273 [TOK_RETURN
] = "return",
3274 [TOK_SHORT
] = "short",
3275 [TOK_SIGNED
] = "signed",
3276 [TOK_SIZEOF
] = "sizeof",
3277 [TOK_STATIC
] = "static",
3278 [TOK_STRUCT
] = "struct",
3279 [TOK_SWITCH
] = "switch",
3280 [TOK_TYPEDEF
] = "typedef",
3281 [TOK_UNION
] = "union",
3282 [TOK_UNSIGNED
] = "unsigned",
3283 [TOK_VOID
] = "void",
3284 [TOK_VOLATILE
] = "volatile",
3285 [TOK_WHILE
] = "while",
3287 [TOK_ATTRIBUTE
] = "__attribute__",
3288 [TOK_ALIGNOF
] = "__alignof__",
3290 [TOK_MDEFINE
] = "#define",
3291 [TOK_MDEFINED
] = "#defined",
3292 [TOK_MUNDEF
] = "#undef",
3293 [TOK_MINCLUDE
] = "#include",
3294 [TOK_MLINE
] = "#line",
3295 [TOK_MERROR
] = "#error",
3296 [TOK_MWARNING
] = "#warning",
3297 [TOK_MPRAGMA
] = "#pragma",
3298 [TOK_MIFDEF
] = "#ifdef",
3299 [TOK_MIFNDEF
] = "#ifndef",
3300 [TOK_MELIF
] = "#elif",
3301 [TOK_MENDIF
] = "#endif",
3304 [TOK_MELSE
] = "#else",
3305 [TOK_MIDENT
] = "#:ident:",
3310 static unsigned int hash(const char *str
, int str_len
)
3314 end
= str
+ str_len
;
3316 for(; str
< end
; str
++) {
3317 hash
= (hash
*263) + *str
;
3319 hash
= hash
& (HASH_TABLE_SIZE
-1);
3323 static struct hash_entry
*lookup(
3324 struct compile_state
*state
, const char *name
, int name_len
)
3326 struct hash_entry
*entry
;
3328 index
= hash(name
, name_len
);
3329 entry
= state
->hash_table
[index
];
3331 ((entry
->name_len
!= name_len
) ||
3332 (memcmp(entry
->name
, name
, name_len
) != 0))) {
3333 entry
= entry
->next
;
3337 /* Get a private copy of the name */
3338 new_name
= xmalloc(name_len
+ 1, "hash_name");
3339 memcpy(new_name
, name
, name_len
);
3340 new_name
[name_len
] = '\0';
3342 /* Create a new hash entry */
3343 entry
= xcmalloc(sizeof(*entry
), "hash_entry");
3344 entry
->next
= state
->hash_table
[index
];
3345 entry
->name
= new_name
;
3346 entry
->name_len
= name_len
;
3348 /* Place the new entry in the hash table */
3349 state
->hash_table
[index
] = entry
;
3354 static void ident_to_keyword(struct compile_state
*state
, struct token
*tk
)
3356 struct hash_entry
*entry
;
3358 if (entry
&& ((entry
->tok
== TOK_TYPE_NAME
) ||
3359 (entry
->tok
== TOK_ENUM_CONST
) ||
3360 ((entry
->tok
>= TOK_FIRST_KEYWORD
) &&
3361 (entry
->tok
<= TOK_LAST_KEYWORD
)))) {
3362 tk
->tok
= entry
->tok
;
3366 static void ident_to_macro(struct compile_state
*state
, struct token
*tk
)
3368 struct hash_entry
*entry
;
3372 if ((entry
->tok
>= TOK_FIRST_MACRO
) && (entry
->tok
<= TOK_LAST_MACRO
)) {
3373 tk
->tok
= entry
->tok
;
3375 else if (entry
->tok
== TOK_IF
) {
3378 else if (entry
->tok
== TOK_ELSE
) {
3379 tk
->tok
= TOK_MELSE
;
3382 tk
->tok
= TOK_MIDENT
;
3386 static void hash_keyword(
3387 struct compile_state
*state
, const char *keyword
, int tok
)
3389 struct hash_entry
*entry
;
3390 entry
= lookup(state
, keyword
, strlen(keyword
));
3391 if (entry
&& entry
->tok
!= TOK_UNKNOWN
) {
3392 die("keyword %s already hashed", keyword
);
3397 static void romcc_symbol(
3398 struct compile_state
*state
, struct hash_entry
*ident
,
3399 struct symbol
**chain
, struct triple
*def
, struct type
*type
, int depth
)
3402 if (*chain
&& ((*chain
)->scope_depth
>= depth
)) {
3403 error(state
, 0, "%s already defined", ident
->name
);
3405 sym
= xcmalloc(sizeof(*sym
), "symbol");
3409 sym
->scope_depth
= depth
;
3415 struct compile_state
*state
, struct hash_entry
*ident
,
3416 struct symbol
**chain
, struct triple
*def
, struct type
*type
)
3418 romcc_symbol(state
, ident
, chain
, def
, type
, state
->scope_depth
);
3421 static void var_symbol(struct compile_state
*state
,
3422 struct hash_entry
*ident
, struct triple
*def
)
3424 if ((def
->type
->type
& TYPE_MASK
) == TYPE_PRODUCT
) {
3425 internal_error(state
, 0, "bad var type");
3427 symbol(state
, ident
, &ident
->sym_ident
, def
, def
->type
);
3430 static void label_symbol(struct compile_state
*state
,
3431 struct hash_entry
*ident
, struct triple
*label
, int depth
)
3433 romcc_symbol(state
, ident
, &ident
->sym_label
, label
, &void_type
, depth
);
3436 static void start_scope(struct compile_state
*state
)
3438 state
->scope_depth
++;
3441 static void end_scope_syms(struct compile_state
*state
,
3442 struct symbol
**chain
, int depth
)
3444 struct symbol
*sym
, *next
;
3446 while(sym
&& (sym
->scope_depth
== depth
)) {
3454 static void end_scope(struct compile_state
*state
)
3458 /* Walk through the hash table and remove all symbols
3459 * in the current scope.
3461 depth
= state
->scope_depth
;
3462 for(i
= 0; i
< HASH_TABLE_SIZE
; i
++) {
3463 struct hash_entry
*entry
;
3464 entry
= state
->hash_table
[i
];
3466 end_scope_syms(state
, &entry
->sym_label
, depth
);
3467 end_scope_syms(state
, &entry
->sym_tag
, depth
);
3468 end_scope_syms(state
, &entry
->sym_ident
, depth
);
3469 entry
= entry
->next
;
3472 state
->scope_depth
= depth
- 1;
3475 static void register_keywords(struct compile_state
*state
)
3477 hash_keyword(state
, "auto", TOK_AUTO
);
3478 hash_keyword(state
, "break", TOK_BREAK
);
3479 hash_keyword(state
, "case", TOK_CASE
);
3480 hash_keyword(state
, "char", TOK_CHAR
);
3481 hash_keyword(state
, "const", TOK_CONST
);
3482 hash_keyword(state
, "continue", TOK_CONTINUE
);
3483 hash_keyword(state
, "default", TOK_DEFAULT
);
3484 hash_keyword(state
, "do", TOK_DO
);
3485 hash_keyword(state
, "double", TOK_DOUBLE
);
3486 hash_keyword(state
, "else", TOK_ELSE
);
3487 hash_keyword(state
, "enum", TOK_ENUM
);
3488 hash_keyword(state
, "extern", TOK_EXTERN
);
3489 hash_keyword(state
, "float", TOK_FLOAT
);
3490 hash_keyword(state
, "for", TOK_FOR
);
3491 hash_keyword(state
, "goto", TOK_GOTO
);
3492 hash_keyword(state
, "if", TOK_IF
);
3493 hash_keyword(state
, "inline", TOK_INLINE
);
3494 hash_keyword(state
, "int", TOK_INT
);
3495 hash_keyword(state
, "long", TOK_LONG
);
3496 hash_keyword(state
, "register", TOK_REGISTER
);
3497 hash_keyword(state
, "restrict", TOK_RESTRICT
);
3498 hash_keyword(state
, "return", TOK_RETURN
);
3499 hash_keyword(state
, "short", TOK_SHORT
);
3500 hash_keyword(state
, "signed", TOK_SIGNED
);
3501 hash_keyword(state
, "sizeof", TOK_SIZEOF
);
3502 hash_keyword(state
, "static", TOK_STATIC
);
3503 hash_keyword(state
, "struct", TOK_STRUCT
);
3504 hash_keyword(state
, "switch", TOK_SWITCH
);
3505 hash_keyword(state
, "typedef", TOK_TYPEDEF
);
3506 hash_keyword(state
, "union", TOK_UNION
);
3507 hash_keyword(state
, "unsigned", TOK_UNSIGNED
);
3508 hash_keyword(state
, "void", TOK_VOID
);
3509 hash_keyword(state
, "volatile", TOK_VOLATILE
);
3510 hash_keyword(state
, "__volatile__", TOK_VOLATILE
);
3511 hash_keyword(state
, "while", TOK_WHILE
);
3512 hash_keyword(state
, "asm", TOK_ASM
);
3513 hash_keyword(state
, "__asm__", TOK_ASM
);
3514 hash_keyword(state
, "__attribute__", TOK_ATTRIBUTE
);
3515 hash_keyword(state
, "__alignof__", TOK_ALIGNOF
);
3518 static void register_macro_keywords(struct compile_state
*state
)
3520 hash_keyword(state
, "define", TOK_MDEFINE
);
3521 hash_keyword(state
, "defined", TOK_MDEFINED
);
3522 hash_keyword(state
, "undef", TOK_MUNDEF
);
3523 hash_keyword(state
, "include", TOK_MINCLUDE
);
3524 hash_keyword(state
, "line", TOK_MLINE
);
3525 hash_keyword(state
, "error", TOK_MERROR
);
3526 hash_keyword(state
, "warning", TOK_MWARNING
);
3527 hash_keyword(state
, "pragma", TOK_MPRAGMA
);
3528 hash_keyword(state
, "ifdef", TOK_MIFDEF
);
3529 hash_keyword(state
, "ifndef", TOK_MIFNDEF
);
3530 hash_keyword(state
, "elif", TOK_MELIF
);
3531 hash_keyword(state
, "endif", TOK_MENDIF
);
3535 static void undef_macro(struct compile_state
*state
, struct hash_entry
*ident
)
3537 if (ident
->sym_define
!= 0) {
3538 struct macro
*macro
;
3539 struct macro_arg
*arg
, *anext
;
3540 macro
= ident
->sym_define
;
3541 ident
->sym_define
= 0;
3543 /* Free the macro arguments... */
3544 anext
= macro
->args
;
3551 /* Free the macro buffer */
3554 /* Now free the macro itself */
3559 static void do_define_macro(struct compile_state
*state
,
3560 struct hash_entry
*ident
, const char *body
,
3561 int argc
, struct macro_arg
*args
)
3563 struct macro
*macro
;
3564 struct macro_arg
*arg
;
3567 /* Find the length of the body */
3568 body_len
= strlen(body
);
3569 macro
= ident
->sym_define
;
3571 int identical_bodies
, identical_args
;
3572 struct macro_arg
*oarg
;
3573 /* Explicitly allow identical redfinitions of the same macro */
3575 (macro
->buf_len
== body_len
) &&
3576 (memcmp(macro
->buf
, body
, body_len
) == 0);
3577 identical_args
= macro
->argc
== argc
;
3580 while(identical_args
&& arg
) {
3581 identical_args
= oarg
->ident
== arg
->ident
;
3585 if (identical_bodies
&& identical_args
) {
3589 error(state
, 0, "macro %s already defined\n", ident
->name
);
3592 fprintf(state
->errout
, "#define %s: `%*.*s'\n",
3593 ident
->name
, body_len
, body_len
, body
);
3595 macro
= xmalloc(sizeof(*macro
), "macro");
3596 macro
->ident
= ident
;
3598 macro
->buf_len
= body_len
;
3602 ident
->sym_define
= macro
;
3605 static void define_macro(
3606 struct compile_state
*state
,
3607 struct hash_entry
*ident
,
3608 const char *body
, int body_len
,
3609 int argc
, struct macro_arg
*args
)
3612 buf
= xmalloc(body_len
+ 1, "macro buf");
3613 memcpy(buf
, body
, body_len
);
3614 buf
[body_len
] = '\0';
3615 do_define_macro(state
, ident
, buf
, argc
, args
);
3618 static void register_builtin_macro(struct compile_state
*state
,
3619 const char *name
, const char *value
)
3621 struct hash_entry
*ident
;
3623 if (value
[0] == '(') {
3624 internal_error(state
, 0, "Builtin macros with arguments not supported");
3626 ident
= lookup(state
, name
, strlen(name
));
3627 define_macro(state
, ident
, value
, strlen(value
), -1, 0);
3630 static void register_builtin_macros(struct compile_state
*state
)
3637 tm
= localtime(&now
);
3639 register_builtin_macro(state
, "__ROMCC__", VERSION_MAJOR
);
3640 register_builtin_macro(state
, "__ROMCC_MINOR__", VERSION_MINOR
);
3641 register_builtin_macro(state
, "__FILE__", "\"This should be the filename\"");
3642 register_builtin_macro(state
, "__LINE__", "54321");
3644 strftime(scratch
, sizeof(scratch
), "%b %e %Y", tm
);
3645 sprintf(buf
, "\"%s\"", scratch
);
3646 register_builtin_macro(state
, "__DATE__", buf
);
3648 strftime(scratch
, sizeof(scratch
), "%H:%M:%S", tm
);
3649 sprintf(buf
, "\"%s\"", scratch
);
3650 register_builtin_macro(state
, "__TIME__", buf
);
3652 /* I can't be a conforming implementation of C :( */
3653 register_builtin_macro(state
, "__STDC__", "0");
3654 /* In particular I don't conform to C99 */
3655 register_builtin_macro(state
, "__STDC_VERSION__", "199901L");
3659 static void process_cmdline_macros(struct compile_state
*state
)
3661 const char **macro
, *name
;
3662 struct hash_entry
*ident
;
3663 for(macro
= state
->compiler
->defines
; (name
= *macro
); macro
++) {
3667 name_len
= strlen(name
);
3668 body
= strchr(name
, '=');
3672 name_len
= body
- name
;
3675 ident
= lookup(state
, name
, name_len
);
3676 define_macro(state
, ident
, body
, strlen(body
), -1, 0);
3678 for(macro
= state
->compiler
->undefs
; (name
= *macro
); macro
++) {
3679 ident
= lookup(state
, name
, strlen(name
));
3680 undef_macro(state
, ident
);
3684 static int spacep(int c
)
3699 static int digitp(int c
)
3703 case '0': case '1': case '2': case '3': case '4':
3704 case '5': case '6': case '7': case '8': case '9':
3710 static int digval(int c
)
3713 if ((c
>= '0') && (c
<= '9')) {
3719 static int hexdigitp(int c
)
3723 case '0': case '1': case '2': case '3': case '4':
3724 case '5': case '6': case '7': case '8': case '9':
3725 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
3726 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
3732 static int hexdigval(int c
)
3735 if ((c
>= '0') && (c
<= '9')) {
3738 else if ((c
>= 'A') && (c
<= 'F')) {
3739 val
= 10 + (c
- 'A');
3741 else if ((c
>= 'a') && (c
<= 'f')) {
3742 val
= 10 + (c
- 'a');
3747 static int octdigitp(int c
)
3751 case '0': case '1': case '2': case '3':
3752 case '4': case '5': case '6': case '7':
3758 static int octdigval(int c
)
3761 if ((c
>= '0') && (c
<= '7')) {
3767 static int letterp(int c
)
3771 case 'a': case 'b': case 'c': case 'd': case 'e':
3772 case 'f': case 'g': case 'h': case 'i': case 'j':
3773 case 'k': case 'l': case 'm': case 'n': case 'o':
3774 case 'p': case 'q': case 'r': case 's': case 't':
3775 case 'u': case 'v': case 'w': case 'x': case 'y':
3777 case 'A': case 'B': case 'C': case 'D': case 'E':
3778 case 'F': case 'G': case 'H': case 'I': case 'J':
3779 case 'K': case 'L': case 'M': case 'N': case 'O':
3780 case 'P': case 'Q': case 'R': case 'S': case 'T':
3781 case 'U': case 'V': case 'W': case 'X': case 'Y':
3790 static const char *identifier(const char *str
, const char *end
)
3792 if (letterp(*str
)) {
3793 for(; str
< end
; str
++) {
3796 if (!letterp(c
) && !digitp(c
)) {
3804 static int char_value(struct compile_state
*state
,
3805 const signed char **strp
, const signed char *end
)
3807 const signed char *str
;
3811 if ((c
== '\\') && (str
< end
)) {
3813 case 'n': c
= '\n'; str
++; break;
3814 case 't': c
= '\t'; str
++; break;
3815 case 'v': c
= '\v'; str
++; break;
3816 case 'b': c
= '\b'; str
++; break;
3817 case 'r': c
= '\r'; str
++; break;
3818 case 'f': c
= '\f'; str
++; break;
3819 case 'a': c
= '\a'; str
++; break;
3820 case '\\': c
= '\\'; str
++; break;
3821 case '?': c
= '?'; str
++; break;
3822 case '\'': c
= '\''; str
++; break;
3823 case '"': c
= '"'; str
++; break;
3827 while((str
< end
) && hexdigitp(*str
)) {
3829 c
+= hexdigval(*str
);
3833 case '0': case '1': case '2': case '3':
3834 case '4': case '5': case '6': case '7':
3836 while((str
< end
) && octdigitp(*str
)) {
3838 c
+= octdigval(*str
);
3843 error(state
, 0, "Invalid character constant");
3851 static const char *next_char(struct file_state
*file
, const char *pos
, int index
)
3853 const char *end
= file
->buf
+ file
->size
;
3855 /* Lookup the character */
3858 /* Is this a trigraph? */
3859 if (file
->trigraphs
&&
3860 (c
== '?') && ((end
- pos
) >= 3) && (pos
[1] == '?'))
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;
3871 case '-': c
= '~'; break;
3877 /* Is this an escaped newline? */
3878 if (file
->join_lines
&&
3879 (c
== '\\') && (pos
+ size
< end
) && ((pos
[1] == '\n') || ((pos
[1] == '\r') && (pos
[2] == '\n'))))
3881 int cr_offset
= ((pos
[1] == '\r') && (pos
[2] == '\n'))?1:0;
3882 /* At the start of a line just eat it */
3883 if (pos
== file
->pos
) {
3885 file
->report_line
++;
3886 file
->line_start
= pos
+ size
+ 1 + cr_offset
;
3888 pos
+= size
+ 1 + cr_offset
;
3890 /* Do I need to ga any farther? */
3891 else if (index
== 0) {
3894 /* Process a normal character */
3903 static int get_char(struct file_state
*file
, const char *pos
)
3905 const char *end
= file
->buf
+ file
->size
;
3908 pos
= next_char(file
, pos
, 0);
3910 /* Lookup the character */
3912 /* If it is a trigraph get the trigraph value */
3913 if (file
->trigraphs
&&
3914 (c
== '?') && ((end
- pos
) >= 3) && (pos
[1] == '?'))
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;
3925 case '-': c
= '~'; break;
3932 static void eat_chars(struct file_state
*file
, const char *targ
)
3934 const char *pos
= file
->pos
;
3936 /* Do we have a newline? */
3937 if (pos
[0] == '\n') {
3939 file
->report_line
++;
3940 file
->line_start
= pos
+ 1;
3948 static size_t char_strlen(struct file_state
*file
, const char *src
, const char *end
)
3953 src
= next_char(file
, src
, 1);
3959 static void char_strcpy(char *dest
,
3960 struct file_state
*file
, const char *src
, const char *end
)
3964 c
= get_char(file
, src
);
3965 src
= next_char(file
, src
, 1);
3970 static char *char_strdup(struct file_state
*file
,
3971 const char *start
, const char *end
, const char *id
)
3975 str_len
= char_strlen(file
, start
, end
);
3976 str
= xcmalloc(str_len
+ 1, id
);
3977 char_strcpy(str
, file
, start
, end
);
3978 str
[str_len
] = '\0';
3982 static const char *after_digits(struct file_state
*file
, const char *ptr
)
3984 while(digitp(get_char(file
, ptr
))) {
3985 ptr
= next_char(file
, ptr
, 1);
3990 static const char *after_octdigits(struct file_state
*file
, const char *ptr
)
3992 while(octdigitp(get_char(file
, ptr
))) {
3993 ptr
= next_char(file
, ptr
, 1);
3998 static const char *after_hexdigits(struct file_state
*file
, const char *ptr
)
4000 while(hexdigitp(get_char(file
, ptr
))) {
4001 ptr
= next_char(file
, ptr
, 1);
4006 static const char *after_alnums(struct file_state
*file
, const char *ptr
)
4009 c
= get_char(file
, ptr
);
4010 while(letterp(c
) || digitp(c
)) {
4011 ptr
= next_char(file
, ptr
, 1);
4012 c
= get_char(file
, ptr
);
4017 static void save_string(struct file_state
*file
,
4018 struct token
*tk
, const char *start
, const char *end
, const char *id
)
4022 /* Create a private copy of the string */
4023 str
= char_strdup(file
, start
, end
, id
);
4025 /* Store the copy in the token */
4027 tk
->str_len
= strlen(str
);
4030 static void raw_next_token(struct compile_state
*state
,
4031 struct file_state
*file
, struct token
*tk
)
4041 token
= tokp
= next_char(file
, file
->pos
, 0);
4043 c
= get_char(file
, tokp
);
4044 tokp
= next_char(file
, tokp
, 1);
4046 c1
= get_char(file
, tokp
);
4047 c2
= get_char(file
, next_char(file
, tokp
, 1));
4048 c3
= get_char(file
, next_char(file
, tokp
, 2));
4050 /* The end of the file */
4055 else if (spacep(c
)) {
4057 while (spacep(get_char(file
, tokp
))) {
4058 tokp
= next_char(file
, tokp
, 1);
4062 else if ((c
== '/') && (c1
== '/')) {
4064 tokp
= next_char(file
, tokp
, 1);
4065 while((c
= get_char(file
, tokp
)) != -1) {
4066 /* Advance to the next character only after we verify
4067 * the current character is not a newline.
4068 * EOL is special to the preprocessor so we don't
4069 * want to loose any.
4074 tokp
= next_char(file
, tokp
, 1);
4078 else if ((c
== '/') && (c1
== '*')) {
4079 tokp
= next_char(file
, tokp
, 2);
4081 while((c1
= get_char(file
, tokp
)) != -1) {
4082 tokp
= next_char(file
, tokp
, 1);
4083 if ((c
== '*') && (c1
== '/')) {
4089 if (tok
== TOK_UNKNOWN
) {
4090 error(state
, 0, "unterminated comment");
4093 /* string constants */
4094 else if ((c
== '"') || ((c
== 'L') && (c1
== '"'))) {
4099 tokp
= next_char(file
, tokp
, 1);
4101 while((c
= get_char(file
, tokp
)) != -1) {
4102 tokp
= next_char(file
, tokp
, 1);
4106 else if (c
== '\\') {
4107 tokp
= next_char(file
, tokp
, 1);
4109 else if (c
== '"') {
4110 tok
= TOK_LIT_STRING
;
4114 if (tok
== TOK_UNKNOWN
) {
4115 error(state
, 0, "unterminated string constant");
4118 warning(state
, 0, "multiline string constant");
4121 /* Save the string value */
4122 save_string(file
, tk
, token
, tokp
, "literal string");
4124 /* character constants */
4125 else if ((c
== '\'') || ((c
== 'L') && (c1
== '\''))) {
4130 tokp
= next_char(file
, tokp
, 1);
4132 while((c
= get_char(file
, tokp
)) != -1) {
4133 tokp
= next_char(file
, tokp
, 1);
4137 else if (c
== '\\') {
4138 tokp
= next_char(file
, tokp
, 1);
4140 else if (c
== '\'') {
4145 if (tok
== TOK_UNKNOWN
) {
4146 error(state
, 0, "unterminated character constant");
4149 warning(state
, 0, "multiline character constant");
4152 /* Save the character value */
4153 save_string(file
, tk
, token
, tokp
, "literal character");
4155 /* integer and floating constants
4161 * Floating constants
4162 * {digits}.{digits}[Ee][+-]?{digits}
4164 * {digits}[Ee][+-]?{digits}
4165 * .{digits}[Ee][+-]?{digits}
4168 else if (digitp(c
) || ((c
== '.') && (digitp(c1
)))) {
4174 next
= after_digits(file
, tokp
);
4179 cn
= get_char(file
, next
);
4181 next
= next_char(file
, next
, 1);
4182 next
= after_digits(file
, next
);
4185 cn
= get_char(file
, next
);
4186 if ((cn
== 'e') || (cn
== 'E')) {
4188 next
= next_char(file
, next
, 1);
4189 cn
= get_char(file
, next
);
4190 if ((cn
== '+') || (cn
== '-')) {
4191 next
= next_char(file
, next
, 1);
4193 new = after_digits(file
, next
);
4194 is_float
|= (new != next
);
4198 tok
= TOK_LIT_FLOAT
;
4199 cn
= get_char(file
, next
);
4200 if ((cn
== 'f') || (cn
== 'F') || (cn
== 'l') || (cn
== 'L')) {
4201 next
= next_char(file
, next
, 1);
4204 if (!is_float
&& digitp(c
)) {
4206 if ((c
== '0') && ((c1
== 'x') || (c1
== 'X'))) {
4207 next
= next_char(file
, tokp
, 1);
4208 next
= after_hexdigits(file
, next
);
4210 else if (c
== '0') {
4211 next
= after_octdigits(file
, tokp
);
4214 next
= after_digits(file
, tokp
);
4216 /* crazy integer suffixes */
4217 cn
= get_char(file
, next
);
4218 if ((cn
== 'u') || (cn
== 'U')) {
4219 next
= next_char(file
, next
, 1);
4220 cn
= get_char(file
, next
);
4221 if ((cn
== 'l') || (cn
== 'L')) {
4222 next
= next_char(file
, next
, 1);
4223 cn
= get_char(file
, next
);
4225 if ((cn
== 'l') || (cn
== 'L')) {
4226 next
= next_char(file
, next
, 1);
4229 else if ((cn
== 'l') || (cn
== 'L')) {
4230 next
= next_char(file
, next
, 1);
4231 cn
= get_char(file
, next
);
4232 if ((cn
== 'l') || (cn
== 'L')) {
4233 next
= next_char(file
, next
, 1);
4234 cn
= get_char(file
, next
);
4236 if ((cn
== 'u') || (cn
== 'U')) {
4237 next
= next_char(file
, next
, 1);
4243 /* Save the integer/floating point value */
4244 save_string(file
, tk
, token
, tokp
, "literal number");
4247 else if (letterp(c
)) {
4250 /* Find and save the identifier string */
4251 tokp
= after_alnums(file
, tokp
);
4252 save_string(file
, tk
, token
, tokp
, "identifier");
4254 /* Look up to see which identifier it is */
4255 tk
->ident
= lookup(state
, tk
->val
.str
, tk
->str_len
);
4257 /* Free the identifier string */
4261 /* See if this identifier can be macro expanded */
4262 tk
->val
.notmacro
= 0;
4263 c
= get_char(file
, tokp
);
4265 tokp
= next_char(file
, tokp
, 1);
4266 tk
->val
.notmacro
= 1;
4269 /* C99 alternate macro characters */
4270 else if ((c
== '%') && (c1
== ':') && (c2
== '%') && (c3
== ':')) {
4272 tok
= TOK_CONCATENATE
;
4274 else if ((c
== '.') && (c1
== '.') && (c2
== '.')) { eat
+= 2; tok
= TOK_DOTS
; }
4275 else if ((c
== '<') && (c1
== '<') && (c2
== '=')) { eat
+= 2; tok
= TOK_SLEQ
; }
4276 else if ((c
== '>') && (c1
== '>') && (c2
== '=')) { eat
+= 2; tok
= TOK_SREQ
; }
4277 else if ((c
== '*') && (c1
== '=')) { eat
+= 1; tok
= TOK_TIMESEQ
; }
4278 else if ((c
== '/') && (c1
== '=')) { eat
+= 1; tok
= TOK_DIVEQ
; }
4279 else if ((c
== '%') && (c1
== '=')) { eat
+= 1; tok
= TOK_MODEQ
; }
4280 else if ((c
== '+') && (c1
== '=')) { eat
+= 1; tok
= TOK_PLUSEQ
; }
4281 else if ((c
== '-') && (c1
== '=')) { eat
+= 1; tok
= TOK_MINUSEQ
; }
4282 else if ((c
== '&') && (c1
== '=')) { eat
+= 1; tok
= TOK_ANDEQ
; }
4283 else if ((c
== '^') && (c1
== '=')) { eat
+= 1; tok
= TOK_XOREQ
; }
4284 else if ((c
== '|') && (c1
== '=')) { eat
+= 1; tok
= TOK_OREQ
; }
4285 else if ((c
== '=') && (c1
== '=')) { eat
+= 1; tok
= TOK_EQEQ
; }
4286 else if ((c
== '!') && (c1
== '=')) { eat
+= 1; tok
= TOK_NOTEQ
; }
4287 else if ((c
== '|') && (c1
== '|')) { eat
+= 1; tok
= TOK_LOGOR
; }
4288 else if ((c
== '&') && (c1
== '&')) { eat
+= 1; tok
= TOK_LOGAND
; }
4289 else if ((c
== '<') && (c1
== '=')) { eat
+= 1; tok
= TOK_LESSEQ
; }
4290 else if ((c
== '>') && (c1
== '=')) { eat
+= 1; tok
= TOK_MOREEQ
; }
4291 else if ((c
== '<') && (c1
== '<')) { eat
+= 1; tok
= TOK_SL
; }
4292 else if ((c
== '>') && (c1
== '>')) { eat
+= 1; tok
= TOK_SR
; }
4293 else if ((c
== '+') && (c1
== '+')) { eat
+= 1; tok
= TOK_PLUSPLUS
; }
4294 else if ((c
== '-') && (c1
== '-')) { eat
+= 1; tok
= TOK_MINUSMINUS
; }
4295 else if ((c
== '-') && (c1
== '>')) { eat
+= 1; tok
= TOK_ARROW
; }
4296 else if ((c
== '<') && (c1
== ':')) { eat
+= 1; tok
= TOK_LBRACKET
; }
4297 else if ((c
== ':') && (c1
== '>')) { eat
+= 1; tok
= TOK_RBRACKET
; }
4298 else if ((c
== '<') && (c1
== '%')) { eat
+= 1; tok
= TOK_LBRACE
; }
4299 else if ((c
== '%') && (c1
== '>')) { eat
+= 1; tok
= TOK_RBRACE
; }
4300 else if ((c
== '%') && (c1
== ':')) { eat
+= 1; tok
= TOK_MACRO
; }
4301 else if ((c
== '#') && (c1
== '#')) { eat
+= 1; tok
= TOK_CONCATENATE
; }
4302 else if (c
== ';') { tok
= TOK_SEMI
; }
4303 else if (c
== '{') { tok
= TOK_LBRACE
; }
4304 else if (c
== '}') { tok
= TOK_RBRACE
; }
4305 else if (c
== ',') { tok
= TOK_COMMA
; }
4306 else if (c
== '=') { tok
= TOK_EQ
; }
4307 else if (c
== ':') { tok
= TOK_COLON
; }
4308 else if (c
== '[') { tok
= TOK_LBRACKET
; }
4309 else if (c
== ']') { tok
= TOK_RBRACKET
; }
4310 else if (c
== '(') { tok
= TOK_LPAREN
; }
4311 else if (c
== ')') { tok
= TOK_RPAREN
; }
4312 else if (c
== '*') { tok
= TOK_STAR
; }
4313 else if (c
== '>') { tok
= TOK_MORE
; }
4314 else if (c
== '<') { tok
= TOK_LESS
; }
4315 else if (c
== '?') { tok
= TOK_QUEST
; }
4316 else if (c
== '|') { tok
= TOK_OR
; }
4317 else if (c
== '&') { tok
= TOK_AND
; }
4318 else if (c
== '^') { tok
= TOK_XOR
; }
4319 else if (c
== '+') { tok
= TOK_PLUS
; }
4320 else if (c
== '-') { tok
= TOK_MINUS
; }
4321 else if (c
== '/') { tok
= TOK_DIV
; }
4322 else if (c
== '%') { tok
= TOK_MOD
; }
4323 else if (c
== '!') { tok
= TOK_BANG
; }
4324 else if (c
== '.') { tok
= TOK_DOT
; }
4325 else if (c
== '~') { tok
= TOK_TILDE
; }
4326 else if (c
== '#') { tok
= TOK_MACRO
; }
4327 else if (c
== '\n') { tok
= TOK_EOL
; }
4329 tokp
= next_char(file
, tokp
, eat
);
4330 eat_chars(file
, tokp
);
4335 static void check_tok(struct compile_state
*state
, struct token
*tk
, int tok
)
4337 if (tk
->tok
!= tok
) {
4338 const char *name1
, *name2
;
4339 name1
= tokens
[tk
->tok
];
4341 if ((tk
->tok
== TOK_IDENT
) || (tk
->tok
== TOK_MIDENT
)) {
4342 name2
= tk
->ident
->name
;
4344 error(state
, 0, "\tfound %s %s expected %s",
4345 name1
, name2
, tokens
[tok
]);
4349 struct macro_arg_value
{
4350 struct hash_entry
*ident
;
4354 static struct macro_arg_value
*read_macro_args(
4355 struct compile_state
*state
, struct macro
*macro
,
4356 struct file_state
*file
, struct token
*tk
)
4358 struct macro_arg_value
*argv
;
4359 struct macro_arg
*arg
;
4363 if (macro
->argc
== 0) {
4365 raw_next_token(state
, file
, tk
);
4366 } while(tk
->tok
== TOK_SPACE
);
4369 argv
= xcmalloc(sizeof(*argv
) * macro
->argc
, "macro args");
4370 for(i
= 0, arg
= macro
->args
; arg
; arg
= arg
->next
, i
++) {
4373 argv
[i
].ident
= arg
->ident
;
4382 raw_next_token(state
, file
, tk
);
4384 if (!paren_depth
&& (tk
->tok
== TOK_COMMA
) &&
4385 (argv
[i
].ident
!= state
->i___VA_ARGS__
))
4388 if (i
>= macro
->argc
) {
4389 error(state
, 0, "too many args to %s\n",
4390 macro
->ident
->name
);
4395 if (tk
->tok
== TOK_LPAREN
) {
4399 if (tk
->tok
== TOK_RPAREN
) {
4400 if (paren_depth
== 0) {
4405 if (tk
->tok
== TOK_EOF
) {
4406 error(state
, 0, "End of file encountered while parsing macro arguments");
4409 len
= char_strlen(file
, start
, file
->pos
);
4410 argv
[i
].value
= xrealloc(
4411 argv
[i
].value
, argv
[i
].len
+ len
, "macro args");
4412 char_strcpy((char *)argv
[i
].value
+ argv
[i
].len
, file
, start
, file
->pos
);
4415 if (i
!= macro
->argc
-1) {
4416 error(state
, 0, "missing %s arg %d\n",
4417 macro
->ident
->name
, i
+2);
4423 static void free_macro_args(struct macro
*macro
, struct macro_arg_value
*argv
)
4426 for(i
= 0; i
< macro
->argc
; i
++) {
4427 xfree(argv
[i
].value
);
4437 static void grow_macro_buf(struct compile_state
*state
,
4438 const char *id
, struct macro_buf
*buf
,
4441 if ((buf
->pos
+ grow
) >= buf
->len
) {
4442 buf
->str
= xrealloc(buf
->str
, buf
->len
+ grow
, id
);
4447 static void append_macro_text(struct compile_state
*state
,
4448 const char *id
, struct macro_buf
*buf
,
4449 const char *fstart
, size_t flen
)
4451 grow_macro_buf(state
, id
, buf
, flen
);
4452 memcpy(buf
->str
+ buf
->pos
, fstart
, flen
);
4454 fprintf(state
->errout
, "append: `%*.*s' `%*.*s'\n",
4455 buf
->pos
, buf
->pos
, buf
->str
,
4456 flen
, flen
, buf
->str
+ buf
->pos
);
4462 static void append_macro_chars(struct compile_state
*state
,
4463 const char *id
, struct macro_buf
*buf
,
4464 struct file_state
*file
, const char *start
, const char *end
)
4467 flen
= char_strlen(file
, start
, end
);
4468 grow_macro_buf(state
, id
, buf
, flen
);
4469 char_strcpy(buf
->str
+ buf
->pos
, file
, start
, end
);
4471 fprintf(state
->errout
, "append: `%*.*s' `%*.*s'\n",
4472 buf
->pos
, buf
->pos
, buf
->str
,
4473 flen
, flen
, buf
->str
+ buf
->pos
);
4478 static int compile_macro(struct compile_state
*state
,
4479 struct file_state
**filep
, struct token
*tk
);
4481 static void macro_expand_args(struct compile_state
*state
,
4482 struct macro
*macro
, struct macro_arg_value
*argv
, struct token
*tk
)
4486 for(i
= 0; i
< macro
->argc
; i
++) {
4487 struct file_state fmacro
, *file
;
4488 struct macro_buf buf
;
4491 fmacro
.basename
= argv
[i
].ident
->name
;
4492 fmacro
.dirname
= "";
4493 fmacro
.buf
= (char *)argv
[i
].value
;
4494 fmacro
.size
= argv
[i
].len
;
4495 fmacro
.pos
= fmacro
.buf
;
4497 fmacro
.line_start
= fmacro
.buf
;
4498 fmacro
.report_line
= 1;
4499 fmacro
.report_name
= fmacro
.basename
;
4500 fmacro
.report_dir
= fmacro
.dirname
;
4502 fmacro
.trigraphs
= 0;
4503 fmacro
.join_lines
= 0;
4505 buf
.len
= argv
[i
].len
;
4506 buf
.str
= xmalloc(buf
.len
, argv
[i
].ident
->name
);
4511 raw_next_token(state
, file
, tk
);
4513 /* If we have recursed into another macro body
4516 if (tk
->tok
== TOK_EOF
) {
4517 struct file_state
*old
;
4523 /* old->basename is used keep it */
4524 xfree(old
->dirname
);
4529 else if (tk
->ident
&& tk
->ident
->sym_define
) {
4530 if (compile_macro(state
, &file
, tk
)) {
4535 append_macro_chars(state
, macro
->ident
->name
, &buf
,
4536 file
, tk
->pos
, file
->pos
);
4539 xfree(argv
[i
].value
);
4540 argv
[i
].value
= buf
.str
;
4541 argv
[i
].len
= buf
.pos
;
4546 static void expand_macro(struct compile_state
*state
,
4547 struct macro
*macro
, struct macro_buf
*buf
,
4548 struct macro_arg_value
*argv
, struct token
*tk
)
4550 struct file_state fmacro
;
4551 const char space
[] = " ";
4556 /* Place the macro body in a dummy file */
4558 fmacro
.basename
= macro
->ident
->name
;
4559 fmacro
.dirname
= "";
4560 fmacro
.buf
= macro
->buf
;
4561 fmacro
.size
= macro
->buf_len
;
4562 fmacro
.pos
= fmacro
.buf
;
4564 fmacro
.line_start
= fmacro
.buf
;
4565 fmacro
.report_line
= 1;
4566 fmacro
.report_name
= fmacro
.basename
;
4567 fmacro
.report_dir
= fmacro
.dirname
;
4569 fmacro
.trigraphs
= 0;
4570 fmacro
.join_lines
= 0;
4572 /* Allocate a buffer to hold the macro expansion */
4573 buf
->len
= macro
->buf_len
+ 3;
4574 buf
->str
= xmalloc(buf
->len
, macro
->ident
->name
);
4577 fstart
= fmacro
.pos
;
4578 raw_next_token(state
, &fmacro
, tk
);
4579 while(tk
->tok
!= TOK_EOF
) {
4580 flen
= fmacro
.pos
- fstart
;
4583 for(i
= 0; i
< macro
->argc
; i
++) {
4584 if (argv
[i
].ident
== tk
->ident
) {
4588 if (i
>= macro
->argc
) {
4591 /* Substitute macro parameter */
4592 fstart
= argv
[i
].value
;
4596 if (macro
->argc
< 0) {
4600 raw_next_token(state
, &fmacro
, tk
);
4601 } while(tk
->tok
== TOK_SPACE
);
4602 check_tok(state
, tk
, TOK_IDENT
);
4603 for(i
= 0; i
< macro
->argc
; i
++) {
4604 if (argv
[i
].ident
== tk
->ident
) {
4608 if (i
>= macro
->argc
) {
4609 error(state
, 0, "parameter `%s' not found",
4612 /* Stringize token */
4613 append_macro_text(state
, macro
->ident
->name
, buf
, "\"", 1);
4614 for(j
= 0; j
< argv
[i
].len
; j
++) {
4615 char *str
= argv
[i
].value
+ j
;
4621 else if (*str
== '"') {
4625 append_macro_text(state
, macro
->ident
->name
, buf
, str
, len
);
4627 append_macro_text(state
, macro
->ident
->name
, buf
, "\"", 1);
4631 case TOK_CONCATENATE
:
4632 /* Concatenate tokens */
4633 /* Delete the previous whitespace token */
4634 if (buf
->str
[buf
->pos
- 1] == ' ') {
4637 /* Skip the next sequence of whitspace tokens */
4639 fstart
= fmacro
.pos
;
4640 raw_next_token(state
, &fmacro
, tk
);
4641 } while(tk
->tok
== TOK_SPACE
);
4642 /* Restart at the top of the loop.
4643 * I need to process the non white space token.
4648 /* Collapse multiple spaces into one */
4649 if (buf
->str
[buf
->pos
- 1] != ' ') {
4661 append_macro_text(state
, macro
->ident
->name
, buf
, fstart
, flen
);
4663 fstart
= fmacro
.pos
;
4664 raw_next_token(state
, &fmacro
, tk
);
4668 static void tag_macro_name(struct compile_state
*state
,
4669 struct macro
*macro
, struct macro_buf
*buf
,
4672 /* Guard all instances of the macro name in the replacement
4673 * text from further macro expansion.
4675 struct file_state fmacro
;
4679 /* Put the old macro expansion buffer in a file */
4681 fmacro
.basename
= macro
->ident
->name
;
4682 fmacro
.dirname
= "";
4683 fmacro
.buf
= buf
->str
;
4684 fmacro
.size
= buf
->pos
;
4685 fmacro
.pos
= fmacro
.buf
;
4687 fmacro
.line_start
= fmacro
.buf
;
4688 fmacro
.report_line
= 1;
4689 fmacro
.report_name
= fmacro
.basename
;
4690 fmacro
.report_dir
= fmacro
.dirname
;
4692 fmacro
.trigraphs
= 0;
4693 fmacro
.join_lines
= 0;
4695 /* Allocate a new macro expansion buffer */
4696 buf
->len
= macro
->buf_len
+ 3;
4697 buf
->str
= xmalloc(buf
->len
, macro
->ident
->name
);
4700 fstart
= fmacro
.pos
;
4701 raw_next_token(state
, &fmacro
, tk
);
4702 while(tk
->tok
!= TOK_EOF
) {
4703 flen
= fmacro
.pos
- fstart
;
4704 if ((tk
->tok
== TOK_IDENT
) &&
4705 (tk
->ident
== macro
->ident
) &&
4706 (tk
->val
.notmacro
== 0))
4708 append_macro_text(state
, macro
->ident
->name
, buf
, fstart
, flen
);
4713 append_macro_text(state
, macro
->ident
->name
, buf
, fstart
, flen
);
4715 fstart
= fmacro
.pos
;
4716 raw_next_token(state
, &fmacro
, tk
);
4721 static int compile_macro(struct compile_state
*state
,
4722 struct file_state
**filep
, struct token
*tk
)
4724 struct file_state
*file
;
4725 struct hash_entry
*ident
;
4726 struct macro
*macro
;
4727 struct macro_arg_value
*argv
;
4728 struct macro_buf buf
;
4731 fprintf(state
->errout
, "macro: %s\n", tk
->ident
->name
);
4734 macro
= ident
->sym_define
;
4736 /* If this token comes from a macro expansion ignore it */
4737 if (tk
->val
.notmacro
) {
4740 /* If I am a function like macro and the identifier is not followed
4741 * by a left parenthesis, do nothing.
4743 if ((macro
->argc
>= 0) && (get_char(*filep
, (*filep
)->pos
) != '(')) {
4747 /* Read in the macro arguments */
4749 if (macro
->argc
>= 0) {
4750 raw_next_token(state
, *filep
, tk
);
4751 check_tok(state
, tk
, TOK_LPAREN
);
4753 argv
= read_macro_args(state
, macro
, *filep
, tk
);
4755 check_tok(state
, tk
, TOK_RPAREN
);
4757 /* Macro expand the macro arguments */
4758 macro_expand_args(state
, macro
, argv
, tk
);
4763 if (ident
== state
->i___FILE__
) {
4764 buf
.len
= strlen(state
->file
->basename
) + 1 + 2 + 3;
4765 buf
.str
= xmalloc(buf
.len
, ident
->name
);
4766 sprintf(buf
.str
, "\"%s\"", state
->file
->basename
);
4767 buf
.pos
= strlen(buf
.str
);
4769 else if (ident
== state
->i___LINE__
) {
4771 buf
.str
= xmalloc(buf
.len
, ident
->name
);
4772 sprintf(buf
.str
, "%d", state
->file
->line
);
4773 buf
.pos
= strlen(buf
.str
);
4776 expand_macro(state
, macro
, &buf
, argv
, tk
);
4778 /* Tag the macro name with a $ so it will no longer
4779 * be regonized as a canidate for macro expansion.
4781 tag_macro_name(state
, macro
, &buf
, tk
);
4784 fprintf(state
->errout
, "%s: %d -> `%*.*s'\n",
4785 ident
->name
, buf
.pos
, buf
.pos
, (int)(buf
.pos
), buf
.str
);
4788 free_macro_args(macro
, argv
);
4790 file
= xmalloc(sizeof(*file
), "file_state");
4791 file
->prev
= *filep
;
4792 file
->basename
= xstrdup(ident
->name
);
4793 file
->dirname
= xstrdup("");
4794 file
->buf
= buf
.str
;
4795 file
->size
= buf
.pos
;
4796 file
->pos
= file
->buf
;
4798 file
->line_start
= file
->pos
;
4799 file
->report_line
= 1;
4800 file
->report_name
= file
->basename
;
4801 file
->report_dir
= file
->dirname
;
4803 file
->trigraphs
= 0;
4804 file
->join_lines
= 0;
4809 static void eat_tokens(struct compile_state
*state
, int targ_tok
)
4811 if (state
->eat_depth
> 0) {
4812 internal_error(state
, 0, "Already eating...");
4814 state
->eat_depth
= state
->if_depth
;
4815 state
->eat_targ
= targ_tok
;
4817 static int if_eat(struct compile_state
*state
)
4819 return state
->eat_depth
> 0;
4821 static int if_value(struct compile_state
*state
)
4824 index
= state
->if_depth
/ CHAR_BIT
;
4825 offset
= state
->if_depth
% CHAR_BIT
;
4826 return !!(state
->if_bytes
[index
] & (1 << (offset
)));
4828 static void set_if_value(struct compile_state
*state
, int value
)
4831 index
= state
->if_depth
/ CHAR_BIT
;
4832 offset
= state
->if_depth
% CHAR_BIT
;
4834 state
->if_bytes
[index
] &= ~(1 << offset
);
4836 state
->if_bytes
[index
] |= (1 << offset
);
4839 static void in_if(struct compile_state
*state
, const char *name
)
4841 if (state
->if_depth
<= 0) {
4842 error(state
, 0, "%s without #if", name
);
4845 static void enter_if(struct compile_state
*state
)
4847 state
->if_depth
+= 1;
4848 if (state
->if_depth
> MAX_PP_IF_DEPTH
) {
4849 error(state
, 0, "#if depth too great");
4852 static void reenter_if(struct compile_state
*state
, const char *name
)
4855 if ((state
->eat_depth
== state
->if_depth
) &&
4856 (state
->eat_targ
== TOK_MELSE
)) {
4857 state
->eat_depth
= 0;
4858 state
->eat_targ
= 0;
4861 static void enter_else(struct compile_state
*state
, const char *name
)
4864 if ((state
->eat_depth
== state
->if_depth
) &&
4865 (state
->eat_targ
== TOK_MELSE
)) {
4866 state
->eat_depth
= 0;
4867 state
->eat_targ
= 0;
4870 static void exit_if(struct compile_state
*state
, const char *name
)
4873 if (state
->eat_depth
== state
->if_depth
) {
4874 state
->eat_depth
= 0;
4875 state
->eat_targ
= 0;
4877 state
->if_depth
-= 1;
4880 static void raw_token(struct compile_state
*state
, struct token
*tk
)
4882 struct file_state
*file
;
4886 raw_next_token(state
, file
, tk
);
4890 /* Exit out of an include directive or macro call */
4891 if ((tk
->tok
== TOK_EOF
) &&
4892 (file
!= state
->macro_file
) && file
->prev
)
4894 state
->file
= file
->prev
;
4895 /* file->basename is used keep it */
4896 xfree(file
->dirname
);
4900 raw_next_token(state
, state
->file
, tk
);
4906 static void pp_token(struct compile_state
*state
, struct token
*tk
)
4910 raw_token(state
, tk
);
4913 if (tk
->tok
== TOK_SPACE
) {
4914 raw_token(state
, tk
);
4917 else if (tk
->tok
== TOK_IDENT
) {
4918 if (state
->token_base
== 0) {
4919 ident_to_keyword(state
, tk
);
4921 ident_to_macro(state
, tk
);
4927 static void preprocess(struct compile_state
*state
, struct token
*tk
);
4929 static void token(struct compile_state
*state
, struct token
*tk
)
4932 pp_token(state
, tk
);
4935 /* Process a macro directive */
4936 if (tk
->tok
== TOK_MACRO
) {
4937 /* Only match preprocessor directives at the start of a line */
4939 ptr
= state
->file
->line_start
;
4940 while((ptr
< tk
->pos
)
4941 && spacep(get_char(state
->file
, ptr
)))
4943 ptr
= next_char(state
->file
, ptr
, 1);
4945 if (ptr
== tk
->pos
) {
4946 preprocess(state
, tk
);
4950 /* Expand a macro call */
4951 else if (tk
->ident
&& tk
->ident
->sym_define
) {
4952 rescan
= compile_macro(state
, &state
->file
, tk
);
4954 pp_token(state
, tk
);
4957 /* Eat tokens disabled by the preprocessor
4958 * (Unless we are parsing a preprocessor directive
4960 else if (if_eat(state
) && (state
->token_base
== 0)) {
4961 pp_token(state
, tk
);
4964 /* Make certain EOL only shows up in preprocessor directives */
4965 else if ((tk
->tok
== TOK_EOL
) && (state
->token_base
== 0)) {
4966 pp_token(state
, tk
);
4969 /* Error on unknown tokens */
4970 else if (tk
->tok
== TOK_UNKNOWN
) {
4971 error(state
, 0, "unknown token");
4977 static inline struct token
*get_token(struct compile_state
*state
, int offset
)
4980 index
= state
->token_base
+ offset
;
4981 if (index
>= sizeof(state
->token
)/sizeof(state
->token
[0])) {
4982 internal_error(state
, 0, "token array to small");
4984 return &state
->token
[index
];
4987 static struct token
*do_eat_token(struct compile_state
*state
, int tok
)
4991 check_tok(state
, get_token(state
, 1), tok
);
4993 /* Free the old token value */
4994 tk
= get_token(state
, 0);
4996 memset((void *)tk
->val
.str
, -1, tk
->str_len
);
4999 /* Overwrite the old token with newer tokens */
5000 for(i
= state
->token_base
; i
< sizeof(state
->token
)/sizeof(state
->token
[0]) - 1; i
++) {
5001 state
->token
[i
] = state
->token
[i
+ 1];
5003 /* Clear the last token */
5004 memset(&state
->token
[i
], 0, sizeof(state
->token
[i
]));
5005 state
->token
[i
].tok
= -1;
5007 /* Return the token */
5011 static int raw_peek(struct compile_state
*state
)
5014 tk1
= get_token(state
, 1);
5015 if (tk1
->tok
== -1) {
5016 raw_token(state
, tk1
);
5021 static struct token
*raw_eat(struct compile_state
*state
, int tok
)
5024 return do_eat_token(state
, tok
);
5027 static int pp_peek(struct compile_state
*state
)
5030 tk1
= get_token(state
, 1);
5031 if (tk1
->tok
== -1) {
5032 pp_token(state
, tk1
);
5037 static struct token
*pp_eat(struct compile_state
*state
, int tok
)
5040 return do_eat_token(state
, tok
);
5043 static int peek(struct compile_state
*state
)
5046 tk1
= get_token(state
, 1);
5047 if (tk1
->tok
== -1) {
5053 static int peek2(struct compile_state
*state
)
5055 struct token
*tk1
, *tk2
;
5056 tk1
= get_token(state
, 1);
5057 tk2
= get_token(state
, 2);
5058 if (tk1
->tok
== -1) {
5061 if (tk2
->tok
== -1) {
5067 static struct token
*eat(struct compile_state
*state
, int tok
)
5070 return do_eat_token(state
, tok
);
5073 static void compile_file(struct compile_state
*state
, const char *filename
, int local
)
5075 char cwd
[MAX_CWD_SIZE
];
5076 const char *subdir
, *base
;
5078 struct file_state
*file
;
5080 file
= xmalloc(sizeof(*file
), "file_state");
5082 base
= strrchr(filename
, '/');
5085 subdir_len
= base
- filename
;
5092 basename
= xmalloc(strlen(base
) +1, "basename");
5093 strcpy(basename
, base
);
5094 file
->basename
= basename
;
5096 if (getcwd(cwd
, sizeof(cwd
)) == 0) {
5097 die("cwd buffer to small");
5099 if ((subdir
[0] == '/') || ((subdir
[1] == ':') && ((subdir
[2] == '/') || (subdir
[2] == '\\')))) {
5100 file
->dirname
= xmalloc(subdir_len
+ 1, "dirname");
5101 memcpy(file
->dirname
, subdir
, subdir_len
);
5102 file
->dirname
[subdir_len
] = '\0';
5108 /* Find the appropriate directory... */
5110 if (!state
->file
&& exists(cwd
, filename
)) {
5113 if (local
&& state
->file
&& exists(state
->file
->dirname
, filename
)) {
5114 dir
= state
->file
->dirname
;
5116 for(path
= state
->compiler
->include_paths
; !dir
&& *path
; path
++) {
5117 if (exists(*path
, filename
)) {
5122 error(state
, 0, "Cannot open `%s'\n", filename
);
5124 dirlen
= strlen(dir
);
5125 file
->dirname
= xmalloc(dirlen
+ 1 + subdir_len
+ 1, "dirname");
5126 memcpy(file
->dirname
, dir
, dirlen
);
5127 file
->dirname
[dirlen
] = '/';
5128 memcpy(file
->dirname
+ dirlen
+ 1, subdir
, subdir_len
);
5129 file
->dirname
[dirlen
+ 1 + subdir_len
] = '\0';
5131 file
->buf
= slurp_file(file
->dirname
, file
->basename
, &file
->size
);
5133 file
->pos
= file
->buf
;
5134 file
->line_start
= file
->pos
;
5137 file
->report_line
= 1;
5138 file
->report_name
= file
->basename
;
5139 file
->report_dir
= file
->dirname
;
5141 file
->trigraphs
= (state
->compiler
->flags
& COMPILER_TRIGRAPHS
)? 1: 0;
5142 file
->join_lines
= 1;
5144 file
->prev
= state
->file
;
5148 static struct triple
*constant_expr(struct compile_state
*state
);
5149 static void integral(struct compile_state
*state
, struct triple
*def
);
5151 static int mcexpr(struct compile_state
*state
)
5153 struct triple
*cvalue
;
5154 cvalue
= constant_expr(state
);
5155 integral(state
, cvalue
);
5156 if (cvalue
->op
!= OP_INTCONST
) {
5157 error(state
, 0, "integer constant expected");
5159 return cvalue
->u
.cval
!= 0;
5162 static void preprocess(struct compile_state
*state
, struct token
*current_token
)
5164 /* Doing much more with the preprocessor would require
5165 * a parser and a major restructuring.
5166 * Postpone that for later.
5171 state
->macro_file
= state
->file
;
5173 old_token_base
= state
->token_base
;
5174 state
->token_base
= current_token
- state
->token
;
5176 tok
= pp_peek(state
);
5182 tk
= pp_eat(state
, TOK_LIT_INT
);
5183 override_line
= strtoul(tk
->val
.str
, 0, 10);
5184 /* I have a preprocessor line marker parse it */
5185 if (pp_peek(state
) == TOK_LIT_STRING
) {
5186 const char *token
, *base
;
5188 int name_len
, dir_len
;
5189 tk
= pp_eat(state
, TOK_LIT_STRING
);
5190 name
= xmalloc(tk
->str_len
, "report_name");
5191 token
= tk
->val
.str
+ 1;
5192 base
= strrchr(token
, '/');
5193 name_len
= tk
->str_len
-2;
5195 dir_len
= base
- token
;
5197 name_len
-= base
- token
;
5202 memcpy(name
, base
, name_len
);
5203 name
[name_len
] = '\0';
5204 dir
= xmalloc(dir_len
+ 1, "report_dir");
5205 memcpy(dir
, token
, dir_len
);
5206 dir
[dir_len
] = '\0';
5207 state
->file
->report_line
= override_line
- 1;
5208 state
->file
->report_name
= name
;
5209 state
->file
->report_dir
= dir
;
5210 state
->file
->macro
= 0;
5217 pp_eat(state
, TOK_MLINE
);
5218 tk
= eat(state
, TOK_LIT_INT
);
5219 state
->file
->report_line
= strtoul(tk
->val
.str
, 0, 10) -1;
5220 if (pp_peek(state
) == TOK_LIT_STRING
) {
5221 const char *token
, *base
;
5223 int name_len
, dir_len
;
5224 tk
= pp_eat(state
, TOK_LIT_STRING
);
5225 name
= xmalloc(tk
->str_len
, "report_name");
5226 token
= tk
->val
.str
+ 1;
5227 base
= strrchr(token
, '/');
5228 name_len
= tk
->str_len
- 2;
5230 dir_len
= base
- token
;
5232 name_len
-= base
- token
;
5237 memcpy(name
, base
, name_len
);
5238 name
[name_len
] = '\0';
5239 dir
= xmalloc(dir_len
+ 1, "report_dir");
5240 memcpy(dir
, token
, dir_len
);
5241 dir
[dir_len
] = '\0';
5242 state
->file
->report_name
= name
;
5243 state
->file
->report_dir
= dir
;
5244 state
->file
->macro
= 0;
5250 struct hash_entry
*ident
;
5251 pp_eat(state
, TOK_MUNDEF
);
5252 if (if_eat(state
)) /* quit early when #if'd out */
5255 ident
= pp_eat(state
, TOK_MIDENT
)->ident
;
5257 undef_macro(state
, ident
);
5261 pp_eat(state
, TOK_MPRAGMA
);
5262 if (if_eat(state
)) /* quit early when #if'd out */
5264 warning(state
, 0, "Ignoring pragma");
5267 pp_eat(state
, TOK_MELIF
);
5268 reenter_if(state
, "#elif");
5269 if (if_eat(state
)) /* quit early when #if'd out */
5271 /* If the #if was taken the #elif just disables the following code */
5272 if (if_value(state
)) {
5273 eat_tokens(state
, TOK_MENDIF
);
5275 /* If the previous #if was not taken see if the #elif enables the
5279 set_if_value(state
, mcexpr(state
));
5280 if (!if_value(state
)) {
5281 eat_tokens(state
, TOK_MELSE
);
5286 pp_eat(state
, TOK_MIF
);
5288 if (if_eat(state
)) /* quit early when #if'd out */
5290 set_if_value(state
, mcexpr(state
));
5291 if (!if_value(state
)) {
5292 eat_tokens(state
, TOK_MELSE
);
5297 struct hash_entry
*ident
;
5299 pp_eat(state
, TOK_MIFNDEF
);
5301 if (if_eat(state
)) /* quit early when #if'd out */
5303 ident
= pp_eat(state
, TOK_MIDENT
)->ident
;
5304 set_if_value(state
, ident
->sym_define
== 0);
5305 if (!if_value(state
)) {
5306 eat_tokens(state
, TOK_MELSE
);
5312 struct hash_entry
*ident
;
5313 pp_eat(state
, TOK_MIFDEF
);
5315 if (if_eat(state
)) /* quit early when #if'd out */
5317 ident
= pp_eat(state
, TOK_MIDENT
)->ident
;
5318 set_if_value(state
, ident
->sym_define
!= 0);
5319 if (!if_value(state
)) {
5320 eat_tokens(state
, TOK_MELSE
);
5325 pp_eat(state
, TOK_MELSE
);
5326 enter_else(state
, "#else");
5327 if (!if_eat(state
) && if_value(state
)) {
5328 eat_tokens(state
, TOK_MENDIF
);
5332 pp_eat(state
, TOK_MENDIF
);
5333 exit_if(state
, "#endif");
5337 struct hash_entry
*ident
;
5338 struct macro_arg
*args
, **larg
;
5339 const char *mstart
, *mend
;
5342 pp_eat(state
, TOK_MDEFINE
);
5343 if (if_eat(state
)) /* quit early when #if'd out */
5345 ident
= pp_eat(state
, TOK_MIDENT
)->ident
;
5350 /* Parse macro parameters */
5351 if (raw_peek(state
) == TOK_LPAREN
) {
5352 raw_eat(state
, TOK_LPAREN
);
5356 struct macro_arg
*narg
, *arg
;
5357 struct hash_entry
*aident
;
5360 tok
= pp_peek(state
);
5361 if (!args
&& (tok
== TOK_RPAREN
)) {
5364 else if (tok
== TOK_DOTS
) {
5365 pp_eat(state
, TOK_DOTS
);
5366 aident
= state
->i___VA_ARGS__
;
5369 aident
= pp_eat(state
, TOK_MIDENT
)->ident
;
5372 narg
= xcmalloc(sizeof(*arg
), "macro arg");
5373 narg
->ident
= aident
;
5375 /* Verify I don't have a duplicate identifier */
5376 for(arg
= args
; arg
; arg
= arg
->next
) {
5377 if (arg
->ident
== narg
->ident
) {
5378 error(state
, 0, "Duplicate macro arg `%s'",
5382 /* Add the new argument to the end of the list */
5387 if ((aident
== state
->i___VA_ARGS__
) ||
5388 (pp_peek(state
) != TOK_COMMA
)) {
5391 pp_eat(state
, TOK_COMMA
);
5393 pp_eat(state
, TOK_RPAREN
);
5395 /* Remove leading whitespace */
5396 while(raw_peek(state
) == TOK_SPACE
) {
5397 raw_eat(state
, TOK_SPACE
);
5400 /* Remember the start of the macro body */
5401 tok
= raw_peek(state
);
5402 mend
= mstart
= get_token(state
, 1)->pos
;
5404 /* Find the end of the macro */
5405 for(tok
= raw_peek(state
); tok
!= TOK_EOL
; tok
= raw_peek(state
)) {
5406 raw_eat(state
, tok
);
5407 /* Remember the end of the last non space token */
5409 if (tok
!= TOK_SPACE
) {
5410 mend
= get_token(state
, 1)->pos
;
5414 /* Now that I have found the body defined the token */
5415 do_define_macro(state
, ident
,
5416 char_strdup(state
->file
, mstart
, mend
, "macro buf"),
5422 const char *start
, *end
;
5425 pp_eat(state
, TOK_MERROR
);
5426 /* Find the start of the line */
5428 start
= get_token(state
, 1)->pos
;
5430 /* Find the end of the line */
5431 while((tok
= raw_peek(state
)) != TOK_EOL
) {
5432 raw_eat(state
, tok
);
5434 end
= get_token(state
, 1)->pos
;
5436 if (!if_eat(state
)) {
5437 error(state
, 0, "%*.*s", len
, len
, start
);
5443 const char *start
, *end
;
5446 pp_eat(state
, TOK_MWARNING
);
5448 /* Find the start of the line */
5450 start
= get_token(state
, 1)->pos
;
5452 /* Find the end of the line */
5453 while((tok
= raw_peek(state
)) != TOK_EOL
) {
5454 raw_eat(state
, tok
);
5456 end
= get_token(state
, 1)->pos
;
5458 if (!if_eat(state
)) {
5459 warning(state
, 0, "%*.*s", len
, len
, start
);
5470 pp_eat(state
, TOK_MINCLUDE
);
5471 if (if_eat(state
)) {
5472 /* Find the end of the line */
5473 while((tok
= raw_peek(state
)) != TOK_EOL
) {
5474 raw_eat(state
, tok
);
5479 if (tok
== TOK_LIT_STRING
) {
5483 tk
= eat(state
, TOK_LIT_STRING
);
5484 name
= xmalloc(tk
->str_len
, "include");
5485 token
= tk
->val
.str
+1;
5486 name_len
= tk
->str_len
-2;
5487 if (*token
== '"') {
5491 memcpy(name
, token
, name_len
);
5492 name
[name_len
] = '\0';
5495 else if (tok
== TOK_LESS
) {
5496 struct macro_buf buf
;
5497 eat(state
, TOK_LESS
);
5500 buf
.str
= xmalloc(buf
.len
, "include");
5504 while((tok
!= TOK_MORE
) &&
5505 (tok
!= TOK_EOL
) && (tok
!= TOK_EOF
))
5508 tk
= eat(state
, tok
);
5509 append_macro_chars(state
, "include", &buf
,
5510 state
->file
, tk
->pos
, state
->file
->pos
);
5513 append_macro_text(state
, "include", &buf
, "\0", 1);
5514 if (peek(state
) != TOK_MORE
) {
5515 error(state
, 0, "Unterminated include directive");
5517 eat(state
, TOK_MORE
);
5522 error(state
, 0, "Invalid include directive");
5524 /* Error if there are any tokens after the include */
5525 if (pp_peek(state
) != TOK_EOL
) {
5526 error(state
, 0, "garbage after include directive");
5528 if (!if_eat(state
)) {
5529 compile_file(state
, name
, local
);
5535 /* Ignore # without a follwing ident */
5539 const char *name1
, *name2
;
5540 name1
= tokens
[tok
];
5542 if (tok
== TOK_MIDENT
) {
5543 name2
= get_token(state
, 1)->ident
->name
;
5545 error(state
, 0, "Invalid preprocessor directive: %s %s",
5550 /* Consume the rest of the macro line */
5552 tok
= pp_peek(state
);
5554 } while((tok
!= TOK_EOF
) && (tok
!= TOK_EOL
));
5555 state
->token_base
= old_token_base
;
5556 state
->macro_file
= NULL
;
5560 /* Type helper functions */
5562 static struct type
*new_type(
5563 unsigned int type
, struct type
*left
, struct type
*right
)
5565 struct type
*result
;
5566 result
= xmalloc(sizeof(*result
), "type");
5567 result
->type
= type
;
5568 result
->left
= left
;
5569 result
->right
= right
;
5570 result
->field_ident
= 0;
5571 result
->type_ident
= 0;
5572 result
->elements
= 0;
5576 static struct type
*clone_type(unsigned int specifiers
, struct type
*old
)
5578 struct type
*result
;
5579 result
= xmalloc(sizeof(*result
), "type");
5580 memcpy(result
, old
, sizeof(*result
));
5581 result
->type
&= TYPE_MASK
;
5582 result
->type
|= specifiers
;
5586 static struct type
*dup_type(struct compile_state
*state
, struct type
*orig
)
5589 new = xcmalloc(sizeof(*new), "type");
5590 new->type
= orig
->type
;
5591 new->field_ident
= orig
->field_ident
;
5592 new->type_ident
= orig
->type_ident
;
5593 new->elements
= orig
->elements
;
5595 new->left
= dup_type(state
, orig
->left
);
5598 new->right
= dup_type(state
, orig
->right
);
5604 static struct type
*invalid_type(struct compile_state
*state
, struct type
*type
)
5606 struct type
*invalid
, *member
;
5609 internal_error(state
, 0, "type missing?");
5611 switch(type
->type
& TYPE_MASK
) {
5613 case TYPE_CHAR
: case TYPE_UCHAR
:
5614 case TYPE_SHORT
: case TYPE_USHORT
:
5615 case TYPE_INT
: case TYPE_UINT
:
5616 case TYPE_LONG
: case TYPE_ULONG
:
5617 case TYPE_LLONG
: case TYPE_ULLONG
:
5622 invalid
= invalid_type(state
, type
->left
);
5625 invalid
= invalid_type(state
, type
->left
);
5629 member
= type
->left
;
5630 while(member
&& (invalid
== 0) &&
5631 ((member
->type
& TYPE_MASK
) == TYPE_PRODUCT
)) {
5632 invalid
= invalid_type(state
, member
->left
);
5633 member
= member
->right
;
5636 invalid
= invalid_type(state
, member
);
5641 member
= type
->left
;
5642 while(member
&& (invalid
== 0) &&
5643 ((member
->type
& TYPE_MASK
) == TYPE_OVERLAP
)) {
5644 invalid
= invalid_type(state
, member
->left
);
5645 member
= member
->right
;
5648 invalid
= invalid_type(state
, member
);
5659 static struct type void_type
= { .type
= TYPE_VOID
};
5660 static struct type char_type
= { .type
= TYPE_CHAR
};
5661 static struct type uchar_type
= { .type
= TYPE_UCHAR
};
5662 #if DEBUG_ROMCC_WARNING
5663 static struct type short_type
= { .type
= TYPE_SHORT
};
5665 static struct type ushort_type
= { .type
= TYPE_USHORT
};
5666 static struct type int_type
= { .type
= TYPE_INT
};
5667 static struct type uint_type
= { .type
= TYPE_UINT
};
5668 static struct type long_type
= { .type
= TYPE_LONG
};
5669 static struct type ulong_type
= { .type
= TYPE_ULONG
};
5670 static struct type unknown_type
= { .type
= TYPE_UNKNOWN
};
5672 static struct type void_ptr_type
= {
5673 .type
= TYPE_POINTER
,
5677 #if DEBUG_ROMCC_WARNING
5678 static struct type void_func_type
= {
5679 .type
= TYPE_FUNCTION
,
5681 .right
= &void_type
,
5685 static size_t bits_to_bytes(size_t size
)
5687 return (size
+ SIZEOF_CHAR
- 1)/SIZEOF_CHAR
;
5690 static struct triple
*variable(struct compile_state
*state
, struct type
*type
)
5692 struct triple
*result
;
5693 if ((type
->type
& STOR_MASK
) != STOR_PERM
) {
5694 result
= triple(state
, OP_ADECL
, type
, 0, 0);
5695 generate_lhs_pieces(state
, result
);
5698 result
= triple(state
, OP_SDECL
, type
, 0, 0);
5703 static void stor_of(FILE *fp
, struct type
*type
)
5705 switch(type
->type
& STOR_MASK
) {
5707 fprintf(fp
, "auto ");
5710 fprintf(fp
, "static ");
5713 fprintf(fp
, "local ");
5716 fprintf(fp
, "extern ");
5719 fprintf(fp
, "register ");
5722 fprintf(fp
, "typedef ");
5724 case STOR_INLINE
| STOR_LOCAL
:
5725 fprintf(fp
, "inline ");
5727 case STOR_INLINE
| STOR_STATIC
:
5728 fprintf(fp
, "static inline");
5730 case STOR_INLINE
| STOR_EXTERN
:
5731 fprintf(fp
, "extern inline");
5734 fprintf(fp
, "stor:%x", type
->type
& STOR_MASK
);
5738 static void qual_of(FILE *fp
, struct type
*type
)
5740 if (type
->type
& QUAL_CONST
) {
5741 fprintf(fp
, " const");
5743 if (type
->type
& QUAL_VOLATILE
) {
5744 fprintf(fp
, " volatile");
5746 if (type
->type
& QUAL_RESTRICT
) {
5747 fprintf(fp
, " restrict");
5751 static void name_of(FILE *fp
, struct type
*type
)
5753 unsigned int base_type
;
5754 base_type
= type
->type
& TYPE_MASK
;
5755 if ((base_type
!= TYPE_PRODUCT
) && (base_type
!= TYPE_OVERLAP
)) {
5760 fprintf(fp
, "void");
5764 fprintf(fp
, "signed char");
5768 fprintf(fp
, "unsigned char");
5772 fprintf(fp
, "signed short");
5776 fprintf(fp
, "unsigned short");
5780 fprintf(fp
, "signed int");
5784 fprintf(fp
, "unsigned int");
5788 fprintf(fp
, "signed long");
5792 fprintf(fp
, "unsigned long");
5796 name_of(fp
, type
->left
);
5801 name_of(fp
, type
->left
);
5803 name_of(fp
, type
->right
);
5806 name_of(fp
, type
->left
);
5808 name_of(fp
, type
->right
);
5811 fprintf(fp
, "enum %s",
5812 (type
->type_ident
)? type
->type_ident
->name
: "");
5816 fprintf(fp
, "struct %s { ",
5817 (type
->type_ident
)? type
->type_ident
->name
: "");
5818 name_of(fp
, type
->left
);
5823 fprintf(fp
, "union %s { ",
5824 (type
->type_ident
)? type
->type_ident
->name
: "");
5825 name_of(fp
, type
->left
);
5830 name_of(fp
, type
->left
);
5831 fprintf(fp
, " (*)(");
5832 name_of(fp
, type
->right
);
5836 name_of(fp
, type
->left
);
5837 fprintf(fp
, " [%ld]", (long)(type
->elements
));
5840 fprintf(fp
, "tuple { ");
5841 name_of(fp
, type
->left
);
5846 fprintf(fp
, "join { ");
5847 name_of(fp
, type
->left
);
5852 name_of(fp
, type
->left
);
5853 fprintf(fp
, " : %d ", type
->elements
);
5857 fprintf(fp
, "unknown_t");
5860 fprintf(fp
, "????: %x", base_type
);
5863 if (type
->field_ident
&& type
->field_ident
->name
) {
5864 fprintf(fp
, " .%s", type
->field_ident
->name
);
5868 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
)
5928 switch(type
->type
& TYPE_MASK
) {
5937 align
= REG_ALIGNOF_CHAR
;
5941 align
= REG_ALIGNOF_SHORT
;
5946 align
= REG_ALIGNOF_INT
;
5950 align
= REG_ALIGNOF_LONG
;
5953 align
= REG_ALIGNOF_POINTER
;
5958 size_t left_align
, right_align
;
5959 left_align
= reg_align_of(state
, type
->left
);
5960 right_align
= reg_align_of(state
, type
->right
);
5961 align
= (left_align
>= right_align
) ? left_align
: right_align
;
5965 align
= reg_align_of(state
, type
->left
);
5971 align
= reg_align_of(state
, type
->left
);
5974 error(state
, 0, "alignof not yet defined for type\n");
5980 static size_t align_of_in_bytes(struct compile_state
*state
, struct type
*type
)
5982 return bits_to_bytes(align_of(state
, type
));
5984 static size_t size_of(struct compile_state
*state
, struct type
*type
);
5985 static size_t reg_size_of(struct compile_state
*state
, struct type
*type
);
5987 static size_t needed_padding(struct compile_state
*state
,
5988 struct type
*type
, size_t offset
)
5990 size_t padding
, align
;
5991 align
= align_of(state
, type
);
5992 /* Align to the next machine word if the bitfield does completely
5993 * fit into the current word.
5995 if ((type
->type
& TYPE_MASK
) == TYPE_BITFIELD
) {
5997 size
= size_of(state
, type
);
5998 if ((offset
+ type
->elements
)/size
!= offset
/size
) {
6003 if (offset
% align
) {
6004 padding
= align
- (offset
% align
);
6009 static size_t reg_needed_padding(struct compile_state
*state
,
6010 struct type
*type
, size_t offset
)
6012 size_t padding
, align
;
6013 align
= reg_align_of(state
, type
);
6014 /* Align to the next register word if the bitfield does completely
6015 * fit into the current register.
6017 if (((type
->type
& TYPE_MASK
) == TYPE_BITFIELD
) &&
6018 (((offset
+ type
->elements
)/REG_SIZEOF_REG
) != (offset
/REG_SIZEOF_REG
)))
6020 align
= REG_SIZEOF_REG
;
6023 if (offset
% align
) {
6024 padding
= align
- (offset
% align
);
6029 static size_t size_of(struct compile_state
*state
, struct type
*type
)
6033 switch(type
->type
& TYPE_MASK
) {
6038 size
= type
->elements
;
6046 size
= SIZEOF_SHORT
;
6058 size
= SIZEOF_POINTER
;
6064 while((type
->type
& TYPE_MASK
) == TYPE_PRODUCT
) {
6065 pad
= needed_padding(state
, type
->left
, size
);
6066 size
= size
+ pad
+ size_of(state
, type
->left
);
6069 pad
= needed_padding(state
, type
, size
);
6070 size
= size
+ pad
+ size_of(state
, type
);
6075 size_t size_left
, size_right
;
6076 size_left
= size_of(state
, type
->left
);
6077 size_right
= size_of(state
, type
->right
);
6078 size
= (size_left
>= size_right
)? size_left
: size_right
;
6082 if (type
->elements
== ELEMENT_COUNT_UNSPECIFIED
) {
6083 internal_error(state
, 0, "Invalid array type");
6085 size
= size_of(state
, type
->left
) * type
->elements
;
6092 size
= size_of(state
, type
->left
);
6093 /* Pad structures so their size is a multiples of their alignment */
6094 pad
= needed_padding(state
, type
, size
);
6102 size
= size_of(state
, type
->left
);
6103 /* Pad unions so their size is a multiple of their alignment */
6104 pad
= needed_padding(state
, type
, size
);
6109 internal_error(state
, 0, "sizeof not yet defined for type");
6115 static size_t reg_size_of(struct compile_state
*state
, struct type
*type
)
6119 switch(type
->type
& TYPE_MASK
) {
6124 size
= type
->elements
;
6128 size
= REG_SIZEOF_CHAR
;
6132 size
= REG_SIZEOF_SHORT
;
6137 size
= REG_SIZEOF_INT
;
6141 size
= REG_SIZEOF_LONG
;
6144 size
= REG_SIZEOF_POINTER
;
6150 while((type
->type
& TYPE_MASK
) == TYPE_PRODUCT
) {
6151 pad
= reg_needed_padding(state
, type
->left
, size
);
6152 size
= size
+ pad
+ reg_size_of(state
, type
->left
);
6155 pad
= reg_needed_padding(state
, type
, size
);
6156 size
= size
+ pad
+ reg_size_of(state
, type
);
6161 size_t size_left
, size_right
;
6162 size_left
= reg_size_of(state
, type
->left
);
6163 size_right
= reg_size_of(state
, type
->right
);
6164 size
= (size_left
>= size_right
)? size_left
: size_right
;
6168 if (type
->elements
== ELEMENT_COUNT_UNSPECIFIED
) {
6169 internal_error(state
, 0, "Invalid array type");
6171 size
= reg_size_of(state
, type
->left
) * type
->elements
;
6178 size
= reg_size_of(state
, type
->left
);
6179 /* Pad structures so their size is a multiples of their alignment */
6180 pad
= reg_needed_padding(state
, type
, size
);
6188 size
= reg_size_of(state
, type
->left
);
6189 /* Pad unions so their size is a multiple of their alignment */
6190 pad
= reg_needed_padding(state
, type
, size
);
6195 internal_error(state
, 0, "sizeof not yet defined for type");
6201 static size_t registers_of(struct compile_state
*state
, struct type
*type
)
6204 registers
= reg_size_of(state
, type
);
6205 registers
+= REG_SIZEOF_REG
- 1;
6206 registers
/= REG_SIZEOF_REG
;
6210 static size_t size_of_in_bytes(struct compile_state
*state
, struct type
*type
)
6212 return bits_to_bytes(size_of(state
, type
));
6215 static size_t field_offset(struct compile_state
*state
,
6216 struct type
*type
, struct hash_entry
*field
)
6218 struct type
*member
;
6223 if ((type
->type
& TYPE_MASK
) == TYPE_STRUCT
) {
6224 member
= type
->left
;
6225 while(member
&& ((member
->type
& TYPE_MASK
) == TYPE_PRODUCT
)) {
6226 size
+= needed_padding(state
, member
->left
, size
);
6227 if (member
->left
->field_ident
== field
) {
6228 member
= member
->left
;
6231 size
+= size_of(state
, member
->left
);
6232 member
= member
->right
;
6234 size
+= needed_padding(state
, member
, size
);
6236 else if ((type
->type
& TYPE_MASK
) == TYPE_UNION
) {
6237 member
= type
->left
;
6238 while(member
&& ((member
->type
& TYPE_MASK
) == TYPE_OVERLAP
)) {
6239 if (member
->left
->field_ident
== field
) {
6240 member
= member
->left
;
6243 member
= member
->right
;
6247 internal_error(state
, 0, "field_offset only works on structures and unions");
6250 if (!member
|| (member
->field_ident
!= field
)) {
6251 error(state
, 0, "member %s not present", field
->name
);
6256 static size_t field_reg_offset(struct compile_state
*state
,
6257 struct type
*type
, struct hash_entry
*field
)
6259 struct type
*member
;
6264 if ((type
->type
& TYPE_MASK
) == TYPE_STRUCT
) {
6265 member
= type
->left
;
6266 while(member
&& ((member
->type
& TYPE_MASK
) == TYPE_PRODUCT
)) {
6267 size
+= reg_needed_padding(state
, member
->left
, size
);
6268 if (member
->left
->field_ident
== field
) {
6269 member
= member
->left
;
6272 size
+= reg_size_of(state
, member
->left
);
6273 member
= member
->right
;
6276 else if ((type
->type
& TYPE_MASK
) == TYPE_UNION
) {
6277 member
= type
->left
;
6278 while(member
&& ((member
->type
& TYPE_MASK
) == TYPE_OVERLAP
)) {
6279 if (member
->left
->field_ident
== field
) {
6280 member
= member
->left
;
6283 member
= member
->right
;
6287 internal_error(state
, 0, "field_reg_offset only works on structures and unions");
6290 size
+= reg_needed_padding(state
, member
, size
);
6291 if (!member
|| (member
->field_ident
!= field
)) {
6292 error(state
, 0, "member %s not present", field
->name
);
6297 static struct type
*field_type(struct compile_state
*state
,
6298 struct type
*type
, struct hash_entry
*field
)
6300 struct type
*member
;
6303 if ((type
->type
& TYPE_MASK
) == TYPE_STRUCT
) {
6304 member
= type
->left
;
6305 while(member
&& ((member
->type
& TYPE_MASK
) == TYPE_PRODUCT
)) {
6306 if (member
->left
->field_ident
== field
) {
6307 member
= member
->left
;
6310 member
= member
->right
;
6313 else if ((type
->type
& TYPE_MASK
) == TYPE_UNION
) {
6314 member
= type
->left
;
6315 while(member
&& ((member
->type
& TYPE_MASK
) == TYPE_OVERLAP
)) {
6316 if (member
->left
->field_ident
== field
) {
6317 member
= member
->left
;
6320 member
= member
->right
;
6324 internal_error(state
, 0, "field_type only works on structures and unions");
6327 if (!member
|| (member
->field_ident
!= field
)) {
6328 error(state
, 0, "member %s not present", field
->name
);
6333 static size_t index_offset(struct compile_state
*state
,
6334 struct type
*type
, ulong_t index
)
6336 struct type
*member
;
6339 if ((type
->type
& TYPE_MASK
) == TYPE_ARRAY
) {
6340 size
= size_of(state
, type
->left
) * index
;
6342 else if ((type
->type
& TYPE_MASK
) == TYPE_TUPLE
) {
6344 member
= type
->left
;
6346 while(member
&& ((member
->type
& TYPE_MASK
) == TYPE_PRODUCT
)) {
6347 size
+= needed_padding(state
, member
->left
, size
);
6349 member
= member
->left
;
6352 size
+= size_of(state
, member
->left
);
6354 member
= member
->right
;
6356 size
+= needed_padding(state
, member
, size
);
6358 internal_error(state
, 0, "Missing member index: %u", index
);
6361 else if ((type
->type
& TYPE_MASK
) == TYPE_JOIN
) {
6364 member
= type
->left
;
6366 while(member
&& ((member
->type
& TYPE_MASK
) == TYPE_OVERLAP
)) {
6368 member
= member
->left
;
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
;
6409 size
+= reg_needed_padding(state
, member
, size
);
6411 internal_error(state
, 0, "Missing member index: %u", index
);
6415 else if ((type
->type
& TYPE_MASK
) == TYPE_JOIN
) {
6418 member
= type
->left
;
6420 while(member
&& ((member
->type
& TYPE_MASK
) == TYPE_OVERLAP
)) {
6422 member
= member
->left
;
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
;
6649 offset
+= reg_needed_padding(state
, member
, offset
);
6650 member
= reg_type(state
, member
, reg_offset
- offset
);
6656 struct type
*join
, **jnext
, *mnext
;
6657 join
= new_type(TYPE_JOIN
, 0, 0);
6658 jnext
= &join
->left
;
6664 if ((member
->type
& TYPE_MASK
) == TYPE_OVERLAP
) {
6665 mnext
= member
->right
;
6666 member
= member
->left
;
6668 size
= reg_size_of(state
, member
);
6669 if (size
> reg_offset
) {
6670 struct type
*part
, *hunt
;
6671 part
= reg_type(state
, member
, reg_offset
);
6672 /* See if this type is already in the union */
6675 struct type
*test
= hunt
;
6677 if ((test
->type
& TYPE_MASK
) == TYPE_OVERLAP
) {
6681 if (equiv_types(part
, test
)) {
6689 *jnext
= new_type(TYPE_OVERLAP
, *jnext
, part
);
6690 jnext
= &(*jnext
)->right
;
6697 if (join
->elements
== 0) {
6698 internal_error(state
, 0, "No elements?");
6705 fprintf(state
->errout
, "type: ");
6706 name_of(state
->errout
, type
);
6707 fprintf(state
->errout
, "\n");
6708 internal_error(state
, 0, "reg_type not yet defined for type");
6712 /* If I have a single register compound type not a bit-field
6713 * find the real type.
6715 member
= unpack_type(state
, member
);
6717 size
= reg_size_of(state
, member
);
6718 if (size
> REG_SIZEOF_REG
) {
6719 internal_error(state
, 0, "Cannot find type of single register");
6722 invalid
= invalid_type(state
, member
);
6724 fprintf(state
->errout
, "type: ");
6725 name_of(state
->errout
, member
);
6726 fprintf(state
->errout
, "\n");
6727 fprintf(state
->errout
, "invalid: ");
6728 name_of(state
->errout
, invalid
);
6729 fprintf(state
->errout
, "\n");
6730 internal_error(state
, 0, "returning bad type?");
6736 static struct type
*next_field(struct compile_state
*state
,
6737 struct type
*type
, struct type
*prev_member
)
6739 struct type
*member
;
6740 if ((type
->type
& TYPE_MASK
) != TYPE_STRUCT
) {
6741 internal_error(state
, 0, "next_field only works on structures");
6743 member
= type
->left
;
6744 while((member
->type
& TYPE_MASK
) == TYPE_PRODUCT
) {
6746 member
= member
->left
;
6749 if (member
->left
== prev_member
) {
6752 member
= member
->right
;
6754 if (member
== prev_member
) {
6758 internal_error(state
, 0, "prev_member %s not present",
6759 prev_member
->field_ident
->name
);
6764 typedef void (*walk_type_fields_cb_t
)(struct compile_state
*state
, struct type
*type
,
6765 size_t ret_offset
, size_t mem_offset
, void *arg
);
6767 static void walk_type_fields(struct compile_state
*state
,
6768 struct type
*type
, size_t reg_offset
, size_t mem_offset
,
6769 walk_type_fields_cb_t cb
, void *arg
);
6771 static void walk_struct_fields(struct compile_state
*state
,
6772 struct type
*type
, size_t reg_offset
, size_t mem_offset
,
6773 walk_type_fields_cb_t cb
, void *arg
)
6777 if ((type
->type
& TYPE_MASK
) != TYPE_STRUCT
) {
6778 internal_error(state
, 0, "walk_struct_fields only works on structures");
6781 for(i
= 0; i
< type
->elements
; i
++) {
6784 if ((mtype
->type
& TYPE_MASK
) == TYPE_PRODUCT
) {
6785 mtype
= mtype
->left
;
6787 walk_type_fields(state
, mtype
,
6789 field_reg_offset(state
, type
, mtype
->field_ident
),
6791 field_offset(state
, type
, mtype
->field_ident
),
6798 static void walk_type_fields(struct compile_state
*state
,
6799 struct type
*type
, size_t reg_offset
, size_t mem_offset
,
6800 walk_type_fields_cb_t cb
, void *arg
)
6802 switch(type
->type
& TYPE_MASK
) {
6804 walk_struct_fields(state
, type
, reg_offset
, mem_offset
, cb
, arg
);
6814 cb(state
, type
, reg_offset
, mem_offset
, arg
);
6819 internal_error(state
, 0, "walk_type_fields not yet implemented for type");
6823 static void arrays_complete(struct compile_state
*state
, struct type
*type
)
6825 if ((type
->type
& TYPE_MASK
) == TYPE_ARRAY
) {
6826 if (type
->elements
== ELEMENT_COUNT_UNSPECIFIED
) {
6827 error(state
, 0, "array size not specified");
6829 arrays_complete(state
, type
->left
);
6833 static unsigned int get_basic_type(struct type
*type
)
6836 basic
= type
->type
& TYPE_MASK
;
6837 /* Convert enums to ints */
6838 if (basic
== TYPE_ENUM
) {
6841 /* Convert bitfields to standard types */
6842 else if (basic
== TYPE_BITFIELD
) {
6843 if (type
->elements
<= SIZEOF_CHAR
) {
6846 else if (type
->elements
<= SIZEOF_SHORT
) {
6849 else if (type
->elements
<= SIZEOF_INT
) {
6852 else if (type
->elements
<= SIZEOF_LONG
) {
6855 if (!TYPE_SIGNED(type
->left
->type
)) {
6862 static unsigned int do_integral_promotion(unsigned int type
)
6864 if (TYPE_INTEGER(type
) && (TYPE_RANK(type
) < TYPE_RANK(TYPE_INT
))) {
6870 static unsigned int do_arithmetic_conversion(
6871 unsigned int left
, unsigned int right
)
6873 if ((left
== TYPE_LDOUBLE
) || (right
== TYPE_LDOUBLE
)) {
6874 return TYPE_LDOUBLE
;
6876 else if ((left
== TYPE_DOUBLE
) || (right
== TYPE_DOUBLE
)) {
6879 else if ((left
== TYPE_FLOAT
) || (right
== TYPE_FLOAT
)) {
6882 left
= do_integral_promotion(left
);
6883 right
= do_integral_promotion(right
);
6884 /* If both operands have the same size done */
6885 if (left
== right
) {
6888 /* If both operands have the same signedness pick the larger */
6889 else if (!!TYPE_UNSIGNED(left
) == !!TYPE_UNSIGNED(right
)) {
6890 return (TYPE_RANK(left
) >= TYPE_RANK(right
)) ? left
: right
;
6892 /* If the signed type can hold everything use it */
6893 else if (TYPE_SIGNED(left
) && (TYPE_RANK(left
) > TYPE_RANK(right
))) {
6896 else if (TYPE_SIGNED(right
) && (TYPE_RANK(right
) > TYPE_RANK(left
))) {
6899 /* Convert to the unsigned type with the same rank as the signed type */
6900 else if (TYPE_SIGNED(left
)) {
6901 return TYPE_MKUNSIGNED(left
);
6904 return TYPE_MKUNSIGNED(right
);
6908 /* see if two types are the same except for qualifiers */
6909 static int equiv_types(struct type
*left
, struct type
*right
)
6912 /* Error if the basic types do not match */
6913 if ((left
->type
& TYPE_MASK
) != (right
->type
& TYPE_MASK
)) {
6916 type
= left
->type
& TYPE_MASK
;
6917 /* If the basic types match and it is a void type we are done */
6918 if (type
== TYPE_VOID
) {
6921 /* For bitfields we need to compare the sizes */
6922 else if (type
== TYPE_BITFIELD
) {
6923 return (left
->elements
== right
->elements
) &&
6924 (TYPE_SIGNED(left
->left
->type
) == TYPE_SIGNED(right
->left
->type
));
6926 /* if the basic types match and it is an arithmetic type we are done */
6927 else if (TYPE_ARITHMETIC(type
)) {
6930 /* If it is a pointer type recurse and keep testing */
6931 else if (type
== TYPE_POINTER
) {
6932 return equiv_types(left
->left
, right
->left
);
6934 else if (type
== TYPE_ARRAY
) {
6935 return (left
->elements
== right
->elements
) &&
6936 equiv_types(left
->left
, right
->left
);
6938 /* test for struct equality */
6939 else if (type
== TYPE_STRUCT
) {
6940 return left
->type_ident
== right
->type_ident
;
6942 /* test for union equality */
6943 else if (type
== TYPE_UNION
) {
6944 return left
->type_ident
== right
->type_ident
;
6946 /* Test for equivalent functions */
6947 else if (type
== TYPE_FUNCTION
) {
6948 return equiv_types(left
->left
, right
->left
) &&
6949 equiv_types(left
->right
, right
->right
);
6951 /* We only see TYPE_PRODUCT as part of function equivalence matching */
6952 /* We also see TYPE_PRODUCT as part of of tuple equivalence matchin */
6953 else if (type
== TYPE_PRODUCT
) {
6954 return equiv_types(left
->left
, right
->left
) &&
6955 equiv_types(left
->right
, right
->right
);
6957 /* We should see TYPE_OVERLAP when comparing joins */
6958 else if (type
== TYPE_OVERLAP
) {
6959 return equiv_types(left
->left
, right
->left
) &&
6960 equiv_types(left
->right
, right
->right
);
6962 /* Test for equivalence of tuples */
6963 else if (type
== TYPE_TUPLE
) {
6964 return (left
->elements
== right
->elements
) &&
6965 equiv_types(left
->left
, right
->left
);
6967 /* Test for equivalence of joins */
6968 else if (type
== TYPE_JOIN
) {
6969 return (left
->elements
== right
->elements
) &&
6970 equiv_types(left
->left
, right
->left
);
6977 static int equiv_ptrs(struct type
*left
, struct type
*right
)
6979 if (((left
->type
& TYPE_MASK
) != TYPE_POINTER
) ||
6980 ((right
->type
& TYPE_MASK
) != TYPE_POINTER
)) {
6983 return equiv_types(left
->left
, right
->left
);
6986 static struct type
*compatible_types(struct type
*left
, struct type
*right
)
6988 struct type
*result
;
6989 unsigned int type
, qual_type
;
6990 /* Error if the basic types do not match */
6991 if ((left
->type
& TYPE_MASK
) != (right
->type
& TYPE_MASK
)) {
6994 type
= left
->type
& TYPE_MASK
;
6995 qual_type
= (left
->type
& ~STOR_MASK
) | (right
->type
& ~STOR_MASK
);
6997 /* if the basic types match and it is an arithmetic type we are done */
6998 if (TYPE_ARITHMETIC(type
)) {
6999 result
= new_type(qual_type
, 0, 0);
7001 /* If it is a pointer type recurse and keep testing */
7002 else if (type
== TYPE_POINTER
) {
7003 result
= compatible_types(left
->left
, right
->left
);
7005 result
= new_type(qual_type
, result
, 0);
7008 /* test for struct equality */
7009 else if (type
== TYPE_STRUCT
) {
7010 if (left
->type_ident
== right
->type_ident
) {
7014 /* test for union equality */
7015 else if (type
== TYPE_UNION
) {
7016 if (left
->type_ident
== right
->type_ident
) {
7020 /* Test for equivalent functions */
7021 else if (type
== TYPE_FUNCTION
) {
7022 struct type
*lf
, *rf
;
7023 lf
= compatible_types(left
->left
, right
->left
);
7024 rf
= compatible_types(left
->right
, right
->right
);
7026 result
= new_type(qual_type
, lf
, rf
);
7029 /* We only see TYPE_PRODUCT as part of function equivalence matching */
7030 else if (type
== TYPE_PRODUCT
) {
7031 struct type
*lf
, *rf
;
7032 lf
= compatible_types(left
->left
, right
->left
);
7033 rf
= compatible_types(left
->right
, right
->right
);
7035 result
= new_type(qual_type
, lf
, rf
);
7039 /* Nothing else is compatible */
7044 /* See if left is a equivalent to right or right is a union member of left */
7045 static int is_subset_type(struct type
*left
, struct type
*right
)
7047 if (equiv_types(left
, right
)) {
7050 if ((left
->type
& TYPE_MASK
) == TYPE_JOIN
) {
7051 struct type
*member
, *mnext
;
7056 if ((member
->type
& TYPE_MASK
) == TYPE_OVERLAP
) {
7057 mnext
= member
->right
;
7058 member
= member
->left
;
7060 if (is_subset_type( member
, right
)) {
7068 static struct type
*compatible_ptrs(struct type
*left
, struct type
*right
)
7070 struct type
*result
;
7071 if (((left
->type
& TYPE_MASK
) != TYPE_POINTER
) ||
7072 ((right
->type
& TYPE_MASK
) != TYPE_POINTER
)) {
7075 result
= compatible_types(left
->left
, right
->left
);
7077 unsigned int qual_type
;
7078 qual_type
= (left
->type
& ~STOR_MASK
) | (right
->type
& ~STOR_MASK
);
7079 result
= new_type(qual_type
, result
, 0);
7084 static struct triple
*integral_promotion(
7085 struct compile_state
*state
, struct triple
*def
)
7089 /* As all operations are carried out in registers
7090 * the values are converted on load I just convert
7091 * logical type of the operand.
7093 if (TYPE_INTEGER(type
->type
)) {
7094 unsigned int int_type
;
7095 int_type
= type
->type
& ~TYPE_MASK
;
7096 int_type
|= do_integral_promotion(get_basic_type(type
));
7097 if (int_type
!= type
->type
) {
7098 if (def
->op
!= OP_LOAD
) {
7099 def
->type
= new_type(int_type
, 0, 0);
7102 def
= triple(state
, OP_CONVERT
,
7103 new_type(int_type
, 0, 0), def
, 0);
7111 static void arithmetic(struct compile_state
*state
, struct triple
*def
)
7113 if (!TYPE_ARITHMETIC(def
->type
->type
)) {
7114 error(state
, 0, "arithmetic type expexted");
7118 static void ptr_arithmetic(struct compile_state
*state
, struct triple
*def
)
7120 if (!TYPE_PTR(def
->type
->type
) && !TYPE_ARITHMETIC(def
->type
->type
)) {
7121 error(state
, def
, "pointer or arithmetic type expected");
7125 static int is_integral(struct triple
*ins
)
7127 return TYPE_INTEGER(ins
->type
->type
);
7130 static void integral(struct compile_state
*state
, struct triple
*def
)
7132 if (!is_integral(def
)) {
7133 error(state
, 0, "integral type expected");
7138 static void bool(struct compile_state
*state
, struct triple
*def
)
7140 if (!TYPE_ARITHMETIC(def
->type
->type
) &&
7141 ((def
->type
->type
& TYPE_MASK
) != TYPE_POINTER
)) {
7142 error(state
, 0, "arithmetic or pointer type expected");
7146 static int is_signed(struct type
*type
)
7148 if ((type
->type
& TYPE_MASK
) == TYPE_BITFIELD
) {
7151 return !!TYPE_SIGNED(type
->type
);
7153 static int is_compound_type(struct type
*type
)
7156 switch((type
->type
& TYPE_MASK
)) {
7171 /* Is this value located in a register otherwise it must be in memory */
7172 static int is_in_reg(struct compile_state
*state
, struct triple
*def
)
7175 if (def
->op
== OP_ADECL
) {
7178 else if ((def
->op
== OP_SDECL
) || (def
->op
== OP_DEREF
)) {
7181 else if (triple_is_part(state
, def
)) {
7182 in_reg
= is_in_reg(state
, MISC(def
, 0));
7185 internal_error(state
, def
, "unknown expr storage location");
7191 /* Is this an auto or static variable location? Something that can
7192 * be assigned to. Otherwise it must must be a pure value, a temporary.
7194 static int is_lvalue(struct compile_state
*state
, struct triple
*def
)
7201 if ((def
->op
== OP_ADECL
) ||
7202 (def
->op
== OP_SDECL
) ||
7203 (def
->op
== OP_DEREF
) ||
7204 (def
->op
== OP_BLOBCONST
) ||
7205 (def
->op
== OP_LIST
)) {
7208 else if (triple_is_part(state
, def
)) {
7209 ret
= is_lvalue(state
, MISC(def
, 0));
7214 static void clvalue(struct compile_state
*state
, struct triple
*def
)
7217 internal_error(state
, def
, "nothing where lvalue expected?");
7219 if (!is_lvalue(state
, def
)) {
7220 error(state
, def
, "lvalue expected");
7223 static void lvalue(struct compile_state
*state
, struct triple
*def
)
7225 clvalue(state
, def
);
7226 if (def
->type
->type
& QUAL_CONST
) {
7227 error(state
, def
, "modifable lvalue expected");
7231 static int is_pointer(struct triple
*def
)
7233 return (def
->type
->type
& TYPE_MASK
) == TYPE_POINTER
;
7236 static void pointer(struct compile_state
*state
, struct triple
*def
)
7238 if (!is_pointer(def
)) {
7239 error(state
, def
, "pointer expected");
7243 static struct triple
*int_const(
7244 struct compile_state
*state
, struct type
*type
, ulong_t value
)
7246 struct triple
*result
;
7247 switch(type
->type
& TYPE_MASK
) {
7249 case TYPE_INT
: case TYPE_UINT
:
7250 case TYPE_LONG
: case TYPE_ULONG
:
7253 internal_error(state
, 0, "constant for unknown type");
7255 result
= triple(state
, OP_INTCONST
, type
, 0, 0);
7256 result
->u
.cval
= value
;
7261 static struct triple
*read_expr(struct compile_state
*state
, struct triple
*def
);
7263 static struct triple
*do_mk_addr_expr(struct compile_state
*state
,
7264 struct triple
*expr
, struct type
*type
, ulong_t offset
)
7266 struct triple
*result
;
7267 struct type
*ptr_type
;
7268 clvalue(state
, expr
);
7270 ptr_type
= new_type(TYPE_POINTER
| (type
->type
& QUAL_MASK
), type
, 0);
7274 if (expr
->op
== OP_ADECL
) {
7275 error(state
, expr
, "address of auto variables not supported");
7277 else if (expr
->op
== OP_SDECL
) {
7278 result
= triple(state
, OP_ADDRCONST
, ptr_type
, 0, 0);
7279 MISC(result
, 0) = expr
;
7280 result
->u
.cval
= offset
;
7282 else if (expr
->op
== OP_DEREF
) {
7283 result
= triple(state
, OP_ADD
, ptr_type
,
7285 int_const(state
, &ulong_type
, offset
));
7287 else if (expr
->op
== OP_BLOBCONST
) {
7289 internal_error(state
, expr
, "not yet implemented");
7291 else if (expr
->op
== OP_LIST
) {
7292 error(state
, 0, "Function addresses not supported");
7294 else if (triple_is_part(state
, expr
)) {
7295 struct triple
*part
;
7297 expr
= MISC(expr
, 0);
7298 if (part
->op
== OP_DOT
) {
7299 offset
+= bits_to_bytes(
7300 field_offset(state
, expr
->type
, part
->u
.field
));
7302 else if (part
->op
== OP_INDEX
) {
7303 offset
+= bits_to_bytes(
7304 index_offset(state
, expr
->type
, part
->u
.cval
));
7307 internal_error(state
, part
, "unhandled part type");
7309 result
= do_mk_addr_expr(state
, expr
, type
, offset
);
7312 internal_error(state
, expr
, "cannot take address of expression");
7317 static struct triple
*mk_addr_expr(
7318 struct compile_state
*state
, struct triple
*expr
, ulong_t offset
)
7320 return do_mk_addr_expr(state
, expr
, expr
->type
, offset
);
7323 static struct triple
*mk_deref_expr(
7324 struct compile_state
*state
, struct triple
*expr
)
7326 struct type
*base_type
;
7327 pointer(state
, expr
);
7328 base_type
= expr
->type
->left
;
7329 return triple(state
, OP_DEREF
, base_type
, expr
, 0);
7332 /* lvalue conversions always apply except when certain operators
7333 * are applied. So I apply apply it when I know no more
7334 * operators will be applied.
7336 static struct triple
*lvalue_conversion(struct compile_state
*state
, struct triple
*def
)
7338 /* Tranform an array to a pointer to the first element */
7339 if ((def
->type
->type
& TYPE_MASK
) == TYPE_ARRAY
) {
7342 TYPE_POINTER
| (def
->type
->type
& QUAL_MASK
),
7343 def
->type
->left
, 0);
7344 if ((def
->op
== OP_SDECL
) || IS_CONST_OP(def
->op
)) {
7345 struct triple
*addrconst
;
7346 if ((def
->op
!= OP_SDECL
) && (def
->op
!= OP_BLOBCONST
)) {
7347 internal_error(state
, def
, "bad array constant");
7349 addrconst
= triple(state
, OP_ADDRCONST
, type
, 0, 0);
7350 MISC(addrconst
, 0) = def
;
7354 def
= triple(state
, OP_CONVERT
, type
, def
, 0);
7357 /* Transform a function to a pointer to it */
7358 else if ((def
->type
->type
& TYPE_MASK
) == TYPE_FUNCTION
) {
7359 def
= mk_addr_expr(state
, def
, 0);
7364 static struct triple
*deref_field(
7365 struct compile_state
*state
, struct triple
*expr
, struct hash_entry
*field
)
7367 struct triple
*result
;
7368 struct type
*type
, *member
;
7371 internal_error(state
, 0, "No field passed to deref_field");
7375 if (((type
->type
& TYPE_MASK
) != TYPE_STRUCT
) &&
7376 ((type
->type
& TYPE_MASK
) != TYPE_UNION
)) {
7377 error(state
, 0, "request for member %s in something not a struct or union",
7380 member
= field_type(state
, type
, field
);
7381 if ((type
->type
& STOR_MASK
) == STOR_PERM
) {
7382 /* Do the pointer arithmetic to get a deref the field */
7383 offset
= bits_to_bytes(field_offset(state
, type
, field
));
7384 result
= do_mk_addr_expr(state
, expr
, member
, offset
);
7385 result
= mk_deref_expr(state
, result
);
7388 /* Find the variable for the field I want. */
7389 result
= triple(state
, OP_DOT
, member
, expr
, 0);
7390 result
->u
.field
= field
;
7395 static struct triple
*deref_index(
7396 struct compile_state
*state
, struct triple
*expr
, size_t index
)
7398 struct triple
*result
;
7399 struct type
*type
, *member
;
7404 member
= index_type(state
, type
, index
);
7406 if ((type
->type
& STOR_MASK
) == STOR_PERM
) {
7407 offset
= bits_to_bytes(index_offset(state
, type
, index
));
7408 result
= do_mk_addr_expr(state
, expr
, member
, offset
);
7409 result
= mk_deref_expr(state
, result
);
7412 result
= triple(state
, OP_INDEX
, member
, expr
, 0);
7413 result
->u
.cval
= index
;
7418 static struct triple
*read_expr(struct compile_state
*state
, struct triple
*def
)
7424 #if DEBUG_ROMCC_WARNINGS
7425 #warning "CHECK_ME is this the only place I need to do lvalue conversions?"
7427 /* Transform lvalues into something we can read */
7428 def
= lvalue_conversion(state
, def
);
7429 if (!is_lvalue(state
, def
)) {
7432 if (is_in_reg(state
, def
)) {
7435 if (def
->op
== OP_SDECL
) {
7436 def
= mk_addr_expr(state
, def
, 0);
7437 def
= mk_deref_expr(state
, def
);
7441 def
= triple(state
, op
, def
->type
, def
, 0);
7442 if (def
->type
->type
& QUAL_VOLATILE
) {
7443 def
->id
|= TRIPLE_FLAG_VOLATILE
;
7448 int is_write_compatible(struct compile_state
*state
,
7449 struct type
*dest
, struct type
*rval
)
7452 /* Both operands have arithmetic type */
7453 if (TYPE_ARITHMETIC(dest
->type
) && TYPE_ARITHMETIC(rval
->type
)) {
7456 /* One operand is a pointer and the other is a pointer to void */
7457 else if (((dest
->type
& TYPE_MASK
) == TYPE_POINTER
) &&
7458 ((rval
->type
& TYPE_MASK
) == TYPE_POINTER
) &&
7459 (((dest
->left
->type
& TYPE_MASK
) == TYPE_VOID
) ||
7460 ((rval
->left
->type
& TYPE_MASK
) == TYPE_VOID
))) {
7463 /* If both types are the same without qualifiers we are good */
7464 else if (equiv_ptrs(dest
, rval
)) {
7467 /* test for struct/union equality */
7468 else if (equiv_types(dest
, rval
)) {
7474 static void write_compatible(struct compile_state
*state
,
7475 struct type
*dest
, struct type
*rval
)
7477 if (!is_write_compatible(state
, dest
, rval
)) {
7478 FILE *fp
= state
->errout
;
7479 fprintf(fp
, "dest: ");
7481 fprintf(fp
,"\nrval: ");
7484 error(state
, 0, "Incompatible types in assignment");
7488 static int is_init_compatible(struct compile_state
*state
,
7489 struct type
*dest
, struct type
*rval
)
7492 if (is_write_compatible(state
, dest
, rval
)) {
7495 else if (equiv_types(dest
, rval
)) {
7501 static struct triple
*write_expr(
7502 struct compile_state
*state
, struct triple
*dest
, struct triple
*rval
)
7508 internal_error(state
, 0, "missing rval");
7511 if (rval
->op
== OP_LIST
) {
7512 internal_error(state
, 0, "expression of type OP_LIST?");
7514 if (!is_lvalue(state
, dest
)) {
7515 internal_error(state
, 0, "writing to a non lvalue?");
7517 if (dest
->type
->type
& QUAL_CONST
) {
7518 internal_error(state
, 0, "modifable lvalue expexted");
7521 write_compatible(state
, dest
->type
, rval
->type
);
7522 if (!equiv_types(dest
->type
, rval
->type
)) {
7523 rval
= triple(state
, OP_CONVERT
, dest
->type
, rval
, 0);
7526 /* Now figure out which assignment operator to use */
7527 if (is_in_reg(state
, dest
)) {
7528 def
= triple(state
, OP_WRITE
, dest
->type
, rval
, dest
);
7529 if (MISC(def
, 0) != dest
) {
7530 internal_error(state
, def
, "huh?");
7532 if (RHS(def
, 0) != rval
) {
7533 internal_error(state
, def
, "huh?");
7536 def
= triple(state
, OP_STORE
, dest
->type
, dest
, rval
);
7538 if (def
->type
->type
& QUAL_VOLATILE
) {
7539 def
->id
|= TRIPLE_FLAG_VOLATILE
;
7544 static struct triple
*init_expr(
7545 struct compile_state
*state
, struct triple
*dest
, struct triple
*rval
)
7551 internal_error(state
, 0, "missing rval");
7553 if ((dest
->type
->type
& STOR_MASK
) != STOR_PERM
) {
7554 rval
= read_expr(state
, rval
);
7555 def
= write_expr(state
, dest
, rval
);
7558 /* Fill in the array size if necessary */
7559 if (((dest
->type
->type
& TYPE_MASK
) == TYPE_ARRAY
) &&
7560 ((rval
->type
->type
& TYPE_MASK
) == TYPE_ARRAY
)) {
7561 if (dest
->type
->elements
== ELEMENT_COUNT_UNSPECIFIED
) {
7562 dest
->type
->elements
= rval
->type
->elements
;
7565 if (!equiv_types(dest
->type
, rval
->type
)) {
7566 error(state
, 0, "Incompatible types in inializer");
7568 MISC(dest
, 0) = rval
;
7569 insert_triple(state
, dest
, rval
);
7570 rval
->id
|= TRIPLE_FLAG_FLATTENED
;
7571 use_triple(MISC(dest
, 0), dest
);
7576 struct type
*arithmetic_result(
7577 struct compile_state
*state
, struct triple
*left
, struct triple
*right
)
7580 /* Sanity checks to ensure I am working with arithmetic types */
7581 arithmetic(state
, left
);
7582 arithmetic(state
, right
);
7584 do_arithmetic_conversion(
7585 get_basic_type(left
->type
),
7586 get_basic_type(right
->type
)),
7591 struct type
*ptr_arithmetic_result(
7592 struct compile_state
*state
, struct triple
*left
, struct triple
*right
)
7595 /* Sanity checks to ensure I am working with the proper types */
7596 ptr_arithmetic(state
, left
);
7597 arithmetic(state
, right
);
7598 if (TYPE_ARITHMETIC(left
->type
->type
) &&
7599 TYPE_ARITHMETIC(right
->type
->type
)) {
7600 type
= arithmetic_result(state
, left
, right
);
7602 else if (TYPE_PTR(left
->type
->type
)) {
7606 internal_error(state
, 0, "huh?");
7612 /* boolean helper function */
7614 static struct triple
*ltrue_expr(struct compile_state
*state
,
7615 struct triple
*expr
)
7618 case OP_LTRUE
: case OP_LFALSE
: case OP_EQ
: case OP_NOTEQ
:
7619 case OP_SLESS
: case OP_ULESS
: case OP_SMORE
: case OP_UMORE
:
7620 case OP_SLESSEQ
: case OP_ULESSEQ
: case OP_SMOREEQ
: case OP_UMOREEQ
:
7621 /* If the expression is already boolean do nothing */
7624 expr
= triple(state
, OP_LTRUE
, &int_type
, expr
, 0);
7630 static struct triple
*lfalse_expr(struct compile_state
*state
,
7631 struct triple
*expr
)
7633 return triple(state
, OP_LFALSE
, &int_type
, expr
, 0);
7636 static struct triple
*mkland_expr(
7637 struct compile_state
*state
,
7638 struct triple
*left
, struct triple
*right
)
7640 struct triple
*def
, *val
, *var
, *jmp
, *mid
, *end
;
7641 struct triple
*lstore
, *rstore
;
7643 /* Generate some intermediate triples */
7645 var
= variable(state
, &int_type
);
7647 /* Store the left hand side value */
7648 lstore
= write_expr(state
, var
, left
);
7650 /* Jump if the value is false */
7651 jmp
= branch(state
, end
,
7652 lfalse_expr(state
, read_expr(state
, var
)));
7655 /* Store the right hand side value */
7656 rstore
= write_expr(state
, var
, right
);
7658 /* An expression for the computed value */
7659 val
= read_expr(state
, var
);
7661 /* Generate the prog for a logical and */
7662 def
= mkprog(state
, var
, lstore
, jmp
, mid
, rstore
, end
, val
, 0UL);
7667 static struct triple
*mklor_expr(
7668 struct compile_state
*state
,
7669 struct triple
*left
, struct triple
*right
)
7671 struct triple
*def
, *val
, *var
, *jmp
, *mid
, *end
;
7673 /* Generate some intermediate triples */
7675 var
= variable(state
, &int_type
);
7677 /* Store the left hand side value */
7678 left
= write_expr(state
, var
, left
);
7680 /* Jump if the value is true */
7681 jmp
= branch(state
, end
, read_expr(state
, var
));
7684 /* Store the right hand side value */
7685 right
= write_expr(state
, var
, right
);
7687 /* An expression for the computed value*/
7688 val
= read_expr(state
, var
);
7690 /* Generate the prog for a logical or */
7691 def
= mkprog(state
, var
, left
, jmp
, mid
, right
, end
, val
, 0UL);
7696 static struct triple
*mkcond_expr(
7697 struct compile_state
*state
,
7698 struct triple
*test
, struct triple
*left
, struct triple
*right
)
7700 struct triple
*def
, *val
, *var
, *jmp1
, *jmp2
, *top
, *mid
, *end
;
7701 struct type
*result_type
;
7702 unsigned int left_type
, right_type
;
7704 left_type
= left
->type
->type
;
7705 right_type
= right
->type
->type
;
7707 /* Both operands have arithmetic type */
7708 if (TYPE_ARITHMETIC(left_type
) && TYPE_ARITHMETIC(right_type
)) {
7709 result_type
= arithmetic_result(state
, left
, right
);
7711 /* Both operands have void type */
7712 else if (((left_type
& TYPE_MASK
) == TYPE_VOID
) &&
7713 ((right_type
& TYPE_MASK
) == TYPE_VOID
)) {
7714 result_type
= &void_type
;
7716 /* pointers to the same type... */
7717 else if ((result_type
= compatible_ptrs(left
->type
, right
->type
))) {
7720 /* Both operands are pointers and left is a pointer to void */
7721 else if (((left_type
& TYPE_MASK
) == TYPE_POINTER
) &&
7722 ((right_type
& TYPE_MASK
) == TYPE_POINTER
) &&
7723 ((left
->type
->left
->type
& TYPE_MASK
) == TYPE_VOID
)) {
7724 result_type
= right
->type
;
7726 /* Both operands are pointers and right is a pointer to void */
7727 else if (((left_type
& TYPE_MASK
) == TYPE_POINTER
) &&
7728 ((right_type
& TYPE_MASK
) == TYPE_POINTER
) &&
7729 ((right
->type
->left
->type
& TYPE_MASK
) == TYPE_VOID
)) {
7730 result_type
= left
->type
;
7733 error(state
, 0, "Incompatible types in conditional expression");
7735 /* Generate some intermediate triples */
7738 var
= variable(state
, result_type
);
7740 /* Branch if the test is false */
7741 jmp1
= branch(state
, mid
, lfalse_expr(state
, read_expr(state
, test
)));
7744 /* Store the left hand side value */
7745 left
= write_expr(state
, var
, left
);
7747 /* Branch to the end */
7748 jmp2
= branch(state
, end
, 0);
7750 /* Store the right hand side value */
7751 right
= write_expr(state
, var
, right
);
7753 /* An expression for the computed value */
7754 val
= read_expr(state
, var
);
7756 /* Generate the prog for a conditional expression */
7757 def
= mkprog(state
, var
, jmp1
, top
, left
, jmp2
, mid
, right
, end
, val
, 0UL);
7763 static int expr_depth(struct compile_state
*state
, struct triple
*ins
)
7765 #if DEBUG_ROMCC_WARNINGS
7766 #warning "FIXME move optimal ordering of subexpressions into the optimizer"
7770 if (!ins
|| (ins
->id
& TRIPLE_FLAG_FLATTENED
)) {
7773 else if (ins
->op
== OP_DEREF
) {
7774 count
= expr_depth(state
, RHS(ins
, 0)) - 1;
7776 else if (ins
->op
== OP_VAL
) {
7777 count
= expr_depth(state
, RHS(ins
, 0)) - 1;
7779 else if (ins
->op
== OP_FCALL
) {
7780 /* Don't figure the depth of a call just guess it is huge */
7784 struct triple
**expr
;
7785 expr
= triple_rhs(state
, ins
, 0);
7786 for(;expr
; expr
= triple_rhs(state
, ins
, expr
)) {
7789 depth
= expr_depth(state
, *expr
);
7790 if (depth
> count
) {
7799 static struct triple
*flatten_generic(
7800 struct compile_state
*state
, struct triple
*first
, struct triple
*ptr
,
7805 struct triple
**ins
;
7808 /* Only operations with just a rhs and a lhs should come here */
7811 if (TRIPLE_SIZE(ptr
) != lhs
+ rhs
+ ignored
) {
7812 internal_error(state
, ptr
, "unexpected args for: %d %s",
7813 ptr
->op
, tops(ptr
->op
));
7815 /* Find the depth of the rhs elements */
7816 for(i
= 0; i
< rhs
; i
++) {
7817 vector
[i
].ins
= &RHS(ptr
, i
);
7818 vector
[i
].depth
= expr_depth(state
, *vector
[i
].ins
);
7820 /* Selection sort the rhs */
7821 for(i
= 0; i
< rhs
; i
++) {
7823 for(j
= i
+ 1; j
< rhs
; j
++ ) {
7824 if (vector
[j
].depth
> vector
[max
].depth
) {
7829 struct rhs_vector tmp
;
7831 vector
[i
] = vector
[max
];
7835 /* Now flatten the rhs elements */
7836 for(i
= 0; i
< rhs
; i
++) {
7837 *vector
[i
].ins
= flatten(state
, first
, *vector
[i
].ins
);
7838 use_triple(*vector
[i
].ins
, ptr
);
7841 insert_triple(state
, first
, ptr
);
7842 ptr
->id
|= TRIPLE_FLAG_FLATTENED
;
7843 ptr
->id
&= ~TRIPLE_FLAG_LOCAL
;
7845 /* Now flatten the lhs elements */
7846 for(i
= 0; i
< lhs
; i
++) {
7847 struct triple
**ins
= &LHS(ptr
, i
);
7848 *ins
= flatten(state
, first
, *ins
);
7849 use_triple(*ins
, ptr
);
7855 static struct triple
*flatten_prog(
7856 struct compile_state
*state
, struct triple
*first
, struct triple
*ptr
)
7858 struct triple
*head
, *body
, *val
;
7863 release_triple(state
, head
);
7864 release_triple(state
, ptr
);
7866 body
->prev
= first
->prev
;
7867 body
->prev
->next
= body
;
7868 val
->next
->prev
= val
;
7870 if (triple_is_cbranch(state
, body
->prev
) ||
7871 triple_is_call(state
, body
->prev
)) {
7872 unuse_triple(first
, body
->prev
);
7873 use_triple(body
, body
->prev
);
7876 if (!(val
->id
& TRIPLE_FLAG_FLATTENED
)) {
7877 internal_error(state
, val
, "val not flattened?");
7884 static struct triple
*flatten_part(
7885 struct compile_state
*state
, struct triple
*first
, struct triple
*ptr
)
7887 if (!triple_is_part(state
, ptr
)) {
7888 internal_error(state
, ptr
, "not a part");
7890 if (ptr
->rhs
|| ptr
->lhs
|| ptr
->targ
|| (ptr
->misc
!= 1)) {
7891 internal_error(state
, ptr
, "unexpected args for: %d %s",
7892 ptr
->op
, tops(ptr
->op
));
7894 MISC(ptr
, 0) = flatten(state
, first
, MISC(ptr
, 0));
7895 use_triple(MISC(ptr
, 0), ptr
);
7896 return flatten_generic(state
, first
, ptr
, 1);
7899 static struct triple
*flatten(
7900 struct compile_state
*state
, struct triple
*first
, struct triple
*ptr
)
7902 struct triple
*orig_ptr
;
7907 /* Only flatten triples once */
7908 if (ptr
->id
& TRIPLE_FLAG_FLATTENED
) {
7913 RHS(ptr
, 0) = flatten(state
, first
, RHS(ptr
, 0));
7914 return MISC(ptr
, 0);
7917 ptr
= flatten_prog(state
, first
, ptr
);
7920 ptr
= flatten_generic(state
, first
, ptr
, 1);
7921 insert_triple(state
, first
, ptr
);
7922 ptr
->id
|= TRIPLE_FLAG_FLATTENED
;
7923 ptr
->id
&= ~TRIPLE_FLAG_LOCAL
;
7924 if (ptr
->next
!= ptr
) {
7925 use_triple(ptr
->next
, ptr
);
7930 RHS(ptr
, 0) = flatten(state
, first
, RHS(ptr
, 0));
7931 use_triple(RHS(ptr
, 0), ptr
);
7934 ptr
= flatten_generic(state
, first
, ptr
, 1);
7935 MISC(ptr
, 0) = flatten(state
, first
, MISC(ptr
, 0));
7936 use_triple(MISC(ptr
, 0), ptr
);
7939 use_triple(TARG(ptr
, 0), ptr
);
7942 RHS(ptr
, 0) = flatten(state
, first
, RHS(ptr
, 0));
7943 use_triple(RHS(ptr
, 0), ptr
);
7944 use_triple(TARG(ptr
, 0), ptr
);
7945 insert_triple(state
, first
, ptr
);
7946 ptr
->id
|= TRIPLE_FLAG_FLATTENED
;
7947 ptr
->id
&= ~TRIPLE_FLAG_LOCAL
;
7948 if (ptr
->next
!= ptr
) {
7949 use_triple(ptr
->next
, ptr
);
7953 MISC(ptr
, 0) = flatten(state
, first
, MISC(ptr
, 0));
7954 use_triple(MISC(ptr
, 0), ptr
);
7955 use_triple(TARG(ptr
, 0), ptr
);
7956 insert_triple(state
, first
, ptr
);
7957 ptr
->id
|= TRIPLE_FLAG_FLATTENED
;
7958 ptr
->id
&= ~TRIPLE_FLAG_LOCAL
;
7959 if (ptr
->next
!= ptr
) {
7960 use_triple(ptr
->next
, ptr
);
7964 RHS(ptr
, 0) = flatten(state
, first
, RHS(ptr
, 0));
7965 use_triple(RHS(ptr
, 0), ptr
);
7968 insert_triple(state
, state
->global_pool
, ptr
);
7969 ptr
->id
|= TRIPLE_FLAG_FLATTENED
;
7970 ptr
->id
&= ~TRIPLE_FLAG_LOCAL
;
7971 ptr
= triple(state
, OP_SDECL
, ptr
->type
, ptr
, 0);
7972 use_triple(MISC(ptr
, 0), ptr
);
7975 /* Since OP_DEREF is just a marker delete it when I flatten it */
7977 RHS(orig_ptr
, 0) = 0;
7978 free_triple(state
, orig_ptr
);
7981 if (RHS(ptr
, 0)->op
== OP_DEREF
) {
7982 struct triple
*base
, *left
;
7984 base
= MISC(ptr
, 0);
7985 offset
= bits_to_bytes(field_offset(state
, base
->type
, ptr
->u
.field
));
7986 left
= RHS(base
, 0);
7987 ptr
= triple(state
, OP_ADD
, left
->type
,
7988 read_expr(state
, left
),
7989 int_const(state
, &ulong_type
, offset
));
7990 free_triple(state
, base
);
7993 ptr
= flatten_part(state
, first
, ptr
);
7997 if (RHS(ptr
, 0)->op
== OP_DEREF
) {
7998 struct triple
*base
, *left
;
8000 base
= MISC(ptr
, 0);
8001 offset
= bits_to_bytes(index_offset(state
, base
->type
, ptr
->u
.cval
));
8002 left
= RHS(base
, 0);
8003 ptr
= triple(state
, OP_ADD
, left
->type
,
8004 read_expr(state
, left
),
8005 int_const(state
, &long_type
, offset
));
8006 free_triple(state
, base
);
8009 ptr
= flatten_part(state
, first
, ptr
);
8013 ptr
= flatten_part(state
, first
, ptr
);
8014 use_triple(ptr
, MISC(ptr
, 0));
8017 MISC(ptr
, 0) = flatten(state
, first
, MISC(ptr
, 0));
8018 use_triple(MISC(ptr
, 0), ptr
);
8021 first
= state
->global_pool
;
8022 MISC(ptr
, 0) = flatten(state
, first
, MISC(ptr
, 0));
8023 use_triple(MISC(ptr
, 0), ptr
);
8024 insert_triple(state
, first
, ptr
);
8025 ptr
->id
|= TRIPLE_FLAG_FLATTENED
;
8026 ptr
->id
&= ~TRIPLE_FLAG_LOCAL
;
8029 ptr
= flatten_generic(state
, first
, ptr
, 0);
8032 /* Flatten the easy cases we don't override */
8033 ptr
= flatten_generic(state
, first
, ptr
, 0);
8036 } while(ptr
&& (ptr
!= orig_ptr
));
8037 if (ptr
&& !(ptr
->id
& TRIPLE_FLAG_FLATTENED
)) {
8038 insert_triple(state
, first
, ptr
);
8039 ptr
->id
|= TRIPLE_FLAG_FLATTENED
;
8040 ptr
->id
&= ~TRIPLE_FLAG_LOCAL
;
8045 static void release_expr(struct compile_state
*state
, struct triple
*expr
)
8047 struct triple
*head
;
8048 head
= label(state
);
8049 flatten(state
, head
, expr
);
8050 while(head
->next
!= head
) {
8051 release_triple(state
, head
->next
);
8053 free_triple(state
, head
);
8056 static int replace_rhs_use(struct compile_state
*state
,
8057 struct triple
*orig
, struct triple
*new, struct triple
*use
)
8059 struct triple
**expr
;
8062 expr
= triple_rhs(state
, use
, 0);
8063 for(;expr
; expr
= triple_rhs(state
, use
, expr
)) {
8064 if (*expr
== orig
) {
8070 unuse_triple(orig
, use
);
8071 use_triple(new, use
);
8076 static int replace_lhs_use(struct compile_state
*state
,
8077 struct triple
*orig
, struct triple
*new, struct triple
*use
)
8079 struct triple
**expr
;
8082 expr
= triple_lhs(state
, use
, 0);
8083 for(;expr
; expr
= triple_lhs(state
, use
, expr
)) {
8084 if (*expr
== orig
) {
8090 unuse_triple(orig
, use
);
8091 use_triple(new, use
);
8096 static int replace_misc_use(struct compile_state
*state
,
8097 struct triple
*orig
, struct triple
*new, struct triple
*use
)
8099 struct triple
**expr
;
8102 expr
= triple_misc(state
, use
, 0);
8103 for(;expr
; expr
= triple_misc(state
, use
, expr
)) {
8104 if (*expr
== orig
) {
8110 unuse_triple(orig
, use
);
8111 use_triple(new, use
);
8116 static int replace_targ_use(struct compile_state
*state
,
8117 struct triple
*orig
, struct triple
*new, struct triple
*use
)
8119 struct triple
**expr
;
8122 expr
= triple_targ(state
, use
, 0);
8123 for(;expr
; expr
= triple_targ(state
, use
, expr
)) {
8124 if (*expr
== orig
) {
8130 unuse_triple(orig
, use
);
8131 use_triple(new, use
);
8136 static void replace_use(struct compile_state
*state
,
8137 struct triple
*orig
, struct triple
*new, struct triple
*use
)
8141 found
|= replace_rhs_use(state
, orig
, new, use
);
8142 found
|= replace_lhs_use(state
, orig
, new, use
);
8143 found
|= replace_misc_use(state
, orig
, new, use
);
8144 found
|= replace_targ_use(state
, orig
, new, use
);
8146 internal_error(state
, use
, "use without use");
8150 static void propogate_use(struct compile_state
*state
,
8151 struct triple
*orig
, struct triple
*new)
8153 struct triple_set
*user
, *next
;
8154 for(user
= orig
->use
; user
; user
= next
) {
8155 /* Careful replace_use modifies the use chain and
8156 * removes use. So we must get a copy of the next
8160 replace_use(state
, orig
, new, user
->member
);
8163 internal_error(state
, orig
, "used after propogate_use");
8169 * ===========================
8172 static struct triple
*mk_cast_expr(
8173 struct compile_state
*state
, struct type
*type
, struct triple
*expr
)
8176 def
= read_expr(state
, expr
);
8177 def
= triple(state
, OP_CONVERT
, type
, def
, 0);
8181 static struct triple
*mk_add_expr(
8182 struct compile_state
*state
, struct triple
*left
, struct triple
*right
)
8184 struct type
*result_type
;
8185 /* Put pointer operands on the left */
8186 if (is_pointer(right
)) {
8192 left
= read_expr(state
, left
);
8193 right
= read_expr(state
, right
);
8194 result_type
= ptr_arithmetic_result(state
, left
, right
);
8195 if (is_pointer(left
)) {
8196 struct type
*ptr_math
;
8198 if (is_signed(right
->type
)) {
8199 ptr_math
= &long_type
;
8202 ptr_math
= &ulong_type
;
8205 if (!equiv_types(right
->type
, ptr_math
)) {
8206 right
= mk_cast_expr(state
, ptr_math
, right
);
8208 right
= triple(state
, op
, ptr_math
, right
,
8209 int_const(state
, ptr_math
,
8210 size_of_in_bytes(state
, left
->type
->left
)));
8212 return triple(state
, OP_ADD
, result_type
, left
, right
);
8215 static struct triple
*mk_sub_expr(
8216 struct compile_state
*state
, struct triple
*left
, struct triple
*right
)
8218 struct type
*result_type
;
8219 result_type
= ptr_arithmetic_result(state
, left
, right
);
8220 left
= read_expr(state
, left
);
8221 right
= read_expr(state
, right
);
8222 if (is_pointer(left
)) {
8223 struct type
*ptr_math
;
8225 if (is_signed(right
->type
)) {
8226 ptr_math
= &long_type
;
8229 ptr_math
= &ulong_type
;
8232 if (!equiv_types(right
->type
, ptr_math
)) {
8233 right
= mk_cast_expr(state
, ptr_math
, right
);
8235 right
= triple(state
, op
, ptr_math
, right
,
8236 int_const(state
, ptr_math
,
8237 size_of_in_bytes(state
, left
->type
->left
)));
8239 return triple(state
, OP_SUB
, result_type
, left
, right
);
8242 static struct triple
*mk_pre_inc_expr(
8243 struct compile_state
*state
, struct triple
*def
)
8247 val
= mk_add_expr(state
, def
, int_const(state
, &int_type
, 1));
8248 return triple(state
, OP_VAL
, def
->type
,
8249 write_expr(state
, def
, val
),
8253 static struct triple
*mk_pre_dec_expr(
8254 struct compile_state
*state
, struct triple
*def
)
8258 val
= mk_sub_expr(state
, def
, int_const(state
, &int_type
, 1));
8259 return triple(state
, OP_VAL
, def
->type
,
8260 write_expr(state
, def
, val
),
8264 static struct triple
*mk_post_inc_expr(
8265 struct compile_state
*state
, struct triple
*def
)
8269 val
= read_expr(state
, def
);
8270 return triple(state
, OP_VAL
, def
->type
,
8271 write_expr(state
, def
,
8272 mk_add_expr(state
, val
, int_const(state
, &int_type
, 1)))
8276 static struct triple
*mk_post_dec_expr(
8277 struct compile_state
*state
, struct triple
*def
)
8281 val
= read_expr(state
, def
);
8282 return triple(state
, OP_VAL
, def
->type
,
8283 write_expr(state
, def
,
8284 mk_sub_expr(state
, val
, int_const(state
, &int_type
, 1)))
8288 static struct triple
*mk_subscript_expr(
8289 struct compile_state
*state
, struct triple
*left
, struct triple
*right
)
8291 left
= read_expr(state
, left
);
8292 right
= read_expr(state
, right
);
8293 if (!is_pointer(left
) && !is_pointer(right
)) {
8294 error(state
, left
, "subscripted value is not a pointer");
8296 return mk_deref_expr(state
, mk_add_expr(state
, left
, right
));
8301 * Compile time evaluation
8302 * ===========================
8304 static int is_const(struct triple
*ins
)
8306 return IS_CONST_OP(ins
->op
);
8309 static int is_simple_const(struct triple
*ins
)
8311 /* Is this a constant that u.cval has the value.
8312 * Or equivalently is this a constant that read_const
8314 * So far only OP_INTCONST qualifies.
8316 return (ins
->op
== OP_INTCONST
);
8319 static int constants_equal(struct compile_state
*state
,
8320 struct triple
*left
, struct triple
*right
)
8323 if ((left
->op
== OP_UNKNOWNVAL
) || (right
->op
== OP_UNKNOWNVAL
)) {
8326 else if (!is_const(left
) || !is_const(right
)) {
8329 else if (left
->op
!= right
->op
) {
8332 else if (!equiv_types(left
->type
, right
->type
)) {
8339 if (left
->u
.cval
== right
->u
.cval
) {
8345 size_t lsize
, rsize
, bytes
;
8346 lsize
= size_of(state
, left
->type
);
8347 rsize
= size_of(state
, right
->type
);
8348 if (lsize
!= rsize
) {
8351 bytes
= bits_to_bytes(lsize
);
8352 if (memcmp(left
->u
.blob
, right
->u
.blob
, bytes
) == 0) {
8358 if ((MISC(left
, 0) == MISC(right
, 0)) &&
8359 (left
->u
.cval
== right
->u
.cval
)) {
8364 internal_error(state
, left
, "uknown constant type");
8371 static int is_zero(struct triple
*ins
)
8373 return is_simple_const(ins
) && (ins
->u
.cval
== 0);
8376 static int is_one(struct triple
*ins
)
8378 return is_simple_const(ins
) && (ins
->u
.cval
== 1);
8381 #if DEBUG_ROMCC_WARNING
8382 static long_t
bit_count(ulong_t value
)
8387 for(i
= (sizeof(ulong_t
)*8) -1; i
>= 0; i
--) {
8400 static long_t
bsr(ulong_t value
)
8403 for(i
= (sizeof(ulong_t
)*8) -1; i
>= 0; i
--) {
8414 static long_t
bsf(ulong_t value
)
8417 for(i
= 0; i
< (sizeof(ulong_t
)*8); i
++) {
8428 static long_t
ilog2(ulong_t value
)
8433 static long_t
tlog2(struct triple
*ins
)
8435 return ilog2(ins
->u
.cval
);
8438 static int is_pow2(struct triple
*ins
)
8440 ulong_t value
, mask
;
8442 if (!is_const(ins
)) {
8445 value
= ins
->u
.cval
;
8452 return ((value
& mask
) == value
);
8455 static ulong_t
read_const(struct compile_state
*state
,
8456 struct triple
*ins
, struct triple
*rhs
)
8458 switch(rhs
->type
->type
&TYPE_MASK
) {
8471 fprintf(state
->errout
, "type: ");
8472 name_of(state
->errout
, rhs
->type
);
8473 fprintf(state
->errout
, "\n");
8474 internal_warning(state
, rhs
, "bad type to read_const");
8477 if (!is_simple_const(rhs
)) {
8478 internal_error(state
, rhs
, "bad op to read_const");
8483 static long_t
read_sconst(struct compile_state
*state
,
8484 struct triple
*ins
, struct triple
*rhs
)
8486 return (long_t
)(rhs
->u
.cval
);
8489 int const_ltrue(struct compile_state
*state
, struct triple
*ins
, struct triple
*rhs
)
8491 if (!is_const(rhs
)) {
8492 internal_error(state
, 0, "non const passed to const_true");
8494 return !is_zero(rhs
);
8497 int const_eq(struct compile_state
*state
, struct triple
*ins
,
8498 struct triple
*left
, struct triple
*right
)
8501 if (!is_const(left
) || !is_const(right
)) {
8502 internal_warning(state
, ins
, "non const passed to const_eq");
8505 else if (left
== right
) {
8508 else if (is_simple_const(left
) && is_simple_const(right
)) {
8510 lval
= read_const(state
, ins
, left
);
8511 rval
= read_const(state
, ins
, right
);
8512 result
= (lval
== rval
);
8514 else if ((left
->op
== OP_ADDRCONST
) &&
8515 (right
->op
== OP_ADDRCONST
)) {
8516 result
= (MISC(left
, 0) == MISC(right
, 0)) &&
8517 (left
->u
.cval
== right
->u
.cval
);
8520 internal_warning(state
, ins
, "incomparable constants passed to const_eq");
8527 int const_ucmp(struct compile_state
*state
, struct triple
*ins
,
8528 struct triple
*left
, struct triple
*right
)
8531 if (!is_const(left
) || !is_const(right
)) {
8532 internal_warning(state
, ins
, "non const past to const_ucmp");
8535 else if (left
== right
) {
8538 else if (is_simple_const(left
) && is_simple_const(right
)) {
8540 lval
= read_const(state
, ins
, left
);
8541 rval
= read_const(state
, ins
, right
);
8545 } else if (rval
> lval
) {
8549 else if ((left
->op
== OP_ADDRCONST
) &&
8550 (right
->op
== OP_ADDRCONST
) &&
8551 (MISC(left
, 0) == MISC(right
, 0))) {
8553 if (left
->u
.cval
> right
->u
.cval
) {
8555 } else if (left
->u
.cval
< right
->u
.cval
) {
8560 internal_warning(state
, ins
, "incomparable constants passed to const_ucmp");
8566 int const_scmp(struct compile_state
*state
, struct triple
*ins
,
8567 struct triple
*left
, struct triple
*right
)
8570 if (!is_const(left
) || !is_const(right
)) {
8571 internal_warning(state
, ins
, "non const past to ucmp_const");
8574 else if (left
== right
) {
8577 else if (is_simple_const(left
) && is_simple_const(right
)) {
8579 lval
= read_sconst(state
, ins
, left
);
8580 rval
= read_sconst(state
, ins
, right
);
8584 } else if (rval
> lval
) {
8589 internal_warning(state
, ins
, "incomparable constants passed to const_scmp");
8595 static void unuse_rhs(struct compile_state
*state
, struct triple
*ins
)
8597 struct triple
**expr
;
8598 expr
= triple_rhs(state
, ins
, 0);
8599 for(;expr
;expr
= triple_rhs(state
, ins
, expr
)) {
8601 unuse_triple(*expr
, ins
);
8607 static void unuse_lhs(struct compile_state
*state
, struct triple
*ins
)
8609 struct triple
**expr
;
8610 expr
= triple_lhs(state
, ins
, 0);
8611 for(;expr
;expr
= triple_lhs(state
, ins
, expr
)) {
8612 unuse_triple(*expr
, ins
);
8617 #if DEBUG_ROMCC_WARNING
8618 static void unuse_misc(struct compile_state
*state
, struct triple
*ins
)
8620 struct triple
**expr
;
8621 expr
= triple_misc(state
, ins
, 0);
8622 for(;expr
;expr
= triple_misc(state
, ins
, expr
)) {
8623 unuse_triple(*expr
, ins
);
8628 static void unuse_targ(struct compile_state
*state
, struct triple
*ins
)
8631 struct triple
**slot
;
8632 slot
= &TARG(ins
, 0);
8633 for(i
= 0; i
< ins
->targ
; i
++) {
8634 unuse_triple(slot
[i
], ins
);
8639 static void check_lhs(struct compile_state
*state
, struct triple
*ins
)
8641 struct triple
**expr
;
8642 expr
= triple_lhs(state
, ins
, 0);
8643 for(;expr
;expr
= triple_lhs(state
, ins
, expr
)) {
8644 internal_error(state
, ins
, "unexpected lhs");
8650 static void check_misc(struct compile_state
*state
, struct triple
*ins
)
8652 struct triple
**expr
;
8653 expr
= triple_misc(state
, ins
, 0);
8654 for(;expr
;expr
= triple_misc(state
, ins
, expr
)) {
8656 internal_error(state
, ins
, "unexpected misc");
8661 static void check_targ(struct compile_state
*state
, struct triple
*ins
)
8663 struct triple
**expr
;
8664 expr
= triple_targ(state
, ins
, 0);
8665 for(;expr
;expr
= triple_targ(state
, ins
, expr
)) {
8666 internal_error(state
, ins
, "unexpected targ");
8670 static void wipe_ins(struct compile_state
*state
, struct triple
*ins
)
8672 /* Becareful which instructions you replace the wiped
8673 * instruction with, as there are not enough slots
8674 * in all instructions to hold all others.
8676 check_targ(state
, ins
);
8677 check_misc(state
, ins
);
8678 unuse_rhs(state
, ins
);
8679 unuse_lhs(state
, ins
);
8686 #if DEBUG_ROMCC_WARNING
8687 static void wipe_branch(struct compile_state
*state
, struct triple
*ins
)
8689 /* Becareful which instructions you replace the wiped
8690 * instruction with, as there are not enough slots
8691 * in all instructions to hold all others.
8693 unuse_rhs(state
, ins
);
8694 unuse_lhs(state
, ins
);
8695 unuse_misc(state
, ins
);
8696 unuse_targ(state
, ins
);
8704 static void mkcopy(struct compile_state
*state
,
8705 struct triple
*ins
, struct triple
*rhs
)
8707 struct block
*block
;
8708 if (!equiv_types(ins
->type
, rhs
->type
)) {
8709 FILE *fp
= state
->errout
;
8710 fprintf(fp
, "src type: ");
8711 name_of(fp
, rhs
->type
);
8712 fprintf(fp
, "\ndst type: ");
8713 name_of(fp
, ins
->type
);
8715 internal_error(state
, ins
, "mkcopy type mismatch");
8717 block
= block_of_triple(state
, ins
);
8718 wipe_ins(state
, ins
);
8721 ins
->u
.block
= block
;
8723 use_triple(RHS(ins
, 0), ins
);
8726 static void mkconst(struct compile_state
*state
,
8727 struct triple
*ins
, ulong_t value
)
8729 if (!is_integral(ins
) && !is_pointer(ins
)) {
8730 fprintf(state
->errout
, "type: ");
8731 name_of(state
->errout
, ins
->type
);
8732 fprintf(state
->errout
, "\n");
8733 internal_error(state
, ins
, "unknown type to make constant value: %ld",
8736 wipe_ins(state
, ins
);
8737 ins
->op
= OP_INTCONST
;
8738 ins
->u
.cval
= value
;
8741 static void mkaddr_const(struct compile_state
*state
,
8742 struct triple
*ins
, struct triple
*sdecl
, ulong_t value
)
8744 if ((sdecl
->op
!= OP_SDECL
) && (sdecl
->op
!= OP_LABEL
)) {
8745 internal_error(state
, ins
, "bad base for addrconst");
8747 wipe_ins(state
, ins
);
8748 ins
->op
= OP_ADDRCONST
;
8750 MISC(ins
, 0) = sdecl
;
8751 ins
->u
.cval
= value
;
8752 use_triple(sdecl
, ins
);
8755 #if DEBUG_DECOMPOSE_PRINT_TUPLES
8756 static void print_tuple(struct compile_state
*state
,
8757 struct triple
*ins
, struct triple
*tuple
)
8759 FILE *fp
= state
->dbgout
;
8760 fprintf(fp
, "%5s %p tuple: %p ", tops(ins
->op
), ins
, tuple
);
8761 name_of(fp
, tuple
->type
);
8762 if (tuple
->lhs
> 0) {
8763 fprintf(fp
, " lhs: ");
8764 name_of(fp
, LHS(tuple
, 0)->type
);
8771 static struct triple
*decompose_with_tuple(struct compile_state
*state
,
8772 struct triple
*ins
, struct triple
*tuple
)
8774 struct triple
*next
;
8776 flatten(state
, next
, tuple
);
8777 #if DEBUG_DECOMPOSE_PRINT_TUPLES
8778 print_tuple(state
, ins
, tuple
);
8781 if (!is_compound_type(tuple
->type
) && (tuple
->lhs
> 0)) {
8783 if (tuple
->lhs
!= 1) {
8784 internal_error(state
, tuple
, "plain type in multiple registers?");
8786 tmp
= LHS(tuple
, 0);
8787 release_triple(state
, tuple
);
8791 propogate_use(state
, ins
, tuple
);
8792 release_triple(state
, ins
);
8797 static struct triple
*decompose_unknownval(struct compile_state
*state
,
8800 struct triple
*tuple
;
8803 #if DEBUG_DECOMPOSE_HIRES
8804 FILE *fp
= state
->dbgout
;
8805 fprintf(fp
, "unknown type: ");
8806 name_of(fp
, ins
->type
);
8810 get_occurance(ins
->occurance
);
8811 tuple
= alloc_triple(state
, OP_TUPLE
, ins
->type
, -1, -1,
8814 for(i
= 0; i
< tuple
->lhs
; i
++) {
8815 struct type
*piece_type
;
8816 struct triple
*unknown
;
8818 piece_type
= reg_type(state
, ins
->type
, i
* REG_SIZEOF_REG
);
8819 get_occurance(tuple
->occurance
);
8820 unknown
= alloc_triple(state
, OP_UNKNOWNVAL
, piece_type
, 0, 0,
8822 LHS(tuple
, i
) = unknown
;
8824 return decompose_with_tuple(state
, ins
, tuple
);
8828 static struct triple
*decompose_read(struct compile_state
*state
,
8831 struct triple
*tuple
, *lval
;
8836 if (lval
->op
== OP_PIECE
) {
8839 get_occurance(ins
->occurance
);
8840 tuple
= alloc_triple(state
, OP_TUPLE
, lval
->type
, -1, -1,
8843 if ((tuple
->lhs
!= lval
->lhs
) &&
8844 (!triple_is_def(state
, lval
) || (tuple
->lhs
!= 1)))
8846 internal_error(state
, ins
, "lhs size inconsistency?");
8848 for(i
= 0; i
< tuple
->lhs
; i
++) {
8849 struct triple
*piece
, *read
, *bitref
;
8850 if ((i
!= 0) || !triple_is_def(state
, lval
)) {
8851 piece
= LHS(lval
, i
);
8856 /* See if the piece is really a bitref */
8858 if (piece
->op
== OP_BITREF
) {
8860 piece
= RHS(bitref
, 0);
8863 get_occurance(tuple
->occurance
);
8864 read
= alloc_triple(state
, OP_READ
, piece
->type
, -1, -1,
8866 RHS(read
, 0) = piece
;
8869 struct triple
*extract
;
8871 if (is_signed(bitref
->type
->left
)) {
8876 get_occurance(tuple
->occurance
);
8877 extract
= alloc_triple(state
, op
, bitref
->type
, -1, -1,
8879 RHS(extract
, 0) = read
;
8880 extract
->u
.bitfield
.size
= bitref
->u
.bitfield
.size
;
8881 extract
->u
.bitfield
.offset
= bitref
->u
.bitfield
.offset
;
8886 LHS(tuple
, i
) = read
;
8888 return decompose_with_tuple(state
, ins
, tuple
);
8891 static struct triple
*decompose_write(struct compile_state
*state
,
8894 struct triple
*tuple
, *lval
, *val
;
8897 lval
= MISC(ins
, 0);
8899 get_occurance(ins
->occurance
);
8900 tuple
= alloc_triple(state
, OP_TUPLE
, ins
->type
, -1, -1,
8903 if ((tuple
->lhs
!= lval
->lhs
) &&
8904 (!triple_is_def(state
, lval
) || tuple
->lhs
!= 1))
8906 internal_error(state
, ins
, "lhs size inconsistency?");
8908 for(i
= 0; i
< tuple
->lhs
; i
++) {
8909 struct triple
*piece
, *write
, *pval
, *bitref
;
8910 if ((i
!= 0) || !triple_is_def(state
, lval
)) {
8911 piece
= LHS(lval
, i
);
8915 if ((i
== 0) && (tuple
->lhs
== 1) && (val
->lhs
== 0)) {
8920 internal_error(state
, ins
, "lhs size inconsistency?");
8925 /* See if the piece is really a bitref */
8927 if (piece
->op
== OP_BITREF
) {
8928 struct triple
*read
, *deposit
;
8930 piece
= RHS(bitref
, 0);
8932 /* Read the destination register */
8933 get_occurance(tuple
->occurance
);
8934 read
= alloc_triple(state
, OP_READ
, piece
->type
, -1, -1,
8936 RHS(read
, 0) = piece
;
8938 /* Deposit the new bitfield value */
8939 get_occurance(tuple
->occurance
);
8940 deposit
= alloc_triple(state
, OP_DEPOSIT
, piece
->type
, -1, -1,
8942 RHS(deposit
, 0) = read
;
8943 RHS(deposit
, 1) = pval
;
8944 deposit
->u
.bitfield
.size
= bitref
->u
.bitfield
.size
;
8945 deposit
->u
.bitfield
.offset
= bitref
->u
.bitfield
.offset
;
8947 /* Now write the newly generated value */
8951 get_occurance(tuple
->occurance
);
8952 write
= alloc_triple(state
, OP_WRITE
, piece
->type
, -1, -1,
8954 MISC(write
, 0) = piece
;
8955 RHS(write
, 0) = pval
;
8956 LHS(tuple
, i
) = write
;
8958 return decompose_with_tuple(state
, ins
, tuple
);
8961 struct decompose_load_info
{
8962 struct occurance
*occurance
;
8963 struct triple
*lval
;
8964 struct triple
*tuple
;
8966 static void decompose_load_cb(struct compile_state
*state
,
8967 struct type
*type
, size_t reg_offset
, size_t mem_offset
, void *arg
)
8969 struct decompose_load_info
*info
= arg
;
8970 struct triple
*load
;
8972 if (reg_offset
> info
->tuple
->lhs
) {
8973 internal_error(state
, info
->tuple
, "lhs to small?");
8975 get_occurance(info
->occurance
);
8976 load
= alloc_triple(state
, OP_LOAD
, type
, -1, -1, info
->occurance
);
8977 RHS(load
, 0) = mk_addr_expr(state
, info
->lval
, mem_offset
);
8978 LHS(info
->tuple
, reg_offset
/REG_SIZEOF_REG
) = load
;
8981 static struct triple
*decompose_load(struct compile_state
*state
,
8984 struct triple
*tuple
;
8985 struct decompose_load_info info
;
8987 if (!is_compound_type(ins
->type
)) {
8990 get_occurance(ins
->occurance
);
8991 tuple
= alloc_triple(state
, OP_TUPLE
, ins
->type
, -1, -1,
8994 info
.occurance
= ins
->occurance
;
8995 info
.lval
= RHS(ins
, 0);
8997 walk_type_fields(state
, ins
->type
, 0, 0, decompose_load_cb
, &info
);
8999 return decompose_with_tuple(state
, ins
, tuple
);
9003 struct decompose_store_info
{
9004 struct occurance
*occurance
;
9005 struct triple
*lval
;
9007 struct triple
*tuple
;
9009 static void decompose_store_cb(struct compile_state
*state
,
9010 struct type
*type
, size_t reg_offset
, size_t mem_offset
, void *arg
)
9012 struct decompose_store_info
*info
= arg
;
9013 struct triple
*store
;
9015 if (reg_offset
> info
->tuple
->lhs
) {
9016 internal_error(state
, info
->tuple
, "lhs to small?");
9018 get_occurance(info
->occurance
);
9019 store
= alloc_triple(state
, OP_STORE
, type
, -1, -1, info
->occurance
);
9020 RHS(store
, 0) = mk_addr_expr(state
, info
->lval
, mem_offset
);
9021 RHS(store
, 1) = LHS(info
->val
, reg_offset
);
9022 LHS(info
->tuple
, reg_offset
/REG_SIZEOF_REG
) = store
;
9025 static struct triple
*decompose_store(struct compile_state
*state
,
9028 struct triple
*tuple
;
9029 struct decompose_store_info info
;
9031 if (!is_compound_type(ins
->type
)) {
9034 get_occurance(ins
->occurance
);
9035 tuple
= alloc_triple(state
, OP_TUPLE
, ins
->type
, -1, -1,
9038 info
.occurance
= ins
->occurance
;
9039 info
.lval
= RHS(ins
, 0);
9040 info
.val
= RHS(ins
, 1);
9042 walk_type_fields(state
, ins
->type
, 0, 0, decompose_store_cb
, &info
);
9044 return decompose_with_tuple(state
, ins
, tuple
);
9047 static struct triple
*decompose_dot(struct compile_state
*state
,
9050 struct triple
*tuple
, *lval
;
9055 lval
= MISC(ins
, 0);
9056 reg_offset
= field_reg_offset(state
, lval
->type
, ins
->u
.field
);
9057 idx
= reg_offset
/REG_SIZEOF_REG
;
9058 type
= field_type(state
, lval
->type
, ins
->u
.field
);
9059 #if DEBUG_DECOMPOSE_HIRES
9061 FILE *fp
= state
->dbgout
;
9062 fprintf(fp
, "field type: ");
9068 get_occurance(ins
->occurance
);
9069 tuple
= alloc_triple(state
, OP_TUPLE
, type
, -1, -1,
9072 if (((ins
->type
->type
& TYPE_MASK
) == TYPE_BITFIELD
) &&
9075 internal_error(state
, ins
, "multi register bitfield?");
9078 for(i
= 0; i
< tuple
->lhs
; i
++, idx
++) {
9079 struct triple
*piece
;
9080 if (!triple_is_def(state
, lval
)) {
9081 if (idx
> lval
->lhs
) {
9082 internal_error(state
, ins
, "inconsistent lhs count");
9084 piece
= LHS(lval
, idx
);
9087 internal_error(state
, ins
, "bad reg_offset into def");
9090 internal_error(state
, ins
, "bad reg count from def");
9095 /* Remember the offset of the bitfield */
9096 if ((type
->type
& TYPE_MASK
) == TYPE_BITFIELD
) {
9097 get_occurance(ins
->occurance
);
9098 piece
= build_triple(state
, OP_BITREF
, type
, piece
, 0,
9100 piece
->u
.bitfield
.size
= size_of(state
, type
);
9101 piece
->u
.bitfield
.offset
= reg_offset
% REG_SIZEOF_REG
;
9103 else if ((reg_offset
% REG_SIZEOF_REG
) != 0) {
9104 internal_error(state
, ins
,
9105 "request for a nonbitfield sub register?");
9108 LHS(tuple
, i
) = piece
;
9111 return decompose_with_tuple(state
, ins
, tuple
);
9114 static struct triple
*decompose_index(struct compile_state
*state
,
9117 struct triple
*tuple
, *lval
;
9121 lval
= MISC(ins
, 0);
9122 idx
= index_reg_offset(state
, lval
->type
, ins
->u
.cval
)/REG_SIZEOF_REG
;
9123 type
= index_type(state
, lval
->type
, ins
->u
.cval
);
9124 #if DEBUG_DECOMPOSE_HIRES
9126 FILE *fp
= state
->dbgout
;
9127 fprintf(fp
, "index type: ");
9133 get_occurance(ins
->occurance
);
9134 tuple
= alloc_triple(state
, OP_TUPLE
, type
, -1, -1,
9137 for(i
= 0; i
< tuple
->lhs
; i
++, idx
++) {
9138 struct triple
*piece
;
9139 if (!triple_is_def(state
, lval
)) {
9140 if (idx
> lval
->lhs
) {
9141 internal_error(state
, ins
, "inconsistent lhs count");
9143 piece
= LHS(lval
, idx
);
9146 internal_error(state
, ins
, "bad reg_offset into def");
9149 internal_error(state
, ins
, "bad reg count from def");
9153 LHS(tuple
, i
) = piece
;
9156 return decompose_with_tuple(state
, ins
, tuple
);
9159 static void decompose_compound_types(struct compile_state
*state
)
9161 struct triple
*ins
, *next
, *first
;
9162 first
= state
->first
;
9165 /* Pass one expand compound values into pseudo registers.
9173 next
= decompose_unknownval(state
, ins
);
9177 next
= decompose_read(state
, ins
);
9181 next
= decompose_write(state
, ins
);
9185 /* Be very careful with the load/store logic. These
9186 * operations must convert from the in register layout
9187 * to the in memory layout, which is nontrivial.
9190 next
= decompose_load(state
, ins
);
9193 next
= decompose_store(state
, ins
);
9197 next
= decompose_dot(state
, ins
);
9200 next
= decompose_index(state
, ins
);
9204 #if DEBUG_DECOMPOSE_HIRES
9205 fprintf(fp
, "decompose next: %p \n", next
);
9207 fprintf(fp
, "next->op: %d %s\n",
9208 next
->op
, tops(next
->op
));
9209 /* High resolution debugging mode */
9210 print_triples(state
);
9212 } while (next
!= first
);
9214 /* Pass two remove the tuples.
9219 if (ins
->op
== OP_TUPLE
) {
9221 internal_error(state
, ins
, "tuple used");
9224 release_triple(state
, ins
);
9228 } while(ins
!= first
);
9232 if (ins
->op
== OP_BITREF
) {
9234 internal_error(state
, ins
, "bitref used");
9237 release_triple(state
, ins
);
9241 } while(ins
!= first
);
9243 /* Pass three verify the state and set ->id to 0.
9249 ins
->id
&= ~TRIPLE_FLAG_FLATTENED
;
9250 if (triple_stores_block(state
, ins
)) {
9253 if (triple_is_def(state
, ins
)) {
9254 if (reg_size_of(state
, ins
->type
) > REG_SIZEOF_REG
) {
9255 internal_error(state
, ins
, "multi register value remains?");
9258 if (ins
->op
== OP_DOT
) {
9259 internal_error(state
, ins
, "OP_DOT remains?");
9261 if (ins
->op
== OP_INDEX
) {
9262 internal_error(state
, ins
, "OP_INDEX remains?");
9264 if (ins
->op
== OP_BITREF
) {
9265 internal_error(state
, ins
, "OP_BITREF remains?");
9267 if (ins
->op
== OP_TUPLE
) {
9268 internal_error(state
, ins
, "OP_TUPLE remains?");
9270 } while(next
!= first
);
9273 /* For those operations that cannot be simplified */
9274 static void simplify_noop(struct compile_state
*state
, struct triple
*ins
)
9279 static void simplify_smul(struct compile_state
*state
, struct triple
*ins
)
9281 if (is_const(RHS(ins
, 0)) && !is_const(RHS(ins
, 1))) {
9284 RHS(ins
, 0) = RHS(ins
, 1);
9287 if (is_const(RHS(ins
, 0)) && is_const(RHS(ins
, 1))) {
9289 left
= read_sconst(state
, ins
, RHS(ins
, 0));
9290 right
= read_sconst(state
, ins
, RHS(ins
, 1));
9291 mkconst(state
, ins
, left
* right
);
9293 else if (is_zero(RHS(ins
, 1))) {
9294 mkconst(state
, ins
, 0);
9296 else if (is_one(RHS(ins
, 1))) {
9297 mkcopy(state
, ins
, RHS(ins
, 0));
9299 else if (is_pow2(RHS(ins
, 1))) {
9301 val
= int_const(state
, ins
->type
, tlog2(RHS(ins
, 1)));
9303 insert_triple(state
, state
->global_pool
, val
);
9304 unuse_triple(RHS(ins
, 1), ins
);
9305 use_triple(val
, ins
);
9310 static void simplify_umul(struct compile_state
*state
, struct triple
*ins
)
9312 if (is_const(RHS(ins
, 0)) && !is_const(RHS(ins
, 1))) {
9315 RHS(ins
, 0) = RHS(ins
, 1);
9318 if (is_simple_const(RHS(ins
, 0)) && is_simple_const(RHS(ins
, 1))) {
9319 ulong_t left
, right
;
9320 left
= read_const(state
, ins
, RHS(ins
, 0));
9321 right
= read_const(state
, ins
, RHS(ins
, 1));
9322 mkconst(state
, ins
, left
* right
);
9324 else if (is_zero(RHS(ins
, 1))) {
9325 mkconst(state
, ins
, 0);
9327 else if (is_one(RHS(ins
, 1))) {
9328 mkcopy(state
, ins
, RHS(ins
, 0));
9330 else if (is_pow2(RHS(ins
, 1))) {
9332 val
= int_const(state
, ins
->type
, tlog2(RHS(ins
, 1)));
9334 insert_triple(state
, state
->global_pool
, val
);
9335 unuse_triple(RHS(ins
, 1), ins
);
9336 use_triple(val
, ins
);
9341 static void simplify_sdiv(struct compile_state
*state
, struct triple
*ins
)
9343 if (is_const(RHS(ins
, 0)) && is_const(RHS(ins
, 1))) {
9345 left
= read_sconst(state
, ins
, RHS(ins
, 0));
9346 right
= read_sconst(state
, ins
, RHS(ins
, 1));
9347 mkconst(state
, ins
, left
/ right
);
9349 else if (is_zero(RHS(ins
, 0))) {
9350 mkconst(state
, ins
, 0);
9352 else if (is_zero(RHS(ins
, 1))) {
9353 error(state
, ins
, "division by zero");
9355 else if (is_one(RHS(ins
, 1))) {
9356 mkcopy(state
, ins
, RHS(ins
, 0));
9358 else if (is_pow2(RHS(ins
, 1))) {
9360 val
= int_const(state
, ins
->type
, tlog2(RHS(ins
, 1)));
9362 insert_triple(state
, state
->global_pool
, val
);
9363 unuse_triple(RHS(ins
, 1), ins
);
9364 use_triple(val
, ins
);
9369 static void simplify_udiv(struct compile_state
*state
, struct triple
*ins
)
9371 if (is_simple_const(RHS(ins
, 0)) && is_simple_const(RHS(ins
, 1))) {
9372 ulong_t left
, right
;
9373 left
= read_const(state
, ins
, RHS(ins
, 0));
9374 right
= read_const(state
, ins
, RHS(ins
, 1));
9375 mkconst(state
, ins
, left
/ right
);
9377 else if (is_zero(RHS(ins
, 0))) {
9378 mkconst(state
, ins
, 0);
9380 else if (is_zero(RHS(ins
, 1))) {
9381 error(state
, ins
, "division by zero");
9383 else if (is_one(RHS(ins
, 1))) {
9384 mkcopy(state
, ins
, RHS(ins
, 0));
9386 else if (is_pow2(RHS(ins
, 1))) {
9388 val
= int_const(state
, ins
->type
, tlog2(RHS(ins
, 1)));
9390 insert_triple(state
, state
->global_pool
, val
);
9391 unuse_triple(RHS(ins
, 1), ins
);
9392 use_triple(val
, ins
);
9397 static void simplify_smod(struct compile_state
*state
, struct triple
*ins
)
9399 if (is_simple_const(RHS(ins
, 0)) && is_simple_const(RHS(ins
, 1))) {
9401 left
= read_const(state
, ins
, RHS(ins
, 0));
9402 right
= read_const(state
, ins
, RHS(ins
, 1));
9403 mkconst(state
, ins
, left
% right
);
9405 else if (is_zero(RHS(ins
, 0))) {
9406 mkconst(state
, ins
, 0);
9408 else if (is_zero(RHS(ins
, 1))) {
9409 error(state
, ins
, "division by zero");
9411 else if (is_one(RHS(ins
, 1))) {
9412 mkconst(state
, ins
, 0);
9414 else if (is_pow2(RHS(ins
, 1))) {
9416 val
= int_const(state
, ins
->type
, RHS(ins
, 1)->u
.cval
- 1);
9418 insert_triple(state
, state
->global_pool
, val
);
9419 unuse_triple(RHS(ins
, 1), ins
);
9420 use_triple(val
, ins
);
9425 static void simplify_umod(struct compile_state
*state
, struct triple
*ins
)
9427 if (is_simple_const(RHS(ins
, 0)) && is_simple_const(RHS(ins
, 1))) {
9428 ulong_t left
, right
;
9429 left
= read_const(state
, ins
, RHS(ins
, 0));
9430 right
= read_const(state
, ins
, RHS(ins
, 1));
9431 mkconst(state
, ins
, left
% right
);
9433 else if (is_zero(RHS(ins
, 0))) {
9434 mkconst(state
, ins
, 0);
9436 else if (is_zero(RHS(ins
, 1))) {
9437 error(state
, ins
, "division by zero");
9439 else if (is_one(RHS(ins
, 1))) {
9440 mkconst(state
, ins
, 0);
9442 else if (is_pow2(RHS(ins
, 1))) {
9444 val
= int_const(state
, ins
->type
, RHS(ins
, 1)->u
.cval
- 1);
9446 insert_triple(state
, state
->global_pool
, val
);
9447 unuse_triple(RHS(ins
, 1), ins
);
9448 use_triple(val
, ins
);
9453 static void simplify_add(struct compile_state
*state
, struct triple
*ins
)
9455 /* start with the pointer on the left */
9456 if (is_pointer(RHS(ins
, 1))) {
9459 RHS(ins
, 0) = RHS(ins
, 1);
9462 if (is_const(RHS(ins
, 0)) && is_simple_const(RHS(ins
, 1))) {
9463 if (RHS(ins
, 0)->op
== OP_INTCONST
) {
9464 ulong_t left
, right
;
9465 left
= read_const(state
, ins
, RHS(ins
, 0));
9466 right
= read_const(state
, ins
, RHS(ins
, 1));
9467 mkconst(state
, ins
, left
+ right
);
9469 else if (RHS(ins
, 0)->op
== OP_ADDRCONST
) {
9470 struct triple
*sdecl
;
9471 ulong_t left
, right
;
9472 sdecl
= MISC(RHS(ins
, 0), 0);
9473 left
= RHS(ins
, 0)->u
.cval
;
9474 right
= RHS(ins
, 1)->u
.cval
;
9475 mkaddr_const(state
, ins
, sdecl
, left
+ right
);
9478 internal_warning(state
, ins
, "Optimize me!");
9481 else if (is_const(RHS(ins
, 0)) && !is_const(RHS(ins
, 1))) {
9484 RHS(ins
, 1) = RHS(ins
, 0);
9489 static void simplify_sub(struct compile_state
*state
, struct triple
*ins
)
9491 if (is_const(RHS(ins
, 0)) && is_simple_const(RHS(ins
, 1))) {
9492 if (RHS(ins
, 0)->op
== OP_INTCONST
) {
9493 ulong_t left
, right
;
9494 left
= read_const(state
, ins
, RHS(ins
, 0));
9495 right
= read_const(state
, ins
, RHS(ins
, 1));
9496 mkconst(state
, ins
, left
- right
);
9498 else if (RHS(ins
, 0)->op
== OP_ADDRCONST
) {
9499 struct triple
*sdecl
;
9500 ulong_t left
, right
;
9501 sdecl
= MISC(RHS(ins
, 0), 0);
9502 left
= RHS(ins
, 0)->u
.cval
;
9503 right
= RHS(ins
, 1)->u
.cval
;
9504 mkaddr_const(state
, ins
, sdecl
, left
- right
);
9507 internal_warning(state
, ins
, "Optimize me!");
9512 static void simplify_sl(struct compile_state
*state
, struct triple
*ins
)
9514 if (is_simple_const(RHS(ins
, 1))) {
9516 right
= read_const(state
, ins
, RHS(ins
, 1));
9517 if (right
>= (size_of(state
, ins
->type
))) {
9518 warning(state
, ins
, "left shift count >= width of type");
9521 if (is_simple_const(RHS(ins
, 0)) && is_simple_const(RHS(ins
, 1))) {
9522 ulong_t left
, right
;
9523 left
= read_const(state
, ins
, RHS(ins
, 0));
9524 right
= read_const(state
, ins
, RHS(ins
, 1));
9525 mkconst(state
, ins
, left
<< right
);
9529 static void simplify_usr(struct compile_state
*state
, struct triple
*ins
)
9531 if (is_simple_const(RHS(ins
, 1))) {
9533 right
= read_const(state
, ins
, RHS(ins
, 1));
9534 if (right
>= (size_of(state
, ins
->type
))) {
9535 warning(state
, ins
, "right shift count >= width of type");
9538 if (is_simple_const(RHS(ins
, 0)) && is_simple_const(RHS(ins
, 1))) {
9539 ulong_t left
, right
;
9540 left
= read_const(state
, ins
, RHS(ins
, 0));
9541 right
= read_const(state
, ins
, RHS(ins
, 1));
9542 mkconst(state
, ins
, left
>> right
);
9546 static void simplify_ssr(struct compile_state
*state
, struct triple
*ins
)
9548 if (is_simple_const(RHS(ins
, 1))) {
9550 right
= read_const(state
, ins
, RHS(ins
, 1));
9551 if (right
>= (size_of(state
, ins
->type
))) {
9552 warning(state
, ins
, "right shift count >= width of type");
9555 if (is_simple_const(RHS(ins
, 0)) && is_simple_const(RHS(ins
, 1))) {
9557 left
= read_sconst(state
, ins
, RHS(ins
, 0));
9558 right
= read_sconst(state
, ins
, RHS(ins
, 1));
9559 mkconst(state
, ins
, left
>> right
);
9563 static void simplify_and(struct compile_state
*state
, struct triple
*ins
)
9565 struct triple
*left
, *right
;
9567 right
= RHS(ins
, 1);
9569 if (is_simple_const(left
) && is_simple_const(right
)) {
9571 lval
= read_const(state
, ins
, left
);
9572 rval
= read_const(state
, ins
, right
);
9573 mkconst(state
, ins
, lval
& rval
);
9575 else if (is_zero(right
) || is_zero(left
)) {
9576 mkconst(state
, ins
, 0);
9580 static void simplify_or(struct compile_state
*state
, struct triple
*ins
)
9582 struct triple
*left
, *right
;
9584 right
= RHS(ins
, 1);
9586 if (is_simple_const(left
) && is_simple_const(right
)) {
9588 lval
= read_const(state
, ins
, left
);
9589 rval
= read_const(state
, ins
, right
);
9590 mkconst(state
, ins
, lval
| rval
);
9592 #if 0 /* I need to handle type mismatches here... */
9593 else if (is_zero(right
)) {
9594 mkcopy(state
, ins
, left
);
9596 else if (is_zero(left
)) {
9597 mkcopy(state
, ins
, right
);
9602 static void simplify_xor(struct compile_state
*state
, struct triple
*ins
)
9604 if (is_simple_const(RHS(ins
, 0)) && is_simple_const(RHS(ins
, 1))) {
9605 ulong_t left
, right
;
9606 left
= read_const(state
, ins
, RHS(ins
, 0));
9607 right
= read_const(state
, ins
, RHS(ins
, 1));
9608 mkconst(state
, ins
, left
^ right
);
9612 static void simplify_pos(struct compile_state
*state
, struct triple
*ins
)
9614 if (is_const(RHS(ins
, 0))) {
9615 mkconst(state
, ins
, RHS(ins
, 0)->u
.cval
);
9618 mkcopy(state
, ins
, RHS(ins
, 0));
9622 static void simplify_neg(struct compile_state
*state
, struct triple
*ins
)
9624 if (is_simple_const(RHS(ins
, 0))) {
9626 left
= read_const(state
, ins
, RHS(ins
, 0));
9627 mkconst(state
, ins
, -left
);
9629 else if (RHS(ins
, 0)->op
== OP_NEG
) {
9630 mkcopy(state
, ins
, RHS(RHS(ins
, 0), 0));
9634 static void simplify_invert(struct compile_state
*state
, struct triple
*ins
)
9636 if (is_simple_const(RHS(ins
, 0))) {
9638 left
= read_const(state
, ins
, RHS(ins
, 0));
9639 mkconst(state
, ins
, ~left
);
9643 static void simplify_eq(struct compile_state
*state
, struct triple
*ins
)
9645 struct triple
*left
, *right
;
9647 right
= RHS(ins
, 1);
9649 if (is_const(left
) && is_const(right
)) {
9651 val
= const_eq(state
, ins
, left
, right
);
9653 mkconst(state
, ins
, val
== 1);
9656 else if (left
== right
) {
9657 mkconst(state
, ins
, 1);
9661 static void simplify_noteq(struct compile_state
*state
, struct triple
*ins
)
9663 struct triple
*left
, *right
;
9665 right
= RHS(ins
, 1);
9667 if (is_const(left
) && is_const(right
)) {
9669 val
= const_eq(state
, ins
, left
, right
);
9671 mkconst(state
, ins
, val
!= 1);
9674 if (left
== right
) {
9675 mkconst(state
, ins
, 0);
9679 static void simplify_sless(struct compile_state
*state
, struct triple
*ins
)
9681 struct triple
*left
, *right
;
9683 right
= RHS(ins
, 1);
9685 if (is_const(left
) && is_const(right
)) {
9687 val
= const_scmp(state
, ins
, left
, right
);
9688 if ((val
>= -1) && (val
<= 1)) {
9689 mkconst(state
, ins
, val
< 0);
9692 else if (left
== right
) {
9693 mkconst(state
, ins
, 0);
9697 static void simplify_uless(struct compile_state
*state
, struct triple
*ins
)
9699 struct triple
*left
, *right
;
9701 right
= RHS(ins
, 1);
9703 if (is_const(left
) && is_const(right
)) {
9705 val
= const_ucmp(state
, ins
, left
, right
);
9706 if ((val
>= -1) && (val
<= 1)) {
9707 mkconst(state
, ins
, val
< 0);
9710 else if (is_zero(right
)) {
9711 mkconst(state
, ins
, 0);
9713 else if (left
== right
) {
9714 mkconst(state
, ins
, 0);
9718 static void simplify_smore(struct compile_state
*state
, struct triple
*ins
)
9720 struct triple
*left
, *right
;
9722 right
= RHS(ins
, 1);
9724 if (is_const(left
) && is_const(right
)) {
9726 val
= const_scmp(state
, ins
, left
, right
);
9727 if ((val
>= -1) && (val
<= 1)) {
9728 mkconst(state
, ins
, val
> 0);
9731 else if (left
== right
) {
9732 mkconst(state
, ins
, 0);
9736 static void simplify_umore(struct compile_state
*state
, struct triple
*ins
)
9738 struct triple
*left
, *right
;
9740 right
= RHS(ins
, 1);
9742 if (is_const(left
) && is_const(right
)) {
9744 val
= const_ucmp(state
, ins
, left
, right
);
9745 if ((val
>= -1) && (val
<= 1)) {
9746 mkconst(state
, ins
, val
> 0);
9749 else if (is_zero(left
)) {
9750 mkconst(state
, ins
, 0);
9752 else if (left
== right
) {
9753 mkconst(state
, ins
, 0);
9758 static void simplify_slesseq(struct compile_state
*state
, struct triple
*ins
)
9760 struct triple
*left
, *right
;
9762 right
= RHS(ins
, 1);
9764 if (is_const(left
) && is_const(right
)) {
9766 val
= const_scmp(state
, ins
, left
, right
);
9767 if ((val
>= -1) && (val
<= 1)) {
9768 mkconst(state
, ins
, val
<= 0);
9771 else if (left
== right
) {
9772 mkconst(state
, ins
, 1);
9776 static void simplify_ulesseq(struct compile_state
*state
, struct triple
*ins
)
9778 struct triple
*left
, *right
;
9780 right
= RHS(ins
, 1);
9782 if (is_const(left
) && is_const(right
)) {
9784 val
= const_ucmp(state
, ins
, left
, right
);
9785 if ((val
>= -1) && (val
<= 1)) {
9786 mkconst(state
, ins
, val
<= 0);
9789 else if (is_zero(left
)) {
9790 mkconst(state
, ins
, 1);
9792 else if (left
== right
) {
9793 mkconst(state
, ins
, 1);
9797 static void simplify_smoreeq(struct compile_state
*state
, struct triple
*ins
)
9799 struct triple
*left
, *right
;
9801 right
= RHS(ins
, 1);
9803 if (is_const(left
) && is_const(right
)) {
9805 val
= const_scmp(state
, ins
, left
, right
);
9806 if ((val
>= -1) && (val
<= 1)) {
9807 mkconst(state
, ins
, val
>= 0);
9810 else if (left
== right
) {
9811 mkconst(state
, ins
, 1);
9815 static void simplify_umoreeq(struct compile_state
*state
, struct triple
*ins
)
9817 struct triple
*left
, *right
;
9819 right
= RHS(ins
, 1);
9821 if (is_const(left
) && is_const(right
)) {
9823 val
= const_ucmp(state
, ins
, left
, right
);
9824 if ((val
>= -1) && (val
<= 1)) {
9825 mkconst(state
, ins
, val
>= 0);
9828 else if (is_zero(right
)) {
9829 mkconst(state
, ins
, 1);
9831 else if (left
== right
) {
9832 mkconst(state
, ins
, 1);
9836 static void simplify_lfalse(struct compile_state
*state
, struct triple
*ins
)
9841 if (is_const(rhs
)) {
9842 mkconst(state
, ins
, !const_ltrue(state
, ins
, rhs
));
9844 /* Otherwise if I am the only user... */
9845 else if ((rhs
->use
) &&
9846 (rhs
->use
->member
== ins
) && (rhs
->use
->next
== 0)) {
9848 /* Invert a boolean operation */
9850 case OP_LTRUE
: rhs
->op
= OP_LFALSE
; break;
9851 case OP_LFALSE
: rhs
->op
= OP_LTRUE
; break;
9852 case OP_EQ
: rhs
->op
= OP_NOTEQ
; break;
9853 case OP_NOTEQ
: rhs
->op
= OP_EQ
; break;
9854 case OP_SLESS
: rhs
->op
= OP_SMOREEQ
; break;
9855 case OP_ULESS
: rhs
->op
= OP_UMOREEQ
; break;
9856 case OP_SMORE
: rhs
->op
= OP_SLESSEQ
; break;
9857 case OP_UMORE
: rhs
->op
= OP_ULESSEQ
; break;
9858 case OP_SLESSEQ
: rhs
->op
= OP_SMORE
; break;
9859 case OP_ULESSEQ
: rhs
->op
= OP_UMORE
; break;
9860 case OP_SMOREEQ
: rhs
->op
= OP_SLESS
; break;
9861 case OP_UMOREEQ
: rhs
->op
= OP_ULESS
; break;
9867 mkcopy(state
, ins
, rhs
);
9872 static void simplify_ltrue (struct compile_state
*state
, struct triple
*ins
)
9877 if (is_const(rhs
)) {
9878 mkconst(state
, ins
, const_ltrue(state
, ins
, rhs
));
9880 else switch(rhs
->op
) {
9881 case OP_LTRUE
: case OP_LFALSE
: case OP_EQ
: case OP_NOTEQ
:
9882 case OP_SLESS
: case OP_ULESS
: case OP_SMORE
: case OP_UMORE
:
9883 case OP_SLESSEQ
: case OP_ULESSEQ
: case OP_SMOREEQ
: case OP_UMOREEQ
:
9884 mkcopy(state
, ins
, rhs
);
9889 static void simplify_load(struct compile_state
*state
, struct triple
*ins
)
9891 struct triple
*addr
, *sdecl
, *blob
;
9893 /* If I am doing a load with a constant pointer from a constant
9894 * table get the value.
9897 if ((addr
->op
== OP_ADDRCONST
) && (sdecl
= MISC(addr
, 0)) &&
9898 (sdecl
->op
== OP_SDECL
) && (blob
= MISC(sdecl
, 0)) &&
9899 (blob
->op
== OP_BLOBCONST
)) {
9900 unsigned char buffer
[SIZEOF_WORD
];
9901 size_t reg_size
, mem_size
;
9902 const char *src
, *end
;
9904 reg_size
= reg_size_of(state
, ins
->type
);
9905 if (reg_size
> REG_SIZEOF_REG
) {
9906 internal_error(state
, ins
, "load size greater than register");
9908 mem_size
= size_of(state
, ins
->type
);
9910 end
+= bits_to_bytes(size_of(state
, sdecl
->type
));
9912 src
+= addr
->u
.cval
;
9915 error(state
, ins
, "Load address out of bounds");
9918 memset(buffer
, 0, sizeof(buffer
));
9919 memcpy(buffer
, src
, bits_to_bytes(mem_size
));
9922 case SIZEOF_I8
: val
= *((uint8_t *) buffer
); break;
9923 case SIZEOF_I16
: val
= *((uint16_t *)buffer
); break;
9924 case SIZEOF_I32
: val
= *((uint32_t *)buffer
); break;
9925 case SIZEOF_I64
: val
= *((uint64_t *)buffer
); break;
9927 internal_error(state
, ins
, "mem_size: %d not handled",
9932 mkconst(state
, ins
, val
);
9936 static void simplify_uextract(struct compile_state
*state
, struct triple
*ins
)
9938 if (is_simple_const(RHS(ins
, 0))) {
9941 val
= read_const(state
, ins
, RHS(ins
, 0));
9943 mask
<<= ins
->u
.bitfield
.size
;
9945 val
>>= ins
->u
.bitfield
.offset
;
9947 mkconst(state
, ins
, val
);
9951 static void simplify_sextract(struct compile_state
*state
, struct triple
*ins
)
9953 if (is_simple_const(RHS(ins
, 0))) {
9957 val
= read_const(state
, ins
, RHS(ins
, 0));
9959 mask
<<= ins
->u
.bitfield
.size
;
9961 val
>>= ins
->u
.bitfield
.offset
;
9963 val
<<= (SIZEOF_LONG
- ins
->u
.bitfield
.size
);
9965 sval
>>= (SIZEOF_LONG
- ins
->u
.bitfield
.size
);
9966 mkconst(state
, ins
, sval
);
9970 static void simplify_deposit(struct compile_state
*state
, struct triple
*ins
)
9972 if (is_simple_const(RHS(ins
, 0)) && is_simple_const(RHS(ins
, 1))) {
9975 targ
= read_const(state
, ins
, RHS(ins
, 0));
9976 val
= read_const(state
, ins
, RHS(ins
, 1));
9978 mask
<<= ins
->u
.bitfield
.size
;
9980 mask
<<= ins
->u
.bitfield
.offset
;
9982 val
<<= ins
->u
.bitfield
.offset
;
9985 mkconst(state
, ins
, targ
);
9989 static void simplify_copy(struct compile_state
*state
, struct triple
*ins
)
9991 struct triple
*right
;
9992 right
= RHS(ins
, 0);
9993 if (is_subset_type(ins
->type
, right
->type
)) {
9994 ins
->type
= right
->type
;
9996 if (equiv_types(ins
->type
, right
->type
)) {
9997 ins
->op
= OP_COPY
;/* I don't need to convert if the types match */
9999 if (ins
->op
== OP_COPY
) {
10000 internal_error(state
, ins
, "type mismatch on copy");
10003 if (is_const(right
) && (right
->op
== OP_ADDRCONST
) && is_pointer(ins
)) {
10004 struct triple
*sdecl
;
10006 sdecl
= MISC(right
, 0);
10007 offset
= right
->u
.cval
;
10008 mkaddr_const(state
, ins
, sdecl
, offset
);
10010 else if (is_const(right
) && is_write_compatible(state
, ins
->type
, right
->type
)) {
10011 switch(right
->op
) {
10015 left
= read_const(state
, ins
, right
);
10016 /* Ensure I have not overflowed the destination. */
10017 if (size_of(state
, right
->type
) > size_of(state
, ins
->type
)) {
10020 mask
<<= size_of(state
, ins
->type
);
10024 /* Ensure I am properly sign extended */
10025 if (size_of(state
, right
->type
) < size_of(state
, ins
->type
) &&
10026 is_signed(right
->type
)) {
10029 shift
= SIZEOF_LONG
- size_of(state
, right
->type
);
10035 mkconst(state
, ins
, left
);
10039 internal_error(state
, ins
, "uknown constant");
10045 static int phi_present(struct block
*block
)
10047 struct triple
*ptr
;
10051 ptr
= block
->first
;
10053 if (ptr
->op
== OP_PHI
) {
10057 } while(ptr
!= block
->last
);
10061 static int phi_dependency(struct block
*block
)
10063 /* A block has a phi dependency if a phi function
10064 * depends on that block to exist, and makes a block
10065 * that is otherwise useless unsafe to remove.
10068 struct block_set
*edge
;
10069 for(edge
= block
->edges
; edge
; edge
= edge
->next
) {
10070 if (phi_present(edge
->member
)) {
10078 static struct triple
*branch_target(struct compile_state
*state
, struct triple
*ins
)
10080 struct triple
*targ
;
10081 targ
= TARG(ins
, 0);
10082 /* During scc_transform temporary triples are allocated that
10083 * loop back onto themselves. If I see one don't advance the
10086 while(triple_is_structural(state
, targ
) &&
10087 (targ
->next
!= targ
) && (targ
->next
!= state
->first
)) {
10094 static void simplify_branch(struct compile_state
*state
, struct triple
*ins
)
10096 int simplified
, loops
;
10097 if ((ins
->op
!= OP_BRANCH
) && (ins
->op
!= OP_CBRANCH
)) {
10098 internal_error(state
, ins
, "not branch");
10100 if (ins
->use
!= 0) {
10101 internal_error(state
, ins
, "branch use");
10103 /* The challenge here with simplify branch is that I need to
10104 * make modifications to the control flow graph as well
10105 * as to the branch instruction itself. That is handled
10106 * by rebuilding the basic blocks after simplify all is called.
10109 /* If we have a branch to an unconditional branch update
10110 * our target. But watch out for dependencies from phi
10112 * Also only do this a limited number of times so
10113 * we don't get into an infinite loop.
10117 struct triple
*targ
;
10119 targ
= branch_target(state
, ins
);
10120 if ((targ
!= ins
) && (targ
->op
== OP_BRANCH
) &&
10121 !phi_dependency(targ
->u
.block
))
10123 unuse_triple(TARG(ins
, 0), ins
);
10124 TARG(ins
, 0) = TARG(targ
, 0);
10125 use_triple(TARG(ins
, 0), ins
);
10128 } while(simplified
&& (++loops
< 20));
10130 /* If we have a conditional branch with a constant condition
10131 * make it an unconditional branch.
10133 if ((ins
->op
== OP_CBRANCH
) && is_simple_const(RHS(ins
, 0))) {
10134 struct triple
*targ
;
10136 value
= read_const(state
, ins
, RHS(ins
, 0));
10137 unuse_triple(RHS(ins
, 0), ins
);
10138 targ
= TARG(ins
, 0);
10141 ins
->op
= OP_BRANCH
;
10143 unuse_triple(ins
->next
, ins
);
10144 TARG(ins
, 0) = targ
;
10147 unuse_triple(targ
, ins
);
10148 TARG(ins
, 0) = ins
->next
;
10152 /* If we have a branch to the next instruction,
10155 if (TARG(ins
, 0) == ins
->next
) {
10156 unuse_triple(TARG(ins
, 0), ins
);
10157 if (ins
->op
== OP_CBRANCH
) {
10158 unuse_triple(RHS(ins
, 0), ins
);
10159 unuse_triple(ins
->next
, ins
);
10167 internal_error(state
, ins
, "noop use != 0");
10172 static void simplify_label(struct compile_state
*state
, struct triple
*ins
)
10174 /* Ignore volatile labels */
10175 if (!triple_is_pure(state
, ins
, ins
->id
)) {
10178 if (ins
->use
== 0) {
10181 else if (ins
->prev
->op
== OP_LABEL
) {
10182 /* In general it is not safe to merge one label that
10183 * imediately follows another. The problem is that the empty
10184 * looking block may have phi functions that depend on it.
10186 if (!phi_dependency(ins
->prev
->u
.block
)) {
10187 struct triple_set
*user
, *next
;
10189 for(user
= ins
->use
; user
; user
= next
) {
10190 struct triple
*use
, **expr
;
10192 use
= user
->member
;
10193 expr
= triple_targ(state
, use
, 0);
10194 for(;expr
; expr
= triple_targ(state
, use
, expr
)) {
10195 if (*expr
== ins
) {
10197 unuse_triple(ins
, use
);
10198 use_triple(ins
->prev
, use
);
10204 internal_error(state
, ins
, "noop use != 0");
10210 static void simplify_phi(struct compile_state
*state
, struct triple
*ins
)
10212 struct triple
**slot
;
10213 struct triple
*value
;
10216 slot
= &RHS(ins
, 0);
10221 /* See if all of the rhs members of a phi have the same value */
10222 if (slot
[0] && is_simple_const(slot
[0])) {
10223 cvalue
= read_const(state
, ins
, slot
[0]);
10224 for(i
= 1; i
< zrhs
; i
++) {
10226 !is_simple_const(slot
[i
]) ||
10227 !equiv_types(slot
[0]->type
, slot
[i
]->type
) ||
10228 (cvalue
!= read_const(state
, ins
, slot
[i
]))) {
10233 mkconst(state
, ins
, cvalue
);
10238 /* See if all of rhs members of a phi are the same */
10240 for(i
= 1; i
< zrhs
; i
++) {
10241 if (slot
[i
] != value
) {
10246 /* If the phi has a single value just copy it */
10247 if (!is_subset_type(ins
->type
, value
->type
)) {
10248 internal_error(state
, ins
, "bad input type to phi");
10250 /* Make the types match */
10251 if (!equiv_types(ins
->type
, value
->type
)) {
10252 ins
->type
= value
->type
;
10254 /* Now make the actual copy */
10255 mkcopy(state
, ins
, value
);
10261 static void simplify_bsf(struct compile_state
*state
, struct triple
*ins
)
10263 if (is_simple_const(RHS(ins
, 0))) {
10265 left
= read_const(state
, ins
, RHS(ins
, 0));
10266 mkconst(state
, ins
, bsf(left
));
10270 static void simplify_bsr(struct compile_state
*state
, struct triple
*ins
)
10272 if (is_simple_const(RHS(ins
, 0))) {
10274 left
= read_const(state
, ins
, RHS(ins
, 0));
10275 mkconst(state
, ins
, bsr(left
));
10280 typedef void (*simplify_t
)(struct compile_state
*state
, struct triple
*ins
);
10281 static const struct simplify_table
{
10283 unsigned long flag
;
10284 } table_simplify
[] = {
10285 #define simplify_sdivt simplify_noop
10286 #define simplify_udivt simplify_noop
10287 #define simplify_piece simplify_noop
10289 [OP_SDIVT
] = { simplify_sdivt
, COMPILER_SIMPLIFY_ARITH
},
10290 [OP_UDIVT
] = { simplify_udivt
, COMPILER_SIMPLIFY_ARITH
},
10291 [OP_SMUL
] = { simplify_smul
, COMPILER_SIMPLIFY_ARITH
},
10292 [OP_UMUL
] = { simplify_umul
, COMPILER_SIMPLIFY_ARITH
},
10293 [OP_SDIV
] = { simplify_sdiv
, COMPILER_SIMPLIFY_ARITH
},
10294 [OP_UDIV
] = { simplify_udiv
, COMPILER_SIMPLIFY_ARITH
},
10295 [OP_SMOD
] = { simplify_smod
, COMPILER_SIMPLIFY_ARITH
},
10296 [OP_UMOD
] = { simplify_umod
, COMPILER_SIMPLIFY_ARITH
},
10297 [OP_ADD
] = { simplify_add
, COMPILER_SIMPLIFY_ARITH
},
10298 [OP_SUB
] = { simplify_sub
, COMPILER_SIMPLIFY_ARITH
},
10299 [OP_SL
] = { simplify_sl
, COMPILER_SIMPLIFY_SHIFT
},
10300 [OP_USR
] = { simplify_usr
, COMPILER_SIMPLIFY_SHIFT
},
10301 [OP_SSR
] = { simplify_ssr
, COMPILER_SIMPLIFY_SHIFT
},
10302 [OP_AND
] = { simplify_and
, COMPILER_SIMPLIFY_BITWISE
},
10303 [OP_XOR
] = { simplify_xor
, COMPILER_SIMPLIFY_BITWISE
},
10304 [OP_OR
] = { simplify_or
, COMPILER_SIMPLIFY_BITWISE
},
10305 [OP_POS
] = { simplify_pos
, COMPILER_SIMPLIFY_ARITH
},
10306 [OP_NEG
] = { simplify_neg
, COMPILER_SIMPLIFY_ARITH
},
10307 [OP_INVERT
] = { simplify_invert
, COMPILER_SIMPLIFY_BITWISE
},
10309 [OP_EQ
] = { simplify_eq
, COMPILER_SIMPLIFY_LOGICAL
},
10310 [OP_NOTEQ
] = { simplify_noteq
, COMPILER_SIMPLIFY_LOGICAL
},
10311 [OP_SLESS
] = { simplify_sless
, COMPILER_SIMPLIFY_LOGICAL
},
10312 [OP_ULESS
] = { simplify_uless
, COMPILER_SIMPLIFY_LOGICAL
},
10313 [OP_SMORE
] = { simplify_smore
, COMPILER_SIMPLIFY_LOGICAL
},
10314 [OP_UMORE
] = { simplify_umore
, COMPILER_SIMPLIFY_LOGICAL
},
10315 [OP_SLESSEQ
] = { simplify_slesseq
, COMPILER_SIMPLIFY_LOGICAL
},
10316 [OP_ULESSEQ
] = { simplify_ulesseq
, COMPILER_SIMPLIFY_LOGICAL
},
10317 [OP_SMOREEQ
] = { simplify_smoreeq
, COMPILER_SIMPLIFY_LOGICAL
},
10318 [OP_UMOREEQ
] = { simplify_umoreeq
, COMPILER_SIMPLIFY_LOGICAL
},
10319 [OP_LFALSE
] = { simplify_lfalse
, COMPILER_SIMPLIFY_LOGICAL
},
10320 [OP_LTRUE
] = { simplify_ltrue
, COMPILER_SIMPLIFY_LOGICAL
},
10322 [OP_LOAD
] = { simplify_load
, COMPILER_SIMPLIFY_OP
},
10323 [OP_STORE
] = { simplify_noop
, COMPILER_SIMPLIFY_OP
},
10325 [OP_UEXTRACT
] = { simplify_uextract
, COMPILER_SIMPLIFY_BITFIELD
},
10326 [OP_SEXTRACT
] = { simplify_sextract
, COMPILER_SIMPLIFY_BITFIELD
},
10327 [OP_DEPOSIT
] = { simplify_deposit
, COMPILER_SIMPLIFY_BITFIELD
},
10329 [OP_NOOP
] = { simplify_noop
, COMPILER_SIMPLIFY_OP
},
10331 [OP_INTCONST
] = { simplify_noop
, COMPILER_SIMPLIFY_OP
},
10332 [OP_BLOBCONST
] = { simplify_noop
, COMPILER_SIMPLIFY_OP
},
10333 [OP_ADDRCONST
] = { simplify_noop
, COMPILER_SIMPLIFY_OP
},
10334 [OP_UNKNOWNVAL
] = { simplify_noop
, COMPILER_SIMPLIFY_OP
},
10336 [OP_WRITE
] = { simplify_noop
, COMPILER_SIMPLIFY_OP
},
10337 [OP_READ
] = { simplify_noop
, COMPILER_SIMPLIFY_OP
},
10338 [OP_COPY
] = { simplify_copy
, COMPILER_SIMPLIFY_COPY
},
10339 [OP_CONVERT
] = { simplify_copy
, COMPILER_SIMPLIFY_COPY
},
10340 [OP_PIECE
] = { simplify_piece
, COMPILER_SIMPLIFY_OP
},
10341 [OP_ASM
] = { simplify_noop
, COMPILER_SIMPLIFY_OP
},
10343 [OP_DOT
] = { simplify_noop
, COMPILER_SIMPLIFY_OP
},
10344 [OP_INDEX
] = { simplify_noop
, COMPILER_SIMPLIFY_OP
},
10346 [OP_LIST
] = { simplify_noop
, COMPILER_SIMPLIFY_OP
},
10347 [OP_BRANCH
] = { simplify_branch
, COMPILER_SIMPLIFY_BRANCH
},
10348 [OP_CBRANCH
] = { simplify_branch
, COMPILER_SIMPLIFY_BRANCH
},
10349 [OP_CALL
] = { simplify_noop
, COMPILER_SIMPLIFY_BRANCH
},
10350 [OP_RET
] = { simplify_noop
, COMPILER_SIMPLIFY_BRANCH
},
10351 [OP_LABEL
] = { simplify_label
, COMPILER_SIMPLIFY_LABEL
},
10352 [OP_ADECL
] = { simplify_noop
, COMPILER_SIMPLIFY_OP
},
10353 [OP_SDECL
] = { simplify_noop
, COMPILER_SIMPLIFY_OP
},
10354 [OP_PHI
] = { simplify_phi
, COMPILER_SIMPLIFY_PHI
},
10356 [OP_INB
] = { simplify_noop
, COMPILER_SIMPLIFY_OP
},
10357 [OP_INW
] = { simplify_noop
, COMPILER_SIMPLIFY_OP
},
10358 [OP_INL
] = { simplify_noop
, COMPILER_SIMPLIFY_OP
},
10359 [OP_OUTB
] = { simplify_noop
, COMPILER_SIMPLIFY_OP
},
10360 [OP_OUTW
] = { simplify_noop
, COMPILER_SIMPLIFY_OP
},
10361 [OP_OUTL
] = { simplify_noop
, COMPILER_SIMPLIFY_OP
},
10362 [OP_BSF
] = { simplify_bsf
, COMPILER_SIMPLIFY_OP
},
10363 [OP_BSR
] = { simplify_bsr
, COMPILER_SIMPLIFY_OP
},
10364 [OP_RDMSR
] = { simplify_noop
, COMPILER_SIMPLIFY_OP
},
10365 [OP_WRMSR
] = { simplify_noop
, COMPILER_SIMPLIFY_OP
},
10366 [OP_HLT
] = { simplify_noop
, COMPILER_SIMPLIFY_OP
},
10369 static inline void debug_simplify(struct compile_state
*state
,
10370 simplify_t do_simplify
, struct triple
*ins
)
10372 #if DEBUG_SIMPLIFY_HIRES
10373 if (state
->functions_joined
&& (do_simplify
!= simplify_noop
)) {
10374 /* High resolution debugging mode */
10375 fprintf(state
->dbgout
, "simplifing: ");
10376 display_triple(state
->dbgout
, ins
);
10379 do_simplify(state
, ins
);
10380 #if DEBUG_SIMPLIFY_HIRES
10381 if (state
->functions_joined
&& (do_simplify
!= simplify_noop
)) {
10382 /* High resolution debugging mode */
10383 fprintf(state
->dbgout
, "simplified: ");
10384 display_triple(state
->dbgout
, ins
);
10388 static void simplify(struct compile_state
*state
, struct triple
*ins
)
10391 simplify_t do_simplify
;
10392 if (ins
== &unknown_triple
) {
10393 internal_error(state
, ins
, "simplifying the unknown triple?");
10398 if ((op
< 0) || (op
>= sizeof(table_simplify
)/sizeof(table_simplify
[0]))) {
10402 do_simplify
= table_simplify
[op
].func
;
10405 !(state
->compiler
->flags
& table_simplify
[op
].flag
)) {
10406 do_simplify
= simplify_noop
;
10408 if (do_simplify
&& (ins
->id
& TRIPLE_FLAG_VOLATILE
)) {
10409 do_simplify
= simplify_noop
;
10412 if (!do_simplify
) {
10413 internal_error(state
, ins
, "cannot simplify op: %d %s",
10417 debug_simplify(state
, do_simplify
, ins
);
10418 } while(ins
->op
!= op
);
10421 static void rebuild_ssa_form(struct compile_state
*state
);
10423 static void simplify_all(struct compile_state
*state
)
10425 struct triple
*ins
, *first
;
10426 if (!(state
->compiler
->flags
& COMPILER_SIMPLIFY
)) {
10429 first
= state
->first
;
10432 simplify(state
, ins
);
10434 } while(ins
!= first
->prev
);
10437 simplify(state
, ins
);
10439 }while(ins
!= first
);
10440 rebuild_ssa_form(state
);
10442 print_blocks(state
, __func__
, state
->dbgout
);
10447 * ============================
10450 static void register_builtin_function(struct compile_state
*state
,
10451 const char *name
, int op
, struct type
*rtype
, ...)
10453 struct type
*ftype
, *atype
, *ctype
, *crtype
, *param
, **next
;
10454 struct triple
*def
, *result
, *work
, *first
, *retvar
, *ret
;
10455 struct hash_entry
*ident
;
10456 struct file_state file
;
10462 /* Dummy file state to get debug handling right */
10463 memset(&file
, 0, sizeof(file
));
10464 file
.basename
= "<built-in>";
10466 file
.report_line
= 1;
10467 file
.report_name
= file
.basename
;
10468 file
.prev
= state
->file
;
10469 state
->file
= &file
;
10470 state
->function
= name
;
10472 /* Find the Parameter count */
10473 valid_op(state
, op
);
10474 parameters
= table_ops
[op
].rhs
;
10475 if (parameters
< 0 ) {
10476 internal_error(state
, 0, "Invalid builtin parameter count");
10479 /* Find the function type */
10480 ftype
= new_type(TYPE_FUNCTION
| STOR_INLINE
| STOR_STATIC
, rtype
, 0);
10481 ftype
->elements
= parameters
;
10482 next
= &ftype
->right
;
10483 va_start(args
, rtype
);
10484 for(i
= 0; i
< parameters
; i
++) {
10485 atype
= va_arg(args
, struct type
*);
10489 *next
= new_type(TYPE_PRODUCT
, *next
, atype
);
10490 next
= &((*next
)->right
);
10494 *next
= &void_type
;
10498 /* Get the initial closure type */
10499 ctype
= new_type(TYPE_JOIN
, &void_type
, 0);
10500 ctype
->elements
= 1;
10502 /* Get the return type */
10503 crtype
= new_type(TYPE_TUPLE
, new_type(TYPE_PRODUCT
, ctype
, rtype
), 0);
10504 crtype
->elements
= 2;
10506 /* Generate the needed triples */
10507 def
= triple(state
, OP_LIST
, ftype
, 0, 0);
10508 first
= label(state
);
10509 RHS(def
, 0) = first
;
10510 result
= flatten(state
, first
, variable(state
, crtype
));
10511 retvar
= flatten(state
, first
, variable(state
, &void_ptr_type
));
10512 ret
= triple(state
, OP_RET
, &void_type
, read_expr(state
, retvar
), 0);
10514 /* Now string them together */
10515 param
= ftype
->right
;
10516 for(i
= 0; i
< parameters
; i
++) {
10517 if ((param
->type
& TYPE_MASK
) == TYPE_PRODUCT
) {
10518 atype
= param
->left
;
10522 flatten(state
, first
, variable(state
, atype
));
10523 param
= param
->right
;
10525 work
= new_triple(state
, op
, rtype
, -1, parameters
);
10526 generate_lhs_pieces(state
, work
);
10527 for(i
= 0; i
< parameters
; i
++) {
10528 RHS(work
, i
) = read_expr(state
, farg(state
, def
, i
));
10530 if ((rtype
->type
& TYPE_MASK
) != TYPE_VOID
) {
10531 work
= write_expr(state
, deref_index(state
, result
, 1), work
);
10533 work
= flatten(state
, first
, work
);
10534 flatten(state
, first
, label(state
));
10535 ret
= flatten(state
, first
, ret
);
10536 name_len
= strlen(name
);
10537 ident
= lookup(state
, name
, name_len
);
10538 ftype
->type_ident
= ident
;
10539 symbol(state
, ident
, &ident
->sym_ident
, def
, ftype
);
10541 state
->file
= file
.prev
;
10542 state
->function
= 0;
10543 state
->main_function
= 0;
10545 if (!state
->functions
) {
10546 state
->functions
= def
;
10548 insert_triple(state
, state
->functions
, def
);
10550 if (state
->compiler
->debug
& DEBUG_INLINE
) {
10551 FILE *fp
= state
->dbgout
;
10554 fprintf(fp
, "\n__________ %s _________\n", __FUNCTION__
);
10555 display_func(state
, fp
, def
);
10556 fprintf(fp
, "__________ %s _________ done\n\n", __FUNCTION__
);
10560 static struct type
*partial_struct(struct compile_state
*state
,
10561 const char *field_name
, struct type
*type
, struct type
*rest
)
10563 struct hash_entry
*field_ident
;
10564 struct type
*result
;
10565 int field_name_len
;
10567 field_name_len
= strlen(field_name
);
10568 field_ident
= lookup(state
, field_name
, field_name_len
);
10570 result
= clone_type(0, type
);
10571 result
->field_ident
= field_ident
;
10574 result
= new_type(TYPE_PRODUCT
, result
, rest
);
10579 static struct type
*register_builtin_type(struct compile_state
*state
,
10580 const char *name
, struct type
*type
)
10582 struct hash_entry
*ident
;
10585 name_len
= strlen(name
);
10586 ident
= lookup(state
, name
, name_len
);
10588 if ((type
->type
& TYPE_MASK
) == TYPE_PRODUCT
) {
10589 ulong_t elements
= 0;
10590 struct type
*field
;
10591 type
= new_type(TYPE_STRUCT
, type
, 0);
10592 field
= type
->left
;
10593 while((field
->type
& TYPE_MASK
) == TYPE_PRODUCT
) {
10595 field
= field
->right
;
10598 symbol(state
, ident
, &ident
->sym_tag
, 0, type
);
10599 type
->type_ident
= ident
;
10600 type
->elements
= elements
;
10602 symbol(state
, ident
, &ident
->sym_ident
, 0, type
);
10603 ident
->tok
= TOK_TYPE_NAME
;
10608 static void register_builtins(struct compile_state
*state
)
10610 struct type
*div_type
, *ldiv_type
;
10611 struct type
*udiv_type
, *uldiv_type
;
10612 struct type
*msr_type
;
10614 div_type
= register_builtin_type(state
, "__builtin_div_t",
10615 partial_struct(state
, "quot", &int_type
,
10616 partial_struct(state
, "rem", &int_type
, 0)));
10617 ldiv_type
= register_builtin_type(state
, "__builtin_ldiv_t",
10618 partial_struct(state
, "quot", &long_type
,
10619 partial_struct(state
, "rem", &long_type
, 0)));
10620 udiv_type
= register_builtin_type(state
, "__builtin_udiv_t",
10621 partial_struct(state
, "quot", &uint_type
,
10622 partial_struct(state
, "rem", &uint_type
, 0)));
10623 uldiv_type
= register_builtin_type(state
, "__builtin_uldiv_t",
10624 partial_struct(state
, "quot", &ulong_type
,
10625 partial_struct(state
, "rem", &ulong_type
, 0)));
10627 register_builtin_function(state
, "__builtin_div", OP_SDIVT
, div_type
,
10628 &int_type
, &int_type
);
10629 register_builtin_function(state
, "__builtin_ldiv", OP_SDIVT
, ldiv_type
,
10630 &long_type
, &long_type
);
10631 register_builtin_function(state
, "__builtin_udiv", OP_UDIVT
, udiv_type
,
10632 &uint_type
, &uint_type
);
10633 register_builtin_function(state
, "__builtin_uldiv", OP_UDIVT
, uldiv_type
,
10634 &ulong_type
, &ulong_type
);
10636 register_builtin_function(state
, "__builtin_inb", OP_INB
, &uchar_type
,
10638 register_builtin_function(state
, "__builtin_inw", OP_INW
, &ushort_type
,
10640 register_builtin_function(state
, "__builtin_inl", OP_INL
, &uint_type
,
10643 register_builtin_function(state
, "__builtin_outb", OP_OUTB
, &void_type
,
10644 &uchar_type
, &ushort_type
);
10645 register_builtin_function(state
, "__builtin_outw", OP_OUTW
, &void_type
,
10646 &ushort_type
, &ushort_type
);
10647 register_builtin_function(state
, "__builtin_outl", OP_OUTL
, &void_type
,
10648 &uint_type
, &ushort_type
);
10650 register_builtin_function(state
, "__builtin_bsf", OP_BSF
, &int_type
,
10652 register_builtin_function(state
, "__builtin_bsr", OP_BSR
, &int_type
,
10655 msr_type
= register_builtin_type(state
, "__builtin_msr_t",
10656 partial_struct(state
, "lo", &ulong_type
,
10657 partial_struct(state
, "hi", &ulong_type
, 0)));
10659 register_builtin_function(state
, "__builtin_rdmsr", OP_RDMSR
, msr_type
,
10661 register_builtin_function(state
, "__builtin_wrmsr", OP_WRMSR
, &void_type
,
10662 &ulong_type
, &ulong_type
, &ulong_type
);
10664 register_builtin_function(state
, "__builtin_hlt", OP_HLT
, &void_type
,
10668 static struct type
*declarator(
10669 struct compile_state
*state
, struct type
*type
,
10670 struct hash_entry
**ident
, int need_ident
);
10671 static void decl(struct compile_state
*state
, struct triple
*first
);
10672 static struct type
*specifier_qualifier_list(struct compile_state
*state
);
10673 #if DEBUG_ROMCC_WARNING
10674 static int isdecl_specifier(int tok
);
10676 static struct type
*decl_specifiers(struct compile_state
*state
);
10677 static int istype(int tok
);
10678 static struct triple
*expr(struct compile_state
*state
);
10679 static struct triple
*assignment_expr(struct compile_state
*state
);
10680 static struct type
*type_name(struct compile_state
*state
);
10681 static void statement(struct compile_state
*state
, struct triple
*first
);
10683 static struct triple
*call_expr(
10684 struct compile_state
*state
, struct triple
*func
)
10686 struct triple
*def
;
10687 struct type
*param
, *type
;
10688 ulong_t pvals
, index
;
10690 if ((func
->type
->type
& TYPE_MASK
) != TYPE_FUNCTION
) {
10691 error(state
, 0, "Called object is not a function");
10693 if (func
->op
!= OP_LIST
) {
10694 internal_error(state
, 0, "improper function");
10696 eat(state
, TOK_LPAREN
);
10697 /* Find the return type without any specifiers */
10698 type
= clone_type(0, func
->type
->left
);
10699 /* Count the number of rhs entries for OP_FCALL */
10700 param
= func
->type
->right
;
10702 while((param
->type
& TYPE_MASK
) == TYPE_PRODUCT
) {
10704 param
= param
->right
;
10706 if ((param
->type
& TYPE_MASK
) != TYPE_VOID
) {
10709 def
= new_triple(state
, OP_FCALL
, type
, -1, pvals
);
10710 MISC(def
, 0) = func
;
10712 param
= func
->type
->right
;
10713 for(index
= 0; index
< pvals
; index
++) {
10714 struct triple
*val
;
10715 struct type
*arg_type
;
10716 val
= read_expr(state
, assignment_expr(state
));
10718 if ((param
->type
& TYPE_MASK
) == TYPE_PRODUCT
) {
10719 arg_type
= param
->left
;
10721 write_compatible(state
, arg_type
, val
->type
);
10722 RHS(def
, index
) = val
;
10723 if (index
!= (pvals
- 1)) {
10724 eat(state
, TOK_COMMA
);
10725 param
= param
->right
;
10728 eat(state
, TOK_RPAREN
);
10733 static struct triple
*character_constant(struct compile_state
*state
)
10735 struct triple
*def
;
10737 const signed char *str
, *end
;
10740 tk
= eat(state
, TOK_LIT_CHAR
);
10741 str
= (signed char *)tk
->val
.str
+ 1;
10742 str_len
= tk
->str_len
- 2;
10743 if (str_len
<= 0) {
10744 error(state
, 0, "empty character constant");
10746 end
= str
+ str_len
;
10747 c
= char_value(state
, &str
, end
);
10749 error(state
, 0, "multibyte character constant not supported");
10751 def
= int_const(state
, &char_type
, (ulong_t
)((long_t
)c
));
10755 static struct triple
*string_constant(struct compile_state
*state
)
10757 struct triple
*def
;
10760 const signed char *str
, *end
;
10761 signed char *buf
, *ptr
;
10765 type
= new_type(TYPE_ARRAY
, &char_type
, 0);
10766 type
->elements
= 0;
10767 /* The while loop handles string concatenation */
10769 tk
= eat(state
, TOK_LIT_STRING
);
10770 str
= (signed char *)tk
->val
.str
+ 1;
10771 str_len
= tk
->str_len
- 2;
10773 error(state
, 0, "negative string constant length");
10775 /* ignore empty string tokens */
10776 if ('"' == *str
&& 0 == str
[1])
10778 end
= str
+ str_len
;
10780 buf
= xmalloc(type
->elements
+ str_len
+ 1, "string_constant");
10781 memcpy(buf
, ptr
, type
->elements
);
10782 ptr
= buf
+ type
->elements
;
10784 *ptr
++ = char_value(state
, &str
, end
);
10785 } while(str
< end
);
10786 type
->elements
= ptr
- buf
;
10787 } while(peek(state
) == TOK_LIT_STRING
);
10789 type
->elements
+= 1;
10790 def
= triple(state
, OP_BLOBCONST
, type
, 0, 0);
10797 static struct triple
*integer_constant(struct compile_state
*state
)
10799 struct triple
*def
;
10806 tk
= eat(state
, TOK_LIT_INT
);
10808 decimal
= (tk
->val
.str
[0] != '0');
10809 val
= strtoul(tk
->val
.str
, &end
, 0);
10810 if (errno
== ERANGE
) {
10811 error(state
, 0, "Integer constant out of range");
10814 if ((*end
== 'u') || (*end
== 'U')) {
10818 if ((*end
== 'l') || (*end
== 'L')) {
10822 if ((*end
== 'u') || (*end
== 'U')) {
10827 error(state
, 0, "Junk at end of integer constant");
10830 type
= &ulong_type
;
10834 if (!decimal
&& (val
> LONG_T_MAX
)) {
10835 type
= &ulong_type
;
10840 if (val
> UINT_T_MAX
) {
10841 type
= &ulong_type
;
10846 if (!decimal
&& (val
> INT_T_MAX
) && (val
<= UINT_T_MAX
)) {
10849 else if (!decimal
&& (val
> LONG_T_MAX
)) {
10850 type
= &ulong_type
;
10852 else if (val
> INT_T_MAX
) {
10856 def
= int_const(state
, type
, val
);
10860 static struct triple
*primary_expr(struct compile_state
*state
)
10862 struct triple
*def
;
10868 struct hash_entry
*ident
;
10869 /* Here ident is either:
10873 ident
= eat(state
, TOK_IDENT
)->ident
;
10874 if (!ident
->sym_ident
) {
10875 error(state
, 0, "%s undeclared", ident
->name
);
10877 def
= ident
->sym_ident
->def
;
10880 case TOK_ENUM_CONST
:
10882 struct hash_entry
*ident
;
10883 /* Here ident is an enumeration constant */
10884 ident
= eat(state
, TOK_ENUM_CONST
)->ident
;
10885 if (!ident
->sym_ident
) {
10886 error(state
, 0, "%s undeclared", ident
->name
);
10888 def
= ident
->sym_ident
->def
;
10893 struct hash_entry
*ident
;
10894 ident
= eat(state
, TOK_MIDENT
)->ident
;
10895 warning(state
, 0, "Replacing undefined macro: %s with 0",
10897 def
= int_const(state
, &int_type
, 0);
10901 eat(state
, TOK_LPAREN
);
10903 eat(state
, TOK_RPAREN
);
10906 def
= integer_constant(state
);
10908 case TOK_LIT_FLOAT
:
10909 eat(state
, TOK_LIT_FLOAT
);
10910 error(state
, 0, "Floating point constants not supported");
10915 def
= character_constant(state
);
10917 case TOK_LIT_STRING
:
10918 def
= string_constant(state
);
10922 error(state
, 0, "Unexpected token: %s\n", tokens
[tok
]);
10927 static struct triple
*postfix_expr(struct compile_state
*state
)
10929 struct triple
*def
;
10931 def
= primary_expr(state
);
10933 struct triple
*left
;
10937 switch((tok
= peek(state
))) {
10939 eat(state
, TOK_LBRACKET
);
10940 def
= mk_subscript_expr(state
, left
, expr(state
));
10941 eat(state
, TOK_RBRACKET
);
10944 def
= call_expr(state
, def
);
10948 struct hash_entry
*field
;
10949 eat(state
, TOK_DOT
);
10950 field
= eat(state
, TOK_IDENT
)->ident
;
10951 def
= deref_field(state
, def
, field
);
10956 struct hash_entry
*field
;
10957 eat(state
, TOK_ARROW
);
10958 field
= eat(state
, TOK_IDENT
)->ident
;
10959 def
= mk_deref_expr(state
, read_expr(state
, def
));
10960 def
= deref_field(state
, def
, field
);
10964 eat(state
, TOK_PLUSPLUS
);
10965 def
= mk_post_inc_expr(state
, left
);
10967 case TOK_MINUSMINUS
:
10968 eat(state
, TOK_MINUSMINUS
);
10969 def
= mk_post_dec_expr(state
, left
);
10979 static struct triple
*cast_expr(struct compile_state
*state
);
10981 static struct triple
*unary_expr(struct compile_state
*state
)
10983 struct triple
*def
, *right
;
10985 switch((tok
= peek(state
))) {
10987 eat(state
, TOK_PLUSPLUS
);
10988 def
= mk_pre_inc_expr(state
, unary_expr(state
));
10990 case TOK_MINUSMINUS
:
10991 eat(state
, TOK_MINUSMINUS
);
10992 def
= mk_pre_dec_expr(state
, unary_expr(state
));
10995 eat(state
, TOK_AND
);
10996 def
= mk_addr_expr(state
, cast_expr(state
), 0);
10999 eat(state
, TOK_STAR
);
11000 def
= mk_deref_expr(state
, read_expr(state
, cast_expr(state
)));
11003 eat(state
, TOK_PLUS
);
11004 right
= read_expr(state
, cast_expr(state
));
11005 arithmetic(state
, right
);
11006 def
= integral_promotion(state
, right
);
11009 eat(state
, TOK_MINUS
);
11010 right
= read_expr(state
, cast_expr(state
));
11011 arithmetic(state
, right
);
11012 def
= integral_promotion(state
, right
);
11013 def
= triple(state
, OP_NEG
, def
->type
, def
, 0);
11016 eat(state
, TOK_TILDE
);
11017 right
= read_expr(state
, cast_expr(state
));
11018 integral(state
, right
);
11019 def
= integral_promotion(state
, right
);
11020 def
= triple(state
, OP_INVERT
, def
->type
, def
, 0);
11023 eat(state
, TOK_BANG
);
11024 right
= read_expr(state
, cast_expr(state
));
11025 bool(state
, right
);
11026 def
= lfalse_expr(state
, right
);
11032 eat(state
, TOK_SIZEOF
);
11033 tok1
= peek(state
);
11034 tok2
= peek2(state
);
11035 if ((tok1
== TOK_LPAREN
) && istype(tok2
)) {
11036 eat(state
, TOK_LPAREN
);
11037 type
= type_name(state
);
11038 eat(state
, TOK_RPAREN
);
11041 struct triple
*expr
;
11042 expr
= unary_expr(state
);
11044 release_expr(state
, expr
);
11046 def
= int_const(state
, &ulong_type
, size_of_in_bytes(state
, type
));
11053 eat(state
, TOK_ALIGNOF
);
11054 tok1
= peek(state
);
11055 tok2
= peek2(state
);
11056 if ((tok1
== TOK_LPAREN
) && istype(tok2
)) {
11057 eat(state
, TOK_LPAREN
);
11058 type
= type_name(state
);
11059 eat(state
, TOK_RPAREN
);
11062 struct triple
*expr
;
11063 expr
= unary_expr(state
);
11065 release_expr(state
, expr
);
11067 def
= int_const(state
, &ulong_type
, align_of_in_bytes(state
, type
));
11072 /* We only come here if we are called from the preprocessor */
11073 struct hash_entry
*ident
;
11075 eat(state
, TOK_MDEFINED
);
11077 if (pp_peek(state
) == TOK_LPAREN
) {
11078 pp_eat(state
, TOK_LPAREN
);
11081 ident
= pp_eat(state
, TOK_MIDENT
)->ident
;
11083 eat(state
, TOK_RPAREN
);
11085 def
= int_const(state
, &int_type
, ident
->sym_define
!= 0);
11089 def
= postfix_expr(state
);
11095 static struct triple
*cast_expr(struct compile_state
*state
)
11097 struct triple
*def
;
11099 tok1
= peek(state
);
11100 tok2
= peek2(state
);
11101 if ((tok1
== TOK_LPAREN
) && istype(tok2
)) {
11103 eat(state
, TOK_LPAREN
);
11104 type
= type_name(state
);
11105 eat(state
, TOK_RPAREN
);
11106 def
= mk_cast_expr(state
, type
, cast_expr(state
));
11109 def
= unary_expr(state
);
11114 static struct triple
*mult_expr(struct compile_state
*state
)
11116 struct triple
*def
;
11118 def
= cast_expr(state
);
11120 struct triple
*left
, *right
;
11121 struct type
*result_type
;
11129 left
= read_expr(state
, def
);
11130 arithmetic(state
, left
);
11134 right
= read_expr(state
, cast_expr(state
));
11135 arithmetic(state
, right
);
11137 result_type
= arithmetic_result(state
, left
, right
);
11138 sign
= is_signed(result_type
);
11141 case TOK_STAR
: op
= sign
? OP_SMUL
: OP_UMUL
; break;
11142 case TOK_DIV
: op
= sign
? OP_SDIV
: OP_UDIV
; break;
11143 case TOK_MOD
: op
= sign
? OP_SMOD
: OP_UMOD
; break;
11145 def
= triple(state
, op
, result_type
, left
, right
);
11155 static struct triple
*add_expr(struct compile_state
*state
)
11157 struct triple
*def
;
11159 def
= mult_expr(state
);
11162 switch( peek(state
)) {
11164 eat(state
, TOK_PLUS
);
11165 def
= mk_add_expr(state
, def
, mult_expr(state
));
11168 eat(state
, TOK_MINUS
);
11169 def
= mk_sub_expr(state
, def
, mult_expr(state
));
11179 static struct triple
*shift_expr(struct compile_state
*state
)
11181 struct triple
*def
;
11183 def
= add_expr(state
);
11185 struct triple
*left
, *right
;
11188 switch((tok
= peek(state
))) {
11191 left
= read_expr(state
, def
);
11192 integral(state
, left
);
11193 left
= integral_promotion(state
, left
);
11197 right
= read_expr(state
, add_expr(state
));
11198 integral(state
, right
);
11199 right
= integral_promotion(state
, right
);
11201 op
= (tok
== TOK_SL
)? OP_SL
:
11202 is_signed(left
->type
)? OP_SSR
: OP_USR
;
11204 def
= triple(state
, op
, left
->type
, left
, right
);
11214 static struct triple
*relational_expr(struct compile_state
*state
)
11216 #if DEBUG_ROMCC_WARNINGS
11217 #warning "Extend relational exprs to work on more than arithmetic types"
11219 struct triple
*def
;
11221 def
= shift_expr(state
);
11223 struct triple
*left
, *right
;
11224 struct type
*arg_type
;
11227 switch((tok
= peek(state
))) {
11232 left
= read_expr(state
, def
);
11233 arithmetic(state
, left
);
11237 right
= read_expr(state
, shift_expr(state
));
11238 arithmetic(state
, right
);
11240 arg_type
= arithmetic_result(state
, left
, right
);
11241 sign
= is_signed(arg_type
);
11244 case TOK_LESS
: op
= sign
? OP_SLESS
: OP_ULESS
; break;
11245 case TOK_MORE
: op
= sign
? OP_SMORE
: OP_UMORE
; break;
11246 case TOK_LESSEQ
: op
= sign
? OP_SLESSEQ
: OP_ULESSEQ
; break;
11247 case TOK_MOREEQ
: op
= sign
? OP_SMOREEQ
: OP_UMOREEQ
; break;
11249 def
= triple(state
, op
, &int_type
, left
, right
);
11259 static struct triple
*equality_expr(struct compile_state
*state
)
11261 #if DEBUG_ROMCC_WARNINGS
11262 #warning "Extend equality exprs to work on more than arithmetic types"
11264 struct triple
*def
;
11266 def
= relational_expr(state
);
11268 struct triple
*left
, *right
;
11271 switch((tok
= peek(state
))) {
11274 left
= read_expr(state
, def
);
11275 arithmetic(state
, left
);
11277 right
= read_expr(state
, relational_expr(state
));
11278 arithmetic(state
, right
);
11279 op
= (tok
== TOK_EQEQ
) ? OP_EQ
: OP_NOTEQ
;
11280 def
= triple(state
, op
, &int_type
, left
, right
);
11290 static struct triple
*and_expr(struct compile_state
*state
)
11292 struct triple
*def
;
11293 def
= equality_expr(state
);
11294 while(peek(state
) == TOK_AND
) {
11295 struct triple
*left
, *right
;
11296 struct type
*result_type
;
11297 left
= read_expr(state
, def
);
11298 integral(state
, left
);
11299 eat(state
, TOK_AND
);
11300 right
= read_expr(state
, equality_expr(state
));
11301 integral(state
, right
);
11302 result_type
= arithmetic_result(state
, left
, right
);
11303 def
= triple(state
, OP_AND
, result_type
, left
, right
);
11308 static struct triple
*xor_expr(struct compile_state
*state
)
11310 struct triple
*def
;
11311 def
= and_expr(state
);
11312 while(peek(state
) == TOK_XOR
) {
11313 struct triple
*left
, *right
;
11314 struct type
*result_type
;
11315 left
= read_expr(state
, def
);
11316 integral(state
, left
);
11317 eat(state
, TOK_XOR
);
11318 right
= read_expr(state
, and_expr(state
));
11319 integral(state
, right
);
11320 result_type
= arithmetic_result(state
, left
, right
);
11321 def
= triple(state
, OP_XOR
, result_type
, left
, right
);
11326 static struct triple
*or_expr(struct compile_state
*state
)
11328 struct triple
*def
;
11329 def
= xor_expr(state
);
11330 while(peek(state
) == TOK_OR
) {
11331 struct triple
*left
, *right
;
11332 struct type
*result_type
;
11333 left
= read_expr(state
, def
);
11334 integral(state
, left
);
11335 eat(state
, TOK_OR
);
11336 right
= read_expr(state
, xor_expr(state
));
11337 integral(state
, right
);
11338 result_type
= arithmetic_result(state
, left
, right
);
11339 def
= triple(state
, OP_OR
, result_type
, left
, right
);
11344 static struct triple
*land_expr(struct compile_state
*state
)
11346 struct triple
*def
;
11347 def
= or_expr(state
);
11348 while(peek(state
) == TOK_LOGAND
) {
11349 struct triple
*left
, *right
;
11350 left
= read_expr(state
, def
);
11352 eat(state
, TOK_LOGAND
);
11353 right
= read_expr(state
, or_expr(state
));
11354 bool(state
, right
);
11356 def
= mkland_expr(state
,
11357 ltrue_expr(state
, left
),
11358 ltrue_expr(state
, right
));
11363 static struct triple
*lor_expr(struct compile_state
*state
)
11365 struct triple
*def
;
11366 def
= land_expr(state
);
11367 while(peek(state
) == TOK_LOGOR
) {
11368 struct triple
*left
, *right
;
11369 left
= read_expr(state
, def
);
11371 eat(state
, TOK_LOGOR
);
11372 right
= read_expr(state
, land_expr(state
));
11373 bool(state
, right
);
11375 def
= mklor_expr(state
,
11376 ltrue_expr(state
, left
),
11377 ltrue_expr(state
, right
));
11382 static struct triple
*conditional_expr(struct compile_state
*state
)
11384 struct triple
*def
;
11385 def
= lor_expr(state
);
11386 if (peek(state
) == TOK_QUEST
) {
11387 struct triple
*test
, *left
, *right
;
11389 test
= ltrue_expr(state
, read_expr(state
, def
));
11390 eat(state
, TOK_QUEST
);
11391 left
= read_expr(state
, expr(state
));
11392 eat(state
, TOK_COLON
);
11393 right
= read_expr(state
, conditional_expr(state
));
11395 def
= mkcond_expr(state
, test
, left
, right
);
11401 struct triple
*val
;
11405 static void set_cv(struct compile_state
*state
, struct cv_triple
*cv
,
11406 struct triple
*dest
, struct triple
*val
)
11408 if (cv
[dest
->id
].val
) {
11409 free_triple(state
, cv
[dest
->id
].val
);
11411 cv
[dest
->id
].val
= val
;
11413 static struct triple
*get_cv(struct compile_state
*state
, struct cv_triple
*cv
,
11414 struct triple
*src
)
11416 return cv
[src
->id
].val
;
11419 static struct triple
*eval_const_expr(
11420 struct compile_state
*state
, struct triple
*expr
)
11422 struct triple
*def
;
11423 if (is_const(expr
)) {
11427 /* If we don't start out as a constant simplify into one */
11428 struct triple
*head
, *ptr
;
11429 struct cv_triple
*cv
;
11431 head
= label(state
); /* dummy initial triple */
11432 flatten(state
, head
, expr
);
11434 for(ptr
= head
->next
; ptr
!= head
; ptr
= ptr
->next
) {
11437 cv
= xcmalloc(sizeof(struct cv_triple
)*count
, "const value vector");
11439 for(ptr
= head
->next
; ptr
!= head
; ptr
= ptr
->next
) {
11441 cv
[i
].id
= ptr
->id
;
11447 valid_ins(state
, ptr
);
11448 if ((ptr
->op
== OP_PHI
) || (ptr
->op
== OP_LIST
)) {
11449 internal_error(state
, ptr
,
11450 "unexpected %s in constant expression",
11453 else if (ptr
->op
== OP_LIST
) {
11455 else if (triple_is_structural(state
, ptr
)) {
11458 else if (triple_is_ubranch(state
, ptr
)) {
11459 ptr
= TARG(ptr
, 0);
11461 else if (triple_is_cbranch(state
, ptr
)) {
11462 struct triple
*cond_val
;
11463 cond_val
= get_cv(state
, cv
, RHS(ptr
, 0));
11464 if (!cond_val
|| !is_const(cond_val
) ||
11465 (cond_val
->op
!= OP_INTCONST
))
11467 internal_error(state
, ptr
, "bad branch condition");
11469 if (cond_val
->u
.cval
== 0) {
11472 ptr
= TARG(ptr
, 0);
11475 else if (triple_is_branch(state
, ptr
)) {
11476 error(state
, ptr
, "bad branch type in constant expression");
11478 else if (ptr
->op
== OP_WRITE
) {
11479 struct triple
*val
;
11480 val
= get_cv(state
, cv
, RHS(ptr
, 0));
11482 set_cv(state
, cv
, MISC(ptr
, 0),
11483 copy_triple(state
, val
));
11484 set_cv(state
, cv
, ptr
,
11485 copy_triple(state
, val
));
11488 else if (ptr
->op
== OP_READ
) {
11489 set_cv(state
, cv
, ptr
,
11491 get_cv(state
, cv
, RHS(ptr
, 0))));
11494 else if (triple_is_pure(state
, ptr
, cv
[ptr
->id
].id
)) {
11495 struct triple
*val
, **rhs
;
11496 val
= copy_triple(state
, ptr
);
11497 rhs
= triple_rhs(state
, val
, 0);
11498 for(; rhs
; rhs
= triple_rhs(state
, val
, rhs
)) {
11500 internal_error(state
, ptr
, "Missing rhs");
11502 *rhs
= get_cv(state
, cv
, *rhs
);
11504 simplify(state
, val
);
11505 set_cv(state
, cv
, ptr
, val
);
11509 error(state
, ptr
, "impure operation in constant expression");
11512 } while(ptr
!= head
);
11514 /* Get the result value */
11515 def
= get_cv(state
, cv
, head
->prev
);
11516 cv
[head
->prev
->id
].val
= 0;
11518 /* Free the temporary values */
11519 for(i
= 0; i
< count
; i
++) {
11521 free_triple(state
, cv
[i
].val
);
11526 /* Free the intermediate expressions */
11527 while(head
->next
!= head
) {
11528 release_triple(state
, head
->next
);
11530 free_triple(state
, head
);
11532 if (!is_const(def
)) {
11533 error(state
, expr
, "Not a constant expression");
11538 static struct triple
*constant_expr(struct compile_state
*state
)
11540 return eval_const_expr(state
, conditional_expr(state
));
11543 static struct triple
*assignment_expr(struct compile_state
*state
)
11545 struct triple
*def
, *left
, *right
;
11547 /* The C grammer in K&R shows assignment expressions
11548 * only taking unary expressions as input on their
11549 * left hand side. But specifies the precedence of
11550 * assignemnt as the lowest operator except for comma.
11552 * Allowing conditional expressions on the left hand side
11553 * of an assignement results in a grammar that accepts
11554 * a larger set of statements than standard C. As long
11555 * as the subset of the grammar that is standard C behaves
11556 * correctly this should cause no problems.
11558 * For the extra token strings accepted by the grammar
11559 * none of them should produce a valid lvalue, so they
11560 * should not produce functioning programs.
11562 * GCC has this bug as well, so surprises should be minimal.
11564 def
= conditional_expr(state
);
11566 switch((tok
= peek(state
))) {
11568 lvalue(state
, left
);
11569 eat(state
, TOK_EQ
);
11570 def
= write_expr(state
, left
,
11571 read_expr(state
, assignment_expr(state
)));
11576 lvalue(state
, left
);
11577 arithmetic(state
, left
);
11579 right
= read_expr(state
, assignment_expr(state
));
11580 arithmetic(state
, right
);
11582 sign
= is_signed(left
->type
);
11585 case TOK_TIMESEQ
: op
= sign
? OP_SMUL
: OP_UMUL
; break;
11586 case TOK_DIVEQ
: op
= sign
? OP_SDIV
: OP_UDIV
; break;
11587 case TOK_MODEQ
: op
= sign
? OP_SMOD
: OP_UMOD
; break;
11589 def
= write_expr(state
, left
,
11590 triple(state
, op
, left
->type
,
11591 read_expr(state
, left
), right
));
11594 lvalue(state
, left
);
11595 eat(state
, TOK_PLUSEQ
);
11596 def
= write_expr(state
, left
,
11597 mk_add_expr(state
, left
, assignment_expr(state
)));
11600 lvalue(state
, left
);
11601 eat(state
, TOK_MINUSEQ
);
11602 def
= write_expr(state
, left
,
11603 mk_sub_expr(state
, left
, assignment_expr(state
)));
11610 lvalue(state
, left
);
11611 integral(state
, left
);
11613 right
= read_expr(state
, assignment_expr(state
));
11614 integral(state
, right
);
11615 right
= integral_promotion(state
, right
);
11616 sign
= is_signed(left
->type
);
11619 case TOK_SLEQ
: op
= OP_SL
; break;
11620 case TOK_SREQ
: op
= sign
? OP_SSR
: OP_USR
; break;
11621 case TOK_ANDEQ
: op
= OP_AND
; break;
11622 case TOK_XOREQ
: op
= OP_XOR
; break;
11623 case TOK_OREQ
: op
= OP_OR
; break;
11625 def
= write_expr(state
, left
,
11626 triple(state
, op
, left
->type
,
11627 read_expr(state
, left
), right
));
11633 static struct triple
*expr(struct compile_state
*state
)
11635 struct triple
*def
;
11636 def
= assignment_expr(state
);
11637 while(peek(state
) == TOK_COMMA
) {
11638 eat(state
, TOK_COMMA
);
11639 def
= mkprog(state
, def
, assignment_expr(state
), 0UL);
11644 static void expr_statement(struct compile_state
*state
, struct triple
*first
)
11646 if (peek(state
) != TOK_SEMI
) {
11647 /* lvalue conversions always apply except when certian operators
11648 * are applied. I apply the lvalue conversions here
11649 * as I know no more operators will be applied.
11651 flatten(state
, first
, lvalue_conversion(state
, expr(state
)));
11653 eat(state
, TOK_SEMI
);
11656 static void if_statement(struct compile_state
*state
, struct triple
*first
)
11658 struct triple
*test
, *jmp1
, *jmp2
, *middle
, *end
;
11660 jmp1
= jmp2
= middle
= 0;
11661 eat(state
, TOK_IF
);
11662 eat(state
, TOK_LPAREN
);
11663 test
= expr(state
);
11665 /* Cleanup and invert the test */
11666 test
= lfalse_expr(state
, read_expr(state
, test
));
11667 eat(state
, TOK_RPAREN
);
11668 /* Generate the needed pieces */
11669 middle
= label(state
);
11670 jmp1
= branch(state
, middle
, test
);
11671 /* Thread the pieces together */
11672 flatten(state
, first
, test
);
11673 flatten(state
, first
, jmp1
);
11674 flatten(state
, first
, label(state
));
11675 statement(state
, first
);
11676 if (peek(state
) == TOK_ELSE
) {
11677 eat(state
, TOK_ELSE
);
11678 /* Generate the rest of the pieces */
11679 end
= label(state
);
11680 jmp2
= branch(state
, end
, 0);
11681 /* Thread them together */
11682 flatten(state
, first
, jmp2
);
11683 flatten(state
, first
, middle
);
11684 statement(state
, first
);
11685 flatten(state
, first
, end
);
11688 flatten(state
, first
, middle
);
11692 static void for_statement(struct compile_state
*state
, struct triple
*first
)
11694 struct triple
*head
, *test
, *tail
, *jmp1
, *jmp2
, *end
;
11695 struct triple
*label1
, *label2
, *label3
;
11696 struct hash_entry
*ident
;
11698 eat(state
, TOK_FOR
);
11699 eat(state
, TOK_LPAREN
);
11700 head
= test
= tail
= jmp1
= jmp2
= 0;
11701 if (peek(state
) != TOK_SEMI
) {
11702 head
= expr(state
);
11704 eat(state
, TOK_SEMI
);
11705 if (peek(state
) != TOK_SEMI
) {
11706 test
= expr(state
);
11708 test
= ltrue_expr(state
, read_expr(state
, test
));
11710 eat(state
, TOK_SEMI
);
11711 if (peek(state
) != TOK_RPAREN
) {
11712 tail
= expr(state
);
11714 eat(state
, TOK_RPAREN
);
11715 /* Generate the needed pieces */
11716 label1
= label(state
);
11717 label2
= label(state
);
11718 label3
= label(state
);
11720 jmp1
= branch(state
, label3
, 0);
11721 jmp2
= branch(state
, label1
, test
);
11724 jmp2
= branch(state
, label1
, 0);
11726 end
= label(state
);
11727 /* Remember where break and continue go */
11728 start_scope(state
);
11729 ident
= state
->i_break
;
11730 symbol(state
, ident
, &ident
->sym_ident
, end
, end
->type
);
11731 ident
= state
->i_continue
;
11732 symbol(state
, ident
, &ident
->sym_ident
, label2
, label2
->type
);
11733 /* Now include the body */
11734 flatten(state
, first
, head
);
11735 flatten(state
, first
, jmp1
);
11736 flatten(state
, first
, label1
);
11737 statement(state
, first
);
11738 flatten(state
, first
, label2
);
11739 flatten(state
, first
, tail
);
11740 flatten(state
, first
, label3
);
11741 flatten(state
, first
, test
);
11742 flatten(state
, first
, jmp2
);
11743 flatten(state
, first
, end
);
11744 /* Cleanup the break/continue scope */
11748 static void while_statement(struct compile_state
*state
, struct triple
*first
)
11750 struct triple
*label1
, *test
, *label2
, *jmp1
, *jmp2
, *end
;
11751 struct hash_entry
*ident
;
11752 eat(state
, TOK_WHILE
);
11753 eat(state
, TOK_LPAREN
);
11754 test
= expr(state
);
11756 test
= ltrue_expr(state
, read_expr(state
, test
));
11757 eat(state
, TOK_RPAREN
);
11758 /* Generate the needed pieces */
11759 label1
= label(state
);
11760 label2
= label(state
);
11761 jmp1
= branch(state
, label2
, 0);
11762 jmp2
= branch(state
, label1
, test
);
11763 end
= label(state
);
11764 /* Remember where break and continue go */
11765 start_scope(state
);
11766 ident
= state
->i_break
;
11767 symbol(state
, ident
, &ident
->sym_ident
, end
, end
->type
);
11768 ident
= state
->i_continue
;
11769 symbol(state
, ident
, &ident
->sym_ident
, label2
, label2
->type
);
11770 /* Thread them together */
11771 flatten(state
, first
, jmp1
);
11772 flatten(state
, first
, label1
);
11773 statement(state
, first
);
11774 flatten(state
, first
, label2
);
11775 flatten(state
, first
, test
);
11776 flatten(state
, first
, jmp2
);
11777 flatten(state
, first
, end
);
11778 /* Cleanup the break/continue scope */
11782 static void do_statement(struct compile_state
*state
, struct triple
*first
)
11784 struct triple
*label1
, *label2
, *test
, *end
;
11785 struct hash_entry
*ident
;
11786 eat(state
, TOK_DO
);
11787 /* Generate the needed pieces */
11788 label1
= label(state
);
11789 label2
= label(state
);
11790 end
= label(state
);
11791 /* Remember where break and continue go */
11792 start_scope(state
);
11793 ident
= state
->i_break
;
11794 symbol(state
, ident
, &ident
->sym_ident
, end
, end
->type
);
11795 ident
= state
->i_continue
;
11796 symbol(state
, ident
, &ident
->sym_ident
, label2
, label2
->type
);
11797 /* Now include the body */
11798 flatten(state
, first
, label1
);
11799 statement(state
, first
);
11800 /* Cleanup the break/continue scope */
11802 /* Eat the rest of the loop */
11803 eat(state
, TOK_WHILE
);
11804 eat(state
, TOK_LPAREN
);
11805 test
= read_expr(state
, expr(state
));
11807 eat(state
, TOK_RPAREN
);
11808 eat(state
, TOK_SEMI
);
11809 /* Thread the pieces together */
11810 test
= ltrue_expr(state
, test
);
11811 flatten(state
, first
, label2
);
11812 flatten(state
, first
, test
);
11813 flatten(state
, first
, branch(state
, label1
, test
));
11814 flatten(state
, first
, end
);
11818 static void return_statement(struct compile_state
*state
, struct triple
*first
)
11820 struct triple
*jmp
, *mv
, *dest
, *var
, *val
;
11822 eat(state
, TOK_RETURN
);
11824 #if DEBUG_ROMCC_WARNINGS
11825 #warning "FIXME implement a more general excess branch elimination"
11828 /* If we have a return value do some more work */
11829 if (peek(state
) != TOK_SEMI
) {
11830 val
= read_expr(state
, expr(state
));
11832 eat(state
, TOK_SEMI
);
11834 /* See if this last statement in a function */
11835 last
= ((peek(state
) == TOK_RBRACE
) &&
11836 (state
->scope_depth
== GLOBAL_SCOPE_DEPTH
+2));
11838 /* Find the return variable */
11839 var
= fresult(state
, state
->main_function
);
11841 /* Find the return destination */
11842 dest
= state
->i_return
->sym_ident
->def
;
11844 /* If needed generate a jump instruction */
11846 jmp
= branch(state
, dest
, 0);
11848 /* If needed generate an assignment instruction */
11850 mv
= write_expr(state
, deref_index(state
, var
, 1), val
);
11852 /* Now put the code together */
11854 flatten(state
, first
, mv
);
11855 flatten(state
, first
, jmp
);
11858 flatten(state
, first
, jmp
);
11862 static void break_statement(struct compile_state
*state
, struct triple
*first
)
11864 struct triple
*dest
;
11865 eat(state
, TOK_BREAK
);
11866 eat(state
, TOK_SEMI
);
11867 if (!state
->i_break
->sym_ident
) {
11868 error(state
, 0, "break statement not within loop or switch");
11870 dest
= state
->i_break
->sym_ident
->def
;
11871 flatten(state
, first
, branch(state
, dest
, 0));
11874 static void continue_statement(struct compile_state
*state
, struct triple
*first
)
11876 struct triple
*dest
;
11877 eat(state
, TOK_CONTINUE
);
11878 eat(state
, TOK_SEMI
);
11879 if (!state
->i_continue
->sym_ident
) {
11880 error(state
, 0, "continue statement outside of a loop");
11882 dest
= state
->i_continue
->sym_ident
->def
;
11883 flatten(state
, first
, branch(state
, dest
, 0));
11886 static void goto_statement(struct compile_state
*state
, struct triple
*first
)
11888 struct hash_entry
*ident
;
11889 eat(state
, TOK_GOTO
);
11890 ident
= eat(state
, TOK_IDENT
)->ident
;
11891 if (!ident
->sym_label
) {
11892 /* If this is a forward branch allocate the label now,
11893 * it will be flattend in the appropriate location later.
11895 struct triple
*ins
;
11896 ins
= label(state
);
11897 label_symbol(state
, ident
, ins
, FUNCTION_SCOPE_DEPTH
);
11899 eat(state
, TOK_SEMI
);
11901 flatten(state
, first
, branch(state
, ident
->sym_label
->def
, 0));
11904 static void labeled_statement(struct compile_state
*state
, struct triple
*first
)
11906 struct triple
*ins
;
11907 struct hash_entry
*ident
;
11909 ident
= eat(state
, TOK_IDENT
)->ident
;
11910 if (ident
->sym_label
&& ident
->sym_label
->def
) {
11911 ins
= ident
->sym_label
->def
;
11912 put_occurance(ins
->occurance
);
11913 ins
->occurance
= new_occurance(state
);
11916 ins
= label(state
);
11917 label_symbol(state
, ident
, ins
, FUNCTION_SCOPE_DEPTH
);
11919 if (ins
->id
& TRIPLE_FLAG_FLATTENED
) {
11920 error(state
, 0, "label %s already defined", ident
->name
);
11922 flatten(state
, first
, ins
);
11924 eat(state
, TOK_COLON
);
11925 statement(state
, first
);
11928 static void switch_statement(struct compile_state
*state
, struct triple
*first
)
11930 struct triple
*value
, *top
, *end
, *dbranch
;
11931 struct hash_entry
*ident
;
11933 /* See if we have a valid switch statement */
11934 eat(state
, TOK_SWITCH
);
11935 eat(state
, TOK_LPAREN
);
11936 value
= expr(state
);
11937 integral(state
, value
);
11938 value
= read_expr(state
, value
);
11939 eat(state
, TOK_RPAREN
);
11940 /* Generate the needed pieces */
11941 top
= label(state
);
11942 end
= label(state
);
11943 dbranch
= branch(state
, end
, 0);
11944 /* Remember where case branches and break goes */
11945 start_scope(state
);
11946 ident
= state
->i_switch
;
11947 symbol(state
, ident
, &ident
->sym_ident
, value
, value
->type
);
11948 ident
= state
->i_case
;
11949 symbol(state
, ident
, &ident
->sym_ident
, top
, top
->type
);
11950 ident
= state
->i_break
;
11951 symbol(state
, ident
, &ident
->sym_ident
, end
, end
->type
);
11952 ident
= state
->i_default
;
11953 symbol(state
, ident
, &ident
->sym_ident
, dbranch
, dbranch
->type
);
11954 /* Thread them together */
11955 flatten(state
, first
, value
);
11956 flatten(state
, first
, top
);
11957 flatten(state
, first
, dbranch
);
11958 statement(state
, first
);
11959 flatten(state
, first
, end
);
11960 /* Cleanup the switch scope */
11964 static void case_statement(struct compile_state
*state
, struct triple
*first
)
11966 struct triple
*cvalue
, *dest
, *test
, *jmp
;
11967 struct triple
*ptr
, *value
, *top
, *dbranch
;
11969 /* See if w have a valid case statement */
11970 eat(state
, TOK_CASE
);
11971 cvalue
= constant_expr(state
);
11972 integral(state
, cvalue
);
11973 if (cvalue
->op
!= OP_INTCONST
) {
11974 error(state
, 0, "integer constant expected");
11976 eat(state
, TOK_COLON
);
11977 if (!state
->i_case
->sym_ident
) {
11978 error(state
, 0, "case statement not within a switch");
11981 /* Lookup the interesting pieces */
11982 top
= state
->i_case
->sym_ident
->def
;
11983 value
= state
->i_switch
->sym_ident
->def
;
11984 dbranch
= state
->i_default
->sym_ident
->def
;
11986 /* See if this case label has already been used */
11987 for(ptr
= top
; ptr
!= dbranch
; ptr
= ptr
->next
) {
11988 if (ptr
->op
!= OP_EQ
) {
11991 if (RHS(ptr
, 1)->u
.cval
== cvalue
->u
.cval
) {
11992 error(state
, 0, "duplicate case %d statement",
11996 /* Generate the needed pieces */
11997 dest
= label(state
);
11998 test
= triple(state
, OP_EQ
, &int_type
, value
, cvalue
);
11999 jmp
= branch(state
, dest
, test
);
12000 /* Thread the pieces together */
12001 flatten(state
, dbranch
, test
);
12002 flatten(state
, dbranch
, jmp
);
12003 flatten(state
, dbranch
, label(state
));
12004 flatten(state
, first
, dest
);
12005 statement(state
, first
);
12008 static void default_statement(struct compile_state
*state
, struct triple
*first
)
12010 struct triple
*dest
;
12011 struct triple
*dbranch
, *end
;
12013 /* See if we have a valid default statement */
12014 eat(state
, TOK_DEFAULT
);
12015 eat(state
, TOK_COLON
);
12017 if (!state
->i_case
->sym_ident
) {
12018 error(state
, 0, "default statement not within a switch");
12021 /* Lookup the interesting pieces */
12022 dbranch
= state
->i_default
->sym_ident
->def
;
12023 end
= state
->i_break
->sym_ident
->def
;
12025 /* See if a default statement has already happened */
12026 if (TARG(dbranch
, 0) != end
) {
12027 error(state
, 0, "duplicate default statement");
12030 /* Generate the needed pieces */
12031 dest
= label(state
);
12033 /* Blame the branch on the default statement */
12034 put_occurance(dbranch
->occurance
);
12035 dbranch
->occurance
= new_occurance(state
);
12037 /* Thread the pieces together */
12038 TARG(dbranch
, 0) = dest
;
12039 use_triple(dest
, dbranch
);
12040 flatten(state
, first
, dest
);
12041 statement(state
, first
);
12044 static void asm_statement(struct compile_state
*state
, struct triple
*first
)
12046 struct asm_info
*info
;
12048 struct triple
*constraint
;
12049 struct triple
*expr
;
12050 } out_param
[MAX_LHS
], in_param
[MAX_RHS
], clob_param
[MAX_LHS
];
12051 struct triple
*def
, *asm_str
;
12052 int out
, in
, clobbers
, more
, colons
, i
;
12056 eat(state
, TOK_ASM
);
12057 /* For now ignore the qualifiers */
12058 switch(peek(state
)) {
12060 eat(state
, TOK_CONST
);
12063 eat(state
, TOK_VOLATILE
);
12064 flags
|= TRIPLE_FLAG_VOLATILE
;
12067 eat(state
, TOK_LPAREN
);
12068 asm_str
= string_constant(state
);
12071 out
= in
= clobbers
= 0;
12073 if ((colons
== 0) && (peek(state
) == TOK_COLON
)) {
12074 eat(state
, TOK_COLON
);
12076 more
= (peek(state
) == TOK_LIT_STRING
);
12078 struct triple
*var
;
12079 struct triple
*constraint
;
12082 if (out
> MAX_LHS
) {
12083 error(state
, 0, "Maximum output count exceeded.");
12085 constraint
= string_constant(state
);
12086 str
= constraint
->u
.blob
;
12087 if (str
[0] != '=') {
12088 error(state
, 0, "Output constraint does not start with =");
12090 constraint
->u
.blob
= str
+ 1;
12091 eat(state
, TOK_LPAREN
);
12092 var
= conditional_expr(state
);
12093 eat(state
, TOK_RPAREN
);
12095 lvalue(state
, var
);
12096 out_param
[out
].constraint
= constraint
;
12097 out_param
[out
].expr
= var
;
12098 if (peek(state
) == TOK_COMMA
) {
12099 eat(state
, TOK_COMMA
);
12106 if ((colons
== 1) && (peek(state
) == TOK_COLON
)) {
12107 eat(state
, TOK_COLON
);
12109 more
= (peek(state
) == TOK_LIT_STRING
);
12111 struct triple
*val
;
12112 struct triple
*constraint
;
12115 if (in
> MAX_RHS
) {
12116 error(state
, 0, "Maximum input count exceeded.");
12118 constraint
= string_constant(state
);
12119 str
= constraint
->u
.blob
;
12120 if (digitp(str
[0] && str
[1] == '\0')) {
12122 val
= digval(str
[0]);
12123 if ((val
< 0) || (val
>= out
)) {
12124 error(state
, 0, "Invalid input constraint %d", val
);
12127 eat(state
, TOK_LPAREN
);
12128 val
= conditional_expr(state
);
12129 eat(state
, TOK_RPAREN
);
12131 in_param
[in
].constraint
= constraint
;
12132 in_param
[in
].expr
= val
;
12133 if (peek(state
) == TOK_COMMA
) {
12134 eat(state
, TOK_COMMA
);
12142 if ((colons
== 2) && (peek(state
) == TOK_COLON
)) {
12143 eat(state
, TOK_COLON
);
12145 more
= (peek(state
) == TOK_LIT_STRING
);
12147 struct triple
*clobber
;
12149 if ((clobbers
+ out
) > MAX_LHS
) {
12150 error(state
, 0, "Maximum clobber limit exceeded.");
12152 clobber
= string_constant(state
);
12154 clob_param
[clobbers
].constraint
= clobber
;
12155 if (peek(state
) == TOK_COMMA
) {
12156 eat(state
, TOK_COMMA
);
12162 eat(state
, TOK_RPAREN
);
12163 eat(state
, TOK_SEMI
);
12166 info
= xcmalloc(sizeof(*info
), "asm_info");
12167 info
->str
= asm_str
->u
.blob
;
12168 free_triple(state
, asm_str
);
12170 def
= new_triple(state
, OP_ASM
, &void_type
, clobbers
+ out
, in
);
12171 def
->u
.ainfo
= info
;
12174 /* Find the register constraints */
12175 for(i
= 0; i
< out
; i
++) {
12176 struct triple
*constraint
;
12177 constraint
= out_param
[i
].constraint
;
12178 info
->tmpl
.lhs
[i
] = arch_reg_constraint(state
,
12179 out_param
[i
].expr
->type
, constraint
->u
.blob
);
12180 free_triple(state
, constraint
);
12182 for(; i
- out
< clobbers
; i
++) {
12183 struct triple
*constraint
;
12184 constraint
= clob_param
[i
- out
].constraint
;
12185 info
->tmpl
.lhs
[i
] = arch_reg_clobber(state
, constraint
->u
.blob
);
12186 free_triple(state
, constraint
);
12188 for(i
= 0; i
< in
; i
++) {
12189 struct triple
*constraint
;
12191 constraint
= in_param
[i
].constraint
;
12192 str
= constraint
->u
.blob
;
12193 if (digitp(str
[0]) && str
[1] == '\0') {
12194 struct reg_info cinfo
;
12196 val
= digval(str
[0]);
12197 cinfo
.reg
= info
->tmpl
.lhs
[val
].reg
;
12198 cinfo
.regcm
= arch_type_to_regcm(state
, in_param
[i
].expr
->type
);
12199 cinfo
.regcm
&= info
->tmpl
.lhs
[val
].regcm
;
12200 if (cinfo
.reg
== REG_UNSET
) {
12201 cinfo
.reg
= REG_VIRT0
+ val
;
12203 if (cinfo
.regcm
== 0) {
12204 error(state
, 0, "No registers for %d", val
);
12206 info
->tmpl
.lhs
[val
] = cinfo
;
12207 info
->tmpl
.rhs
[i
] = cinfo
;
12210 info
->tmpl
.rhs
[i
] = arch_reg_constraint(state
,
12211 in_param
[i
].expr
->type
, str
);
12213 free_triple(state
, constraint
);
12216 /* Now build the helper expressions */
12217 for(i
= 0; i
< in
; i
++) {
12218 RHS(def
, i
) = read_expr(state
, in_param
[i
].expr
);
12220 flatten(state
, first
, def
);
12221 for(i
= 0; i
< (out
+ clobbers
); i
++) {
12223 struct triple
*piece
;
12225 type
= out_param
[i
].expr
->type
;
12227 size_t size
= arch_reg_size(info
->tmpl
.lhs
[i
].reg
);
12228 if (size
>= SIZEOF_LONG
) {
12229 type
= &ulong_type
;
12231 else if (size
>= SIZEOF_INT
) {
12234 else if (size
>= SIZEOF_SHORT
) {
12235 type
= &ushort_type
;
12238 type
= &uchar_type
;
12241 piece
= triple(state
, OP_PIECE
, type
, def
, 0);
12243 LHS(def
, i
) = piece
;
12244 flatten(state
, first
, piece
);
12246 /* And write the helpers to their destinations */
12247 for(i
= 0; i
< out
; i
++) {
12248 struct triple
*piece
;
12249 piece
= LHS(def
, i
);
12250 flatten(state
, first
,
12251 write_expr(state
, out_param
[i
].expr
, piece
));
12256 static int isdecl(int tok
)
12279 case TOK_TYPE_NAME
: /* typedef name */
12286 static void compound_statement(struct compile_state
*state
, struct triple
*first
)
12288 eat(state
, TOK_LBRACE
);
12289 start_scope(state
);
12291 /* statement-list opt */
12292 while (peek(state
) != TOK_RBRACE
) {
12293 statement(state
, first
);
12296 eat(state
, TOK_RBRACE
);
12299 static void statement(struct compile_state
*state
, struct triple
*first
)
12303 if (tok
== TOK_LBRACE
) {
12304 compound_statement(state
, first
);
12306 else if (tok
== TOK_IF
) {
12307 if_statement(state
, first
);
12309 else if (tok
== TOK_FOR
) {
12310 for_statement(state
, first
);
12312 else if (tok
== TOK_WHILE
) {
12313 while_statement(state
, first
);
12315 else if (tok
== TOK_DO
) {
12316 do_statement(state
, first
);
12318 else if (tok
== TOK_RETURN
) {
12319 return_statement(state
, first
);
12321 else if (tok
== TOK_BREAK
) {
12322 break_statement(state
, first
);
12324 else if (tok
== TOK_CONTINUE
) {
12325 continue_statement(state
, first
);
12327 else if (tok
== TOK_GOTO
) {
12328 goto_statement(state
, first
);
12330 else if (tok
== TOK_SWITCH
) {
12331 switch_statement(state
, first
);
12333 else if (tok
== TOK_ASM
) {
12334 asm_statement(state
, first
);
12336 else if ((tok
== TOK_IDENT
) && (peek2(state
) == TOK_COLON
)) {
12337 labeled_statement(state
, first
);
12339 else if (tok
== TOK_CASE
) {
12340 case_statement(state
, first
);
12342 else if (tok
== TOK_DEFAULT
) {
12343 default_statement(state
, first
);
12345 else if (isdecl(tok
)) {
12346 /* This handles C99 intermixing of statements and decls */
12347 decl(state
, first
);
12350 expr_statement(state
, first
);
12354 static struct type
*param_decl(struct compile_state
*state
)
12357 struct hash_entry
*ident
;
12358 /* Cheat so the declarator will know we are not global */
12359 start_scope(state
);
12361 type
= decl_specifiers(state
);
12362 type
= declarator(state
, type
, &ident
, 0);
12363 type
->field_ident
= ident
;
12368 static struct type
*param_type_list(struct compile_state
*state
, struct type
*type
)
12370 struct type
*ftype
, **next
;
12371 ftype
= new_type(TYPE_FUNCTION
| (type
->type
& STOR_MASK
), type
, param_decl(state
));
12372 next
= &ftype
->right
;
12373 ftype
->elements
= 1;
12374 while(peek(state
) == TOK_COMMA
) {
12375 eat(state
, TOK_COMMA
);
12376 if (peek(state
) == TOK_DOTS
) {
12377 eat(state
, TOK_DOTS
);
12378 error(state
, 0, "variadic functions not supported");
12381 *next
= new_type(TYPE_PRODUCT
, *next
, param_decl(state
));
12382 next
= &((*next
)->right
);
12389 static struct type
*type_name(struct compile_state
*state
)
12392 type
= specifier_qualifier_list(state
);
12393 /* abstract-declarator (may consume no tokens) */
12394 type
= declarator(state
, type
, 0, 0);
12398 static struct type
*direct_declarator(
12399 struct compile_state
*state
, struct type
*type
,
12400 struct hash_entry
**pident
, int need_ident
)
12402 struct hash_entry
*ident
;
12403 struct type
*outer
;
12406 arrays_complete(state
, type
);
12407 switch(peek(state
)) {
12409 ident
= eat(state
, TOK_IDENT
)->ident
;
12411 error(state
, 0, "Unexpected identifier found");
12413 /* The name of what we are declaring */
12417 eat(state
, TOK_LPAREN
);
12418 outer
= declarator(state
, type
, pident
, need_ident
);
12419 eat(state
, TOK_RPAREN
);
12423 error(state
, 0, "Identifier expected");
12429 arrays_complete(state
, type
);
12430 switch(peek(state
)) {
12432 eat(state
, TOK_LPAREN
);
12433 type
= param_type_list(state
, type
);
12434 eat(state
, TOK_RPAREN
);
12438 unsigned int qualifiers
;
12439 struct triple
*value
;
12441 eat(state
, TOK_LBRACKET
);
12442 if (peek(state
) != TOK_RBRACKET
) {
12443 value
= constant_expr(state
);
12444 integral(state
, value
);
12446 eat(state
, TOK_RBRACKET
);
12448 qualifiers
= type
->type
& (QUAL_MASK
| STOR_MASK
);
12449 type
= new_type(TYPE_ARRAY
| qualifiers
, type
, 0);
12451 type
->elements
= value
->u
.cval
;
12452 free_triple(state
, value
);
12454 type
->elements
= ELEMENT_COUNT_UNSPECIFIED
;
12465 struct type
*inner
;
12466 arrays_complete(state
, type
);
12468 for(inner
= outer
; inner
->left
; inner
= inner
->left
)
12470 inner
->left
= type
;
12476 static struct type
*declarator(
12477 struct compile_state
*state
, struct type
*type
,
12478 struct hash_entry
**pident
, int need_ident
)
12480 while(peek(state
) == TOK_STAR
) {
12481 eat(state
, TOK_STAR
);
12482 type
= new_type(TYPE_POINTER
| (type
->type
& STOR_MASK
), type
, 0);
12484 type
= direct_declarator(state
, type
, pident
, need_ident
);
12488 static struct type
*typedef_name(
12489 struct compile_state
*state
, unsigned int specifiers
)
12491 struct hash_entry
*ident
;
12493 ident
= eat(state
, TOK_TYPE_NAME
)->ident
;
12494 type
= ident
->sym_ident
->type
;
12495 specifiers
|= type
->type
& QUAL_MASK
;
12496 if ((specifiers
& (STOR_MASK
| QUAL_MASK
)) !=
12497 (type
->type
& (STOR_MASK
| QUAL_MASK
))) {
12498 type
= clone_type(specifiers
, type
);
12503 static struct type
*enum_specifier(
12504 struct compile_state
*state
, unsigned int spec
)
12506 struct hash_entry
*ident
;
12509 struct type
*enum_type
;
12512 eat(state
, TOK_ENUM
);
12514 if ((tok
== TOK_IDENT
) || (tok
== TOK_ENUM_CONST
) || (tok
== TOK_TYPE_NAME
)) {
12515 ident
= eat(state
, tok
)->ident
;
12518 if (!ident
|| (peek(state
) == TOK_LBRACE
)) {
12519 struct type
**next
;
12520 eat(state
, TOK_LBRACE
);
12521 enum_type
= new_type(TYPE_ENUM
| spec
, 0, 0);
12522 enum_type
->type_ident
= ident
;
12523 next
= &enum_type
->right
;
12525 struct hash_entry
*eident
;
12526 struct triple
*value
;
12527 struct type
*entry
;
12528 eident
= eat(state
, TOK_IDENT
)->ident
;
12529 if (eident
->sym_ident
) {
12530 error(state
, 0, "%s already declared",
12533 eident
->tok
= TOK_ENUM_CONST
;
12534 if (peek(state
) == TOK_EQ
) {
12535 struct triple
*val
;
12536 eat(state
, TOK_EQ
);
12537 val
= constant_expr(state
);
12538 integral(state
, val
);
12539 base
= val
->u
.cval
;
12541 value
= int_const(state
, &int_type
, base
);
12542 symbol(state
, eident
, &eident
->sym_ident
, value
, &int_type
);
12543 entry
= new_type(TYPE_LIST
, 0, 0);
12544 entry
->field_ident
= eident
;
12546 next
= &entry
->right
;
12548 if (peek(state
) == TOK_COMMA
) {
12549 eat(state
, TOK_COMMA
);
12551 } while(peek(state
) != TOK_RBRACE
);
12552 eat(state
, TOK_RBRACE
);
12554 symbol(state
, ident
, &ident
->sym_tag
, 0, enum_type
);
12557 if (ident
&& ident
->sym_tag
&&
12558 ident
->sym_tag
->type
&&
12559 ((ident
->sym_tag
->type
->type
& TYPE_MASK
) == TYPE_ENUM
)) {
12560 enum_type
= clone_type(spec
, ident
->sym_tag
->type
);
12562 else if (ident
&& !enum_type
) {
12563 error(state
, 0, "enum %s undeclared", ident
->name
);
12568 static struct type
*struct_declarator(
12569 struct compile_state
*state
, struct type
*type
, struct hash_entry
**ident
)
12571 if (peek(state
) != TOK_COLON
) {
12572 type
= declarator(state
, type
, ident
, 1);
12574 if (peek(state
) == TOK_COLON
) {
12575 struct triple
*value
;
12576 eat(state
, TOK_COLON
);
12577 value
= constant_expr(state
);
12578 if (value
->op
!= OP_INTCONST
) {
12579 error(state
, 0, "Invalid constant expression");
12581 if (value
->u
.cval
> size_of(state
, type
)) {
12582 error(state
, 0, "bitfield larger than base type");
12584 if (!TYPE_INTEGER(type
->type
) || ((type
->type
& TYPE_MASK
) == TYPE_BITFIELD
)) {
12585 error(state
, 0, "bitfield base not an integer type");
12587 type
= new_type(TYPE_BITFIELD
, type
, 0);
12588 type
->elements
= value
->u
.cval
;
12593 static struct type
*struct_or_union_specifier(
12594 struct compile_state
*state
, unsigned int spec
)
12596 struct type
*struct_type
;
12597 struct hash_entry
*ident
;
12598 unsigned int type_main
;
12599 unsigned int type_join
;
12603 switch(peek(state
)) {
12605 eat(state
, TOK_STRUCT
);
12606 type_main
= TYPE_STRUCT
;
12607 type_join
= TYPE_PRODUCT
;
12610 eat(state
, TOK_UNION
);
12611 type_main
= TYPE_UNION
;
12612 type_join
= TYPE_OVERLAP
;
12615 eat(state
, TOK_STRUCT
);
12616 type_main
= TYPE_STRUCT
;
12617 type_join
= TYPE_PRODUCT
;
12621 if ((tok
== TOK_IDENT
) || (tok
== TOK_ENUM_CONST
) || (tok
== TOK_TYPE_NAME
)) {
12622 ident
= eat(state
, tok
)->ident
;
12624 if (!ident
|| (peek(state
) == TOK_LBRACE
)) {
12626 struct type
**next
;
12628 eat(state
, TOK_LBRACE
);
12629 next
= &struct_type
;
12631 struct type
*base_type
;
12633 base_type
= specifier_qualifier_list(state
);
12636 struct hash_entry
*fident
;
12638 type
= struct_declarator(state
, base_type
, &fident
);
12640 if (peek(state
) == TOK_COMMA
) {
12642 eat(state
, TOK_COMMA
);
12644 type
= clone_type(0, type
);
12645 type
->field_ident
= fident
;
12647 *next
= new_type(type_join
, *next
, type
);
12648 next
= &((*next
)->right
);
12653 eat(state
, TOK_SEMI
);
12654 } while(peek(state
) != TOK_RBRACE
);
12655 eat(state
, TOK_RBRACE
);
12656 struct_type
= new_type(type_main
| spec
, struct_type
, 0);
12657 struct_type
->type_ident
= ident
;
12658 struct_type
->elements
= elements
;
12660 symbol(state
, ident
, &ident
->sym_tag
, 0, struct_type
);
12663 if (ident
&& ident
->sym_tag
&&
12664 ident
->sym_tag
->type
&&
12665 ((ident
->sym_tag
->type
->type
& TYPE_MASK
) == type_main
)) {
12666 struct_type
= clone_type(spec
, ident
->sym_tag
->type
);
12668 else if (ident
&& !struct_type
) {
12669 error(state
, 0, "%s %s undeclared",
12670 (type_main
== TYPE_STRUCT
)?"struct" : "union",
12673 return struct_type
;
12676 static unsigned int storage_class_specifier_opt(struct compile_state
*state
)
12678 unsigned int specifiers
;
12679 switch(peek(state
)) {
12681 eat(state
, TOK_AUTO
);
12682 specifiers
= STOR_AUTO
;
12685 eat(state
, TOK_REGISTER
);
12686 specifiers
= STOR_REGISTER
;
12689 eat(state
, TOK_STATIC
);
12690 specifiers
= STOR_STATIC
;
12693 eat(state
, TOK_EXTERN
);
12694 specifiers
= STOR_EXTERN
;
12697 eat(state
, TOK_TYPEDEF
);
12698 specifiers
= STOR_TYPEDEF
;
12701 if (state
->scope_depth
<= GLOBAL_SCOPE_DEPTH
) {
12702 specifiers
= STOR_LOCAL
;
12705 specifiers
= STOR_AUTO
;
12711 static unsigned int function_specifier_opt(struct compile_state
*state
)
12713 /* Ignore the inline keyword */
12714 unsigned int specifiers
;
12716 switch(peek(state
)) {
12718 eat(state
, TOK_INLINE
);
12719 specifiers
= STOR_INLINE
;
12724 static unsigned int attrib(struct compile_state
*state
, unsigned int attributes
)
12726 int tok
= peek(state
);
12730 /* The empty attribute ignore it */
12733 case TOK_ENUM_CONST
:
12734 case TOK_TYPE_NAME
:
12736 struct hash_entry
*ident
;
12737 ident
= eat(state
, TOK_IDENT
)->ident
;
12739 if (ident
== state
->i_noinline
) {
12740 if (attributes
& ATTRIB_ALWAYS_INLINE
) {
12741 error(state
, 0, "both always_inline and noinline attribtes");
12743 attributes
|= ATTRIB_NOINLINE
;
12745 else if (ident
== state
->i_always_inline
) {
12746 if (attributes
& ATTRIB_NOINLINE
) {
12747 error(state
, 0, "both noinline and always_inline attribtes");
12749 attributes
|= ATTRIB_ALWAYS_INLINE
;
12751 else if (ident
== state
->i_noreturn
) {
12752 // attribute((noreturn)) does nothing (yet?)
12754 else if (ident
== state
->i_unused
) {
12755 // attribute((unused)) does nothing (yet?)
12757 else if (ident
== state
->i_packed
) {
12758 // attribute((packed)) does nothing (yet?)
12761 error(state
, 0, "Unknown attribute:%s", ident
->name
);
12766 error(state
, 0, "Unexpected token: %s\n", tokens
[tok
]);
12772 static unsigned int attribute_list(struct compile_state
*state
, unsigned type
)
12774 type
= attrib(state
, type
);
12775 while(peek(state
) == TOK_COMMA
) {
12776 eat(state
, TOK_COMMA
);
12777 type
= attrib(state
, type
);
12782 static unsigned int attributes_opt(struct compile_state
*state
, unsigned type
)
12784 if (peek(state
) == TOK_ATTRIBUTE
) {
12785 eat(state
, TOK_ATTRIBUTE
);
12786 eat(state
, TOK_LPAREN
);
12787 eat(state
, TOK_LPAREN
);
12788 type
= attribute_list(state
, type
);
12789 eat(state
, TOK_RPAREN
);
12790 eat(state
, TOK_RPAREN
);
12795 static unsigned int type_qualifiers(struct compile_state
*state
)
12797 unsigned int specifiers
;
12800 specifiers
= QUAL_NONE
;
12802 switch(peek(state
)) {
12804 eat(state
, TOK_CONST
);
12805 specifiers
|= QUAL_CONST
;
12808 eat(state
, TOK_VOLATILE
);
12809 specifiers
|= QUAL_VOLATILE
;
12812 eat(state
, TOK_RESTRICT
);
12813 specifiers
|= QUAL_RESTRICT
;
12823 static struct type
*type_specifier(
12824 struct compile_state
*state
, unsigned int spec
)
12829 switch((tok
= peek(state
))) {
12831 eat(state
, TOK_VOID
);
12832 type
= new_type(TYPE_VOID
| spec
, 0, 0);
12835 eat(state
, TOK_CHAR
);
12836 type
= new_type(TYPE_CHAR
| spec
, 0, 0);
12839 eat(state
, TOK_SHORT
);
12840 if (peek(state
) == TOK_INT
) {
12841 eat(state
, TOK_INT
);
12843 type
= new_type(TYPE_SHORT
| spec
, 0, 0);
12846 eat(state
, TOK_INT
);
12847 type
= new_type(TYPE_INT
| spec
, 0, 0);
12850 eat(state
, TOK_LONG
);
12851 switch(peek(state
)) {
12853 eat(state
, TOK_LONG
);
12854 error(state
, 0, "long long not supported");
12857 eat(state
, TOK_DOUBLE
);
12858 error(state
, 0, "long double not supported");
12861 eat(state
, TOK_INT
);
12862 type
= new_type(TYPE_LONG
| spec
, 0, 0);
12865 type
= new_type(TYPE_LONG
| spec
, 0, 0);
12870 eat(state
, TOK_FLOAT
);
12871 error(state
, 0, "type float not supported");
12874 eat(state
, TOK_DOUBLE
);
12875 error(state
, 0, "type double not supported");
12878 eat(state
, TOK_SIGNED
);
12879 switch(peek(state
)) {
12881 eat(state
, TOK_LONG
);
12882 switch(peek(state
)) {
12884 eat(state
, TOK_LONG
);
12885 error(state
, 0, "type long long not supported");
12888 eat(state
, TOK_INT
);
12889 type
= new_type(TYPE_LONG
| spec
, 0, 0);
12892 type
= new_type(TYPE_LONG
| spec
, 0, 0);
12897 eat(state
, TOK_INT
);
12898 type
= new_type(TYPE_INT
| spec
, 0, 0);
12901 eat(state
, TOK_SHORT
);
12902 type
= new_type(TYPE_SHORT
| spec
, 0, 0);
12905 eat(state
, TOK_CHAR
);
12906 type
= new_type(TYPE_CHAR
| spec
, 0, 0);
12909 type
= new_type(TYPE_INT
| spec
, 0, 0);
12914 eat(state
, TOK_UNSIGNED
);
12915 switch(peek(state
)) {
12917 eat(state
, TOK_LONG
);
12918 switch(peek(state
)) {
12920 eat(state
, TOK_LONG
);
12921 error(state
, 0, "unsigned long long not supported");
12924 eat(state
, TOK_INT
);
12925 type
= new_type(TYPE_ULONG
| spec
, 0, 0);
12928 type
= new_type(TYPE_ULONG
| spec
, 0, 0);
12933 eat(state
, TOK_INT
);
12934 type
= new_type(TYPE_UINT
| spec
, 0, 0);
12937 eat(state
, TOK_SHORT
);
12938 type
= new_type(TYPE_USHORT
| spec
, 0, 0);
12941 eat(state
, TOK_CHAR
);
12942 type
= new_type(TYPE_UCHAR
| spec
, 0, 0);
12945 type
= new_type(TYPE_UINT
| spec
, 0, 0);
12949 /* struct or union specifier */
12952 type
= struct_or_union_specifier(state
, spec
);
12954 /* enum-spefifier */
12956 type
= enum_specifier(state
, spec
);
12959 case TOK_TYPE_NAME
:
12960 type
= typedef_name(state
, spec
);
12963 error(state
, 0, "bad type specifier %s",
12970 static int istype(int tok
)
12988 case TOK_TYPE_NAME
:
12996 static struct type
*specifier_qualifier_list(struct compile_state
*state
)
12999 unsigned int specifiers
= 0;
13001 /* type qualifiers */
13002 specifiers
|= type_qualifiers(state
);
13004 /* type specifier */
13005 type
= type_specifier(state
, specifiers
);
13010 #if DEBUG_ROMCC_WARNING
13011 static int isdecl_specifier(int tok
)
13014 /* storage class specifier */
13020 /* type qualifier */
13024 /* type specifiers */
13034 /* struct or union specifier */
13037 /* enum-spefifier */
13040 case TOK_TYPE_NAME
:
13041 /* function specifiers */
13050 static struct type
*decl_specifiers(struct compile_state
*state
)
13053 unsigned int specifiers
;
13054 /* I am overly restrictive in the arragement of specifiers supported.
13055 * C is overly flexible in this department it makes interpreting
13056 * the parse tree difficult.
13060 /* storage class specifier */
13061 specifiers
|= storage_class_specifier_opt(state
);
13063 /* function-specifier */
13064 specifiers
|= function_specifier_opt(state
);
13067 specifiers
|= attributes_opt(state
, 0);
13069 /* type qualifier */
13070 specifiers
|= type_qualifiers(state
);
13072 /* type specifier */
13073 type
= type_specifier(state
, specifiers
);
13077 struct field_info
{
13082 static struct field_info
designator(struct compile_state
*state
, struct type
*type
)
13085 struct field_info info
;
13089 switch(peek(state
)) {
13092 struct triple
*value
;
13093 if ((type
->type
& TYPE_MASK
) != TYPE_ARRAY
) {
13094 error(state
, 0, "Array designator not in array initializer");
13096 eat(state
, TOK_LBRACKET
);
13097 value
= constant_expr(state
);
13098 eat(state
, TOK_RBRACKET
);
13100 info
.type
= type
->left
;
13101 info
.offset
= value
->u
.cval
* size_of(state
, info
.type
);
13106 struct hash_entry
*field
;
13107 if (((type
->type
& TYPE_MASK
) != TYPE_STRUCT
) &&
13108 ((type
->type
& TYPE_MASK
) != TYPE_UNION
))
13110 error(state
, 0, "Struct designator not in struct initializer");
13112 eat(state
, TOK_DOT
);
13113 field
= eat(state
, TOK_IDENT
)->ident
;
13114 info
.offset
= field_offset(state
, type
, field
);
13115 info
.type
= field_type(state
, type
, field
);
13119 error(state
, 0, "Invalid designator");
13122 } while((tok
== TOK_LBRACKET
) || (tok
== TOK_DOT
));
13123 eat(state
, TOK_EQ
);
13127 static struct triple
*initializer(
13128 struct compile_state
*state
, struct type
*type
)
13130 struct triple
*result
;
13131 #if DEBUG_ROMCC_WARNINGS
13132 #warning "FIXME more consistent initializer handling (where should eval_const_expr go?"
13134 if (peek(state
) != TOK_LBRACE
) {
13135 result
= assignment_expr(state
);
13136 if (((type
->type
& TYPE_MASK
) == TYPE_ARRAY
) &&
13137 (type
->elements
== ELEMENT_COUNT_UNSPECIFIED
) &&
13138 ((result
->type
->type
& TYPE_MASK
) == TYPE_ARRAY
) &&
13139 (result
->type
->elements
!= ELEMENT_COUNT_UNSPECIFIED
) &&
13140 (equiv_types(type
->left
, result
->type
->left
))) {
13141 type
->elements
= result
->type
->elements
;
13143 if (is_lvalue(state
, result
) &&
13144 ((result
->type
->type
& TYPE_MASK
) == TYPE_ARRAY
) &&
13145 (type
->type
& TYPE_MASK
) != TYPE_ARRAY
)
13147 result
= lvalue_conversion(state
, result
);
13149 if (!is_init_compatible(state
, type
, result
->type
)) {
13150 error(state
, 0, "Incompatible types in initializer");
13152 if (!equiv_types(type
, result
->type
)) {
13153 result
= mk_cast_expr(state
, type
, result
);
13159 struct field_info info
;
13161 if (((type
->type
& TYPE_MASK
) != TYPE_ARRAY
) &&
13162 ((type
->type
& TYPE_MASK
) != TYPE_STRUCT
)) {
13163 internal_error(state
, 0, "unknown initializer type");
13166 info
.type
= type
->left
;
13167 if ((type
->type
& TYPE_MASK
) == TYPE_STRUCT
) {
13168 info
.type
= next_field(state
, type
, 0);
13170 if (type
->elements
== ELEMENT_COUNT_UNSPECIFIED
) {
13173 max_offset
= size_of(state
, type
);
13175 buf
= xcmalloc(bits_to_bytes(max_offset
), "initializer");
13176 eat(state
, TOK_LBRACE
);
13178 struct triple
*value
;
13179 struct type
*value_type
;
13185 if ((tok
== TOK_LBRACKET
) || (tok
== TOK_DOT
)) {
13186 info
= designator(state
, type
);
13188 if ((type
->elements
!= ELEMENT_COUNT_UNSPECIFIED
) &&
13189 (info
.offset
>= max_offset
)) {
13190 error(state
, 0, "element beyond bounds");
13192 value_type
= info
.type
;
13193 value
= eval_const_expr(state
, initializer(state
, value_type
));
13194 value_size
= size_of(state
, value_type
);
13195 if (((type
->type
& TYPE_MASK
) == TYPE_ARRAY
) &&
13196 (type
->elements
== ELEMENT_COUNT_UNSPECIFIED
) &&
13197 (max_offset
<= info
.offset
)) {
13201 old_size
= max_offset
;
13202 max_offset
= info
.offset
+ value_size
;
13203 buf
= xmalloc(bits_to_bytes(max_offset
), "initializer");
13204 memcpy(buf
, old_buf
, bits_to_bytes(old_size
));
13207 dest
= ((char *)buf
) + bits_to_bytes(info
.offset
);
13208 #if DEBUG_INITIALIZER
13209 fprintf(state
->errout
, "dest = buf + %d max_offset: %d value_size: %d op: %d\n",
13211 bits_to_bytes(max_offset
),
13212 bits_to_bytes(value_size
),
13215 if (value
->op
== OP_BLOBCONST
) {
13216 memcpy(dest
, value
->u
.blob
, bits_to_bytes(value_size
));
13218 else if ((value
->op
== OP_INTCONST
) && (value_size
== SIZEOF_I8
)) {
13219 #if DEBUG_INITIALIZER
13220 fprintf(state
->errout
, "byte: %02x\n", value
->u
.cval
& 0xff);
13222 *((uint8_t *)dest
) = value
->u
.cval
& 0xff;
13224 else if ((value
->op
== OP_INTCONST
) && (value_size
== SIZEOF_I16
)) {
13225 *((uint16_t *)dest
) = value
->u
.cval
& 0xffff;
13227 else if ((value
->op
== OP_INTCONST
) && (value_size
== SIZEOF_I32
)) {
13228 *((uint32_t *)dest
) = value
->u
.cval
& 0xffffffff;
13231 internal_error(state
, 0, "unhandled constant initializer");
13233 free_triple(state
, value
);
13234 if (peek(state
) == TOK_COMMA
) {
13235 eat(state
, TOK_COMMA
);
13238 info
.offset
+= value_size
;
13239 if ((type
->type
& TYPE_MASK
) == TYPE_STRUCT
) {
13240 info
.type
= next_field(state
, type
, info
.type
);
13241 info
.offset
= field_offset(state
, type
,
13242 info
.type
->field_ident
);
13244 } while(comma
&& (peek(state
) != TOK_RBRACE
));
13245 if ((type
->elements
== ELEMENT_COUNT_UNSPECIFIED
) &&
13246 ((type
->type
& TYPE_MASK
) == TYPE_ARRAY
)) {
13247 type
->elements
= max_offset
/ size_of(state
, type
->left
);
13249 eat(state
, TOK_RBRACE
);
13250 result
= triple(state
, OP_BLOBCONST
, type
, 0, 0);
13251 result
->u
.blob
= buf
;
13256 static void resolve_branches(struct compile_state
*state
, struct triple
*first
)
13258 /* Make a second pass and finish anything outstanding
13259 * with respect to branches. The only outstanding item
13260 * is to see if there are goto to labels that have not
13261 * been defined and to error about them.
13264 struct triple
*ins
;
13265 /* Also error on branches that do not use their targets */
13268 if (!triple_is_ret(state
, ins
)) {
13269 struct triple
**expr
;
13270 struct triple_set
*set
;
13271 expr
= triple_targ(state
, ins
, 0);
13272 for(; expr
; expr
= triple_targ(state
, ins
, expr
)) {
13273 struct triple
*targ
;
13275 for(set
= targ
?targ
->use
:0; set
; set
= set
->next
) {
13276 if (set
->member
== ins
) {
13281 internal_error(state
, ins
, "targ not used");
13286 } while(ins
!= first
);
13287 /* See if there are goto to labels that have not been defined */
13288 for(i
= 0; i
< HASH_TABLE_SIZE
; i
++) {
13289 struct hash_entry
*entry
;
13290 for(entry
= state
->hash_table
[i
]; entry
; entry
= entry
->next
) {
13291 struct triple
*ins
;
13292 if (!entry
->sym_label
) {
13295 ins
= entry
->sym_label
->def
;
13296 if (!(ins
->id
& TRIPLE_FLAG_FLATTENED
)) {
13297 error(state
, ins
, "label `%s' used but not defined",
13304 static struct triple
*function_definition(
13305 struct compile_state
*state
, struct type
*type
)
13307 struct triple
*def
, *tmp
, *first
, *end
, *retvar
, *ret
;
13308 struct triple
*fname
;
13309 struct type
*fname_type
;
13310 struct hash_entry
*ident
;
13311 struct type
*param
, *crtype
, *ctype
;
13313 if ((type
->type
&TYPE_MASK
) != TYPE_FUNCTION
) {
13314 error(state
, 0, "Invalid function header");
13317 /* Verify the function type */
13318 if (((type
->right
->type
& TYPE_MASK
) != TYPE_VOID
) &&
13319 ((type
->right
->type
& TYPE_MASK
) != TYPE_PRODUCT
) &&
13320 (type
->right
->field_ident
== 0)) {
13321 error(state
, 0, "Invalid function parameters");
13323 param
= type
->right
;
13325 while((param
->type
& TYPE_MASK
) == TYPE_PRODUCT
) {
13327 if (!param
->left
->field_ident
) {
13328 error(state
, 0, "No identifier for parameter %d\n", i
);
13330 param
= param
->right
;
13333 if (((param
->type
& TYPE_MASK
) != TYPE_VOID
) && !param
->field_ident
) {
13334 error(state
, 0, "No identifier for paramter %d\n", i
);
13337 /* Get a list of statements for this function. */
13338 def
= triple(state
, OP_LIST
, type
, 0, 0);
13340 /* Start a new scope for the passed parameters */
13341 start_scope(state
);
13343 /* Put a label at the very start of a function */
13344 first
= label(state
);
13345 RHS(def
, 0) = first
;
13347 /* Put a label at the very end of a function */
13348 end
= label(state
);
13349 flatten(state
, first
, end
);
13350 /* Remember where return goes */
13351 ident
= state
->i_return
;
13352 symbol(state
, ident
, &ident
->sym_ident
, end
, end
->type
);
13354 /* Get the initial closure type */
13355 ctype
= new_type(TYPE_JOIN
, &void_type
, 0);
13356 ctype
->elements
= 1;
13358 /* Add a variable for the return value */
13359 crtype
= new_type(TYPE_TUPLE
,
13360 /* Remove all type qualifiers from the return type */
13361 new_type(TYPE_PRODUCT
, ctype
, clone_type(0, type
->left
)), 0);
13362 crtype
->elements
= 2;
13363 flatten(state
, end
, variable(state
, crtype
));
13365 /* Allocate a variable for the return address */
13366 retvar
= flatten(state
, end
, variable(state
, &void_ptr_type
));
13368 /* Add in the return instruction */
13369 ret
= triple(state
, OP_RET
, &void_type
, read_expr(state
, retvar
), 0);
13370 ret
= flatten(state
, first
, ret
);
13372 /* Walk through the parameters and create symbol table entries
13375 param
= type
->right
;
13376 while((param
->type
& TYPE_MASK
) == TYPE_PRODUCT
) {
13377 ident
= param
->left
->field_ident
;
13378 tmp
= variable(state
, param
->left
);
13379 var_symbol(state
, ident
, tmp
);
13380 flatten(state
, end
, tmp
);
13381 param
= param
->right
;
13383 if ((param
->type
& TYPE_MASK
) != TYPE_VOID
) {
13384 /* And don't forget the last parameter */
13385 ident
= param
->field_ident
;
13386 tmp
= variable(state
, param
);
13387 symbol(state
, ident
, &ident
->sym_ident
, tmp
, tmp
->type
);
13388 flatten(state
, end
, tmp
);
13391 /* Add the declaration static const char __func__ [] = "func-name" */
13392 fname_type
= new_type(TYPE_ARRAY
,
13393 clone_type(QUAL_CONST
| STOR_STATIC
, &char_type
), 0);
13394 fname_type
->type
|= QUAL_CONST
| STOR_STATIC
;
13395 fname_type
->elements
= strlen(state
->function
) + 1;
13397 fname
= triple(state
, OP_BLOBCONST
, fname_type
, 0, 0);
13398 fname
->u
.blob
= (void *)state
->function
;
13399 fname
= flatten(state
, end
, fname
);
13401 ident
= state
->i___func__
;
13402 symbol(state
, ident
, &ident
->sym_ident
, fname
, fname_type
);
13404 /* Remember which function I am compiling.
13405 * Also assume the last defined function is the main function.
13407 state
->main_function
= def
;
13409 /* Now get the actual function definition */
13410 compound_statement(state
, end
);
13412 /* Finish anything unfinished with branches */
13413 resolve_branches(state
, first
);
13415 /* Remove the parameter scope */
13419 /* Remember I have defined a function */
13420 if (!state
->functions
) {
13421 state
->functions
= def
;
13423 insert_triple(state
, state
->functions
, def
);
13425 if (state
->compiler
->debug
& DEBUG_INLINE
) {
13426 FILE *fp
= state
->dbgout
;
13429 fprintf(fp
, "\n__________ %s _________\n", __FUNCTION__
);
13430 display_func(state
, fp
, def
);
13431 fprintf(fp
, "__________ %s _________ done\n\n", __FUNCTION__
);
13437 static struct triple
*do_decl(struct compile_state
*state
,
13438 struct type
*type
, struct hash_entry
*ident
)
13440 struct triple
*def
;
13442 /* Clean up the storage types used */
13443 switch (type
->type
& STOR_MASK
) {
13446 /* These are the good types I am aiming for */
13448 case STOR_REGISTER
:
13449 type
->type
&= ~STOR_MASK
;
13450 type
->type
|= STOR_AUTO
;
13454 type
->type
&= ~STOR_MASK
;
13455 type
->type
|= STOR_STATIC
;
13459 error(state
, 0, "typedef without name");
13461 symbol(state
, ident
, &ident
->sym_ident
, 0, type
);
13462 ident
->tok
= TOK_TYPE_NAME
;
13466 internal_error(state
, 0, "Undefined storage class");
13468 if ((type
->type
& TYPE_MASK
) == TYPE_FUNCTION
) {
13469 // ignore function prototypes
13473 ((type
->type
& TYPE_MASK
) == TYPE_ARRAY
) &&
13474 ((type
->type
& STOR_MASK
) != STOR_STATIC
))
13475 error(state
, 0, "non static arrays not supported");
13477 ((type
->type
& STOR_MASK
) == STOR_STATIC
) &&
13478 ((type
->type
& QUAL_CONST
) == 0)) {
13479 error(state
, 0, "non const static variables not supported");
13482 def
= variable(state
, type
);
13483 var_symbol(state
, ident
, def
);
13488 static void decl(struct compile_state
*state
, struct triple
*first
)
13490 struct type
*base_type
, *type
;
13491 struct hash_entry
*ident
;
13492 struct triple
*def
;
13494 global
= (state
->scope_depth
<= GLOBAL_SCOPE_DEPTH
);
13495 base_type
= decl_specifiers(state
);
13497 type
= declarator(state
, base_type
, &ident
, 0);
13498 type
->type
= attributes_opt(state
, type
->type
);
13499 if (global
&& ident
&& (peek(state
) == TOK_LBRACE
)) {
13501 type
->type_ident
= ident
;
13502 state
->function
= ident
->name
;
13503 def
= function_definition(state
, type
);
13504 symbol(state
, ident
, &ident
->sym_ident
, def
, type
);
13505 state
->function
= 0;
13509 flatten(state
, first
, do_decl(state
, type
, ident
));
13510 /* type or variable definition */
13513 if (peek(state
) == TOK_EQ
) {
13515 error(state
, 0, "cannot assign to a type");
13517 eat(state
, TOK_EQ
);
13518 flatten(state
, first
,
13520 ident
->sym_ident
->def
,
13521 initializer(state
, type
)));
13523 arrays_complete(state
, type
);
13524 if (peek(state
) == TOK_COMMA
) {
13525 eat(state
, TOK_COMMA
);
13527 type
= declarator(state
, base_type
, &ident
, 0);
13528 flatten(state
, first
, do_decl(state
, type
, ident
));
13532 eat(state
, TOK_SEMI
);
13536 static void decls(struct compile_state
*state
)
13538 struct triple
*list
;
13540 list
= label(state
);
13543 if (tok
== TOK_EOF
) {
13546 if (tok
== TOK_SPACE
) {
13547 eat(state
, TOK_SPACE
);
13550 if (list
->next
!= list
) {
13551 error(state
, 0, "global variables not supported");
13557 * Function inlining
13559 struct triple_reg_set
{
13560 struct triple_reg_set
*next
;
13561 struct triple
*member
;
13562 struct triple
*new;
13565 struct block
*block
;
13566 struct triple_reg_set
*in
;
13567 struct triple_reg_set
*out
;
13570 static void setup_basic_blocks(struct compile_state
*, struct basic_blocks
*bb
);
13571 static void analyze_basic_blocks(struct compile_state
*state
, struct basic_blocks
*bb
);
13572 static void free_basic_blocks(struct compile_state
*, struct basic_blocks
*bb
);
13573 static int tdominates(struct compile_state
*state
, struct triple
*dom
, struct triple
*sub
);
13574 static void walk_blocks(struct compile_state
*state
, struct basic_blocks
*bb
,
13575 void (*cb
)(struct compile_state
*state
, struct block
*block
, void *arg
),
13577 static void print_block(
13578 struct compile_state
*state
, struct block
*block
, void *arg
);
13579 static int do_triple_set(struct triple_reg_set
**head
,
13580 struct triple
*member
, struct triple
*new_member
);
13581 static void do_triple_unset(struct triple_reg_set
**head
, struct triple
*member
);
13582 static struct reg_block
*compute_variable_lifetimes(
13583 struct compile_state
*state
, struct basic_blocks
*bb
);
13584 static void free_variable_lifetimes(struct compile_state
*state
,
13585 struct basic_blocks
*bb
, struct reg_block
*blocks
);
13586 #if DEBUG_EXPLICIT_CLOSURES
13587 static void print_live_variables(struct compile_state
*state
,
13588 struct basic_blocks
*bb
, struct reg_block
*rb
, FILE *fp
);
13592 static struct triple
*call(struct compile_state
*state
,
13593 struct triple
*retvar
, struct triple
*ret_addr
,
13594 struct triple
*targ
, struct triple
*ret
)
13596 struct triple
*call
;
13598 if (!retvar
|| !is_lvalue(state
, retvar
)) {
13599 internal_error(state
, 0, "writing to a non lvalue?");
13601 write_compatible(state
, retvar
->type
, &void_ptr_type
);
13603 call
= new_triple(state
, OP_CALL
, &void_type
, 1, 0);
13604 TARG(call
, 0) = targ
;
13605 MISC(call
, 0) = ret
;
13606 if (!targ
|| (targ
->op
!= OP_LABEL
)) {
13607 internal_error(state
, 0, "call not to a label");
13609 if (!ret
|| (ret
->op
!= OP_RET
)) {
13610 internal_error(state
, 0, "call not matched with return");
13615 static void walk_functions(struct compile_state
*state
,
13616 void (*cb
)(struct compile_state
*state
, struct triple
*func
, void *arg
),
13619 struct triple
*func
, *first
;
13620 func
= first
= state
->functions
;
13622 cb(state
, func
, arg
);
13624 } while(func
!= first
);
13627 static void reverse_walk_functions(struct compile_state
*state
,
13628 void (*cb
)(struct compile_state
*state
, struct triple
*func
, void *arg
),
13631 struct triple
*func
, *first
;
13632 func
= first
= state
->functions
;
13635 cb(state
, func
, arg
);
13636 } while(func
!= first
);
13640 static void mark_live(struct compile_state
*state
, struct triple
*func
, void *arg
)
13642 struct triple
*ptr
, *first
;
13643 if (func
->u
.cval
== 0) {
13646 ptr
= first
= RHS(func
, 0);
13648 if (ptr
->op
== OP_FCALL
) {
13649 struct triple
*called_func
;
13650 called_func
= MISC(ptr
, 0);
13651 /* Mark the called function as used */
13652 if (!(func
->id
& TRIPLE_FLAG_FLATTENED
)) {
13653 called_func
->u
.cval
++;
13655 /* Remove the called function from the list */
13656 called_func
->prev
->next
= called_func
->next
;
13657 called_func
->next
->prev
= called_func
->prev
;
13659 /* Place the called function before me on the list */
13660 called_func
->next
= func
;
13661 called_func
->prev
= func
->prev
;
13662 called_func
->prev
->next
= called_func
;
13663 called_func
->next
->prev
= called_func
;
13666 } while(ptr
!= first
);
13667 func
->id
|= TRIPLE_FLAG_FLATTENED
;
13670 static void mark_live_functions(struct compile_state
*state
)
13672 /* Ensure state->main_function is the last function in
13673 * the list of functions.
13675 if ((state
->main_function
->next
!= state
->functions
) ||
13676 (state
->functions
->prev
!= state
->main_function
)) {
13677 internal_error(state
, 0,
13678 "state->main_function is not at the end of the function list ");
13680 state
->main_function
->u
.cval
= 1;
13681 reverse_walk_functions(state
, mark_live
, 0);
13684 static int local_triple(struct compile_state
*state
,
13685 struct triple
*func
, struct triple
*ins
)
13687 int local
= (ins
->id
& TRIPLE_FLAG_LOCAL
);
13690 FILE *fp
= state
->errout
;
13691 fprintf(fp
, "global: ");
13692 display_triple(fp
, ins
);
13698 struct triple
*copy_func(struct compile_state
*state
, struct triple
*ofunc
,
13699 struct occurance
*base_occurance
)
13701 struct triple
*nfunc
;
13702 struct triple
*nfirst
, *ofirst
;
13703 struct triple
*new, *old
;
13705 if (state
->compiler
->debug
& DEBUG_INLINE
) {
13706 FILE *fp
= state
->dbgout
;
13709 fprintf(fp
, "\n__________ %s _________\n", __FUNCTION__
);
13710 display_func(state
, fp
, ofunc
);
13711 fprintf(fp
, "__________ %s _________ done\n\n", __FUNCTION__
);
13714 /* Make a new copy of the old function */
13715 nfunc
= triple(state
, OP_LIST
, ofunc
->type
, 0, 0);
13717 ofirst
= old
= RHS(ofunc
, 0);
13719 struct triple
*new;
13720 struct occurance
*occurance
;
13721 int old_lhs
, old_rhs
;
13722 old_lhs
= old
->lhs
;
13723 old_rhs
= old
->rhs
;
13724 occurance
= inline_occurance(state
, base_occurance
, old
->occurance
);
13725 if (ofunc
->u
.cval
&& (old
->op
== OP_FCALL
)) {
13726 MISC(old
, 0)->u
.cval
+= 1;
13728 new = alloc_triple(state
, old
->op
, old
->type
, old_lhs
, old_rhs
,
13730 if (!triple_stores_block(state
, new)) {
13731 memcpy(&new->u
, &old
->u
, sizeof(new->u
));
13734 RHS(nfunc
, 0) = nfirst
= new;
13737 insert_triple(state
, nfirst
, new);
13739 new->id
|= TRIPLE_FLAG_FLATTENED
;
13740 new->id
|= old
->id
& TRIPLE_FLAG_COPY
;
13742 /* During the copy remember new as user of old */
13743 use_triple(old
, new);
13745 /* Remember which instructions are local */
13746 old
->id
|= TRIPLE_FLAG_LOCAL
;
13748 } while(old
!= ofirst
);
13750 /* Make a second pass to fix up any unresolved references */
13754 struct triple
**oexpr
, **nexpr
;
13756 /* Lookup where the copy is, to join pointers */
13757 count
= TRIPLE_SIZE(old
);
13758 for(i
= 0; i
< count
; i
++) {
13759 oexpr
= &old
->param
[i
];
13760 nexpr
= &new->param
[i
];
13761 if (*oexpr
&& !*nexpr
) {
13762 if (!local_triple(state
, ofunc
, *oexpr
)) {
13765 else if ((*oexpr
)->use
) {
13766 *nexpr
= (*oexpr
)->use
->member
;
13768 if (*nexpr
== old
) {
13769 internal_error(state
, 0, "new == old?");
13771 use_triple(*nexpr
, new);
13773 if (!*nexpr
&& *oexpr
) {
13774 internal_error(state
, 0, "Could not copy %d", i
);
13779 } while((old
!= ofirst
) && (new != nfirst
));
13781 /* Make a third pass to cleanup the extra useses */
13785 unuse_triple(old
, new);
13786 /* Forget which instructions are local */
13787 old
->id
&= ~TRIPLE_FLAG_LOCAL
;
13790 } while ((old
!= ofirst
) && (new != nfirst
));
13794 static void expand_inline_call(
13795 struct compile_state
*state
, struct triple
*me
, struct triple
*fcall
)
13797 /* Inline the function call */
13798 struct type
*ptype
;
13799 struct triple
*ofunc
, *nfunc
, *nfirst
, *result
, *retvar
, *ins
;
13800 struct triple
*end
, *nend
;
13803 /* Find the triples */
13804 ofunc
= MISC(fcall
, 0);
13805 if (ofunc
->op
!= OP_LIST
) {
13806 internal_error(state
, 0, "improper function");
13808 nfunc
= copy_func(state
, ofunc
, fcall
->occurance
);
13809 /* Prepend the parameter reading into the new function list */
13810 ptype
= nfunc
->type
->right
;
13811 pvals
= fcall
->rhs
;
13812 for(i
= 0; i
< pvals
; i
++) {
13813 struct type
*atype
;
13814 struct triple
*arg
, *param
;
13816 if ((ptype
->type
& TYPE_MASK
) == TYPE_PRODUCT
) {
13817 atype
= ptype
->left
;
13819 param
= farg(state
, nfunc
, i
);
13820 if ((param
->type
->type
& TYPE_MASK
) != (atype
->type
& TYPE_MASK
)) {
13821 internal_error(state
, fcall
, "param %d type mismatch", i
);
13823 arg
= RHS(fcall
, i
);
13824 flatten(state
, fcall
, write_expr(state
, param
, arg
));
13825 ptype
= ptype
->right
;
13828 if ((nfunc
->type
->left
->type
& TYPE_MASK
) != TYPE_VOID
) {
13829 result
= read_expr(state
,
13830 deref_index(state
, fresult(state
, nfunc
), 1));
13832 if (state
->compiler
->debug
& DEBUG_INLINE
) {
13833 FILE *fp
= state
->dbgout
;
13836 fprintf(fp
, "\n__________ %s _________\n", __FUNCTION__
);
13837 display_func(state
, fp
, nfunc
);
13838 fprintf(fp
, "__________ %s _________ done\n\n", __FUNCTION__
);
13842 * Get rid of the extra triples
13844 /* Remove the read of the return address */
13845 ins
= RHS(nfunc
, 0)->prev
->prev
;
13846 if ((ins
->op
!= OP_READ
) || (RHS(ins
, 0) != fretaddr(state
, nfunc
))) {
13847 internal_error(state
, ins
, "Not return addres read?");
13849 release_triple(state
, ins
);
13850 /* Remove the return instruction */
13851 ins
= RHS(nfunc
, 0)->prev
;
13852 if (ins
->op
!= OP_RET
) {
13853 internal_error(state
, ins
, "Not return?");
13855 release_triple(state
, ins
);
13856 /* Remove the retaddres variable */
13857 retvar
= fretaddr(state
, nfunc
);
13858 if ((retvar
->lhs
!= 1) ||
13859 (retvar
->op
!= OP_ADECL
) ||
13860 (retvar
->next
->op
!= OP_PIECE
) ||
13861 (MISC(retvar
->next
, 0) != retvar
)) {
13862 internal_error(state
, retvar
, "Not the return address?");
13864 release_triple(state
, retvar
->next
);
13865 release_triple(state
, retvar
);
13867 /* Remove the label at the start of the function */
13868 ins
= RHS(nfunc
, 0);
13869 if (ins
->op
!= OP_LABEL
) {
13870 internal_error(state
, ins
, "Not label?");
13872 nfirst
= ins
->next
;
13873 free_triple(state
, ins
);
13874 /* Release the new function header */
13876 free_triple(state
, nfunc
);
13878 /* Append the new function list onto the return list */
13880 nend
= nfirst
->prev
;
13881 end
->next
= nfirst
;
13882 nfirst
->prev
= end
;
13883 nend
->next
= fcall
;
13884 fcall
->prev
= nend
;
13886 /* Now the result reading code */
13888 result
= flatten(state
, fcall
, result
);
13889 propogate_use(state
, fcall
, result
);
13892 /* Release the original fcall instruction */
13893 release_triple(state
, fcall
);
13900 * Type of the result variable.
13904 * +----------+------------+
13906 * union of closures result_type
13908 * +------------------+---------------+
13910 * closure1 ... closuerN
13912 * +----+--+-+--------+-----+ +----+----+---+-----+
13913 * | | | | | | | | |
13914 * var1 var2 var3 ... varN result var1 var2 ... varN result
13916 * +--------+---------+
13918 * union of closures result_type
13920 * +-----+-------------------+
13922 * closure1 ... closureN
13924 * +-----+---+----+----+ +----+---+----+-----+
13926 * var1 var2 ... varN result var1 var2 ... varN result
13929 static int add_closure_type(struct compile_state
*state
,
13930 struct triple
*func
, struct type
*closure_type
)
13932 struct type
*type
, *ctype
, **next
;
13933 struct triple
*var
, *new_var
;
13937 FILE *fp
= state
->errout
;
13938 fprintf(fp
, "original_type: ");
13939 name_of(fp
, fresult(state
, func
)->type
);
13942 /* find the original type */
13943 var
= fresult(state
, func
);
13945 if (type
->elements
!= 2) {
13946 internal_error(state
, var
, "bad return type");
13949 /* Find the complete closure type and update it */
13950 ctype
= type
->left
->left
;
13951 next
= &ctype
->left
;
13952 while(((*next
)->type
& TYPE_MASK
) == TYPE_OVERLAP
) {
13953 next
= &(*next
)->right
;
13955 *next
= new_type(TYPE_OVERLAP
, *next
, dup_type(state
, closure_type
));
13956 ctype
->elements
+= 1;
13959 fprintf(fp
, "new_type: ");
13962 fprintf(fp
, "ctype: %p %d bits: %d ",
13963 ctype
, ctype
->elements
, reg_size_of(state
, ctype
));
13964 name_of(fp
, ctype
);
13968 /* Regenerate the variable with the new type definition */
13969 new_var
= pre_triple(state
, var
, OP_ADECL
, type
, 0, 0);
13970 new_var
->id
|= TRIPLE_FLAG_FLATTENED
;
13971 for(i
= 0; i
< new_var
->lhs
; i
++) {
13972 LHS(new_var
, i
)->id
|= TRIPLE_FLAG_FLATTENED
;
13975 /* Point everyone at the new variable */
13976 propogate_use(state
, var
, new_var
);
13978 /* Release the original variable */
13979 for(i
= 0; i
< var
->lhs
; i
++) {
13980 release_triple(state
, LHS(var
, i
));
13982 release_triple(state
, var
);
13984 /* Return the index of the added closure type */
13985 return ctype
->elements
- 1;
13988 static struct triple
*closure_expr(struct compile_state
*state
,
13989 struct triple
*func
, int closure_idx
, int var_idx
)
13991 return deref_index(state
,
13993 deref_index(state
, fresult(state
, func
), 0),
13999 static void insert_triple_set(
14000 struct triple_reg_set
**head
, struct triple
*member
)
14002 struct triple_reg_set
*new;
14003 new = xcmalloc(sizeof(*new), "triple_set");
14004 new->member
= member
;
14010 static int ordered_triple_set(
14011 struct triple_reg_set
**head
, struct triple
*member
)
14013 struct triple_reg_set
**ptr
;
14018 if (member
== (*ptr
)->member
) {
14021 /* keep the list ordered */
14022 if (member
->id
< (*ptr
)->member
->id
) {
14025 ptr
= &(*ptr
)->next
;
14027 insert_triple_set(ptr
, member
);
14032 static void free_closure_variables(struct compile_state
*state
,
14033 struct triple_reg_set
**enclose
)
14035 struct triple_reg_set
*entry
, *next
;
14036 for(entry
= *enclose
; entry
; entry
= next
) {
14037 next
= entry
->next
;
14038 do_triple_unset(enclose
, entry
->member
);
14042 static int lookup_closure_index(struct compile_state
*state
,
14043 struct triple
*me
, struct triple
*val
)
14045 struct triple
*first
, *ins
, *next
;
14046 first
= RHS(me
, 0);
14047 ins
= next
= first
;
14049 struct triple
*result
;
14050 struct triple
*index0
, *index1
, *index2
, *read
, *write
;
14053 if (ins
->op
!= OP_CALL
) {
14056 /* I am at a previous call point examine it closely */
14057 if (ins
->next
->op
!= OP_LABEL
) {
14058 internal_error(state
, ins
, "call not followed by label");
14060 /* Does this call does not enclose any variables? */
14061 if ((ins
->next
->next
->op
!= OP_INDEX
) ||
14062 (ins
->next
->next
->u
.cval
!= 0) ||
14063 (result
= MISC(ins
->next
->next
, 0)) ||
14064 (result
->id
& TRIPLE_FLAG_LOCAL
)) {
14067 index0
= ins
->next
->next
;
14069 * 0 index result < 0 >
14075 for(index0
= ins
->next
->next
;
14076 (index0
->op
== OP_INDEX
) &&
14077 (MISC(index0
, 0) == result
) &&
14078 (index0
->u
.cval
== 0) ;
14079 index0
= write
->next
)
14081 index1
= index0
->next
;
14082 index2
= index1
->next
;
14083 read
= index2
->next
;
14084 write
= read
->next
;
14085 if ((index0
->op
!= OP_INDEX
) ||
14086 (index1
->op
!= OP_INDEX
) ||
14087 (index2
->op
!= OP_INDEX
) ||
14088 (read
->op
!= OP_READ
) ||
14089 (write
->op
!= OP_WRITE
) ||
14090 (MISC(index1
, 0) != index0
) ||
14091 (MISC(index2
, 0) != index1
) ||
14092 (RHS(read
, 0) != index2
) ||
14093 (RHS(write
, 0) != read
)) {
14094 internal_error(state
, index0
, "bad var read");
14096 if (MISC(write
, 0) == val
) {
14097 return index2
->u
.cval
;
14100 } while(next
!= first
);
14104 static inline int enclose_triple(struct triple
*ins
)
14106 return (ins
&& ((ins
->type
->type
& TYPE_MASK
) != TYPE_VOID
));
14109 static void compute_closure_variables(struct compile_state
*state
,
14110 struct triple
*me
, struct triple
*fcall
, struct triple_reg_set
**enclose
)
14112 struct triple_reg_set
*set
, *vars
, **last_var
;
14113 struct basic_blocks bb
;
14114 struct reg_block
*rb
;
14115 struct block
*block
;
14116 struct triple
*old_result
, *first
, *ins
;
14118 unsigned long used_indicies
;
14120 #define MAX_INDICIES (sizeof(used_indicies)*CHAR_BIT)
14121 #define ID_BITS(X) ((X) & (TRIPLE_FLAG_LOCAL -1))
14128 /* Find the basic blocks of this function */
14130 bb
.first
= RHS(me
, 0);
14132 if (!triple_is_ret(state
, bb
.first
->prev
)) {
14135 old_result
= fresult(state
, me
);
14137 analyze_basic_blocks(state
, &bb
);
14139 /* Find which variables are currently alive in a given block */
14140 rb
= compute_variable_lifetimes(state
, &bb
);
14142 /* Find the variables that are currently alive */
14143 block
= block_of_triple(state
, fcall
);
14144 if (!block
|| (block
->vertex
<= 0) || (block
->vertex
> bb
.last_vertex
)) {
14145 internal_error(state
, fcall
, "No reg block? block: %p", block
);
14148 #if DEBUG_EXPLICIT_CLOSURES
14149 print_live_variables(state
, &bb
, rb
, state
->dbgout
);
14150 fflush(state
->dbgout
);
14153 /* Count the number of triples in the function */
14154 first
= RHS(me
, 0);
14160 } while(ins
!= first
);
14162 /* Allocate some memory to temorary hold the id info */
14163 info
= xcmalloc(sizeof(*info
) * (count
+1), "info");
14165 /* Mark the local function */
14166 first
= RHS(me
, 0);
14170 info
[idx
].id
= ins
->id
;
14171 ins
->id
= TRIPLE_FLAG_LOCAL
| idx
;
14174 } while(ins
!= first
);
14177 * Build the list of variables to enclose.
14179 * A target it to put the same variable in the
14180 * same slot for ever call of a given function.
14181 * After coloring this removes all of the variable
14182 * manipulation code.
14184 * The list of variables to enclose is built ordered
14185 * program order because except in corner cases this
14186 * gives me the stability of assignment I need.
14188 * To gurantee that stability I lookup the variables
14189 * to see where they have been used before and
14190 * I build my final list with the assigned indicies.
14193 if (enclose_triple(old_result
)) {
14194 ordered_triple_set(&vars
, old_result
);
14196 for(set
= rb
[block
->vertex
].out
; set
; set
= set
->next
) {
14197 if (!enclose_triple(set
->member
)) {
14200 if ((set
->member
== fcall
) || (set
->member
== old_result
)) {
14203 if (!local_triple(state
, me
, set
->member
)) {
14204 internal_error(state
, set
->member
, "not local?");
14206 ordered_triple_set(&vars
, set
->member
);
14209 /* Lookup the current indicies of the live varialbe */
14212 for(set
= vars
; set
; set
= set
->next
) {
14213 struct triple
*ins
;
14216 index
= lookup_closure_index(state
, me
, ins
);
14217 info
[ID_BITS(ins
->id
)].index
= index
;
14221 if (index
>= MAX_INDICIES
) {
14222 internal_error(state
, ins
, "index unexpectedly large");
14224 if (used_indicies
& (1 << index
)) {
14225 internal_error(state
, ins
, "index previously used?");
14227 /* Remember which indicies have been used */
14228 used_indicies
|= (1 << index
);
14229 if (index
> max_index
) {
14234 /* Walk through the live variables and make certain
14235 * everything is assigned an index.
14237 for(set
= vars
; set
; set
= set
->next
) {
14238 struct triple
*ins
;
14241 index
= info
[ID_BITS(ins
->id
)].index
;
14245 /* Find the lowest unused index value */
14246 for(index
= 0; index
< MAX_INDICIES
; index
++) {
14247 if (!(used_indicies
& (1 << index
))) {
14251 if (index
== MAX_INDICIES
) {
14252 internal_error(state
, ins
, "no free indicies?");
14254 info
[ID_BITS(ins
->id
)].index
= index
;
14255 /* Remember which indicies have been used */
14256 used_indicies
|= (1 << index
);
14257 if (index
> max_index
) {
14262 /* Build the return list of variables with positions matching
14266 last_var
= enclose
;
14267 for(i
= 0; i
<= max_index
; i
++) {
14268 struct triple
*var
;
14270 if (used_indicies
& (1 << i
)) {
14271 for(set
= vars
; set
; set
= set
->next
) {
14273 index
= info
[ID_BITS(set
->member
->id
)].index
;
14280 internal_error(state
, me
, "missing variable");
14283 insert_triple_set(last_var
, var
);
14284 last_var
= &(*last_var
)->next
;
14287 #if DEBUG_EXPLICIT_CLOSURES
14288 /* Print out the variables to be enclosed */
14289 loc(state
->dbgout
, state
, fcall
);
14290 fprintf(state
->dbgout
, "Alive: \n");
14291 for(set
= *enclose
; set
; set
= set
->next
) {
14292 display_triple(state
->dbgout
, set
->member
);
14294 fflush(state
->dbgout
);
14297 /* Clear the marks */
14300 ins
->id
= info
[ID_BITS(ins
->id
)].id
;
14302 } while(ins
!= first
);
14304 /* Release the ordered list of live variables */
14305 free_closure_variables(state
, &vars
);
14307 /* Release the storage of the old ids */
14310 /* Release the variable lifetime information */
14311 free_variable_lifetimes(state
, &bb
, rb
);
14313 /* Release the basic blocks of this function */
14314 free_basic_blocks(state
, &bb
);
14317 static void expand_function_call(
14318 struct compile_state
*state
, struct triple
*me
, struct triple
*fcall
)
14320 /* Generate an ordinary function call */
14321 struct type
*closure_type
, **closure_next
;
14322 struct triple
*func
, *func_first
, *func_last
, *retvar
;
14323 struct triple
*first
;
14324 struct type
*ptype
, *rtype
;
14325 struct triple
*ret_addr
, *ret_loc
;
14326 struct triple_reg_set
*enclose
, *set
;
14327 int closure_idx
, pvals
, i
;
14329 #if DEBUG_EXPLICIT_CLOSURES
14330 FILE *fp
= state
->dbgout
;
14331 fprintf(fp
, "\ndisplay_func(me) ptr: %p\n", fcall
);
14332 display_func(state
, fp
, MISC(fcall
, 0));
14333 display_func(state
, fp
, me
);
14334 fprintf(fp
, "__________ %s _________ done\n\n", __FUNCTION__
);
14337 /* Find the triples */
14338 func
= MISC(fcall
, 0);
14339 func_first
= RHS(func
, 0);
14340 retvar
= fretaddr(state
, func
);
14341 func_last
= func_first
->prev
;
14342 first
= fcall
->next
;
14344 /* Find what I need to enclose */
14345 compute_closure_variables(state
, me
, fcall
, &enclose
);
14347 /* Compute the closure type */
14348 closure_type
= new_type(TYPE_TUPLE
, 0, 0);
14349 closure_type
->elements
= 0;
14350 closure_next
= &closure_type
->left
;
14351 for(set
= enclose
; set
; set
= set
->next
) {
14355 type
= set
->member
->type
;
14357 if (!*closure_next
) {
14358 *closure_next
= type
;
14360 *closure_next
= new_type(TYPE_PRODUCT
, *closure_next
,
14362 closure_next
= &(*closure_next
)->right
;
14364 closure_type
->elements
+= 1;
14366 if (closure_type
->elements
== 0) {
14367 closure_type
->type
= TYPE_VOID
;
14371 #if DEBUG_EXPLICIT_CLOSURES
14372 fprintf(state
->dbgout
, "closure type: ");
14373 name_of(state
->dbgout
, closure_type
);
14374 fprintf(state
->dbgout
, "\n");
14377 /* Update the called functions closure variable */
14378 closure_idx
= add_closure_type(state
, func
, closure_type
);
14380 /* Generate some needed triples */
14381 ret_loc
= label(state
);
14382 ret_addr
= triple(state
, OP_ADDRCONST
, &void_ptr_type
, ret_loc
, 0);
14384 /* Pass the parameters to the new function */
14385 ptype
= func
->type
->right
;
14386 pvals
= fcall
->rhs
;
14387 for(i
= 0; i
< pvals
; i
++) {
14388 struct type
*atype
;
14389 struct triple
*arg
, *param
;
14391 if ((ptype
->type
& TYPE_MASK
) == TYPE_PRODUCT
) {
14392 atype
= ptype
->left
;
14394 param
= farg(state
, func
, i
);
14395 if ((param
->type
->type
& TYPE_MASK
) != (atype
->type
& TYPE_MASK
)) {
14396 internal_error(state
, fcall
, "param type mismatch");
14398 arg
= RHS(fcall
, i
);
14399 flatten(state
, first
, write_expr(state
, param
, arg
));
14400 ptype
= ptype
->right
;
14402 rtype
= func
->type
->left
;
14404 /* Thread the triples together */
14405 ret_loc
= flatten(state
, first
, ret_loc
);
14407 /* Save the active variables in the result variable */
14408 for(i
= 0, set
= enclose
; set
; set
= set
->next
, i
++) {
14409 if (!set
->member
) {
14412 flatten(state
, ret_loc
,
14414 closure_expr(state
, func
, closure_idx
, i
),
14415 read_expr(state
, set
->member
)));
14418 /* Initialize the return value */
14419 if ((rtype
->type
& TYPE_MASK
) != TYPE_VOID
) {
14420 flatten(state
, ret_loc
,
14422 deref_index(state
, fresult(state
, func
), 1),
14423 new_triple(state
, OP_UNKNOWNVAL
, rtype
, 0, 0)));
14426 ret_addr
= flatten(state
, ret_loc
, ret_addr
);
14427 flatten(state
, ret_loc
, write_expr(state
, retvar
, ret_addr
));
14428 flatten(state
, ret_loc
,
14429 call(state
, retvar
, ret_addr
, func_first
, func_last
));
14431 /* Find the result */
14432 if ((rtype
->type
& TYPE_MASK
) != TYPE_VOID
) {
14433 struct triple
* result
;
14434 result
= flatten(state
, first
,
14436 deref_index(state
, fresult(state
, func
), 1)));
14438 propogate_use(state
, fcall
, result
);
14441 /* Release the original fcall instruction */
14442 release_triple(state
, fcall
);
14444 /* Restore the active variables from the result variable */
14445 for(i
= 0, set
= enclose
; set
; set
= set
->next
, i
++) {
14446 struct triple_set
*use
, *next
;
14447 struct triple
*new;
14448 struct basic_blocks bb
;
14449 if (!set
->member
|| (set
->member
== fcall
)) {
14452 /* Generate an expression for the value */
14453 new = flatten(state
, first
,
14455 closure_expr(state
, func
, closure_idx
, i
)));
14458 /* If the original is an lvalue restore the preserved value */
14459 if (is_lvalue(state
, set
->member
)) {
14460 flatten(state
, first
,
14461 write_expr(state
, set
->member
, new));
14465 * If the original is a value update the dominated uses.
14468 /* Analyze the basic blocks so I can see who dominates whom */
14470 bb
.first
= RHS(me
, 0);
14471 if (!triple_is_ret(state
, bb
.first
->prev
)) {
14474 analyze_basic_blocks(state
, &bb
);
14477 #if DEBUG_EXPLICIT_CLOSURES
14478 fprintf(state
->errout
, "Updating domindated uses: %p -> %p\n",
14481 /* If fcall dominates the use update the expression */
14482 for(use
= set
->member
->use
; use
; use
= next
) {
14483 /* Replace use modifies the use chain and
14484 * removes use, so I must take a copy of the
14485 * next entry early.
14488 if (!tdominates(state
, fcall
, use
->member
)) {
14491 replace_use(state
, set
->member
, new, use
->member
);
14494 /* Release the basic blocks, the instructions will be
14495 * different next time, and flatten/insert_triple does
14496 * not update the block values so I can't cache the analysis.
14498 free_basic_blocks(state
, &bb
);
14501 /* Release the closure variable list */
14502 free_closure_variables(state
, &enclose
);
14504 if (state
->compiler
->debug
& DEBUG_INLINE
) {
14505 FILE *fp
= state
->dbgout
;
14508 fprintf(fp
, "\n__________ %s _________\n", __FUNCTION__
);
14509 display_func(state
, fp
, func
);
14510 display_func(state
, fp
, me
);
14511 fprintf(fp
, "__________ %s _________ done\n\n", __FUNCTION__
);
14517 static int do_inline(struct compile_state
*state
, struct triple
*func
)
14522 policy
= state
->compiler
->flags
& COMPILER_INLINE_MASK
;
14524 case COMPILER_INLINE_ALWAYS
:
14526 if (func
->type
->type
& ATTRIB_NOINLINE
) {
14527 error(state
, func
, "noinline with always_inline compiler option");
14530 case COMPILER_INLINE_NEVER
:
14532 if (func
->type
->type
& ATTRIB_ALWAYS_INLINE
) {
14533 error(state
, func
, "always_inline with noinline compiler option");
14536 case COMPILER_INLINE_DEFAULTON
:
14537 switch(func
->type
->type
& STOR_MASK
) {
14538 case STOR_STATIC
| STOR_INLINE
:
14539 case STOR_LOCAL
| STOR_INLINE
:
14540 case STOR_EXTERN
| STOR_INLINE
:
14548 case COMPILER_INLINE_DEFAULTOFF
:
14549 switch(func
->type
->type
& STOR_MASK
) {
14550 case STOR_STATIC
| STOR_INLINE
:
14551 case STOR_LOCAL
| STOR_INLINE
:
14552 case STOR_EXTERN
| STOR_INLINE
:
14560 case COMPILER_INLINE_NOPENALTY
:
14561 switch(func
->type
->type
& STOR_MASK
) {
14562 case STOR_STATIC
| STOR_INLINE
:
14563 case STOR_LOCAL
| STOR_INLINE
:
14564 case STOR_EXTERN
| STOR_INLINE
:
14568 do_inline
= (func
->u
.cval
== 1);
14574 internal_error(state
, 0, "Unimplemented inline policy");
14577 /* Force inlining */
14578 if (func
->type
->type
& ATTRIB_NOINLINE
) {
14581 if (func
->type
->type
& ATTRIB_ALWAYS_INLINE
) {
14587 static void inline_function(struct compile_state
*state
, struct triple
*me
, void *arg
)
14589 struct triple
*first
, *ptr
, *next
;
14590 /* If the function is not used don't bother */
14591 if (me
->u
.cval
<= 0) {
14594 if (state
->compiler
->debug
& DEBUG_CALLS2
) {
14595 FILE *fp
= state
->dbgout
;
14596 fprintf(fp
, "in: %s\n",
14597 me
->type
->type_ident
->name
);
14600 first
= RHS(me
, 0);
14601 ptr
= next
= first
;
14603 struct triple
*func
, *prev
;
14607 if (ptr
->op
!= OP_FCALL
) {
14610 func
= MISC(ptr
, 0);
14611 /* See if the function should be inlined */
14612 if (!do_inline(state
, func
)) {
14613 /* Put a label after the fcall */
14614 post_triple(state
, ptr
, OP_LABEL
, &void_type
, 0, 0);
14617 if (state
->compiler
->debug
& DEBUG_CALLS
) {
14618 FILE *fp
= state
->dbgout
;
14619 if (state
->compiler
->debug
& DEBUG_CALLS2
) {
14620 loc(fp
, state
, ptr
);
14622 fprintf(fp
, "inlining %s\n",
14623 func
->type
->type_ident
->name
);
14627 /* Update the function use counts */
14630 /* Replace the fcall with the called function */
14631 expand_inline_call(state
, me
, ptr
);
14634 } while (next
!= first
);
14636 ptr
= next
= first
;
14638 struct triple
*prev
, *func
;
14642 if (ptr
->op
!= OP_FCALL
) {
14645 func
= MISC(ptr
, 0);
14646 if (state
->compiler
->debug
& DEBUG_CALLS
) {
14647 FILE *fp
= state
->dbgout
;
14648 if (state
->compiler
->debug
& DEBUG_CALLS2
) {
14649 loc(fp
, state
, ptr
);
14651 fprintf(fp
, "calling %s\n",
14652 func
->type
->type_ident
->name
);
14655 /* Replace the fcall with the instruction sequence
14656 * needed to make the call.
14658 expand_function_call(state
, me
, ptr
);
14660 } while(next
!= first
);
14663 static void inline_functions(struct compile_state
*state
, struct triple
*func
)
14665 inline_function(state
, func
, 0);
14666 reverse_walk_functions(state
, inline_function
, 0);
14669 static void insert_function(struct compile_state
*state
,
14670 struct triple
*func
, void *arg
)
14672 struct triple
*first
, *end
, *ffirst
, *fend
;
14674 if (state
->compiler
->debug
& DEBUG_INLINE
) {
14675 FILE *fp
= state
->errout
;
14676 fprintf(fp
, "%s func count: %d\n",
14677 func
->type
->type_ident
->name
, func
->u
.cval
);
14679 if (func
->u
.cval
== 0) {
14683 /* Find the end points of the lists */
14686 ffirst
= RHS(func
, 0);
14687 fend
= ffirst
->prev
;
14689 /* splice the lists together */
14690 end
->next
= ffirst
;
14691 ffirst
->prev
= end
;
14692 fend
->next
= first
;
14693 first
->prev
= fend
;
14696 struct triple
*input_asm(struct compile_state
*state
)
14698 struct asm_info
*info
;
14699 struct triple
*def
;
14702 info
= xcmalloc(sizeof(*info
), "asm_info");
14705 out
= sizeof(arch_input_regs
)/sizeof(arch_input_regs
[0]);
14706 memcpy(&info
->tmpl
.lhs
, arch_input_regs
, sizeof(arch_input_regs
));
14708 def
= new_triple(state
, OP_ASM
, &void_type
, out
, 0);
14709 def
->u
.ainfo
= info
;
14710 def
->id
|= TRIPLE_FLAG_VOLATILE
;
14712 for(i
= 0; i
< out
; i
++) {
14713 struct triple
*piece
;
14714 piece
= triple(state
, OP_PIECE
, &int_type
, def
, 0);
14716 LHS(def
, i
) = piece
;
14722 struct triple
*output_asm(struct compile_state
*state
)
14724 struct asm_info
*info
;
14725 struct triple
*def
;
14728 info
= xcmalloc(sizeof(*info
), "asm_info");
14731 in
= sizeof(arch_output_regs
)/sizeof(arch_output_regs
[0]);
14732 memcpy(&info
->tmpl
.rhs
, arch_output_regs
, sizeof(arch_output_regs
));
14734 def
= new_triple(state
, OP_ASM
, &void_type
, 0, in
);
14735 def
->u
.ainfo
= info
;
14736 def
->id
|= TRIPLE_FLAG_VOLATILE
;
14741 static void join_functions(struct compile_state
*state
)
14743 struct triple
*start
, *end
, *call
, *in
, *out
, *func
;
14744 struct file_state file
;
14745 struct type
*pnext
, *param
;
14746 struct type
*result_type
, *args_type
;
14749 /* Be clear the functions have not been joined yet */
14750 state
->functions_joined
= 0;
14752 /* Dummy file state to get debug handing right */
14753 memset(&file
, 0, sizeof(file
));
14754 file
.basename
= "";
14756 file
.report_line
= 0;
14757 file
.report_name
= file
.basename
;
14758 file
.prev
= state
->file
;
14759 state
->file
= &file
;
14760 state
->function
= "";
14762 if (!state
->main_function
) {
14763 error(state
, 0, "No functions to compile\n");
14766 /* The type of arguments */
14767 args_type
= state
->main_function
->type
->right
;
14768 /* The return type without any specifiers */
14769 result_type
= clone_type(0, state
->main_function
->type
->left
);
14772 /* Verify the external arguments */
14773 if (registers_of(state
, args_type
) > ARCH_INPUT_REGS
) {
14774 error(state
, state
->main_function
,
14775 "Too many external input arguments");
14777 if (registers_of(state
, result_type
) > ARCH_OUTPUT_REGS
) {
14778 error(state
, state
->main_function
,
14779 "Too many external output arguments");
14782 /* Lay down the basic program structure */
14783 end
= label(state
);
14784 start
= label(state
);
14785 start
= flatten(state
, state
->first
, start
);
14786 end
= flatten(state
, state
->first
, end
);
14787 in
= input_asm(state
);
14788 out
= output_asm(state
);
14789 call
= new_triple(state
, OP_FCALL
, result_type
, -1, registers_of(state
, args_type
));
14790 MISC(call
, 0) = state
->main_function
;
14791 in
= flatten(state
, state
->first
, in
);
14792 call
= flatten(state
, state
->first
, call
);
14793 out
= flatten(state
, state
->first
, out
);
14796 /* Read the external input arguments */
14799 while(pnext
&& ((pnext
->type
& TYPE_MASK
) != TYPE_VOID
)) {
14800 struct triple
*expr
;
14803 if ((param
->type
& TYPE_MASK
) == TYPE_PRODUCT
) {
14804 pnext
= param
->right
;
14805 param
= param
->left
;
14807 if (registers_of(state
, param
) != 1) {
14808 error(state
, state
->main_function
,
14809 "Arg: %d %s requires multiple registers",
14810 idx
+ 1, param
->field_ident
->name
);
14812 expr
= read_expr(state
, LHS(in
, idx
));
14813 RHS(call
, idx
) = expr
;
14814 expr
= flatten(state
, call
, expr
);
14815 use_triple(expr
, call
);
14821 /* Write the external output arguments */
14822 pnext
= result_type
;
14823 if ((pnext
->type
& TYPE_MASK
) == TYPE_STRUCT
) {
14824 pnext
= result_type
->left
;
14826 for(idx
= 0; idx
< out
->rhs
; idx
++) {
14827 struct triple
*expr
;
14830 if (param
&& ((param
->type
& TYPE_MASK
) == TYPE_PRODUCT
)) {
14831 pnext
= param
->right
;
14832 param
= param
->left
;
14834 if (param
&& ((param
->type
& TYPE_MASK
) == TYPE_VOID
)) {
14838 if (registers_of(state
, param
) != 1) {
14839 error(state
, state
->main_function
,
14840 "Result: %d %s requires multiple registers",
14841 idx
, param
->field_ident
->name
);
14843 expr
= read_expr(state
, call
);
14844 if ((result_type
->type
& TYPE_MASK
) == TYPE_STRUCT
) {
14845 expr
= deref_field(state
, expr
, param
->field_ident
);
14848 expr
= triple(state
, OP_UNKNOWNVAL
, &int_type
, 0, 0);
14850 flatten(state
, out
, expr
);
14851 RHS(out
, idx
) = expr
;
14852 use_triple(expr
, out
);
14855 /* Allocate a dummy containing function */
14856 func
= triple(state
, OP_LIST
,
14857 new_type(TYPE_FUNCTION
, &void_type
, &void_type
), 0, 0);
14858 func
->type
->type_ident
= lookup(state
, "", 0);
14859 RHS(func
, 0) = state
->first
;
14862 /* See which functions are called, and how often */
14863 mark_live_functions(state
);
14864 inline_functions(state
, func
);
14865 walk_functions(state
, insert_function
, end
);
14867 if (start
->next
!= end
) {
14868 flatten(state
, start
, branch(state
, end
, 0));
14871 /* OK now the functions have been joined. */
14872 state
->functions_joined
= 1;
14874 /* Done now cleanup */
14875 state
->file
= file
.prev
;
14876 state
->function
= 0;
14880 * Data structurs for optimation.
14884 static int do_use_block(
14885 struct block
*used
, struct block_set
**head
, struct block
*user
,
14888 struct block_set
**ptr
, *new;
14895 if ((*ptr
)->member
== user
) {
14898 ptr
= &(*ptr
)->next
;
14900 new = xcmalloc(sizeof(*new), "block_set");
14901 new->member
= user
;
14912 static int do_unuse_block(
14913 struct block
*used
, struct block_set
**head
, struct block
*unuser
)
14915 struct block_set
*use
, **ptr
;
14921 if (use
->member
== unuser
) {
14923 memset(use
, -1, sizeof(*use
));
14934 static void use_block(struct block
*used
, struct block
*user
)
14937 /* Append new to the head of the list, print_block
14940 count
= do_use_block(used
, &used
->use
, user
, 1);
14941 used
->users
+= count
;
14943 static void unuse_block(struct block
*used
, struct block
*unuser
)
14946 count
= do_unuse_block(used
, &used
->use
, unuser
);
14947 used
->users
-= count
;
14950 static void add_block_edge(struct block
*block
, struct block
*edge
, int front
)
14953 count
= do_use_block(block
, &block
->edges
, edge
, front
);
14954 block
->edge_count
+= count
;
14957 static void remove_block_edge(struct block
*block
, struct block
*edge
)
14960 count
= do_unuse_block(block
, &block
->edges
, edge
);
14961 block
->edge_count
-= count
;
14964 static void idom_block(struct block
*idom
, struct block
*user
)
14966 do_use_block(idom
, &idom
->idominates
, user
, 0);
14969 static void unidom_block(struct block
*idom
, struct block
*unuser
)
14971 do_unuse_block(idom
, &idom
->idominates
, unuser
);
14974 static void domf_block(struct block
*block
, struct block
*domf
)
14976 do_use_block(block
, &block
->domfrontier
, domf
, 0);
14979 static void undomf_block(struct block
*block
, struct block
*undomf
)
14981 do_unuse_block(block
, &block
->domfrontier
, undomf
);
14984 static void ipdom_block(struct block
*ipdom
, struct block
*user
)
14986 do_use_block(ipdom
, &ipdom
->ipdominates
, user
, 0);
14989 static void unipdom_block(struct block
*ipdom
, struct block
*unuser
)
14991 do_unuse_block(ipdom
, &ipdom
->ipdominates
, unuser
);
14994 static void ipdomf_block(struct block
*block
, struct block
*ipdomf
)
14996 do_use_block(block
, &block
->ipdomfrontier
, ipdomf
, 0);
14999 static void unipdomf_block(struct block
*block
, struct block
*unipdomf
)
15001 do_unuse_block(block
, &block
->ipdomfrontier
, unipdomf
);
15004 static int walk_triples(
15005 struct compile_state
*state
,
15006 int (*cb
)(struct compile_state
*state
, struct triple
*ptr
, void *arg
),
15009 struct triple
*ptr
;
15011 ptr
= state
->first
;
15013 result
= cb(state
, ptr
, arg
);
15014 if (ptr
->next
->prev
!= ptr
) {
15015 internal_error(state
, ptr
->next
, "bad prev");
15018 } while((result
== 0) && (ptr
!= state
->first
));
15022 #define PRINT_LIST 1
15023 static int do_print_triple(struct compile_state
*state
, struct triple
*ins
, void *arg
)
15028 if (op
== OP_LIST
) {
15033 if ((op
== OP_LABEL
) && (ins
->use
)) {
15034 fprintf(fp
, "\n%p:\n", ins
);
15036 display_triple(fp
, ins
);
15038 if (triple_is_branch(state
, ins
) && ins
->use
&&
15039 (ins
->op
!= OP_RET
) && (ins
->op
!= OP_FCALL
)) {
15040 internal_error(state
, ins
, "branch used?");
15042 if (triple_is_branch(state
, ins
)) {
15048 static void print_triples(struct compile_state
*state
)
15050 if (state
->compiler
->debug
& DEBUG_TRIPLES
) {
15051 FILE *fp
= state
->dbgout
;
15052 fprintf(fp
, "--------------- triples ---------------\n");
15053 walk_triples(state
, do_print_triple
, fp
);
15059 struct block
*block
;
15061 static void find_cf_blocks(struct cf_block
*cf
, struct block
*block
)
15063 struct block_set
*edge
;
15064 if (!block
|| (cf
[block
->vertex
].block
== block
)) {
15067 cf
[block
->vertex
].block
= block
;
15068 for(edge
= block
->edges
; edge
; edge
= edge
->next
) {
15069 find_cf_blocks(cf
, edge
->member
);
15073 static void print_control_flow(struct compile_state
*state
,
15074 FILE *fp
, struct basic_blocks
*bb
)
15076 struct cf_block
*cf
;
15078 fprintf(fp
, "\ncontrol flow\n");
15079 cf
= xcmalloc(sizeof(*cf
) * (bb
->last_vertex
+ 1), "cf_block");
15080 find_cf_blocks(cf
, bb
->first_block
);
15082 for(i
= 1; i
<= bb
->last_vertex
; i
++) {
15083 struct block
*block
;
15084 struct block_set
*edge
;
15085 block
= cf
[i
].block
;
15088 fprintf(fp
, "(%p) %d:", block
, block
->vertex
);
15089 for(edge
= block
->edges
; edge
; edge
= edge
->next
) {
15090 fprintf(fp
, " %d", edge
->member
->vertex
);
15098 static void free_basic_block(struct compile_state
*state
, struct block
*block
)
15100 struct block_set
*edge
, *entry
;
15101 struct block
*child
;
15105 if (block
->vertex
== -1) {
15108 block
->vertex
= -1;
15109 for(edge
= block
->edges
; edge
; edge
= edge
->next
) {
15110 if (edge
->member
) {
15111 unuse_block(edge
->member
, block
);
15115 unidom_block(block
->idom
, block
);
15118 if (block
->ipdom
) {
15119 unipdom_block(block
->ipdom
, block
);
15122 while((entry
= block
->use
)) {
15123 child
= entry
->member
;
15124 unuse_block(block
, child
);
15125 if (child
&& (child
->vertex
!= -1)) {
15126 for(edge
= child
->edges
; edge
; edge
= edge
->next
) {
15131 while((entry
= block
->idominates
)) {
15132 child
= entry
->member
;
15133 unidom_block(block
, child
);
15134 if (child
&& (child
->vertex
!= -1)) {
15138 while((entry
= block
->domfrontier
)) {
15139 child
= entry
->member
;
15140 undomf_block(block
, child
);
15142 while((entry
= block
->ipdominates
)) {
15143 child
= entry
->member
;
15144 unipdom_block(block
, child
);
15145 if (child
&& (child
->vertex
!= -1)) {
15149 while((entry
= block
->ipdomfrontier
)) {
15150 child
= entry
->member
;
15151 unipdomf_block(block
, child
);
15153 if (block
->users
!= 0) {
15154 internal_error(state
, 0, "block still has users");
15156 while((edge
= block
->edges
)) {
15157 child
= edge
->member
;
15158 remove_block_edge(block
, child
);
15160 if (child
&& (child
->vertex
!= -1)) {
15161 free_basic_block(state
, child
);
15164 memset(block
, -1, sizeof(*block
));
15167 static void free_basic_blocks(struct compile_state
*state
,
15168 struct basic_blocks
*bb
)
15170 struct triple
*first
, *ins
;
15171 free_basic_block(state
, bb
->first_block
);
15172 bb
->last_vertex
= 0;
15173 bb
->first_block
= bb
->last_block
= 0;
15177 if (triple_stores_block(state
, ins
)) {
15181 } while(ins
!= first
);
15185 static struct block
*basic_block(struct compile_state
*state
,
15186 struct basic_blocks
*bb
, struct triple
*first
)
15188 struct block
*block
;
15189 struct triple
*ptr
;
15190 if (!triple_is_label(state
, first
)) {
15191 internal_error(state
, first
, "block does not start with a label");
15193 /* See if this basic block has already been setup */
15194 if (first
->u
.block
!= 0) {
15195 return first
->u
.block
;
15197 /* Allocate another basic block structure */
15198 bb
->last_vertex
+= 1;
15199 block
= xcmalloc(sizeof(*block
), "block");
15200 block
->first
= block
->last
= first
;
15201 block
->vertex
= bb
->last_vertex
;
15204 if ((ptr
!= first
) && triple_is_label(state
, ptr
) && (ptr
->use
)) {
15208 /* If ptr->u is not used remember where the baic block is */
15209 if (triple_stores_block(state
, ptr
)) {
15210 ptr
->u
.block
= block
;
15212 if (triple_is_branch(state
, ptr
)) {
15216 } while (ptr
!= bb
->first
);
15217 if ((ptr
== bb
->first
) ||
15218 ((ptr
->next
== bb
->first
) && (
15219 triple_is_end(state
, ptr
) ||
15220 triple_is_ret(state
, ptr
))))
15222 /* The block has no outflowing edges */
15224 else if (triple_is_label(state
, ptr
)) {
15225 struct block
*next
;
15226 next
= basic_block(state
, bb
, ptr
);
15227 add_block_edge(block
, next
, 0);
15228 use_block(next
, block
);
15230 else if (triple_is_branch(state
, ptr
)) {
15231 struct triple
**expr
, *first
;
15232 struct block
*child
;
15233 /* Find the branch targets.
15234 * I special case the first branch as that magically
15235 * avoids some difficult cases for the register allocator.
15237 expr
= triple_edge_targ(state
, ptr
, 0);
15239 internal_error(state
, ptr
, "branch without targets");
15242 expr
= triple_edge_targ(state
, ptr
, expr
);
15243 for(; expr
; expr
= triple_edge_targ(state
, ptr
, expr
)) {
15244 if (!*expr
) continue;
15245 child
= basic_block(state
, bb
, *expr
);
15246 use_block(child
, block
);
15247 add_block_edge(block
, child
, 0);
15250 child
= basic_block(state
, bb
, first
);
15251 use_block(child
, block
);
15252 add_block_edge(block
, child
, 1);
15254 /* Be certain the return block of a call is
15255 * in a basic block. When it is not find
15256 * start of the block, insert a label if
15257 * necessary and build the basic block.
15258 * Then add a fake edge from the start block
15259 * to the return block of the function.
15261 if (state
->functions_joined
&& triple_is_call(state
, ptr
)
15262 && !block_of_triple(state
, MISC(ptr
, 0))) {
15263 struct block
*tail
;
15264 struct triple
*start
;
15265 start
= triple_to_block_start(state
, MISC(ptr
, 0));
15266 if (!triple_is_label(state
, start
)) {
15267 start
= pre_triple(state
,
15268 start
, OP_LABEL
, &void_type
, 0, 0);
15270 tail
= basic_block(state
, bb
, start
);
15271 add_block_edge(child
, tail
, 0);
15272 use_block(tail
, child
);
15277 internal_error(state
, 0, "Bad basic block split");
15281 struct block_set
*edge
;
15282 FILE *fp
= state
->errout
;
15283 fprintf(fp
, "basic_block: %10p [%2d] ( %10p - %10p )",
15284 block
, block
->vertex
,
15285 block
->first
, block
->last
);
15286 for(edge
= block
->edges
; edge
; edge
= edge
->next
) {
15287 fprintf(fp
, " %10p [%2d]",
15288 edge
->member
? edge
->member
->first
: 0,
15289 edge
->member
? edge
->member
->vertex
: -1);
15298 static void walk_blocks(struct compile_state
*state
, struct basic_blocks
*bb
,
15299 void (*cb
)(struct compile_state
*state
, struct block
*block
, void *arg
),
15302 struct triple
*ptr
, *first
;
15303 struct block
*last_block
;
15308 if (triple_stores_block(state
, ptr
)) {
15309 struct block
*block
;
15310 block
= ptr
->u
.block
;
15311 if (block
&& (block
!= last_block
)) {
15312 cb(state
, block
, arg
);
15314 last_block
= block
;
15317 } while(ptr
!= first
);
15320 static void print_block(
15321 struct compile_state
*state
, struct block
*block
, void *arg
)
15323 struct block_set
*user
, *edge
;
15324 struct triple
*ptr
;
15327 fprintf(fp
, "\nblock: %p (%d) ",
15331 for(edge
= block
->edges
; edge
; edge
= edge
->next
) {
15332 fprintf(fp
, " %p<-%p",
15334 (edge
->member
&& edge
->member
->use
)?
15335 edge
->member
->use
->member
: 0);
15338 if (block
->first
->op
== OP_LABEL
) {
15339 fprintf(fp
, "%p:\n", block
->first
);
15341 for(ptr
= block
->first
; ; ) {
15342 display_triple(fp
, ptr
);
15343 if (ptr
== block
->last
)
15346 if (ptr
== block
->first
) {
15347 internal_error(state
, 0, "missing block last?");
15350 fprintf(fp
, "users %d: ", block
->users
);
15351 for(user
= block
->use
; user
; user
= user
->next
) {
15352 fprintf(fp
, "%p (%d) ",
15354 user
->member
->vertex
);
15356 fprintf(fp
,"\n\n");
15360 static void romcc_print_blocks(struct compile_state
*state
, FILE *fp
)
15362 fprintf(fp
, "--------------- blocks ---------------\n");
15363 walk_blocks(state
, &state
->bb
, print_block
, fp
);
15365 static void print_blocks(struct compile_state
*state
, const char *func
, FILE *fp
)
15367 if (state
->compiler
->debug
& DEBUG_BASIC_BLOCKS
) {
15368 fprintf(fp
, "After %s\n", func
);
15369 romcc_print_blocks(state
, fp
);
15370 if (state
->compiler
->debug
& DEBUG_FDOMINATORS
) {
15371 print_dominators(state
, fp
, &state
->bb
);
15372 print_dominance_frontiers(state
, fp
, &state
->bb
);
15374 print_control_flow(state
, fp
, &state
->bb
);
15378 static void prune_nonblock_triples(struct compile_state
*state
,
15379 struct basic_blocks
*bb
)
15381 struct block
*block
;
15382 struct triple
*first
, *ins
, *next
;
15383 /* Delete the triples not in a basic block */
15389 if (ins
->op
== OP_LABEL
) {
15390 block
= ins
->u
.block
;
15393 struct triple_set
*use
;
15394 for(use
= ins
->use
; use
; use
= use
->next
) {
15395 struct block
*block
;
15396 block
= block_of_triple(state
, use
->member
);
15398 internal_error(state
, ins
, "pruning used ins?");
15401 release_triple(state
, ins
);
15403 if (block
&& block
->last
== ins
) {
15407 } while(ins
!= first
);
15410 static void setup_basic_blocks(struct compile_state
*state
,
15411 struct basic_blocks
*bb
)
15413 if (!triple_stores_block(state
, bb
->first
)) {
15414 internal_error(state
, 0, "ins will not store block?");
15416 /* Initialize the state */
15417 bb
->first_block
= bb
->last_block
= 0;
15418 bb
->last_vertex
= 0;
15419 free_basic_blocks(state
, bb
);
15421 /* Find the basic blocks */
15422 bb
->first_block
= basic_block(state
, bb
, bb
->first
);
15424 /* Be certain the last instruction of a function, or the
15425 * entire program is in a basic block. When it is not find
15426 * the start of the block, insert a label if necessary and build
15427 * basic block. Then add a fake edge from the start block
15428 * to the final block.
15430 if (!block_of_triple(state
, bb
->first
->prev
)) {
15431 struct triple
*start
;
15432 struct block
*tail
;
15433 start
= triple_to_block_start(state
, bb
->first
->prev
);
15434 if (!triple_is_label(state
, start
)) {
15435 start
= pre_triple(state
,
15436 start
, OP_LABEL
, &void_type
, 0, 0);
15438 tail
= basic_block(state
, bb
, start
);
15439 add_block_edge(bb
->first_block
, tail
, 0);
15440 use_block(tail
, bb
->first_block
);
15443 /* Find the last basic block.
15445 bb
->last_block
= block_of_triple(state
, bb
->first
->prev
);
15447 /* Delete the triples not in a basic block */
15448 prune_nonblock_triples(state
, bb
);
15451 /* If we are debugging print what I have just done */
15452 if (state
->compiler
->debug
& DEBUG_BASIC_BLOCKS
) {
15453 print_blocks(state
, state
->dbgout
);
15454 print_control_flow(state
, bb
);
15460 struct sdom_block
{
15461 struct block
*block
;
15462 struct sdom_block
*sdominates
;
15463 struct sdom_block
*sdom_next
;
15464 struct sdom_block
*sdom
;
15465 struct sdom_block
*label
;
15466 struct sdom_block
*parent
;
15467 struct sdom_block
*ancestor
;
15472 static void unsdom_block(struct sdom_block
*block
)
15474 struct sdom_block
**ptr
;
15475 if (!block
->sdom_next
) {
15478 ptr
= &block
->sdom
->sdominates
;
15480 if ((*ptr
) == block
) {
15481 *ptr
= block
->sdom_next
;
15484 ptr
= &(*ptr
)->sdom_next
;
15488 static void sdom_block(struct sdom_block
*sdom
, struct sdom_block
*block
)
15490 unsdom_block(block
);
15491 block
->sdom
= sdom
;
15492 block
->sdom_next
= sdom
->sdominates
;
15493 sdom
->sdominates
= block
;
15498 static int initialize_sdblock(struct sdom_block
*sd
,
15499 struct block
*parent
, struct block
*block
, int vertex
)
15501 struct block_set
*edge
;
15502 if (!block
|| (sd
[block
->vertex
].block
== block
)) {
15506 /* Renumber the blocks in a convinient fashion */
15507 block
->vertex
= vertex
;
15508 sd
[vertex
].block
= block
;
15509 sd
[vertex
].sdom
= &sd
[vertex
];
15510 sd
[vertex
].label
= &sd
[vertex
];
15511 sd
[vertex
].parent
= parent
? &sd
[parent
->vertex
] : 0;
15512 sd
[vertex
].ancestor
= 0;
15513 sd
[vertex
].vertex
= vertex
;
15514 for(edge
= block
->edges
; edge
; edge
= edge
->next
) {
15515 vertex
= initialize_sdblock(sd
, block
, edge
->member
, vertex
);
15520 static int initialize_spdblock(
15521 struct compile_state
*state
, struct sdom_block
*sd
,
15522 struct block
*parent
, struct block
*block
, int vertex
)
15524 struct block_set
*user
;
15525 if (!block
|| (sd
[block
->vertex
].block
== block
)) {
15529 /* Renumber the blocks in a convinient fashion */
15530 block
->vertex
= vertex
;
15531 sd
[vertex
].block
= block
;
15532 sd
[vertex
].sdom
= &sd
[vertex
];
15533 sd
[vertex
].label
= &sd
[vertex
];
15534 sd
[vertex
].parent
= parent
? &sd
[parent
->vertex
] : 0;
15535 sd
[vertex
].ancestor
= 0;
15536 sd
[vertex
].vertex
= vertex
;
15537 for(user
= block
->use
; user
; user
= user
->next
) {
15538 vertex
= initialize_spdblock(state
, sd
, block
, user
->member
, vertex
);
15543 static int setup_spdblocks(struct compile_state
*state
,
15544 struct basic_blocks
*bb
, struct sdom_block
*sd
)
15546 struct block
*block
;
15548 /* Setup as many sdpblocks as possible without using fake edges */
15549 vertex
= initialize_spdblock(state
, sd
, 0, bb
->last_block
, 0);
15551 /* Walk through the graph and find unconnected blocks. Add a
15552 * fake edge from the unconnected blocks to the end of the
15555 block
= bb
->first_block
->last
->next
->u
.block
;
15556 for(; block
&& block
!= bb
->first_block
; block
= block
->last
->next
->u
.block
) {
15557 if (sd
[block
->vertex
].block
== block
) {
15560 #if DEBUG_SDP_BLOCKS
15562 FILE *fp
= state
->errout
;
15563 fprintf(fp
, "Adding %d\n", vertex
+1);
15566 add_block_edge(block
, bb
->last_block
, 0);
15567 use_block(bb
->last_block
, block
);
15569 vertex
= initialize_spdblock(state
, sd
, bb
->last_block
, block
, vertex
);
15574 static void compress_ancestors(struct sdom_block
*v
)
15576 /* This procedure assumes ancestor(v) != 0 */
15577 /* if (ancestor(ancestor(v)) != 0) {
15578 * compress(ancestor(ancestor(v)));
15579 * if (semi(label(ancestor(v))) < semi(label(v))) {
15580 * label(v) = label(ancestor(v));
15582 * ancestor(v) = ancestor(ancestor(v));
15585 if (!v
->ancestor
) {
15588 if (v
->ancestor
->ancestor
) {
15589 compress_ancestors(v
->ancestor
->ancestor
);
15590 if (v
->ancestor
->label
->sdom
->vertex
< v
->label
->sdom
->vertex
) {
15591 v
->label
= v
->ancestor
->label
;
15593 v
->ancestor
= v
->ancestor
->ancestor
;
15597 static void compute_sdom(struct compile_state
*state
,
15598 struct basic_blocks
*bb
, struct sdom_block
*sd
)
15602 * for each v <= pred(w) {
15604 * if (semi[u] < semi[w] {
15605 * semi[w] = semi[u];
15608 * add w to bucket(vertex(semi[w]));
15609 * LINK(parent(w), w);
15612 * for each v <= bucket(parent(w)) {
15613 * delete v from bucket(parent(w));
15615 * dom(v) = (semi[u] < semi[v]) ? u : parent(w);
15618 for(i
= bb
->last_vertex
; i
>= 2; i
--) {
15619 struct sdom_block
*v
, *parent
, *next
;
15620 struct block_set
*user
;
15621 struct block
*block
;
15622 block
= sd
[i
].block
;
15623 parent
= sd
[i
].parent
;
15625 for(user
= block
->use
; user
; user
= user
->next
) {
15626 struct sdom_block
*v
, *u
;
15627 v
= &sd
[user
->member
->vertex
];
15628 u
= !(v
->ancestor
)? v
: (compress_ancestors(v
), v
->label
);
15629 if (u
->sdom
->vertex
< sd
[i
].sdom
->vertex
) {
15630 sd
[i
].sdom
= u
->sdom
;
15633 sdom_block(sd
[i
].sdom
, &sd
[i
]);
15634 sd
[i
].ancestor
= parent
;
15636 for(v
= parent
->sdominates
; v
; v
= next
) {
15637 struct sdom_block
*u
;
15638 next
= v
->sdom_next
;
15640 u
= (!v
->ancestor
) ? v
: (compress_ancestors(v
), v
->label
);
15641 v
->block
->idom
= (u
->sdom
->vertex
< v
->sdom
->vertex
)?
15642 u
->block
: parent
->block
;
15647 static void compute_spdom(struct compile_state
*state
,
15648 struct basic_blocks
*bb
, struct sdom_block
*sd
)
15652 * for each v <= pred(w) {
15654 * if (semi[u] < semi[w] {
15655 * semi[w] = semi[u];
15658 * add w to bucket(vertex(semi[w]));
15659 * LINK(parent(w), w);
15662 * for each v <= bucket(parent(w)) {
15663 * delete v from bucket(parent(w));
15665 * dom(v) = (semi[u] < semi[v]) ? u : parent(w);
15668 for(i
= bb
->last_vertex
; i
>= 2; i
--) {
15669 struct sdom_block
*u
, *v
, *parent
, *next
;
15670 struct block_set
*edge
;
15671 struct block
*block
;
15672 block
= sd
[i
].block
;
15673 parent
= sd
[i
].parent
;
15675 for(edge
= block
->edges
; edge
; edge
= edge
->next
) {
15676 v
= &sd
[edge
->member
->vertex
];
15677 u
= !(v
->ancestor
)? v
: (compress_ancestors(v
), v
->label
);
15678 if (u
->sdom
->vertex
< sd
[i
].sdom
->vertex
) {
15679 sd
[i
].sdom
= u
->sdom
;
15682 sdom_block(sd
[i
].sdom
, &sd
[i
]);
15683 sd
[i
].ancestor
= parent
;
15685 for(v
= parent
->sdominates
; v
; v
= next
) {
15686 struct sdom_block
*u
;
15687 next
= v
->sdom_next
;
15689 u
= (!v
->ancestor
) ? v
: (compress_ancestors(v
), v
->label
);
15690 v
->block
->ipdom
= (u
->sdom
->vertex
< v
->sdom
->vertex
)?
15691 u
->block
: parent
->block
;
15696 static void compute_idom(struct compile_state
*state
,
15697 struct basic_blocks
*bb
, struct sdom_block
*sd
)
15700 for(i
= 2; i
<= bb
->last_vertex
; i
++) {
15701 struct block
*block
;
15702 block
= sd
[i
].block
;
15703 if (block
->idom
->vertex
!= sd
[i
].sdom
->vertex
) {
15704 block
->idom
= block
->idom
->idom
;
15706 idom_block(block
->idom
, block
);
15708 sd
[1].block
->idom
= 0;
15711 static void compute_ipdom(struct compile_state
*state
,
15712 struct basic_blocks
*bb
, struct sdom_block
*sd
)
15715 for(i
= 2; i
<= bb
->last_vertex
; i
++) {
15716 struct block
*block
;
15717 block
= sd
[i
].block
;
15718 if (block
->ipdom
->vertex
!= sd
[i
].sdom
->vertex
) {
15719 block
->ipdom
= block
->ipdom
->ipdom
;
15721 ipdom_block(block
->ipdom
, block
);
15723 sd
[1].block
->ipdom
= 0;
15727 * Every vertex of a flowgraph G = (V, E, r) except r has
15728 * a unique immediate dominator.
15729 * The edges {(idom(w), w) |w <= V - {r}} form a directed tree
15730 * rooted at r, called the dominator tree of G, such that
15731 * v dominates w if and only if v is a proper ancestor of w in
15732 * the dominator tree.
15735 * If v and w are vertices of G such that v <= w,
15736 * than any path from v to w must contain a common ancestor
15739 /* Lemma 2: For any vertex w != r, idom(w) -> w */
15740 /* Lemma 3: For any vertex w != r, sdom(w) -> w */
15741 /* Lemma 4: For any vertex w != r, idom(w) -> sdom(w) */
15743 * Let w != r. Suppose every u for which sdom(w) -> u -> w satisfies
15744 * sdom(u) >= sdom(w). Then idom(w) = sdom(w).
15747 * Let w != r and let u be a vertex for which sdom(u) is
15748 * minimum amoung vertices u satisfying sdom(w) -> u -> w.
15749 * Then sdom(u) <= sdom(w) and idom(u) = idom(w).
15751 /* Lemma 5: Let vertices v,w satisfy v -> w.
15752 * Then v -> idom(w) or idom(w) -> idom(v)
15755 static void find_immediate_dominators(struct compile_state
*state
,
15756 struct basic_blocks
*bb
)
15758 struct sdom_block
*sd
;
15759 /* w->sdom = min{v| there is a path v = v0,v1,...,vk = w such that:
15760 * vi > w for (1 <= i <= k - 1}
15763 * For any vertex w != r.
15765 * {v|(v,w) <= E and v < w } U
15766 * {sdom(u) | u > w and there is an edge (v, w) such that u -> v})
15769 * Let w != r and let u be a vertex for which sdom(u) is
15770 * minimum amoung vertices u satisfying sdom(w) -> u -> w.
15772 * { sdom(w) if sdom(w) = sdom(u),
15774 * { idom(u) otherwise
15776 /* The algorithm consists of the following 4 steps.
15777 * Step 1. Carry out a depth-first search of the problem graph.
15778 * Number the vertices from 1 to N as they are reached during
15779 * the search. Initialize the variables used in succeeding steps.
15780 * Step 2. Compute the semidominators of all vertices by applying
15781 * theorem 4. Carry out the computation vertex by vertex in
15782 * decreasing order by number.
15783 * Step 3. Implicitly define the immediate dominator of each vertex
15784 * by applying Corollary 1.
15785 * Step 4. Explicitly define the immediate dominator of each vertex,
15786 * carrying out the computation vertex by vertex in increasing order
15789 /* Step 1 initialize the basic block information */
15790 sd
= xcmalloc(sizeof(*sd
) * (bb
->last_vertex
+ 1), "sdom_state");
15791 initialize_sdblock(sd
, 0, bb
->first_block
, 0);
15797 /* Step 2 compute the semidominators */
15798 /* Step 3 implicitly define the immediate dominator of each vertex */
15799 compute_sdom(state
, bb
, sd
);
15800 /* Step 4 explicitly define the immediate dominator of each vertex */
15801 compute_idom(state
, bb
, sd
);
15805 static void find_post_dominators(struct compile_state
*state
,
15806 struct basic_blocks
*bb
)
15808 struct sdom_block
*sd
;
15810 /* Step 1 initialize the basic block information */
15811 sd
= xcmalloc(sizeof(*sd
) * (bb
->last_vertex
+ 1), "sdom_state");
15813 vertex
= setup_spdblocks(state
, bb
, sd
);
15814 if (vertex
!= bb
->last_vertex
) {
15815 internal_error(state
, 0, "missing %d blocks",
15816 bb
->last_vertex
- vertex
);
15819 /* Step 2 compute the semidominators */
15820 /* Step 3 implicitly define the immediate dominator of each vertex */
15821 compute_spdom(state
, bb
, sd
);
15822 /* Step 4 explicitly define the immediate dominator of each vertex */
15823 compute_ipdom(state
, bb
, sd
);
15829 static void find_block_domf(struct compile_state
*state
, struct block
*block
)
15831 struct block
*child
;
15832 struct block_set
*user
, *edge
;
15833 if (block
->domfrontier
!= 0) {
15834 internal_error(state
, block
->first
, "domfrontier present?");
15836 for(user
= block
->idominates
; user
; user
= user
->next
) {
15837 child
= user
->member
;
15838 if (child
->idom
!= block
) {
15839 internal_error(state
, block
->first
, "bad idom");
15841 find_block_domf(state
, child
);
15843 for(edge
= block
->edges
; edge
; edge
= edge
->next
) {
15844 if (edge
->member
->idom
!= block
) {
15845 domf_block(block
, edge
->member
);
15848 for(user
= block
->idominates
; user
; user
= user
->next
) {
15849 struct block_set
*frontier
;
15850 child
= user
->member
;
15851 for(frontier
= child
->domfrontier
; frontier
; frontier
= frontier
->next
) {
15852 if (frontier
->member
->idom
!= block
) {
15853 domf_block(block
, frontier
->member
);
15859 static void find_block_ipdomf(struct compile_state
*state
, struct block
*block
)
15861 struct block
*child
;
15862 struct block_set
*user
;
15863 if (block
->ipdomfrontier
!= 0) {
15864 internal_error(state
, block
->first
, "ipdomfrontier present?");
15866 for(user
= block
->ipdominates
; user
; user
= user
->next
) {
15867 child
= user
->member
;
15868 if (child
->ipdom
!= block
) {
15869 internal_error(state
, block
->first
, "bad ipdom");
15871 find_block_ipdomf(state
, child
);
15873 for(user
= block
->use
; user
; user
= user
->next
) {
15874 if (user
->member
->ipdom
!= block
) {
15875 ipdomf_block(block
, user
->member
);
15878 for(user
= block
->ipdominates
; user
; user
= user
->next
) {
15879 struct block_set
*frontier
;
15880 child
= user
->member
;
15881 for(frontier
= child
->ipdomfrontier
; frontier
; frontier
= frontier
->next
) {
15882 if (frontier
->member
->ipdom
!= block
) {
15883 ipdomf_block(block
, frontier
->member
);
15889 static void print_dominated(
15890 struct compile_state
*state
, struct block
*block
, void *arg
)
15892 struct block_set
*user
;
15895 fprintf(fp
, "%d:", block
->vertex
);
15896 for(user
= block
->idominates
; user
; user
= user
->next
) {
15897 fprintf(fp
, " %d", user
->member
->vertex
);
15898 if (user
->member
->idom
!= block
) {
15899 internal_error(state
, user
->member
->first
, "bad idom");
15905 static void print_dominated2(
15906 struct compile_state
*state
, FILE *fp
, int depth
, struct block
*block
)
15908 struct block_set
*user
;
15909 struct triple
*ins
;
15910 struct occurance
*ptr
, *ptr2
;
15911 const char *filename1
, *filename2
;
15912 int equal_filenames
;
15914 for(i
= 0; i
< depth
; i
++) {
15917 fprintf(fp
, "%3d: %p (%p - %p) @",
15918 block
->vertex
, block
, block
->first
, block
->last
);
15919 ins
= block
->first
;
15920 while(ins
!= block
->last
&& (ins
->occurance
->line
== 0)) {
15923 ptr
= ins
->occurance
;
15924 ptr2
= block
->last
->occurance
;
15925 filename1
= ptr
->filename
? ptr
->filename
: "";
15926 filename2
= ptr2
->filename
? ptr2
->filename
: "";
15927 equal_filenames
= (strcmp(filename1
, filename2
) == 0);
15928 if ((ptr
== ptr2
) || (equal_filenames
&& ptr
->line
== ptr2
->line
)) {
15929 fprintf(fp
, " %s:%d", ptr
->filename
, ptr
->line
);
15930 } else if (equal_filenames
) {
15931 fprintf(fp
, " %s:(%d - %d)",
15932 ptr
->filename
, ptr
->line
, ptr2
->line
);
15934 fprintf(fp
, " (%s:%d - %s:%d)",
15935 ptr
->filename
, ptr
->line
,
15936 ptr2
->filename
, ptr2
->line
);
15939 for(user
= block
->idominates
; user
; user
= user
->next
) {
15940 print_dominated2(state
, fp
, depth
+ 1, user
->member
);
15944 static void print_dominators(struct compile_state
*state
, FILE *fp
, struct basic_blocks
*bb
)
15946 fprintf(fp
, "\ndominates\n");
15947 walk_blocks(state
, bb
, print_dominated
, fp
);
15948 fprintf(fp
, "dominates\n");
15949 print_dominated2(state
, fp
, 0, bb
->first_block
);
15953 static int print_frontiers(
15954 struct compile_state
*state
, FILE *fp
, struct block
*block
, int vertex
)
15956 struct block_set
*user
, *edge
;
15958 if (!block
|| (block
->vertex
!= vertex
+ 1)) {
15963 fprintf(fp
, "%d:", block
->vertex
);
15964 for(user
= block
->domfrontier
; user
; user
= user
->next
) {
15965 fprintf(fp
, " %d", user
->member
->vertex
);
15969 for(edge
= block
->edges
; edge
; edge
= edge
->next
) {
15970 vertex
= print_frontiers(state
, fp
, edge
->member
, vertex
);
15974 static void print_dominance_frontiers(struct compile_state
*state
,
15975 FILE *fp
, struct basic_blocks
*bb
)
15977 fprintf(fp
, "\ndominance frontiers\n");
15978 print_frontiers(state
, fp
, bb
->first_block
, 0);
15982 static void analyze_idominators(struct compile_state
*state
, struct basic_blocks
*bb
)
15984 /* Find the immediate dominators */
15985 find_immediate_dominators(state
, bb
);
15986 /* Find the dominance frontiers */
15987 find_block_domf(state
, bb
->first_block
);
15988 /* If debuging print the print what I have just found */
15989 if (state
->compiler
->debug
& DEBUG_FDOMINATORS
) {
15990 print_dominators(state
, state
->dbgout
, bb
);
15991 print_dominance_frontiers(state
, state
->dbgout
, bb
);
15992 print_control_flow(state
, state
->dbgout
, bb
);
15997 static void print_ipdominated(
15998 struct compile_state
*state
, struct block
*block
, void *arg
)
16000 struct block_set
*user
;
16003 fprintf(fp
, "%d:", block
->vertex
);
16004 for(user
= block
->ipdominates
; user
; user
= user
->next
) {
16005 fprintf(fp
, " %d", user
->member
->vertex
);
16006 if (user
->member
->ipdom
!= block
) {
16007 internal_error(state
, user
->member
->first
, "bad ipdom");
16013 static void print_ipdominators(struct compile_state
*state
, FILE *fp
,
16014 struct basic_blocks
*bb
)
16016 fprintf(fp
, "\nipdominates\n");
16017 walk_blocks(state
, bb
, print_ipdominated
, fp
);
16020 static int print_pfrontiers(
16021 struct compile_state
*state
, FILE *fp
, struct block
*block
, int vertex
)
16023 struct block_set
*user
;
16025 if (!block
|| (block
->vertex
!= vertex
+ 1)) {
16030 fprintf(fp
, "%d:", block
->vertex
);
16031 for(user
= block
->ipdomfrontier
; user
; user
= user
->next
) {
16032 fprintf(fp
, " %d", user
->member
->vertex
);
16035 for(user
= block
->use
; user
; user
= user
->next
) {
16036 vertex
= print_pfrontiers(state
, fp
, user
->member
, vertex
);
16040 static void print_ipdominance_frontiers(struct compile_state
*state
,
16041 FILE *fp
, struct basic_blocks
*bb
)
16043 fprintf(fp
, "\nipdominance frontiers\n");
16044 print_pfrontiers(state
, fp
, bb
->last_block
, 0);
16048 static void analyze_ipdominators(struct compile_state
*state
,
16049 struct basic_blocks
*bb
)
16051 /* Find the post dominators */
16052 find_post_dominators(state
, bb
);
16053 /* Find the control dependencies (post dominance frontiers) */
16054 find_block_ipdomf(state
, bb
->last_block
);
16055 /* If debuging print the print what I have just found */
16056 if (state
->compiler
->debug
& DEBUG_RDOMINATORS
) {
16057 print_ipdominators(state
, state
->dbgout
, bb
);
16058 print_ipdominance_frontiers(state
, state
->dbgout
, bb
);
16059 print_control_flow(state
, state
->dbgout
, bb
);
16063 static int bdominates(struct compile_state
*state
,
16064 struct block
*dom
, struct block
*sub
)
16066 while(sub
&& (sub
!= dom
)) {
16072 static int tdominates(struct compile_state
*state
,
16073 struct triple
*dom
, struct triple
*sub
)
16075 struct block
*bdom
, *bsub
;
16077 bdom
= block_of_triple(state
, dom
);
16078 bsub
= block_of_triple(state
, sub
);
16079 if (bdom
!= bsub
) {
16080 result
= bdominates(state
, bdom
, bsub
);
16083 struct triple
*ins
;
16084 if (!bdom
|| !bsub
) {
16085 internal_error(state
, dom
, "huh?");
16088 while((ins
!= bsub
->first
) && (ins
!= dom
)) {
16091 result
= (ins
== dom
);
16096 static void analyze_basic_blocks(
16097 struct compile_state
*state
, struct basic_blocks
*bb
)
16099 setup_basic_blocks(state
, bb
);
16100 analyze_idominators(state
, bb
);
16101 analyze_ipdominators(state
, bb
);
16104 static void insert_phi_operations(struct compile_state
*state
)
16107 struct triple
*first
;
16108 int *has_already
, *work
;
16109 struct block
*work_list
, **work_list_tail
;
16111 struct triple
*var
, *vnext
;
16113 size
= sizeof(int) * (state
->bb
.last_vertex
+ 1);
16114 has_already
= xcmalloc(size
, "has_already");
16115 work
= xcmalloc(size
, "work");
16118 first
= state
->first
;
16119 for(var
= first
->next
; var
!= first
; var
= vnext
) {
16120 struct block
*block
;
16121 struct triple_set
*user
, *unext
;
16124 if (!triple_is_auto_var(state
, var
) || !var
->use
) {
16130 work_list_tail
= &work_list
;
16131 for(user
= var
->use
; user
; user
= unext
) {
16132 unext
= user
->next
;
16133 if (MISC(var
, 0) == user
->member
) {
16136 if (user
->member
->op
== OP_READ
) {
16139 if (user
->member
->op
!= OP_WRITE
) {
16140 internal_error(state
, user
->member
,
16141 "bad variable access");
16143 block
= user
->member
->u
.block
;
16145 warning(state
, user
->member
, "dead code");
16146 release_triple(state
, user
->member
);
16149 if (work
[block
->vertex
] >= iter
) {
16152 work
[block
->vertex
] = iter
;
16153 *work_list_tail
= block
;
16154 block
->work_next
= 0;
16155 work_list_tail
= &block
->work_next
;
16157 for(block
= work_list
; block
; block
= block
->work_next
) {
16158 struct block_set
*df
;
16159 for(df
= block
->domfrontier
; df
; df
= df
->next
) {
16160 struct triple
*phi
;
16161 struct block
*front
;
16163 front
= df
->member
;
16165 if (has_already
[front
->vertex
] >= iter
) {
16168 /* Count how many edges flow into this block */
16169 in_edges
= front
->users
;
16170 /* Insert a phi function for this variable */
16171 get_occurance(var
->occurance
);
16172 phi
= alloc_triple(
16173 state
, OP_PHI
, var
->type
, -1, in_edges
,
16175 phi
->u
.block
= front
;
16176 MISC(phi
, 0) = var
;
16177 use_triple(var
, phi
);
16179 if (phi
->rhs
!= in_edges
) {
16180 internal_error(state
, phi
, "phi->rhs: %d != in_edges: %d",
16181 phi
->rhs
, in_edges
);
16184 /* Insert the phi functions immediately after the label */
16185 insert_triple(state
, front
->first
->next
, phi
);
16186 if (front
->first
== front
->last
) {
16187 front
->last
= front
->first
->next
;
16189 has_already
[front
->vertex
] = iter
;
16190 transform_to_arch_instruction(state
, phi
);
16192 /* If necessary plan to visit the basic block */
16193 if (work
[front
->vertex
] >= iter
) {
16196 work
[front
->vertex
] = iter
;
16197 *work_list_tail
= front
;
16198 front
->work_next
= 0;
16199 work_list_tail
= &front
->work_next
;
16203 xfree(has_already
);
16209 struct triple_set
*top
;
16213 static int count_auto_vars(struct compile_state
*state
)
16215 struct triple
*first
, *ins
;
16217 first
= state
->first
;
16220 if (triple_is_auto_var(state
, ins
)) {
16224 } while(ins
!= first
);
16228 static void number_auto_vars(struct compile_state
*state
, struct stack
*stacks
)
16230 struct triple
*first
, *ins
;
16232 first
= state
->first
;
16235 if (triple_is_auto_var(state
, ins
)) {
16237 stacks
[auto_vars
].orig_id
= ins
->id
;
16238 ins
->id
= auto_vars
;
16241 } while(ins
!= first
);
16244 static void restore_auto_vars(struct compile_state
*state
, struct stack
*stacks
)
16246 struct triple
*first
, *ins
;
16247 first
= state
->first
;
16250 if (triple_is_auto_var(state
, ins
)) {
16251 ins
->id
= stacks
[ins
->id
].orig_id
;
16254 } while(ins
!= first
);
16257 static struct triple
*peek_triple(struct stack
*stacks
, struct triple
*var
)
16259 struct triple_set
*head
;
16260 struct triple
*top_val
;
16262 head
= stacks
[var
->id
].top
;
16264 top_val
= head
->member
;
16269 static void push_triple(struct stack
*stacks
, struct triple
*var
, struct triple
*val
)
16271 struct triple_set
*new;
16272 /* Append new to the head of the list,
16273 * it's the only sensible behavoir for a stack.
16275 new = xcmalloc(sizeof(*new), "triple_set");
16277 new->next
= stacks
[var
->id
].top
;
16278 stacks
[var
->id
].top
= new;
16281 static void pop_triple(struct stack
*stacks
, struct triple
*var
, struct triple
*oldval
)
16283 struct triple_set
*set
, **ptr
;
16284 ptr
= &stacks
[var
->id
].top
;
16287 if (set
->member
== oldval
) {
16290 /* Only free one occurance from the stack */
16303 static void fixup_block_phi_variables(
16304 struct compile_state
*state
, struct stack
*stacks
, struct block
*parent
, struct block
*block
)
16306 struct block_set
*set
;
16307 struct triple
*ptr
;
16309 if (!parent
|| !block
)
16311 /* Find the edge I am coming in on */
16313 for(set
= block
->use
; set
; set
= set
->next
, edge
++) {
16314 if (set
->member
== parent
) {
16319 internal_error(state
, 0, "phi input is not on a control predecessor");
16321 for(ptr
= block
->first
; ; ptr
= ptr
->next
) {
16322 if (ptr
->op
== OP_PHI
) {
16323 struct triple
*var
, *val
, **slot
;
16324 var
= MISC(ptr
, 0);
16326 internal_error(state
, ptr
, "no var???");
16328 /* Find the current value of the variable */
16329 val
= peek_triple(stacks
, var
);
16330 if (val
&& ((val
->op
== OP_WRITE
) || (val
->op
== OP_READ
))) {
16331 internal_error(state
, val
, "bad value in phi");
16333 if (edge
>= ptr
->rhs
) {
16334 internal_error(state
, ptr
, "edges > phi rhs");
16336 slot
= &RHS(ptr
, edge
);
16337 if ((*slot
!= 0) && (*slot
!= val
)) {
16338 internal_error(state
, ptr
, "phi already bound on this edge");
16341 use_triple(val
, ptr
);
16343 if (ptr
== block
->last
) {
16350 static void rename_block_variables(
16351 struct compile_state
*state
, struct stack
*stacks
, struct block
*block
)
16353 struct block_set
*user
, *edge
;
16354 struct triple
*ptr
, *next
, *last
;
16358 last
= block
->first
;
16360 for(ptr
= block
->first
; !done
; ptr
= next
) {
16362 if (ptr
== block
->last
) {
16366 if (ptr
->op
== OP_READ
) {
16367 struct triple
*var
, *val
;
16369 if (!triple_is_auto_var(state
, var
)) {
16370 internal_error(state
, ptr
, "read of non auto var!");
16372 unuse_triple(var
, ptr
);
16373 /* Find the current value of the variable */
16374 val
= peek_triple(stacks
, var
);
16376 /* Let the optimizer at variables that are not initially
16377 * set. But give it a bogus value so things seem to
16378 * work by accident. This is useful for bitfields because
16379 * setting them always involves a read-modify-write.
16381 if (TYPE_ARITHMETIC(ptr
->type
->type
)) {
16382 val
= pre_triple(state
, ptr
, OP_INTCONST
, ptr
->type
, 0, 0);
16383 val
->u
.cval
= 0xdeadbeaf;
16385 val
= pre_triple(state
, ptr
, OP_UNKNOWNVAL
, ptr
->type
, 0, 0);
16389 error(state
, ptr
, "variable used without being set");
16391 if ((val
->op
== OP_WRITE
) || (val
->op
== OP_READ
)) {
16392 internal_error(state
, val
, "bad value in read");
16394 propogate_use(state
, ptr
, val
);
16395 release_triple(state
, ptr
);
16399 if (ptr
->op
== OP_WRITE
) {
16400 struct triple
*var
, *val
, *tval
;
16401 var
= MISC(ptr
, 0);
16402 if (!triple_is_auto_var(state
, var
)) {
16403 internal_error(state
, ptr
, "write to non auto var!");
16405 tval
= val
= RHS(ptr
, 0);
16406 if ((val
->op
== OP_WRITE
) || (val
->op
== OP_READ
) ||
16407 triple_is_auto_var(state
, val
)) {
16408 internal_error(state
, ptr
, "bad value in write");
16410 /* Insert a cast if the types differ */
16411 if (!is_subset_type(ptr
->type
, val
->type
)) {
16412 if (val
->op
== OP_INTCONST
) {
16413 tval
= pre_triple(state
, ptr
, OP_INTCONST
, ptr
->type
, 0, 0);
16414 tval
->u
.cval
= val
->u
.cval
;
16417 tval
= pre_triple(state
, ptr
, OP_CONVERT
, ptr
->type
, val
, 0);
16418 use_triple(val
, tval
);
16420 transform_to_arch_instruction(state
, tval
);
16421 unuse_triple(val
, ptr
);
16422 RHS(ptr
, 0) = tval
;
16423 use_triple(tval
, ptr
);
16425 propogate_use(state
, ptr
, tval
);
16426 unuse_triple(var
, ptr
);
16427 /* Push OP_WRITE ptr->right onto a stack of variable uses */
16428 push_triple(stacks
, var
, tval
);
16430 if (ptr
->op
== OP_PHI
) {
16431 struct triple
*var
;
16432 var
= MISC(ptr
, 0);
16433 if (!triple_is_auto_var(state
, var
)) {
16434 internal_error(state
, ptr
, "phi references non auto var!");
16436 /* Push OP_PHI onto a stack of variable uses */
16437 push_triple(stacks
, var
, ptr
);
16441 block
->last
= last
;
16443 /* Fixup PHI functions in the cf successors */
16444 for(edge
= block
->edges
; edge
; edge
= edge
->next
) {
16445 fixup_block_phi_variables(state
, stacks
, block
, edge
->member
);
16447 /* rename variables in the dominated nodes */
16448 for(user
= block
->idominates
; user
; user
= user
->next
) {
16449 rename_block_variables(state
, stacks
, user
->member
);
16451 /* pop the renamed variable stack */
16452 last
= block
->first
;
16454 for(ptr
= block
->first
; !done
; ptr
= next
) {
16456 if (ptr
== block
->last
) {
16459 if (ptr
->op
== OP_WRITE
) {
16460 struct triple
*var
;
16461 var
= MISC(ptr
, 0);
16462 /* Pop OP_WRITE ptr->right from the stack of variable uses */
16463 pop_triple(stacks
, var
, RHS(ptr
, 0));
16464 release_triple(state
, ptr
);
16467 if (ptr
->op
== OP_PHI
) {
16468 struct triple
*var
;
16469 var
= MISC(ptr
, 0);
16470 /* Pop OP_WRITE ptr->right from the stack of variable uses */
16471 pop_triple(stacks
, var
, ptr
);
16475 block
->last
= last
;
16478 static void rename_variables(struct compile_state
*state
)
16480 struct stack
*stacks
;
16483 /* Allocate stacks for the Variables */
16484 auto_vars
= count_auto_vars(state
);
16485 stacks
= xcmalloc(sizeof(stacks
[0])*(auto_vars
+ 1), "auto var stacks");
16487 /* Give each auto_var a stack */
16488 number_auto_vars(state
, stacks
);
16490 /* Rename the variables */
16491 rename_block_variables(state
, stacks
, state
->bb
.first_block
);
16493 /* Remove the stacks from the auto_vars */
16494 restore_auto_vars(state
, stacks
);
16498 static void prune_block_variables(struct compile_state
*state
,
16499 struct block
*block
)
16501 struct block_set
*user
;
16502 struct triple
*next
, *ptr
;
16506 for(ptr
= block
->first
; !done
; ptr
= next
) {
16507 /* Be extremely careful I am deleting the list
16508 * as I walk trhough it.
16511 if (ptr
== block
->last
) {
16514 if (triple_is_auto_var(state
, ptr
)) {
16515 struct triple_set
*user
, *next
;
16516 for(user
= ptr
->use
; user
; user
= next
) {
16517 struct triple
*use
;
16519 use
= user
->member
;
16520 if (MISC(ptr
, 0) == user
->member
) {
16523 if (use
->op
!= OP_PHI
) {
16524 internal_error(state
, use
, "decl still used");
16526 if (MISC(use
, 0) != ptr
) {
16527 internal_error(state
, use
, "bad phi use of decl");
16529 unuse_triple(ptr
, use
);
16532 if ((ptr
->u
.cval
== 0) && (MISC(ptr
, 0)->lhs
== 1)) {
16533 /* Delete the adecl */
16534 release_triple(state
, MISC(ptr
, 0));
16535 /* And the piece */
16536 release_triple(state
, ptr
);
16541 for(user
= block
->idominates
; user
; user
= user
->next
) {
16542 prune_block_variables(state
, user
->member
);
16546 struct phi_triple
{
16547 struct triple
*phi
;
16552 static void keep_phi(struct compile_state
*state
, struct phi_triple
*live
, struct triple
*phi
)
16554 struct triple
**slot
;
16556 if (live
[phi
->id
].alive
) {
16559 live
[phi
->id
].alive
= 1;
16561 slot
= &RHS(phi
, 0);
16562 for(i
= 0; i
< zrhs
; i
++) {
16563 struct triple
*used
;
16565 if (used
&& (used
->op
== OP_PHI
)) {
16566 keep_phi(state
, live
, used
);
16571 static void prune_unused_phis(struct compile_state
*state
)
16573 struct triple
*first
, *phi
;
16574 struct phi_triple
*live
;
16577 /* Find the first instruction */
16578 first
= state
->first
;
16580 /* Count how many phi functions I need to process */
16582 for(phi
= first
->next
; phi
!= first
; phi
= phi
->next
) {
16583 if (phi
->op
== OP_PHI
) {
16588 /* Mark them all dead */
16589 live
= xcmalloc(sizeof(*live
) * (phis
+ 1), "phi_triple");
16591 for(phi
= first
->next
; phi
!= first
; phi
= phi
->next
) {
16592 if (phi
->op
!= OP_PHI
) {
16595 live
[phis
].alive
= 0;
16596 live
[phis
].orig_id
= phi
->id
;
16597 live
[phis
].phi
= phi
;
16602 /* Mark phis alive that are used by non phis */
16603 for(i
= 0; i
< phis
; i
++) {
16604 struct triple_set
*set
;
16605 for(set
= live
[i
].phi
->use
; !live
[i
].alive
&& set
; set
= set
->next
) {
16606 if (set
->member
->op
!= OP_PHI
) {
16607 keep_phi(state
, live
, live
[i
].phi
);
16613 /* Delete the extraneous phis */
16614 for(i
= 0; i
< phis
; i
++) {
16615 struct triple
**slot
;
16617 if (!live
[i
].alive
) {
16618 release_triple(state
, live
[i
].phi
);
16622 slot
= &RHS(phi
, 0);
16624 for(j
= 0; j
< zrhs
; j
++) {
16626 struct triple
*unknown
;
16627 get_occurance(phi
->occurance
);
16628 unknown
= flatten(state
, state
->global_pool
,
16629 alloc_triple(state
, OP_UNKNOWNVAL
,
16630 phi
->type
, 0, 0, phi
->occurance
));
16632 use_triple(unknown
, phi
);
16633 transform_to_arch_instruction(state
, unknown
);
16635 warning(state
, phi
, "variable not set at index %d on all paths to use", j
);
16643 static void transform_to_ssa_form(struct compile_state
*state
)
16645 insert_phi_operations(state
);
16646 rename_variables(state
);
16648 prune_block_variables(state
, state
->bb
.first_block
);
16649 prune_unused_phis(state
);
16651 print_blocks(state
, __func__
, state
->dbgout
);
16655 static void clear_vertex(
16656 struct compile_state
*state
, struct block
*block
, void *arg
)
16658 /* Clear the current blocks vertex and the vertex of all
16659 * of the current blocks neighbors in case there are malformed
16660 * blocks with now instructions at this point.
16662 struct block_set
*user
, *edge
;
16664 for(edge
= block
->edges
; edge
; edge
= edge
->next
) {
16665 edge
->member
->vertex
= 0;
16667 for(user
= block
->use
; user
; user
= user
->next
) {
16668 user
->member
->vertex
= 0;
16672 static void mark_live_block(
16673 struct compile_state
*state
, struct block
*block
, int *next_vertex
)
16675 /* See if this is a block that has not been marked */
16676 if (block
->vertex
!= 0) {
16679 block
->vertex
= *next_vertex
;
16681 if (triple_is_branch(state
, block
->last
)) {
16682 struct triple
**targ
;
16683 targ
= triple_edge_targ(state
, block
->last
, 0);
16684 for(; targ
; targ
= triple_edge_targ(state
, block
->last
, targ
)) {
16688 if (!triple_stores_block(state
, *targ
)) {
16689 internal_error(state
, 0, "bad targ");
16691 mark_live_block(state
, (*targ
)->u
.block
, next_vertex
);
16693 /* Ensure the last block of a function remains alive */
16694 if (triple_is_call(state
, block
->last
)) {
16695 mark_live_block(state
, MISC(block
->last
, 0)->u
.block
, next_vertex
);
16698 else if (block
->last
->next
!= state
->first
) {
16699 struct triple
*ins
;
16700 ins
= block
->last
->next
;
16701 if (!triple_stores_block(state
, ins
)) {
16702 internal_error(state
, 0, "bad block start");
16704 mark_live_block(state
, ins
->u
.block
, next_vertex
);
16708 static void transform_from_ssa_form(struct compile_state
*state
)
16710 /* To get out of ssa form we insert moves on the incoming
16711 * edges to blocks containting phi functions.
16713 struct triple
*first
;
16714 struct triple
*phi
, *var
, *next
;
16717 /* Walk the control flow to see which blocks remain alive */
16718 walk_blocks(state
, &state
->bb
, clear_vertex
, 0);
16720 mark_live_block(state
, state
->bb
.first_block
, &next_vertex
);
16722 /* Walk all of the operations to find the phi functions */
16723 first
= state
->first
;
16724 for(phi
= first
->next
; phi
!= first
; phi
= next
) {
16725 struct block_set
*set
;
16726 struct block
*block
;
16727 struct triple
**slot
;
16728 struct triple
*var
;
16729 struct triple_set
*use
, *use_next
;
16730 int edge
, writers
, readers
;
16732 if (phi
->op
!= OP_PHI
) {
16736 block
= phi
->u
.block
;
16737 slot
= &RHS(phi
, 0);
16739 /* If this phi is in a dead block just forget it */
16740 if (block
->vertex
== 0) {
16741 release_triple(state
, phi
);
16745 /* Forget uses from code in dead blocks */
16746 for(use
= phi
->use
; use
; use
= use_next
) {
16747 struct block
*ublock
;
16748 struct triple
**expr
;
16749 use_next
= use
->next
;
16750 ublock
= block_of_triple(state
, use
->member
);
16751 if ((use
->member
== phi
) || (ublock
->vertex
!= 0)) {
16754 expr
= triple_rhs(state
, use
->member
, 0);
16755 for(; expr
; expr
= triple_rhs(state
, use
->member
, expr
)) {
16756 if (*expr
== phi
) {
16760 unuse_triple(phi
, use
->member
);
16762 /* A variable to replace the phi function */
16763 if (registers_of(state
, phi
->type
) != 1) {
16764 internal_error(state
, phi
, "phi->type does not fit in a single register!");
16766 var
= post_triple(state
, phi
, OP_ADECL
, phi
->type
, 0, 0);
16767 var
= var
->next
; /* point at the var */
16769 /* Replaces use of phi with var */
16770 propogate_use(state
, phi
, var
);
16772 /* Count the readers */
16774 for(use
= var
->use
; use
; use
= use
->next
) {
16775 if (use
->member
!= MISC(var
, 0)) {
16780 /* Walk all of the incoming edges/blocks and insert moves.
16783 for(edge
= 0, set
= block
->use
; set
; set
= set
->next
, edge
++) {
16784 struct block
*eblock
, *vblock
;
16785 struct triple
*move
;
16786 struct triple
*val
, *base
;
16787 eblock
= set
->member
;
16790 unuse_triple(val
, phi
);
16791 vblock
= block_of_triple(state
, val
);
16793 /* If we don't have a value that belongs in an OP_WRITE
16796 if (!val
|| (val
== &unknown_triple
) || (val
== phi
)
16797 || (vblock
&& (vblock
->vertex
== 0))) {
16800 /* If the value should never occur error */
16802 internal_error(state
, val
, "no vblock?");
16806 /* If the value occurs in a dead block see if a replacement
16807 * block can be found.
16809 while(eblock
&& (eblock
->vertex
== 0)) {
16810 eblock
= eblock
->idom
;
16812 /* If not continue on with the next value. */
16813 if (!eblock
|| (eblock
->vertex
== 0)) {
16817 /* If we have an empty incoming block ignore it. */
16818 if (!eblock
->first
) {
16819 internal_error(state
, 0, "empty block?");
16822 /* Make certain the write is placed in the edge block... */
16823 /* Walk through the edge block backwards to find an
16824 * appropriate location for the OP_WRITE.
16826 for(base
= eblock
->last
; base
!= eblock
->first
; base
= base
->prev
) {
16827 struct triple
**expr
;
16828 if (base
->op
== OP_PIECE
) {
16829 base
= MISC(base
, 0);
16831 if ((base
== var
) || (base
== val
)) {
16834 expr
= triple_lhs(state
, base
, 0);
16835 for(; expr
; expr
= triple_lhs(state
, base
, expr
)) {
16836 if ((*expr
) == val
) {
16840 expr
= triple_rhs(state
, base
, 0);
16841 for(; expr
; expr
= triple_rhs(state
, base
, expr
)) {
16842 if ((*expr
) == var
) {
16848 if (triple_is_branch(state
, base
)) {
16849 internal_error(state
, base
,
16850 "Could not insert write to phi");
16852 move
= post_triple(state
, base
, OP_WRITE
, var
->type
, val
, var
);
16853 use_triple(val
, move
);
16854 use_triple(var
, move
);
16857 if (!writers
&& readers
) {
16858 internal_error(state
, var
, "no value written to in use phi?");
16860 /* If var is not used free it */
16862 release_triple(state
, MISC(var
, 0));
16863 release_triple(state
, var
);
16865 /* Release the phi function */
16866 release_triple(state
, phi
);
16869 /* Walk all of the operations to find the adecls */
16870 for(var
= first
->next
; var
!= first
; var
= var
->next
) {
16871 struct triple_set
*use
, *use_next
;
16872 if (!triple_is_auto_var(state
, var
)) {
16876 /* Walk through all of the rhs uses of var and
16877 * replace them with read of var.
16879 for(use
= var
->use
; use
; use
= use_next
) {
16880 struct triple
*read
, *user
;
16881 struct triple
**slot
;
16883 use_next
= use
->next
;
16884 user
= use
->member
;
16886 /* Generate a read of var */
16887 read
= pre_triple(state
, user
, OP_READ
, var
->type
, var
, 0);
16888 use_triple(var
, read
);
16890 /* Find the rhs uses and see if they need to be replaced */
16893 slot
= &RHS(user
, 0);
16894 for(i
= 0; i
< zrhs
; i
++) {
16895 if (slot
[i
] == var
) {
16900 /* If we did use it cleanup the uses */
16902 unuse_triple(var
, user
);
16903 use_triple(read
, user
);
16905 /* If we didn't use it release the extra triple */
16907 release_triple(state
, read
);
16913 #define HI() if (state->compiler->debug & DEBUG_REBUILD_SSA_FORM) { \
16914 FILE *fp = state->dbgout; \
16915 fprintf(fp, "@ %s:%d\n", __FILE__, __LINE__); romcc_print_blocks(state, fp); \
16918 static void rebuild_ssa_form(struct compile_state
*state
)
16921 transform_from_ssa_form(state
);
16923 state
->bb
.first
= state
->first
;
16924 free_basic_blocks(state
, &state
->bb
);
16925 analyze_basic_blocks(state
, &state
->bb
);
16927 insert_phi_operations(state
);
16929 rename_variables(state
);
16932 prune_block_variables(state
, state
->bb
.first_block
);
16934 prune_unused_phis(state
);
16940 * Register conflict resolution
16941 * =========================================================
16944 static struct reg_info
find_def_color(
16945 struct compile_state
*state
, struct triple
*def
)
16947 struct triple_set
*set
;
16948 struct reg_info info
;
16949 info
.reg
= REG_UNSET
;
16951 if (!triple_is_def(state
, def
)) {
16954 info
= arch_reg_lhs(state
, def
, 0);
16955 if (info
.reg
>= MAX_REGISTERS
) {
16956 info
.reg
= REG_UNSET
;
16958 for(set
= def
->use
; set
; set
= set
->next
) {
16959 struct reg_info tinfo
;
16961 i
= find_rhs_use(state
, set
->member
, def
);
16965 tinfo
= arch_reg_rhs(state
, set
->member
, i
);
16966 if (tinfo
.reg
>= MAX_REGISTERS
) {
16967 tinfo
.reg
= REG_UNSET
;
16969 if ((tinfo
.reg
!= REG_UNSET
) &&
16970 (info
.reg
!= REG_UNSET
) &&
16971 (tinfo
.reg
!= info
.reg
)) {
16972 internal_error(state
, def
, "register conflict");
16974 if ((info
.regcm
& tinfo
.regcm
) == 0) {
16975 internal_error(state
, def
, "regcm conflict %x & %x == 0",
16976 info
.regcm
, tinfo
.regcm
);
16978 if (info
.reg
== REG_UNSET
) {
16979 info
.reg
= tinfo
.reg
;
16981 info
.regcm
&= tinfo
.regcm
;
16983 if (info
.reg
>= MAX_REGISTERS
) {
16984 internal_error(state
, def
, "register out of range");
16989 static struct reg_info
find_lhs_pre_color(
16990 struct compile_state
*state
, struct triple
*ins
, int index
)
16992 struct reg_info info
;
16996 if (!zlhs
&& triple_is_def(state
, ins
)) {
16999 if (index
>= zlhs
) {
17000 internal_error(state
, ins
, "Bad lhs %d", index
);
17002 info
= arch_reg_lhs(state
, ins
, index
);
17003 for(i
= 0; i
< zrhs
; i
++) {
17004 struct reg_info rinfo
;
17005 rinfo
= arch_reg_rhs(state
, ins
, i
);
17006 if ((info
.reg
== rinfo
.reg
) &&
17007 (rinfo
.reg
>= MAX_REGISTERS
)) {
17008 struct reg_info tinfo
;
17009 tinfo
= find_lhs_pre_color(state
, RHS(ins
, index
), 0);
17010 info
.reg
= tinfo
.reg
;
17011 info
.regcm
&= tinfo
.regcm
;
17015 if (info
.reg
>= MAX_REGISTERS
) {
17016 info
.reg
= REG_UNSET
;
17021 static struct reg_info
find_rhs_post_color(
17022 struct compile_state
*state
, struct triple
*ins
, int index
);
17024 static struct reg_info
find_lhs_post_color(
17025 struct compile_state
*state
, struct triple
*ins
, int index
)
17027 struct triple_set
*set
;
17028 struct reg_info info
;
17029 struct triple
*lhs
;
17030 #if DEBUG_TRIPLE_COLOR
17031 fprintf(state
->errout
, "find_lhs_post_color(%p, %d)\n",
17034 if ((index
== 0) && triple_is_def(state
, ins
)) {
17037 else if (index
< ins
->lhs
) {
17038 lhs
= LHS(ins
, index
);
17041 internal_error(state
, ins
, "Bad lhs %d", index
);
17044 info
= arch_reg_lhs(state
, ins
, index
);
17045 if (info
.reg
>= MAX_REGISTERS
) {
17046 info
.reg
= REG_UNSET
;
17048 for(set
= lhs
->use
; set
; set
= set
->next
) {
17049 struct reg_info rinfo
;
17050 struct triple
*user
;
17052 user
= set
->member
;
17054 for(i
= 0; i
< zrhs
; i
++) {
17055 if (RHS(user
, i
) != lhs
) {
17058 rinfo
= find_rhs_post_color(state
, user
, i
);
17059 if ((info
.reg
!= REG_UNSET
) &&
17060 (rinfo
.reg
!= REG_UNSET
) &&
17061 (info
.reg
!= rinfo
.reg
)) {
17062 internal_error(state
, ins
, "register conflict");
17064 if ((info
.regcm
& rinfo
.regcm
) == 0) {
17065 internal_error(state
, ins
, "regcm conflict %x & %x == 0",
17066 info
.regcm
, rinfo
.regcm
);
17068 if (info
.reg
== REG_UNSET
) {
17069 info
.reg
= rinfo
.reg
;
17071 info
.regcm
&= rinfo
.regcm
;
17074 #if DEBUG_TRIPLE_COLOR
17075 fprintf(state
->errout
, "find_lhs_post_color(%p, %d) -> ( %d, %x)\n",
17076 ins
, index
, info
.reg
, info
.regcm
);
17081 static struct reg_info
find_rhs_post_color(
17082 struct compile_state
*state
, struct triple
*ins
, int index
)
17084 struct reg_info info
, rinfo
;
17086 #if DEBUG_TRIPLE_COLOR
17087 fprintf(state
->errout
, "find_rhs_post_color(%p, %d)\n",
17090 rinfo
= arch_reg_rhs(state
, ins
, index
);
17092 if (!zlhs
&& triple_is_def(state
, ins
)) {
17096 if (info
.reg
>= MAX_REGISTERS
) {
17097 info
.reg
= REG_UNSET
;
17099 for(i
= 0; i
< zlhs
; i
++) {
17100 struct reg_info linfo
;
17101 linfo
= arch_reg_lhs(state
, ins
, i
);
17102 if ((linfo
.reg
== rinfo
.reg
) &&
17103 (linfo
.reg
>= MAX_REGISTERS
)) {
17104 struct reg_info tinfo
;
17105 tinfo
= find_lhs_post_color(state
, ins
, i
);
17106 if (tinfo
.reg
>= MAX_REGISTERS
) {
17107 tinfo
.reg
= REG_UNSET
;
17109 info
.regcm
&= linfo
.regcm
;
17110 info
.regcm
&= tinfo
.regcm
;
17111 if (info
.reg
!= REG_UNSET
) {
17112 internal_error(state
, ins
, "register conflict");
17114 if (info
.regcm
== 0) {
17115 internal_error(state
, ins
, "regcm conflict");
17117 info
.reg
= tinfo
.reg
;
17120 #if DEBUG_TRIPLE_COLOR
17121 fprintf(state
->errout
, "find_rhs_post_color(%p, %d) -> ( %d, %x)\n",
17122 ins
, index
, info
.reg
, info
.regcm
);
17127 static struct reg_info
find_lhs_color(
17128 struct compile_state
*state
, struct triple
*ins
, int index
)
17130 struct reg_info pre
, post
, info
;
17131 #if DEBUG_TRIPLE_COLOR
17132 fprintf(state
->errout
, "find_lhs_color(%p, %d)\n",
17135 pre
= find_lhs_pre_color(state
, ins
, index
);
17136 post
= find_lhs_post_color(state
, ins
, index
);
17137 if ((pre
.reg
!= post
.reg
) &&
17138 (pre
.reg
!= REG_UNSET
) &&
17139 (post
.reg
!= REG_UNSET
)) {
17140 internal_error(state
, ins
, "register conflict");
17142 info
.regcm
= pre
.regcm
& post
.regcm
;
17143 info
.reg
= pre
.reg
;
17144 if (info
.reg
== REG_UNSET
) {
17145 info
.reg
= post
.reg
;
17147 #if DEBUG_TRIPLE_COLOR
17148 fprintf(state
->errout
, "find_lhs_color(%p, %d) -> ( %d, %x) ... (%d, %x) (%d, %x)\n",
17149 ins
, index
, info
.reg
, info
.regcm
,
17150 pre
.reg
, pre
.regcm
, post
.reg
, post
.regcm
);
17155 static struct triple
*post_copy(struct compile_state
*state
, struct triple
*ins
)
17157 struct triple_set
*entry
, *next
;
17158 struct triple
*out
;
17159 struct reg_info info
, rinfo
;
17161 info
= arch_reg_lhs(state
, ins
, 0);
17162 out
= post_triple(state
, ins
, OP_COPY
, ins
->type
, ins
, 0);
17163 use_triple(RHS(out
, 0), out
);
17164 /* Get the users of ins to use out instead */
17165 for(entry
= ins
->use
; entry
; entry
= next
) {
17167 next
= entry
->next
;
17168 if (entry
->member
== out
) {
17171 i
= find_rhs_use(state
, entry
->member
, ins
);
17175 rinfo
= arch_reg_rhs(state
, entry
->member
, i
);
17176 if ((info
.reg
== REG_UNNEEDED
) && (rinfo
.reg
== REG_UNNEEDED
)) {
17179 replace_rhs_use(state
, ins
, out
, entry
->member
);
17181 transform_to_arch_instruction(state
, out
);
17185 static struct triple
*typed_pre_copy(
17186 struct compile_state
*state
, struct type
*type
, struct triple
*ins
, int index
)
17188 /* Carefully insert enough operations so that I can
17189 * enter any operation with a GPR32.
17192 struct triple
**expr
;
17194 struct reg_info info
;
17196 if (ins
->op
== OP_PHI
) {
17197 internal_error(state
, ins
, "pre_copy on a phi?");
17199 classes
= arch_type_to_regcm(state
, type
);
17200 info
= arch_reg_rhs(state
, ins
, index
);
17201 expr
= &RHS(ins
, index
);
17202 if ((info
.regcm
& classes
) == 0) {
17203 FILE *fp
= state
->errout
;
17204 fprintf(fp
, "src_type: ");
17205 name_of(fp
, ins
->type
);
17206 fprintf(fp
, "\ndst_type: ");
17209 internal_error(state
, ins
, "pre_copy with no register classes");
17212 if (!equiv_types(type
, (*expr
)->type
)) {
17215 in
= pre_triple(state
, ins
, op
, type
, *expr
, 0);
17216 unuse_triple(*expr
, ins
);
17218 use_triple(RHS(in
, 0), in
);
17219 use_triple(in
, ins
);
17220 transform_to_arch_instruction(state
, in
);
17224 static struct triple
*pre_copy(
17225 struct compile_state
*state
, struct triple
*ins
, int index
)
17227 return typed_pre_copy(state
, RHS(ins
, index
)->type
, ins
, index
);
17231 static void insert_copies_to_phi(struct compile_state
*state
)
17233 /* To get out of ssa form we insert moves on the incoming
17234 * edges to blocks containting phi functions.
17236 struct triple
*first
;
17237 struct triple
*phi
;
17239 /* Walk all of the operations to find the phi functions */
17240 first
= state
->first
;
17241 for(phi
= first
->next
; phi
!= first
; phi
= phi
->next
) {
17242 struct block_set
*set
;
17243 struct block
*block
;
17244 struct triple
**slot
, *copy
;
17246 if (phi
->op
!= OP_PHI
) {
17249 phi
->id
|= TRIPLE_FLAG_POST_SPLIT
;
17250 block
= phi
->u
.block
;
17251 slot
= &RHS(phi
, 0);
17252 /* Phi's that feed into mandatory live range joins
17253 * cause nasty complications. Insert a copy of
17254 * the phi value so I never have to deal with
17255 * that in the rest of the code.
17257 copy
= post_copy(state
, phi
);
17258 copy
->id
|= TRIPLE_FLAG_PRE_SPLIT
;
17259 /* Walk all of the incoming edges/blocks and insert moves.
17261 for(edge
= 0, set
= block
->use
; set
; set
= set
->next
, edge
++) {
17262 struct block
*eblock
;
17263 struct triple
*move
;
17264 struct triple
*val
;
17265 struct triple
*ptr
;
17266 eblock
= set
->member
;
17273 get_occurance(val
->occurance
);
17274 move
= build_triple(state
, OP_COPY
, val
->type
, val
, 0,
17276 move
->u
.block
= eblock
;
17277 move
->id
|= TRIPLE_FLAG_PRE_SPLIT
;
17278 use_triple(val
, move
);
17281 unuse_triple(val
, phi
);
17282 use_triple(move
, phi
);
17284 /* Walk up the dominator tree until I have found the appropriate block */
17285 while(eblock
&& !tdominates(state
, val
, eblock
->last
)) {
17286 eblock
= eblock
->idom
;
17289 internal_error(state
, phi
, "Cannot find block dominated by %p",
17293 /* Walk through the block backwards to find
17294 * an appropriate location for the OP_COPY.
17296 for(ptr
= eblock
->last
; ptr
!= eblock
->first
; ptr
= ptr
->prev
) {
17297 struct triple
**expr
;
17298 if (ptr
->op
== OP_PIECE
) {
17299 ptr
= MISC(ptr
, 0);
17301 if ((ptr
== phi
) || (ptr
== val
)) {
17304 expr
= triple_lhs(state
, ptr
, 0);
17305 for(;expr
; expr
= triple_lhs(state
, ptr
, expr
)) {
17306 if ((*expr
) == val
) {
17310 expr
= triple_rhs(state
, ptr
, 0);
17311 for(;expr
; expr
= triple_rhs(state
, ptr
, expr
)) {
17312 if ((*expr
) == phi
) {
17318 if (triple_is_branch(state
, ptr
)) {
17319 internal_error(state
, ptr
,
17320 "Could not insert write to phi");
17322 insert_triple(state
, after_lhs(state
, ptr
), move
);
17323 if (eblock
->last
== after_lhs(state
, ptr
)->prev
) {
17324 eblock
->last
= move
;
17326 transform_to_arch_instruction(state
, move
);
17329 print_blocks(state
, __func__
, state
->dbgout
);
17332 struct triple_reg_set
;
17336 static int do_triple_set(struct triple_reg_set
**head
,
17337 struct triple
*member
, struct triple
*new_member
)
17339 struct triple_reg_set
**ptr
, *new;
17344 if ((*ptr
)->member
== member
) {
17347 ptr
= &(*ptr
)->next
;
17349 new = xcmalloc(sizeof(*new), "triple_set");
17350 new->member
= member
;
17351 new->new = new_member
;
17357 static void do_triple_unset(struct triple_reg_set
**head
, struct triple
*member
)
17359 struct triple_reg_set
*entry
, **ptr
;
17363 if (entry
->member
== member
) {
17364 *ptr
= entry
->next
;
17369 ptr
= &entry
->next
;
17374 static int in_triple(struct reg_block
*rb
, struct triple
*in
)
17376 return do_triple_set(&rb
->in
, in
, 0);
17379 #if DEBUG_ROMCC_WARNING
17380 static void unin_triple(struct reg_block
*rb
, struct triple
*unin
)
17382 do_triple_unset(&rb
->in
, unin
);
17386 static int out_triple(struct reg_block
*rb
, struct triple
*out
)
17388 return do_triple_set(&rb
->out
, out
, 0);
17390 #if DEBUG_ROMCC_WARNING
17391 static void unout_triple(struct reg_block
*rb
, struct triple
*unout
)
17393 do_triple_unset(&rb
->out
, unout
);
17397 static int initialize_regblock(struct reg_block
*blocks
,
17398 struct block
*block
, int vertex
)
17400 struct block_set
*user
;
17401 if (!block
|| (blocks
[block
->vertex
].block
== block
)) {
17405 /* Renumber the blocks in a convinient fashion */
17406 block
->vertex
= vertex
;
17407 blocks
[vertex
].block
= block
;
17408 blocks
[vertex
].vertex
= vertex
;
17409 for(user
= block
->use
; user
; user
= user
->next
) {
17410 vertex
= initialize_regblock(blocks
, user
->member
, vertex
);
17415 static struct triple
*part_to_piece(struct compile_state
*state
, struct triple
*ins
)
17417 /* Part to piece is a best attempt and it cannot be correct all by
17418 * itself. If various values are read as different sizes in different
17419 * parts of the code this function cannot work. Or rather it cannot
17420 * work in conjunction with compute_variable_liftimes. As the
17421 * analysis will get confused.
17423 struct triple
*base
;
17425 if (!is_lvalue(state
, ins
)) {
17430 while(ins
&& triple_is_part(state
, ins
) && (ins
->op
!= OP_PIECE
)) {
17431 base
= MISC(ins
, 0);
17434 reg
+= index_reg_offset(state
, base
->type
, ins
->u
.cval
)/REG_SIZEOF_REG
;
17437 reg
+= field_reg_offset(state
, base
->type
, ins
->u
.field
)/REG_SIZEOF_REG
;
17440 internal_error(state
, ins
, "unhandled part");
17446 if (reg
> base
->lhs
) {
17447 internal_error(state
, base
, "part out of range?");
17449 ins
= LHS(base
, reg
);
17454 static int this_def(struct compile_state
*state
,
17455 struct triple
*ins
, struct triple
*other
)
17457 if (ins
== other
) {
17460 if (ins
->op
== OP_WRITE
) {
17461 ins
= part_to_piece(state
, MISC(ins
, 0));
17463 return ins
== other
;
17466 static int phi_in(struct compile_state
*state
, struct reg_block
*blocks
,
17467 struct reg_block
*rb
, struct block
*suc
)
17469 /* Read the conditional input set of a successor block
17470 * (i.e. the input to the phi nodes) and place it in the
17471 * current blocks output set.
17473 struct block_set
*set
;
17474 struct triple
*ptr
;
17478 /* Find the edge I am coming in on */
17479 for(edge
= 0, set
= suc
->use
; set
; set
= set
->next
, edge
++) {
17480 if (set
->member
== rb
->block
) {
17485 internal_error(state
, 0, "Not coming on a control edge?");
17487 for(done
= 0, ptr
= suc
->first
; !done
; ptr
= ptr
->next
) {
17488 struct triple
**slot
, *expr
, *ptr2
;
17489 int out_change
, done2
;
17490 done
= (ptr
== suc
->last
);
17491 if (ptr
->op
!= OP_PHI
) {
17494 slot
= &RHS(ptr
, 0);
17496 out_change
= out_triple(rb
, expr
);
17500 /* If we don't define the variable also plast it
17501 * in the current blocks input set.
17503 ptr2
= rb
->block
->first
;
17504 for(done2
= 0; !done2
; ptr2
= ptr2
->next
) {
17505 if (this_def(state
, ptr2
, expr
)) {
17508 done2
= (ptr2
== rb
->block
->last
);
17513 change
|= in_triple(rb
, expr
);
17518 static int reg_in(struct compile_state
*state
, struct reg_block
*blocks
,
17519 struct reg_block
*rb
, struct block
*suc
)
17521 struct triple_reg_set
*in_set
;
17524 /* Read the input set of a successor block
17525 * and place it in the current blocks output set.
17527 in_set
= blocks
[suc
->vertex
].in
;
17528 for(; in_set
; in_set
= in_set
->next
) {
17529 int out_change
, done
;
17530 struct triple
*first
, *last
, *ptr
;
17531 out_change
= out_triple(rb
, in_set
->member
);
17535 /* If we don't define the variable also place it
17536 * in the current blocks input set.
17538 first
= rb
->block
->first
;
17539 last
= rb
->block
->last
;
17541 for(ptr
= first
; !done
; ptr
= ptr
->next
) {
17542 if (this_def(state
, ptr
, in_set
->member
)) {
17545 done
= (ptr
== last
);
17550 change
|= in_triple(rb
, in_set
->member
);
17552 change
|= phi_in(state
, blocks
, rb
, suc
);
17556 static int use_in(struct compile_state
*state
, struct reg_block
*rb
)
17558 /* Find the variables we use but don't define and add
17559 * it to the current blocks input set.
17561 #if DEBUG_ROMCC_WARNINGS
17562 #warning "FIXME is this O(N^2) algorithm bad?"
17564 struct block
*block
;
17565 struct triple
*ptr
;
17570 for(done
= 0, ptr
= block
->last
; !done
; ptr
= ptr
->prev
) {
17571 struct triple
**expr
;
17572 done
= (ptr
== block
->first
);
17573 /* The variable a phi function uses depends on the
17574 * control flow, and is handled in phi_in, not
17577 if (ptr
->op
== OP_PHI
) {
17580 expr
= triple_rhs(state
, ptr
, 0);
17581 for(;expr
; expr
= triple_rhs(state
, ptr
, expr
)) {
17582 struct triple
*rhs
, *test
;
17584 rhs
= part_to_piece(state
, *expr
);
17589 /* See if rhs is defined in this block.
17590 * A write counts as a definition.
17592 for(tdone
= 0, test
= ptr
; !tdone
; test
= test
->prev
) {
17593 tdone
= (test
== block
->first
);
17594 if (this_def(state
, test
, rhs
)) {
17599 /* If I still have a valid rhs add it to in */
17600 change
|= in_triple(rb
, rhs
);
17606 static struct reg_block
*compute_variable_lifetimes(
17607 struct compile_state
*state
, struct basic_blocks
*bb
)
17609 struct reg_block
*blocks
;
17612 sizeof(*blocks
)*(bb
->last_vertex
+ 1), "reg_block");
17613 initialize_regblock(blocks
, bb
->last_block
, 0);
17617 for(i
= 1; i
<= bb
->last_vertex
; i
++) {
17618 struct block_set
*edge
;
17619 struct reg_block
*rb
;
17621 /* Add the all successor's input set to in */
17622 for(edge
= rb
->block
->edges
; edge
; edge
= edge
->next
) {
17623 change
|= reg_in(state
, blocks
, rb
, edge
->member
);
17625 /* Add use to in... */
17626 change
|= use_in(state
, rb
);
17632 static void free_variable_lifetimes(struct compile_state
*state
,
17633 struct basic_blocks
*bb
, struct reg_block
*blocks
)
17636 /* free in_set && out_set on each block */
17637 for(i
= 1; i
<= bb
->last_vertex
; i
++) {
17638 struct triple_reg_set
*entry
, *next
;
17639 struct reg_block
*rb
;
17641 for(entry
= rb
->in
; entry
; entry
= next
) {
17642 next
= entry
->next
;
17643 do_triple_unset(&rb
->in
, entry
->member
);
17645 for(entry
= rb
->out
; entry
; entry
= next
) {
17646 next
= entry
->next
;
17647 do_triple_unset(&rb
->out
, entry
->member
);
17654 typedef void (*wvl_cb_t
)(
17655 struct compile_state
*state
,
17656 struct reg_block
*blocks
, struct triple_reg_set
*live
,
17657 struct reg_block
*rb
, struct triple
*ins
, void *arg
);
17659 static void walk_variable_lifetimes(struct compile_state
*state
,
17660 struct basic_blocks
*bb
, struct reg_block
*blocks
,
17661 wvl_cb_t cb
, void *arg
)
17665 for(i
= 1; i
<= state
->bb
.last_vertex
; i
++) {
17666 struct triple_reg_set
*live
;
17667 struct triple_reg_set
*entry
, *next
;
17668 struct triple
*ptr
, *prev
;
17669 struct reg_block
*rb
;
17670 struct block
*block
;
17673 /* Get the blocks */
17677 /* Copy out into live */
17679 for(entry
= rb
->out
; entry
; entry
= next
) {
17680 next
= entry
->next
;
17681 do_triple_set(&live
, entry
->member
, entry
->new);
17683 /* Walk through the basic block calculating live */
17684 for(done
= 0, ptr
= block
->last
; !done
; ptr
= prev
) {
17685 struct triple
**expr
;
17688 done
= (ptr
== block
->first
);
17690 /* Ensure the current definition is in live */
17691 if (triple_is_def(state
, ptr
)) {
17692 do_triple_set(&live
, ptr
, 0);
17695 /* Inform the callback function of what is
17698 cb(state
, blocks
, live
, rb
, ptr
, arg
);
17700 /* Remove the current definition from live */
17701 do_triple_unset(&live
, ptr
);
17703 /* Add the current uses to live.
17705 * It is safe to skip phi functions because they do
17706 * not have any block local uses, and the block
17707 * output sets already properly account for what
17708 * control flow depedent uses phi functions do have.
17710 if (ptr
->op
== OP_PHI
) {
17713 expr
= triple_rhs(state
, ptr
, 0);
17714 for(;expr
; expr
= triple_rhs(state
, ptr
, expr
)) {
17715 /* If the triple is not a definition skip it. */
17716 if (!*expr
|| !triple_is_def(state
, *expr
)) {
17719 do_triple_set(&live
, *expr
, 0);
17723 for(entry
= live
; entry
; entry
= next
) {
17724 next
= entry
->next
;
17725 do_triple_unset(&live
, entry
->member
);
17730 struct print_live_variable_info
{
17731 struct reg_block
*rb
;
17734 #if DEBUG_EXPLICIT_CLOSURES
17735 static void print_live_variables_block(
17736 struct compile_state
*state
, struct block
*block
, void *arg
)
17739 struct print_live_variable_info
*info
= arg
;
17740 struct block_set
*edge
;
17741 FILE *fp
= info
->fp
;
17742 struct reg_block
*rb
;
17743 struct triple
*ptr
;
17746 rb
= &info
->rb
[block
->vertex
];
17748 fprintf(fp
, "\nblock: %p (%d),",
17749 block
, block
->vertex
);
17750 for(edge
= block
->edges
; edge
; edge
= edge
->next
) {
17751 fprintf(fp
, " %p<-%p",
17753 edge
->member
&& edge
->member
->use
?edge
->member
->use
->member
: 0);
17757 struct triple_reg_set
*in_set
;
17758 fprintf(fp
, " in:");
17759 for(in_set
= rb
->in
; in_set
; in_set
= in_set
->next
) {
17760 fprintf(fp
, " %-10p", in_set
->member
);
17765 for(done
= 0, ptr
= block
->first
; !done
; ptr
= ptr
->next
) {
17766 done
= (ptr
== block
->last
);
17767 if (ptr
->op
== OP_PHI
) {
17774 for(edge
= 0; edge
< block
->users
; edge
++) {
17775 fprintf(fp
, " in(%d):", edge
);
17776 for(done
= 0, ptr
= block
->first
; !done
; ptr
= ptr
->next
) {
17777 struct triple
**slot
;
17778 done
= (ptr
== block
->last
);
17779 if (ptr
->op
!= OP_PHI
) {
17782 slot
= &RHS(ptr
, 0);
17783 fprintf(fp
, " %-10p", slot
[edge
]);
17788 if (block
->first
->op
== OP_LABEL
) {
17789 fprintf(fp
, "%p:\n", block
->first
);
17791 for(done
= 0, ptr
= block
->first
; !done
; ptr
= ptr
->next
) {
17792 done
= (ptr
== block
->last
);
17793 display_triple(fp
, ptr
);
17796 struct triple_reg_set
*out_set
;
17797 fprintf(fp
, " out:");
17798 for(out_set
= rb
->out
; out_set
; out_set
= out_set
->next
) {
17799 fprintf(fp
, " %-10p", out_set
->member
);
17806 static void print_live_variables(struct compile_state
*state
,
17807 struct basic_blocks
*bb
, struct reg_block
*rb
, FILE *fp
)
17809 struct print_live_variable_info info
;
17812 fprintf(fp
, "\nlive variables by block\n");
17813 walk_blocks(state
, bb
, print_live_variables_block
, &info
);
17818 static int count_triples(struct compile_state
*state
)
17820 struct triple
*first
, *ins
;
17822 first
= state
->first
;
17827 } while (ins
!= first
);
17832 struct dead_triple
{
17833 struct triple
*triple
;
17834 struct dead_triple
*work_next
;
17835 struct block
*block
;
17838 #define TRIPLE_FLAG_ALIVE 1
17839 #define TRIPLE_FLAG_FREE 1
17842 static void print_dead_triples(struct compile_state
*state
,
17843 struct dead_triple
*dtriple
)
17845 struct triple
*first
, *ins
;
17846 struct dead_triple
*dt
;
17848 if (!(state
->compiler
->debug
& DEBUG_TRIPLES
)) {
17851 fp
= state
->dbgout
;
17852 fprintf(fp
, "--------------- dtriples ---------------\n");
17853 first
= state
->first
;
17856 dt
= &dtriple
[ins
->id
];
17857 if ((ins
->op
== OP_LABEL
) && (ins
->use
)) {
17858 fprintf(fp
, "\n%p:\n", ins
);
17861 (dt
->flags
& TRIPLE_FLAG_ALIVE
)?' ': '-');
17862 display_triple(fp
, ins
);
17863 if (triple_is_branch(state
, ins
)) {
17867 } while(ins
!= first
);
17872 static void awaken(
17873 struct compile_state
*state
,
17874 struct dead_triple
*dtriple
, struct triple
**expr
,
17875 struct dead_triple
***work_list_tail
)
17877 struct triple
*triple
;
17878 struct dead_triple
*dt
;
17886 if (triple
->id
<= 0) {
17887 internal_error(state
, triple
, "bad triple id: %d",
17890 if (triple
->op
== OP_NOOP
) {
17891 internal_error(state
, triple
, "awakening noop?");
17894 dt
= &dtriple
[triple
->id
];
17895 if (!(dt
->flags
& TRIPLE_FLAG_ALIVE
)) {
17896 dt
->flags
|= TRIPLE_FLAG_ALIVE
;
17897 if (!dt
->work_next
) {
17898 **work_list_tail
= dt
;
17899 *work_list_tail
= &dt
->work_next
;
17904 static void eliminate_inefectual_code(struct compile_state
*state
)
17906 struct dead_triple
*dtriple
, *work_list
, **work_list_tail
, *dt
;
17908 struct triple
*first
, *ins
;
17910 if (!(state
->compiler
->flags
& COMPILER_ELIMINATE_INEFECTUAL_CODE
)) {
17914 /* Setup the work list */
17916 work_list_tail
= &work_list
;
17918 first
= state
->first
;
17920 /* Count how many triples I have */
17921 triples
= count_triples(state
);
17923 /* Now put then in an array and mark all of the triples dead */
17924 dtriple
= xcmalloc(sizeof(*dtriple
) * (triples
+ 1), "dtriples");
17929 dtriple
[i
].triple
= ins
;
17930 dtriple
[i
].block
= block_of_triple(state
, ins
);
17931 dtriple
[i
].flags
= 0;
17932 dtriple
[i
].old_id
= ins
->id
;
17934 /* See if it is an operation we always keep */
17935 if (!triple_is_pure(state
, ins
, dtriple
[i
].old_id
)) {
17936 awaken(state
, dtriple
, &ins
, &work_list_tail
);
17940 } while(ins
!= first
);
17942 struct block
*block
;
17943 struct dead_triple
*dt
;
17944 struct block_set
*user
;
17945 struct triple
**expr
;
17947 work_list
= dt
->work_next
;
17949 work_list_tail
= &work_list
;
17951 /* Make certain the block the current instruction is in lives */
17952 block
= block_of_triple(state
, dt
->triple
);
17953 awaken(state
, dtriple
, &block
->first
, &work_list_tail
);
17954 if (triple_is_branch(state
, block
->last
)) {
17955 awaken(state
, dtriple
, &block
->last
, &work_list_tail
);
17957 awaken(state
, dtriple
, &block
->last
->next
, &work_list_tail
);
17960 /* Wake up the data depencencies of this triple */
17963 expr
= triple_rhs(state
, dt
->triple
, expr
);
17964 awaken(state
, dtriple
, expr
, &work_list_tail
);
17967 expr
= triple_lhs(state
, dt
->triple
, expr
);
17968 awaken(state
, dtriple
, expr
, &work_list_tail
);
17971 expr
= triple_misc(state
, dt
->triple
, expr
);
17972 awaken(state
, dtriple
, expr
, &work_list_tail
);
17974 /* Wake up the forward control dependencies */
17976 expr
= triple_targ(state
, dt
->triple
, expr
);
17977 awaken(state
, dtriple
, expr
, &work_list_tail
);
17979 /* Wake up the reverse control dependencies of this triple */
17980 for(user
= dt
->block
->ipdomfrontier
; user
; user
= user
->next
) {
17981 struct triple
*last
;
17982 last
= user
->member
->last
;
17983 while((last
->op
== OP_NOOP
) && (last
!= user
->member
->first
)) {
17984 #if DEBUG_ROMCC_WARNINGS
17985 #warning "Should we bring the awakening noops back?"
17987 // internal_warning(state, last, "awakening noop?");
17990 awaken(state
, dtriple
, &last
, &work_list_tail
);
17993 print_dead_triples(state
, dtriple
);
17994 for(dt
= &dtriple
[1]; dt
<= &dtriple
[triples
]; dt
++) {
17995 if ((dt
->triple
->op
== OP_NOOP
) &&
17996 (dt
->flags
& TRIPLE_FLAG_ALIVE
)) {
17997 internal_error(state
, dt
->triple
, "noop effective?");
17999 dt
->triple
->id
= dt
->old_id
; /* Restore the color */
18000 if (!(dt
->flags
& TRIPLE_FLAG_ALIVE
)) {
18001 release_triple(state
, dt
->triple
);
18006 rebuild_ssa_form(state
);
18008 print_blocks(state
, __func__
, state
->dbgout
);
18012 static void insert_mandatory_copies(struct compile_state
*state
)
18014 struct triple
*ins
, *first
;
18016 /* The object is with a minimum of inserted copies,
18017 * to resolve in fundamental register conflicts between
18018 * register value producers and consumers.
18019 * Theoretically we may be greater than minimal when we
18020 * are inserting copies before instructions but that
18021 * case should be rare.
18023 first
= state
->first
;
18026 struct triple_set
*entry
, *next
;
18027 struct triple
*tmp
;
18028 struct reg_info info
;
18029 unsigned reg
, regcm
;
18030 int do_post_copy
, do_pre_copy
;
18032 if (!triple_is_def(state
, ins
)) {
18035 /* Find the architecture specific color information */
18036 info
= find_lhs_pre_color(state
, ins
, 0);
18037 if (info
.reg
>= MAX_REGISTERS
) {
18038 info
.reg
= REG_UNSET
;
18042 regcm
= arch_type_to_regcm(state
, ins
->type
);
18043 do_post_copy
= do_pre_copy
= 0;
18045 /* Walk through the uses of ins and check for conflicts */
18046 for(entry
= ins
->use
; entry
; entry
= next
) {
18047 struct reg_info rinfo
;
18049 next
= entry
->next
;
18050 i
= find_rhs_use(state
, entry
->member
, ins
);
18055 /* Find the users color requirements */
18056 rinfo
= arch_reg_rhs(state
, entry
->member
, i
);
18057 if (rinfo
.reg
>= MAX_REGISTERS
) {
18058 rinfo
.reg
= REG_UNSET
;
18061 /* See if I need a pre_copy */
18062 if (rinfo
.reg
!= REG_UNSET
) {
18063 if ((reg
!= REG_UNSET
) && (reg
!= rinfo
.reg
)) {
18068 regcm
&= rinfo
.regcm
;
18069 regcm
= arch_regcm_normalize(state
, regcm
);
18073 /* Always use pre_copies for constants.
18074 * They do not take up any registers until a
18075 * copy places them in one.
18077 if ((info
.reg
== REG_UNNEEDED
) &&
18078 (rinfo
.reg
!= REG_UNNEEDED
)) {
18084 (((info
.reg
!= REG_UNSET
) &&
18085 (reg
!= REG_UNSET
) &&
18086 (info
.reg
!= reg
)) ||
18087 ((info
.regcm
& regcm
) == 0));
18090 regcm
= info
.regcm
;
18091 /* Walk through the uses of ins and do a pre_copy or see if a post_copy is warranted */
18092 for(entry
= ins
->use
; entry
; entry
= next
) {
18093 struct reg_info rinfo
;
18095 next
= entry
->next
;
18096 i
= find_rhs_use(state
, entry
->member
, ins
);
18101 /* Find the users color requirements */
18102 rinfo
= arch_reg_rhs(state
, entry
->member
, i
);
18103 if (rinfo
.reg
>= MAX_REGISTERS
) {
18104 rinfo
.reg
= REG_UNSET
;
18107 /* Now see if it is time to do the pre_copy */
18108 if (rinfo
.reg
!= REG_UNSET
) {
18109 if (((reg
!= REG_UNSET
) && (reg
!= rinfo
.reg
)) ||
18110 ((regcm
& rinfo
.regcm
) == 0) ||
18111 /* Don't let a mandatory coalesce sneak
18112 * into a operation that is marked to prevent
18115 ((reg
!= REG_UNNEEDED
) &&
18116 ((ins
->id
& TRIPLE_FLAG_POST_SPLIT
) ||
18117 (entry
->member
->id
& TRIPLE_FLAG_PRE_SPLIT
)))
18120 struct triple
*user
;
18121 user
= entry
->member
;
18122 if (RHS(user
, i
) != ins
) {
18123 internal_error(state
, user
, "bad rhs");
18125 tmp
= pre_copy(state
, user
, i
);
18126 tmp
->id
|= TRIPLE_FLAG_PRE_SPLIT
;
18134 if ((regcm
& rinfo
.regcm
) == 0) {
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
;
18148 regcm
&= rinfo
.regcm
;
18151 if (do_post_copy
) {
18152 struct reg_info pre
, post
;
18153 tmp
= post_copy(state
, ins
);
18154 tmp
->id
|= TRIPLE_FLAG_PRE_SPLIT
;
18155 pre
= arch_reg_lhs(state
, ins
, 0);
18156 post
= arch_reg_lhs(state
, tmp
, 0);
18157 if ((pre
.reg
== post
.reg
) && (pre
.regcm
== post
.regcm
)) {
18158 internal_error(state
, tmp
, "useless copy");
18163 } while(ins
!= first
);
18165 print_blocks(state
, __func__
, state
->dbgout
);
18169 struct live_range_edge
;
18170 struct live_range_def
;
18171 struct live_range
{
18172 struct live_range_edge
*edges
;
18173 struct live_range_def
*defs
;
18174 /* Note. The list pointed to by defs is kept in order.
18175 * That is baring splits in the flow control
18176 * defs dominates defs->next wich dominates defs->next->next
18183 struct live_range
*group_next
, **group_prev
;
18186 struct live_range_edge
{
18187 struct live_range_edge
*next
;
18188 struct live_range
*node
;
18191 struct live_range_def
{
18192 struct live_range_def
*next
;
18193 struct live_range_def
*prev
;
18194 struct live_range
*lr
;
18195 struct triple
*def
;
18199 #define LRE_HASH_SIZE 2048
18201 struct lre_hash
*next
;
18202 struct live_range
*left
;
18203 struct live_range
*right
;
18208 struct lre_hash
*hash
[LRE_HASH_SIZE
];
18209 struct reg_block
*blocks
;
18210 struct live_range_def
*lrd
;
18211 struct live_range
*lr
;
18212 struct live_range
*low
, **low_tail
;
18213 struct live_range
*high
, **high_tail
;
18216 int passes
, max_passes
;
18220 struct print_interference_block_info
{
18221 struct reg_state
*rstate
;
18225 static void print_interference_block(
18226 struct compile_state
*state
, struct block
*block
, void *arg
)
18229 struct print_interference_block_info
*info
= arg
;
18230 struct reg_state
*rstate
= info
->rstate
;
18231 struct block_set
*edge
;
18232 FILE *fp
= info
->fp
;
18233 struct reg_block
*rb
;
18234 struct triple
*ptr
;
18237 rb
= &rstate
->blocks
[block
->vertex
];
18239 fprintf(fp
, "\nblock: %p (%d),",
18240 block
, block
->vertex
);
18241 for(edge
= block
->edges
; edge
; edge
= edge
->next
) {
18242 fprintf(fp
, " %p<-%p",
18244 edge
->member
&& edge
->member
->use
?edge
->member
->use
->member
: 0);
18248 struct triple_reg_set
*in_set
;
18249 fprintf(fp
, " in:");
18250 for(in_set
= rb
->in
; in_set
; in_set
= in_set
->next
) {
18251 fprintf(fp
, " %-10p", in_set
->member
);
18256 for(done
= 0, ptr
= block
->first
; !done
; ptr
= ptr
->next
) {
18257 done
= (ptr
== block
->last
);
18258 if (ptr
->op
== OP_PHI
) {
18265 for(edge
= 0; edge
< block
->users
; edge
++) {
18266 fprintf(fp
, " in(%d):", edge
);
18267 for(done
= 0, ptr
= block
->first
; !done
; ptr
= ptr
->next
) {
18268 struct triple
**slot
;
18269 done
= (ptr
== block
->last
);
18270 if (ptr
->op
!= OP_PHI
) {
18273 slot
= &RHS(ptr
, 0);
18274 fprintf(fp
, " %-10p", slot
[edge
]);
18279 if (block
->first
->op
== OP_LABEL
) {
18280 fprintf(fp
, "%p:\n", block
->first
);
18282 for(done
= 0, ptr
= block
->first
; !done
; ptr
= ptr
->next
) {
18283 struct live_range
*lr
;
18285 done
= (ptr
== block
->last
);
18286 lr
= rstate
->lrd
[ptr
->id
].lr
;
18289 ptr
->id
= rstate
->lrd
[id
].orig_id
;
18290 SET_REG(ptr
->id
, lr
->color
);
18291 display_triple(fp
, ptr
);
18294 if (triple_is_def(state
, ptr
) && (lr
->defs
== 0)) {
18295 internal_error(state
, ptr
, "lr has no defs!");
18297 if (info
->need_edges
) {
18299 struct live_range_def
*lrd
;
18300 fprintf(fp
, " range:");
18303 fprintf(fp
, " %-10p", lrd
->def
);
18305 } while(lrd
!= lr
->defs
);
18308 if (lr
->edges
> 0) {
18309 struct live_range_edge
*edge
;
18310 fprintf(fp
, " edges:");
18311 for(edge
= lr
->edges
; edge
; edge
= edge
->next
) {
18312 struct live_range_def
*lrd
;
18313 lrd
= edge
->node
->defs
;
18315 fprintf(fp
, " %-10p", lrd
->def
);
18317 } while(lrd
!= edge
->node
->defs
);
18323 /* Do a bunch of sanity checks */
18324 valid_ins(state
, ptr
);
18325 if (ptr
->id
> rstate
->defs
) {
18326 internal_error(state
, ptr
, "Invalid triple id: %d",
18331 struct triple_reg_set
*out_set
;
18332 fprintf(fp
, " out:");
18333 for(out_set
= rb
->out
; out_set
; out_set
= out_set
->next
) {
18334 fprintf(fp
, " %-10p", out_set
->member
);
18341 static void print_interference_blocks(
18342 struct compile_state
*state
, struct reg_state
*rstate
, FILE *fp
, int need_edges
)
18344 struct print_interference_block_info info
;
18345 info
.rstate
= rstate
;
18347 info
.need_edges
= need_edges
;
18348 fprintf(fp
, "\nlive variables by block\n");
18349 walk_blocks(state
, &state
->bb
, print_interference_block
, &info
);
18353 static unsigned regc_max_size(struct compile_state
*state
, int classes
)
18358 for(i
= 0; i
< MAX_REGC
; i
++) {
18359 if (classes
& (1 << i
)) {
18361 size
= arch_regc_size(state
, i
);
18362 if (size
> max_size
) {
18370 static int reg_is_reg(struct compile_state
*state
, int reg1
, int reg2
)
18372 unsigned equivs
[MAX_REG_EQUIVS
];
18374 if ((reg1
< 0) || (reg1
>= MAX_REGISTERS
)) {
18375 internal_error(state
, 0, "invalid register");
18377 if ((reg2
< 0) || (reg2
>= MAX_REGISTERS
)) {
18378 internal_error(state
, 0, "invalid register");
18380 arch_reg_equivs(state
, equivs
, reg1
);
18381 for(i
= 0; (i
< MAX_REG_EQUIVS
) && equivs
[i
] != REG_UNSET
; i
++) {
18382 if (equivs
[i
] == reg2
) {
18389 static void reg_fill_used(struct compile_state
*state
, char *used
, int reg
)
18391 unsigned equivs
[MAX_REG_EQUIVS
];
18393 if (reg
== REG_UNNEEDED
) {
18396 arch_reg_equivs(state
, equivs
, reg
);
18397 for(i
= 0; (i
< MAX_REG_EQUIVS
) && equivs
[i
] != REG_UNSET
; i
++) {
18398 used
[equivs
[i
]] = 1;
18403 static void reg_inc_used(struct compile_state
*state
, char *used
, int reg
)
18405 unsigned equivs
[MAX_REG_EQUIVS
];
18407 if (reg
== REG_UNNEEDED
) {
18410 arch_reg_equivs(state
, equivs
, reg
);
18411 for(i
= 0; (i
< MAX_REG_EQUIVS
) && equivs
[i
] != REG_UNSET
; i
++) {
18412 used
[equivs
[i
]] += 1;
18417 static unsigned int hash_live_edge(
18418 struct live_range
*left
, struct live_range
*right
)
18420 unsigned int hash
, val
;
18421 unsigned long lval
, rval
;
18422 lval
= ((unsigned long)left
)/sizeof(struct live_range
);
18423 rval
= ((unsigned long)right
)/sizeof(struct live_range
);
18428 hash
= (hash
*263) + val
;
18433 hash
= (hash
*263) + val
;
18435 hash
= hash
& (LRE_HASH_SIZE
- 1);
18439 static struct lre_hash
**lre_probe(struct reg_state
*rstate
,
18440 struct live_range
*left
, struct live_range
*right
)
18442 struct lre_hash
**ptr
;
18443 unsigned int index
;
18444 /* Ensure left <= right */
18445 if (left
> right
) {
18446 struct live_range
*tmp
;
18451 index
= hash_live_edge(left
, right
);
18453 ptr
= &rstate
->hash
[index
];
18455 if (((*ptr
)->left
== left
) && ((*ptr
)->right
== right
)) {
18458 ptr
= &(*ptr
)->next
;
18463 static int interfere(struct reg_state
*rstate
,
18464 struct live_range
*left
, struct live_range
*right
)
18466 struct lre_hash
**ptr
;
18467 ptr
= lre_probe(rstate
, left
, right
);
18468 return ptr
&& *ptr
;
18471 static void add_live_edge(struct reg_state
*rstate
,
18472 struct live_range
*left
, struct live_range
*right
)
18474 /* FIXME the memory allocation overhead is noticeable here... */
18475 struct lre_hash
**ptr
, *new_hash
;
18476 struct live_range_edge
*edge
;
18478 if (left
== right
) {
18481 if ((left
== &rstate
->lr
[0]) || (right
== &rstate
->lr
[0])) {
18484 /* Ensure left <= right */
18485 if (left
> right
) {
18486 struct live_range
*tmp
;
18491 ptr
= lre_probe(rstate
, left
, right
);
18496 fprintf(state
->errout
, "new_live_edge(%p, %p)\n",
18499 new_hash
= xmalloc(sizeof(*new_hash
), "lre_hash");
18500 new_hash
->next
= *ptr
;
18501 new_hash
->left
= left
;
18502 new_hash
->right
= right
;
18505 edge
= xmalloc(sizeof(*edge
), "live_range_edge");
18506 edge
->next
= left
->edges
;
18507 edge
->node
= right
;
18508 left
->edges
= edge
;
18511 edge
= xmalloc(sizeof(*edge
), "live_range_edge");
18512 edge
->next
= right
->edges
;
18514 right
->edges
= edge
;
18515 right
->degree
+= 1;
18518 static void remove_live_edge(struct reg_state
*rstate
,
18519 struct live_range
*left
, struct live_range
*right
)
18521 struct live_range_edge
*edge
, **ptr
;
18522 struct lre_hash
**hptr
, *entry
;
18523 hptr
= lre_probe(rstate
, left
, right
);
18524 if (!hptr
|| !*hptr
) {
18528 *hptr
= entry
->next
;
18531 for(ptr
= &left
->edges
; *ptr
; ptr
= &(*ptr
)->next
) {
18533 if (edge
->node
== right
) {
18535 memset(edge
, 0, sizeof(*edge
));
18541 for(ptr
= &right
->edges
; *ptr
; ptr
= &(*ptr
)->next
) {
18543 if (edge
->node
== left
) {
18545 memset(edge
, 0, sizeof(*edge
));
18553 static void remove_live_edges(struct reg_state
*rstate
, struct live_range
*range
)
18555 struct live_range_edge
*edge
, *next
;
18556 for(edge
= range
->edges
; edge
; edge
= next
) {
18558 remove_live_edge(rstate
, range
, edge
->node
);
18562 static void transfer_live_edges(struct reg_state
*rstate
,
18563 struct live_range
*dest
, struct live_range
*src
)
18565 struct live_range_edge
*edge
, *next
;
18566 for(edge
= src
->edges
; edge
; edge
= next
) {
18567 struct live_range
*other
;
18569 other
= edge
->node
;
18570 remove_live_edge(rstate
, src
, other
);
18571 add_live_edge(rstate
, dest
, other
);
18576 /* Interference graph...
18578 * new(n) --- Return a graph with n nodes but no edges.
18579 * add(g,x,y) --- Return a graph including g with an between x and y
18580 * interfere(g, x, y) --- Return true if there exists an edge between the nodes
18581 * x and y in the graph g
18582 * degree(g, x) --- Return the degree of the node x in the graph g
18583 * neighbors(g, x, f) --- Apply function f to each neighbor of node x in the graph g
18585 * Implement with a hash table && a set of adjcency vectors.
18586 * The hash table supports constant time implementations of add and interfere.
18587 * The adjacency vectors support an efficient implementation of neighbors.
18591 * +---------------------------------------------------+
18592 * | +--------------+ |
18594 * renumber -> build graph -> colalesce -> spill_costs -> simplify -> select
18596 * -- In simplify implment optimistic coloring... (No backtracking)
18597 * -- Implement Rematerialization it is the only form of spilling we can perform
18598 * Essentially this means dropping a constant from a register because
18599 * we can regenerate it later.
18601 * --- Very conservative colalescing (don't colalesce just mark the opportunities)
18602 * coalesce at phi points...
18603 * --- Bias coloring if at all possible do the coalesing a compile time.
18608 #if DEBUG_ROMCC_WARNING
18609 static void different_colored(
18610 struct compile_state
*state
, struct reg_state
*rstate
,
18611 struct triple
*parent
, struct triple
*ins
)
18613 struct live_range
*lr
;
18614 struct triple
**expr
;
18615 lr
= rstate
->lrd
[ins
->id
].lr
;
18616 expr
= triple_rhs(state
, ins
, 0);
18617 for(;expr
; expr
= triple_rhs(state
, ins
, expr
)) {
18618 struct live_range
*lr2
;
18619 if (!*expr
|| (*expr
== parent
) || (*expr
== ins
)) {
18622 lr2
= rstate
->lrd
[(*expr
)->id
].lr
;
18623 if (lr
->color
== lr2
->color
) {
18624 internal_error(state
, ins
, "live range too big");
18630 static struct live_range
*coalesce_ranges(
18631 struct compile_state
*state
, struct reg_state
*rstate
,
18632 struct live_range
*lr1
, struct live_range
*lr2
)
18634 struct live_range_def
*head
, *mid1
, *mid2
, *end
, *lrd
;
18640 if (!lr1
->defs
|| !lr2
->defs
) {
18641 internal_error(state
, 0,
18642 "cannot coalese dead live ranges");
18644 if ((lr1
->color
== REG_UNNEEDED
) ||
18645 (lr2
->color
== REG_UNNEEDED
)) {
18646 internal_error(state
, 0,
18647 "cannot coalesce live ranges without a possible color");
18649 if ((lr1
->color
!= lr2
->color
) &&
18650 (lr1
->color
!= REG_UNSET
) &&
18651 (lr2
->color
!= REG_UNSET
)) {
18652 internal_error(state
, lr1
->defs
->def
,
18653 "cannot coalesce live ranges of different colors");
18655 color
= lr1
->color
;
18656 if (color
== REG_UNSET
) {
18657 color
= lr2
->color
;
18659 classes
= lr1
->classes
& lr2
->classes
;
18661 internal_error(state
, lr1
->defs
->def
,
18662 "cannot coalesce live ranges with dissimilar register classes");
18664 if (state
->compiler
->debug
& DEBUG_COALESCING
) {
18665 FILE *fp
= state
->errout
;
18666 fprintf(fp
, "coalescing:");
18669 fprintf(fp
, " %p", lrd
->def
);
18671 } while(lrd
!= lr1
->defs
);
18675 fprintf(fp
, " %p", lrd
->def
);
18677 } while(lrd
!= lr2
->defs
);
18680 /* If there is a clear dominate live range put it in lr1,
18681 * For purposes of this test phi functions are
18682 * considered dominated by the definitions that feed into
18685 if ((lr1
->defs
->prev
->def
->op
== OP_PHI
) ||
18686 ((lr2
->defs
->prev
->def
->op
!= OP_PHI
) &&
18687 tdominates(state
, lr2
->defs
->def
, lr1
->defs
->def
))) {
18688 struct live_range
*tmp
;
18694 if (lr1
->defs
->orig_id
& TRIPLE_FLAG_POST_SPLIT
) {
18695 fprintf(state
->errout
, "lr1 post\n");
18697 if (lr1
->defs
->orig_id
& TRIPLE_FLAG_PRE_SPLIT
) {
18698 fprintf(state
->errout
, "lr1 pre\n");
18700 if (lr2
->defs
->orig_id
& TRIPLE_FLAG_POST_SPLIT
) {
18701 fprintf(state
->errout
, "lr2 post\n");
18703 if (lr2
->defs
->orig_id
& TRIPLE_FLAG_PRE_SPLIT
) {
18704 fprintf(state
->errout
, "lr2 pre\n");
18708 fprintf(state
->errout
, "coalesce color1(%p): %3d color2(%p) %3d\n",
18715 /* Append lr2 onto lr1 */
18716 #if DEBUG_ROMCC_WARNINGS
18717 #warning "FIXME should this be a merge instead of a splice?"
18719 /* This FIXME item applies to the correctness of live_range_end
18720 * and to the necessity of making multiple passes of coalesce_live_ranges.
18721 * A failure to find some coalesce opportunities in coaleace_live_ranges
18722 * does not impact the correct of the compiler just the efficiency with
18723 * which registers are allocated.
18726 mid1
= lr1
->defs
->prev
;
18728 end
= lr2
->defs
->prev
;
18736 /* Fixup the live range in the added live range defs */
18741 } while(lrd
!= head
);
18743 /* Mark lr2 as free. */
18745 lr2
->color
= REG_UNNEEDED
;
18749 internal_error(state
, 0, "lr1->defs == 0 ?");
18752 lr1
->color
= color
;
18753 lr1
->classes
= classes
;
18755 /* Keep the graph in sync by transfering the edges from lr2 to lr1 */
18756 transfer_live_edges(rstate
, lr1
, lr2
);
18761 static struct live_range_def
*live_range_head(
18762 struct compile_state
*state
, struct live_range
*lr
,
18763 struct live_range_def
*last
)
18765 struct live_range_def
*result
;
18770 else if (!tdominates(state
, lr
->defs
->def
, last
->next
->def
)) {
18771 result
= last
->next
;
18776 static struct live_range_def
*live_range_end(
18777 struct compile_state
*state
, struct live_range
*lr
,
18778 struct live_range_def
*last
)
18780 struct live_range_def
*result
;
18783 result
= lr
->defs
->prev
;
18785 else if (!tdominates(state
, last
->prev
->def
, lr
->defs
->prev
->def
)) {
18786 result
= last
->prev
;
18792 static void initialize_live_ranges(
18793 struct compile_state
*state
, struct reg_state
*rstate
)
18795 struct triple
*ins
, *first
;
18796 size_t count
, size
;
18799 first
= state
->first
;
18800 /* First count how many instructions I have.
18802 count
= count_triples(state
);
18803 /* Potentially I need one live range definitions for each
18806 rstate
->defs
= count
;
18807 /* Potentially I need one live range for each instruction
18808 * plus an extra for the dummy live range.
18810 rstate
->ranges
= count
+ 1;
18811 size
= sizeof(rstate
->lrd
[0]) * rstate
->defs
;
18812 rstate
->lrd
= xcmalloc(size
, "live_range_def");
18813 size
= sizeof(rstate
->lr
[0]) * rstate
->ranges
;
18814 rstate
->lr
= xcmalloc(size
, "live_range");
18816 /* Setup the dummy live range */
18817 rstate
->lr
[0].classes
= 0;
18818 rstate
->lr
[0].color
= REG_UNSET
;
18819 rstate
->lr
[0].defs
= 0;
18823 /* If the triple is a variable give it a live range */
18824 if (triple_is_def(state
, ins
)) {
18825 struct reg_info info
;
18826 /* Find the architecture specific color information */
18827 info
= find_def_color(state
, ins
);
18829 rstate
->lr
[i
].defs
= &rstate
->lrd
[j
];
18830 rstate
->lr
[i
].color
= info
.reg
;
18831 rstate
->lr
[i
].classes
= info
.regcm
;
18832 rstate
->lr
[i
].degree
= 0;
18833 rstate
->lrd
[j
].lr
= &rstate
->lr
[i
];
18835 /* Otherwise give the triple the dummy live range. */
18837 rstate
->lrd
[j
].lr
= &rstate
->lr
[0];
18840 /* Initalize the live_range_def */
18841 rstate
->lrd
[j
].next
= &rstate
->lrd
[j
];
18842 rstate
->lrd
[j
].prev
= &rstate
->lrd
[j
];
18843 rstate
->lrd
[j
].def
= ins
;
18844 rstate
->lrd
[j
].orig_id
= ins
->id
;
18849 } while(ins
!= first
);
18850 rstate
->ranges
= i
;
18852 /* Make a second pass to handle achitecture specific register
18857 int zlhs
, zrhs
, i
, j
;
18858 if (ins
->id
> rstate
->defs
) {
18859 internal_error(state
, ins
, "bad id");
18862 /* Walk through the template of ins and coalesce live ranges */
18864 if ((zlhs
== 0) && triple_is_def(state
, ins
)) {
18869 if (state
->compiler
->debug
& DEBUG_COALESCING2
) {
18870 fprintf(state
->errout
, "mandatory coalesce: %p %d %d\n",
18874 for(i
= 0; i
< zlhs
; i
++) {
18875 struct reg_info linfo
;
18876 struct live_range_def
*lhs
;
18877 linfo
= arch_reg_lhs(state
, ins
, i
);
18878 if (linfo
.reg
< MAX_REGISTERS
) {
18881 if (triple_is_def(state
, ins
)) {
18882 lhs
= &rstate
->lrd
[ins
->id
];
18884 lhs
= &rstate
->lrd
[LHS(ins
, i
)->id
];
18887 if (state
->compiler
->debug
& DEBUG_COALESCING2
) {
18888 fprintf(state
->errout
, "coalesce lhs(%d): %p %d\n",
18889 i
, lhs
, linfo
.reg
);
18892 for(j
= 0; j
< zrhs
; j
++) {
18893 struct reg_info rinfo
;
18894 struct live_range_def
*rhs
;
18895 rinfo
= arch_reg_rhs(state
, ins
, j
);
18896 if (rinfo
.reg
< MAX_REGISTERS
) {
18899 rhs
= &rstate
->lrd
[RHS(ins
, j
)->id
];
18901 if (state
->compiler
->debug
& DEBUG_COALESCING2
) {
18902 fprintf(state
->errout
, "coalesce rhs(%d): %p %d\n",
18903 j
, rhs
, rinfo
.reg
);
18906 if (rinfo
.reg
== linfo
.reg
) {
18907 coalesce_ranges(state
, rstate
,
18913 } while(ins
!= first
);
18916 static void graph_ins(
18917 struct compile_state
*state
,
18918 struct reg_block
*blocks
, struct triple_reg_set
*live
,
18919 struct reg_block
*rb
, struct triple
*ins
, void *arg
)
18921 struct reg_state
*rstate
= arg
;
18922 struct live_range
*def
;
18923 struct triple_reg_set
*entry
;
18925 /* If the triple is not a definition
18926 * we do not have a definition to add to
18927 * the interference graph.
18929 if (!triple_is_def(state
, ins
)) {
18932 def
= rstate
->lrd
[ins
->id
].lr
;
18934 /* Create an edge between ins and everything that is
18935 * alive, unless the live_range cannot share
18936 * a physical register with ins.
18938 for(entry
= live
; entry
; entry
= entry
->next
) {
18939 struct live_range
*lr
;
18940 if (entry
->member
->id
> rstate
->defs
) {
18941 internal_error(state
, 0, "bad entry?");
18943 lr
= rstate
->lrd
[entry
->member
->id
].lr
;
18947 if (!arch_regcm_intersect(def
->classes
, lr
->classes
)) {
18950 add_live_edge(rstate
, def
, lr
);
18955 #if DEBUG_CONSISTENCY > 1
18956 static struct live_range
*get_verify_live_range(
18957 struct compile_state
*state
, struct reg_state
*rstate
, struct triple
*ins
)
18959 struct live_range
*lr
;
18960 struct live_range_def
*lrd
;
18962 if ((ins
->id
< 0) || (ins
->id
> rstate
->defs
)) {
18963 internal_error(state
, ins
, "bad ins?");
18965 lr
= rstate
->lrd
[ins
->id
].lr
;
18969 if (lrd
->def
== ins
) {
18973 } while(lrd
!= lr
->defs
);
18975 internal_error(state
, ins
, "ins not in live range");
18980 static void verify_graph_ins(
18981 struct compile_state
*state
,
18982 struct reg_block
*blocks
, struct triple_reg_set
*live
,
18983 struct reg_block
*rb
, struct triple
*ins
, void *arg
)
18985 struct reg_state
*rstate
= arg
;
18986 struct triple_reg_set
*entry1
, *entry2
;
18989 /* Compare live against edges and make certain the code is working */
18990 for(entry1
= live
; entry1
; entry1
= entry1
->next
) {
18991 struct live_range
*lr1
;
18992 lr1
= get_verify_live_range(state
, rstate
, entry1
->member
);
18993 for(entry2
= live
; entry2
; entry2
= entry2
->next
) {
18994 struct live_range
*lr2
;
18995 struct live_range_edge
*edge2
;
18998 if (entry2
== entry1
) {
19001 lr2
= get_verify_live_range(state
, rstate
, entry2
->member
);
19003 internal_error(state
, entry2
->member
,
19004 "live range with 2 values simultaneously alive");
19006 if (!arch_regcm_intersect(lr1
->classes
, lr2
->classes
)) {
19009 if (!interfere(rstate
, lr1
, lr2
)) {
19010 internal_error(state
, entry2
->member
,
19011 "edges don't interfere?");
19016 for(edge2
= lr2
->edges
; edge2
; edge2
= edge2
->next
) {
19018 if (edge2
->node
== lr1
) {
19022 if (lr2_degree
!= lr2
->degree
) {
19023 internal_error(state
, entry2
->member
,
19024 "computed degree: %d does not match reported degree: %d\n",
19025 lr2_degree
, lr2
->degree
);
19028 internal_error(state
, entry2
->member
, "missing edge");
19036 static void print_interference_ins(
19037 struct compile_state
*state
,
19038 struct reg_block
*blocks
, struct triple_reg_set
*live
,
19039 struct reg_block
*rb
, struct triple
*ins
, void *arg
)
19041 struct reg_state
*rstate
= arg
;
19042 struct live_range
*lr
;
19044 FILE *fp
= state
->dbgout
;
19046 lr
= rstate
->lrd
[ins
->id
].lr
;
19048 ins
->id
= rstate
->lrd
[id
].orig_id
;
19049 SET_REG(ins
->id
, lr
->color
);
19050 display_triple(state
->dbgout
, ins
);
19054 struct live_range_def
*lrd
;
19055 fprintf(fp
, " range:");
19058 fprintf(fp
, " %-10p", lrd
->def
);
19060 } while(lrd
!= lr
->defs
);
19064 struct triple_reg_set
*entry
;
19065 fprintf(fp
, " live:");
19066 for(entry
= live
; entry
; entry
= entry
->next
) {
19067 fprintf(fp
, " %-10p", entry
->member
);
19072 struct live_range_edge
*entry
;
19073 fprintf(fp
, " edges:");
19074 for(entry
= lr
->edges
; entry
; entry
= entry
->next
) {
19075 struct live_range_def
*lrd
;
19076 lrd
= entry
->node
->defs
;
19078 fprintf(fp
, " %-10p", lrd
->def
);
19080 } while(lrd
!= entry
->node
->defs
);
19085 if (triple_is_branch(state
, ins
)) {
19091 static int coalesce_live_ranges(
19092 struct compile_state
*state
, struct reg_state
*rstate
)
19094 /* At the point where a value is moved from one
19095 * register to another that value requires two
19096 * registers, thus increasing register pressure.
19097 * Live range coaleescing reduces the register
19098 * pressure by keeping a value in one register
19101 * In the case of a phi function all paths leading
19102 * into it must be allocated to the same register
19103 * otherwise the phi function may not be removed.
19105 * Forcing a value to stay in a single register
19106 * for an extended period of time does have
19107 * limitations when applied to non homogenous
19110 * The two cases I have identified are:
19111 * 1) Two forced register assignments may
19113 * 2) Registers may go unused because they
19114 * are only good for storing the value
19115 * and not manipulating it.
19117 * Because of this I need to split live ranges,
19118 * even outside of the context of coalesced live
19119 * ranges. The need to split live ranges does
19120 * impose some constraints on live range coalescing.
19122 * - Live ranges may not be coalesced across phi
19123 * functions. This creates a 2 headed live
19124 * range that cannot be sanely split.
19126 * - phi functions (coalesced in initialize_live_ranges)
19127 * are handled as pre split live ranges so we will
19128 * never attempt to split them.
19134 for(i
= 0; i
<= rstate
->ranges
; i
++) {
19135 struct live_range
*lr1
;
19136 struct live_range_def
*lrd1
;
19137 lr1
= &rstate
->lr
[i
];
19141 lrd1
= live_range_end(state
, lr1
, 0);
19142 for(; lrd1
; lrd1
= live_range_end(state
, lr1
, lrd1
)) {
19143 struct triple_set
*set
;
19144 if (lrd1
->def
->op
!= OP_COPY
) {
19147 /* Skip copies that are the result of a live range split. */
19148 if (lrd1
->orig_id
& TRIPLE_FLAG_POST_SPLIT
) {
19151 for(set
= lrd1
->def
->use
; set
; set
= set
->next
) {
19152 struct live_range_def
*lrd2
;
19153 struct live_range
*lr2
, *res
;
19155 lrd2
= &rstate
->lrd
[set
->member
->id
];
19157 /* Don't coalesce with instructions
19158 * that are the result of a live range
19161 if (lrd2
->orig_id
& TRIPLE_FLAG_PRE_SPLIT
) {
19164 lr2
= rstate
->lrd
[set
->member
->id
].lr
;
19168 if ((lr1
->color
!= lr2
->color
) &&
19169 (lr1
->color
!= REG_UNSET
) &&
19170 (lr2
->color
!= REG_UNSET
)) {
19173 if ((lr1
->classes
& lr2
->classes
) == 0) {
19177 if (interfere(rstate
, lr1
, lr2
)) {
19181 res
= coalesce_ranges(state
, rstate
, lr1
, lr2
);
19195 static void fix_coalesce_conflicts(struct compile_state
*state
,
19196 struct reg_block
*blocks
, struct triple_reg_set
*live
,
19197 struct reg_block
*rb
, struct triple
*ins
, void *arg
)
19199 int *conflicts
= arg
;
19200 int zlhs
, zrhs
, i
, j
;
19202 /* See if we have a mandatory coalesce operation between
19203 * a lhs and a rhs value. If so and the rhs value is also
19204 * alive then this triple needs to be pre copied. Otherwise
19205 * we would have two definitions in the same live range simultaneously
19209 if ((zlhs
== 0) && triple_is_def(state
, ins
)) {
19213 for(i
= 0; i
< zlhs
; i
++) {
19214 struct reg_info linfo
;
19215 linfo
= arch_reg_lhs(state
, ins
, i
);
19216 if (linfo
.reg
< MAX_REGISTERS
) {
19219 for(j
= 0; j
< zrhs
; j
++) {
19220 struct reg_info rinfo
;
19221 struct triple
*rhs
;
19222 struct triple_reg_set
*set
;
19225 rinfo
= arch_reg_rhs(state
, ins
, j
);
19226 if (rinfo
.reg
!= linfo
.reg
) {
19230 for(set
= live
; set
&& !found
; set
= set
->next
) {
19231 if (set
->member
== rhs
) {
19236 struct triple
*copy
;
19237 copy
= pre_copy(state
, ins
, j
);
19238 copy
->id
|= TRIPLE_FLAG_PRE_SPLIT
;
19246 static int correct_coalesce_conflicts(
19247 struct compile_state
*state
, struct reg_block
*blocks
)
19251 walk_variable_lifetimes(state
, &state
->bb
, blocks
,
19252 fix_coalesce_conflicts
, &conflicts
);
19256 static void replace_set_use(struct compile_state
*state
,
19257 struct triple_reg_set
*head
, struct triple
*orig
, struct triple
*new)
19259 struct triple_reg_set
*set
;
19260 for(set
= head
; set
; set
= set
->next
) {
19261 if (set
->member
== orig
) {
19267 static void replace_block_use(struct compile_state
*state
,
19268 struct reg_block
*blocks
, struct triple
*orig
, struct triple
*new)
19271 #if DEBUG_ROMCC_WARNINGS
19272 #warning "WISHLIST visit just those blocks that need it *"
19274 for(i
= 1; i
<= state
->bb
.last_vertex
; i
++) {
19275 struct reg_block
*rb
;
19277 replace_set_use(state
, rb
->in
, orig
, new);
19278 replace_set_use(state
, rb
->out
, orig
, new);
19282 static void color_instructions(struct compile_state
*state
)
19284 struct triple
*ins
, *first
;
19285 first
= state
->first
;
19288 if (triple_is_def(state
, ins
)) {
19289 struct reg_info info
;
19290 info
= find_lhs_color(state
, ins
, 0);
19291 if (info
.reg
>= MAX_REGISTERS
) {
19292 info
.reg
= REG_UNSET
;
19294 SET_INFO(ins
->id
, info
);
19297 } while(ins
!= first
);
19300 static struct reg_info
read_lhs_color(
19301 struct compile_state
*state
, struct triple
*ins
, int index
)
19303 struct reg_info info
;
19304 if ((index
== 0) && triple_is_def(state
, ins
)) {
19305 info
.reg
= ID_REG(ins
->id
);
19306 info
.regcm
= ID_REGCM(ins
->id
);
19308 else if (index
< ins
->lhs
) {
19309 info
= read_lhs_color(state
, LHS(ins
, index
), 0);
19312 internal_error(state
, ins
, "Bad lhs %d", index
);
19313 info
.reg
= REG_UNSET
;
19319 static struct triple
*resolve_tangle(
19320 struct compile_state
*state
, struct triple
*tangle
)
19322 struct reg_info info
, uinfo
;
19323 struct triple_set
*set
, *next
;
19324 struct triple
*copy
;
19326 #if DEBUG_ROMCC_WARNINGS
19327 #warning "WISHLIST recalculate all affected instructions colors"
19329 info
= find_lhs_color(state
, tangle
, 0);
19330 for(set
= tangle
->use
; set
; set
= next
) {
19331 struct triple
*user
;
19334 user
= set
->member
;
19336 for(i
= 0; i
< zrhs
; i
++) {
19337 if (RHS(user
, i
) != tangle
) {
19340 uinfo
= find_rhs_post_color(state
, user
, i
);
19341 if (uinfo
.reg
== info
.reg
) {
19342 copy
= pre_copy(state
, user
, i
);
19343 copy
->id
|= TRIPLE_FLAG_PRE_SPLIT
;
19344 SET_INFO(copy
->id
, uinfo
);
19349 uinfo
= find_lhs_pre_color(state
, tangle
, 0);
19350 if (uinfo
.reg
== info
.reg
) {
19351 struct reg_info linfo
;
19352 copy
= post_copy(state
, tangle
);
19353 copy
->id
|= TRIPLE_FLAG_PRE_SPLIT
;
19354 linfo
= find_lhs_color(state
, copy
, 0);
19355 SET_INFO(copy
->id
, linfo
);
19357 info
= find_lhs_color(state
, tangle
, 0);
19358 SET_INFO(tangle
->id
, info
);
19364 static void fix_tangles(struct compile_state
*state
,
19365 struct reg_block
*blocks
, struct triple_reg_set
*live
,
19366 struct reg_block
*rb
, struct triple
*ins
, void *arg
)
19368 int *tangles
= arg
;
19369 struct triple
*tangle
;
19371 char used
[MAX_REGISTERS
];
19372 struct triple_reg_set
*set
;
19375 /* Find out which registers have multiple uses at this point */
19376 memset(used
, 0, sizeof(used
));
19377 for(set
= live
; set
; set
= set
->next
) {
19378 struct reg_info info
;
19379 info
= read_lhs_color(state
, set
->member
, 0);
19380 if (info
.reg
== REG_UNSET
) {
19383 reg_inc_used(state
, used
, info
.reg
);
19386 /* Now find the least dominated definition of a register in
19387 * conflict I have seen so far.
19389 for(set
= live
; set
; set
= set
->next
) {
19390 struct reg_info info
;
19391 info
= read_lhs_color(state
, set
->member
, 0);
19392 if (used
[info
.reg
] < 2) {
19395 /* Changing copies that feed into phi functions
19398 if (set
->member
->use
&&
19399 (set
->member
->use
->member
->op
== OP_PHI
)) {
19402 if (!tangle
|| tdominates(state
, set
->member
, tangle
)) {
19403 tangle
= set
->member
;
19406 /* If I have found a tangle resolve it */
19408 struct triple
*post_copy
;
19410 post_copy
= resolve_tangle(state
, tangle
);
19412 replace_block_use(state
, blocks
, tangle
, post_copy
);
19414 if (post_copy
&& (tangle
!= ins
)) {
19415 replace_set_use(state
, live
, tangle
, post_copy
);
19422 static int correct_tangles(
19423 struct compile_state
*state
, struct reg_block
*blocks
)
19427 color_instructions(state
);
19428 walk_variable_lifetimes(state
, &state
->bb
, blocks
,
19429 fix_tangles
, &tangles
);
19434 static void ids_from_rstate(struct compile_state
*state
, struct reg_state
*rstate
);
19435 static void cleanup_rstate(struct compile_state
*state
, struct reg_state
*rstate
);
19437 struct triple
*find_constrained_def(
19438 struct compile_state
*state
, struct live_range
*range
, struct triple
*constrained
)
19440 struct live_range_def
*lrd
, *lrd_next
;
19441 lrd_next
= range
->defs
;
19443 struct reg_info info
;
19447 lrd_next
= lrd
->next
;
19449 regcm
= arch_type_to_regcm(state
, lrd
->def
->type
);
19450 info
= find_lhs_color(state
, lrd
->def
, 0);
19451 regcm
= arch_regcm_reg_normalize(state
, regcm
);
19452 info
.regcm
= arch_regcm_reg_normalize(state
, info
.regcm
);
19453 /* If the 2 register class masks are equal then
19454 * the current register class is not constrained.
19456 if (regcm
== info
.regcm
) {
19460 /* If there is just one use.
19461 * That use cannot accept a larger register class.
19462 * There are no intervening definitions except
19463 * definitions that feed into that use.
19464 * Then a triple is not constrained.
19465 * FIXME handle this case!
19467 #if DEBUG_ROMCC_WARNINGS
19468 #warning "FIXME ignore cases that cannot be fixed (a definition followed by a use)"
19472 /* Of the constrained live ranges deal with the
19473 * least dominated one first.
19475 if (state
->compiler
->debug
& DEBUG_RANGE_CONFLICTS
) {
19476 fprintf(state
->errout
, "canidate: %p %-8s regcm: %x %x\n",
19477 lrd
->def
, tops(lrd
->def
->op
), regcm
, info
.regcm
);
19479 if (!constrained
||
19480 tdominates(state
, lrd
->def
, constrained
))
19482 constrained
= lrd
->def
;
19484 } while(lrd_next
!= range
->defs
);
19485 return constrained
;
19488 static int split_constrained_ranges(
19489 struct compile_state
*state
, struct reg_state
*rstate
,
19490 struct live_range
*range
)
19492 /* Walk through the edges in conflict and our current live
19493 * range, and find definitions that are more severly constrained
19494 * than they type of data they contain require.
19496 * Then pick one of those ranges and relax the constraints.
19498 struct live_range_edge
*edge
;
19499 struct triple
*constrained
;
19502 for(edge
= range
->edges
; edge
; edge
= edge
->next
) {
19503 constrained
= find_constrained_def(state
, edge
->node
, constrained
);
19505 #if DEBUG_ROMCC_WARNINGS
19506 #warning "FIXME should I call find_constrained_def here only if no previous constrained def was found?"
19508 if (!constrained
) {
19509 constrained
= find_constrained_def(state
, range
, constrained
);
19512 if (state
->compiler
->debug
& DEBUG_RANGE_CONFLICTS
) {
19513 fprintf(state
->errout
, "constrained: ");
19514 display_triple(state
->errout
, constrained
);
19517 ids_from_rstate(state
, rstate
);
19518 cleanup_rstate(state
, rstate
);
19519 resolve_tangle(state
, constrained
);
19521 return !!constrained
;
19524 static int split_ranges(
19525 struct compile_state
*state
, struct reg_state
*rstate
,
19526 char *used
, struct live_range
*range
)
19529 if (state
->compiler
->debug
& DEBUG_RANGE_CONFLICTS
) {
19530 fprintf(state
->errout
, "split_ranges %d %s %p\n",
19531 rstate
->passes
, tops(range
->defs
->def
->op
), range
->defs
->def
);
19533 if ((range
->color
== REG_UNNEEDED
) ||
19534 (rstate
->passes
>= rstate
->max_passes
)) {
19537 split
= split_constrained_ranges(state
, rstate
, range
);
19539 /* Ideally I would split the live range that will not be used
19540 * for the longest period of time in hopes that this will
19541 * (a) allow me to spill a register or
19542 * (b) allow me to place a value in another register.
19544 * So far I don't have a test case for this, the resolving
19545 * of mandatory constraints has solved all of my
19546 * know issues. So I have choosen not to write any
19547 * code until I cat get a better feel for cases where
19548 * it would be useful to have.
19551 #if DEBUG_ROMCC_WARNINGS
19552 #warning "WISHLIST implement live range splitting..."
19555 if (!split
&& (state
->compiler
->debug
& DEBUG_RANGE_CONFLICTS2
)) {
19556 FILE *fp
= state
->errout
;
19557 print_interference_blocks(state
, rstate
, fp
, 0);
19558 print_dominators(state
, fp
, &state
->bb
);
19563 static FILE *cgdebug_fp(struct compile_state
*state
)
19567 if (!fp
&& (state
->compiler
->debug
& DEBUG_COLOR_GRAPH2
)) {
19568 fp
= state
->errout
;
19570 if (!fp
&& (state
->compiler
->debug
& DEBUG_COLOR_GRAPH
)) {
19571 fp
= state
->dbgout
;
19576 static void cgdebug_printf(struct compile_state
*state
, const char *fmt
, ...)
19579 fp
= cgdebug_fp(state
);
19582 va_start(args
, fmt
);
19583 vfprintf(fp
, fmt
, args
);
19588 static void cgdebug_flush(struct compile_state
*state
)
19591 fp
= cgdebug_fp(state
);
19597 static void cgdebug_loc(struct compile_state
*state
, struct triple
*ins
)
19600 fp
= cgdebug_fp(state
);
19602 loc(fp
, state
, ins
);
19606 static int select_free_color(struct compile_state
*state
,
19607 struct reg_state
*rstate
, struct live_range
*range
)
19609 struct triple_set
*entry
;
19610 struct live_range_def
*lrd
;
19611 struct live_range_def
*phi
;
19612 struct live_range_edge
*edge
;
19613 char used
[MAX_REGISTERS
];
19614 struct triple
**expr
;
19616 /* Instead of doing just the trivial color select here I try
19617 * a few extra things because a good color selection will help reduce
19621 /* Find the registers currently in use */
19622 memset(used
, 0, sizeof(used
));
19623 for(edge
= range
->edges
; edge
; edge
= edge
->next
) {
19624 if (edge
->node
->color
== REG_UNSET
) {
19627 reg_fill_used(state
, used
, edge
->node
->color
);
19630 if (state
->compiler
->debug
& DEBUG_COLOR_GRAPH2
) {
19633 for(edge
= range
->edges
; edge
; edge
= edge
->next
) {
19636 cgdebug_printf(state
, "\n%s edges: %d",
19637 tops(range
->defs
->def
->op
), i
);
19638 cgdebug_loc(state
, range
->defs
->def
);
19639 cgdebug_printf(state
, "\n");
19640 for(i
= 0; i
< MAX_REGISTERS
; i
++) {
19642 cgdebug_printf(state
, "used: %s\n",
19648 /* If a color is already assigned see if it will work */
19649 if (range
->color
!= REG_UNSET
) {
19650 struct live_range_def
*lrd
;
19651 if (!used
[range
->color
]) {
19654 for(edge
= range
->edges
; edge
; edge
= edge
->next
) {
19655 if (edge
->node
->color
!= range
->color
) {
19658 warning(state
, edge
->node
->defs
->def
, "edge: ");
19659 lrd
= edge
->node
->defs
;
19661 warning(state
, lrd
->def
, " %p %s",
19662 lrd
->def
, tops(lrd
->def
->op
));
19664 } while(lrd
!= edge
->node
->defs
);
19667 warning(state
, range
->defs
->def
, "def: ");
19669 warning(state
, lrd
->def
, " %p %s",
19670 lrd
->def
, tops(lrd
->def
->op
));
19672 } while(lrd
!= range
->defs
);
19673 internal_error(state
, range
->defs
->def
,
19674 "live range with already used color %s",
19675 arch_reg_str(range
->color
));
19678 /* If I feed into an expression reuse it's color.
19679 * This should help remove copies in the case of 2 register instructions
19680 * and phi functions.
19683 lrd
= live_range_end(state
, range
, 0);
19684 for(; (range
->color
== REG_UNSET
) && lrd
; lrd
= live_range_end(state
, range
, lrd
)) {
19685 entry
= lrd
->def
->use
;
19686 for(;(range
->color
== REG_UNSET
) && entry
; entry
= entry
->next
) {
19687 struct live_range_def
*insd
;
19689 insd
= &rstate
->lrd
[entry
->member
->id
];
19690 if (insd
->lr
->defs
== 0) {
19693 if (!phi
&& (insd
->def
->op
== OP_PHI
) &&
19694 !interfere(rstate
, range
, insd
->lr
)) {
19697 if (insd
->lr
->color
== REG_UNSET
) {
19700 regcm
= insd
->lr
->classes
;
19701 if (((regcm
& range
->classes
) == 0) ||
19702 (used
[insd
->lr
->color
])) {
19705 if (interfere(rstate
, range
, insd
->lr
)) {
19708 range
->color
= insd
->lr
->color
;
19711 /* If I feed into a phi function reuse it's color or the color
19712 * of something else that feeds into the phi function.
19715 if (phi
->lr
->color
!= REG_UNSET
) {
19716 if (used
[phi
->lr
->color
]) {
19717 range
->color
= phi
->lr
->color
;
19721 expr
= triple_rhs(state
, phi
->def
, 0);
19722 for(; expr
; expr
= triple_rhs(state
, phi
->def
, expr
)) {
19723 struct live_range
*lr
;
19728 lr
= rstate
->lrd
[(*expr
)->id
].lr
;
19729 if (lr
->color
== REG_UNSET
) {
19732 regcm
= lr
->classes
;
19733 if (((regcm
& range
->classes
) == 0) ||
19734 (used
[lr
->color
])) {
19737 if (interfere(rstate
, range
, lr
)) {
19740 range
->color
= lr
->color
;
19744 /* If I don't interfere with a rhs node reuse it's color */
19745 lrd
= live_range_head(state
, range
, 0);
19746 for(; (range
->color
== REG_UNSET
) && lrd
; lrd
= live_range_head(state
, range
, lrd
)) {
19747 expr
= triple_rhs(state
, lrd
->def
, 0);
19748 for(; expr
; expr
= triple_rhs(state
, lrd
->def
, expr
)) {
19749 struct live_range
*lr
;
19754 lr
= rstate
->lrd
[(*expr
)->id
].lr
;
19755 if (lr
->color
== REG_UNSET
) {
19758 regcm
= lr
->classes
;
19759 if (((regcm
& range
->classes
) == 0) ||
19760 (used
[lr
->color
])) {
19763 if (interfere(rstate
, range
, lr
)) {
19766 range
->color
= lr
->color
;
19770 /* If I have not opportunitically picked a useful color
19771 * pick the first color that is free.
19773 if (range
->color
== REG_UNSET
) {
19775 arch_select_free_register(state
, used
, range
->classes
);
19777 if (range
->color
== REG_UNSET
) {
19778 struct live_range_def
*lrd
;
19780 if (split_ranges(state
, rstate
, used
, range
)) {
19783 for(edge
= range
->edges
; edge
; edge
= edge
->next
) {
19784 warning(state
, edge
->node
->defs
->def
, "edge reg %s",
19785 arch_reg_str(edge
->node
->color
));
19786 lrd
= edge
->node
->defs
;
19788 warning(state
, lrd
->def
, " %s %p",
19789 tops(lrd
->def
->op
), lrd
->def
);
19791 } while(lrd
!= edge
->node
->defs
);
19793 warning(state
, range
->defs
->def
, "range: ");
19796 warning(state
, lrd
->def
, " %s %p",
19797 tops(lrd
->def
->op
), lrd
->def
);
19799 } while(lrd
!= range
->defs
);
19801 warning(state
, range
->defs
->def
, "classes: %x",
19803 for(i
= 0; i
< MAX_REGISTERS
; i
++) {
19805 warning(state
, range
->defs
->def
, "used: %s",
19809 error(state
, range
->defs
->def
, "too few registers");
19811 range
->classes
&= arch_reg_regcm(state
, range
->color
);
19812 if ((range
->color
== REG_UNSET
) || (range
->classes
== 0)) {
19813 internal_error(state
, range
->defs
->def
, "select_free_color did not?");
19818 static int color_graph(struct compile_state
*state
, struct reg_state
*rstate
)
19821 struct live_range_edge
*edge
;
19822 struct live_range
*range
;
19824 cgdebug_printf(state
, "Lo: ");
19825 range
= rstate
->low
;
19826 if (*range
->group_prev
!= range
) {
19827 internal_error(state
, 0, "lo: *prev != range?");
19829 *range
->group_prev
= range
->group_next
;
19830 if (range
->group_next
) {
19831 range
->group_next
->group_prev
= range
->group_prev
;
19833 if (&range
->group_next
== rstate
->low_tail
) {
19834 rstate
->low_tail
= range
->group_prev
;
19836 if (rstate
->low
== range
) {
19837 internal_error(state
, 0, "low: next != prev?");
19840 else if (rstate
->high
) {
19841 cgdebug_printf(state
, "Hi: ");
19842 range
= rstate
->high
;
19843 if (*range
->group_prev
!= range
) {
19844 internal_error(state
, 0, "hi: *prev != range?");
19846 *range
->group_prev
= range
->group_next
;
19847 if (range
->group_next
) {
19848 range
->group_next
->group_prev
= range
->group_prev
;
19850 if (&range
->group_next
== rstate
->high_tail
) {
19851 rstate
->high_tail
= range
->group_prev
;
19853 if (rstate
->high
== range
) {
19854 internal_error(state
, 0, "high: next != prev?");
19860 cgdebug_printf(state
, " %d\n", range
- rstate
->lr
);
19861 range
->group_prev
= 0;
19862 for(edge
= range
->edges
; edge
; edge
= edge
->next
) {
19863 struct live_range
*node
;
19865 /* Move nodes from the high to the low list */
19866 if (node
->group_prev
&& (node
->color
== REG_UNSET
) &&
19867 (node
->degree
== regc_max_size(state
, node
->classes
))) {
19868 if (*node
->group_prev
!= node
) {
19869 internal_error(state
, 0, "move: *prev != node?");
19871 *node
->group_prev
= node
->group_next
;
19872 if (node
->group_next
) {
19873 node
->group_next
->group_prev
= node
->group_prev
;
19875 if (&node
->group_next
== rstate
->high_tail
) {
19876 rstate
->high_tail
= node
->group_prev
;
19878 cgdebug_printf(state
, "Moving...%d to low\n", node
- rstate
->lr
);
19879 node
->group_prev
= rstate
->low_tail
;
19880 node
->group_next
= 0;
19881 *rstate
->low_tail
= node
;
19882 rstate
->low_tail
= &node
->group_next
;
19883 if (*node
->group_prev
!= node
) {
19884 internal_error(state
, 0, "move2: *prev != node?");
19889 colored
= color_graph(state
, rstate
);
19891 cgdebug_printf(state
, "Coloring %d @", range
- rstate
->lr
);
19892 cgdebug_loc(state
, range
->defs
->def
);
19893 cgdebug_flush(state
);
19894 colored
= select_free_color(state
, rstate
, range
);
19896 cgdebug_printf(state
, " %s\n", arch_reg_str(range
->color
));
19902 static void verify_colors(struct compile_state
*state
, struct reg_state
*rstate
)
19904 struct live_range
*lr
;
19905 struct live_range_edge
*edge
;
19906 struct triple
*ins
, *first
;
19907 char used
[MAX_REGISTERS
];
19908 first
= state
->first
;
19911 if (triple_is_def(state
, ins
)) {
19912 if (ins
->id
> rstate
->defs
) {
19913 internal_error(state
, ins
,
19914 "triple without a live range def");
19916 lr
= rstate
->lrd
[ins
->id
].lr
;
19917 if (lr
->color
== REG_UNSET
) {
19918 internal_error(state
, ins
,
19919 "triple without a color");
19921 /* Find the registers used by the edges */
19922 memset(used
, 0, sizeof(used
));
19923 for(edge
= lr
->edges
; edge
; edge
= edge
->next
) {
19924 if (edge
->node
->color
== REG_UNSET
) {
19925 internal_error(state
, 0,
19926 "live range without a color");
19928 reg_fill_used(state
, used
, edge
->node
->color
);
19930 if (used
[lr
->color
]) {
19931 internal_error(state
, ins
,
19932 "triple with already used color");
19936 } while(ins
!= first
);
19939 static void color_triples(struct compile_state
*state
, struct reg_state
*rstate
)
19941 struct live_range_def
*lrd
;
19942 struct live_range
*lr
;
19943 struct triple
*first
, *ins
;
19944 first
= state
->first
;
19947 if (ins
->id
> rstate
->defs
) {
19948 internal_error(state
, ins
,
19949 "triple without a live range");
19951 lrd
= &rstate
->lrd
[ins
->id
];
19953 ins
->id
= lrd
->orig_id
;
19954 SET_REG(ins
->id
, lr
->color
);
19956 } while (ins
!= first
);
19959 static struct live_range
*merge_sort_lr(
19960 struct live_range
*first
, struct live_range
*last
)
19962 struct live_range
*mid
, *join
, **join_tail
, *pick
;
19964 size
= (last
- first
) + 1;
19966 mid
= first
+ size
/2;
19967 first
= merge_sort_lr(first
, mid
-1);
19968 mid
= merge_sort_lr(mid
, last
);
19972 /* merge the two lists */
19973 while(first
&& mid
) {
19974 if ((first
->degree
< mid
->degree
) ||
19975 ((first
->degree
== mid
->degree
) &&
19976 (first
->length
< mid
->length
))) {
19978 first
= first
->group_next
;
19980 first
->group_prev
= 0;
19985 mid
= mid
->group_next
;
19987 mid
->group_prev
= 0;
19990 pick
->group_next
= 0;
19991 pick
->group_prev
= join_tail
;
19993 join_tail
= &pick
->group_next
;
19995 /* Splice the remaining list */
19996 pick
= (first
)? first
: mid
;
19999 pick
->group_prev
= join_tail
;
20003 if (!first
->defs
) {
20011 static void ids_from_rstate(struct compile_state
*state
,
20012 struct reg_state
*rstate
)
20014 struct triple
*ins
, *first
;
20015 if (!rstate
->defs
) {
20018 /* Display the graph if desired */
20019 if (state
->compiler
->debug
& DEBUG_INTERFERENCE
) {
20020 FILE *fp
= state
->dbgout
;
20021 print_interference_blocks(state
, rstate
, fp
, 0);
20022 print_control_flow(state
, fp
, &state
->bb
);
20025 first
= state
->first
;
20029 struct live_range_def
*lrd
;
20030 lrd
= &rstate
->lrd
[ins
->id
];
20031 ins
->id
= lrd
->orig_id
;
20034 } while(ins
!= first
);
20037 static void cleanup_live_edges(struct reg_state
*rstate
)
20040 /* Free the edges on each node */
20041 for(i
= 1; i
<= rstate
->ranges
; i
++) {
20042 remove_live_edges(rstate
, &rstate
->lr
[i
]);
20046 static void cleanup_rstate(struct compile_state
*state
, struct reg_state
*rstate
)
20048 cleanup_live_edges(rstate
);
20049 xfree(rstate
->lrd
);
20052 /* Free the variable lifetime information */
20053 if (rstate
->blocks
) {
20054 free_variable_lifetimes(state
, &state
->bb
, rstate
->blocks
);
20057 rstate
->ranges
= 0;
20060 rstate
->blocks
= 0;
20063 static void verify_consistency(struct compile_state
*state
);
20064 static void allocate_registers(struct compile_state
*state
)
20066 struct reg_state rstate
;
20069 /* Clear out the reg_state */
20070 memset(&rstate
, 0, sizeof(rstate
));
20071 rstate
.max_passes
= state
->compiler
->max_allocation_passes
;
20074 struct live_range
**point
, **next
;
20078 if (state
->compiler
->debug
& DEBUG_RANGE_CONFLICTS
) {
20079 FILE *fp
= state
->errout
;
20080 fprintf(fp
, "pass: %d\n", rstate
.passes
);
20085 ids_from_rstate(state
, &rstate
);
20087 /* Cleanup the temporary data structures */
20088 cleanup_rstate(state
, &rstate
);
20090 /* Compute the variable lifetimes */
20091 rstate
.blocks
= compute_variable_lifetimes(state
, &state
->bb
);
20093 /* Fix invalid mandatory live range coalesce conflicts */
20094 correct_coalesce_conflicts(state
, rstate
.blocks
);
20096 /* Fix two simultaneous uses of the same register.
20097 * In a few pathlogical cases a partial untangle moves
20098 * the tangle to a part of the graph we won't revisit.
20099 * So we keep looping until we have no more tangle fixes
20103 tangles
= correct_tangles(state
, rstate
.blocks
);
20107 print_blocks(state
, "resolve_tangles", state
->dbgout
);
20108 verify_consistency(state
);
20110 /* Allocate and initialize the live ranges */
20111 initialize_live_ranges(state
, &rstate
);
20113 /* Note currently doing coalescing in a loop appears to
20114 * buys me nothing. The code is left this way in case
20115 * there is some value in it. Or if a future bugfix
20116 * yields some benefit.
20119 if (state
->compiler
->debug
& DEBUG_COALESCING
) {
20120 fprintf(state
->errout
, "coalescing\n");
20123 /* Remove any previous live edge calculations */
20124 cleanup_live_edges(&rstate
);
20126 /* Compute the interference graph */
20127 walk_variable_lifetimes(
20128 state
, &state
->bb
, rstate
.blocks
,
20129 graph_ins
, &rstate
);
20131 /* Display the interference graph if desired */
20132 if (state
->compiler
->debug
& DEBUG_INTERFERENCE
) {
20133 print_interference_blocks(state
, &rstate
, state
->dbgout
, 1);
20134 fprintf(state
->dbgout
, "\nlive variables by instruction\n");
20135 walk_variable_lifetimes(
20136 state
, &state
->bb
, rstate
.blocks
,
20137 print_interference_ins
, &rstate
);
20140 coalesced
= coalesce_live_ranges(state
, &rstate
);
20142 if (state
->compiler
->debug
& DEBUG_COALESCING
) {
20143 fprintf(state
->errout
, "coalesced: %d\n", coalesced
);
20145 } while(coalesced
);
20147 #if DEBUG_CONSISTENCY > 1
20149 fprintf(state
->errout
, "verify_graph_ins...\n");
20151 /* Verify the interference graph */
20152 walk_variable_lifetimes(
20153 state
, &state
->bb
, rstate
.blocks
,
20154 verify_graph_ins
, &rstate
);
20156 fprintf(state
->errout
, "verify_graph_ins done\n");
20160 /* Build the groups low and high. But with the nodes
20161 * first sorted by degree order.
20163 rstate
.low_tail
= &rstate
.low
;
20164 rstate
.high_tail
= &rstate
.high
;
20165 rstate
.high
= merge_sort_lr(&rstate
.lr
[1], &rstate
.lr
[rstate
.ranges
]);
20167 rstate
.high
->group_prev
= &rstate
.high
;
20169 for(point
= &rstate
.high
; *point
; point
= &(*point
)->group_next
)
20171 rstate
.high_tail
= point
;
20172 /* Walk through the high list and move everything that needs
20175 for(point
= &rstate
.high
; *point
; point
= next
) {
20176 struct live_range
*range
;
20177 next
= &(*point
)->group_next
;
20180 /* If it has a low degree or it already has a color
20181 * place the node in low.
20183 if ((range
->degree
< regc_max_size(state
, range
->classes
)) ||
20184 (range
->color
!= REG_UNSET
)) {
20185 cgdebug_printf(state
, "Lo: %5d degree %5d%s\n",
20186 range
- rstate
.lr
, range
->degree
,
20187 (range
->color
!= REG_UNSET
) ? " (colored)": "");
20188 *range
->group_prev
= range
->group_next
;
20189 if (range
->group_next
) {
20190 range
->group_next
->group_prev
= range
->group_prev
;
20192 if (&range
->group_next
== rstate
.high_tail
) {
20193 rstate
.high_tail
= range
->group_prev
;
20195 range
->group_prev
= rstate
.low_tail
;
20196 range
->group_next
= 0;
20197 *rstate
.low_tail
= range
;
20198 rstate
.low_tail
= &range
->group_next
;
20202 cgdebug_printf(state
, "hi: %5d degree %5d%s\n",
20203 range
- rstate
.lr
, range
->degree
,
20204 (range
->color
!= REG_UNSET
) ? " (colored)": "");
20207 /* Color the live_ranges */
20208 colored
= color_graph(state
, &rstate
);
20210 } while (!colored
);
20212 /* Verify the graph was properly colored */
20213 verify_colors(state
, &rstate
);
20215 /* Move the colors from the graph to the triples */
20216 color_triples(state
, &rstate
);
20218 /* Cleanup the temporary data structures */
20219 cleanup_rstate(state
, &rstate
);
20221 /* Display the new graph */
20222 print_blocks(state
, __func__
, state
->dbgout
);
20225 /* Sparce Conditional Constant Propogation
20226 * =========================================
20230 struct lattice_node
{
20232 struct triple
*def
;
20233 struct ssa_edge
*out
;
20234 struct flow_block
*fblock
;
20235 struct triple
*val
;
20236 /* lattice high val == def
20237 * lattice const is_const(val)
20238 * lattice low other
20242 struct lattice_node
*src
;
20243 struct lattice_node
*dst
;
20244 struct ssa_edge
*work_next
;
20245 struct ssa_edge
*work_prev
;
20246 struct ssa_edge
*out_next
;
20249 struct flow_block
*src
;
20250 struct flow_block
*dst
;
20251 struct flow_edge
*work_next
;
20252 struct flow_edge
*work_prev
;
20253 struct flow_edge
*in_next
;
20254 struct flow_edge
*out_next
;
20257 #define MAX_FLOW_BLOCK_EDGES 3
20258 struct flow_block
{
20259 struct block
*block
;
20260 struct flow_edge
*in
;
20261 struct flow_edge
*out
;
20262 struct flow_edge
*edges
;
20267 struct lattice_node
*lattice
;
20268 struct ssa_edge
*ssa_edges
;
20269 struct flow_block
*flow_blocks
;
20270 struct flow_edge
*flow_work_list
;
20271 struct ssa_edge
*ssa_work_list
;
20275 static int is_scc_const(struct compile_state
*state
, struct triple
*ins
)
20277 return ins
&& (triple_is_ubranch(state
, ins
) || is_const(ins
));
20280 static int is_lattice_hi(struct compile_state
*state
, struct lattice_node
*lnode
)
20282 return !is_scc_const(state
, lnode
->val
) && (lnode
->val
== lnode
->def
);
20285 static int is_lattice_const(struct compile_state
*state
, struct lattice_node
*lnode
)
20287 return is_scc_const(state
, lnode
->val
);
20290 static int is_lattice_lo(struct compile_state
*state
, struct lattice_node
*lnode
)
20292 return (lnode
->val
!= lnode
->def
) && !is_scc_const(state
, lnode
->val
);
20295 static void scc_add_fedge(struct compile_state
*state
, struct scc_state
*scc
,
20296 struct flow_edge
*fedge
)
20298 if (state
->compiler
->debug
& DEBUG_SCC_TRANSFORM2
) {
20299 fprintf(state
->errout
, "adding fedge: %p (%4d -> %5d)\n",
20301 fedge
->src
->block
?fedge
->src
->block
->last
->id
: 0,
20302 fedge
->dst
->block
?fedge
->dst
->block
->first
->id
: 0);
20304 if ((fedge
== scc
->flow_work_list
) ||
20305 (fedge
->work_next
!= fedge
) ||
20306 (fedge
->work_prev
!= fedge
)) {
20308 if (state
->compiler
->debug
& DEBUG_SCC_TRANSFORM2
) {
20309 fprintf(state
->errout
, "dupped fedge: %p\n",
20314 if (!scc
->flow_work_list
) {
20315 scc
->flow_work_list
= fedge
;
20316 fedge
->work_next
= fedge
->work_prev
= fedge
;
20319 struct flow_edge
*ftail
;
20320 ftail
= scc
->flow_work_list
->work_prev
;
20321 fedge
->work_next
= ftail
->work_next
;
20322 fedge
->work_prev
= ftail
;
20323 fedge
->work_next
->work_prev
= fedge
;
20324 fedge
->work_prev
->work_next
= fedge
;
20328 static struct flow_edge
*scc_next_fedge(
20329 struct compile_state
*state
, struct scc_state
*scc
)
20331 struct flow_edge
*fedge
;
20332 fedge
= scc
->flow_work_list
;
20334 fedge
->work_next
->work_prev
= fedge
->work_prev
;
20335 fedge
->work_prev
->work_next
= fedge
->work_next
;
20336 if (fedge
->work_next
!= fedge
) {
20337 scc
->flow_work_list
= fedge
->work_next
;
20339 scc
->flow_work_list
= 0;
20341 fedge
->work_next
= fedge
->work_prev
= fedge
;
20346 static void scc_add_sedge(struct compile_state
*state
, struct scc_state
*scc
,
20347 struct ssa_edge
*sedge
)
20349 if (state
->compiler
->debug
& DEBUG_SCC_TRANSFORM2
) {
20350 fprintf(state
->errout
, "adding sedge: %5ld (%4d -> %5d)\n",
20351 (long)(sedge
- scc
->ssa_edges
),
20352 sedge
->src
->def
->id
,
20353 sedge
->dst
->def
->id
);
20355 if ((sedge
== scc
->ssa_work_list
) ||
20356 (sedge
->work_next
!= sedge
) ||
20357 (sedge
->work_prev
!= sedge
)) {
20359 if (state
->compiler
->debug
& DEBUG_SCC_TRANSFORM2
) {
20360 fprintf(state
->errout
, "dupped sedge: %5ld\n",
20361 (long)(sedge
- scc
->ssa_edges
));
20365 if (!scc
->ssa_work_list
) {
20366 scc
->ssa_work_list
= sedge
;
20367 sedge
->work_next
= sedge
->work_prev
= sedge
;
20370 struct ssa_edge
*stail
;
20371 stail
= scc
->ssa_work_list
->work_prev
;
20372 sedge
->work_next
= stail
->work_next
;
20373 sedge
->work_prev
= stail
;
20374 sedge
->work_next
->work_prev
= sedge
;
20375 sedge
->work_prev
->work_next
= sedge
;
20379 static struct ssa_edge
*scc_next_sedge(
20380 struct compile_state
*state
, struct scc_state
*scc
)
20382 struct ssa_edge
*sedge
;
20383 sedge
= scc
->ssa_work_list
;
20385 sedge
->work_next
->work_prev
= sedge
->work_prev
;
20386 sedge
->work_prev
->work_next
= sedge
->work_next
;
20387 if (sedge
->work_next
!= sedge
) {
20388 scc
->ssa_work_list
= sedge
->work_next
;
20390 scc
->ssa_work_list
= 0;
20392 sedge
->work_next
= sedge
->work_prev
= sedge
;
20397 static void initialize_scc_state(
20398 struct compile_state
*state
, struct scc_state
*scc
)
20400 int ins_count
, ssa_edge_count
;
20401 int ins_index
, ssa_edge_index
, fblock_index
;
20402 struct triple
*first
, *ins
;
20403 struct block
*block
;
20404 struct flow_block
*fblock
;
20406 memset(scc
, 0, sizeof(*scc
));
20408 /* Inialize pass zero find out how much memory we need */
20409 first
= state
->first
;
20411 ins_count
= ssa_edge_count
= 0;
20413 struct triple_set
*edge
;
20415 for(edge
= ins
->use
; edge
; edge
= edge
->next
) {
20419 } while(ins
!= first
);
20420 if (state
->compiler
->debug
& DEBUG_SCC_TRANSFORM
) {
20421 fprintf(state
->errout
, "ins_count: %d ssa_edge_count: %d vertex_count: %d\n",
20422 ins_count
, ssa_edge_count
, state
->bb
.last_vertex
);
20424 scc
->ins_count
= ins_count
;
20426 xcmalloc(sizeof(*scc
->lattice
)*(ins_count
+ 1), "lattice");
20428 xcmalloc(sizeof(*scc
->ssa_edges
)*(ssa_edge_count
+ 1), "ssa_edges");
20430 xcmalloc(sizeof(*scc
->flow_blocks
)*(state
->bb
.last_vertex
+ 1),
20433 /* Initialize pass one collect up the nodes */
20436 ins_index
= ssa_edge_index
= fblock_index
= 0;
20439 if ((ins
->op
== OP_LABEL
) && (block
!= ins
->u
.block
)) {
20440 block
= ins
->u
.block
;
20442 internal_error(state
, ins
, "label without block");
20445 block
->vertex
= fblock_index
;
20446 fblock
= &scc
->flow_blocks
[fblock_index
];
20447 fblock
->block
= block
;
20448 fblock
->edges
= xcmalloc(sizeof(*fblock
->edges
)*block
->edge_count
,
20452 struct lattice_node
*lnode
;
20454 lnode
= &scc
->lattice
[ins_index
];
20457 lnode
->fblock
= fblock
;
20458 lnode
->val
= ins
; /* LATTICE HIGH */
20459 if (lnode
->val
->op
== OP_UNKNOWNVAL
) {
20460 lnode
->val
= 0; /* LATTICE LOW by definition */
20462 lnode
->old_id
= ins
->id
;
20463 ins
->id
= ins_index
;
20466 } while(ins
!= first
);
20467 /* Initialize pass two collect up the edges */
20473 struct triple_set
*edge
;
20474 struct ssa_edge
**stail
;
20475 struct lattice_node
*lnode
;
20476 lnode
= &scc
->lattice
[ins
->id
];
20478 stail
= &lnode
->out
;
20479 for(edge
= ins
->use
; edge
; edge
= edge
->next
) {
20480 struct ssa_edge
*sedge
;
20481 ssa_edge_index
+= 1;
20482 sedge
= &scc
->ssa_edges
[ssa_edge_index
];
20484 stail
= &sedge
->out_next
;
20485 sedge
->src
= lnode
;
20486 sedge
->dst
= &scc
->lattice
[edge
->member
->id
];
20487 sedge
->work_next
= sedge
->work_prev
= sedge
;
20488 sedge
->out_next
= 0;
20491 if ((ins
->op
== OP_LABEL
) && (block
!= ins
->u
.block
)) {
20492 struct flow_edge
*fedge
, **ftail
;
20493 struct block_set
*bedge
;
20494 block
= ins
->u
.block
;
20495 fblock
= &scc
->flow_blocks
[block
->vertex
];
20498 ftail
= &fblock
->out
;
20500 fedge
= fblock
->edges
;
20501 bedge
= block
->edges
;
20502 for(; bedge
; bedge
= bedge
->next
, fedge
++) {
20503 fedge
->dst
= &scc
->flow_blocks
[bedge
->member
->vertex
];
20504 if (fedge
->dst
->block
!= bedge
->member
) {
20505 internal_error(state
, 0, "block mismatch");
20508 ftail
= &fedge
->out_next
;
20509 fedge
->out_next
= 0;
20511 for(fedge
= fblock
->out
; fedge
; fedge
= fedge
->out_next
) {
20512 fedge
->src
= fblock
;
20513 fedge
->work_next
= fedge
->work_prev
= fedge
;
20514 fedge
->executable
= 0;
20518 } while (ins
!= first
);
20523 if ((ins
->op
== OP_LABEL
) && (block
!= ins
->u
.block
)) {
20524 struct flow_edge
**ftail
;
20525 struct block_set
*bedge
;
20526 block
= ins
->u
.block
;
20527 fblock
= &scc
->flow_blocks
[block
->vertex
];
20528 ftail
= &fblock
->in
;
20529 for(bedge
= block
->use
; bedge
; bedge
= bedge
->next
) {
20530 struct block
*src_block
;
20531 struct flow_block
*sfblock
;
20532 struct flow_edge
*sfedge
;
20533 src_block
= bedge
->member
;
20534 sfblock
= &scc
->flow_blocks
[src_block
->vertex
];
20535 for(sfedge
= sfblock
->out
; sfedge
; sfedge
= sfedge
->out_next
) {
20536 if (sfedge
->dst
== fblock
) {
20541 internal_error(state
, 0, "edge mismatch");
20544 ftail
= &sfedge
->in_next
;
20545 sfedge
->in_next
= 0;
20549 } while(ins
!= first
);
20550 /* Setup a dummy block 0 as a node above the start node */
20552 struct flow_block
*fblock
, *dst
;
20553 struct flow_edge
*fedge
;
20554 fblock
= &scc
->flow_blocks
[0];
20556 fblock
->edges
= xcmalloc(sizeof(*fblock
->edges
)*1, "flow_edges");
20558 fblock
->out
= fblock
->edges
;
20559 dst
= &scc
->flow_blocks
[state
->bb
.first_block
->vertex
];
20560 fedge
= fblock
->edges
;
20561 fedge
->src
= fblock
;
20563 fedge
->work_next
= fedge
;
20564 fedge
->work_prev
= fedge
;
20565 fedge
->in_next
= fedge
->dst
->in
;
20566 fedge
->out_next
= 0;
20567 fedge
->executable
= 0;
20568 fedge
->dst
->in
= fedge
;
20570 /* Initialize the work lists */
20571 scc
->flow_work_list
= 0;
20572 scc
->ssa_work_list
= 0;
20573 scc_add_fedge(state
, scc
, fedge
);
20575 if (state
->compiler
->debug
& DEBUG_SCC_TRANSFORM
) {
20576 fprintf(state
->errout
, "ins_index: %d ssa_edge_index: %d fblock_index: %d\n",
20577 ins_index
, ssa_edge_index
, fblock_index
);
20582 static void free_scc_state(
20583 struct compile_state
*state
, struct scc_state
*scc
)
20586 for(i
= 0; i
< state
->bb
.last_vertex
+ 1; i
++) {
20587 struct flow_block
*fblock
;
20588 fblock
= &scc
->flow_blocks
[i
];
20589 if (fblock
->edges
) {
20590 xfree(fblock
->edges
);
20594 xfree(scc
->flow_blocks
);
20595 xfree(scc
->ssa_edges
);
20596 xfree(scc
->lattice
);
20600 static struct lattice_node
*triple_to_lattice(
20601 struct compile_state
*state
, struct scc_state
*scc
, struct triple
*ins
)
20603 if (ins
->id
<= 0) {
20604 internal_error(state
, ins
, "bad id");
20606 return &scc
->lattice
[ins
->id
];
20609 static struct triple
*preserve_lval(
20610 struct compile_state
*state
, struct lattice_node
*lnode
)
20612 struct triple
*old
;
20613 /* Preserve the original value */
20615 old
= dup_triple(state
, lnode
->val
);
20616 if (lnode
->val
!= lnode
->def
) {
20626 static int lval_changed(struct compile_state
*state
,
20627 struct triple
*old
, struct lattice_node
*lnode
)
20630 /* See if the lattice value has changed */
20632 if (!old
&& !lnode
->val
) {
20636 lnode
->val
&& old
&&
20637 (memcmp(lnode
->val
->param
, old
->param
,
20638 TRIPLE_SIZE(lnode
->val
) * sizeof(lnode
->val
->param
[0])) == 0) &&
20639 (memcmp(&lnode
->val
->u
, &old
->u
, sizeof(old
->u
)) == 0)) {
20649 static void scc_debug_lnode(
20650 struct compile_state
*state
, struct scc_state
*scc
,
20651 struct lattice_node
*lnode
, int changed
)
20653 if ((state
->compiler
->debug
& DEBUG_SCC_TRANSFORM2
) && lnode
->val
) {
20654 display_triple_changes(state
->errout
, lnode
->val
, lnode
->def
);
20656 if (state
->compiler
->debug
& DEBUG_SCC_TRANSFORM
) {
20657 FILE *fp
= state
->errout
;
20658 struct triple
*val
, **expr
;
20659 val
= lnode
->val
? lnode
->val
: lnode
->def
;
20660 fprintf(fp
, "%p %s %3d %10s (",
20662 ((lnode
->def
->op
== OP_PHI
)? "phi: ": "expr:"),
20664 tops(lnode
->def
->op
));
20665 expr
= triple_rhs(state
, lnode
->def
, 0);
20666 for(;expr
;expr
= triple_rhs(state
, lnode
->def
, expr
)) {
20668 fprintf(fp
, " %d", (*expr
)->id
);
20671 if (val
->op
== OP_INTCONST
) {
20672 fprintf(fp
, " <0x%08lx>", (unsigned long)(val
->u
.cval
));
20674 fprintf(fp
, " ) -> %s %s\n",
20675 (is_lattice_hi(state
, lnode
)? "hi":
20676 is_lattice_const(state
, lnode
)? "const" : "lo"),
20677 changed
? "changed" : ""
20682 static int compute_lnode_val(struct compile_state
*state
, struct scc_state
*scc
,
20683 struct lattice_node
*lnode
)
20686 struct triple
*old
, *scratch
;
20687 struct triple
**dexpr
, **vexpr
;
20690 /* Store the original value */
20691 old
= preserve_lval(state
, lnode
);
20693 /* Reinitialize the value */
20694 lnode
->val
= scratch
= dup_triple(state
, lnode
->def
);
20695 scratch
->id
= lnode
->old_id
;
20696 scratch
->next
= scratch
;
20697 scratch
->prev
= scratch
;
20700 count
= TRIPLE_SIZE(scratch
);
20701 for(i
= 0; i
< count
; i
++) {
20702 dexpr
= &lnode
->def
->param
[i
];
20703 vexpr
= &scratch
->param
[i
];
20705 if (((i
< TRIPLE_MISC_OFF(scratch
)) ||
20706 (i
>= TRIPLE_TARG_OFF(scratch
))) &&
20708 struct lattice_node
*tmp
;
20709 tmp
= triple_to_lattice(state
, scc
, *dexpr
);
20710 *vexpr
= (tmp
->val
)? tmp
->val
: tmp
->def
;
20713 if (triple_is_branch(state
, scratch
)) {
20714 scratch
->next
= lnode
->def
->next
;
20716 /* Recompute the value */
20717 #if DEBUG_ROMCC_WARNINGS
20718 #warning "FIXME see if simplify does anything bad"
20720 /* So far it looks like only the strength reduction
20721 * optimization are things I need to worry about.
20723 simplify(state
, scratch
);
20724 /* Cleanup my value */
20725 if (scratch
->use
) {
20726 internal_error(state
, lnode
->def
, "scratch used?");
20728 if ((scratch
->prev
!= scratch
) ||
20729 ((scratch
->next
!= scratch
) &&
20730 (!triple_is_branch(state
, lnode
->def
) ||
20731 (scratch
->next
!= lnode
->def
->next
)))) {
20732 internal_error(state
, lnode
->def
, "scratch in list?");
20734 /* undo any uses... */
20735 count
= TRIPLE_SIZE(scratch
);
20736 for(i
= 0; i
< count
; i
++) {
20737 vexpr
= &scratch
->param
[i
];
20739 unuse_triple(*vexpr
, scratch
);
20742 if (lnode
->val
->op
== OP_UNKNOWNVAL
) {
20743 lnode
->val
= 0; /* Lattice low by definition */
20745 /* Find the case when I am lattice high */
20747 (lnode
->val
->op
== lnode
->def
->op
) &&
20748 (memcmp(lnode
->val
->param
, lnode
->def
->param
,
20749 count
* sizeof(lnode
->val
->param
[0])) == 0) &&
20750 (memcmp(&lnode
->val
->u
, &lnode
->def
->u
, sizeof(lnode
->def
->u
)) == 0)) {
20751 lnode
->val
= lnode
->def
;
20753 /* Only allow lattice high when all of my inputs
20754 * are also lattice high. Occassionally I can
20755 * have constants with a lattice low input, so
20756 * I do not need to check that case.
20758 if (is_lattice_hi(state
, lnode
)) {
20759 struct lattice_node
*tmp
;
20761 rhs
= lnode
->val
->rhs
;
20762 for(i
= 0; i
< rhs
; i
++) {
20763 tmp
= triple_to_lattice(state
, scc
, RHS(lnode
->val
, i
));
20764 if (!is_lattice_hi(state
, tmp
)) {
20770 /* Find the cases that are always lattice lo */
20772 triple_is_def(state
, lnode
->val
) &&
20773 !triple_is_pure(state
, lnode
->val
, lnode
->old_id
)) {
20776 /* See if the lattice value has changed */
20777 changed
= lval_changed(state
, old
, lnode
);
20778 /* See if this value should not change */
20779 if ((lnode
->val
!= lnode
->def
) &&
20780 (( !triple_is_def(state
, lnode
->def
) &&
20781 !triple_is_cbranch(state
, lnode
->def
)) ||
20782 (lnode
->def
->op
== OP_PIECE
))) {
20783 #if DEBUG_ROMCC_WARNINGS
20784 #warning "FIXME constant propogate through expressions with multiple left hand sides"
20787 internal_warning(state
, lnode
->def
, "non def changes value?");
20792 /* See if we need to free the scratch value */
20793 if (lnode
->val
!= scratch
) {
20801 static void scc_visit_cbranch(struct compile_state
*state
, struct scc_state
*scc
,
20802 struct lattice_node
*lnode
)
20804 struct lattice_node
*cond
;
20805 struct flow_edge
*left
, *right
;
20808 /* Update the branch value */
20809 changed
= compute_lnode_val(state
, scc
, lnode
);
20810 scc_debug_lnode(state
, scc
, lnode
, changed
);
20812 /* This only applies to conditional branches */
20813 if (!triple_is_cbranch(state
, lnode
->def
)) {
20814 internal_error(state
, lnode
->def
, "not a conditional branch");
20817 if (state
->compiler
->debug
& DEBUG_SCC_TRANSFORM
) {
20818 struct flow_edge
*fedge
;
20819 FILE *fp
= state
->errout
;
20820 fprintf(fp
, "%s: %d (",
20821 tops(lnode
->def
->op
),
20824 for(fedge
= lnode
->fblock
->out
; fedge
; fedge
= fedge
->out_next
) {
20825 fprintf(fp
, " %d", fedge
->dst
->block
->vertex
);
20828 if (lnode
->def
->rhs
> 0) {
20829 fprintf(fp
, " <- %d",
20830 RHS(lnode
->def
, 0)->id
);
20834 cond
= triple_to_lattice(state
, scc
, RHS(lnode
->def
,0));
20835 for(left
= cond
->fblock
->out
; left
; left
= left
->out_next
) {
20836 if (left
->dst
->block
->first
== lnode
->def
->next
) {
20841 internal_error(state
, lnode
->def
, "Cannot find left branch edge");
20843 for(right
= cond
->fblock
->out
; right
; right
= right
->out_next
) {
20844 if (right
->dst
->block
->first
== TARG(lnode
->def
, 0)) {
20849 internal_error(state
, lnode
->def
, "Cannot find right branch edge");
20851 /* I should only come here if the controlling expressions value
20852 * has changed, which means it must be either a constant or lo.
20854 if (is_lattice_hi(state
, cond
)) {
20855 internal_error(state
, cond
->def
, "condition high?");
20858 if (is_lattice_lo(state
, cond
)) {
20859 scc_add_fedge(state
, scc
, left
);
20860 scc_add_fedge(state
, scc
, right
);
20862 else if (cond
->val
->u
.cval
) {
20863 scc_add_fedge(state
, scc
, right
);
20865 scc_add_fedge(state
, scc
, left
);
20871 static void scc_add_sedge_dst(struct compile_state
*state
,
20872 struct scc_state
*scc
, struct ssa_edge
*sedge
)
20874 if (triple_is_cbranch(state
, sedge
->dst
->def
)) {
20875 scc_visit_cbranch(state
, scc
, sedge
->dst
);
20877 else if (triple_is_def(state
, sedge
->dst
->def
)) {
20878 scc_add_sedge(state
, scc
, sedge
);
20882 static void scc_visit_phi(struct compile_state
*state
, struct scc_state
*scc
,
20883 struct lattice_node
*lnode
)
20885 struct lattice_node
*tmp
;
20886 struct triple
**slot
, *old
;
20887 struct flow_edge
*fedge
;
20890 if (lnode
->def
->op
!= OP_PHI
) {
20891 internal_error(state
, lnode
->def
, "not phi");
20893 /* Store the original value */
20894 old
= preserve_lval(state
, lnode
);
20896 /* default to lattice high */
20897 lnode
->val
= lnode
->def
;
20898 slot
= &RHS(lnode
->def
, 0);
20900 for(fedge
= lnode
->fblock
->in
; fedge
; index
++, fedge
= fedge
->in_next
) {
20901 if (state
->compiler
->debug
& DEBUG_SCC_TRANSFORM
) {
20902 fprintf(state
->errout
, "Examining edge: %d vertex: %d executable: %d\n",
20904 fedge
->dst
->block
->vertex
,
20908 if (!fedge
->executable
) {
20911 if (!slot
[index
]) {
20912 internal_error(state
, lnode
->def
, "no phi value");
20914 tmp
= triple_to_lattice(state
, scc
, slot
[index
]);
20915 /* meet(X, lattice low) = lattice low */
20916 if (is_lattice_lo(state
, tmp
)) {
20919 /* meet(X, lattice high) = X */
20920 else if (is_lattice_hi(state
, tmp
)) {
20921 lnode
->val
= lnode
->val
;
20923 /* meet(lattice high, X) = X */
20924 else if (is_lattice_hi(state
, lnode
)) {
20925 lnode
->val
= dup_triple(state
, tmp
->val
);
20926 /* Only change the type if necessary */
20927 if (!is_subset_type(lnode
->def
->type
, tmp
->val
->type
)) {
20928 lnode
->val
->type
= lnode
->def
->type
;
20931 /* meet(const, const) = const or lattice low */
20932 else if (!constants_equal(state
, lnode
->val
, tmp
->val
)) {
20936 /* meet(lattice low, X) = lattice low */
20937 if (is_lattice_lo(state
, lnode
)) {
20942 changed
= lval_changed(state
, old
, lnode
);
20943 scc_debug_lnode(state
, scc
, lnode
, changed
);
20945 /* If the lattice value has changed update the work lists. */
20947 struct ssa_edge
*sedge
;
20948 for(sedge
= lnode
->out
; sedge
; sedge
= sedge
->out_next
) {
20949 scc_add_sedge_dst(state
, scc
, sedge
);
20955 static void scc_visit_expr(struct compile_state
*state
, struct scc_state
*scc
,
20956 struct lattice_node
*lnode
)
20960 if (!triple_is_def(state
, lnode
->def
)) {
20961 internal_warning(state
, lnode
->def
, "not visiting an expression?");
20963 changed
= compute_lnode_val(state
, scc
, lnode
);
20964 scc_debug_lnode(state
, scc
, lnode
, changed
);
20967 struct ssa_edge
*sedge
;
20968 for(sedge
= lnode
->out
; sedge
; sedge
= sedge
->out_next
) {
20969 scc_add_sedge_dst(state
, scc
, sedge
);
20974 static void scc_writeback_values(
20975 struct compile_state
*state
, struct scc_state
*scc
)
20977 struct triple
*first
, *ins
;
20978 first
= state
->first
;
20981 struct lattice_node
*lnode
;
20982 lnode
= triple_to_lattice(state
, scc
, ins
);
20983 if (state
->compiler
->debug
& DEBUG_SCC_TRANSFORM
) {
20984 if (is_lattice_hi(state
, lnode
) &&
20985 (lnode
->val
->op
!= OP_NOOP
))
20987 struct flow_edge
*fedge
;
20990 for(fedge
= lnode
->fblock
->in
;
20991 !executable
&& fedge
; fedge
= fedge
->in_next
) {
20992 executable
|= fedge
->executable
;
20995 internal_warning(state
, lnode
->def
,
20996 "lattice node %d %s->%s still high?",
20998 tops(lnode
->def
->op
),
20999 tops(lnode
->val
->op
));
21005 ins
->id
= lnode
->old_id
;
21006 if (lnode
->val
&& (lnode
->val
!= ins
)) {
21007 /* See if it something I know how to write back */
21008 switch(lnode
->val
->op
) {
21010 mkconst(state
, ins
, lnode
->val
->u
.cval
);
21013 mkaddr_const(state
, ins
,
21014 MISC(lnode
->val
, 0), lnode
->val
->u
.cval
);
21017 /* By default don't copy the changes,
21018 * recompute them in place instead.
21020 simplify(state
, ins
);
21023 if (is_const(lnode
->val
) &&
21024 !constants_equal(state
, lnode
->val
, ins
)) {
21025 internal_error(state
, 0, "constants not equal");
21027 /* Free the lattice nodes */
21032 } while(ins
!= first
);
21035 static void scc_transform(struct compile_state
*state
)
21037 struct scc_state scc
;
21038 if (!(state
->compiler
->flags
& COMPILER_SCC_TRANSFORM
)) {
21042 initialize_scc_state(state
, &scc
);
21044 while(scc
.flow_work_list
|| scc
.ssa_work_list
) {
21045 struct flow_edge
*fedge
;
21046 struct ssa_edge
*sedge
;
21047 struct flow_edge
*fptr
;
21048 while((fedge
= scc_next_fedge(state
, &scc
))) {
21049 struct block
*block
;
21050 struct triple
*ptr
;
21051 struct flow_block
*fblock
;
21054 if (fedge
->executable
) {
21058 internal_error(state
, 0, "fedge without dst");
21061 internal_error(state
, 0, "fedge without src");
21063 fedge
->executable
= 1;
21064 fblock
= fedge
->dst
;
21065 block
= fblock
->block
;
21067 for(fptr
= fblock
->in
; fptr
; fptr
= fptr
->in_next
) {
21068 if (fptr
->executable
) {
21073 if (state
->compiler
->debug
& DEBUG_SCC_TRANSFORM
) {
21074 fprintf(state
->errout
, "vertex: %d reps: %d\n",
21075 block
->vertex
, reps
);
21079 for(ptr
= block
->first
; !done
; ptr
= ptr
->next
) {
21080 struct lattice_node
*lnode
;
21081 done
= (ptr
== block
->last
);
21082 lnode
= &scc
.lattice
[ptr
->id
];
21083 if (ptr
->op
== OP_PHI
) {
21084 scc_visit_phi(state
, &scc
, lnode
);
21086 else if ((reps
== 1) && triple_is_def(state
, ptr
))
21088 scc_visit_expr(state
, &scc
, lnode
);
21091 /* Add unconditional branch edges */
21092 if (!triple_is_cbranch(state
, fblock
->block
->last
)) {
21093 struct flow_edge
*out
;
21094 for(out
= fblock
->out
; out
; out
= out
->out_next
) {
21095 scc_add_fedge(state
, &scc
, out
);
21099 while((sedge
= scc_next_sedge(state
, &scc
))) {
21100 struct lattice_node
*lnode
;
21101 struct flow_block
*fblock
;
21102 lnode
= sedge
->dst
;
21103 fblock
= lnode
->fblock
;
21105 if (state
->compiler
->debug
& DEBUG_SCC_TRANSFORM
) {
21106 fprintf(state
->errout
, "sedge: %5ld (%5d -> %5d)\n",
21107 (unsigned long)sedge
- (unsigned long)scc
.ssa_edges
,
21108 sedge
->src
->def
->id
,
21109 sedge
->dst
->def
->id
);
21112 if (lnode
->def
->op
== OP_PHI
) {
21113 scc_visit_phi(state
, &scc
, lnode
);
21116 for(fptr
= fblock
->in
; fptr
; fptr
= fptr
->in_next
) {
21117 if (fptr
->executable
) {
21122 scc_visit_expr(state
, &scc
, lnode
);
21128 scc_writeback_values(state
, &scc
);
21129 free_scc_state(state
, &scc
);
21130 rebuild_ssa_form(state
);
21132 print_blocks(state
, __func__
, state
->dbgout
);
21136 static void transform_to_arch_instructions(struct compile_state
*state
)
21138 struct triple
*ins
, *first
;
21139 first
= state
->first
;
21142 ins
= transform_to_arch_instruction(state
, ins
);
21143 } while(ins
!= first
);
21145 print_blocks(state
, __func__
, state
->dbgout
);
21148 #if DEBUG_CONSISTENCY
21149 static void verify_uses(struct compile_state
*state
)
21151 struct triple
*first
, *ins
;
21152 struct triple_set
*set
;
21153 first
= state
->first
;
21156 struct triple
**expr
;
21157 expr
= triple_rhs(state
, ins
, 0);
21158 for(; expr
; expr
= triple_rhs(state
, ins
, expr
)) {
21159 struct triple
*rhs
;
21161 for(set
= rhs
?rhs
->use
:0; set
; set
= set
->next
) {
21162 if (set
->member
== ins
) {
21167 internal_error(state
, ins
, "rhs not used");
21170 expr
= triple_lhs(state
, ins
, 0);
21171 for(; expr
; expr
= triple_lhs(state
, ins
, expr
)) {
21172 struct triple
*lhs
;
21174 for(set
= lhs
?lhs
->use
:0; set
; set
= set
->next
) {
21175 if (set
->member
== ins
) {
21180 internal_error(state
, ins
, "lhs not used");
21183 expr
= triple_misc(state
, ins
, 0);
21184 if (ins
->op
!= OP_PHI
) {
21185 for(; expr
; expr
= triple_targ(state
, ins
, expr
)) {
21186 struct triple
*misc
;
21188 for(set
= misc
?misc
->use
:0; set
; set
= set
->next
) {
21189 if (set
->member
== ins
) {
21194 internal_error(state
, ins
, "misc not used");
21198 if (!triple_is_ret(state
, ins
)) {
21199 expr
= triple_targ(state
, ins
, 0);
21200 for(; expr
; expr
= triple_targ(state
, ins
, expr
)) {
21201 struct triple
*targ
;
21203 for(set
= targ
?targ
->use
:0; set
; set
= set
->next
) {
21204 if (set
->member
== ins
) {
21209 internal_error(state
, ins
, "targ not used");
21214 } while(ins
!= first
);
21217 static void verify_blocks_present(struct compile_state
*state
)
21219 struct triple
*first
, *ins
;
21220 if (!state
->bb
.first_block
) {
21223 first
= state
->first
;
21226 valid_ins(state
, ins
);
21227 if (triple_stores_block(state
, ins
)) {
21228 if (!ins
->u
.block
) {
21229 internal_error(state
, ins
,
21230 "%p not in a block?", ins
);
21234 } while(ins
!= first
);
21239 static int edge_present(struct compile_state
*state
, struct block
*block
, struct triple
*edge
)
21241 struct block_set
*bedge
;
21242 struct block
*targ
;
21243 targ
= block_of_triple(state
, edge
);
21244 for(bedge
= block
->edges
; bedge
; bedge
= bedge
->next
) {
21245 if (bedge
->member
== targ
) {
21252 static void verify_blocks(struct compile_state
*state
)
21254 struct triple
*ins
;
21255 struct block
*block
;
21257 block
= state
->bb
.first_block
;
21264 struct block_set
*user
, *edge
;
21266 for(ins
= block
->first
; ins
!= block
->last
->next
; ins
= ins
->next
) {
21267 if (triple_stores_block(state
, ins
) && (ins
->u
.block
!= block
)) {
21268 internal_error(state
, ins
, "inconsitent block specified");
21270 valid_ins(state
, ins
);
21273 for(user
= block
->use
; user
; user
= user
->next
) {
21275 if (!user
->member
->first
) {
21276 internal_error(state
, block
->first
, "user is empty");
21278 if ((block
== state
->bb
.last_block
) &&
21279 (user
->member
== state
->bb
.first_block
)) {
21282 for(edge
= user
->member
->edges
; edge
; edge
= edge
->next
) {
21283 if (edge
->member
== block
) {
21288 internal_error(state
, user
->member
->first
,
21289 "user does not use block");
21292 if (triple_is_branch(state
, block
->last
)) {
21293 struct triple
**expr
;
21294 expr
= triple_edge_targ(state
, block
->last
, 0);
21295 for(;expr
; expr
= triple_edge_targ(state
, block
->last
, expr
)) {
21296 if (*expr
&& !edge_present(state
, block
, *expr
)) {
21297 internal_error(state
, block
->last
, "no edge to targ");
21301 if (!triple_is_ubranch(state
, block
->last
) &&
21302 (block
!= state
->bb
.last_block
) &&
21303 !edge_present(state
, block
, block
->last
->next
)) {
21304 internal_error(state
, block
->last
, "no edge to block->last->next");
21306 for(edge
= block
->edges
; edge
; edge
= edge
->next
) {
21307 for(user
= edge
->member
->use
; user
; user
= user
->next
) {
21308 if (user
->member
== block
) {
21312 if (!user
|| user
->member
!= block
) {
21313 internal_error(state
, block
->first
,
21314 "block does not use edge");
21316 if (!edge
->member
->first
) {
21317 internal_error(state
, block
->first
, "edge block is empty");
21320 if (block
->users
!= users
) {
21321 internal_error(state
, block
->first
,
21322 "computed users %d != stored users %d",
21323 users
, block
->users
);
21325 if (!triple_stores_block(state
, block
->last
->next
)) {
21326 internal_error(state
, block
->last
->next
,
21327 "cannot find next block");
21329 block
= block
->last
->next
->u
.block
;
21331 internal_error(state
, block
->last
->next
,
21334 } while(block
!= state
->bb
.first_block
);
21335 if (blocks
!= state
->bb
.last_vertex
) {
21336 internal_error(state
, 0, "computed blocks: %d != stored blocks %d",
21337 blocks
, state
->bb
.last_vertex
);
21341 static void verify_domination(struct compile_state
*state
)
21343 struct triple
*first
, *ins
;
21344 struct triple_set
*set
;
21345 if (!state
->bb
.first_block
) {
21349 first
= state
->first
;
21352 for(set
= ins
->use
; set
; set
= set
->next
) {
21353 struct triple
**slot
;
21354 struct triple
*use_point
;
21357 zrhs
= set
->member
->rhs
;
21358 slot
= &RHS(set
->member
, 0);
21359 /* See if the use is on the right hand side */
21360 for(i
= 0; i
< zrhs
; i
++) {
21361 if (slot
[i
] == ins
) {
21366 use_point
= set
->member
;
21367 if (set
->member
->op
== OP_PHI
) {
21368 struct block_set
*bset
;
21370 bset
= set
->member
->u
.block
->use
;
21371 for(edge
= 0; bset
&& (edge
< i
); edge
++) {
21375 internal_error(state
, set
->member
,
21376 "no edge for phi rhs %d", i
);
21378 use_point
= bset
->member
->last
;
21382 !tdominates(state
, ins
, use_point
)) {
21383 if (is_const(ins
)) {
21384 internal_warning(state
, ins
,
21385 "non dominated rhs use point %p?", use_point
);
21388 internal_error(state
, ins
,
21389 "non dominated rhs use point %p?", use_point
);
21394 } while(ins
!= first
);
21397 static void verify_rhs(struct compile_state
*state
)
21399 struct triple
*first
, *ins
;
21400 first
= state
->first
;
21403 struct triple
**slot
;
21406 slot
= &RHS(ins
, 0);
21407 for(i
= 0; i
< zrhs
; i
++) {
21408 if (slot
[i
] == 0) {
21409 internal_error(state
, ins
,
21410 "missing rhs %d on %s",
21413 if ((ins
->op
!= OP_PHI
) && (slot
[i
] == ins
)) {
21414 internal_error(state
, ins
,
21415 "ins == rhs[%d] on %s",
21420 } while(ins
!= first
);
21423 static void verify_piece(struct compile_state
*state
)
21425 struct triple
*first
, *ins
;
21426 first
= state
->first
;
21429 struct triple
*ptr
;
21432 for(ptr
= ins
->next
, i
= 0; i
< lhs
; i
++, ptr
= ptr
->next
) {
21433 if (ptr
!= LHS(ins
, i
)) {
21434 internal_error(state
, ins
, "malformed lhs on %s",
21437 if (ptr
->op
!= OP_PIECE
) {
21438 internal_error(state
, ins
, "bad lhs op %s at %d on %s",
21439 tops(ptr
->op
), i
, tops(ins
->op
));
21441 if (ptr
->u
.cval
!= i
) {
21442 internal_error(state
, ins
, "bad u.cval of %d %d expected",
21447 } while(ins
!= first
);
21450 static void verify_ins_colors(struct compile_state
*state
)
21452 struct triple
*first
, *ins
;
21454 first
= state
->first
;
21458 } while(ins
!= first
);
21461 static void verify_unknown(struct compile_state
*state
)
21463 struct triple
*first
, *ins
;
21464 if ( (unknown_triple
.next
!= &unknown_triple
) ||
21465 (unknown_triple
.prev
!= &unknown_triple
) ||
21467 (unknown_triple
.use
!= 0) ||
21469 (unknown_triple
.op
!= OP_UNKNOWNVAL
) ||
21470 (unknown_triple
.lhs
!= 0) ||
21471 (unknown_triple
.rhs
!= 0) ||
21472 (unknown_triple
.misc
!= 0) ||
21473 (unknown_triple
.targ
!= 0) ||
21474 (unknown_triple
.template_id
!= 0) ||
21475 (unknown_triple
.id
!= -1) ||
21476 (unknown_triple
.type
!= &unknown_type
) ||
21477 (unknown_triple
.occurance
!= &dummy_occurance
) ||
21478 (unknown_triple
.param
[0] != 0) ||
21479 (unknown_triple
.param
[1] != 0)) {
21480 internal_error(state
, &unknown_triple
, "unknown_triple corrupted!");
21482 if ( (dummy_occurance
.count
!= 2) ||
21483 (strcmp(dummy_occurance
.filename
, __FILE__
) != 0) ||
21484 (strcmp(dummy_occurance
.function
, "") != 0) ||
21485 (dummy_occurance
.col
!= 0) ||
21486 (dummy_occurance
.parent
!= 0)) {
21487 internal_error(state
, &unknown_triple
, "dummy_occurance corrupted!");
21489 if ( (unknown_type
.type
!= TYPE_UNKNOWN
)) {
21490 internal_error(state
, &unknown_triple
, "unknown_type corrupted!");
21492 first
= state
->first
;
21496 if (ins
== &unknown_triple
) {
21497 internal_error(state
, ins
, "unknown triple in list");
21499 params
= TRIPLE_SIZE(ins
);
21500 for(i
= 0; i
< params
; i
++) {
21501 if (ins
->param
[i
] == &unknown_triple
) {
21502 internal_error(state
, ins
, "unknown triple used!");
21506 } while(ins
!= first
);
21509 static void verify_types(struct compile_state
*state
)
21511 struct triple
*first
, *ins
;
21512 first
= state
->first
;
21515 struct type
*invalid
;
21516 invalid
= invalid_type(state
, ins
->type
);
21518 FILE *fp
= state
->errout
;
21519 fprintf(fp
, "type: ");
21520 name_of(fp
, ins
->type
);
21522 fprintf(fp
, "invalid type: ");
21523 name_of(fp
, invalid
);
21525 internal_error(state
, ins
, "invalid ins type");
21527 } while(ins
!= first
);
21530 static void verify_copy(struct compile_state
*state
)
21532 struct triple
*first
, *ins
, *next
;
21533 first
= state
->first
;
21534 next
= ins
= first
;
21538 if (ins
->op
!= OP_COPY
) {
21541 if (!equiv_types(ins
->type
, RHS(ins
, 0)->type
)) {
21542 FILE *fp
= state
->errout
;
21543 fprintf(fp
, "src type: ");
21544 name_of(fp
, RHS(ins
, 0)->type
);
21546 fprintf(fp
, "dst type: ");
21547 name_of(fp
, ins
->type
);
21549 internal_error(state
, ins
, "type mismatch in copy");
21551 } while(next
!= first
);
21554 static void verify_consistency(struct compile_state
*state
)
21556 verify_unknown(state
);
21557 verify_uses(state
);
21558 verify_blocks_present(state
);
21559 verify_blocks(state
);
21560 verify_domination(state
);
21562 verify_piece(state
);
21563 verify_ins_colors(state
);
21564 verify_types(state
);
21565 verify_copy(state
);
21566 if (state
->compiler
->debug
& DEBUG_VERIFICATION
) {
21567 fprintf(state
->dbgout
, "consistency verified\n");
21571 static void verify_consistency(struct compile_state
*state
) {}
21572 #endif /* DEBUG_CONSISTENCY */
21574 static void optimize(struct compile_state
*state
)
21576 /* Join all of the functions into one giant function */
21577 join_functions(state
);
21579 /* Dump what the instruction graph intially looks like */
21580 print_triples(state
);
21582 /* Replace structures with simpler data types */
21583 decompose_compound_types(state
);
21584 print_triples(state
);
21586 verify_consistency(state
);
21587 /* Analyze the intermediate code */
21588 state
->bb
.first
= state
->first
;
21589 analyze_basic_blocks(state
, &state
->bb
);
21591 /* Transform the code to ssa form. */
21593 * The transformation to ssa form puts a phi function
21594 * on each of edge of a dominance frontier where that
21595 * phi function might be needed. At -O2 if we don't
21596 * eleminate the excess phi functions we can get an
21597 * exponential code size growth. So I kill the extra
21598 * phi functions early and I kill them often.
21600 transform_to_ssa_form(state
);
21601 verify_consistency(state
);
21603 /* Remove dead code */
21604 eliminate_inefectual_code(state
);
21605 verify_consistency(state
);
21607 /* Do strength reduction and simple constant optimizations */
21608 simplify_all(state
);
21609 verify_consistency(state
);
21610 /* Propogate constants throughout the code */
21611 scc_transform(state
);
21612 verify_consistency(state
);
21613 #if DEBUG_ROMCC_WARNINGS
21614 #warning "WISHLIST implement single use constants (least possible register pressure)"
21615 #warning "WISHLIST implement induction variable elimination"
21617 /* Select architecture instructions and an initial partial
21618 * coloring based on architecture constraints.
21620 transform_to_arch_instructions(state
);
21621 verify_consistency(state
);
21623 /* Remove dead code */
21624 eliminate_inefectual_code(state
);
21625 verify_consistency(state
);
21627 /* Color all of the variables to see if they will fit in registers */
21628 insert_copies_to_phi(state
);
21629 verify_consistency(state
);
21631 insert_mandatory_copies(state
);
21632 verify_consistency(state
);
21634 allocate_registers(state
);
21635 verify_consistency(state
);
21637 /* Remove the optimization information.
21638 * This is more to check for memory consistency than to free memory.
21640 free_basic_blocks(state
, &state
->bb
);
21643 static void print_op_asm(struct compile_state
*state
,
21644 struct triple
*ins
, FILE *fp
)
21646 struct asm_info
*info
;
21648 unsigned lhs
, rhs
, i
;
21649 info
= ins
->u
.ainfo
;
21652 /* Don't count the clobbers in lhs */
21653 for(i
= 0; i
< lhs
; i
++) {
21654 if (LHS(ins
, i
)->type
== &void_type
) {
21659 fprintf(fp
, "#ASM\n");
21661 for(ptr
= info
->str
; *ptr
; ptr
++) {
21663 unsigned long param
;
21664 struct triple
*piece
;
21674 param
= strtoul(ptr
, &next
, 10);
21676 error(state
, ins
, "Invalid asm template");
21678 if (param
>= (lhs
+ rhs
)) {
21679 error(state
, ins
, "Invalid param %%%u in asm template",
21682 piece
= (param
< lhs
)? LHS(ins
, param
) : RHS(ins
, param
- lhs
);
21684 arch_reg_str(ID_REG(piece
->id
)));
21687 fprintf(fp
, "\n#NOT ASM\n");
21691 /* Only use the low x86 byte registers. This allows me
21692 * allocate the entire register when a byte register is used.
21694 #define X86_4_8BIT_GPRS 1
21697 #define X86_MMX_REGS (1<<0)
21698 #define X86_XMM_REGS (1<<1)
21699 #define X86_NOOP_COPY (1<<2)
21701 /* The x86 register classes */
21702 #define REGC_FLAGS 0
21703 #define REGC_GPR8 1
21704 #define REGC_GPR16 2
21705 #define REGC_GPR32 3
21706 #define REGC_DIVIDEND64 4
21707 #define REGC_DIVIDEND32 5
21710 #define REGC_GPR32_8 8
21711 #define REGC_GPR16_8 9
21712 #define REGC_GPR8_LO 10
21713 #define REGC_IMM32 11
21714 #define REGC_IMM16 12
21715 #define REGC_IMM8 13
21716 #define LAST_REGC REGC_IMM8
21717 #if LAST_REGC >= MAX_REGC
21718 #error "MAX_REGC is to low"
21721 /* Register class masks */
21722 #define REGCM_FLAGS (1 << REGC_FLAGS)
21723 #define REGCM_GPR8 (1 << REGC_GPR8)
21724 #define REGCM_GPR16 (1 << REGC_GPR16)
21725 #define REGCM_GPR32 (1 << REGC_GPR32)
21726 #define REGCM_DIVIDEND64 (1 << REGC_DIVIDEND64)
21727 #define REGCM_DIVIDEND32 (1 << REGC_DIVIDEND32)
21728 #define REGCM_MMX (1 << REGC_MMX)
21729 #define REGCM_XMM (1 << REGC_XMM)
21730 #define REGCM_GPR32_8 (1 << REGC_GPR32_8)
21731 #define REGCM_GPR16_8 (1 << REGC_GPR16_8)
21732 #define REGCM_GPR8_LO (1 << REGC_GPR8_LO)
21733 #define REGCM_IMM32 (1 << REGC_IMM32)
21734 #define REGCM_IMM16 (1 << REGC_IMM16)
21735 #define REGCM_IMM8 (1 << REGC_IMM8)
21736 #define REGCM_ALL ((1 << (LAST_REGC + 1)) - 1)
21737 #define REGCM_IMMALL (REGCM_IMM32 | REGCM_IMM16 | REGCM_IMM8)
21739 /* The x86 registers */
21740 #define REG_EFLAGS 2
21741 #define REGC_FLAGS_FIRST REG_EFLAGS
21742 #define REGC_FLAGS_LAST REG_EFLAGS
21751 #define REGC_GPR8_LO_FIRST REG_AL
21752 #define REGC_GPR8_LO_LAST REG_DL
21753 #define REGC_GPR8_FIRST REG_AL
21754 #define REGC_GPR8_LAST REG_DH
21763 #define REGC_GPR16_FIRST REG_AX
21764 #define REGC_GPR16_LAST REG_SP
21773 #define REGC_GPR32_FIRST REG_EAX
21774 #define REGC_GPR32_LAST REG_ESP
21775 #define REG_EDXEAX 27
21776 #define REGC_DIVIDEND64_FIRST REG_EDXEAX
21777 #define REGC_DIVIDEND64_LAST REG_EDXEAX
21778 #define REG_DXAX 28
21779 #define REGC_DIVIDEND32_FIRST REG_DXAX
21780 #define REGC_DIVIDEND32_LAST REG_DXAX
21781 #define REG_MMX0 29
21782 #define REG_MMX1 30
21783 #define REG_MMX2 31
21784 #define REG_MMX3 32
21785 #define REG_MMX4 33
21786 #define REG_MMX5 34
21787 #define REG_MMX6 35
21788 #define REG_MMX7 36
21789 #define REGC_MMX_FIRST REG_MMX0
21790 #define REGC_MMX_LAST REG_MMX7
21791 #define REG_XMM0 37
21792 #define REG_XMM1 38
21793 #define REG_XMM2 39
21794 #define REG_XMM3 40
21795 #define REG_XMM4 41
21796 #define REG_XMM5 42
21797 #define REG_XMM6 43
21798 #define REG_XMM7 44
21799 #define REGC_XMM_FIRST REG_XMM0
21800 #define REGC_XMM_LAST REG_XMM7
21802 #if DEBUG_ROMCC_WARNINGS
21803 #warning "WISHLIST figure out how to use pinsrw and pextrw to better use extended regs"
21806 #define LAST_REG REG_XMM7
21808 #define REGC_GPR32_8_FIRST REG_EAX
21809 #define REGC_GPR32_8_LAST REG_EDX
21810 #define REGC_GPR16_8_FIRST REG_AX
21811 #define REGC_GPR16_8_LAST REG_DX
21813 #define REGC_IMM8_FIRST -1
21814 #define REGC_IMM8_LAST -1
21815 #define REGC_IMM16_FIRST -2
21816 #define REGC_IMM16_LAST -1
21817 #define REGC_IMM32_FIRST -4
21818 #define REGC_IMM32_LAST -1
21820 #if LAST_REG >= MAX_REGISTERS
21821 #error "MAX_REGISTERS to low"
21825 static unsigned regc_size
[LAST_REGC
+1] = {
21826 [REGC_FLAGS
] = REGC_FLAGS_LAST
- REGC_FLAGS_FIRST
+ 1,
21827 [REGC_GPR8
] = REGC_GPR8_LAST
- REGC_GPR8_FIRST
+ 1,
21828 [REGC_GPR16
] = REGC_GPR16_LAST
- REGC_GPR16_FIRST
+ 1,
21829 [REGC_GPR32
] = REGC_GPR32_LAST
- REGC_GPR32_FIRST
+ 1,
21830 [REGC_DIVIDEND64
] = REGC_DIVIDEND64_LAST
- REGC_DIVIDEND64_FIRST
+ 1,
21831 [REGC_DIVIDEND32
] = REGC_DIVIDEND32_LAST
- REGC_DIVIDEND32_FIRST
+ 1,
21832 [REGC_MMX
] = REGC_MMX_LAST
- REGC_MMX_FIRST
+ 1,
21833 [REGC_XMM
] = REGC_XMM_LAST
- REGC_XMM_FIRST
+ 1,
21834 [REGC_GPR32_8
] = REGC_GPR32_8_LAST
- REGC_GPR32_8_FIRST
+ 1,
21835 [REGC_GPR16_8
] = REGC_GPR16_8_LAST
- REGC_GPR16_8_FIRST
+ 1,
21836 [REGC_GPR8_LO
] = REGC_GPR8_LO_LAST
- REGC_GPR8_LO_FIRST
+ 1,
21842 static const struct {
21844 } regcm_bound
[LAST_REGC
+ 1] = {
21845 [REGC_FLAGS
] = { REGC_FLAGS_FIRST
, REGC_FLAGS_LAST
},
21846 [REGC_GPR8
] = { REGC_GPR8_FIRST
, REGC_GPR8_LAST
},
21847 [REGC_GPR16
] = { REGC_GPR16_FIRST
, REGC_GPR16_LAST
},
21848 [REGC_GPR32
] = { REGC_GPR32_FIRST
, REGC_GPR32_LAST
},
21849 [REGC_DIVIDEND64
] = { REGC_DIVIDEND64_FIRST
, REGC_DIVIDEND64_LAST
},
21850 [REGC_DIVIDEND32
] = { REGC_DIVIDEND32_FIRST
, REGC_DIVIDEND32_LAST
},
21851 [REGC_MMX
] = { REGC_MMX_FIRST
, REGC_MMX_LAST
},
21852 [REGC_XMM
] = { REGC_XMM_FIRST
, REGC_XMM_LAST
},
21853 [REGC_GPR32_8
] = { REGC_GPR32_8_FIRST
, REGC_GPR32_8_LAST
},
21854 [REGC_GPR16_8
] = { REGC_GPR16_8_FIRST
, REGC_GPR16_8_LAST
},
21855 [REGC_GPR8_LO
] = { REGC_GPR8_LO_FIRST
, REGC_GPR8_LO_LAST
},
21856 [REGC_IMM32
] = { REGC_IMM32_FIRST
, REGC_IMM32_LAST
},
21857 [REGC_IMM16
] = { REGC_IMM16_FIRST
, REGC_IMM16_LAST
},
21858 [REGC_IMM8
] = { REGC_IMM8_FIRST
, REGC_IMM8_LAST
},
21861 #if ARCH_INPUT_REGS != 4
21862 #error ARCH_INPUT_REGS size mismatch
21864 static const struct reg_info arch_input_regs
[ARCH_INPUT_REGS
] = {
21865 { .reg
= REG_EAX
, .regcm
= REGCM_GPR32
},
21866 { .reg
= REG_EBX
, .regcm
= REGCM_GPR32
},
21867 { .reg
= REG_ECX
, .regcm
= REGCM_GPR32
},
21868 { .reg
= REG_EDX
, .regcm
= REGCM_GPR32
},
21871 #if ARCH_OUTPUT_REGS != 4
21872 #error ARCH_INPUT_REGS size mismatch
21874 static const struct reg_info arch_output_regs
[ARCH_OUTPUT_REGS
] = {
21875 { .reg
= REG_EAX
, .regcm
= REGCM_GPR32
},
21876 { .reg
= REG_EBX
, .regcm
= REGCM_GPR32
},
21877 { .reg
= REG_ECX
, .regcm
= REGCM_GPR32
},
21878 { .reg
= REG_EDX
, .regcm
= REGCM_GPR32
},
21881 static void init_arch_state(struct arch_state
*arch
)
21883 memset(arch
, 0, sizeof(*arch
));
21884 arch
->features
= 0;
21887 static const struct compiler_flag arch_flags
[] = {
21888 { "mmx", X86_MMX_REGS
},
21889 { "sse", X86_XMM_REGS
},
21890 { "noop-copy", X86_NOOP_COPY
},
21893 static const struct compiler_flag arch_cpus
[] = {
21895 { "p2", X86_MMX_REGS
},
21896 { "p3", X86_MMX_REGS
| X86_XMM_REGS
},
21897 { "p4", X86_MMX_REGS
| X86_XMM_REGS
},
21898 { "k7", X86_MMX_REGS
},
21899 { "k8", X86_MMX_REGS
| X86_XMM_REGS
},
21900 { "c3", X86_MMX_REGS
},
21901 { "c3-2", X86_MMX_REGS
| X86_XMM_REGS
}, /* Nehemiah */
21904 static int arch_encode_flag(struct arch_state
*arch
, const char *flag
)
21911 if (strncmp(flag
, "no-", 3) == 0) {
21915 if (act
&& strncmp(flag
, "cpu=", 4) == 0) {
21917 result
= set_flag(arch_cpus
, &arch
->features
, 1, flag
);
21920 result
= set_flag(arch_flags
, &arch
->features
, act
, flag
);
21925 static void arch_usage(FILE *fp
)
21927 flag_usage(fp
, arch_flags
, "-m", "-mno-");
21928 flag_usage(fp
, arch_cpus
, "-mcpu=", 0);
21931 static unsigned arch_regc_size(struct compile_state
*state
, int class)
21933 if ((class < 0) || (class > LAST_REGC
)) {
21936 return regc_size
[class];
21939 static int arch_regcm_intersect(unsigned regcm1
, unsigned regcm2
)
21941 /* See if two register classes may have overlapping registers */
21942 unsigned gpr_mask
= REGCM_GPR8
| REGCM_GPR8_LO
| REGCM_GPR16_8
| REGCM_GPR16
|
21943 REGCM_GPR32_8
| REGCM_GPR32
|
21944 REGCM_DIVIDEND32
| REGCM_DIVIDEND64
;
21946 /* Special case for the immediates */
21947 if ((regcm1
& (REGCM_IMM32
| REGCM_IMM16
| REGCM_IMM8
)) &&
21948 ((regcm1
& ~(REGCM_IMM32
| REGCM_IMM16
| REGCM_IMM8
)) == 0) &&
21949 (regcm2
& (REGCM_IMM32
| REGCM_IMM16
| REGCM_IMM8
)) &&
21950 ((regcm2
& ~(REGCM_IMM32
| REGCM_IMM16
| REGCM_IMM8
)) == 0)) {
21953 return (regcm1
& regcm2
) ||
21954 ((regcm1
& gpr_mask
) && (regcm2
& gpr_mask
));
21957 static void arch_reg_equivs(
21958 struct compile_state
*state
, unsigned *equiv
, int reg
)
21960 if ((reg
< 0) || (reg
> LAST_REG
)) {
21961 internal_error(state
, 0, "invalid register");
21966 #if X86_4_8BIT_GPRS
21970 *equiv
++ = REG_EAX
;
21971 *equiv
++ = REG_DXAX
;
21972 *equiv
++ = REG_EDXEAX
;
21975 #if X86_4_8BIT_GPRS
21979 *equiv
++ = REG_EAX
;
21980 *equiv
++ = REG_DXAX
;
21981 *equiv
++ = REG_EDXEAX
;
21984 #if X86_4_8BIT_GPRS
21988 *equiv
++ = REG_EBX
;
21992 #if X86_4_8BIT_GPRS
21996 *equiv
++ = REG_EBX
;
21999 #if X86_4_8BIT_GPRS
22003 *equiv
++ = REG_ECX
;
22007 #if X86_4_8BIT_GPRS
22011 *equiv
++ = REG_ECX
;
22014 #if X86_4_8BIT_GPRS
22018 *equiv
++ = REG_EDX
;
22019 *equiv
++ = REG_DXAX
;
22020 *equiv
++ = REG_EDXEAX
;
22023 #if X86_4_8BIT_GPRS
22027 *equiv
++ = REG_EDX
;
22028 *equiv
++ = REG_DXAX
;
22029 *equiv
++ = REG_EDXEAX
;
22034 *equiv
++ = REG_EAX
;
22035 *equiv
++ = REG_DXAX
;
22036 *equiv
++ = REG_EDXEAX
;
22041 *equiv
++ = REG_EBX
;
22046 *equiv
++ = REG_ECX
;
22051 *equiv
++ = REG_EDX
;
22052 *equiv
++ = REG_DXAX
;
22053 *equiv
++ = REG_EDXEAX
;
22056 *equiv
++ = REG_ESI
;
22059 *equiv
++ = REG_EDI
;
22062 *equiv
++ = REG_EBP
;
22065 *equiv
++ = REG_ESP
;
22071 *equiv
++ = REG_DXAX
;
22072 *equiv
++ = REG_EDXEAX
;
22088 *equiv
++ = REG_DXAX
;
22089 *equiv
++ = REG_EDXEAX
;
22110 *equiv
++ = REG_EAX
;
22111 *equiv
++ = REG_EDX
;
22112 *equiv
++ = REG_EDXEAX
;
22121 *equiv
++ = REG_EAX
;
22122 *equiv
++ = REG_EDX
;
22123 *equiv
++ = REG_DXAX
;
22126 *equiv
++ = REG_UNSET
;
22129 static unsigned arch_avail_mask(struct compile_state
*state
)
22131 unsigned avail_mask
;
22132 /* REGCM_GPR8 is not available */
22133 avail_mask
= REGCM_GPR8_LO
| REGCM_GPR16_8
| REGCM_GPR16
|
22134 REGCM_GPR32
| REGCM_GPR32_8
|
22135 REGCM_DIVIDEND32
| REGCM_DIVIDEND64
|
22136 REGCM_IMM32
| REGCM_IMM16
| REGCM_IMM8
| REGCM_FLAGS
;
22137 if (state
->arch
->features
& X86_MMX_REGS
) {
22138 avail_mask
|= REGCM_MMX
;
22140 if (state
->arch
->features
& X86_XMM_REGS
) {
22141 avail_mask
|= REGCM_XMM
;
22146 static unsigned arch_regcm_normalize(struct compile_state
*state
, unsigned regcm
)
22148 unsigned mask
, result
;
22152 for(class = 0, mask
= 1; mask
; mask
<<= 1, class++) {
22153 if ((result
& mask
) == 0) {
22156 if (class > LAST_REGC
) {
22159 for(class2
= 0; class2
<= LAST_REGC
; class2
++) {
22160 if ((regcm_bound
[class2
].first
>= regcm_bound
[class].first
) &&
22161 (regcm_bound
[class2
].last
<= regcm_bound
[class].last
)) {
22162 result
|= (1 << class2
);
22166 result
&= arch_avail_mask(state
);
22170 static unsigned arch_regcm_reg_normalize(struct compile_state
*state
, unsigned regcm
)
22172 /* Like arch_regcm_normalize except immediate register classes are excluded */
22173 regcm
= arch_regcm_normalize(state
, regcm
);
22174 /* Remove the immediate register classes */
22175 regcm
&= ~(REGCM_IMM32
| REGCM_IMM16
| REGCM_IMM8
);
22180 static unsigned arch_reg_regcm(struct compile_state
*state
, int reg
)
22185 for(class = 0; class <= LAST_REGC
; class++) {
22186 if ((reg
>= regcm_bound
[class].first
) &&
22187 (reg
<= regcm_bound
[class].last
)) {
22188 mask
|= (1 << class);
22192 internal_error(state
, 0, "reg %d not in any class", reg
);
22197 static struct reg_info
arch_reg_constraint(
22198 struct compile_state
*state
, struct type
*type
, const char *constraint
)
22200 static const struct {
22204 } constraints
[] = {
22205 { 'r', REGCM_GPR32
, REG_UNSET
},
22206 { 'g', REGCM_GPR32
, REG_UNSET
},
22207 { 'p', REGCM_GPR32
, REG_UNSET
},
22208 { 'q', REGCM_GPR8_LO
, REG_UNSET
},
22209 { 'Q', REGCM_GPR32_8
, REG_UNSET
},
22210 { 'x', REGCM_XMM
, REG_UNSET
},
22211 { 'y', REGCM_MMX
, REG_UNSET
},
22212 { 'a', REGCM_GPR32
, REG_EAX
},
22213 { 'b', REGCM_GPR32
, REG_EBX
},
22214 { 'c', REGCM_GPR32
, REG_ECX
},
22215 { 'd', REGCM_GPR32
, REG_EDX
},
22216 { 'D', REGCM_GPR32
, REG_EDI
},
22217 { 'S', REGCM_GPR32
, REG_ESI
},
22218 { '\0', 0, REG_UNSET
},
22220 unsigned int regcm
;
22221 unsigned int mask
, reg
;
22222 struct reg_info result
;
22224 regcm
= arch_type_to_regcm(state
, type
);
22227 for(ptr
= constraint
; *ptr
; ptr
++) {
22232 for(i
= 0; constraints
[i
].class != '\0'; i
++) {
22233 if (constraints
[i
].class == *ptr
) {
22237 if (constraints
[i
].class == '\0') {
22238 error(state
, 0, "invalid register constraint ``%c''", *ptr
);
22241 if ((constraints
[i
].mask
& regcm
) == 0) {
22242 error(state
, 0, "invalid register class %c specified",
22245 mask
|= constraints
[i
].mask
;
22246 if (constraints
[i
].reg
!= REG_UNSET
) {
22247 if ((reg
!= REG_UNSET
) && (reg
!= constraints
[i
].reg
)) {
22248 error(state
, 0, "Only one register may be specified");
22250 reg
= constraints
[i
].reg
;
22254 result
.regcm
= mask
;
22258 static struct reg_info
arch_reg_clobber(
22259 struct compile_state
*state
, const char *clobber
)
22261 struct reg_info result
;
22262 if (strcmp(clobber
, "memory") == 0) {
22263 result
.reg
= REG_UNSET
;
22266 else if (strcmp(clobber
, "eax") == 0) {
22267 result
.reg
= REG_EAX
;
22268 result
.regcm
= REGCM_GPR32
;
22270 else if (strcmp(clobber
, "ebx") == 0) {
22271 result
.reg
= REG_EBX
;
22272 result
.regcm
= REGCM_GPR32
;
22274 else if (strcmp(clobber
, "ecx") == 0) {
22275 result
.reg
= REG_ECX
;
22276 result
.regcm
= REGCM_GPR32
;
22278 else if (strcmp(clobber
, "edx") == 0) {
22279 result
.reg
= REG_EDX
;
22280 result
.regcm
= REGCM_GPR32
;
22282 else if (strcmp(clobber
, "esi") == 0) {
22283 result
.reg
= REG_ESI
;
22284 result
.regcm
= REGCM_GPR32
;
22286 else if (strcmp(clobber
, "edi") == 0) {
22287 result
.reg
= REG_EDI
;
22288 result
.regcm
= REGCM_GPR32
;
22290 else if (strcmp(clobber
, "ebp") == 0) {
22291 result
.reg
= REG_EBP
;
22292 result
.regcm
= REGCM_GPR32
;
22294 else if (strcmp(clobber
, "esp") == 0) {
22295 result
.reg
= REG_ESP
;
22296 result
.regcm
= REGCM_GPR32
;
22298 else if (strcmp(clobber
, "cc") == 0) {
22299 result
.reg
= REG_EFLAGS
;
22300 result
.regcm
= REGCM_FLAGS
;
22302 else if ((strncmp(clobber
, "xmm", 3) == 0) &&
22303 octdigitp(clobber
[3]) && (clobber
[4] == '\0')) {
22304 result
.reg
= REG_XMM0
+ octdigval(clobber
[3]);
22305 result
.regcm
= REGCM_XMM
;
22307 else if ((strncmp(clobber
, "mm", 2) == 0) &&
22308 octdigitp(clobber
[3]) && (clobber
[4] == '\0')) {
22309 result
.reg
= REG_MMX0
+ octdigval(clobber
[3]);
22310 result
.regcm
= REGCM_MMX
;
22313 error(state
, 0, "unknown register name `%s' in asm",
22315 result
.reg
= REG_UNSET
;
22321 static int do_select_reg(struct compile_state
*state
,
22322 char *used
, int reg
, unsigned classes
)
22328 mask
= arch_reg_regcm(state
, reg
);
22329 return (classes
& mask
) ? reg
: REG_UNSET
;
22332 static int arch_select_free_register(
22333 struct compile_state
*state
, char *used
, int classes
)
22335 /* Live ranges with the most neighbors are colored first.
22337 * Generally it does not matter which colors are given
22338 * as the register allocator attempts to color live ranges
22339 * in an order where you are guaranteed not to run out of colors.
22341 * Occasionally the register allocator cannot find an order
22342 * of register selection that will find a free color. To
22343 * increase the odds the register allocator will work when
22344 * it guesses first give out registers from register classes
22345 * least likely to run out of registers.
22350 for(i
= REGC_XMM_FIRST
; (reg
== REG_UNSET
) && (i
<= REGC_XMM_LAST
); i
++) {
22351 reg
= do_select_reg(state
, used
, i
, classes
);
22353 for(i
= REGC_MMX_FIRST
; (reg
== REG_UNSET
) && (i
<= REGC_MMX_LAST
); i
++) {
22354 reg
= do_select_reg(state
, used
, i
, classes
);
22356 for(i
= REGC_GPR32_LAST
; (reg
== REG_UNSET
) && (i
>= REGC_GPR32_FIRST
); i
--) {
22357 reg
= do_select_reg(state
, used
, i
, classes
);
22359 for(i
= REGC_GPR16_FIRST
; (reg
== REG_UNSET
) && (i
<= REGC_GPR16_LAST
); i
++) {
22360 reg
= do_select_reg(state
, used
, i
, classes
);
22362 for(i
= REGC_GPR8_FIRST
; (reg
== REG_UNSET
) && (i
<= REGC_GPR8_LAST
); i
++) {
22363 reg
= do_select_reg(state
, used
, i
, classes
);
22365 for(i
= REGC_GPR8_LO_FIRST
; (reg
== REG_UNSET
) && (i
<= REGC_GPR8_LO_LAST
); i
++) {
22366 reg
= do_select_reg(state
, used
, i
, classes
);
22368 for(i
= REGC_DIVIDEND32_FIRST
; (reg
== REG_UNSET
) && (i
<= REGC_DIVIDEND32_LAST
); i
++) {
22369 reg
= do_select_reg(state
, used
, i
, classes
);
22371 for(i
= REGC_DIVIDEND64_FIRST
; (reg
== REG_UNSET
) && (i
<= REGC_DIVIDEND64_LAST
); i
++) {
22372 reg
= do_select_reg(state
, used
, i
, classes
);
22374 for(i
= REGC_FLAGS_FIRST
; (reg
== REG_UNSET
) && (i
<= REGC_FLAGS_LAST
); i
++) {
22375 reg
= do_select_reg(state
, used
, i
, classes
);
22381 static unsigned arch_type_to_regcm(struct compile_state
*state
, struct type
*type
)
22384 #if DEBUG_ROMCC_WARNINGS
22385 #warning "FIXME force types smaller (if legal) before I get here"
22389 switch(type
->type
& TYPE_MASK
) {
22396 mask
= REGCM_GPR8
| REGCM_GPR8_LO
|
22397 REGCM_GPR16
| REGCM_GPR16_8
|
22398 REGCM_GPR32
| REGCM_GPR32_8
|
22399 REGCM_DIVIDEND32
| REGCM_DIVIDEND64
|
22400 REGCM_MMX
| REGCM_XMM
|
22401 REGCM_IMM32
| REGCM_IMM16
| REGCM_IMM8
;
22405 mask
= REGCM_GPR16
| REGCM_GPR16_8
|
22406 REGCM_GPR32
| REGCM_GPR32_8
|
22407 REGCM_DIVIDEND32
| REGCM_DIVIDEND64
|
22408 REGCM_MMX
| REGCM_XMM
|
22409 REGCM_IMM32
| REGCM_IMM16
;
22417 mask
= REGCM_GPR32
| REGCM_GPR32_8
|
22418 REGCM_DIVIDEND32
| REGCM_DIVIDEND64
|
22419 REGCM_MMX
| REGCM_XMM
|
22424 mask
= arch_type_to_regcm(state
, type
->left
);
22427 mask
= arch_type_to_regcm(state
, type
->left
) &
22428 arch_type_to_regcm(state
, type
->right
);
22430 case TYPE_BITFIELD
:
22431 mask
= arch_type_to_regcm(state
, type
->left
);
22434 fprintf(state
->errout
, "type: ");
22435 name_of(state
->errout
, type
);
22436 fprintf(state
->errout
, "\n");
22437 internal_error(state
, 0, "no register class for type");
22440 mask
= arch_regcm_normalize(state
, mask
);
22444 static int is_imm32(struct triple
*imm
)
22446 // second condition commented out to prevent compiler warning:
22447 // imm->u.cval is always 32bit unsigned, so the comparison is
22449 return ((imm
->op
== OP_INTCONST
) /* && (imm->u.cval <= 0xffffffffUL) */ ) ||
22450 (imm
->op
== OP_ADDRCONST
);
22453 static int is_imm16(struct triple
*imm
)
22455 return ((imm
->op
== OP_INTCONST
) && (imm
->u
.cval
<= 0xffff));
22457 static int is_imm8(struct triple
*imm
)
22459 return ((imm
->op
== OP_INTCONST
) && (imm
->u
.cval
<= 0xff));
22462 static int get_imm32(struct triple
*ins
, struct triple
**expr
)
22464 struct triple
*imm
;
22466 while(imm
->op
== OP_COPY
) {
22469 if (!is_imm32(imm
)) {
22472 unuse_triple(*expr
, ins
);
22473 use_triple(imm
, ins
);
22478 static int get_imm8(struct triple
*ins
, struct triple
**expr
)
22480 struct triple
*imm
;
22482 while(imm
->op
== OP_COPY
) {
22485 if (!is_imm8(imm
)) {
22488 unuse_triple(*expr
, ins
);
22489 use_triple(imm
, ins
);
22494 #define TEMPLATE_NOP 0
22495 #define TEMPLATE_INTCONST8 1
22496 #define TEMPLATE_INTCONST32 2
22497 #define TEMPLATE_UNKNOWNVAL 3
22498 #define TEMPLATE_COPY8_REG 5
22499 #define TEMPLATE_COPY16_REG 6
22500 #define TEMPLATE_COPY32_REG 7
22501 #define TEMPLATE_COPY_IMM8 8
22502 #define TEMPLATE_COPY_IMM16 9
22503 #define TEMPLATE_COPY_IMM32 10
22504 #define TEMPLATE_PHI8 11
22505 #define TEMPLATE_PHI16 12
22506 #define TEMPLATE_PHI32 13
22507 #define TEMPLATE_STORE8 14
22508 #define TEMPLATE_STORE16 15
22509 #define TEMPLATE_STORE32 16
22510 #define TEMPLATE_LOAD8 17
22511 #define TEMPLATE_LOAD16 18
22512 #define TEMPLATE_LOAD32 19
22513 #define TEMPLATE_BINARY8_REG 20
22514 #define TEMPLATE_BINARY16_REG 21
22515 #define TEMPLATE_BINARY32_REG 22
22516 #define TEMPLATE_BINARY8_IMM 23
22517 #define TEMPLATE_BINARY16_IMM 24
22518 #define TEMPLATE_BINARY32_IMM 25
22519 #define TEMPLATE_SL8_CL 26
22520 #define TEMPLATE_SL16_CL 27
22521 #define TEMPLATE_SL32_CL 28
22522 #define TEMPLATE_SL8_IMM 29
22523 #define TEMPLATE_SL16_IMM 30
22524 #define TEMPLATE_SL32_IMM 31
22525 #define TEMPLATE_UNARY8 32
22526 #define TEMPLATE_UNARY16 33
22527 #define TEMPLATE_UNARY32 34
22528 #define TEMPLATE_CMP8_REG 35
22529 #define TEMPLATE_CMP16_REG 36
22530 #define TEMPLATE_CMP32_REG 37
22531 #define TEMPLATE_CMP8_IMM 38
22532 #define TEMPLATE_CMP16_IMM 39
22533 #define TEMPLATE_CMP32_IMM 40
22534 #define TEMPLATE_TEST8 41
22535 #define TEMPLATE_TEST16 42
22536 #define TEMPLATE_TEST32 43
22537 #define TEMPLATE_SET 44
22538 #define TEMPLATE_JMP 45
22539 #define TEMPLATE_RET 46
22540 #define TEMPLATE_INB_DX 47
22541 #define TEMPLATE_INB_IMM 48
22542 #define TEMPLATE_INW_DX 49
22543 #define TEMPLATE_INW_IMM 50
22544 #define TEMPLATE_INL_DX 51
22545 #define TEMPLATE_INL_IMM 52
22546 #define TEMPLATE_OUTB_DX 53
22547 #define TEMPLATE_OUTB_IMM 54
22548 #define TEMPLATE_OUTW_DX 55
22549 #define TEMPLATE_OUTW_IMM 56
22550 #define TEMPLATE_OUTL_DX 57
22551 #define TEMPLATE_OUTL_IMM 58
22552 #define TEMPLATE_BSF 59
22553 #define TEMPLATE_RDMSR 60
22554 #define TEMPLATE_WRMSR 61
22555 #define TEMPLATE_UMUL8 62
22556 #define TEMPLATE_UMUL16 63
22557 #define TEMPLATE_UMUL32 64
22558 #define TEMPLATE_DIV8 65
22559 #define TEMPLATE_DIV16 66
22560 #define TEMPLATE_DIV32 67
22561 #define LAST_TEMPLATE TEMPLATE_DIV32
22562 #if LAST_TEMPLATE >= MAX_TEMPLATES
22563 #error "MAX_TEMPLATES to low"
22566 #define COPY8_REGCM (REGCM_DIVIDEND64 | REGCM_DIVIDEND32 | REGCM_GPR32 | REGCM_GPR16 | REGCM_GPR8_LO | REGCM_MMX | REGCM_XMM)
22567 #define COPY16_REGCM (REGCM_DIVIDEND64 | REGCM_DIVIDEND32 | REGCM_GPR32 | REGCM_GPR16 | REGCM_MMX | REGCM_XMM)
22568 #define COPY32_REGCM (REGCM_DIVIDEND64 | REGCM_DIVIDEND32 | REGCM_GPR32 | REGCM_MMX | REGCM_XMM)
22571 static struct ins_template templates
[] = {
22574 [ 0] = { REG_UNNEEDED
, REGCM_IMMALL
},
22575 [ 1] = { REG_UNNEEDED
, REGCM_IMMALL
},
22576 [ 2] = { REG_UNNEEDED
, REGCM_IMMALL
},
22577 [ 3] = { REG_UNNEEDED
, REGCM_IMMALL
},
22578 [ 4] = { REG_UNNEEDED
, REGCM_IMMALL
},
22579 [ 5] = { REG_UNNEEDED
, REGCM_IMMALL
},
22580 [ 6] = { REG_UNNEEDED
, REGCM_IMMALL
},
22581 [ 7] = { REG_UNNEEDED
, REGCM_IMMALL
},
22582 [ 8] = { REG_UNNEEDED
, REGCM_IMMALL
},
22583 [ 9] = { REG_UNNEEDED
, REGCM_IMMALL
},
22584 [10] = { REG_UNNEEDED
, REGCM_IMMALL
},
22585 [11] = { REG_UNNEEDED
, REGCM_IMMALL
},
22586 [12] = { REG_UNNEEDED
, REGCM_IMMALL
},
22587 [13] = { REG_UNNEEDED
, REGCM_IMMALL
},
22588 [14] = { REG_UNNEEDED
, REGCM_IMMALL
},
22589 [15] = { REG_UNNEEDED
, REGCM_IMMALL
},
22590 [16] = { REG_UNNEEDED
, REGCM_IMMALL
},
22591 [17] = { REG_UNNEEDED
, REGCM_IMMALL
},
22592 [18] = { REG_UNNEEDED
, REGCM_IMMALL
},
22593 [19] = { REG_UNNEEDED
, REGCM_IMMALL
},
22594 [20] = { REG_UNNEEDED
, REGCM_IMMALL
},
22595 [21] = { REG_UNNEEDED
, REGCM_IMMALL
},
22596 [22] = { REG_UNNEEDED
, REGCM_IMMALL
},
22597 [23] = { REG_UNNEEDED
, REGCM_IMMALL
},
22598 [24] = { REG_UNNEEDED
, REGCM_IMMALL
},
22599 [25] = { REG_UNNEEDED
, REGCM_IMMALL
},
22600 [26] = { REG_UNNEEDED
, REGCM_IMMALL
},
22601 [27] = { REG_UNNEEDED
, REGCM_IMMALL
},
22602 [28] = { REG_UNNEEDED
, REGCM_IMMALL
},
22603 [29] = { REG_UNNEEDED
, REGCM_IMMALL
},
22604 [30] = { REG_UNNEEDED
, REGCM_IMMALL
},
22605 [31] = { REG_UNNEEDED
, REGCM_IMMALL
},
22606 [32] = { REG_UNNEEDED
, REGCM_IMMALL
},
22607 [33] = { REG_UNNEEDED
, REGCM_IMMALL
},
22608 [34] = { REG_UNNEEDED
, REGCM_IMMALL
},
22609 [35] = { REG_UNNEEDED
, REGCM_IMMALL
},
22610 [36] = { REG_UNNEEDED
, REGCM_IMMALL
},
22611 [37] = { REG_UNNEEDED
, REGCM_IMMALL
},
22612 [38] = { REG_UNNEEDED
, REGCM_IMMALL
},
22613 [39] = { REG_UNNEEDED
, REGCM_IMMALL
},
22614 [40] = { REG_UNNEEDED
, REGCM_IMMALL
},
22615 [41] = { REG_UNNEEDED
, REGCM_IMMALL
},
22616 [42] = { REG_UNNEEDED
, REGCM_IMMALL
},
22617 [43] = { REG_UNNEEDED
, REGCM_IMMALL
},
22618 [44] = { REG_UNNEEDED
, REGCM_IMMALL
},
22619 [45] = { REG_UNNEEDED
, REGCM_IMMALL
},
22620 [46] = { REG_UNNEEDED
, REGCM_IMMALL
},
22621 [47] = { REG_UNNEEDED
, REGCM_IMMALL
},
22622 [48] = { REG_UNNEEDED
, REGCM_IMMALL
},
22623 [49] = { REG_UNNEEDED
, REGCM_IMMALL
},
22624 [50] = { REG_UNNEEDED
, REGCM_IMMALL
},
22625 [51] = { REG_UNNEEDED
, REGCM_IMMALL
},
22626 [52] = { REG_UNNEEDED
, REGCM_IMMALL
},
22627 [53] = { REG_UNNEEDED
, REGCM_IMMALL
},
22628 [54] = { REG_UNNEEDED
, REGCM_IMMALL
},
22629 [55] = { REG_UNNEEDED
, REGCM_IMMALL
},
22630 [56] = { REG_UNNEEDED
, REGCM_IMMALL
},
22631 [57] = { REG_UNNEEDED
, REGCM_IMMALL
},
22632 [58] = { REG_UNNEEDED
, REGCM_IMMALL
},
22633 [59] = { REG_UNNEEDED
, REGCM_IMMALL
},
22634 [60] = { REG_UNNEEDED
, REGCM_IMMALL
},
22635 [61] = { REG_UNNEEDED
, REGCM_IMMALL
},
22636 [62] = { REG_UNNEEDED
, REGCM_IMMALL
},
22637 [63] = { REG_UNNEEDED
, REGCM_IMMALL
},
22640 [TEMPLATE_INTCONST8
] = {
22641 .lhs
= { [0] = { REG_UNNEEDED
, REGCM_IMM8
} },
22643 [TEMPLATE_INTCONST32
] = {
22644 .lhs
= { [0] = { REG_UNNEEDED
, REGCM_IMM32
} },
22646 [TEMPLATE_UNKNOWNVAL
] = {
22647 .lhs
= { [0] = { REG_UNSET
, COPY32_REGCM
} },
22649 [TEMPLATE_COPY8_REG
] = {
22650 .lhs
= { [0] = { REG_UNSET
, COPY8_REGCM
} },
22651 .rhs
= { [0] = { REG_UNSET
, COPY8_REGCM
} },
22653 [TEMPLATE_COPY16_REG
] = {
22654 .lhs
= { [0] = { REG_UNSET
, COPY16_REGCM
} },
22655 .rhs
= { [0] = { REG_UNSET
, COPY16_REGCM
} },
22657 [TEMPLATE_COPY32_REG
] = {
22658 .lhs
= { [0] = { REG_UNSET
, COPY32_REGCM
} },
22659 .rhs
= { [0] = { REG_UNSET
, COPY32_REGCM
} },
22661 [TEMPLATE_COPY_IMM8
] = {
22662 .lhs
= { [0] = { REG_UNSET
, COPY8_REGCM
} },
22663 .rhs
= { [0] = { REG_UNNEEDED
, REGCM_IMM8
} },
22665 [TEMPLATE_COPY_IMM16
] = {
22666 .lhs
= { [0] = { REG_UNSET
, COPY16_REGCM
} },
22667 .rhs
= { [0] = { REG_UNNEEDED
, REGCM_IMM16
| REGCM_IMM8
} },
22669 [TEMPLATE_COPY_IMM32
] = {
22670 .lhs
= { [0] = { REG_UNSET
, COPY32_REGCM
} },
22671 .rhs
= { [0] = { REG_UNNEEDED
, REGCM_IMM32
| REGCM_IMM16
| REGCM_IMM8
} },
22673 [TEMPLATE_PHI8
] = {
22674 .lhs
= { [0] = { REG_VIRT0
, COPY8_REGCM
} },
22675 .rhs
= { [0] = { REG_VIRT0
, COPY8_REGCM
} },
22677 [TEMPLATE_PHI16
] = {
22678 .lhs
= { [0] = { REG_VIRT0
, COPY16_REGCM
} },
22679 .rhs
= { [0] = { REG_VIRT0
, COPY16_REGCM
} },
22681 [TEMPLATE_PHI32
] = {
22682 .lhs
= { [0] = { REG_VIRT0
, COPY32_REGCM
} },
22683 .rhs
= { [0] = { REG_VIRT0
, COPY32_REGCM
} },
22685 [TEMPLATE_STORE8
] = {
22687 [0] = { REG_UNSET
, REGCM_GPR32
},
22688 [1] = { REG_UNSET
, REGCM_GPR8_LO
},
22691 [TEMPLATE_STORE16
] = {
22693 [0] = { REG_UNSET
, REGCM_GPR32
},
22694 [1] = { REG_UNSET
, REGCM_GPR16
},
22697 [TEMPLATE_STORE32
] = {
22699 [0] = { REG_UNSET
, REGCM_GPR32
},
22700 [1] = { REG_UNSET
, REGCM_GPR32
},
22703 [TEMPLATE_LOAD8
] = {
22704 .lhs
= { [0] = { REG_UNSET
, REGCM_GPR8_LO
} },
22705 .rhs
= { [0] = { REG_UNSET
, REGCM_GPR32
} },
22707 [TEMPLATE_LOAD16
] = {
22708 .lhs
= { [0] = { REG_UNSET
, REGCM_GPR16
} },
22709 .rhs
= { [0] = { REG_UNSET
, REGCM_GPR32
} },
22711 [TEMPLATE_LOAD32
] = {
22712 .lhs
= { [0] = { REG_UNSET
, REGCM_GPR32
} },
22713 .rhs
= { [0] = { REG_UNSET
, REGCM_GPR32
} },
22715 [TEMPLATE_BINARY8_REG
] = {
22716 .lhs
= { [0] = { REG_VIRT0
, REGCM_GPR8_LO
} },
22718 [0] = { REG_VIRT0
, REGCM_GPR8_LO
},
22719 [1] = { REG_UNSET
, REGCM_GPR8_LO
},
22722 [TEMPLATE_BINARY16_REG
] = {
22723 .lhs
= { [0] = { REG_VIRT0
, REGCM_GPR16
} },
22725 [0] = { REG_VIRT0
, REGCM_GPR16
},
22726 [1] = { REG_UNSET
, REGCM_GPR16
},
22729 [TEMPLATE_BINARY32_REG
] = {
22730 .lhs
= { [0] = { REG_VIRT0
, REGCM_GPR32
} },
22732 [0] = { REG_VIRT0
, REGCM_GPR32
},
22733 [1] = { REG_UNSET
, REGCM_GPR32
},
22736 [TEMPLATE_BINARY8_IMM
] = {
22737 .lhs
= { [0] = { REG_VIRT0
, REGCM_GPR8_LO
} },
22739 [0] = { REG_VIRT0
, REGCM_GPR8_LO
},
22740 [1] = { REG_UNNEEDED
, REGCM_IMM8
},
22743 [TEMPLATE_BINARY16_IMM
] = {
22744 .lhs
= { [0] = { REG_VIRT0
, REGCM_GPR16
} },
22746 [0] = { REG_VIRT0
, REGCM_GPR16
},
22747 [1] = { REG_UNNEEDED
, REGCM_IMM16
},
22750 [TEMPLATE_BINARY32_IMM
] = {
22751 .lhs
= { [0] = { REG_VIRT0
, REGCM_GPR32
} },
22753 [0] = { REG_VIRT0
, REGCM_GPR32
},
22754 [1] = { REG_UNNEEDED
, REGCM_IMM32
},
22757 [TEMPLATE_SL8_CL
] = {
22758 .lhs
= { [0] = { REG_VIRT0
, REGCM_GPR8_LO
} },
22760 [0] = { REG_VIRT0
, REGCM_GPR8_LO
},
22761 [1] = { REG_CL
, REGCM_GPR8_LO
},
22764 [TEMPLATE_SL16_CL
] = {
22765 .lhs
= { [0] = { REG_VIRT0
, REGCM_GPR16
} },
22767 [0] = { REG_VIRT0
, REGCM_GPR16
},
22768 [1] = { REG_CL
, REGCM_GPR8_LO
},
22771 [TEMPLATE_SL32_CL
] = {
22772 .lhs
= { [0] = { REG_VIRT0
, REGCM_GPR32
} },
22774 [0] = { REG_VIRT0
, REGCM_GPR32
},
22775 [1] = { REG_CL
, REGCM_GPR8_LO
},
22778 [TEMPLATE_SL8_IMM
] = {
22779 .lhs
= { [0] = { REG_VIRT0
, REGCM_GPR8_LO
} },
22781 [0] = { REG_VIRT0
, REGCM_GPR8_LO
},
22782 [1] = { REG_UNNEEDED
, REGCM_IMM8
},
22785 [TEMPLATE_SL16_IMM
] = {
22786 .lhs
= { [0] = { REG_VIRT0
, REGCM_GPR16
} },
22788 [0] = { REG_VIRT0
, REGCM_GPR16
},
22789 [1] = { REG_UNNEEDED
, REGCM_IMM8
},
22792 [TEMPLATE_SL32_IMM
] = {
22793 .lhs
= { [0] = { REG_VIRT0
, REGCM_GPR32
} },
22795 [0] = { REG_VIRT0
, REGCM_GPR32
},
22796 [1] = { REG_UNNEEDED
, REGCM_IMM8
},
22799 [TEMPLATE_UNARY8
] = {
22800 .lhs
= { [0] = { REG_VIRT0
, REGCM_GPR8_LO
} },
22801 .rhs
= { [0] = { REG_VIRT0
, REGCM_GPR8_LO
} },
22803 [TEMPLATE_UNARY16
] = {
22804 .lhs
= { [0] = { REG_VIRT0
, REGCM_GPR16
} },
22805 .rhs
= { [0] = { REG_VIRT0
, REGCM_GPR16
} },
22807 [TEMPLATE_UNARY32
] = {
22808 .lhs
= { [0] = { REG_VIRT0
, REGCM_GPR32
} },
22809 .rhs
= { [0] = { REG_VIRT0
, REGCM_GPR32
} },
22811 [TEMPLATE_CMP8_REG
] = {
22812 .lhs
= { [0] = { REG_EFLAGS
, REGCM_FLAGS
} },
22814 [0] = { REG_UNSET
, REGCM_GPR8_LO
},
22815 [1] = { REG_UNSET
, REGCM_GPR8_LO
},
22818 [TEMPLATE_CMP16_REG
] = {
22819 .lhs
= { [0] = { REG_EFLAGS
, REGCM_FLAGS
} },
22821 [0] = { REG_UNSET
, REGCM_GPR16
},
22822 [1] = { REG_UNSET
, REGCM_GPR16
},
22825 [TEMPLATE_CMP32_REG
] = {
22826 .lhs
= { [0] = { REG_EFLAGS
, REGCM_FLAGS
} },
22828 [0] = { REG_UNSET
, REGCM_GPR32
},
22829 [1] = { REG_UNSET
, REGCM_GPR32
},
22832 [TEMPLATE_CMP8_IMM
] = {
22833 .lhs
= { [0] = { REG_EFLAGS
, REGCM_FLAGS
} },
22835 [0] = { REG_UNSET
, REGCM_GPR8_LO
},
22836 [1] = { REG_UNNEEDED
, REGCM_IMM8
},
22839 [TEMPLATE_CMP16_IMM
] = {
22840 .lhs
= { [0] = { REG_EFLAGS
, REGCM_FLAGS
} },
22842 [0] = { REG_UNSET
, REGCM_GPR16
},
22843 [1] = { REG_UNNEEDED
, REGCM_IMM16
},
22846 [TEMPLATE_CMP32_IMM
] = {
22847 .lhs
= { [0] = { REG_EFLAGS
, REGCM_FLAGS
} },
22849 [0] = { REG_UNSET
, REGCM_GPR32
},
22850 [1] = { REG_UNNEEDED
, REGCM_IMM32
},
22853 [TEMPLATE_TEST8
] = {
22854 .lhs
= { [0] = { REG_EFLAGS
, REGCM_FLAGS
} },
22855 .rhs
= { [0] = { REG_UNSET
, REGCM_GPR8_LO
} },
22857 [TEMPLATE_TEST16
] = {
22858 .lhs
= { [0] = { REG_EFLAGS
, REGCM_FLAGS
} },
22859 .rhs
= { [0] = { REG_UNSET
, REGCM_GPR16
} },
22861 [TEMPLATE_TEST32
] = {
22862 .lhs
= { [0] = { REG_EFLAGS
, REGCM_FLAGS
} },
22863 .rhs
= { [0] = { REG_UNSET
, REGCM_GPR32
} },
22866 .lhs
= { [0] = { REG_UNSET
, REGCM_GPR8_LO
} },
22867 .rhs
= { [0] = { REG_EFLAGS
, REGCM_FLAGS
} },
22870 .rhs
= { [0] = { REG_EFLAGS
, REGCM_FLAGS
} },
22873 .rhs
= { [0] = { REG_UNSET
, REGCM_GPR32
} },
22875 [TEMPLATE_INB_DX
] = {
22876 .lhs
= { [0] = { REG_AL
, REGCM_GPR8_LO
} },
22877 .rhs
= { [0] = { REG_DX
, REGCM_GPR16
} },
22879 [TEMPLATE_INB_IMM
] = {
22880 .lhs
= { [0] = { REG_AL
, REGCM_GPR8_LO
} },
22881 .rhs
= { [0] = { REG_UNNEEDED
, REGCM_IMM8
} },
22883 [TEMPLATE_INW_DX
] = {
22884 .lhs
= { [0] = { REG_AX
, REGCM_GPR16
} },
22885 .rhs
= { [0] = { REG_DX
, REGCM_GPR16
} },
22887 [TEMPLATE_INW_IMM
] = {
22888 .lhs
= { [0] = { REG_AX
, REGCM_GPR16
} },
22889 .rhs
= { [0] = { REG_UNNEEDED
, REGCM_IMM8
} },
22891 [TEMPLATE_INL_DX
] = {
22892 .lhs
= { [0] = { REG_EAX
, REGCM_GPR32
} },
22893 .rhs
= { [0] = { REG_DX
, REGCM_GPR16
} },
22895 [TEMPLATE_INL_IMM
] = {
22896 .lhs
= { [0] = { REG_EAX
, REGCM_GPR32
} },
22897 .rhs
= { [0] = { REG_UNNEEDED
, REGCM_IMM8
} },
22899 [TEMPLATE_OUTB_DX
] = {
22901 [0] = { REG_AL
, REGCM_GPR8_LO
},
22902 [1] = { REG_DX
, REGCM_GPR16
},
22905 [TEMPLATE_OUTB_IMM
] = {
22907 [0] = { REG_AL
, REGCM_GPR8_LO
},
22908 [1] = { REG_UNNEEDED
, REGCM_IMM8
},
22911 [TEMPLATE_OUTW_DX
] = {
22913 [0] = { REG_AX
, REGCM_GPR16
},
22914 [1] = { REG_DX
, REGCM_GPR16
},
22917 [TEMPLATE_OUTW_IMM
] = {
22919 [0] = { REG_AX
, REGCM_GPR16
},
22920 [1] = { REG_UNNEEDED
, REGCM_IMM8
},
22923 [TEMPLATE_OUTL_DX
] = {
22925 [0] = { REG_EAX
, REGCM_GPR32
},
22926 [1] = { REG_DX
, REGCM_GPR16
},
22929 [TEMPLATE_OUTL_IMM
] = {
22931 [0] = { REG_EAX
, REGCM_GPR32
},
22932 [1] = { REG_UNNEEDED
, REGCM_IMM8
},
22936 .lhs
= { [0] = { REG_UNSET
, REGCM_GPR32
} },
22937 .rhs
= { [0] = { REG_UNSET
, REGCM_GPR32
} },
22939 [TEMPLATE_RDMSR
] = {
22941 [0] = { REG_EAX
, REGCM_GPR32
},
22942 [1] = { REG_EDX
, REGCM_GPR32
},
22944 .rhs
= { [0] = { REG_ECX
, REGCM_GPR32
} },
22946 [TEMPLATE_WRMSR
] = {
22948 [0] = { REG_ECX
, REGCM_GPR32
},
22949 [1] = { REG_EAX
, REGCM_GPR32
},
22950 [2] = { REG_EDX
, REGCM_GPR32
},
22953 [TEMPLATE_UMUL8
] = {
22954 .lhs
= { [0] = { REG_AX
, REGCM_GPR16
} },
22956 [0] = { REG_AL
, REGCM_GPR8_LO
},
22957 [1] = { REG_UNSET
, REGCM_GPR8_LO
},
22960 [TEMPLATE_UMUL16
] = {
22961 .lhs
= { [0] = { REG_DXAX
, REGCM_DIVIDEND32
} },
22963 [0] = { REG_AX
, REGCM_GPR16
},
22964 [1] = { REG_UNSET
, REGCM_GPR16
},
22967 [TEMPLATE_UMUL32
] = {
22968 .lhs
= { [0] = { REG_EDXEAX
, REGCM_DIVIDEND64
} },
22970 [0] = { REG_EAX
, REGCM_GPR32
},
22971 [1] = { REG_UNSET
, REGCM_GPR32
},
22974 [TEMPLATE_DIV8
] = {
22976 [0] = { REG_AL
, REGCM_GPR8_LO
},
22977 [1] = { REG_AH
, REGCM_GPR8
},
22980 [0] = { REG_AX
, REGCM_GPR16
},
22981 [1] = { REG_UNSET
, REGCM_GPR8_LO
},
22984 [TEMPLATE_DIV16
] = {
22986 [0] = { REG_AX
, REGCM_GPR16
},
22987 [1] = { REG_DX
, REGCM_GPR16
},
22990 [0] = { REG_DXAX
, REGCM_DIVIDEND32
},
22991 [1] = { REG_UNSET
, REGCM_GPR16
},
22994 [TEMPLATE_DIV32
] = {
22996 [0] = { REG_EAX
, REGCM_GPR32
},
22997 [1] = { REG_EDX
, REGCM_GPR32
},
23000 [0] = { REG_EDXEAX
, REGCM_DIVIDEND64
},
23001 [1] = { REG_UNSET
, REGCM_GPR32
},
23006 static void fixup_branch(struct compile_state
*state
,
23007 struct triple
*branch
, int jmp_op
, int cmp_op
, struct type
*cmp_type
,
23008 struct triple
*left
, struct triple
*right
)
23010 struct triple
*test
;
23012 internal_error(state
, branch
, "no branch test?");
23014 test
= pre_triple(state
, branch
,
23015 cmp_op
, cmp_type
, left
, right
);
23016 test
->template_id
= TEMPLATE_TEST32
;
23017 if (cmp_op
== OP_CMP
) {
23018 test
->template_id
= TEMPLATE_CMP32_REG
;
23019 if (get_imm32(test
, &RHS(test
, 1))) {
23020 test
->template_id
= TEMPLATE_CMP32_IMM
;
23023 use_triple(RHS(test
, 0), test
);
23024 use_triple(RHS(test
, 1), test
);
23025 unuse_triple(RHS(branch
, 0), branch
);
23026 RHS(branch
, 0) = test
;
23027 branch
->op
= jmp_op
;
23028 branch
->template_id
= TEMPLATE_JMP
;
23029 use_triple(RHS(branch
, 0), branch
);
23032 static void fixup_branches(struct compile_state
*state
,
23033 struct triple
*cmp
, struct triple
*use
, int jmp_op
)
23035 struct triple_set
*entry
, *next
;
23036 for(entry
= use
->use
; entry
; entry
= next
) {
23037 next
= entry
->next
;
23038 if (entry
->member
->op
== OP_COPY
) {
23039 fixup_branches(state
, cmp
, entry
->member
, jmp_op
);
23041 else if (entry
->member
->op
== OP_CBRANCH
) {
23042 struct triple
*branch
;
23043 struct triple
*left
, *right
;
23045 left
= RHS(cmp
, 0);
23046 if (cmp
->rhs
> 1) {
23047 right
= RHS(cmp
, 1);
23049 branch
= entry
->member
;
23050 fixup_branch(state
, branch
, jmp_op
,
23051 cmp
->op
, cmp
->type
, left
, right
);
23056 static void bool_cmp(struct compile_state
*state
,
23057 struct triple
*ins
, int cmp_op
, int jmp_op
, int set_op
)
23059 struct triple_set
*entry
, *next
;
23060 struct triple
*set
, *convert
;
23062 /* Put a barrier up before the cmp which preceeds the
23063 * copy instruction. If a set actually occurs this gives
23064 * us a chance to move variables in registers out of the way.
23067 /* Modify the comparison operator */
23069 ins
->template_id
= TEMPLATE_TEST32
;
23070 if (cmp_op
== OP_CMP
) {
23071 ins
->template_id
= TEMPLATE_CMP32_REG
;
23072 if (get_imm32(ins
, &RHS(ins
, 1))) {
23073 ins
->template_id
= TEMPLATE_CMP32_IMM
;
23076 /* Generate the instruction sequence that will transform the
23077 * result of the comparison into a logical value.
23079 set
= post_triple(state
, ins
, set_op
, &uchar_type
, ins
, 0);
23080 use_triple(ins
, set
);
23081 set
->template_id
= TEMPLATE_SET
;
23084 if (!equiv_types(ins
->type
, set
->type
)) {
23085 convert
= post_triple(state
, set
, OP_CONVERT
, ins
->type
, set
, 0);
23086 use_triple(set
, convert
);
23087 convert
->template_id
= TEMPLATE_COPY32_REG
;
23090 for(entry
= ins
->use
; entry
; entry
= next
) {
23091 next
= entry
->next
;
23092 if (entry
->member
== set
) {
23095 replace_rhs_use(state
, ins
, convert
, entry
->member
);
23097 fixup_branches(state
, ins
, convert
, jmp_op
);
23100 struct reg_info
arch_reg_lhs(struct compile_state
*state
, struct triple
*ins
, int index
)
23102 struct ins_template
*template;
23103 struct reg_info result
;
23105 if (ins
->op
== OP_PIECE
) {
23106 index
= ins
->u
.cval
;
23107 ins
= MISC(ins
, 0);
23110 if (triple_is_def(state
, ins
)) {
23113 if (index
>= zlhs
) {
23114 internal_error(state
, ins
, "index %d out of range for %s",
23115 index
, tops(ins
->op
));
23119 template = &ins
->u
.ainfo
->tmpl
;
23122 if (ins
->template_id
> LAST_TEMPLATE
) {
23123 internal_error(state
, ins
, "bad template number %d",
23126 template = &templates
[ins
->template_id
];
23129 result
= template->lhs
[index
];
23130 result
.regcm
= arch_regcm_normalize(state
, result
.regcm
);
23131 if (result
.reg
!= REG_UNNEEDED
) {
23132 result
.regcm
&= ~(REGCM_IMM32
| REGCM_IMM16
| REGCM_IMM8
);
23134 if (result
.regcm
== 0) {
23135 internal_error(state
, ins
, "lhs %d regcm == 0", index
);
23140 struct reg_info
arch_reg_rhs(struct compile_state
*state
, struct triple
*ins
, int index
)
23142 struct reg_info result
;
23143 struct ins_template
*template;
23144 if ((index
> ins
->rhs
) ||
23145 (ins
->op
== OP_PIECE
)) {
23146 internal_error(state
, ins
, "index %d out of range for %s\n",
23147 index
, tops(ins
->op
));
23151 template = &ins
->u
.ainfo
->tmpl
;
23157 if (ins
->template_id
> LAST_TEMPLATE
) {
23158 internal_error(state
, ins
, "bad template number %d",
23161 template = &templates
[ins
->template_id
];
23164 result
= template->rhs
[index
];
23165 result
.regcm
= arch_regcm_normalize(state
, result
.regcm
);
23166 if (result
.regcm
== 0) {
23167 internal_error(state
, ins
, "rhs %d regcm == 0", index
);
23172 static struct triple
*mod_div(struct compile_state
*state
,
23173 struct triple
*ins
, int div_op
, int index
)
23175 struct triple
*div
, *piece1
;
23177 /* Generate the appropriate division instruction */
23178 div
= post_triple(state
, ins
, div_op
, ins
->type
, 0, 0);
23179 RHS(div
, 0) = RHS(ins
, 0);
23180 RHS(div
, 1) = RHS(ins
, 1);
23181 piece1
= LHS(div
, 1);
23182 div
->template_id
= TEMPLATE_DIV32
;
23183 use_triple(RHS(div
, 0), div
);
23184 use_triple(RHS(div
, 1), div
);
23185 use_triple(LHS(div
, 0), div
);
23186 use_triple(LHS(div
, 1), div
);
23188 /* Replate uses of ins with the appropriate piece of the div */
23189 propogate_use(state
, ins
, LHS(div
, index
));
23190 release_triple(state
, ins
);
23192 /* Return the address of the next instruction */
23193 return piece1
->next
;
23196 static int noop_adecl(struct triple
*adecl
)
23198 struct triple_set
*use
;
23199 /* It's a noop if it doesn't specify stoorage */
23200 if (adecl
->lhs
== 0) {
23203 /* Is the adecl used? If not it's a noop */
23204 for(use
= adecl
->use
; use
; use
= use
->next
) {
23205 if ((use
->member
->op
!= OP_PIECE
) ||
23206 (MISC(use
->member
, 0) != adecl
)) {
23213 static struct triple
*x86_deposit(struct compile_state
*state
, struct triple
*ins
)
23215 struct triple
*mask
, *nmask
, *shift
;
23216 struct triple
*val
, *val_mask
, *val_shift
;
23217 struct triple
*targ
, *targ_mask
;
23218 struct triple
*new;
23219 ulong_t the_mask
, the_nmask
;
23221 targ
= RHS(ins
, 0);
23224 /* Get constant for the mask value */
23226 the_mask
<<= ins
->u
.bitfield
.size
;
23228 the_mask
<<= ins
->u
.bitfield
.offset
;
23229 mask
= pre_triple(state
, ins
, OP_INTCONST
, &uint_type
, 0, 0);
23230 mask
->u
.cval
= the_mask
;
23232 /* Get the inverted mask value */
23233 the_nmask
= ~the_mask
;
23234 nmask
= pre_triple(state
, ins
, OP_INTCONST
, &uint_type
, 0, 0);
23235 nmask
->u
.cval
= the_nmask
;
23237 /* Get constant for the shift value */
23238 shift
= pre_triple(state
, ins
, OP_INTCONST
, &uint_type
, 0, 0);
23239 shift
->u
.cval
= ins
->u
.bitfield
.offset
;
23241 /* Shift and mask the source value */
23243 if (shift
->u
.cval
!= 0) {
23244 val_shift
= pre_triple(state
, ins
, OP_SL
, val
->type
, val
, shift
);
23245 use_triple(val
, val_shift
);
23246 use_triple(shift
, val_shift
);
23248 val_mask
= val_shift
;
23249 if (is_signed(val
->type
)) {
23250 val_mask
= pre_triple(state
, ins
, OP_AND
, val
->type
, val_shift
, mask
);
23251 use_triple(val_shift
, val_mask
);
23252 use_triple(mask
, val_mask
);
23255 /* Mask the target value */
23256 targ_mask
= pre_triple(state
, ins
, OP_AND
, targ
->type
, targ
, nmask
);
23257 use_triple(targ
, targ_mask
);
23258 use_triple(nmask
, targ_mask
);
23260 /* Now combined them together */
23261 new = pre_triple(state
, ins
, OP_OR
, targ
->type
, targ_mask
, val_mask
);
23262 use_triple(targ_mask
, new);
23263 use_triple(val_mask
, new);
23265 /* Move all of the users over to the new expression */
23266 propogate_use(state
, ins
, new);
23268 /* Delete the original triple */
23269 release_triple(state
, ins
);
23271 /* Restart the transformation at mask */
23275 static struct triple
*x86_extract(struct compile_state
*state
, struct triple
*ins
)
23277 struct triple
*mask
, *shift
;
23278 struct triple
*val
, *val_mask
, *val_shift
;
23283 /* Get constant for the mask value */
23285 the_mask
<<= ins
->u
.bitfield
.size
;
23287 mask
= pre_triple(state
, ins
, OP_INTCONST
, &int_type
, 0, 0);
23288 mask
->u
.cval
= the_mask
;
23290 /* Get constant for the right shift value */
23291 shift
= pre_triple(state
, ins
, OP_INTCONST
, &int_type
, 0, 0);
23292 shift
->u
.cval
= ins
->u
.bitfield
.offset
;
23294 /* Shift arithmetic right, to correct the sign */
23296 if (shift
->u
.cval
!= 0) {
23298 if (ins
->op
== OP_SEXTRACT
) {
23303 val_shift
= pre_triple(state
, ins
, op
, val
->type
, val
, shift
);
23304 use_triple(val
, val_shift
);
23305 use_triple(shift
, val_shift
);
23308 /* Finally mask the value */
23309 val_mask
= pre_triple(state
, ins
, OP_AND
, ins
->type
, val_shift
, mask
);
23310 use_triple(val_shift
, val_mask
);
23311 use_triple(mask
, val_mask
);
23313 /* Move all of the users over to the new expression */
23314 propogate_use(state
, ins
, val_mask
);
23316 /* Release the original instruction */
23317 release_triple(state
, ins
);
23323 static struct triple
*transform_to_arch_instruction(
23324 struct compile_state
*state
, struct triple
*ins
)
23326 /* Transform from generic 3 address instructions
23327 * to archtecture specific instructions.
23328 * And apply architecture specific constraints to instructions.
23329 * Copies are inserted to preserve the register flexibility
23330 * of 3 address instructions.
23332 struct triple
*next
, *value
;
23337 ins
->template_id
= TEMPLATE_INTCONST32
;
23338 if (ins
->u
.cval
< 256) {
23339 ins
->template_id
= TEMPLATE_INTCONST8
;
23343 ins
->template_id
= TEMPLATE_INTCONST32
;
23345 case OP_UNKNOWNVAL
:
23346 ins
->template_id
= TEMPLATE_UNKNOWNVAL
;
23352 ins
->template_id
= TEMPLATE_NOP
;
23356 size
= size_of(state
, ins
->type
);
23357 value
= RHS(ins
, 0);
23358 if (is_imm8(value
) && (size
<= SIZEOF_I8
)) {
23359 ins
->template_id
= TEMPLATE_COPY_IMM8
;
23361 else if (is_imm16(value
) && (size
<= SIZEOF_I16
)) {
23362 ins
->template_id
= TEMPLATE_COPY_IMM16
;
23364 else if (is_imm32(value
) && (size
<= SIZEOF_I32
)) {
23365 ins
->template_id
= TEMPLATE_COPY_IMM32
;
23367 else if (is_const(value
)) {
23368 internal_error(state
, ins
, "bad constant passed to copy");
23370 else if (size
<= SIZEOF_I8
) {
23371 ins
->template_id
= TEMPLATE_COPY8_REG
;
23373 else if (size
<= SIZEOF_I16
) {
23374 ins
->template_id
= TEMPLATE_COPY16_REG
;
23376 else if (size
<= SIZEOF_I32
) {
23377 ins
->template_id
= TEMPLATE_COPY32_REG
;
23380 internal_error(state
, ins
, "bad type passed to copy");
23384 size
= size_of(state
, ins
->type
);
23385 if (size
<= SIZEOF_I8
) {
23386 ins
->template_id
= TEMPLATE_PHI8
;
23388 else if (size
<= SIZEOF_I16
) {
23389 ins
->template_id
= TEMPLATE_PHI16
;
23391 else if (size
<= SIZEOF_I32
) {
23392 ins
->template_id
= TEMPLATE_PHI32
;
23395 internal_error(state
, ins
, "bad type passed to phi");
23399 /* Adecls should always be treated as dead code and
23400 * removed. If we are not optimizing they may linger.
23402 if (!noop_adecl(ins
)) {
23403 internal_error(state
, ins
, "adecl remains?");
23405 ins
->template_id
= TEMPLATE_NOP
;
23406 next
= after_lhs(state
, ins
);
23409 switch(ins
->type
->type
& TYPE_MASK
) {
23410 case TYPE_CHAR
: case TYPE_UCHAR
:
23411 ins
->template_id
= TEMPLATE_STORE8
;
23413 case TYPE_SHORT
: case TYPE_USHORT
:
23414 ins
->template_id
= TEMPLATE_STORE16
;
23416 case TYPE_INT
: case TYPE_UINT
:
23417 case TYPE_LONG
: case TYPE_ULONG
:
23419 ins
->template_id
= TEMPLATE_STORE32
;
23422 internal_error(state
, ins
, "unknown type in store");
23427 switch(ins
->type
->type
& TYPE_MASK
) {
23428 case TYPE_CHAR
: case TYPE_UCHAR
:
23429 case TYPE_SHORT
: case TYPE_USHORT
:
23430 case TYPE_INT
: case TYPE_UINT
:
23431 case TYPE_LONG
: case TYPE_ULONG
:
23435 internal_error(state
, ins
, "unknown type in load");
23438 ins
->template_id
= TEMPLATE_LOAD32
;
23446 ins
->template_id
= TEMPLATE_BINARY32_REG
;
23447 if (get_imm32(ins
, &RHS(ins
, 1))) {
23448 ins
->template_id
= TEMPLATE_BINARY32_IMM
;
23453 ins
->template_id
= TEMPLATE_DIV32
;
23454 next
= after_lhs(state
, ins
);
23457 ins
->template_id
= TEMPLATE_UMUL32
;
23460 next
= mod_div(state
, ins
, OP_UDIVT
, 0);
23463 next
= mod_div(state
, ins
, OP_SDIVT
, 0);
23466 next
= mod_div(state
, ins
, OP_UDIVT
, 1);
23469 next
= mod_div(state
, ins
, OP_SDIVT
, 1);
23474 ins
->template_id
= TEMPLATE_SL32_CL
;
23475 if (get_imm8(ins
, &RHS(ins
, 1))) {
23476 ins
->template_id
= TEMPLATE_SL32_IMM
;
23477 } else if (size_of(state
, RHS(ins
, 1)->type
) > SIZEOF_CHAR
) {
23478 typed_pre_copy(state
, &uchar_type
, ins
, 1);
23483 ins
->template_id
= TEMPLATE_UNARY32
;
23486 bool_cmp(state
, ins
, OP_CMP
, OP_JMP_EQ
, OP_SET_EQ
);
23489 bool_cmp(state
, ins
, OP_CMP
, OP_JMP_NOTEQ
, OP_SET_NOTEQ
);
23492 bool_cmp(state
, ins
, OP_CMP
, OP_JMP_SLESS
, OP_SET_SLESS
);
23495 bool_cmp(state
, ins
, OP_CMP
, OP_JMP_ULESS
, OP_SET_ULESS
);
23498 bool_cmp(state
, ins
, OP_CMP
, OP_JMP_SMORE
, OP_SET_SMORE
);
23501 bool_cmp(state
, ins
, OP_CMP
, OP_JMP_UMORE
, OP_SET_UMORE
);
23504 bool_cmp(state
, ins
, OP_CMP
, OP_JMP_SLESSEQ
, OP_SET_SLESSEQ
);
23507 bool_cmp(state
, ins
, OP_CMP
, OP_JMP_ULESSEQ
, OP_SET_ULESSEQ
);
23510 bool_cmp(state
, ins
, OP_CMP
, OP_JMP_SMOREEQ
, OP_SET_SMOREEQ
);
23513 bool_cmp(state
, ins
, OP_CMP
, OP_JMP_UMOREEQ
, OP_SET_UMOREEQ
);
23516 bool_cmp(state
, ins
, OP_TEST
, OP_JMP_NOTEQ
, OP_SET_NOTEQ
);
23519 bool_cmp(state
, ins
, OP_TEST
, OP_JMP_EQ
, OP_SET_EQ
);
23523 ins
->template_id
= TEMPLATE_NOP
;
23526 fixup_branch(state
, ins
, OP_JMP_NOTEQ
, OP_TEST
,
23527 RHS(ins
, 0)->type
, RHS(ins
, 0), 0);
23530 ins
->template_id
= TEMPLATE_NOP
;
23533 ins
->template_id
= TEMPLATE_RET
;
23539 case OP_INB
: ins
->template_id
= TEMPLATE_INB_DX
; break;
23540 case OP_INW
: ins
->template_id
= TEMPLATE_INW_DX
; break;
23541 case OP_INL
: ins
->template_id
= TEMPLATE_INL_DX
; break;
23543 if (get_imm8(ins
, &RHS(ins
, 0))) {
23544 ins
->template_id
+= 1;
23551 case OP_OUTB
: ins
->template_id
= TEMPLATE_OUTB_DX
; break;
23552 case OP_OUTW
: ins
->template_id
= TEMPLATE_OUTW_DX
; break;
23553 case OP_OUTL
: ins
->template_id
= TEMPLATE_OUTL_DX
; break;
23555 if (get_imm8(ins
, &RHS(ins
, 1))) {
23556 ins
->template_id
+= 1;
23561 ins
->template_id
= TEMPLATE_BSF
;
23564 ins
->template_id
= TEMPLATE_RDMSR
;
23565 next
= after_lhs(state
, ins
);
23568 ins
->template_id
= TEMPLATE_WRMSR
;
23571 ins
->template_id
= TEMPLATE_NOP
;
23574 ins
->template_id
= TEMPLATE_NOP
;
23575 next
= after_lhs(state
, ins
);
23577 /* Already transformed instructions */
23579 ins
->template_id
= TEMPLATE_TEST32
;
23582 ins
->template_id
= TEMPLATE_CMP32_REG
;
23583 if (get_imm32(ins
, &RHS(ins
, 1))) {
23584 ins
->template_id
= TEMPLATE_CMP32_IMM
;
23588 ins
->template_id
= TEMPLATE_NOP
;
23590 case OP_JMP_EQ
: case OP_JMP_NOTEQ
:
23591 case OP_JMP_SLESS
: case OP_JMP_ULESS
:
23592 case OP_JMP_SMORE
: case OP_JMP_UMORE
:
23593 case OP_JMP_SLESSEQ
: case OP_JMP_ULESSEQ
:
23594 case OP_JMP_SMOREEQ
: case OP_JMP_UMOREEQ
:
23595 ins
->template_id
= TEMPLATE_JMP
;
23597 case OP_SET_EQ
: case OP_SET_NOTEQ
:
23598 case OP_SET_SLESS
: case OP_SET_ULESS
:
23599 case OP_SET_SMORE
: case OP_SET_UMORE
:
23600 case OP_SET_SLESSEQ
: case OP_SET_ULESSEQ
:
23601 case OP_SET_SMOREEQ
: case OP_SET_UMOREEQ
:
23602 ins
->template_id
= TEMPLATE_SET
;
23605 next
= x86_deposit(state
, ins
);
23609 next
= x86_extract(state
, ins
);
23611 /* Unhandled instructions */
23614 internal_error(state
, ins
, "unhandled ins: %d %s",
23615 ins
->op
, tops(ins
->op
));
23621 static long next_label(struct compile_state
*state
)
23623 static long label_counter
= 1000;
23624 return ++label_counter
;
23626 static void generate_local_labels(struct compile_state
*state
)
23628 struct triple
*first
, *label
;
23629 first
= state
->first
;
23632 if ((label
->op
== OP_LABEL
) ||
23633 (label
->op
== OP_SDECL
)) {
23635 label
->u
.cval
= next_label(state
);
23641 label
= label
->next
;
23642 } while(label
!= first
);
23645 static int check_reg(struct compile_state
*state
,
23646 struct triple
*triple
, int classes
)
23650 reg
= ID_REG(triple
->id
);
23651 if (reg
== REG_UNSET
) {
23652 internal_error(state
, triple
, "register not set");
23654 mask
= arch_reg_regcm(state
, reg
);
23655 if (!(classes
& mask
)) {
23656 internal_error(state
, triple
, "reg %d in wrong class",
23664 #error "Registers have renumberd fix arch_reg_str"
23666 static const char *arch_regs
[] = {
23670 "%al", "%bl", "%cl", "%dl", "%ah", "%bh", "%ch", "%dh",
23671 "%ax", "%bx", "%cx", "%dx", "%si", "%di", "%bp", "%sp",
23672 "%eax", "%ebx", "%ecx", "%edx", "%esi", "%edi", "%ebp", "%esp",
23675 "%mm0", "%mm1", "%mm2", "%mm3", "%mm4", "%mm5", "%mm6", "%mm7",
23676 "%xmm0", "%xmm1", "%xmm2", "%xmm3",
23677 "%xmm4", "%xmm5", "%xmm6", "%xmm7",
23679 static const char *arch_reg_str(int reg
)
23681 if (!((reg
>= REG_EFLAGS
) && (reg
<= REG_XMM7
))) {
23684 return arch_regs
[reg
];
23687 static const char *reg(struct compile_state
*state
, struct triple
*triple
,
23691 reg
= check_reg(state
, triple
, classes
);
23692 return arch_reg_str(reg
);
23695 static int arch_reg_size(int reg
)
23699 if (reg
== REG_EFLAGS
) {
23702 else if ((reg
>= REG_AL
) && (reg
<= REG_DH
)) {
23705 else if ((reg
>= REG_AX
) && (reg
<= REG_SP
)) {
23708 else if ((reg
>= REG_EAX
) && (reg
<= REG_ESP
)) {
23711 else if (reg
== REG_EDXEAX
) {
23714 else if (reg
== REG_DXAX
) {
23717 else if ((reg
>= REG_MMX0
) && (reg
<= REG_MMX7
)) {
23720 else if ((reg
>= REG_XMM0
) && (reg
<= REG_XMM7
)) {
23726 static int reg_size(struct compile_state
*state
, struct triple
*ins
)
23729 reg
= ID_REG(ins
->id
);
23730 if (reg
== REG_UNSET
) {
23731 internal_error(state
, ins
, "register not set");
23733 return arch_reg_size(reg
);
23738 const char *type_suffix(struct compile_state
*state
, struct type
*type
)
23740 const char *suffix
;
23741 switch(size_of(state
, type
)) {
23742 case SIZEOF_I8
: suffix
= "b"; break;
23743 case SIZEOF_I16
: suffix
= "w"; break;
23744 case SIZEOF_I32
: suffix
= "l"; break;
23746 internal_error(state
, 0, "unknown suffix");
23753 static void print_const_val(
23754 struct compile_state
*state
, struct triple
*ins
, FILE *fp
)
23758 fprintf(fp
, " $%ld ",
23759 (long)(ins
->u
.cval
));
23762 if ((MISC(ins
, 0)->op
!= OP_SDECL
) &&
23763 (MISC(ins
, 0)->op
!= OP_LABEL
))
23765 internal_error(state
, ins
, "bad base for addrconst");
23767 if (MISC(ins
, 0)->u
.cval
<= 0) {
23768 internal_error(state
, ins
, "unlabeled constant");
23770 fprintf(fp
, " $L%s%lu+%lu ",
23771 state
->compiler
->label_prefix
,
23772 (unsigned long)(MISC(ins
, 0)->u
.cval
),
23773 (unsigned long)(ins
->u
.cval
));
23776 internal_error(state
, ins
, "unknown constant type");
23781 static void print_const(struct compile_state
*state
,
23782 struct triple
*ins
, FILE *fp
)
23786 switch(ins
->type
->type
& TYPE_MASK
) {
23789 fprintf(fp
, ".byte 0x%02lx\n",
23790 (unsigned long)(ins
->u
.cval
));
23794 fprintf(fp
, ".short 0x%04lx\n",
23795 (unsigned long)(ins
->u
.cval
));
23802 fprintf(fp
, ".int %lu\n",
23803 (unsigned long)(ins
->u
.cval
));
23806 fprintf(state
->errout
, "type: ");
23807 name_of(state
->errout
, ins
->type
);
23808 fprintf(state
->errout
, "\n");
23809 internal_error(state
, ins
, "Unknown constant type. Val: %lu",
23810 (unsigned long)(ins
->u
.cval
));
23815 if ((MISC(ins
, 0)->op
!= OP_SDECL
) &&
23816 (MISC(ins
, 0)->op
!= OP_LABEL
)) {
23817 internal_error(state
, ins
, "bad base for addrconst");
23819 if (MISC(ins
, 0)->u
.cval
<= 0) {
23820 internal_error(state
, ins
, "unlabeled constant");
23822 fprintf(fp
, ".int L%s%lu+%lu\n",
23823 state
->compiler
->label_prefix
,
23824 (unsigned long)(MISC(ins
, 0)->u
.cval
),
23825 (unsigned long)(ins
->u
.cval
));
23829 unsigned char *blob
;
23831 size
= size_of_in_bytes(state
, ins
->type
);
23832 blob
= ins
->u
.blob
;
23833 for(i
= 0; i
< size
; i
++) {
23834 fprintf(fp
, ".byte 0x%02x\n",
23840 internal_error(state
, ins
, "Unknown constant type");
23845 #define TEXT_SECTION ".rom.text"
23846 #define DATA_SECTION ".rom.data"
23848 static long get_const_pool_ref(
23849 struct compile_state
*state
, struct triple
*ins
, size_t size
, FILE *fp
)
23853 ref
= next_label(state
);
23854 fprintf(fp
, ".section \"" DATA_SECTION
"\"\n");
23855 fprintf(fp
, ".balign %ld\n", (long int)align_of_in_bytes(state
, ins
->type
));
23856 fprintf(fp
, "L%s%lu:\n", state
->compiler
->label_prefix
, ref
);
23857 print_const(state
, ins
, fp
);
23858 fill_bytes
= bits_to_bytes(size
- size_of(state
, ins
->type
));
23860 fprintf(fp
, ".fill %ld, 1, 0\n", (long int)fill_bytes
);
23862 fprintf(fp
, ".section \"" TEXT_SECTION
"\"\n");
23866 static long get_mask_pool_ref(
23867 struct compile_state
*state
, struct triple
*ins
, unsigned long mask
, FILE *fp
)
23870 if (mask
== 0xff) {
23873 else if (mask
== 0xffff) {
23878 internal_error(state
, ins
, "unhandled mask value");
23883 static void print_binary_op(struct compile_state
*state
,
23884 const char *op
, struct triple
*ins
, FILE *fp
)
23887 mask
= REGCM_GPR32
| REGCM_GPR16
| REGCM_GPR8_LO
;
23888 if (ID_REG(RHS(ins
, 0)->id
) != ID_REG(ins
->id
)) {
23889 internal_error(state
, ins
, "invalid register assignment");
23891 if (is_const(RHS(ins
, 1))) {
23892 fprintf(fp
, "\t%s ", op
);
23893 print_const_val(state
, RHS(ins
, 1), fp
);
23894 fprintf(fp
, ", %s\n",
23895 reg(state
, RHS(ins
, 0), mask
));
23898 unsigned lmask
, rmask
;
23900 lreg
= check_reg(state
, RHS(ins
, 0), mask
);
23901 rreg
= check_reg(state
, RHS(ins
, 1), mask
);
23902 lmask
= arch_reg_regcm(state
, lreg
);
23903 rmask
= arch_reg_regcm(state
, rreg
);
23904 mask
= lmask
& rmask
;
23905 fprintf(fp
, "\t%s %s, %s\n",
23907 reg(state
, RHS(ins
, 1), mask
),
23908 reg(state
, RHS(ins
, 0), mask
));
23911 static void print_unary_op(struct compile_state
*state
,
23912 const char *op
, struct triple
*ins
, FILE *fp
)
23915 mask
= REGCM_GPR32
| REGCM_GPR16
| REGCM_GPR8_LO
;
23916 fprintf(fp
, "\t%s %s\n",
23918 reg(state
, RHS(ins
, 0), mask
));
23921 static void print_op_shift(struct compile_state
*state
,
23922 const char *op
, struct triple
*ins
, FILE *fp
)
23925 mask
= REGCM_GPR32
| REGCM_GPR16
| REGCM_GPR8_LO
;
23926 if (ID_REG(RHS(ins
, 0)->id
) != ID_REG(ins
->id
)) {
23927 internal_error(state
, ins
, "invalid register assignment");
23929 if (is_const(RHS(ins
, 1))) {
23930 fprintf(fp
, "\t%s ", op
);
23931 print_const_val(state
, RHS(ins
, 1), fp
);
23932 fprintf(fp
, ", %s\n",
23933 reg(state
, RHS(ins
, 0), mask
));
23936 fprintf(fp
, "\t%s %s, %s\n",
23938 reg(state
, RHS(ins
, 1), REGCM_GPR8_LO
),
23939 reg(state
, RHS(ins
, 0), mask
));
23943 static void print_op_in(struct compile_state
*state
, struct triple
*ins
, FILE *fp
)
23950 case OP_INB
: op
= "inb", mask
= REGCM_GPR8_LO
; break;
23951 case OP_INW
: op
= "inw", mask
= REGCM_GPR16
; break;
23952 case OP_INL
: op
= "inl", mask
= REGCM_GPR32
; break;
23954 internal_error(state
, ins
, "not an in operation");
23958 dreg
= check_reg(state
, ins
, mask
);
23959 if (!reg_is_reg(state
, dreg
, REG_EAX
)) {
23960 internal_error(state
, ins
, "dst != %%eax");
23962 if (is_const(RHS(ins
, 0))) {
23963 fprintf(fp
, "\t%s ", op
);
23964 print_const_val(state
, RHS(ins
, 0), fp
);
23965 fprintf(fp
, ", %s\n",
23966 reg(state
, ins
, mask
));
23970 addr_reg
= check_reg(state
, RHS(ins
, 0), REGCM_GPR16
);
23971 if (!reg_is_reg(state
, addr_reg
, REG_DX
)) {
23972 internal_error(state
, ins
, "src != %%dx");
23974 fprintf(fp
, "\t%s %s, %s\n",
23976 reg(state
, RHS(ins
, 0), REGCM_GPR16
),
23977 reg(state
, ins
, mask
));
23981 static void print_op_out(struct compile_state
*state
, struct triple
*ins
, FILE *fp
)
23988 case OP_OUTB
: op
= "outb", mask
= REGCM_GPR8_LO
; break;
23989 case OP_OUTW
: op
= "outw", mask
= REGCM_GPR16
; break;
23990 case OP_OUTL
: op
= "outl", mask
= REGCM_GPR32
; break;
23992 internal_error(state
, ins
, "not an out operation");
23996 lreg
= check_reg(state
, RHS(ins
, 0), mask
);
23997 if (!reg_is_reg(state
, lreg
, REG_EAX
)) {
23998 internal_error(state
, ins
, "src != %%eax");
24000 if (is_const(RHS(ins
, 1))) {
24001 fprintf(fp
, "\t%s %s,",
24002 op
, reg(state
, RHS(ins
, 0), mask
));
24003 print_const_val(state
, RHS(ins
, 1), fp
);
24008 addr_reg
= check_reg(state
, RHS(ins
, 1), REGCM_GPR16
);
24009 if (!reg_is_reg(state
, addr_reg
, REG_DX
)) {
24010 internal_error(state
, ins
, "dst != %%dx");
24012 fprintf(fp
, "\t%s %s, %s\n",
24014 reg(state
, RHS(ins
, 0), mask
),
24015 reg(state
, RHS(ins
, 1), REGCM_GPR16
));
24019 static void print_op_move(struct compile_state
*state
,
24020 struct triple
*ins
, FILE *fp
)
24022 /* op_move is complex because there are many types
24023 * of registers we can move between.
24024 * Because OP_COPY will be introduced in arbitrary locations
24025 * OP_COPY must not affect flags.
24026 * OP_CONVERT can change the flags and it is the only operation
24027 * where it is expected the types in the registers can change.
24029 int omit_copy
= 1; /* Is it o.k. to omit a noop copy? */
24030 struct triple
*dst
, *src
;
24031 if (state
->arch
->features
& X86_NOOP_COPY
) {
24034 if ((ins
->op
== OP_COPY
) || (ins
->op
== OP_CONVERT
)) {
24039 internal_error(state
, ins
, "unknown move operation");
24042 if (reg_size(state
, dst
) < size_of(state
, dst
->type
)) {
24043 internal_error(state
, ins
, "Invalid destination register");
24045 if (!equiv_types(src
->type
, dst
->type
) && (dst
->op
== OP_COPY
)) {
24046 fprintf(state
->errout
, "src type: ");
24047 name_of(state
->errout
, src
->type
);
24048 fprintf(state
->errout
, "\n");
24049 fprintf(state
->errout
, "dst type: ");
24050 name_of(state
->errout
, dst
->type
);
24051 fprintf(state
->errout
, "\n");
24052 internal_error(state
, ins
, "Type mismatch for OP_COPY");
24055 if (!is_const(src
)) {
24056 int src_reg
, dst_reg
;
24057 int src_regcm
, dst_regcm
;
24058 src_reg
= ID_REG(src
->id
);
24059 dst_reg
= ID_REG(dst
->id
);
24060 src_regcm
= arch_reg_regcm(state
, src_reg
);
24061 dst_regcm
= arch_reg_regcm(state
, dst_reg
);
24062 /* If the class is the same just move the register */
24063 if (src_regcm
& dst_regcm
&
24064 (REGCM_GPR8_LO
| REGCM_GPR16
| REGCM_GPR32
)) {
24065 if ((src_reg
!= dst_reg
) || !omit_copy
) {
24066 fprintf(fp
, "\tmov %s, %s\n",
24067 reg(state
, src
, src_regcm
),
24068 reg(state
, dst
, dst_regcm
));
24071 /* Move 32bit to 16bit */
24072 else if ((src_regcm
& REGCM_GPR32
) &&
24073 (dst_regcm
& REGCM_GPR16
)) {
24074 src_reg
= (src_reg
- REGC_GPR32_FIRST
) + REGC_GPR16_FIRST
;
24075 if ((src_reg
!= dst_reg
) || !omit_copy
) {
24076 fprintf(fp
, "\tmovw %s, %s\n",
24077 arch_reg_str(src_reg
),
24078 arch_reg_str(dst_reg
));
24081 /* Move from 32bit gprs to 16bit gprs */
24082 else if ((src_regcm
& REGCM_GPR32
) &&
24083 (dst_regcm
& REGCM_GPR16
)) {
24084 dst_reg
= (dst_reg
- REGC_GPR16_FIRST
) + REGC_GPR32_FIRST
;
24085 if ((src_reg
!= dst_reg
) || !omit_copy
) {
24086 fprintf(fp
, "\tmov %s, %s\n",
24087 arch_reg_str(src_reg
),
24088 arch_reg_str(dst_reg
));
24091 /* Move 32bit to 8bit */
24092 else if ((src_regcm
& REGCM_GPR32_8
) &&
24093 (dst_regcm
& REGCM_GPR8_LO
))
24095 src_reg
= (src_reg
- REGC_GPR32_8_FIRST
) + REGC_GPR8_FIRST
;
24096 if ((src_reg
!= dst_reg
) || !omit_copy
) {
24097 fprintf(fp
, "\tmovb %s, %s\n",
24098 arch_reg_str(src_reg
),
24099 arch_reg_str(dst_reg
));
24102 /* Move 16bit to 8bit */
24103 else if ((src_regcm
& REGCM_GPR16_8
) &&
24104 (dst_regcm
& REGCM_GPR8_LO
))
24106 src_reg
= (src_reg
- REGC_GPR16_8_FIRST
) + REGC_GPR8_FIRST
;
24107 if ((src_reg
!= dst_reg
) || !omit_copy
) {
24108 fprintf(fp
, "\tmovb %s, %s\n",
24109 arch_reg_str(src_reg
),
24110 arch_reg_str(dst_reg
));
24113 /* Move 8/16bit to 16/32bit */
24114 else if ((src_regcm
& (REGCM_GPR8_LO
| REGCM_GPR16
)) &&
24115 (dst_regcm
& (REGCM_GPR16
| REGCM_GPR32
))) {
24117 op
= is_signed(src
->type
)? "movsx": "movzx";
24118 fprintf(fp
, "\t%s %s, %s\n",
24120 reg(state
, src
, src_regcm
),
24121 reg(state
, dst
, dst_regcm
));
24123 /* Move between sse registers */
24124 else if ((src_regcm
& dst_regcm
& REGCM_XMM
)) {
24125 if ((src_reg
!= dst_reg
) || !omit_copy
) {
24126 fprintf(fp
, "\tmovdqa %s, %s\n",
24127 reg(state
, src
, src_regcm
),
24128 reg(state
, dst
, dst_regcm
));
24131 /* Move between mmx registers */
24132 else if ((src_regcm
& dst_regcm
& REGCM_MMX
)) {
24133 if ((src_reg
!= dst_reg
) || !omit_copy
) {
24134 fprintf(fp
, "\tmovq %s, %s\n",
24135 reg(state
, src
, src_regcm
),
24136 reg(state
, dst
, dst_regcm
));
24139 /* Move from sse to mmx registers */
24140 else if ((src_regcm
& REGCM_XMM
) && (dst_regcm
& REGCM_MMX
)) {
24141 fprintf(fp
, "\tmovdq2q %s, %s\n",
24142 reg(state
, src
, src_regcm
),
24143 reg(state
, dst
, dst_regcm
));
24145 /* Move from mmx to sse registers */
24146 else if ((src_regcm
& REGCM_MMX
) && (dst_regcm
& REGCM_XMM
)) {
24147 fprintf(fp
, "\tmovq2dq %s, %s\n",
24148 reg(state
, src
, src_regcm
),
24149 reg(state
, dst
, dst_regcm
));
24151 /* Move between 32bit gprs & mmx/sse registers */
24152 else if ((src_regcm
& (REGCM_GPR32
| REGCM_MMX
| REGCM_XMM
)) &&
24153 (dst_regcm
& (REGCM_GPR32
| REGCM_MMX
| REGCM_XMM
))) {
24154 fprintf(fp
, "\tmovd %s, %s\n",
24155 reg(state
, src
, src_regcm
),
24156 reg(state
, dst
, dst_regcm
));
24158 /* Move from 16bit gprs & mmx/sse registers */
24159 else if ((src_regcm
& REGCM_GPR16
) &&
24160 (dst_regcm
& (REGCM_MMX
| REGCM_XMM
))) {
24163 op
= is_signed(src
->type
)? "movsx":"movzx";
24164 mid_reg
= (src_reg
- REGC_GPR16_FIRST
) + REGC_GPR32_FIRST
;
24165 fprintf(fp
, "\t%s %s, %s\n\tmovd %s, %s\n",
24167 arch_reg_str(src_reg
),
24168 arch_reg_str(mid_reg
),
24169 arch_reg_str(mid_reg
),
24170 arch_reg_str(dst_reg
));
24172 /* Move from mmx/sse registers to 16bit gprs */
24173 else if ((src_regcm
& (REGCM_MMX
| REGCM_XMM
)) &&
24174 (dst_regcm
& REGCM_GPR16
)) {
24175 dst_reg
= (dst_reg
- REGC_GPR16_FIRST
) + REGC_GPR32_FIRST
;
24176 fprintf(fp
, "\tmovd %s, %s\n",
24177 arch_reg_str(src_reg
),
24178 arch_reg_str(dst_reg
));
24180 /* Move from gpr to 64bit dividend */
24181 else if ((src_regcm
& (REGCM_GPR32
| REGCM_GPR16
| REGCM_GPR8_LO
)) &&
24182 (dst_regcm
& REGCM_DIVIDEND64
)) {
24183 const char *extend
;
24184 extend
= is_signed(src
->type
)? "cltd":"movl $0, %edx";
24185 fprintf(fp
, "\tmov %s, %%eax\n\t%s\n",
24186 arch_reg_str(src_reg
),
24189 /* Move from 64bit gpr to gpr */
24190 else if ((src_regcm
& REGCM_DIVIDEND64
) &&
24191 (dst_regcm
& (REGCM_GPR32
| REGCM_GPR16
| REGCM_GPR8_LO
))) {
24192 if (dst_regcm
& REGCM_GPR32
) {
24195 else if (dst_regcm
& REGCM_GPR16
) {
24198 else if (dst_regcm
& REGCM_GPR8_LO
) {
24201 fprintf(fp
, "\tmov %s, %s\n",
24202 arch_reg_str(src_reg
),
24203 arch_reg_str(dst_reg
));
24205 /* Move from mmx/sse registers to 64bit gpr */
24206 else if ((src_regcm
& (REGCM_MMX
| REGCM_XMM
)) &&
24207 (dst_regcm
& REGCM_DIVIDEND64
)) {
24208 const char *extend
;
24209 extend
= is_signed(src
->type
)? "cltd": "movl $0, %edx";
24210 fprintf(fp
, "\tmovd %s, %%eax\n\t%s\n",
24211 arch_reg_str(src_reg
),
24214 /* Move from 64bit gpr to mmx/sse register */
24215 else if ((src_regcm
& REGCM_DIVIDEND64
) &&
24216 (dst_regcm
& (REGCM_XMM
| REGCM_MMX
))) {
24217 fprintf(fp
, "\tmovd %%eax, %s\n",
24218 arch_reg_str(dst_reg
));
24220 #if X86_4_8BIT_GPRS
24221 /* Move from 8bit gprs to mmx/sse registers */
24222 else if ((src_regcm
& REGCM_GPR8_LO
) && (src_reg
<= REG_DL
) &&
24223 (dst_regcm
& (REGCM_MMX
| REGCM_XMM
))) {
24226 op
= is_signed(src
->type
)? "movsx":"movzx";
24227 mid_reg
= (src_reg
- REGC_GPR8_FIRST
) + REGC_GPR32_FIRST
;
24228 fprintf(fp
, "\t%s %s, %s\n\tmovd %s, %s\n",
24230 reg(state
, src
, src_regcm
),
24231 arch_reg_str(mid_reg
),
24232 arch_reg_str(mid_reg
),
24233 reg(state
, dst
, dst_regcm
));
24235 /* Move from mmx/sse registers and 8bit gprs */
24236 else if ((src_regcm
& (REGCM_MMX
| REGCM_XMM
)) &&
24237 (dst_regcm
& REGCM_GPR8_LO
) && (dst_reg
<= REG_DL
)) {
24239 mid_reg
= (dst_reg
- REGC_GPR8_FIRST
) + REGC_GPR32_FIRST
;
24240 fprintf(fp
, "\tmovd %s, %s\n",
24241 reg(state
, src
, src_regcm
),
24242 arch_reg_str(mid_reg
));
24244 /* Move from 32bit gprs to 8bit gprs */
24245 else if ((src_regcm
& REGCM_GPR32
) &&
24246 (dst_regcm
& REGCM_GPR8_LO
)) {
24247 dst_reg
= (dst_reg
- REGC_GPR8_FIRST
) + REGC_GPR32_FIRST
;
24248 if ((src_reg
!= dst_reg
) || !omit_copy
) {
24249 fprintf(fp
, "\tmov %s, %s\n",
24250 arch_reg_str(src_reg
),
24251 arch_reg_str(dst_reg
));
24254 /* Move from 16bit gprs to 8bit gprs */
24255 else if ((src_regcm
& REGCM_GPR16
) &&
24256 (dst_regcm
& REGCM_GPR8_LO
)) {
24257 dst_reg
= (dst_reg
- REGC_GPR8_FIRST
) + REGC_GPR16_FIRST
;
24258 if ((src_reg
!= dst_reg
) || !omit_copy
) {
24259 fprintf(fp
, "\tmov %s, %s\n",
24260 arch_reg_str(src_reg
),
24261 arch_reg_str(dst_reg
));
24264 #endif /* X86_4_8BIT_GPRS */
24265 /* Move from %eax:%edx to %eax:%edx */
24266 else if ((src_regcm
& REGCM_DIVIDEND64
) &&
24267 (dst_regcm
& REGCM_DIVIDEND64
) &&
24268 (src_reg
== dst_reg
)) {
24270 fprintf(fp
, "\t/*mov %s, %s*/\n",
24271 arch_reg_str(src_reg
),
24272 arch_reg_str(dst_reg
));
24276 if ((src_regcm
& ~REGCM_FLAGS
) == 0) {
24277 internal_error(state
, ins
, "attempt to copy from %%eflags!");
24279 internal_error(state
, ins
, "unknown copy type");
24286 dst_size
= size_of(state
, dst
->type
);
24287 dst_reg
= ID_REG(dst
->id
);
24288 dst_regcm
= arch_reg_regcm(state
, dst_reg
);
24289 if (dst_regcm
& (REGCM_GPR32
| REGCM_GPR16
| REGCM_GPR8_LO
)) {
24290 fprintf(fp
, "\tmov ");
24291 print_const_val(state
, src
, fp
);
24292 fprintf(fp
, ", %s\n",
24293 reg(state
, dst
, REGCM_GPR32
| REGCM_GPR16
| REGCM_GPR8_LO
));
24295 else if (dst_regcm
& REGCM_DIVIDEND64
) {
24296 if (dst_size
> SIZEOF_I32
) {
24297 internal_error(state
, ins
, "%dbit constant...", dst_size
);
24299 fprintf(fp
, "\tmov $0, %%edx\n");
24300 fprintf(fp
, "\tmov ");
24301 print_const_val(state
, src
, fp
);
24302 fprintf(fp
, ", %%eax\n");
24304 else if (dst_regcm
& REGCM_DIVIDEND32
) {
24305 if (dst_size
> SIZEOF_I16
) {
24306 internal_error(state
, ins
, "%dbit constant...", dst_size
);
24308 fprintf(fp
, "\tmov $0, %%dx\n");
24309 fprintf(fp
, "\tmov ");
24310 print_const_val(state
, src
, fp
);
24311 fprintf(fp
, ", %%ax");
24313 else if (dst_regcm
& (REGCM_XMM
| REGCM_MMX
)) {
24315 if (dst_size
> SIZEOF_I32
) {
24316 internal_error(state
, ins
, "%d bit constant...", dst_size
);
24318 ref
= get_const_pool_ref(state
, src
, SIZEOF_I32
, fp
);
24319 fprintf(fp
, "\tmovd L%s%lu, %s\n",
24320 state
->compiler
->label_prefix
, ref
,
24321 reg(state
, dst
, (REGCM_XMM
| REGCM_MMX
)));
24324 internal_error(state
, ins
, "unknown copy immediate type");
24327 /* Leave now if this is not a type conversion */
24328 if (ins
->op
!= OP_CONVERT
) {
24331 /* Now make certain I have not logically overflowed the destination */
24332 if ((size_of(state
, src
->type
) > size_of(state
, dst
->type
)) &&
24333 (size_of(state
, dst
->type
) < reg_size(state
, dst
)))
24335 unsigned long mask
;
24338 if (size_of(state
, dst
->type
) >= 32) {
24339 fprintf(state
->errout
, "dst type: ");
24340 name_of(state
->errout
, dst
->type
);
24341 fprintf(state
->errout
, "\n");
24342 internal_error(state
, dst
, "unhandled dst type size");
24345 mask
<<= size_of(state
, dst
->type
);
24348 dst_reg
= ID_REG(dst
->id
);
24349 dst_regcm
= arch_reg_regcm(state
, dst_reg
);
24351 if (dst_regcm
& (REGCM_GPR32
| REGCM_GPR16
| REGCM_GPR8_LO
)) {
24352 fprintf(fp
, "\tand $0x%lx, %s\n",
24353 mask
, reg(state
, dst
, REGCM_GPR32
| REGCM_GPR16
| REGCM_GPR8_LO
));
24355 else if (dst_regcm
& REGCM_MMX
) {
24357 ref
= get_mask_pool_ref(state
, dst
, mask
, fp
);
24358 fprintf(fp
, "\tpand L%s%lu, %s\n",
24359 state
->compiler
->label_prefix
, ref
,
24360 reg(state
, dst
, REGCM_MMX
));
24362 else if (dst_regcm
& REGCM_XMM
) {
24364 ref
= get_mask_pool_ref(state
, dst
, mask
, fp
);
24365 fprintf(fp
, "\tpand L%s%lu, %s\n",
24366 state
->compiler
->label_prefix
, ref
,
24367 reg(state
, dst
, REGCM_XMM
));
24370 fprintf(state
->errout
, "dst type: ");
24371 name_of(state
->errout
, dst
->type
);
24372 fprintf(state
->errout
, "\n");
24373 fprintf(state
->errout
, "dst: %s\n", reg(state
, dst
, REGCM_ALL
));
24374 internal_error(state
, dst
, "failed to trunc value: mask %lx", mask
);
24377 /* Make certain I am properly sign extended */
24378 if ((size_of(state
, src
->type
) < size_of(state
, dst
->type
)) &&
24379 (is_signed(src
->type
)))
24381 int reg_bits
, shift_bits
;
24385 reg_bits
= reg_size(state
, dst
);
24386 if (reg_bits
> 32) {
24389 shift_bits
= reg_bits
- size_of(state
, src
->type
);
24390 dst_reg
= ID_REG(dst
->id
);
24391 dst_regcm
= arch_reg_regcm(state
, dst_reg
);
24393 if (shift_bits
< 0) {
24394 internal_error(state
, dst
, "negative shift?");
24397 if (dst_regcm
& (REGCM_GPR32
| REGCM_GPR16
| REGCM_GPR8_LO
)) {
24398 fprintf(fp
, "\tshl $%d, %s\n",
24400 reg(state
, dst
, REGCM_GPR32
| REGCM_GPR16
| REGCM_GPR8_LO
));
24401 fprintf(fp
, "\tsar $%d, %s\n",
24403 reg(state
, dst
, REGCM_GPR32
| REGCM_GPR16
| REGCM_GPR8_LO
));
24405 else if (dst_regcm
& (REGCM_MMX
| REGCM_XMM
)) {
24406 fprintf(fp
, "\tpslld $%d, %s\n",
24408 reg(state
, dst
, REGCM_MMX
| REGCM_XMM
));
24409 fprintf(fp
, "\tpsrad $%d, %s\n",
24411 reg(state
, dst
, REGCM_MMX
| REGCM_XMM
));
24414 fprintf(state
->errout
, "dst type: ");
24415 name_of(state
->errout
, dst
->type
);
24416 fprintf(state
->errout
, "\n");
24417 fprintf(state
->errout
, "dst: %s\n", reg(state
, dst
, REGCM_ALL
));
24418 internal_error(state
, dst
, "failed to signed extend value");
24423 static void print_op_load(struct compile_state
*state
,
24424 struct triple
*ins
, FILE *fp
)
24426 struct triple
*dst
, *src
;
24430 if (is_const(src
) || is_const(dst
)) {
24431 internal_error(state
, ins
, "unknown load operation");
24433 switch(ins
->type
->type
& TYPE_MASK
) {
24434 case TYPE_CHAR
: op
= "movsbl"; break;
24435 case TYPE_UCHAR
: op
= "movzbl"; break;
24436 case TYPE_SHORT
: op
= "movswl"; break;
24437 case TYPE_USHORT
: op
= "movzwl"; break;
24438 case TYPE_INT
: case TYPE_UINT
:
24439 case TYPE_LONG
: case TYPE_ULONG
:
24444 internal_error(state
, ins
, "unknown type in load");
24445 op
= "<invalid opcode>";
24448 fprintf(fp
, "\t%s (%s), %s\n",
24450 reg(state
, src
, REGCM_GPR32
),
24451 reg(state
, dst
, REGCM_GPR32
));
24455 static void print_op_store(struct compile_state
*state
,
24456 struct triple
*ins
, FILE *fp
)
24458 struct triple
*dst
, *src
;
24461 if (is_const(src
) && (src
->op
== OP_INTCONST
)) {
24463 value
= (long_t
)(src
->u
.cval
);
24464 fprintf(fp
, "\tmov%s $%ld, (%s)\n",
24465 type_suffix(state
, src
->type
),
24467 reg(state
, dst
, REGCM_GPR32
));
24469 else if (is_const(dst
) && (dst
->op
== OP_INTCONST
)) {
24470 fprintf(fp
, "\tmov%s %s, 0x%08lx\n",
24471 type_suffix(state
, src
->type
),
24472 reg(state
, src
, REGCM_GPR8_LO
| REGCM_GPR16
| REGCM_GPR32
),
24473 (unsigned long)(dst
->u
.cval
));
24476 if (is_const(src
) || is_const(dst
)) {
24477 internal_error(state
, ins
, "unknown store operation");
24479 fprintf(fp
, "\tmov%s %s, (%s)\n",
24480 type_suffix(state
, src
->type
),
24481 reg(state
, src
, REGCM_GPR8_LO
| REGCM_GPR16
| REGCM_GPR32
),
24482 reg(state
, dst
, REGCM_GPR32
));
24488 static void print_op_smul(struct compile_state
*state
,
24489 struct triple
*ins
, FILE *fp
)
24491 if (!is_const(RHS(ins
, 1))) {
24492 fprintf(fp
, "\timul %s, %s\n",
24493 reg(state
, RHS(ins
, 1), REGCM_GPR32
),
24494 reg(state
, RHS(ins
, 0), REGCM_GPR32
));
24497 fprintf(fp
, "\timul ");
24498 print_const_val(state
, RHS(ins
, 1), fp
);
24499 fprintf(fp
, ", %s\n", reg(state
, RHS(ins
, 0), REGCM_GPR32
));
24503 static void print_op_cmp(struct compile_state
*state
,
24504 struct triple
*ins
, FILE *fp
)
24508 mask
= REGCM_GPR32
| REGCM_GPR16
| REGCM_GPR8_LO
;
24509 dreg
= check_reg(state
, ins
, REGCM_FLAGS
);
24510 if (!reg_is_reg(state
, dreg
, REG_EFLAGS
)) {
24511 internal_error(state
, ins
, "bad dest register for cmp");
24513 if (is_const(RHS(ins
, 1))) {
24514 fprintf(fp
, "\tcmp ");
24515 print_const_val(state
, RHS(ins
, 1), fp
);
24516 fprintf(fp
, ", %s\n", reg(state
, RHS(ins
, 0), mask
));
24519 unsigned lmask
, rmask
;
24521 lreg
= check_reg(state
, RHS(ins
, 0), mask
);
24522 rreg
= check_reg(state
, RHS(ins
, 1), mask
);
24523 lmask
= arch_reg_regcm(state
, lreg
);
24524 rmask
= arch_reg_regcm(state
, rreg
);
24525 mask
= lmask
& rmask
;
24526 fprintf(fp
, "\tcmp %s, %s\n",
24527 reg(state
, RHS(ins
, 1), mask
),
24528 reg(state
, RHS(ins
, 0), mask
));
24532 static void print_op_test(struct compile_state
*state
,
24533 struct triple
*ins
, FILE *fp
)
24536 mask
= REGCM_GPR32
| REGCM_GPR16
| REGCM_GPR8_LO
;
24537 fprintf(fp
, "\ttest %s, %s\n",
24538 reg(state
, RHS(ins
, 0), mask
),
24539 reg(state
, RHS(ins
, 0), mask
));
24542 static void print_op_branch(struct compile_state
*state
,
24543 struct triple
*branch
, FILE *fp
)
24545 const char *bop
= "j";
24546 if ((branch
->op
== OP_JMP
) || (branch
->op
== OP_CALL
)) {
24547 if (branch
->rhs
!= 0) {
24548 internal_error(state
, branch
, "jmp with condition?");
24553 struct triple
*ptr
;
24554 if (branch
->rhs
!= 1) {
24555 internal_error(state
, branch
, "jmpcc without condition?");
24557 check_reg(state
, RHS(branch
, 0), REGCM_FLAGS
);
24558 if ((RHS(branch
, 0)->op
!= OP_CMP
) &&
24559 (RHS(branch
, 0)->op
!= OP_TEST
)) {
24560 internal_error(state
, branch
, "bad branch test");
24562 #if DEBUG_ROMCC_WARNINGS
24563 #warning "FIXME I have observed instructions between the test and branch instructions"
24565 ptr
= RHS(branch
, 0);
24566 for(ptr
= RHS(branch
, 0)->next
; ptr
!= branch
; ptr
= ptr
->next
) {
24567 if (ptr
->op
!= OP_COPY
) {
24568 internal_error(state
, branch
, "branch does not follow test");
24571 switch(branch
->op
) {
24572 case OP_JMP_EQ
: bop
= "jz"; break;
24573 case OP_JMP_NOTEQ
: bop
= "jnz"; break;
24574 case OP_JMP_SLESS
: bop
= "jl"; break;
24575 case OP_JMP_ULESS
: bop
= "jb"; break;
24576 case OP_JMP_SMORE
: bop
= "jg"; break;
24577 case OP_JMP_UMORE
: bop
= "ja"; break;
24578 case OP_JMP_SLESSEQ
: bop
= "jle"; break;
24579 case OP_JMP_ULESSEQ
: bop
= "jbe"; break;
24580 case OP_JMP_SMOREEQ
: bop
= "jge"; break;
24581 case OP_JMP_UMOREEQ
: bop
= "jae"; break;
24583 internal_error(state
, branch
, "Invalid branch op");
24589 if (branch
->op
== OP_CALL
) {
24590 fprintf(fp
, "\t/* call */\n");
24593 fprintf(fp
, "\t%s L%s%lu\n",
24595 state
->compiler
->label_prefix
,
24596 (unsigned long)(TARG(branch
, 0)->u
.cval
));
24599 static void print_op_ret(struct compile_state
*state
,
24600 struct triple
*branch
, FILE *fp
)
24602 fprintf(fp
, "\tjmp *%s\n",
24603 reg(state
, RHS(branch
, 0), REGCM_GPR32
));
24606 static void print_op_set(struct compile_state
*state
,
24607 struct triple
*set
, FILE *fp
)
24609 const char *sop
= "set";
24610 if (set
->rhs
!= 1) {
24611 internal_error(state
, set
, "setcc without condition?");
24613 check_reg(state
, RHS(set
, 0), REGCM_FLAGS
);
24614 if ((RHS(set
, 0)->op
!= OP_CMP
) &&
24615 (RHS(set
, 0)->op
!= OP_TEST
)) {
24616 internal_error(state
, set
, "bad set test");
24618 if (RHS(set
, 0)->next
!= set
) {
24619 internal_error(state
, set
, "set does not follow test");
24622 case OP_SET_EQ
: sop
= "setz"; break;
24623 case OP_SET_NOTEQ
: sop
= "setnz"; break;
24624 case OP_SET_SLESS
: sop
= "setl"; break;
24625 case OP_SET_ULESS
: sop
= "setb"; break;
24626 case OP_SET_SMORE
: sop
= "setg"; break;
24627 case OP_SET_UMORE
: sop
= "seta"; break;
24628 case OP_SET_SLESSEQ
: sop
= "setle"; break;
24629 case OP_SET_ULESSEQ
: sop
= "setbe"; break;
24630 case OP_SET_SMOREEQ
: sop
= "setge"; break;
24631 case OP_SET_UMOREEQ
: sop
= "setae"; break;
24633 internal_error(state
, set
, "Invalid set op");
24636 fprintf(fp
, "\t%s %s\n",
24637 sop
, reg(state
, set
, REGCM_GPR8_LO
));
24640 static void print_op_bit_scan(struct compile_state
*state
,
24641 struct triple
*ins
, FILE *fp
)
24645 case OP_BSF
: op
= "bsf"; break;
24646 case OP_BSR
: op
= "bsr"; break;
24648 internal_error(state
, ins
, "unknown bit scan");
24658 reg(state
, RHS(ins
, 0), REGCM_GPR32
),
24659 reg(state
, ins
, REGCM_GPR32
),
24660 reg(state
, ins
, REGCM_GPR32
));
24664 static void print_sdecl(struct compile_state
*state
,
24665 struct triple
*ins
, FILE *fp
)
24667 fprintf(fp
, ".section \"" DATA_SECTION
"\"\n");
24668 fprintf(fp
, ".balign %ld\n", (long int)align_of_in_bytes(state
, ins
->type
));
24669 fprintf(fp
, "L%s%lu:\n",
24670 state
->compiler
->label_prefix
, (unsigned long)(ins
->u
.cval
));
24671 print_const(state
, MISC(ins
, 0), fp
);
24672 fprintf(fp
, ".section \"" TEXT_SECTION
"\"\n");
24676 static void print_instruction(struct compile_state
*state
,
24677 struct triple
*ins
, FILE *fp
)
24679 /* Assumption: after I have exted the register allocator
24680 * everything is in a valid register.
24684 print_op_asm(state
, ins
, fp
);
24686 case OP_ADD
: print_binary_op(state
, "add", ins
, fp
); break;
24687 case OP_SUB
: print_binary_op(state
, "sub", ins
, fp
); break;
24688 case OP_AND
: print_binary_op(state
, "and", ins
, fp
); break;
24689 case OP_XOR
: print_binary_op(state
, "xor", ins
, fp
); break;
24690 case OP_OR
: print_binary_op(state
, "or", ins
, fp
); break;
24691 case OP_SL
: print_op_shift(state
, "shl", ins
, fp
); break;
24692 case OP_USR
: print_op_shift(state
, "shr", ins
, fp
); break;
24693 case OP_SSR
: print_op_shift(state
, "sar", ins
, fp
); break;
24694 case OP_POS
: break;
24695 case OP_NEG
: print_unary_op(state
, "neg", ins
, fp
); break;
24696 case OP_INVERT
: print_unary_op(state
, "not", ins
, fp
); break;
24701 /* Don't generate anything here for constants */
24703 /* Don't generate anything for variable declarations. */
24705 case OP_UNKNOWNVAL
:
24706 fprintf(fp
, " /* unknown %s */\n",
24707 reg(state
, ins
, REGCM_ALL
));
24710 print_sdecl(state
, ins
, fp
);
24714 print_op_move(state
, ins
, fp
);
24717 print_op_load(state
, ins
, fp
);
24720 print_op_store(state
, ins
, fp
);
24723 print_op_smul(state
, ins
, fp
);
24725 case OP_CMP
: print_op_cmp(state
, ins
, fp
); break;
24726 case OP_TEST
: print_op_test(state
, ins
, fp
); break;
24728 case OP_JMP_EQ
: case OP_JMP_NOTEQ
:
24729 case OP_JMP_SLESS
: case OP_JMP_ULESS
:
24730 case OP_JMP_SMORE
: case OP_JMP_UMORE
:
24731 case OP_JMP_SLESSEQ
: case OP_JMP_ULESSEQ
:
24732 case OP_JMP_SMOREEQ
: case OP_JMP_UMOREEQ
:
24734 print_op_branch(state
, ins
, fp
);
24737 print_op_ret(state
, ins
, fp
);
24739 case OP_SET_EQ
: case OP_SET_NOTEQ
:
24740 case OP_SET_SLESS
: case OP_SET_ULESS
:
24741 case OP_SET_SMORE
: case OP_SET_UMORE
:
24742 case OP_SET_SLESSEQ
: case OP_SET_ULESSEQ
:
24743 case OP_SET_SMOREEQ
: case OP_SET_UMOREEQ
:
24744 print_op_set(state
, ins
, fp
);
24746 case OP_INB
: case OP_INW
: case OP_INL
:
24747 print_op_in(state
, ins
, fp
);
24749 case OP_OUTB
: case OP_OUTW
: case OP_OUTL
:
24750 print_op_out(state
, ins
, fp
);
24754 print_op_bit_scan(state
, ins
, fp
);
24757 after_lhs(state
, ins
);
24758 fprintf(fp
, "\trdmsr\n");
24761 fprintf(fp
, "\twrmsr\n");
24764 fprintf(fp
, "\thlt\n");
24767 fprintf(fp
, "\tidiv %s\n", reg(state
, RHS(ins
, 1), REGCM_GPR32
));
24770 fprintf(fp
, "\tdiv %s\n", reg(state
, RHS(ins
, 1), REGCM_GPR32
));
24773 fprintf(fp
, "\tmul %s\n", reg(state
, RHS(ins
, 1), REGCM_GPR32
));
24779 fprintf(fp
, "L%s%lu:\n",
24780 state
->compiler
->label_prefix
, (unsigned long)(ins
->u
.cval
));
24783 /* Ignore adecls with no registers error otherwise */
24784 if (!noop_adecl(ins
)) {
24785 internal_error(state
, ins
, "adecl remains?");
24788 /* Ignore OP_PIECE */
24791 /* Operations that should never get here */
24792 case OP_SDIV
: case OP_UDIV
:
24793 case OP_SMOD
: case OP_UMOD
:
24794 case OP_LTRUE
: case OP_LFALSE
: case OP_EQ
: case OP_NOTEQ
:
24795 case OP_SLESS
: case OP_ULESS
: case OP_SMORE
: case OP_UMORE
:
24796 case OP_SLESSEQ
: case OP_ULESSEQ
: case OP_SMOREEQ
: case OP_UMOREEQ
:
24798 internal_error(state
, ins
, "unknown op: %d %s",
24799 ins
->op
, tops(ins
->op
));
24804 static void print_instructions(struct compile_state
*state
)
24806 struct triple
*first
, *ins
;
24807 int print_location
;
24808 struct occurance
*last_occurance
;
24810 int max_inline_depth
;
24811 max_inline_depth
= 0;
24812 print_location
= 1;
24813 last_occurance
= 0;
24814 fp
= state
->output
;
24815 /* Masks for common sizes */
24816 fprintf(fp
, ".section \"" DATA_SECTION
"\"\n");
24817 fprintf(fp
, ".balign 16\n");
24818 fprintf(fp
, "L%s1:\n", state
->compiler
->label_prefix
);
24819 fprintf(fp
, ".int 0xff, 0, 0, 0\n");
24820 fprintf(fp
, "L%s2:\n", state
->compiler
->label_prefix
);
24821 fprintf(fp
, ".int 0xffff, 0, 0, 0\n");
24822 fprintf(fp
, ".section \"" TEXT_SECTION
"\"\n");
24823 first
= state
->first
;
24826 if (print_location
&&
24827 last_occurance
!= ins
->occurance
) {
24828 if (!ins
->occurance
->parent
) {
24829 fprintf(fp
, "\t/* %s,%s:%d.%d */\n",
24830 ins
->occurance
->function
?ins
->occurance
->function
:"(null)",
24831 ins
->occurance
->filename
?ins
->occurance
->filename
:"(null)",
24832 ins
->occurance
->line
,
24833 ins
->occurance
->col
);
24836 struct occurance
*ptr
;
24838 fprintf(fp
, "\t/*\n");
24840 for(ptr
= ins
->occurance
; ptr
; ptr
= ptr
->parent
) {
24842 fprintf(fp
, "\t * %s,%s:%d.%d\n",
24848 fprintf(fp
, "\t */\n");
24849 if (inline_depth
> max_inline_depth
) {
24850 max_inline_depth
= inline_depth
;
24853 if (last_occurance
) {
24854 put_occurance(last_occurance
);
24856 get_occurance(ins
->occurance
);
24857 last_occurance
= ins
->occurance
;
24860 print_instruction(state
, ins
, fp
);
24862 } while(ins
!= first
);
24863 if (print_location
) {
24864 fprintf(fp
, "/* max inline depth %d */\n",
24869 static void generate_code(struct compile_state
*state
)
24871 generate_local_labels(state
);
24872 print_instructions(state
);
24876 static void print_preprocessed_tokens(struct compile_state
*state
)
24881 const char *filename
;
24882 fp
= state
->output
;
24886 struct file_state
*file
;
24888 const char *token_str
;
24890 if (tok
== TOK_EOF
) {
24893 tk
= eat(state
, tok
);
24895 tk
->ident
? tk
->ident
->name
:
24896 tk
->str_len
? tk
->val
.str
:
24899 file
= state
->file
;
24900 while(file
->macro
&& file
->prev
) {
24903 if (!file
->macro
&&
24904 ((file
->line
!= line
) || (file
->basename
!= filename
)))
24907 if ((file
->basename
== filename
) &&
24908 (line
< file
->line
)) {
24909 while(line
< file
->line
) {
24915 fprintf(fp
, "\n#line %d \"%s\"\n",
24916 file
->line
, file
->basename
);
24919 filename
= file
->basename
;
24920 col
= get_col(file
) - strlen(token_str
);
24921 for(i
= 0; i
< col
; i
++) {
24926 fprintf(fp
, "%s ", token_str
);
24928 if (state
->compiler
->debug
& DEBUG_TOKENS
) {
24929 loc(state
->dbgout
, state
, 0);
24930 fprintf(state
->dbgout
, "%s <- `%s'\n",
24931 tokens
[tok
], token_str
);
24936 static void compile(const char *filename
,
24937 struct compiler_state
*compiler
, struct arch_state
*arch
)
24940 struct compile_state state
;
24941 struct triple
*ptr
;
24942 struct filelist
*includes
= include_filelist
;
24943 memset(&state
, 0, sizeof(state
));
24944 state
.compiler
= compiler
;
24947 for(i
= 0; i
< sizeof(state
.token
)/sizeof(state
.token
[0]); i
++) {
24948 memset(&state
.token
[i
], 0, sizeof(state
.token
[i
]));
24949 state
.token
[i
].tok
= -1;
24951 /* Remember the output descriptors */
24952 state
.errout
= stderr
;
24953 state
.dbgout
= stdout
;
24954 /* Remember the output filename */
24955 if ((state
.compiler
->flags
& COMPILER_PP_ONLY
) && (strcmp("auto.inc",state
.compiler
->ofilename
) == 0)) {
24956 state
.output
= stdout
;
24958 state
.output
= fopen(state
.compiler
->ofilename
, "w");
24959 if (!state
.output
) {
24960 error(&state
, 0, "Cannot open output file %s\n",
24961 state
.compiler
->ofilename
);
24964 /* Make certain a good cleanup happens */
24965 exit_state
= &state
;
24966 atexit(exit_cleanup
);
24968 /* Prep the preprocessor */
24969 state
.if_depth
= 0;
24970 memset(state
.if_bytes
, 0, sizeof(state
.if_bytes
));
24971 /* register the C keywords */
24972 register_keywords(&state
);
24973 /* register the keywords the macro preprocessor knows */
24974 register_macro_keywords(&state
);
24975 /* generate some builtin macros */
24976 register_builtin_macros(&state
);
24977 /* Memorize where some special keywords are. */
24978 state
.i_switch
= lookup(&state
, "switch", 6);
24979 state
.i_case
= lookup(&state
, "case", 4);
24980 state
.i_continue
= lookup(&state
, "continue", 8);
24981 state
.i_break
= lookup(&state
, "break", 5);
24982 state
.i_default
= lookup(&state
, "default", 7);
24983 state
.i_return
= lookup(&state
, "return", 6);
24984 /* Memorize where predefined macros are. */
24985 state
.i___VA_ARGS__
= lookup(&state
, "__VA_ARGS__", 11);
24986 state
.i___FILE__
= lookup(&state
, "__FILE__", 8);
24987 state
.i___LINE__
= lookup(&state
, "__LINE__", 8);
24988 /* Memorize where predefined identifiers are. */
24989 state
.i___func__
= lookup(&state
, "__func__", 8);
24990 /* Memorize where some attribute keywords are. */
24991 state
.i_noinline
= lookup(&state
, "noinline", 8);
24992 state
.i_always_inline
= lookup(&state
, "always_inline", 13);
24993 state
.i_noreturn
= lookup(&state
, "noreturn", 8);
24994 state
.i_unused
= lookup(&state
, "unused", 6);
24995 state
.i_packed
= lookup(&state
, "packed", 6);
24997 /* Process the command line macros */
24998 process_cmdline_macros(&state
);
25000 /* Allocate beginning bounding labels for the function list */
25001 state
.first
= label(&state
);
25002 state
.first
->id
|= TRIPLE_FLAG_VOLATILE
;
25003 use_triple(state
.first
, state
.first
);
25004 ptr
= label(&state
);
25005 ptr
->id
|= TRIPLE_FLAG_VOLATILE
;
25006 use_triple(ptr
, ptr
);
25007 flatten(&state
, state
.first
, ptr
);
25009 /* Allocate a label for the pool of global variables */
25010 state
.global_pool
= label(&state
);
25011 state
.global_pool
->id
|= TRIPLE_FLAG_VOLATILE
;
25012 flatten(&state
, state
.first
, state
.global_pool
);
25014 /* Enter the globl definition scope */
25015 start_scope(&state
);
25016 register_builtins(&state
);
25018 compile_file(&state
, filename
, 1);
25021 compile_file(&state
, includes
->filename
, 1);
25022 includes
=includes
->next
;
25025 /* Stop if all we want is preprocessor output */
25026 if (state
.compiler
->flags
& COMPILER_PP_ONLY
) {
25027 print_preprocessed_tokens(&state
);
25033 /* Exit the global definition scope */
25036 /* Now that basic compilation has happened
25037 * optimize the intermediate code
25041 generate_code(&state
);
25042 if (state
.compiler
->debug
) {
25043 fprintf(state
.errout
, "done\n");
25048 static void version(FILE *fp
)
25050 fprintf(fp
, "romcc " VERSION
" released " RELEASE_DATE
"\n");
25053 static void usage(void)
25058 "\nUsage: romcc [options] <source>.c\n"
25059 "Compile a C source file generating a binary that does not implicilty use RAM\n"
25061 "-o <output file name>\n"
25062 "-f<option> Specify a generic compiler option\n"
25063 "-m<option> Specify a arch dependent option\n"
25064 "-- Specify this is the last option\n"
25065 "\nGeneric compiler options:\n"
25067 compiler_usage(fp
);
25069 "\nArchitecture compiler options:\n"
25077 static void arg_error(char *fmt
, ...)
25080 va_start(args
, fmt
);
25081 vfprintf(stderr
, fmt
, args
);
25087 static void arg_warning(char *fmt
, ...)
25091 va_start(args
, fmt
);
25092 vfprintf(stderr
, fmt
, args
);
25096 int main(int argc
, char **argv
)
25098 const char *filename
;
25099 struct compiler_state compiler
;
25100 struct arch_state arch
;
25104 /* I don't want any surprises */
25105 setlocale(LC_ALL
, "C");
25107 init_compiler_state(&compiler
);
25108 init_arch_state(&arch
);
25112 if (!all_opts
&& (strcmp(argv
[1], "-o") == 0) && (argc
> 2)) {
25113 compiler
.ofilename
= argv
[2];
25117 else if (!all_opts
&& argv
[1][0] == '-') {
25120 if (strcmp(argv
[1], "--") == 0) {
25124 else if (strncmp(argv
[1], "-E", 2) == 0) {
25125 result
= compiler_encode_flag(&compiler
, argv
[1]);
25127 else if (strncmp(argv
[1], "-O", 2) == 0) {
25128 result
= compiler_encode_flag(&compiler
, argv
[1]);
25130 else if (strncmp(argv
[1], "-I", 2) == 0) {
25131 result
= compiler_encode_flag(&compiler
, argv
[1]);
25133 else if (strncmp(argv
[1], "-D", 2) == 0) {
25134 result
= compiler_encode_flag(&compiler
, argv
[1]);
25136 else if (strncmp(argv
[1], "-U", 2) == 0) {
25137 result
= compiler_encode_flag(&compiler
, argv
[1]);
25139 else if (strncmp(argv
[1], "--label-prefix=", 15) == 0) {
25140 result
= compiler_encode_flag(&compiler
, argv
[1]+2);
25142 else if (strncmp(argv
[1], "-f", 2) == 0) {
25143 result
= compiler_encode_flag(&compiler
, argv
[1]+2);
25145 else if (strncmp(argv
[1], "-m", 2) == 0) {
25146 result
= arch_encode_flag(&arch
, argv
[1]+2);
25148 else if (strncmp(argv
[1], "-c", 2) == 0) {
25151 else if (strncmp(argv
[1], "-S", 2) == 0) {
25154 else if (strncmp(argv
[1], "-include", 10) == 0) {
25155 struct filelist
*old_head
= include_filelist
;
25156 include_filelist
= malloc(sizeof(struct filelist
));
25157 if (!include_filelist
) {
25158 die("Out of memory.\n");
25162 include_filelist
->filename
= strdup(argv
[1]);
25163 include_filelist
->next
= old_head
;
25167 arg_error("Invalid option specified: %s\n",
25175 arg_error("Only one filename may be specified\n");
25177 filename
= argv
[1];
25183 arg_error("No filename specified\n");
25185 compile(filename
, &compiler
, &arch
);