5 #define VERSION_MAJOR "0"
6 #define VERSION_MINOR "73"
7 #define RELEASE_DATE "08 May 2013"
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
)) {
227 static char *slurp_file(const char *dirname
, const char *filename
, off_t
*r_size
)
229 char cwd
[MAX_CWD_SIZE
];
231 off_t size
, progress
;
239 if (getcwd(cwd
, sizeof(cwd
)) == 0) {
240 die("cwd buffer to small");
243 file
= fopen(filename
, "rb");
246 die("Cannot open '%s' : %s\n",
247 filename
, strerror(errno
));
249 fseek(file
, 0, SEEK_END
);
251 fseek(file
, 0, SEEK_SET
);
253 buf
= xmalloc(size
+2, filename
);
254 buf
[size
] = '\n'; /* Make certain the file is newline terminated */
255 buf
[size
+1] = '\0'; /* Null terminate the file for good measure */
257 while(progress
< size
) {
258 result
= fread(buf
+ progress
, 1, size
- progress
, file
);
260 if ((errno
== EINTR
) || (errno
== EAGAIN
))
262 die("read on %s of %ld bytes failed: %s\n",
263 filename
, (size
- progress
)+ 0UL, strerror(errno
));
271 /* Types on the destination platform */
272 #if DEBUG_ROMCC_WARNINGS
273 #warning "FIXME this assumes 32bit x86 is the destination"
275 typedef int8_t schar_t
;
276 typedef uint8_t uchar_t
;
277 typedef int8_t char_t
;
278 typedef int16_t short_t
;
279 typedef uint16_t ushort_t
;
280 typedef int32_t int_t
;
281 typedef uint32_t uint_t
;
282 typedef int32_t long_t
;
283 #define ulong_t uint32_t
285 #define SCHAR_T_MIN (-128)
286 #define SCHAR_T_MAX 127
287 #define UCHAR_T_MAX 255
288 #define CHAR_T_MIN SCHAR_T_MIN
289 #define CHAR_T_MAX SCHAR_T_MAX
290 #define SHRT_T_MIN (-32768)
291 #define SHRT_T_MAX 32767
292 #define USHRT_T_MAX 65535
293 #define INT_T_MIN (-LONG_T_MAX - 1)
294 #define INT_T_MAX 2147483647
295 #define UINT_T_MAX 4294967295U
296 #define LONG_T_MIN (-LONG_T_MAX - 1)
297 #define LONG_T_MAX 2147483647
298 #define ULONG_T_MAX 4294967295U
301 #define SIZEOF_I16 16
302 #define SIZEOF_I32 32
303 #define SIZEOF_I64 64
305 #define SIZEOF_CHAR 8
306 #define SIZEOF_SHORT 16
307 #define SIZEOF_INT 32
308 #define SIZEOF_LONG (sizeof(long_t)*SIZEOF_CHAR)
311 #define ALIGNOF_CHAR 8
312 #define ALIGNOF_SHORT 16
313 #define ALIGNOF_INT 32
314 #define ALIGNOF_LONG (sizeof(long_t)*SIZEOF_CHAR)
316 #define REG_SIZEOF_REG 32
317 #define REG_SIZEOF_CHAR REG_SIZEOF_REG
318 #define REG_SIZEOF_SHORT REG_SIZEOF_REG
319 #define REG_SIZEOF_INT REG_SIZEOF_REG
320 #define REG_SIZEOF_LONG REG_SIZEOF_REG
322 #define REG_ALIGNOF_REG REG_SIZEOF_REG
323 #define REG_ALIGNOF_CHAR REG_SIZEOF_REG
324 #define REG_ALIGNOF_SHORT REG_SIZEOF_REG
325 #define REG_ALIGNOF_INT REG_SIZEOF_REG
326 #define REG_ALIGNOF_LONG REG_SIZEOF_REG
328 /* Additional definitions for clarity.
329 * I currently assume a long is the largest native
330 * machine word and that a pointer fits into it.
332 #define SIZEOF_WORD SIZEOF_LONG
333 #define SIZEOF_POINTER SIZEOF_LONG
334 #define ALIGNOF_WORD ALIGNOF_LONG
335 #define ALIGNOF_POINTER ALIGNOF_LONG
336 #define REG_SIZEOF_POINTER REG_SIZEOF_LONG
337 #define REG_ALIGNOF_POINTER REG_ALIGNOF_LONG
340 struct file_state
*prev
;
341 const char *basename
;
347 const char *line_start
;
349 const char *report_name
;
350 const char *report_dir
;
358 struct hash_entry
*ident
;
368 /* I have two classes of types:
370 * Logical types. (The type the C standard says the operation is of)
372 * The operational types are:
387 * No memory is useable by the compiler.
388 * There is no floating point support.
389 * All operations take place in general purpose registers.
390 * There is one type of general purpose register.
391 * Unsigned longs are stored in that general purpose register.
394 /* Operations on general purpose registers.
413 #define OP_POS 16 /* Dummy positive operator don't use it */
423 #define OP_SLESSEQ 26
424 #define OP_ULESSEQ 27
425 #define OP_SMOREEQ 28
426 #define OP_UMOREEQ 29
428 #define OP_LFALSE 30 /* Test if the expression is logically false */
429 #define OP_LTRUE 31 /* Test if the expression is logcially true */
433 /* For OP_STORE ->type holds the type
434 * RHS(0) holds the destination address
435 * RHS(1) holds the value to store.
438 #define OP_UEXTRACT 34
439 /* OP_UEXTRACT extracts an unsigned bitfield from a pseudo register
440 * RHS(0) holds the psuedo register to extract from
441 * ->type holds the size of the bitfield.
442 * ->u.bitfield.size holds the size of the bitfield.
443 * ->u.bitfield.offset holds the offset to extract from
445 #define OP_SEXTRACT 35
446 /* OP_SEXTRACT extracts a signed bitfield from a pseudo register
447 * RHS(0) holds the psuedo register to extract from
448 * ->type holds the size of the bitfield.
449 * ->u.bitfield.size holds the size of the bitfield.
450 * ->u.bitfield.offset holds the offset to extract from
452 #define OP_DEPOSIT 36
453 /* OP_DEPOSIT replaces a bitfield with a new value.
454 * RHS(0) holds the value to replace a bitifield in.
455 * RHS(1) holds the replacement value
456 * ->u.bitfield.size holds the size of the bitfield.
457 * ->u.bitfield.offset holds the deposit into
462 #define OP_MIN_CONST 50
463 #define OP_MAX_CONST 58
464 #define IS_CONST_OP(X) (((X) >= OP_MIN_CONST) && ((X) <= OP_MAX_CONST))
465 #define OP_INTCONST 50
466 /* For OP_INTCONST ->type holds the type.
467 * ->u.cval holds the constant value.
469 #define OP_BLOBCONST 51
470 /* For OP_BLOBCONST ->type holds the layout and size
471 * information. u.blob holds a pointer to the raw binary
472 * data for the constant initializer.
474 #define OP_ADDRCONST 52
475 /* For OP_ADDRCONST ->type holds the type.
476 * MISC(0) holds the reference to the static variable.
477 * ->u.cval holds an offset from that value.
479 #define OP_UNKNOWNVAL 59
480 /* For OP_UNKNOWNAL ->type holds the type.
481 * For some reason we don't know what value this type has.
482 * This allows for variables that have don't have values
483 * assigned yet, or variables whose value we simply do not know.
487 /* OP_WRITE moves one pseudo register to another.
488 * MISC(0) holds the destination pseudo register, which must be an OP_DECL.
489 * RHS(0) holds the psuedo to move.
493 /* OP_READ reads the value of a variable and makes
494 * it available for the pseudo operation.
495 * Useful for things like def-use chains.
496 * RHS(0) holds points to the triple to read from.
499 /* OP_COPY makes a copy of the pseudo register or constant in RHS(0).
501 #define OP_CONVERT 63
502 /* OP_CONVERT makes a copy of the pseudo register or constant in RHS(0).
503 * And then the type is converted appropriately.
506 /* OP_PIECE returns one piece of a instruction that returns a structure.
507 * MISC(0) is the instruction
508 * u.cval is the LHS piece of the instruction to return.
511 /* OP_ASM holds a sequence of assembly instructions, the result
512 * of a C asm directive.
513 * RHS(x) holds input value x to the assembly sequence.
514 * LHS(x) holds the output value x from the assembly sequence.
515 * u.blob holds the string of assembly instructions.
519 /* OP_DEREF generates an lvalue from a pointer.
520 * RHS(0) holds the pointer value.
521 * OP_DEREF serves as a place holder to indicate all necessary
522 * checks have been done to indicate a value is an lvalue.
525 /* OP_DOT references a submember of a structure lvalue.
526 * MISC(0) holds the lvalue.
527 * ->u.field holds the name of the field we want.
529 * Not seen after structures are flattened.
532 /* OP_INDEX references a submember of a tuple or array lvalue.
533 * MISC(0) holds the lvalue.
534 * ->u.cval holds the index into the lvalue.
536 * Not seen after structures are flattened.
539 /* OP_VAL returns the value of a subexpression of the current expression.
540 * Useful for operators that have side effects.
541 * RHS(0) holds the expression.
542 * MISC(0) holds the subexpression of RHS(0) that is the
543 * value of the expression.
545 * Not seen outside of expressions.
549 /* OP_TUPLE is an array of triples that are either variable
550 * or values for a structure or an array. It is used as
551 * a place holder when flattening compound types.
552 * The value represented by an OP_TUPLE is held in N registers.
553 * LHS(0..N-1) refer to those registers.
554 * ->use is a list of statements that use the value.
556 * Although OP_TUPLE always has register sized pieces they are not
557 * used until structures are flattened/decomposed into their register
559 * ???? registers ????
563 /* OP_BITREF describes a bitfield as an lvalue.
564 * RHS(0) holds the register value.
565 * ->type holds the type of the bitfield.
566 * ->u.bitfield.size holds the size of the bitfield.
567 * ->u.bitfield.offset holds the offset of the bitfield in the register
572 /* OP_FCALL performs a procedure call.
573 * MISC(0) holds a pointer to the OP_LIST of a function
574 * RHS(x) holds argument x of a function
576 * Currently not seen outside of expressions.
579 /* OP_PROG is an expression that holds a list of statements, or
580 * expressions. The final expression is the value of the expression.
581 * RHS(0) holds the start of the list.
586 /* OP_LIST Holds a list of statements that compose a function, and a result value.
587 * RHS(0) holds the list of statements.
588 * A list of all functions is maintained.
591 #define OP_BRANCH 81 /* an unconditional branch */
592 /* For branch instructions
593 * TARG(0) holds the branch target.
594 * ->next holds where to branch to if the branch is not taken.
595 * The branch target can only be a label
598 #define OP_CBRANCH 82 /* a conditional branch */
599 /* For conditional branch instructions
600 * RHS(0) holds the branch condition.
601 * TARG(0) holds the branch target.
602 * ->next holds where to branch to if the branch is not taken.
603 * The branch target can only be a label
606 #define OP_CALL 83 /* an uncontional branch that will return */
607 /* For call instructions
608 * MISC(0) holds the OP_RET that returns from the branch
609 * TARG(0) holds the branch target.
610 * ->next holds where to branch to if the branch is not taken.
611 * The branch target can only be a label
614 #define OP_RET 84 /* an uncontinonal branch through a variable back to an OP_CALL */
615 /* For call instructions
616 * RHS(0) holds the variable with the return address
617 * The branch target can only be a label
621 /* OP_LABEL is a triple that establishes an target for branches.
622 * ->use is the list of all branches that use this label.
626 /* OP_ADECL is a triple that establishes an lvalue for assignments.
627 * A variable takes N registers to contain.
628 * LHS(0..N-1) refer to an OP_PIECE triple that represents
629 * the Xth register that the variable is stored in.
630 * ->use is a list of statements that use the variable.
632 * Although OP_ADECL always has register sized pieces they are not
633 * used until structures are flattened/decomposed into their register
638 /* OP_SDECL is a triple that establishes a variable of static
640 * ->use is a list of statements that use the variable.
641 * MISC(0) holds the initializer expression.
646 /* OP_PHI is a triple used in SSA form code.
647 * It is used when multiple code paths merge and a variable needs
648 * a single assignment from any of those code paths.
649 * The operation is a cross between OP_DECL and OP_WRITE, which
650 * is what OP_PHI is generated from.
652 * RHS(x) points to the value from code path x
653 * The number of RHS entries is the number of control paths into the block
654 * in which OP_PHI resides. The elements of the array point to point
655 * to the variables OP_PHI is derived from.
657 * MISC(0) holds a pointer to the orginal OP_DECL node.
661 /* continuation helpers
663 #define OP_CPS_BRANCH 90 /* an unconditional branch */
664 /* OP_CPS_BRANCH calls a continuation
665 * RHS(x) holds argument x of the function
666 * TARG(0) holds OP_CPS_START target
668 #define OP_CPS_CBRANCH 91 /* a conditional branch */
669 /* OP_CPS_CBRANCH conditionally calls one of two continuations
670 * RHS(0) holds the branch condition
671 * RHS(x + 1) holds argument x of the function
672 * TARG(0) holds the OP_CPS_START to jump to when true
673 * ->next holds the OP_CPS_START to jump to when false
675 #define OP_CPS_CALL 92 /* an uncontional branch that will return */
676 /* For OP_CPS_CALL instructions
677 * RHS(x) holds argument x of the function
678 * MISC(0) holds the OP_CPS_RET that returns from the branch
679 * TARG(0) holds the branch target.
680 * ->next holds where the OP_CPS_RET will return to.
682 #define OP_CPS_RET 93
683 /* OP_CPS_RET conditionally calls one of two continuations
684 * RHS(0) holds the variable with the return function address
685 * RHS(x + 1) holds argument x of the function
686 * The branch target may be any OP_CPS_START
688 #define OP_CPS_END 94
689 /* OP_CPS_END is the triple at the end of the program.
690 * For most practical purposes it is a branch.
692 #define OP_CPS_START 95
693 /* OP_CPS_START is a triple at the start of a continuation
694 * The arguments variables takes N registers to contain.
695 * LHS(0..N-1) refer to an OP_PIECE triple that represents
696 * the Xth register that the arguments are stored in.
700 /* Architecture specific instructions */
703 #define OP_SET_EQ 102
704 #define OP_SET_NOTEQ 103
705 #define OP_SET_SLESS 104
706 #define OP_SET_ULESS 105
707 #define OP_SET_SMORE 106
708 #define OP_SET_UMORE 107
709 #define OP_SET_SLESSEQ 108
710 #define OP_SET_ULESSEQ 109
711 #define OP_SET_SMOREEQ 110
712 #define OP_SET_UMOREEQ 111
715 #define OP_JMP_EQ 113
716 #define OP_JMP_NOTEQ 114
717 #define OP_JMP_SLESS 115
718 #define OP_JMP_ULESS 116
719 #define OP_JMP_SMORE 117
720 #define OP_JMP_UMORE 118
721 #define OP_JMP_SLESSEQ 119
722 #define OP_JMP_ULESSEQ 120
723 #define OP_JMP_SMOREEQ 121
724 #define OP_JMP_UMOREEQ 122
726 /* Builtin operators that it is just simpler to use the compiler for */
742 #define PURE 0x001 /* Triple has no side effects */
743 #define IMPURE 0x002 /* Triple has side effects */
744 #define PURE_BITS(FLAGS) ((FLAGS) & 0x3)
745 #define DEF 0x004 /* Triple is a variable definition */
746 #define BLOCK 0x008 /* Triple stores the current block */
747 #define STRUCTURAL 0x010 /* Triple does not generate a machine instruction */
748 #define BRANCH_BITS(FLAGS) ((FLAGS) & 0xe0 )
749 #define UBRANCH 0x020 /* Triple is an unconditional branch instruction */
750 #define CBRANCH 0x040 /* Triple is a conditional branch instruction */
751 #define RETBRANCH 0x060 /* Triple is a return instruction */
752 #define CALLBRANCH 0x080 /* Triple is a call instruction */
753 #define ENDBRANCH 0x0a0 /* Triple is an end instruction */
754 #define PART 0x100 /* Triple is really part of another triple */
755 #define BITFIELD 0x200 /* Triple manipulates a bitfield */
756 signed char lhs
, rhs
, misc
, targ
;
759 #define OP(LHS, RHS, MISC, TARG, FLAGS, NAME) { \
767 static const struct op_info table_ops
[] = {
768 [OP_SDIVT
] = OP( 2, 2, 0, 0, PURE
| BLOCK
, "sdivt"),
769 [OP_UDIVT
] = OP( 2, 2, 0, 0, PURE
| BLOCK
, "udivt"),
770 [OP_SMUL
] = OP( 0, 2, 0, 0, PURE
| DEF
| BLOCK
, "smul"),
771 [OP_UMUL
] = OP( 0, 2, 0, 0, PURE
| DEF
| BLOCK
, "umul"),
772 [OP_SDIV
] = OP( 0, 2, 0, 0, PURE
| DEF
| BLOCK
, "sdiv"),
773 [OP_UDIV
] = OP( 0, 2, 0, 0, PURE
| DEF
| BLOCK
, "udiv"),
774 [OP_SMOD
] = OP( 0, 2, 0, 0, PURE
| DEF
| BLOCK
, "smod"),
775 [OP_UMOD
] = OP( 0, 2, 0, 0, PURE
| DEF
| BLOCK
, "umod"),
776 [OP_ADD
] = OP( 0, 2, 0, 0, PURE
| DEF
| BLOCK
, "add"),
777 [OP_SUB
] = OP( 0, 2, 0, 0, PURE
| DEF
| BLOCK
, "sub"),
778 [OP_SL
] = OP( 0, 2, 0, 0, PURE
| DEF
| BLOCK
, "sl"),
779 [OP_USR
] = OP( 0, 2, 0, 0, PURE
| DEF
| BLOCK
, "usr"),
780 [OP_SSR
] = OP( 0, 2, 0, 0, PURE
| DEF
| BLOCK
, "ssr"),
781 [OP_AND
] = OP( 0, 2, 0, 0, PURE
| DEF
| BLOCK
, "and"),
782 [OP_XOR
] = OP( 0, 2, 0, 0, PURE
| DEF
| BLOCK
, "xor"),
783 [OP_OR
] = OP( 0, 2, 0, 0, PURE
| DEF
| BLOCK
, "or"),
784 [OP_POS
] = OP( 0, 1, 0, 0, PURE
| DEF
| BLOCK
, "pos"),
785 [OP_NEG
] = OP( 0, 1, 0, 0, PURE
| DEF
| BLOCK
, "neg"),
786 [OP_INVERT
] = OP( 0, 1, 0, 0, PURE
| DEF
| BLOCK
, "invert"),
788 [OP_EQ
] = OP( 0, 2, 0, 0, PURE
| DEF
| BLOCK
, "eq"),
789 [OP_NOTEQ
] = OP( 0, 2, 0, 0, PURE
| DEF
| BLOCK
, "noteq"),
790 [OP_SLESS
] = OP( 0, 2, 0, 0, PURE
| DEF
| BLOCK
, "sless"),
791 [OP_ULESS
] = OP( 0, 2, 0, 0, PURE
| DEF
| BLOCK
, "uless"),
792 [OP_SMORE
] = OP( 0, 2, 0, 0, PURE
| DEF
| BLOCK
, "smore"),
793 [OP_UMORE
] = OP( 0, 2, 0, 0, PURE
| DEF
| BLOCK
, "umore"),
794 [OP_SLESSEQ
] = OP( 0, 2, 0, 0, PURE
| DEF
| BLOCK
, "slesseq"),
795 [OP_ULESSEQ
] = OP( 0, 2, 0, 0, PURE
| DEF
| BLOCK
, "ulesseq"),
796 [OP_SMOREEQ
] = OP( 0, 2, 0, 0, PURE
| DEF
| BLOCK
, "smoreeq"),
797 [OP_UMOREEQ
] = OP( 0, 2, 0, 0, PURE
| DEF
| BLOCK
, "umoreeq"),
798 [OP_LFALSE
] = OP( 0, 1, 0, 0, PURE
| DEF
| BLOCK
, "lfalse"),
799 [OP_LTRUE
] = OP( 0, 1, 0, 0, PURE
| DEF
| BLOCK
, "ltrue"),
801 [OP_LOAD
] = OP( 0, 1, 0, 0, PURE
| DEF
| BLOCK
, "load"),
802 [OP_STORE
] = OP( 0, 2, 0, 0, PURE
| BLOCK
, "store"),
804 [OP_UEXTRACT
] = OP( 0, 1, 0, 0, PURE
| DEF
| BITFIELD
, "uextract"),
805 [OP_SEXTRACT
] = OP( 0, 1, 0, 0, PURE
| DEF
| BITFIELD
, "sextract"),
806 [OP_DEPOSIT
] = OP( 0, 2, 0, 0, PURE
| DEF
| BITFIELD
, "deposit"),
808 [OP_NOOP
] = OP( 0, 0, 0, 0, PURE
| BLOCK
| STRUCTURAL
, "noop"),
810 [OP_INTCONST
] = OP( 0, 0, 0, 0, PURE
| DEF
, "intconst"),
811 [OP_BLOBCONST
] = OP( 0, 0, 0, 0, PURE
, "blobconst"),
812 [OP_ADDRCONST
] = OP( 0, 0, 1, 0, PURE
| DEF
, "addrconst"),
813 [OP_UNKNOWNVAL
] = OP( 0, 0, 0, 0, PURE
| DEF
, "unknown"),
815 #if DEBUG_ROMCC_WARNINGS
816 #warning "FIXME is it correct for OP_WRITE to be a def? I currently use it as one..."
818 [OP_WRITE
] = OP( 0, 1, 1, 0, PURE
| DEF
| BLOCK
, "write"),
819 [OP_READ
] = OP( 0, 1, 0, 0, PURE
| DEF
| BLOCK
, "read"),
820 [OP_COPY
] = OP( 0, 1, 0, 0, PURE
| DEF
| BLOCK
, "copy"),
821 [OP_CONVERT
] = OP( 0, 1, 0, 0, PURE
| DEF
| BLOCK
, "convert"),
822 [OP_PIECE
] = OP( 0, 0, 1, 0, PURE
| DEF
| STRUCTURAL
| PART
, "piece"),
823 [OP_ASM
] = OP(-1, -1, 0, 0, PURE
, "asm"),
824 [OP_DEREF
] = OP( 0, 1, 0, 0, 0 | DEF
| BLOCK
, "deref"),
825 [OP_DOT
] = OP( 0, 0, 1, 0, PURE
| DEF
| PART
, "dot"),
826 [OP_INDEX
] = OP( 0, 0, 1, 0, PURE
| DEF
| PART
, "index"),
828 [OP_VAL
] = OP( 0, 1, 1, 0, 0 | DEF
| BLOCK
, "val"),
829 [OP_TUPLE
] = OP(-1, 0, 0, 0, 0 | PURE
| BLOCK
| STRUCTURAL
, "tuple"),
830 [OP_BITREF
] = OP( 0, 1, 0, 0, 0 | DEF
| PURE
| STRUCTURAL
| BITFIELD
, "bitref"),
831 /* Call is special most it can stand in for anything so it depends on context */
832 [OP_FCALL
] = OP( 0, -1, 1, 0, 0 | BLOCK
| CALLBRANCH
, "fcall"),
833 [OP_PROG
] = OP( 0, 1, 0, 0, 0 | IMPURE
| BLOCK
| STRUCTURAL
, "prog"),
834 /* The sizes of OP_FCALL depends upon context */
836 [OP_LIST
] = OP( 0, 1, 1, 0, 0 | DEF
| STRUCTURAL
, "list"),
837 [OP_BRANCH
] = OP( 0, 0, 0, 1, PURE
| BLOCK
| UBRANCH
, "branch"),
838 [OP_CBRANCH
] = OP( 0, 1, 0, 1, PURE
| BLOCK
| CBRANCH
, "cbranch"),
839 [OP_CALL
] = OP( 0, 0, 1, 1, PURE
| BLOCK
| CALLBRANCH
, "call"),
840 [OP_RET
] = OP( 0, 1, 0, 0, PURE
| BLOCK
| RETBRANCH
, "ret"),
841 [OP_LABEL
] = OP( 0, 0, 0, 0, PURE
| BLOCK
| STRUCTURAL
, "label"),
842 [OP_ADECL
] = OP( 0, 0, 0, 0, PURE
| BLOCK
| STRUCTURAL
, "adecl"),
843 [OP_SDECL
] = OP( 0, 0, 1, 0, PURE
| BLOCK
| STRUCTURAL
, "sdecl"),
844 /* The number of RHS elements of OP_PHI depend upon context */
845 [OP_PHI
] = OP( 0, -1, 1, 0, PURE
| DEF
| BLOCK
, "phi"),
848 [OP_CPS_BRANCH
] = OP( 0, -1, 0, 1, PURE
| BLOCK
| UBRANCH
, "cps_branch"),
849 [OP_CPS_CBRANCH
] = OP( 0, -1, 0, 1, PURE
| BLOCK
| CBRANCH
, "cps_cbranch"),
850 [OP_CPS_CALL
] = OP( 0, -1, 1, 1, PURE
| BLOCK
| CALLBRANCH
, "cps_call"),
851 [OP_CPS_RET
] = OP( 0, -1, 0, 0, PURE
| BLOCK
| RETBRANCH
, "cps_ret"),
852 [OP_CPS_END
] = OP( 0, -1, 0, 0, IMPURE
| BLOCK
| ENDBRANCH
, "cps_end"),
853 [OP_CPS_START
] = OP( -1, 0, 0, 0, PURE
| BLOCK
| STRUCTURAL
, "cps_start"),
856 [OP_CMP
] = OP( 0, 2, 0, 0, PURE
| DEF
| BLOCK
, "cmp"),
857 [OP_TEST
] = OP( 0, 1, 0, 0, PURE
| DEF
| BLOCK
, "test"),
858 [OP_SET_EQ
] = OP( 0, 1, 0, 0, PURE
| DEF
| BLOCK
, "set_eq"),
859 [OP_SET_NOTEQ
] = OP( 0, 1, 0, 0, PURE
| DEF
| BLOCK
, "set_noteq"),
860 [OP_SET_SLESS
] = OP( 0, 1, 0, 0, PURE
| DEF
| BLOCK
, "set_sless"),
861 [OP_SET_ULESS
] = OP( 0, 1, 0, 0, PURE
| DEF
| BLOCK
, "set_uless"),
862 [OP_SET_SMORE
] = OP( 0, 1, 0, 0, PURE
| DEF
| BLOCK
, "set_smore"),
863 [OP_SET_UMORE
] = OP( 0, 1, 0, 0, PURE
| DEF
| BLOCK
, "set_umore"),
864 [OP_SET_SLESSEQ
] = OP( 0, 1, 0, 0, PURE
| DEF
| BLOCK
, "set_slesseq"),
865 [OP_SET_ULESSEQ
] = OP( 0, 1, 0, 0, PURE
| DEF
| BLOCK
, "set_ulesseq"),
866 [OP_SET_SMOREEQ
] = OP( 0, 1, 0, 0, PURE
| DEF
| BLOCK
, "set_smoreq"),
867 [OP_SET_UMOREEQ
] = OP( 0, 1, 0, 0, PURE
| DEF
| BLOCK
, "set_umoreq"),
868 [OP_JMP
] = OP( 0, 0, 0, 1, PURE
| BLOCK
| UBRANCH
, "jmp"),
869 [OP_JMP_EQ
] = OP( 0, 1, 0, 1, PURE
| BLOCK
| CBRANCH
, "jmp_eq"),
870 [OP_JMP_NOTEQ
] = OP( 0, 1, 0, 1, PURE
| BLOCK
| CBRANCH
, "jmp_noteq"),
871 [OP_JMP_SLESS
] = OP( 0, 1, 0, 1, PURE
| BLOCK
| CBRANCH
, "jmp_sless"),
872 [OP_JMP_ULESS
] = OP( 0, 1, 0, 1, PURE
| BLOCK
| CBRANCH
, "jmp_uless"),
873 [OP_JMP_SMORE
] = OP( 0, 1, 0, 1, PURE
| BLOCK
| CBRANCH
, "jmp_smore"),
874 [OP_JMP_UMORE
] = OP( 0, 1, 0, 1, PURE
| BLOCK
| CBRANCH
, "jmp_umore"),
875 [OP_JMP_SLESSEQ
] = OP( 0, 1, 0, 1, PURE
| BLOCK
| CBRANCH
, "jmp_slesseq"),
876 [OP_JMP_ULESSEQ
] = OP( 0, 1, 0, 1, PURE
| BLOCK
| CBRANCH
, "jmp_ulesseq"),
877 [OP_JMP_SMOREEQ
] = OP( 0, 1, 0, 1, PURE
| BLOCK
| CBRANCH
, "jmp_smoreq"),
878 [OP_JMP_UMOREEQ
] = OP( 0, 1, 0, 1, PURE
| BLOCK
| CBRANCH
, "jmp_umoreq"),
880 [OP_INB
] = OP( 0, 1, 0, 0, IMPURE
| DEF
| BLOCK
, "__inb"),
881 [OP_INW
] = OP( 0, 1, 0, 0, IMPURE
| DEF
| BLOCK
, "__inw"),
882 [OP_INL
] = OP( 0, 1, 0, 0, IMPURE
| DEF
| BLOCK
, "__inl"),
883 [OP_OUTB
] = OP( 0, 2, 0, 0, IMPURE
| BLOCK
, "__outb"),
884 [OP_OUTW
] = OP( 0, 2, 0, 0, IMPURE
| BLOCK
, "__outw"),
885 [OP_OUTL
] = OP( 0, 2, 0, 0, IMPURE
| BLOCK
, "__outl"),
886 [OP_BSF
] = OP( 0, 1, 0, 0, PURE
| DEF
| BLOCK
, "__bsf"),
887 [OP_BSR
] = OP( 0, 1, 0, 0, PURE
| DEF
| BLOCK
, "__bsr"),
888 [OP_RDMSR
] = OP( 2, 1, 0, 0, IMPURE
| BLOCK
, "__rdmsr"),
889 [OP_WRMSR
] = OP( 0, 3, 0, 0, IMPURE
| BLOCK
, "__wrmsr"),
890 [OP_HLT
] = OP( 0, 0, 0, 0, IMPURE
| BLOCK
, "__hlt"),
893 #define OP_MAX (sizeof(table_ops)/sizeof(table_ops[0]))
895 static const char *tops(int index
)
897 static const char unknown
[] = "unknown op";
901 if (index
>= OP_MAX
) {
904 return table_ops
[index
].name
;
911 struct triple_set
*next
;
912 struct triple
*member
;
922 const char *filename
;
923 const char *function
;
926 struct occurance
*parent
;
933 struct triple
*next
, *prev
;
934 struct triple_set
*use
;
937 unsigned int template_id
: 7;
938 unsigned int lhs
: 6;
939 unsigned int rhs
: 7;
940 unsigned int misc
: 2;
941 unsigned int targ
: 1;
942 #define TRIPLE_SIZE(TRIPLE) \
943 ((TRIPLE)->lhs + (TRIPLE)->rhs + (TRIPLE)->misc + (TRIPLE)->targ)
944 #define TRIPLE_LHS_OFF(PTR) (0)
945 #define TRIPLE_RHS_OFF(PTR) (TRIPLE_LHS_OFF(PTR) + (PTR)->lhs)
946 #define TRIPLE_MISC_OFF(PTR) (TRIPLE_RHS_OFF(PTR) + (PTR)->rhs)
947 #define TRIPLE_TARG_OFF(PTR) (TRIPLE_MISC_OFF(PTR) + (PTR)->misc)
948 #define LHS(PTR,INDEX) ((PTR)->param[TRIPLE_LHS_OFF(PTR) + (INDEX)])
949 #define RHS(PTR,INDEX) ((PTR)->param[TRIPLE_RHS_OFF(PTR) + (INDEX)])
950 #define TARG(PTR,INDEX) ((PTR)->param[TRIPLE_TARG_OFF(PTR) + (INDEX)])
951 #define MISC(PTR,INDEX) ((PTR)->param[TRIPLE_MISC_OFF(PTR) + (INDEX)])
952 unsigned id
; /* A scratch value and finally the register */
953 #define TRIPLE_FLAG_FLATTENED (1 << 31)
954 #define TRIPLE_FLAG_PRE_SPLIT (1 << 30)
955 #define TRIPLE_FLAG_POST_SPLIT (1 << 29)
956 #define TRIPLE_FLAG_VOLATILE (1 << 28)
957 #define TRIPLE_FLAG_INLINE (1 << 27) /* ???? */
958 #define TRIPLE_FLAG_LOCAL (1 << 26)
960 #define TRIPLE_FLAG_COPY TRIPLE_FLAG_VOLATILE
961 struct occurance
*occurance
;
964 struct bitfield bitfield
;
967 struct hash_entry
*field
;
968 struct asm_info
*ainfo
;
970 struct symbol
*symbol
;
972 struct triple
*param
[2];
979 struct ins_template
{
980 struct reg_info lhs
[MAX_LHS
+ 1], rhs
[MAX_RHS
+ 1];
984 struct ins_template tmpl
;
989 struct block_set
*next
;
990 struct block
*member
;
993 struct block
*work_next
;
994 struct triple
*first
, *last
;
996 struct block_set
*edges
;
998 struct block_set
*use
;
999 struct block_set
*idominates
;
1000 struct block_set
*domfrontier
;
1002 struct block_set
*ipdominates
;
1003 struct block_set
*ipdomfrontier
;
1004 struct block
*ipdom
;
1010 struct symbol
*next
;
1011 struct hash_entry
*ident
;
1018 struct macro_arg
*next
;
1019 struct hash_entry
*ident
;
1022 struct hash_entry
*ident
;
1025 struct macro_arg
*args
;
1030 struct hash_entry
*next
;
1034 struct macro
*sym_define
;
1035 struct symbol
*sym_label
;
1036 struct symbol
*sym_tag
;
1037 struct symbol
*sym_ident
;
1040 #define HASH_TABLE_SIZE 2048
1042 struct compiler_state
{
1043 const char *label_prefix
;
1044 const char *ofilename
;
1045 unsigned long flags
;
1046 unsigned long debug
;
1047 unsigned long max_allocation_passes
;
1049 size_t include_path_count
;
1050 const char **include_paths
;
1052 size_t define_count
;
1053 const char **defines
;
1056 const char **undefs
;
1059 unsigned long features
;
1061 struct basic_blocks
{
1062 struct triple
*func
;
1063 struct triple
*first
;
1064 struct block
*first_block
, *last_block
;
1067 #define MAX_PP_IF_DEPTH 63
1068 struct compile_state
{
1069 struct compiler_state
*compiler
;
1070 struct arch_state
*arch
;
1074 struct file_state
*file
;
1075 struct occurance
*last_occurance
;
1076 const char *function
;
1078 struct token token
[6];
1079 struct hash_entry
*hash_table
[HASH_TABLE_SIZE
];
1080 struct hash_entry
*i_switch
;
1081 struct hash_entry
*i_case
;
1082 struct hash_entry
*i_continue
;
1083 struct hash_entry
*i_break
;
1084 struct hash_entry
*i_default
;
1085 struct hash_entry
*i_return
;
1086 struct hash_entry
*i_noreturn
;
1087 struct hash_entry
*i_unused
;
1088 struct hash_entry
*i_packed
;
1089 /* Additional hash entries for predefined macros */
1090 struct hash_entry
*i_defined
;
1091 struct hash_entry
*i___VA_ARGS__
;
1092 struct hash_entry
*i___FILE__
;
1093 struct hash_entry
*i___LINE__
;
1094 /* Additional hash entries for predefined identifiers */
1095 struct hash_entry
*i___func__
;
1096 /* Additional hash entries for attributes */
1097 struct hash_entry
*i_noinline
;
1098 struct hash_entry
*i_always_inline
;
1100 unsigned char if_bytes
[(MAX_PP_IF_DEPTH
+ CHAR_BIT
-1)/CHAR_BIT
];
1102 int eat_depth
, eat_targ
;
1103 struct file_state
*macro_file
;
1104 struct triple
*functions
;
1105 struct triple
*main_function
;
1106 struct triple
*first
;
1107 struct triple
*global_pool
;
1108 struct basic_blocks bb
;
1109 int functions_joined
;
1112 /* visibility global/local */
1113 /* static/auto duration */
1114 /* typedef, register, inline */
1115 #define STOR_SHIFT 0
1116 #define STOR_MASK 0x001f
1118 #define STOR_GLOBAL 0x0001
1120 #define STOR_PERM 0x0002
1121 /* Definition locality */
1122 #define STOR_NONLOCAL 0x0004 /* The definition is not in this translation unit */
1123 /* Storage specifiers */
1124 #define STOR_AUTO 0x0000
1125 #define STOR_STATIC 0x0002
1126 #define STOR_LOCAL 0x0003
1127 #define STOR_EXTERN 0x0007
1128 #define STOR_INLINE 0x0008
1129 #define STOR_REGISTER 0x0010
1130 #define STOR_TYPEDEF 0x0018
1132 #define QUAL_SHIFT 5
1133 #define QUAL_MASK 0x00e0
1134 #define QUAL_NONE 0x0000
1135 #define QUAL_CONST 0x0020
1136 #define QUAL_VOLATILE 0x0040
1137 #define QUAL_RESTRICT 0x0080
1139 #define TYPE_SHIFT 8
1140 #define TYPE_MASK 0x1f00
1141 #define TYPE_INTEGER(TYPE) ((((TYPE) >= TYPE_CHAR) && ((TYPE) <= TYPE_ULLONG)) || ((TYPE) == TYPE_ENUM) || ((TYPE) == TYPE_BITFIELD))
1142 #define TYPE_ARITHMETIC(TYPE) ((((TYPE) >= TYPE_CHAR) && ((TYPE) <= TYPE_LDOUBLE)) || ((TYPE) == TYPE_ENUM) || ((TYPE) == TYPE_BITFIELD))
1143 #define TYPE_UNSIGNED(TYPE) ((TYPE) & 0x0100)
1144 #define TYPE_SIGNED(TYPE) (!TYPE_UNSIGNED(TYPE))
1145 #define TYPE_MKUNSIGNED(TYPE) (((TYPE) & ~0xF000) | 0x0100)
1146 #define TYPE_RANK(TYPE) ((TYPE) & ~0xF1FF)
1147 #define TYPE_PTR(TYPE) (((TYPE) & TYPE_MASK) == TYPE_POINTER)
1148 #define TYPE_DEFAULT 0x0000
1149 #define TYPE_VOID 0x0100
1150 #define TYPE_CHAR 0x0200
1151 #define TYPE_UCHAR 0x0300
1152 #define TYPE_SHORT 0x0400
1153 #define TYPE_USHORT 0x0500
1154 #define TYPE_INT 0x0600
1155 #define TYPE_UINT 0x0700
1156 #define TYPE_LONG 0x0800
1157 #define TYPE_ULONG 0x0900
1158 #define TYPE_LLONG 0x0a00 /* long long */
1159 #define TYPE_ULLONG 0x0b00
1160 #define TYPE_FLOAT 0x0c00
1161 #define TYPE_DOUBLE 0x0d00
1162 #define TYPE_LDOUBLE 0x0e00 /* long double */
1164 /* Note: TYPE_ENUM is chosen very carefully so TYPE_RANK works */
1165 #define TYPE_ENUM 0x1600
1166 #define TYPE_LIST 0x1700
1167 /* TYPE_LIST is a basic building block when defining enumerations
1168 * type->field_ident holds the name of this enumeration entry.
1169 * type->right holds the entry in the list.
1172 #define TYPE_STRUCT 0x1000
1174 * type->left holds the link list of TYPE_PRODUCT entries that
1175 * make up the structure.
1176 * type->elements hold the length of the linked list
1178 #define TYPE_UNION 0x1100
1180 * type->left holds the link list of TYPE_OVERLAP entries that
1181 * make up the union.
1182 * type->elements hold the length of the linked list
1184 #define TYPE_POINTER 0x1200
1185 /* For TYPE_POINTER:
1186 * type->left holds the type pointed to.
1188 #define TYPE_FUNCTION 0x1300
1189 /* For TYPE_FUNCTION:
1190 * type->left holds the return type.
1191 * type->right holds the type of the arguments
1192 * type->elements holds the count of the arguments
1194 #define TYPE_PRODUCT 0x1400
1195 /* TYPE_PRODUCT is a basic building block when defining structures
1196 * type->left holds the type that appears first in memory.
1197 * type->right holds the type that appears next in memory.
1199 #define TYPE_OVERLAP 0x1500
1200 /* TYPE_OVERLAP is a basic building block when defining unions
1201 * type->left and type->right holds to types that overlap
1202 * each other in memory.
1204 #define TYPE_ARRAY 0x1800
1205 /* TYPE_ARRAY is a basic building block when definitng arrays.
1206 * type->left holds the type we are an array of.
1207 * type->elements holds the number of elements.
1209 #define TYPE_TUPLE 0x1900
1210 /* TYPE_TUPLE is a basic building block when defining
1211 * positionally reference type conglomerations. (i.e. closures)
1212 * In essence it is a wrapper for TYPE_PRODUCT, like TYPE_STRUCT
1213 * except it has no field names.
1214 * type->left holds the liked list of TYPE_PRODUCT entries that
1215 * make up the closure type.
1216 * type->elements hold the number of elements in the closure.
1218 #define TYPE_JOIN 0x1a00
1219 /* TYPE_JOIN is a basic building block when defining
1220 * positionally reference type conglomerations. (i.e. closures)
1221 * In essence it is a wrapper for TYPE_OVERLAP, like TYPE_UNION
1222 * except it has no field names.
1223 * type->left holds the liked list of TYPE_OVERLAP entries that
1224 * make up the closure type.
1225 * type->elements hold the number of elements in the closure.
1227 #define TYPE_BITFIELD 0x1b00
1228 /* TYPE_BITFIED is the type of a bitfield.
1229 * type->left holds the type basic type TYPE_BITFIELD is derived from.
1230 * type->elements holds the number of bits in the bitfield.
1232 #define TYPE_UNKNOWN 0x1c00
1233 /* TYPE_UNKNOWN is the type of an unknown value.
1234 * Used on unknown consts and other places where I don't know the type.
1237 #define ATTRIB_SHIFT 16
1238 #define ATTRIB_MASK 0xffff0000
1239 #define ATTRIB_NOINLINE 0x00010000
1240 #define ATTRIB_ALWAYS_INLINE 0x00020000
1242 #define ELEMENT_COUNT_UNSPECIFIED ULONG_T_MAX
1246 struct type
*left
, *right
;
1248 struct hash_entry
*field_ident
;
1249 struct hash_entry
*type_ident
;
1252 #define TEMPLATE_BITS 7
1253 #define MAX_TEMPLATES (1<<TEMPLATE_BITS)
1254 #define MAX_REG_EQUIVS 16
1256 #define MAX_REGISTERS 75
1257 #define REGISTER_BITS 7
1258 #define MAX_VIRT_REGISTERS (1<<REGISTER_BITS)
1261 #define REG_UNNEEDED 2
1262 #define REG_VIRT0 (MAX_REGISTERS + 0)
1263 #define REG_VIRT1 (MAX_REGISTERS + 1)
1264 #define REG_VIRT2 (MAX_REGISTERS + 2)
1265 #define REG_VIRT3 (MAX_REGISTERS + 3)
1266 #define REG_VIRT4 (MAX_REGISTERS + 4)
1267 #define REG_VIRT5 (MAX_REGISTERS + 5)
1268 #define REG_VIRT6 (MAX_REGISTERS + 6)
1269 #define REG_VIRT7 (MAX_REGISTERS + 7)
1270 #define REG_VIRT8 (MAX_REGISTERS + 8)
1271 #define REG_VIRT9 (MAX_REGISTERS + 9)
1273 #if (MAX_REGISTERS + 9) > MAX_VIRT_REGISTERS
1274 #error "MAX_VIRT_REGISTERS to small"
1276 #if (MAX_REGC + REGISTER_BITS) >= 26
1277 #error "Too many id bits used"
1280 /* Provision for 8 register classes */
1282 #define REGC_SHIFT REGISTER_BITS
1283 #define REGC_MASK (((1 << MAX_REGC) - 1) << REGISTER_BITS)
1284 #define REG_MASK (MAX_VIRT_REGISTERS -1)
1285 #define ID_REG(ID) ((ID) & REG_MASK)
1286 #define SET_REG(ID, REG) ((ID) = (((ID) & ~REG_MASK) | ((REG) & REG_MASK)))
1287 #define ID_REGCM(ID) (((ID) & REGC_MASK) >> REGC_SHIFT)
1288 #define SET_REGCM(ID, REGCM) ((ID) = (((ID) & ~REGC_MASK) | (((REGCM) << REGC_SHIFT) & REGC_MASK)))
1289 #define SET_INFO(ID, INFO) ((ID) = (((ID) & ~(REG_MASK | REGC_MASK)) | \
1290 (((INFO).reg) & REG_MASK) | ((((INFO).regcm) << REGC_SHIFT) & REGC_MASK)))
1292 #define ARCH_INPUT_REGS 4
1293 #define ARCH_OUTPUT_REGS 4
1295 static const struct reg_info arch_input_regs
[ARCH_INPUT_REGS
];
1296 static const struct reg_info arch_output_regs
[ARCH_OUTPUT_REGS
];
1297 static unsigned arch_reg_regcm(struct compile_state
*state
, int reg
);
1298 static unsigned arch_regcm_normalize(struct compile_state
*state
, unsigned regcm
);
1299 static unsigned arch_regcm_reg_normalize(struct compile_state
*state
, unsigned regcm
);
1300 static void arch_reg_equivs(
1301 struct compile_state
*state
, unsigned *equiv
, int reg
);
1302 static int arch_select_free_register(
1303 struct compile_state
*state
, char *used
, int classes
);
1304 static unsigned arch_regc_size(struct compile_state
*state
, int class);
1305 static int arch_regcm_intersect(unsigned regcm1
, unsigned regcm2
);
1306 static unsigned arch_type_to_regcm(struct compile_state
*state
, struct type
*type
);
1307 static const char *arch_reg_str(int reg
);
1308 static struct reg_info
arch_reg_constraint(
1309 struct compile_state
*state
, struct type
*type
, const char *constraint
);
1310 static struct reg_info
arch_reg_clobber(
1311 struct compile_state
*state
, const char *clobber
);
1312 static struct reg_info
arch_reg_lhs(struct compile_state
*state
,
1313 struct triple
*ins
, int index
);
1314 static struct reg_info
arch_reg_rhs(struct compile_state
*state
,
1315 struct triple
*ins
, int index
);
1316 static int arch_reg_size(int reg
);
1317 static struct triple
*transform_to_arch_instruction(
1318 struct compile_state
*state
, struct triple
*ins
);
1319 static struct triple
*flatten(
1320 struct compile_state
*state
, struct triple
*first
, struct triple
*ptr
);
1321 static void print_dominators(struct compile_state
*state
,
1322 FILE *fp
, struct basic_blocks
*bb
);
1323 static void print_dominance_frontiers(struct compile_state
*state
,
1324 FILE *fp
, struct basic_blocks
*bb
);
1328 #define DEBUG_ABORT_ON_ERROR 0x00000001
1329 #define DEBUG_BASIC_BLOCKS 0x00000002
1330 #define DEBUG_FDOMINATORS 0x00000004
1331 #define DEBUG_RDOMINATORS 0x00000008
1332 #define DEBUG_TRIPLES 0x00000010
1333 #define DEBUG_INTERFERENCE 0x00000020
1334 #define DEBUG_SCC_TRANSFORM 0x00000040
1335 #define DEBUG_SCC_TRANSFORM2 0x00000080
1336 #define DEBUG_REBUILD_SSA_FORM 0x00000100
1337 #define DEBUG_INLINE 0x00000200
1338 #define DEBUG_RANGE_CONFLICTS 0x00000400
1339 #define DEBUG_RANGE_CONFLICTS2 0x00000800
1340 #define DEBUG_COLOR_GRAPH 0x00001000
1341 #define DEBUG_COLOR_GRAPH2 0x00002000
1342 #define DEBUG_COALESCING 0x00004000
1343 #define DEBUG_COALESCING2 0x00008000
1344 #define DEBUG_VERIFICATION 0x00010000
1345 #define DEBUG_CALLS 0x00020000
1346 #define DEBUG_CALLS2 0x00040000
1347 #define DEBUG_TOKENS 0x80000000
1349 #define DEBUG_DEFAULT ( \
1350 DEBUG_ABORT_ON_ERROR | \
1351 DEBUG_BASIC_BLOCKS | \
1352 DEBUG_FDOMINATORS | \
1353 DEBUG_RDOMINATORS | \
1357 #define DEBUG_ALL ( \
1358 DEBUG_ABORT_ON_ERROR | \
1359 DEBUG_BASIC_BLOCKS | \
1360 DEBUG_FDOMINATORS | \
1361 DEBUG_RDOMINATORS | \
1363 DEBUG_INTERFERENCE | \
1364 DEBUG_SCC_TRANSFORM | \
1365 DEBUG_SCC_TRANSFORM2 | \
1366 DEBUG_REBUILD_SSA_FORM | \
1368 DEBUG_RANGE_CONFLICTS | \
1369 DEBUG_RANGE_CONFLICTS2 | \
1370 DEBUG_COLOR_GRAPH | \
1371 DEBUG_COLOR_GRAPH2 | \
1372 DEBUG_COALESCING | \
1373 DEBUG_COALESCING2 | \
1374 DEBUG_VERIFICATION | \
1380 #define COMPILER_INLINE_MASK 0x00000007
1381 #define COMPILER_INLINE_ALWAYS 0x00000000
1382 #define COMPILER_INLINE_NEVER 0x00000001
1383 #define COMPILER_INLINE_DEFAULTON 0x00000002
1384 #define COMPILER_INLINE_DEFAULTOFF 0x00000003
1385 #define COMPILER_INLINE_NOPENALTY 0x00000004
1386 #define COMPILER_ELIMINATE_INEFECTUAL_CODE 0x00000008
1387 #define COMPILER_SIMPLIFY 0x00000010
1388 #define COMPILER_SCC_TRANSFORM 0x00000020
1389 #define COMPILER_SIMPLIFY_OP 0x00000040
1390 #define COMPILER_SIMPLIFY_PHI 0x00000080
1391 #define COMPILER_SIMPLIFY_LABEL 0x00000100
1392 #define COMPILER_SIMPLIFY_BRANCH 0x00000200
1393 #define COMPILER_SIMPLIFY_COPY 0x00000400
1394 #define COMPILER_SIMPLIFY_ARITH 0x00000800
1395 #define COMPILER_SIMPLIFY_SHIFT 0x00001000
1396 #define COMPILER_SIMPLIFY_BITWISE 0x00002000
1397 #define COMPILER_SIMPLIFY_LOGICAL 0x00004000
1398 #define COMPILER_SIMPLIFY_BITFIELD 0x00008000
1400 #define COMPILER_TRIGRAPHS 0x40000000
1401 #define COMPILER_PP_ONLY 0x80000000
1403 #define COMPILER_DEFAULT_FLAGS ( \
1404 COMPILER_TRIGRAPHS | \
1405 COMPILER_ELIMINATE_INEFECTUAL_CODE | \
1406 COMPILER_INLINE_DEFAULTON | \
1407 COMPILER_SIMPLIFY_OP | \
1408 COMPILER_SIMPLIFY_PHI | \
1409 COMPILER_SIMPLIFY_LABEL | \
1410 COMPILER_SIMPLIFY_BRANCH | \
1411 COMPILER_SIMPLIFY_COPY | \
1412 COMPILER_SIMPLIFY_ARITH | \
1413 COMPILER_SIMPLIFY_SHIFT | \
1414 COMPILER_SIMPLIFY_BITWISE | \
1415 COMPILER_SIMPLIFY_LOGICAL | \
1416 COMPILER_SIMPLIFY_BITFIELD | \
1419 #define GLOBAL_SCOPE_DEPTH 1
1420 #define FUNCTION_SCOPE_DEPTH (GLOBAL_SCOPE_DEPTH + 1)
1422 static void compile_file(struct compile_state
*old_state
, const char *filename
, int local
);
1426 static void init_compiler_state(struct compiler_state
*compiler
)
1428 memset(compiler
, 0, sizeof(*compiler
));
1429 compiler
->label_prefix
= "";
1430 compiler
->ofilename
= "auto.inc";
1431 compiler
->flags
= COMPILER_DEFAULT_FLAGS
;
1432 compiler
->debug
= 0;
1433 compiler
->max_allocation_passes
= MAX_ALLOCATION_PASSES
;
1434 compiler
->include_path_count
= 1;
1435 compiler
->include_paths
= xcmalloc(sizeof(char *), "include_paths");
1436 compiler
->define_count
= 1;
1437 compiler
->defines
= xcmalloc(sizeof(char *), "defines");
1438 compiler
->undef_count
= 1;
1439 compiler
->undefs
= xcmalloc(sizeof(char *), "undefs");
1442 struct compiler_flag
{
1447 struct compiler_arg
{
1450 struct compiler_flag flags
[16];
1453 static int set_flag(
1454 const struct compiler_flag
*ptr
, unsigned long *flags
,
1455 int act
, const char *flag
)
1458 for(; ptr
->name
; ptr
++) {
1459 if (strcmp(ptr
->name
, flag
) == 0) {
1465 *flags
&= ~(ptr
->flag
);
1467 *flags
|= ptr
->flag
;
1474 const struct compiler_arg
*ptr
, unsigned long *flags
, const char *arg
)
1479 val
= strchr(arg
, '=');
1483 for(; ptr
->name
; ptr
++) {
1484 if (strncmp(ptr
->name
, arg
, len
) == 0) {
1489 *flags
&= ~ptr
->mask
;
1490 result
= set_flag(&ptr
->flags
[0], flags
, 1, val
);
1497 static void flag_usage(FILE *fp
, const struct compiler_flag
*ptr
,
1498 const char *prefix
, const char *invert_prefix
)
1500 for(;ptr
->name
; ptr
++) {
1501 fprintf(fp
, "%s%s\n", prefix
, ptr
->name
);
1502 if (invert_prefix
) {
1503 fprintf(fp
, "%s%s\n", invert_prefix
, ptr
->name
);
1508 static void arg_usage(FILE *fp
, const struct compiler_arg
*ptr
,
1511 for(;ptr
->name
; ptr
++) {
1512 const struct compiler_flag
*flag
;
1513 for(flag
= &ptr
->flags
[0]; flag
->name
; flag
++) {
1514 fprintf(fp
, "%s%s=%s\n",
1515 prefix
, ptr
->name
, flag
->name
);
1520 static int append_string(size_t *max
, const char ***vec
, const char *str
,
1525 *vec
= xrealloc(*vec
, sizeof(char *)*count
, "name");
1526 (*vec
)[count
-1] = 0;
1527 (*vec
)[count
-2] = str
;
1531 static void arg_error(char *fmt
, ...);
1532 static const char *identifier(const char *str
, const char *end
);
1534 static int append_include_path(struct compiler_state
*compiler
, const char *str
)
1537 if (!exists(str
, ".")) {
1538 arg_error("Nonexistent include path: `%s'\n",
1541 result
= append_string(&compiler
->include_path_count
,
1542 &compiler
->include_paths
, str
, "include_paths");
1546 static int append_define(struct compiler_state
*compiler
, const char *str
)
1548 const char *end
, *rest
;
1551 end
= strchr(str
, '=');
1553 end
= str
+ strlen(str
);
1555 rest
= identifier(str
, end
);
1557 int len
= end
- str
- 1;
1558 arg_error("Invalid name cannot define macro: `%*.*s'\n",
1561 result
= append_string(&compiler
->define_count
,
1562 &compiler
->defines
, str
, "defines");
1566 static int append_undef(struct compiler_state
*compiler
, const char *str
)
1568 const char *end
, *rest
;
1571 end
= str
+ strlen(str
);
1572 rest
= identifier(str
, end
);
1574 int len
= end
- str
- 1;
1575 arg_error("Invalid name cannot undefine macro: `%*.*s'\n",
1578 result
= append_string(&compiler
->undef_count
,
1579 &compiler
->undefs
, str
, "undefs");
1583 static const struct compiler_flag romcc_flags
[] = {
1584 { "trigraphs", COMPILER_TRIGRAPHS
},
1585 { "pp-only", COMPILER_PP_ONLY
},
1586 { "eliminate-inefectual-code", COMPILER_ELIMINATE_INEFECTUAL_CODE
},
1587 { "simplify", COMPILER_SIMPLIFY
},
1588 { "scc-transform", COMPILER_SCC_TRANSFORM
},
1589 { "simplify-op", COMPILER_SIMPLIFY_OP
},
1590 { "simplify-phi", COMPILER_SIMPLIFY_PHI
},
1591 { "simplify-label", COMPILER_SIMPLIFY_LABEL
},
1592 { "simplify-branch", COMPILER_SIMPLIFY_BRANCH
},
1593 { "simplify-copy", COMPILER_SIMPLIFY_COPY
},
1594 { "simplify-arith", COMPILER_SIMPLIFY_ARITH
},
1595 { "simplify-shift", COMPILER_SIMPLIFY_SHIFT
},
1596 { "simplify-bitwise", COMPILER_SIMPLIFY_BITWISE
},
1597 { "simplify-logical", COMPILER_SIMPLIFY_LOGICAL
},
1598 { "simplify-bitfield", COMPILER_SIMPLIFY_BITFIELD
},
1601 static const struct compiler_arg romcc_args
[] = {
1602 { "inline-policy", COMPILER_INLINE_MASK
,
1604 { "always", COMPILER_INLINE_ALWAYS
, },
1605 { "never", COMPILER_INLINE_NEVER
, },
1606 { "defaulton", COMPILER_INLINE_DEFAULTON
, },
1607 { "defaultoff", COMPILER_INLINE_DEFAULTOFF
, },
1608 { "nopenalty", COMPILER_INLINE_NOPENALTY
, },
1614 static const struct compiler_flag romcc_opt_flags
[] = {
1615 { "-O", COMPILER_SIMPLIFY
},
1616 { "-O2", COMPILER_SIMPLIFY
| COMPILER_SCC_TRANSFORM
},
1617 { "-E", COMPILER_PP_ONLY
},
1620 static const struct compiler_flag romcc_debug_flags
[] = {
1621 { "all", DEBUG_ALL
},
1622 { "abort-on-error", DEBUG_ABORT_ON_ERROR
},
1623 { "basic-blocks", DEBUG_BASIC_BLOCKS
},
1624 { "fdominators", DEBUG_FDOMINATORS
},
1625 { "rdominators", DEBUG_RDOMINATORS
},
1626 { "triples", DEBUG_TRIPLES
},
1627 { "interference", DEBUG_INTERFERENCE
},
1628 { "scc-transform", DEBUG_SCC_TRANSFORM
},
1629 { "scc-transform2", DEBUG_SCC_TRANSFORM2
},
1630 { "rebuild-ssa-form", DEBUG_REBUILD_SSA_FORM
},
1631 { "inline", DEBUG_INLINE
},
1632 { "live-range-conflicts", DEBUG_RANGE_CONFLICTS
},
1633 { "live-range-conflicts2", DEBUG_RANGE_CONFLICTS2
},
1634 { "color-graph", DEBUG_COLOR_GRAPH
},
1635 { "color-graph2", DEBUG_COLOR_GRAPH2
},
1636 { "coalescing", DEBUG_COALESCING
},
1637 { "coalescing2", DEBUG_COALESCING2
},
1638 { "verification", DEBUG_VERIFICATION
},
1639 { "calls", DEBUG_CALLS
},
1640 { "calls2", DEBUG_CALLS2
},
1641 { "tokens", DEBUG_TOKENS
},
1645 static int compiler_encode_flag(
1646 struct compiler_state
*compiler
, const char *flag
)
1653 if (strncmp(flag
, "no-", 3) == 0) {
1657 if (strncmp(flag
, "-O", 2) == 0) {
1658 result
= set_flag(romcc_opt_flags
, &compiler
->flags
, act
, flag
);
1660 else if (strncmp(flag
, "-E", 2) == 0) {
1661 result
= set_flag(romcc_opt_flags
, &compiler
->flags
, act
, flag
);
1663 else if (strncmp(flag
, "-I", 2) == 0) {
1664 result
= append_include_path(compiler
, flag
+ 2);
1666 else if (strncmp(flag
, "-D", 2) == 0) {
1667 result
= append_define(compiler
, flag
+ 2);
1669 else if (strncmp(flag
, "-U", 2) == 0) {
1670 result
= append_undef(compiler
, flag
+ 2);
1672 else if (act
&& strncmp(flag
, "label-prefix=", 13) == 0) {
1674 compiler
->label_prefix
= flag
+ 13;
1676 else if (act
&& strncmp(flag
, "max-allocation-passes=", 22) == 0) {
1677 unsigned long max_passes
;
1679 max_passes
= strtoul(flag
+ 22, &end
, 10);
1680 if (end
[0] == '\0') {
1682 compiler
->max_allocation_passes
= max_passes
;
1685 else if (act
&& strcmp(flag
, "debug") == 0) {
1687 compiler
->debug
|= DEBUG_DEFAULT
;
1689 else if (strncmp(flag
, "debug-", 6) == 0) {
1691 result
= set_flag(romcc_debug_flags
, &compiler
->debug
, act
, flag
);
1694 result
= set_flag(romcc_flags
, &compiler
->flags
, act
, flag
);
1696 result
= set_arg(romcc_args
, &compiler
->flags
, flag
);
1702 static void compiler_usage(FILE *fp
)
1704 flag_usage(fp
, romcc_opt_flags
, "", 0);
1705 flag_usage(fp
, romcc_flags
, "-f", "-fno-");
1706 arg_usage(fp
, romcc_args
, "-f");
1707 flag_usage(fp
, romcc_debug_flags
, "-fdebug-", "-fno-debug-");
1708 fprintf(fp
, "-flabel-prefix=<prefix for assembly language labels>\n");
1709 fprintf(fp
, "--label-prefix=<prefix for assembly language labels>\n");
1710 fprintf(fp
, "-I<include path>\n");
1711 fprintf(fp
, "-D<macro>[=defn]\n");
1712 fprintf(fp
, "-U<macro>\n");
1715 static void do_cleanup(struct compile_state
*state
)
1717 if (state
->output
) {
1718 fclose(state
->output
);
1719 unlink(state
->compiler
->ofilename
);
1722 if (state
->dbgout
) {
1723 fflush(state
->dbgout
);
1725 if (state
->errout
) {
1726 fflush(state
->errout
);
1730 static struct compile_state
*exit_state
;
1731 static void exit_cleanup(void)
1734 do_cleanup(exit_state
);
1738 static int get_col(struct file_state
*file
)
1741 const char *ptr
, *end
;
1742 ptr
= file
->line_start
;
1744 for(col
= 0; ptr
< end
; ptr
++) {
1749 col
= (col
& ~7) + 8;
1755 static void loc(FILE *fp
, struct compile_state
*state
, struct triple
*triple
)
1758 if (triple
&& triple
->occurance
) {
1759 struct occurance
*spot
;
1760 for(spot
= triple
->occurance
; spot
; spot
= spot
->parent
) {
1761 fprintf(fp
, "%s:%d.%d: ",
1762 spot
->filename
, spot
->line
, spot
->col
);
1769 col
= get_col(state
->file
);
1770 fprintf(fp
, "%s:%d.%d: ",
1771 state
->file
->report_name
, state
->file
->report_line
, col
);
1774 static void __attribute__ ((noreturn
)) internal_error(struct compile_state
*state
, struct triple
*ptr
,
1775 const char *fmt
, ...)
1777 FILE *fp
= state
->errout
;
1779 va_start(args
, fmt
);
1780 loc(fp
, state
, ptr
);
1783 fprintf(fp
, "%p %-10s ", ptr
, tops(ptr
->op
));
1785 fprintf(fp
, "Internal compiler error: ");
1786 vfprintf(fp
, fmt
, args
);
1794 static void internal_warning(struct compile_state
*state
, struct triple
*ptr
,
1795 const char *fmt
, ...)
1797 FILE *fp
= state
->errout
;
1799 va_start(args
, fmt
);
1800 loc(fp
, state
, ptr
);
1802 fprintf(fp
, "%p %-10s ", ptr
, tops(ptr
->op
));
1804 fprintf(fp
, "Internal compiler warning: ");
1805 vfprintf(fp
, fmt
, args
);
1812 static void __attribute__ ((noreturn
)) error(struct compile_state
*state
, struct triple
*ptr
,
1813 const char *fmt
, ...)
1815 FILE *fp
= state
->errout
;
1817 va_start(args
, fmt
);
1818 loc(fp
, state
, ptr
);
1820 if (ptr
&& (state
->compiler
->debug
& DEBUG_ABORT_ON_ERROR
)) {
1821 fprintf(fp
, "%p %-10s ", ptr
, tops(ptr
->op
));
1823 vfprintf(fp
, fmt
, args
);
1827 if (state
->compiler
->debug
& DEBUG_ABORT_ON_ERROR
) {
1833 static void warning(struct compile_state
*state
, struct triple
*ptr
,
1834 const char *fmt
, ...)
1836 FILE *fp
= state
->errout
;
1838 va_start(args
, fmt
);
1839 loc(fp
, state
, ptr
);
1840 fprintf(fp
, "warning: ");
1841 if (ptr
&& (state
->compiler
->debug
& DEBUG_ABORT_ON_ERROR
)) {
1842 fprintf(fp
, "%p %-10s ", ptr
, tops(ptr
->op
));
1844 vfprintf(fp
, fmt
, args
);
1849 #define FINISHME() warning(state, 0, "FINISHME @ %s.%s:%d", __FILE__, __func__, __LINE__)
1851 static void valid_op(struct compile_state
*state
, int op
)
1853 char *fmt
= "invalid op: %d";
1855 internal_error(state
, 0, fmt
, op
);
1858 internal_error(state
, 0, fmt
, op
);
1862 static void valid_ins(struct compile_state
*state
, struct triple
*ptr
)
1864 valid_op(state
, ptr
->op
);
1867 #if DEBUG_ROMCC_WARNING
1868 static void valid_param_count(struct compile_state
*state
, struct triple
*ins
)
1870 int lhs
, rhs
, misc
, targ
;
1871 valid_ins(state
, ins
);
1872 lhs
= table_ops
[ins
->op
].lhs
;
1873 rhs
= table_ops
[ins
->op
].rhs
;
1874 misc
= table_ops
[ins
->op
].misc
;
1875 targ
= table_ops
[ins
->op
].targ
;
1877 if ((lhs
>= 0) && (ins
->lhs
!= lhs
)) {
1878 internal_error(state
, ins
, "Bad lhs count");
1880 if ((rhs
>= 0) && (ins
->rhs
!= rhs
)) {
1881 internal_error(state
, ins
, "Bad rhs count");
1883 if ((misc
>= 0) && (ins
->misc
!= misc
)) {
1884 internal_error(state
, ins
, "Bad misc count");
1886 if ((targ
>= 0) && (ins
->targ
!= targ
)) {
1887 internal_error(state
, ins
, "Bad targ count");
1892 static struct type void_type
;
1893 static struct type unknown_type
;
1894 static void use_triple(struct triple
*used
, struct triple
*user
)
1896 struct triple_set
**ptr
, *new;
1903 if ((*ptr
)->member
== user
) {
1906 ptr
= &(*ptr
)->next
;
1908 /* Append new to the head of the list,
1909 * copy_func and rename_block_variables
1912 new = xcmalloc(sizeof(*new), "triple_set");
1914 new->next
= used
->use
;
1918 static void unuse_triple(struct triple
*used
, struct triple
*unuser
)
1920 struct triple_set
*use
, **ptr
;
1927 if (use
->member
== unuser
) {
1937 static void put_occurance(struct occurance
*occurance
)
1940 occurance
->count
-= 1;
1941 if (occurance
->count
<= 0) {
1942 if (occurance
->parent
) {
1943 put_occurance(occurance
->parent
);
1950 static void get_occurance(struct occurance
*occurance
)
1953 occurance
->count
+= 1;
1958 static struct occurance
*new_occurance(struct compile_state
*state
)
1960 struct occurance
*result
, *last
;
1961 const char *filename
;
1962 const char *function
;
1970 filename
= state
->file
->report_name
;
1971 line
= state
->file
->report_line
;
1972 col
= get_col(state
->file
);
1974 if (state
->function
) {
1975 function
= state
->function
;
1977 last
= state
->last_occurance
;
1979 (last
->col
== col
) &&
1980 (last
->line
== line
) &&
1981 (last
->function
== function
) &&
1982 ((last
->filename
== filename
) ||
1983 (strcmp(last
->filename
, filename
) == 0)))
1985 get_occurance(last
);
1989 state
->last_occurance
= 0;
1990 put_occurance(last
);
1992 result
= xmalloc(sizeof(*result
), "occurance");
1994 result
->filename
= filename
;
1995 result
->function
= function
;
1996 result
->line
= line
;
1999 state
->last_occurance
= result
;
2003 static struct occurance
*inline_occurance(struct compile_state
*state
,
2004 struct occurance
*base
, struct occurance
*top
)
2006 struct occurance
*result
, *last
;
2008 internal_error(state
, 0, "inlining an already inlined function?");
2010 /* If I have a null base treat it that way */
2011 if ((base
->parent
== 0) &&
2013 (base
->line
== 0) &&
2014 (base
->function
[0] == '\0') &&
2015 (base
->filename
[0] == '\0')) {
2018 /* See if I can reuse the last occurance I had */
2019 last
= state
->last_occurance
;
2021 (last
->parent
== base
) &&
2022 (last
->col
== top
->col
) &&
2023 (last
->line
== top
->line
) &&
2024 (last
->function
== top
->function
) &&
2025 (last
->filename
== top
->filename
)) {
2026 get_occurance(last
);
2029 /* I can't reuse the last occurance so free it */
2031 state
->last_occurance
= 0;
2032 put_occurance(last
);
2034 /* Generate a new occurance structure */
2035 get_occurance(base
);
2036 result
= xmalloc(sizeof(*result
), "occurance");
2038 result
->filename
= top
->filename
;
2039 result
->function
= top
->function
;
2040 result
->line
= top
->line
;
2041 result
->col
= top
->col
;
2042 result
->parent
= base
;
2043 state
->last_occurance
= result
;
2047 static struct occurance dummy_occurance
= {
2049 .filename
= __FILE__
,
2056 /* The undef triple is used as a place holder when we are removing pointers
2057 * from a triple. Having allows certain sanity checks to pass even
2058 * when the original triple that was pointed to is gone.
2060 static struct triple unknown_triple
= {
2061 .next
= &unknown_triple
,
2062 .prev
= &unknown_triple
,
2064 .op
= OP_UNKNOWNVAL
,
2069 .type
= &unknown_type
,
2070 .id
= -1, /* An invalid id */
2071 .u
= { .cval
= 0, },
2072 .occurance
= &dummy_occurance
,
2073 .param
= { [0] = 0, [1] = 0, },
2077 static size_t registers_of(struct compile_state
*state
, struct type
*type
);
2079 static struct triple
*alloc_triple(struct compile_state
*state
,
2080 int op
, struct type
*type
, int lhs_wanted
, int rhs_wanted
,
2081 struct occurance
*occurance
)
2083 size_t size
, extra_count
, min_count
;
2084 int lhs
, rhs
, misc
, targ
;
2085 struct triple
*ret
, dummy
;
2087 dummy
.occurance
= occurance
;
2088 valid_op(state
, op
);
2089 lhs
= table_ops
[op
].lhs
;
2090 rhs
= table_ops
[op
].rhs
;
2091 misc
= table_ops
[op
].misc
;
2092 targ
= table_ops
[op
].targ
;
2102 lhs
= registers_of(state
, type
);
2105 lhs
= registers_of(state
, type
);
2112 if ((rhs
< 0) || (rhs
> MAX_RHS
)) {
2113 internal_error(state
, &dummy
, "bad rhs count %d", rhs
);
2115 if ((lhs
< 0) || (lhs
> MAX_LHS
)) {
2116 internal_error(state
, &dummy
, "bad lhs count %d", lhs
);
2118 if ((misc
< 0) || (misc
> MAX_MISC
)) {
2119 internal_error(state
, &dummy
, "bad misc count %d", misc
);
2121 if ((targ
< 0) || (targ
> MAX_TARG
)) {
2122 internal_error(state
, &dummy
, "bad targs count %d", targ
);
2125 min_count
= sizeof(ret
->param
)/sizeof(ret
->param
[0]);
2126 extra_count
= lhs
+ rhs
+ misc
+ targ
;
2127 extra_count
= (extra_count
< min_count
)? 0 : extra_count
- min_count
;
2129 size
= sizeof(*ret
) + sizeof(ret
->param
[0]) * extra_count
;
2130 ret
= xcmalloc(size
, "tripple");
2139 ret
->occurance
= occurance
;
2140 /* A simple sanity check */
2141 if ((ret
->op
!= op
) ||
2142 (ret
->lhs
!= lhs
) ||
2143 (ret
->rhs
!= rhs
) ||
2144 (ret
->misc
!= misc
) ||
2145 (ret
->targ
!= targ
) ||
2146 (ret
->type
!= type
) ||
2147 (ret
->next
!= ret
) ||
2148 (ret
->prev
!= ret
) ||
2149 (ret
->occurance
!= occurance
)) {
2150 internal_error(state
, ret
, "huh?");
2155 struct triple
*dup_triple(struct compile_state
*state
, struct triple
*src
)
2158 int src_lhs
, src_rhs
, src_size
;
2161 src_size
= TRIPLE_SIZE(src
);
2162 get_occurance(src
->occurance
);
2163 dup
= alloc_triple(state
, src
->op
, src
->type
, src_lhs
, src_rhs
,
2165 memcpy(dup
, src
, sizeof(*src
));
2166 memcpy(dup
->param
, src
->param
, src_size
* sizeof(src
->param
[0]));
2170 static struct triple
*copy_triple(struct compile_state
*state
, struct triple
*src
)
2172 struct triple
*copy
;
2173 copy
= dup_triple(state
, src
);
2175 copy
->next
= copy
->prev
= copy
;
2179 static struct triple
*new_triple(struct compile_state
*state
,
2180 int op
, struct type
*type
, int lhs
, int rhs
)
2183 struct occurance
*occurance
;
2184 occurance
= new_occurance(state
);
2185 ret
= alloc_triple(state
, op
, type
, lhs
, rhs
, occurance
);
2189 static struct triple
*build_triple(struct compile_state
*state
,
2190 int op
, struct type
*type
, struct triple
*left
, struct triple
*right
,
2191 struct occurance
*occurance
)
2195 ret
= alloc_triple(state
, op
, type
, -1, -1, occurance
);
2196 count
= TRIPLE_SIZE(ret
);
2198 ret
->param
[0] = left
;
2201 ret
->param
[1] = right
;
2206 static struct triple
*triple(struct compile_state
*state
,
2207 int op
, struct type
*type
, struct triple
*left
, struct triple
*right
)
2211 ret
= new_triple(state
, op
, type
, -1, -1);
2212 count
= TRIPLE_SIZE(ret
);
2214 ret
->param
[0] = left
;
2217 ret
->param
[1] = right
;
2222 static struct triple
*branch(struct compile_state
*state
,
2223 struct triple
*targ
, struct triple
*test
)
2227 ret
= new_triple(state
, OP_CBRANCH
, &void_type
, -1, 1);
2230 ret
= new_triple(state
, OP_BRANCH
, &void_type
, -1, 0);
2232 TARG(ret
, 0) = targ
;
2233 /* record the branch target was used */
2234 if (!targ
|| (targ
->op
!= OP_LABEL
)) {
2235 internal_error(state
, 0, "branch not to label");
2240 static int triple_is_label(struct compile_state
*state
, struct triple
*ins
);
2241 static int triple_is_call(struct compile_state
*state
, struct triple
*ins
);
2242 static int triple_is_cbranch(struct compile_state
*state
, struct triple
*ins
);
2243 static void insert_triple(struct compile_state
*state
,
2244 struct triple
*first
, struct triple
*ptr
)
2247 if ((ptr
->id
& TRIPLE_FLAG_FLATTENED
) || (ptr
->next
!= ptr
)) {
2248 internal_error(state
, ptr
, "expression already used");
2251 ptr
->prev
= first
->prev
;
2252 ptr
->prev
->next
= ptr
;
2253 ptr
->next
->prev
= ptr
;
2255 if (triple_is_cbranch(state
, ptr
->prev
) ||
2256 triple_is_call(state
, ptr
->prev
)) {
2257 unuse_triple(first
, ptr
->prev
);
2258 use_triple(ptr
, ptr
->prev
);
2263 static int triple_stores_block(struct compile_state
*state
, struct triple
*ins
)
2265 /* This function is used to determine if u.block
2266 * is utilized to store the current block number.
2269 valid_ins(state
, ins
);
2270 stores_block
= (table_ops
[ins
->op
].flags
& BLOCK
) == BLOCK
;
2271 return stores_block
;
2274 static int triple_is_branch(struct compile_state
*state
, struct triple
*ins
);
2275 static struct block
*block_of_triple(struct compile_state
*state
,
2278 struct triple
*first
;
2279 if (!ins
|| ins
== &unknown_triple
) {
2282 first
= state
->first
;
2283 while(ins
!= first
&& !triple_is_branch(state
, ins
->prev
) &&
2284 !triple_stores_block(state
, ins
))
2286 if (ins
== ins
->prev
) {
2287 internal_error(state
, ins
, "ins == ins->prev?");
2291 return triple_stores_block(state
, ins
)? ins
->u
.block
: 0;
2294 static void generate_lhs_pieces(struct compile_state
*state
, struct triple
*ins
);
2295 static struct triple
*pre_triple(struct compile_state
*state
,
2296 struct triple
*base
,
2297 int op
, struct type
*type
, struct triple
*left
, struct triple
*right
)
2299 struct block
*block
;
2302 /* If I am an OP_PIECE jump to the real instruction */
2303 if (base
->op
== OP_PIECE
) {
2304 base
= MISC(base
, 0);
2306 block
= block_of_triple(state
, base
);
2307 get_occurance(base
->occurance
);
2308 ret
= build_triple(state
, op
, type
, left
, right
, base
->occurance
);
2309 generate_lhs_pieces(state
, ret
);
2310 if (triple_stores_block(state
, ret
)) {
2311 ret
->u
.block
= block
;
2313 insert_triple(state
, base
, ret
);
2314 for(i
= 0; i
< ret
->lhs
; i
++) {
2315 struct triple
*piece
;
2316 piece
= LHS(ret
, i
);
2317 insert_triple(state
, base
, piece
);
2318 use_triple(ret
, piece
);
2319 use_triple(piece
, ret
);
2321 if (block
&& (block
->first
== base
)) {
2327 static struct triple
*post_triple(struct compile_state
*state
,
2328 struct triple
*base
,
2329 int op
, struct type
*type
, struct triple
*left
, struct triple
*right
)
2331 struct block
*block
;
2332 struct triple
*ret
, *next
;
2334 /* If I am an OP_PIECE jump to the real instruction */
2335 if (base
->op
== OP_PIECE
) {
2336 base
= MISC(base
, 0);
2338 /* If I have a left hand side skip over it */
2341 base
= LHS(base
, zlhs
- 1);
2344 block
= block_of_triple(state
, base
);
2345 get_occurance(base
->occurance
);
2346 ret
= build_triple(state
, op
, type
, left
, right
, base
->occurance
);
2347 generate_lhs_pieces(state
, ret
);
2348 if (triple_stores_block(state
, ret
)) {
2349 ret
->u
.block
= block
;
2352 insert_triple(state
, next
, ret
);
2354 for(i
= 0; i
< zlhs
; i
++) {
2355 struct triple
*piece
;
2356 piece
= LHS(ret
, i
);
2357 insert_triple(state
, next
, piece
);
2358 use_triple(ret
, piece
);
2359 use_triple(piece
, ret
);
2361 if (block
&& (block
->last
== base
)) {
2364 block
->last
= LHS(ret
, zlhs
- 1);
2370 static struct type
*reg_type(
2371 struct compile_state
*state
, struct type
*type
, int reg
);
2373 static void generate_lhs_piece(
2374 struct compile_state
*state
, struct triple
*ins
, int index
)
2376 struct type
*piece_type
;
2377 struct triple
*piece
;
2378 get_occurance(ins
->occurance
);
2379 piece_type
= reg_type(state
, ins
->type
, index
* REG_SIZEOF_REG
);
2381 if ((piece_type
->type
& TYPE_MASK
) == TYPE_BITFIELD
) {
2382 piece_type
= piece_type
->left
;
2386 static void name_of(FILE *fp
, struct type
*type
);
2387 FILE * fp
= state
->errout
;
2388 fprintf(fp
, "piece_type(%d): ", index
);
2389 name_of(fp
, piece_type
);
2393 piece
= alloc_triple(state
, OP_PIECE
, piece_type
, -1, -1, ins
->occurance
);
2394 piece
->u
.cval
= index
;
2395 LHS(ins
, piece
->u
.cval
) = piece
;
2396 MISC(piece
, 0) = ins
;
2399 static void generate_lhs_pieces(struct compile_state
*state
, struct triple
*ins
)
2403 for(i
= 0; i
< zlhs
; i
++) {
2404 generate_lhs_piece(state
, ins
, i
);
2408 static struct triple
*label(struct compile_state
*state
)
2410 /* Labels don't get a type */
2411 struct triple
*result
;
2412 result
= triple(state
, OP_LABEL
, &void_type
, 0, 0);
2416 static struct triple
*mkprog(struct compile_state
*state
, ...)
2418 struct triple
*prog
, *head
, *arg
;
2422 head
= label(state
);
2423 prog
= new_triple(state
, OP_PROG
, &void_type
, -1, -1);
2424 RHS(prog
, 0) = head
;
2425 va_start(args
, state
);
2427 while((arg
= va_arg(args
, struct triple
*)) != 0) {
2429 internal_error(state
, 0, "too many arguments to mkprog");
2431 flatten(state
, head
, arg
);
2434 prog
->type
= head
->prev
->type
;
2437 static void name_of(FILE *fp
, struct type
*type
);
2438 static void display_triple(FILE *fp
, struct triple
*ins
)
2440 struct occurance
*ptr
;
2442 char pre
, post
, vol
;
2443 pre
= post
= vol
= ' ';
2445 if (ins
->id
& TRIPLE_FLAG_PRE_SPLIT
) {
2448 if (ins
->id
& TRIPLE_FLAG_POST_SPLIT
) {
2451 if (ins
->id
& TRIPLE_FLAG_VOLATILE
) {
2454 reg
= arch_reg_str(ID_REG(ins
->id
));
2457 fprintf(fp
, "(%p) <nothing> ", ins
);
2459 else if (ins
->op
== OP_INTCONST
) {
2460 fprintf(fp
, "(%p) %c%c%c %-7s %-2d %-10s <0x%08lx> ",
2461 ins
, pre
, post
, vol
, reg
, ins
->template_id
, tops(ins
->op
),
2462 (unsigned long)(ins
->u
.cval
));
2464 else if (ins
->op
== OP_ADDRCONST
) {
2465 fprintf(fp
, "(%p) %c%c%c %-7s %-2d %-10s %-10p <0x%08lx>",
2466 ins
, pre
, post
, vol
, reg
, ins
->template_id
, tops(ins
->op
),
2467 MISC(ins
, 0), (unsigned long)(ins
->u
.cval
));
2469 else if (ins
->op
== OP_INDEX
) {
2470 fprintf(fp
, "(%p) %c%c%c %-7s %-2d %-10s %-10p <0x%08lx>",
2471 ins
, pre
, post
, vol
, reg
, ins
->template_id
, tops(ins
->op
),
2472 RHS(ins
, 0), (unsigned long)(ins
->u
.cval
));
2474 else if (ins
->op
== OP_PIECE
) {
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
));
2481 fprintf(fp
, "(%p) %c%c%c %-7s %-2d %-10s",
2482 ins
, pre
, post
, vol
, reg
, ins
->template_id
, tops(ins
->op
));
2483 if (table_ops
[ins
->op
].flags
& BITFIELD
) {
2484 fprintf(fp
, " <%2d-%2d:%2d>",
2485 ins
->u
.bitfield
.offset
,
2486 ins
->u
.bitfield
.offset
+ ins
->u
.bitfield
.size
,
2487 ins
->u
.bitfield
.size
);
2489 count
= TRIPLE_SIZE(ins
);
2490 for(i
= 0; i
< count
; i
++) {
2491 fprintf(fp
, " %-10p", ins
->param
[i
]);
2498 struct triple_set
*user
;
2499 #if DEBUG_DISPLAY_TYPES
2501 name_of(fp
, ins
->type
);
2504 #if DEBUG_DISPLAY_USES
2506 for(user
= ins
->use
; user
; user
= user
->next
) {
2507 fprintf(fp
, " %-10p", user
->member
);
2512 for(ptr
= ins
->occurance
; ptr
; ptr
= ptr
->parent
) {
2513 fprintf(fp
, " %s,%s:%d.%d",
2519 if (ins
->op
== OP_ASM
) {
2520 fprintf(fp
, "\n\t%s", ins
->u
.ainfo
->str
);
2527 static int equiv_types(struct type
*left
, struct type
*right
);
2528 static void display_triple_changes(
2529 FILE *fp
, const struct triple
*new, const struct triple
*orig
)
2532 int new_count
, orig_count
;
2533 new_count
= TRIPLE_SIZE(new);
2534 orig_count
= TRIPLE_SIZE(orig
);
2535 if ((new->op
!= orig
->op
) ||
2536 (new_count
!= orig_count
) ||
2537 (memcmp(orig
->param
, new->param
,
2538 orig_count
* sizeof(orig
->param
[0])) != 0) ||
2539 (memcmp(&orig
->u
, &new->u
, sizeof(orig
->u
)) != 0))
2541 struct occurance
*ptr
;
2542 int i
, min_count
, indent
;
2543 fprintf(fp
, "(%p %p)", new, orig
);
2544 if (orig
->op
== new->op
) {
2545 fprintf(fp
, " %-11s", tops(orig
->op
));
2547 fprintf(fp
, " [%-10s %-10s]",
2548 tops(new->op
), tops(orig
->op
));
2550 min_count
= new_count
;
2551 if (min_count
> orig_count
) {
2552 min_count
= orig_count
;
2554 for(indent
= i
= 0; i
< min_count
; i
++) {
2555 if (orig
->param
[i
] == new->param
[i
]) {
2556 fprintf(fp
, " %-11p",
2560 fprintf(fp
, " [%-10p %-10p]",
2566 for(; i
< orig_count
; i
++) {
2567 fprintf(fp
, " [%-9p]", orig
->param
[i
]);
2570 for(; i
< new_count
; i
++) {
2571 fprintf(fp
, " [%-9p]", new->param
[i
]);
2574 if ((new->op
== OP_INTCONST
)||
2575 (new->op
== OP_ADDRCONST
)) {
2576 fprintf(fp
, " <0x%08lx>",
2577 (unsigned long)(new->u
.cval
));
2580 for(;indent
< 36; indent
++) {
2584 #if DEBUG_DISPLAY_TYPES
2586 name_of(fp
, new->type
);
2587 if (!equiv_types(new->type
, orig
->type
)) {
2588 fprintf(fp
, " -- ");
2589 name_of(fp
, orig
->type
);
2595 for(ptr
= orig
->occurance
; ptr
; ptr
= ptr
->parent
) {
2596 fprintf(fp
, " %s,%s:%d.%d",
2608 static int triple_is_pure(struct compile_state
*state
, struct triple
*ins
, unsigned id
)
2610 /* Does the triple have no side effects.
2611 * I.e. Rexecuting the triple with the same arguments
2612 * gives the same value.
2615 valid_ins(state
, ins
);
2616 pure
= PURE_BITS(table_ops
[ins
->op
].flags
);
2617 if ((pure
!= PURE
) && (pure
!= IMPURE
)) {
2618 internal_error(state
, 0, "Purity of %s not known",
2621 return (pure
== PURE
) && !(id
& TRIPLE_FLAG_VOLATILE
);
2624 static int triple_is_branch_type(struct compile_state
*state
,
2625 struct triple
*ins
, unsigned type
)
2627 /* Is this one of the passed branch types? */
2628 valid_ins(state
, ins
);
2629 return (BRANCH_BITS(table_ops
[ins
->op
].flags
) == type
);
2632 static int triple_is_branch(struct compile_state
*state
, struct triple
*ins
)
2634 /* Is this triple a branch instruction? */
2635 valid_ins(state
, ins
);
2636 return (BRANCH_BITS(table_ops
[ins
->op
].flags
) != 0);
2639 static int triple_is_cbranch(struct compile_state
*state
, struct triple
*ins
)
2641 /* Is this triple a conditional branch instruction? */
2642 return triple_is_branch_type(state
, ins
, CBRANCH
);
2645 static int triple_is_ubranch(struct compile_state
*state
, struct triple
*ins
)
2647 /* Is this triple a unconditional branch instruction? */
2649 valid_ins(state
, ins
);
2650 type
= BRANCH_BITS(table_ops
[ins
->op
].flags
);
2651 return (type
!= 0) && (type
!= CBRANCH
);
2654 static int triple_is_call(struct compile_state
*state
, struct triple
*ins
)
2656 /* Is this triple a call instruction? */
2657 return triple_is_branch_type(state
, ins
, CALLBRANCH
);
2660 static int triple_is_ret(struct compile_state
*state
, struct triple
*ins
)
2662 /* Is this triple a return instruction? */
2663 return triple_is_branch_type(state
, ins
, RETBRANCH
);
2666 #if DEBUG_ROMCC_WARNING
2667 static int triple_is_simple_ubranch(struct compile_state
*state
, struct triple
*ins
)
2669 /* Is this triple an unconditional branch and not a call or a
2671 return triple_is_branch_type(state
, ins
, UBRANCH
);
2675 static int triple_is_end(struct compile_state
*state
, struct triple
*ins
)
2677 return triple_is_branch_type(state
, ins
, ENDBRANCH
);
2680 static int triple_is_label(struct compile_state
*state
, struct triple
*ins
)
2682 valid_ins(state
, ins
);
2683 return (ins
->op
== OP_LABEL
);
2686 static struct triple
*triple_to_block_start(
2687 struct compile_state
*state
, struct triple
*start
)
2689 while(!triple_is_branch(state
, start
->prev
) &&
2690 (!triple_is_label(state
, start
) || !start
->use
)) {
2691 start
= start
->prev
;
2696 static int triple_is_def(struct compile_state
*state
, struct triple
*ins
)
2698 /* This function is used to determine which triples need
2702 valid_ins(state
, ins
);
2703 is_def
= (table_ops
[ins
->op
].flags
& DEF
) == DEF
;
2704 if (ins
->lhs
>= 1) {
2710 static int triple_is_structural(struct compile_state
*state
, struct triple
*ins
)
2713 valid_ins(state
, ins
);
2714 is_structural
= (table_ops
[ins
->op
].flags
& STRUCTURAL
) == STRUCTURAL
;
2715 return is_structural
;
2718 static int triple_is_part(struct compile_state
*state
, struct triple
*ins
)
2721 valid_ins(state
, ins
);
2722 is_part
= (table_ops
[ins
->op
].flags
& PART
) == PART
;
2726 static int triple_is_auto_var(struct compile_state
*state
, struct triple
*ins
)
2728 return (ins
->op
== OP_PIECE
) && (MISC(ins
, 0)->op
== OP_ADECL
);
2731 static struct triple
**triple_iter(struct compile_state
*state
,
2732 size_t count
, struct triple
**vector
,
2733 struct triple
*ins
, struct triple
**last
)
2735 struct triple
**ret
;
2741 else if ((last
>= vector
) && (last
< (vector
+ count
- 1))) {
2749 static struct triple
**triple_lhs(struct compile_state
*state
,
2750 struct triple
*ins
, struct triple
**last
)
2752 return triple_iter(state
, ins
->lhs
, &LHS(ins
,0),
2756 static struct triple
**triple_rhs(struct compile_state
*state
,
2757 struct triple
*ins
, struct triple
**last
)
2759 return triple_iter(state
, ins
->rhs
, &RHS(ins
,0),
2763 static struct triple
**triple_misc(struct compile_state
*state
,
2764 struct triple
*ins
, struct triple
**last
)
2766 return triple_iter(state
, ins
->misc
, &MISC(ins
,0),
2770 static struct triple
**do_triple_targ(struct compile_state
*state
,
2771 struct triple
*ins
, struct triple
**last
, int call_edges
, int next_edges
)
2774 struct triple
**ret
, **vector
;
2779 if (triple_is_cbranch(state
, ins
)) {
2782 if (!call_edges
&& triple_is_call(state
, ins
)) {
2785 if (next_edges
&& triple_is_call(state
, ins
)) {
2788 vector
= &TARG(ins
, 0);
2789 if (!ret
&& next_is_targ
) {
2792 } else if (last
== &ins
->next
) {
2796 if (!ret
&& count
) {
2800 else if ((last
>= vector
) && (last
< (vector
+ count
- 1))) {
2803 else if (last
== vector
+ count
- 1) {
2807 if (!ret
&& triple_is_ret(state
, ins
) && call_edges
) {
2808 struct triple_set
*use
;
2809 for(use
= ins
->use
; use
; use
= use
->next
) {
2810 if (!triple_is_call(state
, use
->member
)) {
2814 ret
= &use
->member
->next
;
2817 else if (last
== &use
->member
->next
) {
2825 static struct triple
**triple_targ(struct compile_state
*state
,
2826 struct triple
*ins
, struct triple
**last
)
2828 return do_triple_targ(state
, ins
, last
, 1, 1);
2831 static struct triple
**triple_edge_targ(struct compile_state
*state
,
2832 struct triple
*ins
, struct triple
**last
)
2834 return do_triple_targ(state
, ins
, last
,
2835 state
->functions_joined
, !state
->functions_joined
);
2838 static struct triple
*after_lhs(struct compile_state
*state
, struct triple
*ins
)
2840 struct triple
*next
;
2844 for(i
= 0; i
< lhs
; i
++) {
2845 struct triple
*piece
;
2846 piece
= LHS(ins
, i
);
2847 if (next
!= piece
) {
2848 internal_error(state
, ins
, "malformed lhs on %s",
2851 if (next
->op
!= OP_PIECE
) {
2852 internal_error(state
, ins
, "bad lhs op %s at %d on %s",
2853 tops(next
->op
), i
, tops(ins
->op
));
2855 if (next
->u
.cval
!= i
) {
2856 internal_error(state
, ins
, "bad u.cval of %d %d expected",
2864 /* Function piece accessor functions */
2865 static struct triple
*do_farg(struct compile_state
*state
,
2866 struct triple
*func
, unsigned index
)
2869 struct triple
*first
, *arg
;
2873 if(index
>= (ftype
->elements
+ 2)) {
2874 internal_error(state
, func
, "bad argument index: %d", index
);
2876 first
= RHS(func
, 0);
2878 for(i
= 0; i
< index
; i
++, arg
= after_lhs(state
, arg
)) {
2881 if (arg
->op
!= OP_ADECL
) {
2882 internal_error(state
, 0, "arg not adecl?");
2886 static struct triple
*fresult(struct compile_state
*state
, struct triple
*func
)
2888 return do_farg(state
, func
, 0);
2890 static struct triple
*fretaddr(struct compile_state
*state
, struct triple
*func
)
2892 return do_farg(state
, func
, 1);
2894 static struct triple
*farg(struct compile_state
*state
,
2895 struct triple
*func
, unsigned index
)
2897 return do_farg(state
, func
, index
+ 2);
2901 static void display_func(struct compile_state
*state
, FILE *fp
, struct triple
*func
)
2903 struct triple
*first
, *ins
;
2904 fprintf(fp
, "display_func %s\n", func
->type
->type_ident
->name
);
2905 first
= ins
= RHS(func
, 0);
2907 if (triple_is_label(state
, ins
) && ins
->use
) {
2908 fprintf(fp
, "%p:\n", ins
);
2910 display_triple(fp
, ins
);
2912 if (triple_is_branch(state
, ins
)) {
2915 if (ins
->next
->prev
!= ins
) {
2916 internal_error(state
, ins
->next
, "bad prev");
2919 } while(ins
!= first
);
2922 static void verify_use(struct compile_state
*state
,
2923 struct triple
*user
, struct triple
*used
)
2926 size
= TRIPLE_SIZE(user
);
2927 for(i
= 0; i
< size
; i
++) {
2928 if (user
->param
[i
] == used
) {
2932 if (triple_is_branch(state
, user
)) {
2933 if (user
->next
== used
) {
2938 internal_error(state
, user
, "%s(%p) does not use %s(%p)",
2939 tops(user
->op
), user
, tops(used
->op
), used
);
2943 static int find_rhs_use(struct compile_state
*state
,
2944 struct triple
*user
, struct triple
*used
)
2946 struct triple
**param
;
2948 verify_use(state
, user
, used
);
2950 #if DEBUG_ROMCC_WARNINGS
2951 #warning "AUDIT ME ->rhs"
2954 param
= &RHS(user
, 0);
2955 for(i
= 0; i
< size
; i
++) {
2956 if (param
[i
] == used
) {
2963 static void free_triple(struct compile_state
*state
, struct triple
*ptr
)
2966 size
= sizeof(*ptr
) - sizeof(ptr
->param
) +
2967 (sizeof(ptr
->param
[0])*TRIPLE_SIZE(ptr
));
2968 ptr
->prev
->next
= ptr
->next
;
2969 ptr
->next
->prev
= ptr
->prev
;
2971 internal_error(state
, ptr
, "ptr->use != 0");
2973 put_occurance(ptr
->occurance
);
2974 memset(ptr
, -1, size
);
2978 static void release_triple(struct compile_state
*state
, struct triple
*ptr
)
2980 struct triple_set
*set
, *next
;
2981 struct triple
**expr
;
2982 struct block
*block
;
2983 if (ptr
== &unknown_triple
) {
2986 valid_ins(state
, ptr
);
2987 /* Make certain the we are not the first or last element of a block */
2988 block
= block_of_triple(state
, ptr
);
2990 if ((block
->last
== ptr
) && (block
->first
== ptr
)) {
2991 block
->last
= block
->first
= 0;
2993 else if (block
->last
== ptr
) {
2994 block
->last
= ptr
->prev
;
2996 else if (block
->first
== ptr
) {
2997 block
->first
= ptr
->next
;
3000 /* Remove ptr from use chains where it is the user */
3001 expr
= triple_rhs(state
, ptr
, 0);
3002 for(; expr
; expr
= triple_rhs(state
, ptr
, expr
)) {
3004 unuse_triple(*expr
, ptr
);
3007 expr
= triple_lhs(state
, ptr
, 0);
3008 for(; expr
; expr
= triple_lhs(state
, ptr
, expr
)) {
3010 unuse_triple(*expr
, ptr
);
3013 expr
= triple_misc(state
, ptr
, 0);
3014 for(; expr
; expr
= triple_misc(state
, ptr
, expr
)) {
3016 unuse_triple(*expr
, ptr
);
3019 expr
= triple_targ(state
, ptr
, 0);
3020 for(; expr
; expr
= triple_targ(state
, ptr
, expr
)) {
3022 unuse_triple(*expr
, ptr
);
3025 /* Reomve ptr from use chains where it is used */
3026 for(set
= ptr
->use
; set
; set
= next
) {
3028 valid_ins(state
, set
->member
);
3029 expr
= triple_rhs(state
, set
->member
, 0);
3030 for(; expr
; expr
= triple_rhs(state
, set
->member
, expr
)) {
3032 *expr
= &unknown_triple
;
3035 expr
= triple_lhs(state
, set
->member
, 0);
3036 for(; expr
; expr
= triple_lhs(state
, set
->member
, expr
)) {
3038 *expr
= &unknown_triple
;
3041 expr
= triple_misc(state
, set
->member
, 0);
3042 for(; expr
; expr
= triple_misc(state
, set
->member
, expr
)) {
3044 *expr
= &unknown_triple
;
3047 expr
= triple_targ(state
, set
->member
, 0);
3048 for(; expr
; expr
= triple_targ(state
, set
->member
, expr
)) {
3050 *expr
= &unknown_triple
;
3053 unuse_triple(ptr
, set
->member
);
3055 free_triple(state
, ptr
);
3058 static void print_triples(struct compile_state
*state
);
3059 static void print_blocks(struct compile_state
*state
, const char *func
, FILE *fp
);
3061 #define TOK_UNKNOWN 0
3064 #define TOK_LBRACE 3
3065 #define TOK_RBRACE 4
3069 #define TOK_LBRACKET 8
3070 #define TOK_RBRACKET 9
3071 #define TOK_LPAREN 10
3072 #define TOK_RPAREN 11
3077 #define TOK_TIMESEQ 16
3078 #define TOK_DIVEQ 17
3079 #define TOK_MODEQ 18
3080 #define TOK_PLUSEQ 19
3081 #define TOK_MINUSEQ 20
3084 #define TOK_ANDEQ 23
3085 #define TOK_XOREQ 24
3088 #define TOK_NOTEQ 27
3089 #define TOK_QUEST 28
3090 #define TOK_LOGOR 29
3091 #define TOK_LOGAND 30
3095 #define TOK_LESSEQ 34
3096 #define TOK_MOREEQ 35
3100 #define TOK_MINUS 39
3103 #define TOK_PLUSPLUS 42
3104 #define TOK_MINUSMINUS 43
3106 #define TOK_ARROW 45
3108 #define TOK_TILDE 47
3109 #define TOK_LIT_STRING 48
3110 #define TOK_LIT_CHAR 49
3111 #define TOK_LIT_INT 50
3112 #define TOK_LIT_FLOAT 51
3113 #define TOK_MACRO 52
3114 #define TOK_CONCATENATE 53
3116 #define TOK_IDENT 54
3117 #define TOK_STRUCT_NAME 55
3118 #define TOK_ENUM_CONST 56
3119 #define TOK_TYPE_NAME 57
3122 #define TOK_BREAK 59
3125 #define TOK_CONST 62
3126 #define TOK_CONTINUE 63
3127 #define TOK_DEFAULT 64
3129 #define TOK_DOUBLE 66
3132 #define TOK_EXTERN 69
3133 #define TOK_FLOAT 70
3137 #define TOK_INLINE 74
3140 #define TOK_REGISTER 77
3141 #define TOK_RESTRICT 78
3142 #define TOK_RETURN 79
3143 #define TOK_SHORT 80
3144 #define TOK_SIGNED 81
3145 #define TOK_SIZEOF 82
3146 #define TOK_STATIC 83
3147 #define TOK_STRUCT 84
3148 #define TOK_SWITCH 85
3149 #define TOK_TYPEDEF 86
3150 #define TOK_UNION 87
3151 #define TOK_UNSIGNED 88
3153 #define TOK_VOLATILE 90
3154 #define TOK_WHILE 91
3156 #define TOK_ATTRIBUTE 93
3157 #define TOK_ALIGNOF 94
3158 #define TOK_FIRST_KEYWORD TOK_AUTO
3159 #define TOK_LAST_KEYWORD TOK_ALIGNOF
3161 #define TOK_MDEFINE 100
3162 #define TOK_MDEFINED 101
3163 #define TOK_MUNDEF 102
3164 #define TOK_MINCLUDE 103
3165 #define TOK_MLINE 104
3166 #define TOK_MERROR 105
3167 #define TOK_MWARNING 106
3168 #define TOK_MPRAGMA 107
3169 #define TOK_MIFDEF 108
3170 #define TOK_MIFNDEF 109
3171 #define TOK_MELIF 110
3172 #define TOK_MENDIF 111
3174 #define TOK_FIRST_MACRO TOK_MDEFINE
3175 #define TOK_LAST_MACRO TOK_MENDIF
3178 #define TOK_MELSE 113
3179 #define TOK_MIDENT 114
3184 static const char *tokens
[] = {
3185 [TOK_UNKNOWN
] = ":unknown:",
3186 [TOK_SPACE
] = ":space:",
3188 [TOK_LBRACE
] = "{",
3189 [TOK_RBRACE
] = "}",
3193 [TOK_LBRACKET
] = "[",
3194 [TOK_RBRACKET
] = "]",
3195 [TOK_LPAREN
] = "(",
3196 [TOK_RPAREN
] = ")",
3198 [TOK_DOTS
] = "...",
3201 [TOK_TIMESEQ
] = "*=",
3202 [TOK_DIVEQ
] = "/=",
3203 [TOK_MODEQ
] = "%=",
3204 [TOK_PLUSEQ
] = "+=",
3205 [TOK_MINUSEQ
] = "-=",
3206 [TOK_SLEQ
] = "<<=",
3207 [TOK_SREQ
] = ">>=",
3208 [TOK_ANDEQ
] = "&=",
3209 [TOK_XOREQ
] = "^=",
3212 [TOK_NOTEQ
] = "!=",
3214 [TOK_LOGOR
] = "||",
3215 [TOK_LOGAND
] = "&&",
3219 [TOK_LESSEQ
] = "<=",
3220 [TOK_MOREEQ
] = ">=",
3227 [TOK_PLUSPLUS
] = "++",
3228 [TOK_MINUSMINUS
] = "--",
3230 [TOK_ARROW
] = "->",
3233 [TOK_LIT_STRING
] = ":string:",
3234 [TOK_IDENT
] = ":ident:",
3235 [TOK_TYPE_NAME
] = ":typename:",
3236 [TOK_LIT_CHAR
] = ":char:",
3237 [TOK_LIT_INT
] = ":integer:",
3238 [TOK_LIT_FLOAT
] = ":float:",
3240 [TOK_CONCATENATE
] = "##",
3242 [TOK_AUTO
] = "auto",
3243 [TOK_BREAK
] = "break",
3244 [TOK_CASE
] = "case",
3245 [TOK_CHAR
] = "char",
3246 [TOK_CONST
] = "const",
3247 [TOK_CONTINUE
] = "continue",
3248 [TOK_DEFAULT
] = "default",
3250 [TOK_DOUBLE
] = "double",
3251 [TOK_ELSE
] = "else",
3252 [TOK_ENUM
] = "enum",
3253 [TOK_EXTERN
] = "extern",
3254 [TOK_FLOAT
] = "float",
3256 [TOK_GOTO
] = "goto",
3258 [TOK_INLINE
] = "inline",
3260 [TOK_LONG
] = "long",
3261 [TOK_REGISTER
] = "register",
3262 [TOK_RESTRICT
] = "restrict",
3263 [TOK_RETURN
] = "return",
3264 [TOK_SHORT
] = "short",
3265 [TOK_SIGNED
] = "signed",
3266 [TOK_SIZEOF
] = "sizeof",
3267 [TOK_STATIC
] = "static",
3268 [TOK_STRUCT
] = "struct",
3269 [TOK_SWITCH
] = "switch",
3270 [TOK_TYPEDEF
] = "typedef",
3271 [TOK_UNION
] = "union",
3272 [TOK_UNSIGNED
] = "unsigned",
3273 [TOK_VOID
] = "void",
3274 [TOK_VOLATILE
] = "volatile",
3275 [TOK_WHILE
] = "while",
3277 [TOK_ATTRIBUTE
] = "__attribute__",
3278 [TOK_ALIGNOF
] = "__alignof__",
3280 [TOK_MDEFINE
] = "#define",
3281 [TOK_MDEFINED
] = "#defined",
3282 [TOK_MUNDEF
] = "#undef",
3283 [TOK_MINCLUDE
] = "#include",
3284 [TOK_MLINE
] = "#line",
3285 [TOK_MERROR
] = "#error",
3286 [TOK_MWARNING
] = "#warning",
3287 [TOK_MPRAGMA
] = "#pragma",
3288 [TOK_MIFDEF
] = "#ifdef",
3289 [TOK_MIFNDEF
] = "#ifndef",
3290 [TOK_MELIF
] = "#elif",
3291 [TOK_MENDIF
] = "#endif",
3294 [TOK_MELSE
] = "#else",
3295 [TOK_MIDENT
] = "#:ident:",
3300 static unsigned int hash(const char *str
, int str_len
)
3304 end
= str
+ str_len
;
3306 for(; str
< end
; str
++) {
3307 hash
= (hash
*263) + *str
;
3309 hash
= hash
& (HASH_TABLE_SIZE
-1);
3313 static struct hash_entry
*lookup(
3314 struct compile_state
*state
, const char *name
, int name_len
)
3316 struct hash_entry
*entry
;
3318 index
= hash(name
, name_len
);
3319 entry
= state
->hash_table
[index
];
3321 ((entry
->name_len
!= name_len
) ||
3322 (memcmp(entry
->name
, name
, name_len
) != 0))) {
3323 entry
= entry
->next
;
3327 /* Get a private copy of the name */
3328 new_name
= xmalloc(name_len
+ 1, "hash_name");
3329 memcpy(new_name
, name
, name_len
);
3330 new_name
[name_len
] = '\0';
3332 /* Create a new hash entry */
3333 entry
= xcmalloc(sizeof(*entry
), "hash_entry");
3334 entry
->next
= state
->hash_table
[index
];
3335 entry
->name
= new_name
;
3336 entry
->name_len
= name_len
;
3338 /* Place the new entry in the hash table */
3339 state
->hash_table
[index
] = entry
;
3344 static void ident_to_keyword(struct compile_state
*state
, struct token
*tk
)
3346 struct hash_entry
*entry
;
3348 if (entry
&& ((entry
->tok
== TOK_TYPE_NAME
) ||
3349 (entry
->tok
== TOK_ENUM_CONST
) ||
3350 ((entry
->tok
>= TOK_FIRST_KEYWORD
) &&
3351 (entry
->tok
<= TOK_LAST_KEYWORD
)))) {
3352 tk
->tok
= entry
->tok
;
3356 static void ident_to_macro(struct compile_state
*state
, struct token
*tk
)
3358 struct hash_entry
*entry
;
3362 if ((entry
->tok
>= TOK_FIRST_MACRO
) && (entry
->tok
<= TOK_LAST_MACRO
)) {
3363 tk
->tok
= entry
->tok
;
3365 else if (entry
->tok
== TOK_IF
) {
3368 else if (entry
->tok
== TOK_ELSE
) {
3369 tk
->tok
= TOK_MELSE
;
3372 tk
->tok
= TOK_MIDENT
;
3376 static void hash_keyword(
3377 struct compile_state
*state
, const char *keyword
, int tok
)
3379 struct hash_entry
*entry
;
3380 entry
= lookup(state
, keyword
, strlen(keyword
));
3381 if (entry
&& entry
->tok
!= TOK_UNKNOWN
) {
3382 die("keyword %s already hashed", keyword
);
3387 static void romcc_symbol(
3388 struct compile_state
*state
, struct hash_entry
*ident
,
3389 struct symbol
**chain
, struct triple
*def
, struct type
*type
, int depth
)
3392 if (*chain
&& ((*chain
)->scope_depth
>= depth
)) {
3393 error(state
, 0, "%s already defined", ident
->name
);
3395 sym
= xcmalloc(sizeof(*sym
), "symbol");
3399 sym
->scope_depth
= depth
;
3405 struct compile_state
*state
, struct hash_entry
*ident
,
3406 struct symbol
**chain
, struct triple
*def
, struct type
*type
)
3408 romcc_symbol(state
, ident
, chain
, def
, type
, state
->scope_depth
);
3411 static void var_symbol(struct compile_state
*state
,
3412 struct hash_entry
*ident
, struct triple
*def
)
3414 if ((def
->type
->type
& TYPE_MASK
) == TYPE_PRODUCT
) {
3415 internal_error(state
, 0, "bad var type");
3417 symbol(state
, ident
, &ident
->sym_ident
, def
, def
->type
);
3420 static void label_symbol(struct compile_state
*state
,
3421 struct hash_entry
*ident
, struct triple
*label
, int depth
)
3423 romcc_symbol(state
, ident
, &ident
->sym_label
, label
, &void_type
, depth
);
3426 static void start_scope(struct compile_state
*state
)
3428 state
->scope_depth
++;
3431 static void end_scope_syms(struct compile_state
*state
,
3432 struct symbol
**chain
, int depth
)
3434 struct symbol
*sym
, *next
;
3436 while(sym
&& (sym
->scope_depth
== depth
)) {
3444 static void end_scope(struct compile_state
*state
)
3448 /* Walk through the hash table and remove all symbols
3449 * in the current scope.
3451 depth
= state
->scope_depth
;
3452 for(i
= 0; i
< HASH_TABLE_SIZE
; i
++) {
3453 struct hash_entry
*entry
;
3454 entry
= state
->hash_table
[i
];
3456 end_scope_syms(state
, &entry
->sym_label
, depth
);
3457 end_scope_syms(state
, &entry
->sym_tag
, depth
);
3458 end_scope_syms(state
, &entry
->sym_ident
, depth
);
3459 entry
= entry
->next
;
3462 state
->scope_depth
= depth
- 1;
3465 static void register_keywords(struct compile_state
*state
)
3467 hash_keyword(state
, "auto", TOK_AUTO
);
3468 hash_keyword(state
, "break", TOK_BREAK
);
3469 hash_keyword(state
, "case", TOK_CASE
);
3470 hash_keyword(state
, "char", TOK_CHAR
);
3471 hash_keyword(state
, "const", TOK_CONST
);
3472 hash_keyword(state
, "continue", TOK_CONTINUE
);
3473 hash_keyword(state
, "default", TOK_DEFAULT
);
3474 hash_keyword(state
, "do", TOK_DO
);
3475 hash_keyword(state
, "double", TOK_DOUBLE
);
3476 hash_keyword(state
, "else", TOK_ELSE
);
3477 hash_keyword(state
, "enum", TOK_ENUM
);
3478 hash_keyword(state
, "extern", TOK_EXTERN
);
3479 hash_keyword(state
, "float", TOK_FLOAT
);
3480 hash_keyword(state
, "for", TOK_FOR
);
3481 hash_keyword(state
, "goto", TOK_GOTO
);
3482 hash_keyword(state
, "if", TOK_IF
);
3483 hash_keyword(state
, "inline", TOK_INLINE
);
3484 hash_keyword(state
, "int", TOK_INT
);
3485 hash_keyword(state
, "long", TOK_LONG
);
3486 hash_keyword(state
, "register", TOK_REGISTER
);
3487 hash_keyword(state
, "restrict", TOK_RESTRICT
);
3488 hash_keyword(state
, "return", TOK_RETURN
);
3489 hash_keyword(state
, "short", TOK_SHORT
);
3490 hash_keyword(state
, "signed", TOK_SIGNED
);
3491 hash_keyword(state
, "sizeof", TOK_SIZEOF
);
3492 hash_keyword(state
, "static", TOK_STATIC
);
3493 hash_keyword(state
, "struct", TOK_STRUCT
);
3494 hash_keyword(state
, "switch", TOK_SWITCH
);
3495 hash_keyword(state
, "typedef", TOK_TYPEDEF
);
3496 hash_keyword(state
, "union", TOK_UNION
);
3497 hash_keyword(state
, "unsigned", TOK_UNSIGNED
);
3498 hash_keyword(state
, "void", TOK_VOID
);
3499 hash_keyword(state
, "volatile", TOK_VOLATILE
);
3500 hash_keyword(state
, "__volatile__", TOK_VOLATILE
);
3501 hash_keyword(state
, "while", TOK_WHILE
);
3502 hash_keyword(state
, "asm", TOK_ASM
);
3503 hash_keyword(state
, "__asm__", TOK_ASM
);
3504 hash_keyword(state
, "__attribute__", TOK_ATTRIBUTE
);
3505 hash_keyword(state
, "__alignof__", TOK_ALIGNOF
);
3508 static void register_macro_keywords(struct compile_state
*state
)
3510 hash_keyword(state
, "define", TOK_MDEFINE
);
3511 hash_keyword(state
, "defined", TOK_MDEFINED
);
3512 hash_keyword(state
, "undef", TOK_MUNDEF
);
3513 hash_keyword(state
, "include", TOK_MINCLUDE
);
3514 hash_keyword(state
, "line", TOK_MLINE
);
3515 hash_keyword(state
, "error", TOK_MERROR
);
3516 hash_keyword(state
, "warning", TOK_MWARNING
);
3517 hash_keyword(state
, "pragma", TOK_MPRAGMA
);
3518 hash_keyword(state
, "ifdef", TOK_MIFDEF
);
3519 hash_keyword(state
, "ifndef", TOK_MIFNDEF
);
3520 hash_keyword(state
, "elif", TOK_MELIF
);
3521 hash_keyword(state
, "endif", TOK_MENDIF
);
3525 static void undef_macro(struct compile_state
*state
, struct hash_entry
*ident
)
3527 if (ident
->sym_define
!= 0) {
3528 struct macro
*macro
;
3529 struct macro_arg
*arg
, *anext
;
3530 macro
= ident
->sym_define
;
3531 ident
->sym_define
= 0;
3533 /* Free the macro arguments... */
3534 anext
= macro
->args
;
3541 /* Free the macro buffer */
3544 /* Now free the macro itself */
3549 static void do_define_macro(struct compile_state
*state
,
3550 struct hash_entry
*ident
, const char *body
,
3551 int argc
, struct macro_arg
*args
)
3553 struct macro
*macro
;
3554 struct macro_arg
*arg
;
3557 /* Find the length of the body */
3558 body_len
= strlen(body
);
3559 macro
= ident
->sym_define
;
3561 int identical_bodies
, identical_args
;
3562 struct macro_arg
*oarg
;
3563 /* Explicitly allow identical redfinitions of the same macro */
3565 (macro
->buf_len
== body_len
) &&
3566 (memcmp(macro
->buf
, body
, body_len
) == 0);
3567 identical_args
= macro
->argc
== argc
;
3570 while(identical_args
&& arg
) {
3571 identical_args
= oarg
->ident
== arg
->ident
;
3575 if (identical_bodies
&& identical_args
) {
3579 error(state
, 0, "macro %s already defined\n", ident
->name
);
3582 fprintf(state
->errout
, "#define %s: `%*.*s'\n",
3583 ident
->name
, body_len
, body_len
, body
);
3585 macro
= xmalloc(sizeof(*macro
), "macro");
3586 macro
->ident
= ident
;
3588 macro
->buf_len
= body_len
;
3592 ident
->sym_define
= macro
;
3595 static void define_macro(
3596 struct compile_state
*state
,
3597 struct hash_entry
*ident
,
3598 const char *body
, int body_len
,
3599 int argc
, struct macro_arg
*args
)
3602 buf
= xmalloc(body_len
+ 1, "macro buf");
3603 memcpy(buf
, body
, body_len
);
3604 buf
[body_len
] = '\0';
3605 do_define_macro(state
, ident
, buf
, argc
, args
);
3608 static void register_builtin_macro(struct compile_state
*state
,
3609 const char *name
, const char *value
)
3611 struct hash_entry
*ident
;
3613 if (value
[0] == '(') {
3614 internal_error(state
, 0, "Builtin macros with arguments not supported");
3616 ident
= lookup(state
, name
, strlen(name
));
3617 define_macro(state
, ident
, value
, strlen(value
), -1, 0);
3620 static void register_builtin_macros(struct compile_state
*state
)
3627 tm
= localtime(&now
);
3629 register_builtin_macro(state
, "__ROMCC__", VERSION_MAJOR
);
3630 register_builtin_macro(state
, "__ROMCC_MINOR__", VERSION_MINOR
);
3631 register_builtin_macro(state
, "__FILE__", "\"This should be the filename\"");
3632 register_builtin_macro(state
, "__LINE__", "54321");
3634 strftime(scratch
, sizeof(scratch
), "%b %e %Y", tm
);
3635 sprintf(buf
, "\"%s\"", scratch
);
3636 register_builtin_macro(state
, "__DATE__", buf
);
3638 strftime(scratch
, sizeof(scratch
), "%H:%M:%S", tm
);
3639 sprintf(buf
, "\"%s\"", scratch
);
3640 register_builtin_macro(state
, "__TIME__", buf
);
3642 /* I can't be a conforming implementation of C :( */
3643 register_builtin_macro(state
, "__STDC__", "0");
3644 /* In particular I don't conform to C99 */
3645 register_builtin_macro(state
, "__STDC_VERSION__", "199901L");
3649 static void process_cmdline_macros(struct compile_state
*state
)
3651 const char **macro
, *name
;
3652 struct hash_entry
*ident
;
3653 for(macro
= state
->compiler
->defines
; (name
= *macro
); macro
++) {
3657 name_len
= strlen(name
);
3658 body
= strchr(name
, '=');
3662 name_len
= body
- name
;
3665 ident
= lookup(state
, name
, name_len
);
3666 define_macro(state
, ident
, body
, strlen(body
), -1, 0);
3668 for(macro
= state
->compiler
->undefs
; (name
= *macro
); macro
++) {
3669 ident
= lookup(state
, name
, strlen(name
));
3670 undef_macro(state
, ident
);
3674 static int spacep(int c
)
3689 static int digitp(int c
)
3693 case '0': case '1': case '2': case '3': case '4':
3694 case '5': case '6': case '7': case '8': case '9':
3700 static int digval(int c
)
3703 if ((c
>= '0') && (c
<= '9')) {
3709 static int hexdigitp(int c
)
3713 case '0': case '1': case '2': case '3': case '4':
3714 case '5': case '6': case '7': case '8': case '9':
3715 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
3716 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
3722 static int hexdigval(int c
)
3725 if ((c
>= '0') && (c
<= '9')) {
3728 else if ((c
>= 'A') && (c
<= 'F')) {
3729 val
= 10 + (c
- 'A');
3731 else if ((c
>= 'a') && (c
<= 'f')) {
3732 val
= 10 + (c
- 'a');
3737 static int octdigitp(int c
)
3741 case '0': case '1': case '2': case '3':
3742 case '4': case '5': case '6': case '7':
3748 static int octdigval(int c
)
3751 if ((c
>= '0') && (c
<= '7')) {
3757 static int letterp(int c
)
3761 case 'a': case 'b': case 'c': case 'd': case 'e':
3762 case 'f': case 'g': case 'h': case 'i': case 'j':
3763 case 'k': case 'l': case 'm': case 'n': case 'o':
3764 case 'p': case 'q': case 'r': case 's': case 't':
3765 case 'u': case 'v': case 'w': case 'x': case 'y':
3767 case 'A': case 'B': case 'C': case 'D': case 'E':
3768 case 'F': case 'G': case 'H': case 'I': case 'J':
3769 case 'K': case 'L': case 'M': case 'N': case 'O':
3770 case 'P': case 'Q': case 'R': case 'S': case 'T':
3771 case 'U': case 'V': case 'W': case 'X': case 'Y':
3780 static const char *identifier(const char *str
, const char *end
)
3782 if (letterp(*str
)) {
3783 for(; str
< end
; str
++) {
3786 if (!letterp(c
) && !digitp(c
)) {
3794 static int char_value(struct compile_state
*state
,
3795 const signed char **strp
, const signed char *end
)
3797 const signed char *str
;
3801 if ((c
== '\\') && (str
< end
)) {
3803 case 'n': c
= '\n'; str
++; break;
3804 case 't': c
= '\t'; str
++; break;
3805 case 'v': c
= '\v'; str
++; break;
3806 case 'b': c
= '\b'; str
++; break;
3807 case 'r': c
= '\r'; str
++; break;
3808 case 'f': c
= '\f'; str
++; break;
3809 case 'a': c
= '\a'; str
++; break;
3810 case '\\': c
= '\\'; str
++; break;
3811 case '?': c
= '?'; str
++; break;
3812 case '\'': c
= '\''; str
++; break;
3813 case '"': c
= '"'; str
++; break;
3817 while((str
< end
) && hexdigitp(*str
)) {
3819 c
+= hexdigval(*str
);
3823 case '0': case '1': case '2': case '3':
3824 case '4': case '5': case '6': case '7':
3826 while((str
< end
) && octdigitp(*str
)) {
3828 c
+= octdigval(*str
);
3833 error(state
, 0, "Invalid character constant");
3841 static const char *next_char(struct file_state
*file
, const char *pos
, int index
)
3843 const char *end
= file
->buf
+ file
->size
;
3845 /* Lookup the character */
3848 /* Is this a trigraph? */
3849 if (file
->trigraphs
&&
3850 (c
== '?') && ((end
- pos
) >= 3) && (pos
[1] == '?'))
3853 case '=': c
= '#'; break;
3854 case '/': c
= '\\'; break;
3855 case '\'': c
= '^'; break;
3856 case '(': c
= '['; break;
3857 case ')': c
= ']'; break;
3858 case '!': c
= '!'; break;
3859 case '<': c
= '{'; break;
3860 case '>': c
= '}'; break;
3861 case '-': c
= '~'; break;
3867 /* Is this an escaped newline? */
3868 if (file
->join_lines
&&
3869 (c
== '\\') && (pos
+ size
< end
) && ((pos
[1] == '\n') || ((pos
[1] == '\r') && (pos
[2] == '\n'))))
3871 int cr_offset
= ((pos
[1] == '\r') && (pos
[2] == '\n'))?1:0;
3872 /* At the start of a line just eat it */
3873 if (pos
== file
->pos
) {
3875 file
->report_line
++;
3876 file
->line_start
= pos
+ size
+ 1 + cr_offset
;
3878 pos
+= size
+ 1 + cr_offset
;
3880 /* Do I need to ga any farther? */
3881 else if (index
== 0) {
3884 /* Process a normal character */
3893 static int get_char(struct file_state
*file
, const char *pos
)
3895 const char *end
= file
->buf
+ file
->size
;
3898 pos
= next_char(file
, pos
, 0);
3900 /* Lookup the character */
3902 /* If it is a trigraph get the trigraph value */
3903 if (file
->trigraphs
&&
3904 (c
== '?') && ((end
- pos
) >= 3) && (pos
[1] == '?'))
3907 case '=': c
= '#'; break;
3908 case '/': c
= '\\'; break;
3909 case '\'': c
= '^'; break;
3910 case '(': c
= '['; break;
3911 case ')': c
= ']'; break;
3912 case '!': c
= '!'; break;
3913 case '<': c
= '{'; break;
3914 case '>': c
= '}'; break;
3915 case '-': c
= '~'; break;
3922 static void eat_chars(struct file_state
*file
, const char *targ
)
3924 const char *pos
= file
->pos
;
3926 /* Do we have a newline? */
3927 if (pos
[0] == '\n') {
3929 file
->report_line
++;
3930 file
->line_start
= pos
+ 1;
3938 static size_t char_strlen(struct file_state
*file
, const char *src
, const char *end
)
3943 src
= next_char(file
, src
, 1);
3949 static void char_strcpy(char *dest
,
3950 struct file_state
*file
, const char *src
, const char *end
)
3954 c
= get_char(file
, src
);
3955 src
= next_char(file
, src
, 1);
3960 static char *char_strdup(struct file_state
*file
,
3961 const char *start
, const char *end
, const char *id
)
3965 str_len
= char_strlen(file
, start
, end
);
3966 str
= xcmalloc(str_len
+ 1, id
);
3967 char_strcpy(str
, file
, start
, end
);
3968 str
[str_len
] = '\0';
3972 static const char *after_digits(struct file_state
*file
, const char *ptr
)
3974 while(digitp(get_char(file
, ptr
))) {
3975 ptr
= next_char(file
, ptr
, 1);
3980 static const char *after_octdigits(struct file_state
*file
, const char *ptr
)
3982 while(octdigitp(get_char(file
, ptr
))) {
3983 ptr
= next_char(file
, ptr
, 1);
3988 static const char *after_hexdigits(struct file_state
*file
, const char *ptr
)
3990 while(hexdigitp(get_char(file
, ptr
))) {
3991 ptr
= next_char(file
, ptr
, 1);
3996 static const char *after_alnums(struct file_state
*file
, const char *ptr
)
3999 c
= get_char(file
, ptr
);
4000 while(letterp(c
) || digitp(c
)) {
4001 ptr
= next_char(file
, ptr
, 1);
4002 c
= get_char(file
, ptr
);
4007 static void save_string(struct file_state
*file
,
4008 struct token
*tk
, const char *start
, const char *end
, const char *id
)
4012 /* Create a private copy of the string */
4013 str
= char_strdup(file
, start
, end
, id
);
4015 /* Store the copy in the token */
4017 tk
->str_len
= strlen(str
);
4020 static void raw_next_token(struct compile_state
*state
,
4021 struct file_state
*file
, struct token
*tk
)
4031 token
= tokp
= next_char(file
, file
->pos
, 0);
4033 c
= get_char(file
, tokp
);
4034 tokp
= next_char(file
, tokp
, 1);
4036 c1
= get_char(file
, tokp
);
4037 c2
= get_char(file
, next_char(file
, tokp
, 1));
4038 c3
= get_char(file
, next_char(file
, tokp
, 2));
4040 /* The end of the file */
4045 else if (spacep(c
)) {
4047 while (spacep(get_char(file
, tokp
))) {
4048 tokp
= next_char(file
, tokp
, 1);
4052 else if ((c
== '/') && (c1
== '/')) {
4054 tokp
= next_char(file
, tokp
, 1);
4055 while((c
= get_char(file
, tokp
)) != -1) {
4056 /* Advance to the next character only after we verify
4057 * the current character is not a newline.
4058 * EOL is special to the preprocessor so we don't
4059 * want to loose any.
4064 tokp
= next_char(file
, tokp
, 1);
4068 else if ((c
== '/') && (c1
== '*')) {
4069 tokp
= next_char(file
, tokp
, 2);
4071 while((c1
= get_char(file
, tokp
)) != -1) {
4072 tokp
= next_char(file
, tokp
, 1);
4073 if ((c
== '*') && (c1
== '/')) {
4079 if (tok
== TOK_UNKNOWN
) {
4080 error(state
, 0, "unterminated comment");
4083 /* string constants */
4084 else if ((c
== '"') || ((c
== 'L') && (c1
== '"'))) {
4089 tokp
= next_char(file
, tokp
, 1);
4091 while((c
= get_char(file
, tokp
)) != -1) {
4092 tokp
= next_char(file
, tokp
, 1);
4096 else if (c
== '\\') {
4097 tokp
= next_char(file
, tokp
, 1);
4099 else if (c
== '"') {
4100 tok
= TOK_LIT_STRING
;
4104 if (tok
== TOK_UNKNOWN
) {
4105 error(state
, 0, "unterminated string constant");
4108 warning(state
, 0, "multiline string constant");
4111 /* Save the string value */
4112 save_string(file
, tk
, token
, tokp
, "literal string");
4114 /* character constants */
4115 else if ((c
== '\'') || ((c
== 'L') && (c1
== '\''))) {
4120 tokp
= next_char(file
, tokp
, 1);
4122 while((c
= get_char(file
, tokp
)) != -1) {
4123 tokp
= next_char(file
, tokp
, 1);
4127 else if (c
== '\\') {
4128 tokp
= next_char(file
, tokp
, 1);
4130 else if (c
== '\'') {
4135 if (tok
== TOK_UNKNOWN
) {
4136 error(state
, 0, "unterminated character constant");
4139 warning(state
, 0, "multiline character constant");
4142 /* Save the character value */
4143 save_string(file
, tk
, token
, tokp
, "literal character");
4145 /* integer and floating constants
4151 * Floating constants
4152 * {digits}.{digits}[Ee][+-]?{digits}
4154 * {digits}[Ee][+-]?{digits}
4155 * .{digits}[Ee][+-]?{digits}
4158 else if (digitp(c
) || ((c
== '.') && (digitp(c1
)))) {
4164 next
= after_digits(file
, tokp
);
4169 cn
= get_char(file
, next
);
4171 next
= next_char(file
, next
, 1);
4172 next
= after_digits(file
, next
);
4175 cn
= get_char(file
, next
);
4176 if ((cn
== 'e') || (cn
== 'E')) {
4178 next
= next_char(file
, next
, 1);
4179 cn
= get_char(file
, next
);
4180 if ((cn
== '+') || (cn
== '-')) {
4181 next
= next_char(file
, next
, 1);
4183 new = after_digits(file
, next
);
4184 is_float
|= (new != next
);
4188 tok
= TOK_LIT_FLOAT
;
4189 cn
= get_char(file
, next
);
4190 if ((cn
== 'f') || (cn
== 'F') || (cn
== 'l') || (cn
== 'L')) {
4191 next
= next_char(file
, next
, 1);
4194 if (!is_float
&& digitp(c
)) {
4196 if ((c
== '0') && ((c1
== 'x') || (c1
== 'X'))) {
4197 next
= next_char(file
, tokp
, 1);
4198 next
= after_hexdigits(file
, next
);
4200 else if (c
== '0') {
4201 next
= after_octdigits(file
, tokp
);
4204 next
= after_digits(file
, tokp
);
4206 /* crazy integer suffixes */
4207 cn
= get_char(file
, next
);
4208 if ((cn
== 'u') || (cn
== 'U')) {
4209 next
= next_char(file
, next
, 1);
4210 cn
= get_char(file
, next
);
4211 if ((cn
== 'l') || (cn
== 'L')) {
4212 next
= next_char(file
, next
, 1);
4213 cn
= get_char(file
, next
);
4215 if ((cn
== 'l') || (cn
== 'L')) {
4216 next
= next_char(file
, next
, 1);
4219 else if ((cn
== 'l') || (cn
== 'L')) {
4220 next
= next_char(file
, next
, 1);
4221 cn
= get_char(file
, next
);
4222 if ((cn
== 'l') || (cn
== 'L')) {
4223 next
= next_char(file
, next
, 1);
4224 cn
= get_char(file
, next
);
4226 if ((cn
== 'u') || (cn
== 'U')) {
4227 next
= next_char(file
, next
, 1);
4233 /* Save the integer/floating point value */
4234 save_string(file
, tk
, token
, tokp
, "literal number");
4237 else if (letterp(c
)) {
4240 /* Find and save the identifier string */
4241 tokp
= after_alnums(file
, tokp
);
4242 save_string(file
, tk
, token
, tokp
, "identifier");
4244 /* Look up to see which identifier it is */
4245 tk
->ident
= lookup(state
, tk
->val
.str
, tk
->str_len
);
4247 /* Free the identifier string */
4251 /* See if this identifier can be macro expanded */
4252 tk
->val
.notmacro
= 0;
4253 c
= get_char(file
, tokp
);
4255 tokp
= next_char(file
, tokp
, 1);
4256 tk
->val
.notmacro
= 1;
4259 /* C99 alternate macro characters */
4260 else if ((c
== '%') && (c1
== ':') && (c2
== '%') && (c3
== ':')) {
4262 tok
= TOK_CONCATENATE
;
4264 else if ((c
== '.') && (c1
== '.') && (c2
== '.')) { eat
+= 2; tok
= TOK_DOTS
; }
4265 else if ((c
== '<') && (c1
== '<') && (c2
== '=')) { eat
+= 2; tok
= TOK_SLEQ
; }
4266 else if ((c
== '>') && (c1
== '>') && (c2
== '=')) { eat
+= 2; tok
= TOK_SREQ
; }
4267 else if ((c
== '*') && (c1
== '=')) { eat
+= 1; tok
= TOK_TIMESEQ
; }
4268 else if ((c
== '/') && (c1
== '=')) { eat
+= 1; tok
= TOK_DIVEQ
; }
4269 else if ((c
== '%') && (c1
== '=')) { eat
+= 1; tok
= TOK_MODEQ
; }
4270 else if ((c
== '+') && (c1
== '=')) { eat
+= 1; tok
= TOK_PLUSEQ
; }
4271 else if ((c
== '-') && (c1
== '=')) { eat
+= 1; tok
= TOK_MINUSEQ
; }
4272 else if ((c
== '&') && (c1
== '=')) { eat
+= 1; tok
= TOK_ANDEQ
; }
4273 else if ((c
== '^') && (c1
== '=')) { eat
+= 1; tok
= TOK_XOREQ
; }
4274 else if ((c
== '|') && (c1
== '=')) { eat
+= 1; tok
= TOK_OREQ
; }
4275 else if ((c
== '=') && (c1
== '=')) { eat
+= 1; tok
= TOK_EQEQ
; }
4276 else if ((c
== '!') && (c1
== '=')) { eat
+= 1; tok
= TOK_NOTEQ
; }
4277 else if ((c
== '|') && (c1
== '|')) { eat
+= 1; tok
= TOK_LOGOR
; }
4278 else if ((c
== '&') && (c1
== '&')) { eat
+= 1; tok
= TOK_LOGAND
; }
4279 else if ((c
== '<') && (c1
== '=')) { eat
+= 1; tok
= TOK_LESSEQ
; }
4280 else if ((c
== '>') && (c1
== '=')) { eat
+= 1; tok
= TOK_MOREEQ
; }
4281 else if ((c
== '<') && (c1
== '<')) { eat
+= 1; tok
= TOK_SL
; }
4282 else if ((c
== '>') && (c1
== '>')) { eat
+= 1; tok
= TOK_SR
; }
4283 else if ((c
== '+') && (c1
== '+')) { eat
+= 1; tok
= TOK_PLUSPLUS
; }
4284 else if ((c
== '-') && (c1
== '-')) { eat
+= 1; tok
= TOK_MINUSMINUS
; }
4285 else if ((c
== '-') && (c1
== '>')) { eat
+= 1; tok
= TOK_ARROW
; }
4286 else if ((c
== '<') && (c1
== ':')) { eat
+= 1; tok
= TOK_LBRACKET
; }
4287 else if ((c
== ':') && (c1
== '>')) { eat
+= 1; tok
= TOK_RBRACKET
; }
4288 else if ((c
== '<') && (c1
== '%')) { eat
+= 1; tok
= TOK_LBRACE
; }
4289 else if ((c
== '%') && (c1
== '>')) { eat
+= 1; tok
= TOK_RBRACE
; }
4290 else if ((c
== '%') && (c1
== ':')) { eat
+= 1; tok
= TOK_MACRO
; }
4291 else if ((c
== '#') && (c1
== '#')) { eat
+= 1; tok
= TOK_CONCATENATE
; }
4292 else if (c
== ';') { tok
= TOK_SEMI
; }
4293 else if (c
== '{') { tok
= TOK_LBRACE
; }
4294 else if (c
== '}') { tok
= TOK_RBRACE
; }
4295 else if (c
== ',') { tok
= TOK_COMMA
; }
4296 else if (c
== '=') { tok
= TOK_EQ
; }
4297 else if (c
== ':') { tok
= TOK_COLON
; }
4298 else if (c
== '[') { tok
= TOK_LBRACKET
; }
4299 else if (c
== ']') { tok
= TOK_RBRACKET
; }
4300 else if (c
== '(') { tok
= TOK_LPAREN
; }
4301 else if (c
== ')') { tok
= TOK_RPAREN
; }
4302 else if (c
== '*') { tok
= TOK_STAR
; }
4303 else if (c
== '>') { tok
= TOK_MORE
; }
4304 else if (c
== '<') { tok
= TOK_LESS
; }
4305 else if (c
== '?') { tok
= TOK_QUEST
; }
4306 else if (c
== '|') { tok
= TOK_OR
; }
4307 else if (c
== '&') { tok
= TOK_AND
; }
4308 else if (c
== '^') { tok
= TOK_XOR
; }
4309 else if (c
== '+') { tok
= TOK_PLUS
; }
4310 else if (c
== '-') { tok
= TOK_MINUS
; }
4311 else if (c
== '/') { tok
= TOK_DIV
; }
4312 else if (c
== '%') { tok
= TOK_MOD
; }
4313 else if (c
== '!') { tok
= TOK_BANG
; }
4314 else if (c
== '.') { tok
= TOK_DOT
; }
4315 else if (c
== '~') { tok
= TOK_TILDE
; }
4316 else if (c
== '#') { tok
= TOK_MACRO
; }
4317 else if (c
== '\n') { tok
= TOK_EOL
; }
4319 tokp
= next_char(file
, tokp
, eat
);
4320 eat_chars(file
, tokp
);
4325 static void check_tok(struct compile_state
*state
, struct token
*tk
, int tok
)
4327 if (tk
->tok
!= tok
) {
4328 const char *name1
, *name2
;
4329 name1
= tokens
[tk
->tok
];
4331 if ((tk
->tok
== TOK_IDENT
) || (tk
->tok
== TOK_MIDENT
)) {
4332 name2
= tk
->ident
->name
;
4334 error(state
, 0, "\tfound %s %s expected %s",
4335 name1
, name2
, tokens
[tok
]);
4339 struct macro_arg_value
{
4340 struct hash_entry
*ident
;
4344 static struct macro_arg_value
*read_macro_args(
4345 struct compile_state
*state
, struct macro
*macro
,
4346 struct file_state
*file
, struct token
*tk
)
4348 struct macro_arg_value
*argv
;
4349 struct macro_arg
*arg
;
4353 if (macro
->argc
== 0) {
4355 raw_next_token(state
, file
, tk
);
4356 } while(tk
->tok
== TOK_SPACE
);
4359 argv
= xcmalloc(sizeof(*argv
) * macro
->argc
, "macro args");
4360 for(i
= 0, arg
= macro
->args
; arg
; arg
= arg
->next
, i
++) {
4363 argv
[i
].ident
= arg
->ident
;
4372 raw_next_token(state
, file
, tk
);
4374 if (!paren_depth
&& (tk
->tok
== TOK_COMMA
) &&
4375 (argv
[i
].ident
!= state
->i___VA_ARGS__
))
4378 if (i
>= macro
->argc
) {
4379 error(state
, 0, "too many args to %s\n",
4380 macro
->ident
->name
);
4385 if (tk
->tok
== TOK_LPAREN
) {
4389 if (tk
->tok
== TOK_RPAREN
) {
4390 if (paren_depth
== 0) {
4395 if (tk
->tok
== TOK_EOF
) {
4396 error(state
, 0, "End of file encountered while parsing macro arguments");
4399 len
= char_strlen(file
, start
, file
->pos
);
4400 argv
[i
].value
= xrealloc(
4401 argv
[i
].value
, argv
[i
].len
+ len
, "macro args");
4402 char_strcpy((char *)argv
[i
].value
+ argv
[i
].len
, file
, start
, file
->pos
);
4405 if (i
!= macro
->argc
-1) {
4406 error(state
, 0, "missing %s arg %d\n",
4407 macro
->ident
->name
, i
+2);
4413 static void free_macro_args(struct macro
*macro
, struct macro_arg_value
*argv
)
4416 for(i
= 0; i
< macro
->argc
; i
++) {
4417 xfree(argv
[i
].value
);
4427 static void grow_macro_buf(struct compile_state
*state
,
4428 const char *id
, struct macro_buf
*buf
,
4431 if ((buf
->pos
+ grow
) >= buf
->len
) {
4432 buf
->str
= xrealloc(buf
->str
, buf
->len
+ grow
, id
);
4437 static void append_macro_text(struct compile_state
*state
,
4438 const char *id
, struct macro_buf
*buf
,
4439 const char *fstart
, size_t flen
)
4441 grow_macro_buf(state
, id
, buf
, flen
);
4442 memcpy(buf
->str
+ buf
->pos
, fstart
, flen
);
4444 fprintf(state
->errout
, "append: `%*.*s' `%*.*s'\n",
4445 buf
->pos
, buf
->pos
, buf
->str
,
4446 flen
, flen
, buf
->str
+ buf
->pos
);
4452 static void append_macro_chars(struct compile_state
*state
,
4453 const char *id
, struct macro_buf
*buf
,
4454 struct file_state
*file
, const char *start
, const char *end
)
4457 flen
= char_strlen(file
, start
, end
);
4458 grow_macro_buf(state
, id
, buf
, flen
);
4459 char_strcpy(buf
->str
+ buf
->pos
, file
, start
, end
);
4461 fprintf(state
->errout
, "append: `%*.*s' `%*.*s'\n",
4462 buf
->pos
, buf
->pos
, buf
->str
,
4463 flen
, flen
, buf
->str
+ buf
->pos
);
4468 static int compile_macro(struct compile_state
*state
,
4469 struct file_state
**filep
, struct token
*tk
);
4471 static void macro_expand_args(struct compile_state
*state
,
4472 struct macro
*macro
, struct macro_arg_value
*argv
, struct token
*tk
)
4476 for(i
= 0; i
< macro
->argc
; i
++) {
4477 struct file_state fmacro
, *file
;
4478 struct macro_buf buf
;
4481 fmacro
.basename
= argv
[i
].ident
->name
;
4482 fmacro
.dirname
= "";
4483 fmacro
.buf
= (char *)argv
[i
].value
;
4484 fmacro
.size
= argv
[i
].len
;
4485 fmacro
.pos
= fmacro
.buf
;
4487 fmacro
.line_start
= fmacro
.buf
;
4488 fmacro
.report_line
= 1;
4489 fmacro
.report_name
= fmacro
.basename
;
4490 fmacro
.report_dir
= fmacro
.dirname
;
4492 fmacro
.trigraphs
= 0;
4493 fmacro
.join_lines
= 0;
4495 buf
.len
= argv
[i
].len
;
4496 buf
.str
= xmalloc(buf
.len
, argv
[i
].ident
->name
);
4501 raw_next_token(state
, file
, tk
);
4503 /* If we have recursed into another macro body
4506 if (tk
->tok
== TOK_EOF
) {
4507 struct file_state
*old
;
4513 /* old->basename is used keep it */
4514 xfree(old
->dirname
);
4519 else if (tk
->ident
&& tk
->ident
->sym_define
) {
4520 if (compile_macro(state
, &file
, tk
)) {
4525 append_macro_chars(state
, macro
->ident
->name
, &buf
,
4526 file
, tk
->pos
, file
->pos
);
4529 xfree(argv
[i
].value
);
4530 argv
[i
].value
= buf
.str
;
4531 argv
[i
].len
= buf
.pos
;
4536 static void expand_macro(struct compile_state
*state
,
4537 struct macro
*macro
, struct macro_buf
*buf
,
4538 struct macro_arg_value
*argv
, struct token
*tk
)
4540 struct file_state fmacro
;
4541 const char space
[] = " ";
4546 /* Place the macro body in a dummy file */
4548 fmacro
.basename
= macro
->ident
->name
;
4549 fmacro
.dirname
= "";
4550 fmacro
.buf
= macro
->buf
;
4551 fmacro
.size
= macro
->buf_len
;
4552 fmacro
.pos
= fmacro
.buf
;
4554 fmacro
.line_start
= fmacro
.buf
;
4555 fmacro
.report_line
= 1;
4556 fmacro
.report_name
= fmacro
.basename
;
4557 fmacro
.report_dir
= fmacro
.dirname
;
4559 fmacro
.trigraphs
= 0;
4560 fmacro
.join_lines
= 0;
4562 /* Allocate a buffer to hold the macro expansion */
4563 buf
->len
= macro
->buf_len
+ 3;
4564 buf
->str
= xmalloc(buf
->len
, macro
->ident
->name
);
4567 fstart
= fmacro
.pos
;
4568 raw_next_token(state
, &fmacro
, tk
);
4569 while(tk
->tok
!= TOK_EOF
) {
4570 flen
= fmacro
.pos
- fstart
;
4573 for(i
= 0; i
< macro
->argc
; i
++) {
4574 if (argv
[i
].ident
== tk
->ident
) {
4578 if (i
>= macro
->argc
) {
4581 /* Substitute macro parameter */
4582 fstart
= argv
[i
].value
;
4586 if (macro
->argc
< 0) {
4590 raw_next_token(state
, &fmacro
, tk
);
4591 } while(tk
->tok
== TOK_SPACE
);
4592 check_tok(state
, tk
, TOK_IDENT
);
4593 for(i
= 0; i
< macro
->argc
; i
++) {
4594 if (argv
[i
].ident
== tk
->ident
) {
4598 if (i
>= macro
->argc
) {
4599 error(state
, 0, "parameter `%s' not found",
4602 /* Stringize token */
4603 append_macro_text(state
, macro
->ident
->name
, buf
, "\"", 1);
4604 for(j
= 0; j
< argv
[i
].len
; j
++) {
4605 char *str
= argv
[i
].value
+ j
;
4611 else if (*str
== '"') {
4615 append_macro_text(state
, macro
->ident
->name
, buf
, str
, len
);
4617 append_macro_text(state
, macro
->ident
->name
, buf
, "\"", 1);
4621 case TOK_CONCATENATE
:
4622 /* Concatenate tokens */
4623 /* Delete the previous whitespace token */
4624 if (buf
->str
[buf
->pos
- 1] == ' ') {
4627 /* Skip the next sequence of whitspace tokens */
4629 fstart
= fmacro
.pos
;
4630 raw_next_token(state
, &fmacro
, tk
);
4631 } while(tk
->tok
== TOK_SPACE
);
4632 /* Restart at the top of the loop.
4633 * I need to process the non white space token.
4638 /* Collapse multiple spaces into one */
4639 if (buf
->str
[buf
->pos
- 1] != ' ') {
4651 append_macro_text(state
, macro
->ident
->name
, buf
, fstart
, flen
);
4653 fstart
= fmacro
.pos
;
4654 raw_next_token(state
, &fmacro
, tk
);
4658 static void tag_macro_name(struct compile_state
*state
,
4659 struct macro
*macro
, struct macro_buf
*buf
,
4662 /* Guard all instances of the macro name in the replacement
4663 * text from further macro expansion.
4665 struct file_state fmacro
;
4669 /* Put the old macro expansion buffer in a file */
4671 fmacro
.basename
= macro
->ident
->name
;
4672 fmacro
.dirname
= "";
4673 fmacro
.buf
= buf
->str
;
4674 fmacro
.size
= buf
->pos
;
4675 fmacro
.pos
= fmacro
.buf
;
4677 fmacro
.line_start
= fmacro
.buf
;
4678 fmacro
.report_line
= 1;
4679 fmacro
.report_name
= fmacro
.basename
;
4680 fmacro
.report_dir
= fmacro
.dirname
;
4682 fmacro
.trigraphs
= 0;
4683 fmacro
.join_lines
= 0;
4685 /* Allocate a new macro expansion buffer */
4686 buf
->len
= macro
->buf_len
+ 3;
4687 buf
->str
= xmalloc(buf
->len
, macro
->ident
->name
);
4690 fstart
= fmacro
.pos
;
4691 raw_next_token(state
, &fmacro
, tk
);
4692 while(tk
->tok
!= TOK_EOF
) {
4693 flen
= fmacro
.pos
- fstart
;
4694 if ((tk
->tok
== TOK_IDENT
) &&
4695 (tk
->ident
== macro
->ident
) &&
4696 (tk
->val
.notmacro
== 0))
4698 append_macro_text(state
, macro
->ident
->name
, buf
, fstart
, flen
);
4703 append_macro_text(state
, macro
->ident
->name
, buf
, fstart
, flen
);
4705 fstart
= fmacro
.pos
;
4706 raw_next_token(state
, &fmacro
, tk
);
4711 static int compile_macro(struct compile_state
*state
,
4712 struct file_state
**filep
, struct token
*tk
)
4714 struct file_state
*file
;
4715 struct hash_entry
*ident
;
4716 struct macro
*macro
;
4717 struct macro_arg_value
*argv
;
4718 struct macro_buf buf
;
4721 fprintf(state
->errout
, "macro: %s\n", tk
->ident
->name
);
4724 macro
= ident
->sym_define
;
4726 /* If this token comes from a macro expansion ignore it */
4727 if (tk
->val
.notmacro
) {
4730 /* If I am a function like macro and the identifier is not followed
4731 * by a left parenthesis, do nothing.
4733 if ((macro
->argc
>= 0) && (get_char(*filep
, (*filep
)->pos
) != '(')) {
4737 /* Read in the macro arguments */
4739 if (macro
->argc
>= 0) {
4740 raw_next_token(state
, *filep
, tk
);
4741 check_tok(state
, tk
, TOK_LPAREN
);
4743 argv
= read_macro_args(state
, macro
, *filep
, tk
);
4745 check_tok(state
, tk
, TOK_RPAREN
);
4747 /* Macro expand the macro arguments */
4748 macro_expand_args(state
, macro
, argv
, tk
);
4753 if (ident
== state
->i___FILE__
) {
4754 buf
.len
= strlen(state
->file
->basename
) + 1 + 2 + 3;
4755 buf
.str
= xmalloc(buf
.len
, ident
->name
);
4756 sprintf(buf
.str
, "\"%s\"", state
->file
->basename
);
4757 buf
.pos
= strlen(buf
.str
);
4759 else if (ident
== state
->i___LINE__
) {
4761 buf
.str
= xmalloc(buf
.len
, ident
->name
);
4762 sprintf(buf
.str
, "%d", state
->file
->line
);
4763 buf
.pos
= strlen(buf
.str
);
4766 expand_macro(state
, macro
, &buf
, argv
, tk
);
4768 /* Tag the macro name with a $ so it will no longer
4769 * be regonized as a canidate for macro expansion.
4771 tag_macro_name(state
, macro
, &buf
, tk
);
4774 fprintf(state
->errout
, "%s: %d -> `%*.*s'\n",
4775 ident
->name
, buf
.pos
, buf
.pos
, (int)(buf
.pos
), buf
.str
);
4778 free_macro_args(macro
, argv
);
4780 file
= xmalloc(sizeof(*file
), "file_state");
4781 file
->prev
= *filep
;
4782 file
->basename
= xstrdup(ident
->name
);
4783 file
->dirname
= xstrdup("");
4784 file
->buf
= buf
.str
;
4785 file
->size
= buf
.pos
;
4786 file
->pos
= file
->buf
;
4788 file
->line_start
= file
->pos
;
4789 file
->report_line
= 1;
4790 file
->report_name
= file
->basename
;
4791 file
->report_dir
= file
->dirname
;
4793 file
->trigraphs
= 0;
4794 file
->join_lines
= 0;
4799 static void eat_tokens(struct compile_state
*state
, int targ_tok
)
4801 if (state
->eat_depth
> 0) {
4802 internal_error(state
, 0, "Already eating...");
4804 state
->eat_depth
= state
->if_depth
;
4805 state
->eat_targ
= targ_tok
;
4807 static int if_eat(struct compile_state
*state
)
4809 return state
->eat_depth
> 0;
4811 static int if_value(struct compile_state
*state
)
4814 index
= state
->if_depth
/ CHAR_BIT
;
4815 offset
= state
->if_depth
% CHAR_BIT
;
4816 return !!(state
->if_bytes
[index
] & (1 << (offset
)));
4818 static void set_if_value(struct compile_state
*state
, int value
)
4821 index
= state
->if_depth
/ CHAR_BIT
;
4822 offset
= state
->if_depth
% CHAR_BIT
;
4824 state
->if_bytes
[index
] &= ~(1 << offset
);
4826 state
->if_bytes
[index
] |= (1 << offset
);
4829 static void in_if(struct compile_state
*state
, const char *name
)
4831 if (state
->if_depth
<= 0) {
4832 error(state
, 0, "%s without #if", name
);
4835 static void enter_if(struct compile_state
*state
)
4837 state
->if_depth
+= 1;
4838 if (state
->if_depth
> MAX_PP_IF_DEPTH
) {
4839 error(state
, 0, "#if depth too great");
4842 static void reenter_if(struct compile_state
*state
, const char *name
)
4845 if ((state
->eat_depth
== state
->if_depth
) &&
4846 (state
->eat_targ
== TOK_MELSE
)) {
4847 state
->eat_depth
= 0;
4848 state
->eat_targ
= 0;
4851 static void enter_else(struct compile_state
*state
, const char *name
)
4854 if ((state
->eat_depth
== state
->if_depth
) &&
4855 (state
->eat_targ
== TOK_MELSE
)) {
4856 state
->eat_depth
= 0;
4857 state
->eat_targ
= 0;
4860 static void exit_if(struct compile_state
*state
, const char *name
)
4863 if (state
->eat_depth
== state
->if_depth
) {
4864 state
->eat_depth
= 0;
4865 state
->eat_targ
= 0;
4867 state
->if_depth
-= 1;
4870 static void raw_token(struct compile_state
*state
, struct token
*tk
)
4872 struct file_state
*file
;
4876 raw_next_token(state
, file
, tk
);
4880 /* Exit out of an include directive or macro call */
4881 if ((tk
->tok
== TOK_EOF
) &&
4882 (file
!= state
->macro_file
) && file
->prev
)
4884 state
->file
= file
->prev
;
4885 /* file->basename is used keep it */
4886 xfree(file
->dirname
);
4890 raw_next_token(state
, state
->file
, tk
);
4896 static void pp_token(struct compile_state
*state
, struct token
*tk
)
4900 raw_token(state
, tk
);
4903 if (tk
->tok
== TOK_SPACE
) {
4904 raw_token(state
, tk
);
4907 else if (tk
->tok
== TOK_IDENT
) {
4908 if (state
->token_base
== 0) {
4909 ident_to_keyword(state
, tk
);
4911 ident_to_macro(state
, tk
);
4917 static void preprocess(struct compile_state
*state
, struct token
*tk
);
4919 static void token(struct compile_state
*state
, struct token
*tk
)
4922 pp_token(state
, tk
);
4925 /* Process a macro directive */
4926 if (tk
->tok
== TOK_MACRO
) {
4927 /* Only match preprocessor directives at the start of a line */
4929 ptr
= state
->file
->line_start
;
4930 while((ptr
< tk
->pos
)
4931 && spacep(get_char(state
->file
, ptr
)))
4933 ptr
= next_char(state
->file
, ptr
, 1);
4935 if (ptr
== tk
->pos
) {
4936 preprocess(state
, tk
);
4940 /* Expand a macro call */
4941 else if (tk
->ident
&& tk
->ident
->sym_define
) {
4942 rescan
= compile_macro(state
, &state
->file
, tk
);
4944 pp_token(state
, tk
);
4947 /* Eat tokens disabled by the preprocessor
4948 * (Unless we are parsing a preprocessor directive
4950 else if (if_eat(state
) && (state
->token_base
== 0)) {
4951 pp_token(state
, tk
);
4954 /* Make certain EOL only shows up in preprocessor directives */
4955 else if ((tk
->tok
== TOK_EOL
) && (state
->token_base
== 0)) {
4956 pp_token(state
, tk
);
4959 /* Error on unknown tokens */
4960 else if (tk
->tok
== TOK_UNKNOWN
) {
4961 error(state
, 0, "unknown token");
4967 static inline struct token
*get_token(struct compile_state
*state
, int offset
)
4970 index
= state
->token_base
+ offset
;
4971 if (index
>= sizeof(state
->token
)/sizeof(state
->token
[0])) {
4972 internal_error(state
, 0, "token array to small");
4974 return &state
->token
[index
];
4977 static struct token
*do_eat_token(struct compile_state
*state
, int tok
)
4981 check_tok(state
, get_token(state
, 1), tok
);
4983 /* Free the old token value */
4984 tk
= get_token(state
, 0);
4986 memset((void *)tk
->val
.str
, -1, tk
->str_len
);
4989 /* Overwrite the old token with newer tokens */
4990 for(i
= state
->token_base
; i
< sizeof(state
->token
)/sizeof(state
->token
[0]) - 1; i
++) {
4991 state
->token
[i
] = state
->token
[i
+ 1];
4993 /* Clear the last token */
4994 memset(&state
->token
[i
], 0, sizeof(state
->token
[i
]));
4995 state
->token
[i
].tok
= -1;
4997 /* Return the token */
5001 static int raw_peek(struct compile_state
*state
)
5004 tk1
= get_token(state
, 1);
5005 if (tk1
->tok
== -1) {
5006 raw_token(state
, tk1
);
5011 static struct token
*raw_eat(struct compile_state
*state
, int tok
)
5014 return do_eat_token(state
, tok
);
5017 static int pp_peek(struct compile_state
*state
)
5020 tk1
= get_token(state
, 1);
5021 if (tk1
->tok
== -1) {
5022 pp_token(state
, tk1
);
5027 static struct token
*pp_eat(struct compile_state
*state
, int tok
)
5030 return do_eat_token(state
, tok
);
5033 static int peek(struct compile_state
*state
)
5036 tk1
= get_token(state
, 1);
5037 if (tk1
->tok
== -1) {
5043 static int peek2(struct compile_state
*state
)
5045 struct token
*tk1
, *tk2
;
5046 tk1
= get_token(state
, 1);
5047 tk2
= get_token(state
, 2);
5048 if (tk1
->tok
== -1) {
5051 if (tk2
->tok
== -1) {
5057 static struct token
*eat(struct compile_state
*state
, int tok
)
5060 return do_eat_token(state
, tok
);
5063 static void compile_file(struct compile_state
*state
, const char *filename
, int local
)
5065 char cwd
[MAX_CWD_SIZE
];
5066 const char *subdir
, *base
;
5068 struct file_state
*file
;
5070 file
= xmalloc(sizeof(*file
), "file_state");
5072 base
= strrchr(filename
, '/');
5075 subdir_len
= base
- filename
;
5082 basename
= xmalloc(strlen(base
) +1, "basename");
5083 strcpy(basename
, base
);
5084 file
->basename
= basename
;
5086 if (getcwd(cwd
, sizeof(cwd
)) == 0) {
5087 die("cwd buffer to small");
5089 if ((subdir
[0] == '/') || ((subdir
[1] == ':') && ((subdir
[2] == '/') || (subdir
[2] == '\\')))) {
5090 file
->dirname
= xmalloc(subdir_len
+ 1, "dirname");
5091 memcpy(file
->dirname
, subdir
, subdir_len
);
5092 file
->dirname
[subdir_len
] = '\0';
5098 /* Find the appropriate directory... */
5100 if (!state
->file
&& exists(cwd
, filename
)) {
5103 if (local
&& state
->file
&& exists(state
->file
->dirname
, filename
)) {
5104 dir
= state
->file
->dirname
;
5106 for(path
= state
->compiler
->include_paths
; !dir
&& *path
; path
++) {
5107 if (exists(*path
, filename
)) {
5112 error(state
, 0, "Cannot open `%s'\n", filename
);
5114 dirlen
= strlen(dir
);
5115 file
->dirname
= xmalloc(dirlen
+ 1 + subdir_len
+ 1, "dirname");
5116 memcpy(file
->dirname
, dir
, dirlen
);
5117 file
->dirname
[dirlen
] = '/';
5118 memcpy(file
->dirname
+ dirlen
+ 1, subdir
, subdir_len
);
5119 file
->dirname
[dirlen
+ 1 + subdir_len
] = '\0';
5121 file
->buf
= slurp_file(file
->dirname
, file
->basename
, &file
->size
);
5123 file
->pos
= file
->buf
;
5124 file
->line_start
= file
->pos
;
5127 file
->report_line
= 1;
5128 file
->report_name
= file
->basename
;
5129 file
->report_dir
= file
->dirname
;
5131 file
->trigraphs
= (state
->compiler
->flags
& COMPILER_TRIGRAPHS
)? 1: 0;
5132 file
->join_lines
= 1;
5134 file
->prev
= state
->file
;
5138 static struct triple
*constant_expr(struct compile_state
*state
);
5139 static void integral(struct compile_state
*state
, struct triple
*def
);
5141 static int mcexpr(struct compile_state
*state
)
5143 struct triple
*cvalue
;
5144 cvalue
= constant_expr(state
);
5145 integral(state
, cvalue
);
5146 if (cvalue
->op
!= OP_INTCONST
) {
5147 error(state
, 0, "integer constant expected");
5149 return cvalue
->u
.cval
!= 0;
5152 static void preprocess(struct compile_state
*state
, struct token
*current_token
)
5154 /* Doing much more with the preprocessor would require
5155 * a parser and a major restructuring.
5156 * Postpone that for later.
5161 state
->macro_file
= state
->file
;
5163 old_token_base
= state
->token_base
;
5164 state
->token_base
= current_token
- state
->token
;
5166 tok
= pp_peek(state
);
5172 tk
= pp_eat(state
, TOK_LIT_INT
);
5173 override_line
= strtoul(tk
->val
.str
, 0, 10);
5174 /* I have a preprocessor line marker parse it */
5175 if (pp_peek(state
) == TOK_LIT_STRING
) {
5176 const char *token
, *base
;
5178 int name_len
, dir_len
;
5179 tk
= pp_eat(state
, TOK_LIT_STRING
);
5180 name
= xmalloc(tk
->str_len
, "report_name");
5181 token
= tk
->val
.str
+ 1;
5182 base
= strrchr(token
, '/');
5183 name_len
= tk
->str_len
-2;
5185 dir_len
= base
- token
;
5187 name_len
-= base
- token
;
5192 memcpy(name
, base
, name_len
);
5193 name
[name_len
] = '\0';
5194 dir
= xmalloc(dir_len
+ 1, "report_dir");
5195 memcpy(dir
, token
, dir_len
);
5196 dir
[dir_len
] = '\0';
5197 state
->file
->report_line
= override_line
- 1;
5198 state
->file
->report_name
= name
;
5199 state
->file
->report_dir
= dir
;
5200 state
->file
->macro
= 0;
5207 pp_eat(state
, TOK_MLINE
);
5208 tk
= eat(state
, TOK_LIT_INT
);
5209 state
->file
->report_line
= strtoul(tk
->val
.str
, 0, 10) -1;
5210 if (pp_peek(state
) == TOK_LIT_STRING
) {
5211 const char *token
, *base
;
5213 int name_len
, dir_len
;
5214 tk
= pp_eat(state
, TOK_LIT_STRING
);
5215 name
= xmalloc(tk
->str_len
, "report_name");
5216 token
= tk
->val
.str
+ 1;
5217 base
= strrchr(token
, '/');
5218 name_len
= tk
->str_len
- 2;
5220 dir_len
= base
- token
;
5222 name_len
-= base
- token
;
5227 memcpy(name
, base
, name_len
);
5228 name
[name_len
] = '\0';
5229 dir
= xmalloc(dir_len
+ 1, "report_dir");
5230 memcpy(dir
, token
, dir_len
);
5231 dir
[dir_len
] = '\0';
5232 state
->file
->report_name
= name
;
5233 state
->file
->report_dir
= dir
;
5234 state
->file
->macro
= 0;
5240 struct hash_entry
*ident
;
5241 pp_eat(state
, TOK_MUNDEF
);
5242 if (if_eat(state
)) /* quit early when #if'd out */
5245 ident
= pp_eat(state
, TOK_MIDENT
)->ident
;
5247 undef_macro(state
, ident
);
5251 pp_eat(state
, TOK_MPRAGMA
);
5252 if (if_eat(state
)) /* quit early when #if'd out */
5254 warning(state
, 0, "Ignoring pragma");
5257 pp_eat(state
, TOK_MELIF
);
5258 reenter_if(state
, "#elif");
5259 if (if_eat(state
)) /* quit early when #if'd out */
5261 /* If the #if was taken the #elif just disables the following code */
5262 if (if_value(state
)) {
5263 eat_tokens(state
, TOK_MENDIF
);
5265 /* If the previous #if was not taken see if the #elif enables the
5269 set_if_value(state
, mcexpr(state
));
5270 if (!if_value(state
)) {
5271 eat_tokens(state
, TOK_MELSE
);
5276 pp_eat(state
, TOK_MIF
);
5278 if (if_eat(state
)) /* quit early when #if'd out */
5280 set_if_value(state
, mcexpr(state
));
5281 if (!if_value(state
)) {
5282 eat_tokens(state
, TOK_MELSE
);
5287 struct hash_entry
*ident
;
5289 pp_eat(state
, TOK_MIFNDEF
);
5291 if (if_eat(state
)) /* quit early when #if'd out */
5293 ident
= pp_eat(state
, TOK_MIDENT
)->ident
;
5294 set_if_value(state
, ident
->sym_define
== 0);
5295 if (!if_value(state
)) {
5296 eat_tokens(state
, TOK_MELSE
);
5302 struct hash_entry
*ident
;
5303 pp_eat(state
, TOK_MIFDEF
);
5305 if (if_eat(state
)) /* quit early when #if'd out */
5307 ident
= pp_eat(state
, TOK_MIDENT
)->ident
;
5308 set_if_value(state
, ident
->sym_define
!= 0);
5309 if (!if_value(state
)) {
5310 eat_tokens(state
, TOK_MELSE
);
5315 pp_eat(state
, TOK_MELSE
);
5316 enter_else(state
, "#else");
5317 if (!if_eat(state
) && if_value(state
)) {
5318 eat_tokens(state
, TOK_MENDIF
);
5322 pp_eat(state
, TOK_MENDIF
);
5323 exit_if(state
, "#endif");
5327 struct hash_entry
*ident
;
5328 struct macro_arg
*args
, **larg
;
5329 const char *mstart
, *mend
;
5332 pp_eat(state
, TOK_MDEFINE
);
5333 if (if_eat(state
)) /* quit early when #if'd out */
5335 ident
= pp_eat(state
, TOK_MIDENT
)->ident
;
5340 /* Parse macro parameters */
5341 if (raw_peek(state
) == TOK_LPAREN
) {
5342 raw_eat(state
, TOK_LPAREN
);
5346 struct macro_arg
*narg
, *arg
;
5347 struct hash_entry
*aident
;
5350 tok
= pp_peek(state
);
5351 if (!args
&& (tok
== TOK_RPAREN
)) {
5354 else if (tok
== TOK_DOTS
) {
5355 pp_eat(state
, TOK_DOTS
);
5356 aident
= state
->i___VA_ARGS__
;
5359 aident
= pp_eat(state
, TOK_MIDENT
)->ident
;
5362 narg
= xcmalloc(sizeof(*arg
), "macro arg");
5363 narg
->ident
= aident
;
5365 /* Verify I don't have a duplicate identifier */
5366 for(arg
= args
; arg
; arg
= arg
->next
) {
5367 if (arg
->ident
== narg
->ident
) {
5368 error(state
, 0, "Duplicate macro arg `%s'",
5372 /* Add the new argument to the end of the list */
5377 if ((aident
== state
->i___VA_ARGS__
) ||
5378 (pp_peek(state
) != TOK_COMMA
)) {
5381 pp_eat(state
, TOK_COMMA
);
5383 pp_eat(state
, TOK_RPAREN
);
5385 /* Remove leading whitespace */
5386 while(raw_peek(state
) == TOK_SPACE
) {
5387 raw_eat(state
, TOK_SPACE
);
5390 /* Remember the start of the macro body */
5391 tok
= raw_peek(state
);
5392 mend
= mstart
= get_token(state
, 1)->pos
;
5394 /* Find the end of the macro */
5395 for(tok
= raw_peek(state
); tok
!= TOK_EOL
; tok
= raw_peek(state
)) {
5396 raw_eat(state
, tok
);
5397 /* Remember the end of the last non space token */
5399 if (tok
!= TOK_SPACE
) {
5400 mend
= get_token(state
, 1)->pos
;
5404 /* Now that I have found the body defined the token */
5405 do_define_macro(state
, ident
,
5406 char_strdup(state
->file
, mstart
, mend
, "macro buf"),
5412 const char *start
, *end
;
5415 pp_eat(state
, TOK_MERROR
);
5416 /* Find the start of the line */
5418 start
= get_token(state
, 1)->pos
;
5420 /* Find the end of the line */
5421 while((tok
= raw_peek(state
)) != TOK_EOL
) {
5422 raw_eat(state
, tok
);
5424 end
= get_token(state
, 1)->pos
;
5426 if (!if_eat(state
)) {
5427 error(state
, 0, "%*.*s", len
, len
, start
);
5433 const char *start
, *end
;
5436 pp_eat(state
, TOK_MWARNING
);
5438 /* Find the start of the line */
5440 start
= get_token(state
, 1)->pos
;
5442 /* Find the end of the line */
5443 while((tok
= raw_peek(state
)) != TOK_EOL
) {
5444 raw_eat(state
, tok
);
5446 end
= get_token(state
, 1)->pos
;
5448 if (!if_eat(state
)) {
5449 warning(state
, 0, "%*.*s", len
, len
, start
);
5460 pp_eat(state
, TOK_MINCLUDE
);
5461 if (if_eat(state
)) {
5462 /* Find the end of the line */
5463 while((tok
= raw_peek(state
)) != TOK_EOL
) {
5464 raw_eat(state
, tok
);
5469 if (tok
== TOK_LIT_STRING
) {
5473 tk
= eat(state
, TOK_LIT_STRING
);
5474 name
= xmalloc(tk
->str_len
, "include");
5475 token
= tk
->val
.str
+1;
5476 name_len
= tk
->str_len
-2;
5477 if (*token
== '"') {
5481 memcpy(name
, token
, name_len
);
5482 name
[name_len
] = '\0';
5485 else if (tok
== TOK_LESS
) {
5486 struct macro_buf buf
;
5487 eat(state
, TOK_LESS
);
5490 buf
.str
= xmalloc(buf
.len
, "include");
5494 while((tok
!= TOK_MORE
) &&
5495 (tok
!= TOK_EOL
) && (tok
!= TOK_EOF
))
5498 tk
= eat(state
, tok
);
5499 append_macro_chars(state
, "include", &buf
,
5500 state
->file
, tk
->pos
, state
->file
->pos
);
5503 append_macro_text(state
, "include", &buf
, "\0", 1);
5504 if (peek(state
) != TOK_MORE
) {
5505 error(state
, 0, "Unterminated include directive");
5507 eat(state
, TOK_MORE
);
5512 error(state
, 0, "Invalid include directive");
5514 /* Error if there are any tokens after the include */
5515 if (pp_peek(state
) != TOK_EOL
) {
5516 error(state
, 0, "garbage after include directive");
5518 if (!if_eat(state
)) {
5519 compile_file(state
, name
, local
);
5525 /* Ignore # without a follwing ident */
5529 const char *name1
, *name2
;
5530 name1
= tokens
[tok
];
5532 if (tok
== TOK_MIDENT
) {
5533 name2
= get_token(state
, 1)->ident
->name
;
5535 error(state
, 0, "Invalid preprocessor directive: %s %s",
5540 /* Consume the rest of the macro line */
5542 tok
= pp_peek(state
);
5544 } while((tok
!= TOK_EOF
) && (tok
!= TOK_EOL
));
5545 state
->token_base
= old_token_base
;
5546 state
->macro_file
= NULL
;
5550 /* Type helper functions */
5552 static struct type
*new_type(
5553 unsigned int type
, struct type
*left
, struct type
*right
)
5555 struct type
*result
;
5556 result
= xmalloc(sizeof(*result
), "type");
5557 result
->type
= type
;
5558 result
->left
= left
;
5559 result
->right
= right
;
5560 result
->field_ident
= 0;
5561 result
->type_ident
= 0;
5562 result
->elements
= 0;
5566 static struct type
*clone_type(unsigned int specifiers
, struct type
*old
)
5568 struct type
*result
;
5569 result
= xmalloc(sizeof(*result
), "type");
5570 memcpy(result
, old
, sizeof(*result
));
5571 result
->type
&= TYPE_MASK
;
5572 result
->type
|= specifiers
;
5576 static struct type
*dup_type(struct compile_state
*state
, struct type
*orig
)
5579 new = xcmalloc(sizeof(*new), "type");
5580 new->type
= orig
->type
;
5581 new->field_ident
= orig
->field_ident
;
5582 new->type_ident
= orig
->type_ident
;
5583 new->elements
= orig
->elements
;
5585 new->left
= dup_type(state
, orig
->left
);
5588 new->right
= dup_type(state
, orig
->right
);
5594 static struct type
*invalid_type(struct compile_state
*state
, struct type
*type
)
5596 struct type
*invalid
, *member
;
5599 internal_error(state
, 0, "type missing?");
5601 switch(type
->type
& TYPE_MASK
) {
5603 case TYPE_CHAR
: case TYPE_UCHAR
:
5604 case TYPE_SHORT
: case TYPE_USHORT
:
5605 case TYPE_INT
: case TYPE_UINT
:
5606 case TYPE_LONG
: case TYPE_ULONG
:
5607 case TYPE_LLONG
: case TYPE_ULLONG
:
5612 invalid
= invalid_type(state
, type
->left
);
5615 invalid
= invalid_type(state
, type
->left
);
5619 member
= type
->left
;
5620 while(member
&& (invalid
== 0) &&
5621 ((member
->type
& TYPE_MASK
) == TYPE_PRODUCT
)) {
5622 invalid
= invalid_type(state
, member
->left
);
5623 member
= member
->right
;
5626 invalid
= invalid_type(state
, member
);
5631 member
= type
->left
;
5632 while(member
&& (invalid
== 0) &&
5633 ((member
->type
& TYPE_MASK
) == TYPE_OVERLAP
)) {
5634 invalid
= invalid_type(state
, member
->left
);
5635 member
= member
->right
;
5638 invalid
= invalid_type(state
, member
);
5649 static struct type void_type
= { .type
= TYPE_VOID
};
5650 static struct type char_type
= { .type
= TYPE_CHAR
};
5651 static struct type uchar_type
= { .type
= TYPE_UCHAR
};
5652 #if DEBUG_ROMCC_WARNING
5653 static struct type short_type
= { .type
= TYPE_SHORT
};
5655 static struct type ushort_type
= { .type
= TYPE_USHORT
};
5656 static struct type int_type
= { .type
= TYPE_INT
};
5657 static struct type uint_type
= { .type
= TYPE_UINT
};
5658 static struct type long_type
= { .type
= TYPE_LONG
};
5659 static struct type ulong_type
= { .type
= TYPE_ULONG
};
5660 static struct type unknown_type
= { .type
= TYPE_UNKNOWN
};
5662 static struct type void_ptr_type
= {
5663 .type
= TYPE_POINTER
,
5667 #if DEBUG_ROMCC_WARNING
5668 static struct type void_func_type
= {
5669 .type
= TYPE_FUNCTION
,
5671 .right
= &void_type
,
5675 static size_t bits_to_bytes(size_t size
)
5677 return (size
+ SIZEOF_CHAR
- 1)/SIZEOF_CHAR
;
5680 static struct triple
*variable(struct compile_state
*state
, struct type
*type
)
5682 struct triple
*result
;
5683 if ((type
->type
& STOR_MASK
) != STOR_PERM
) {
5684 result
= triple(state
, OP_ADECL
, type
, 0, 0);
5685 generate_lhs_pieces(state
, result
);
5688 result
= triple(state
, OP_SDECL
, type
, 0, 0);
5693 static void stor_of(FILE *fp
, struct type
*type
)
5695 switch(type
->type
& STOR_MASK
) {
5697 fprintf(fp
, "auto ");
5700 fprintf(fp
, "static ");
5703 fprintf(fp
, "local ");
5706 fprintf(fp
, "extern ");
5709 fprintf(fp
, "register ");
5712 fprintf(fp
, "typedef ");
5714 case STOR_INLINE
| STOR_LOCAL
:
5715 fprintf(fp
, "inline ");
5717 case STOR_INLINE
| STOR_STATIC
:
5718 fprintf(fp
, "static inline");
5720 case STOR_INLINE
| STOR_EXTERN
:
5721 fprintf(fp
, "extern inline");
5724 fprintf(fp
, "stor:%x", type
->type
& STOR_MASK
);
5728 static void qual_of(FILE *fp
, struct type
*type
)
5730 if (type
->type
& QUAL_CONST
) {
5731 fprintf(fp
, " const");
5733 if (type
->type
& QUAL_VOLATILE
) {
5734 fprintf(fp
, " volatile");
5736 if (type
->type
& QUAL_RESTRICT
) {
5737 fprintf(fp
, " restrict");
5741 static void name_of(FILE *fp
, struct type
*type
)
5743 unsigned int base_type
;
5744 base_type
= type
->type
& TYPE_MASK
;
5745 if ((base_type
!= TYPE_PRODUCT
) && (base_type
!= TYPE_OVERLAP
)) {
5750 fprintf(fp
, "void");
5754 fprintf(fp
, "signed char");
5758 fprintf(fp
, "unsigned char");
5762 fprintf(fp
, "signed short");
5766 fprintf(fp
, "unsigned short");
5770 fprintf(fp
, "signed int");
5774 fprintf(fp
, "unsigned int");
5778 fprintf(fp
, "signed long");
5782 fprintf(fp
, "unsigned long");
5786 name_of(fp
, type
->left
);
5791 name_of(fp
, type
->left
);
5793 name_of(fp
, type
->right
);
5796 name_of(fp
, type
->left
);
5798 name_of(fp
, type
->right
);
5801 fprintf(fp
, "enum %s",
5802 (type
->type_ident
)? type
->type_ident
->name
: "");
5806 fprintf(fp
, "struct %s { ",
5807 (type
->type_ident
)? type
->type_ident
->name
: "");
5808 name_of(fp
, type
->left
);
5813 fprintf(fp
, "union %s { ",
5814 (type
->type_ident
)? type
->type_ident
->name
: "");
5815 name_of(fp
, type
->left
);
5820 name_of(fp
, type
->left
);
5821 fprintf(fp
, " (*)(");
5822 name_of(fp
, type
->right
);
5826 name_of(fp
, type
->left
);
5827 fprintf(fp
, " [%ld]", (long)(type
->elements
));
5830 fprintf(fp
, "tuple { ");
5831 name_of(fp
, type
->left
);
5836 fprintf(fp
, "join { ");
5837 name_of(fp
, type
->left
);
5842 name_of(fp
, type
->left
);
5843 fprintf(fp
, " : %d ", type
->elements
);
5847 fprintf(fp
, "unknown_t");
5850 fprintf(fp
, "????: %x", base_type
);
5853 if (type
->field_ident
&& type
->field_ident
->name
) {
5854 fprintf(fp
, " .%s", type
->field_ident
->name
);
5858 static size_t align_of(struct compile_state
*state
, struct type
*type
)
5862 switch(type
->type
& TYPE_MASK
) {
5871 align
= ALIGNOF_CHAR
;
5875 align
= ALIGNOF_SHORT
;
5880 align
= ALIGNOF_INT
;
5884 align
= ALIGNOF_LONG
;
5887 align
= ALIGNOF_POINTER
;
5892 size_t left_align
, right_align
;
5893 left_align
= align_of(state
, type
->left
);
5894 right_align
= align_of(state
, type
->right
);
5895 align
= (left_align
>= right_align
) ? left_align
: right_align
;
5899 align
= align_of(state
, type
->left
);
5905 align
= align_of(state
, type
->left
);
5908 error(state
, 0, "alignof not yet defined for type\n");
5914 static size_t reg_align_of(struct compile_state
*state
, struct type
*type
)
5918 switch(type
->type
& TYPE_MASK
) {
5927 align
= REG_ALIGNOF_CHAR
;
5931 align
= REG_ALIGNOF_SHORT
;
5936 align
= REG_ALIGNOF_INT
;
5940 align
= REG_ALIGNOF_LONG
;
5943 align
= REG_ALIGNOF_POINTER
;
5948 size_t left_align
, right_align
;
5949 left_align
= reg_align_of(state
, type
->left
);
5950 right_align
= reg_align_of(state
, type
->right
);
5951 align
= (left_align
>= right_align
) ? left_align
: right_align
;
5955 align
= reg_align_of(state
, type
->left
);
5961 align
= reg_align_of(state
, type
->left
);
5964 error(state
, 0, "alignof not yet defined for type\n");
5970 static size_t align_of_in_bytes(struct compile_state
*state
, struct type
*type
)
5972 return bits_to_bytes(align_of(state
, type
));
5974 static size_t size_of(struct compile_state
*state
, struct type
*type
);
5975 static size_t reg_size_of(struct compile_state
*state
, struct type
*type
);
5977 static size_t needed_padding(struct compile_state
*state
,
5978 struct type
*type
, size_t offset
)
5980 size_t padding
, align
;
5981 align
= align_of(state
, type
);
5982 /* Align to the next machine word if the bitfield does completely
5983 * fit into the current word.
5985 if ((type
->type
& TYPE_MASK
) == TYPE_BITFIELD
) {
5987 size
= size_of(state
, type
);
5988 if ((offset
+ type
->elements
)/size
!= offset
/size
) {
5993 if (offset
% align
) {
5994 padding
= align
- (offset
% align
);
5999 static size_t reg_needed_padding(struct compile_state
*state
,
6000 struct type
*type
, size_t offset
)
6002 size_t padding
, align
;
6003 align
= reg_align_of(state
, type
);
6004 /* Align to the next register word if the bitfield does completely
6005 * fit into the current register.
6007 if (((type
->type
& TYPE_MASK
) == TYPE_BITFIELD
) &&
6008 (((offset
+ type
->elements
)/REG_SIZEOF_REG
) != (offset
/REG_SIZEOF_REG
)))
6010 align
= REG_SIZEOF_REG
;
6013 if (offset
% align
) {
6014 padding
= align
- (offset
% align
);
6019 static size_t size_of(struct compile_state
*state
, struct type
*type
)
6023 switch(type
->type
& TYPE_MASK
) {
6028 size
= type
->elements
;
6036 size
= SIZEOF_SHORT
;
6048 size
= SIZEOF_POINTER
;
6054 while((type
->type
& TYPE_MASK
) == TYPE_PRODUCT
) {
6055 pad
= needed_padding(state
, type
->left
, size
);
6056 size
= size
+ pad
+ size_of(state
, type
->left
);
6059 pad
= needed_padding(state
, type
, size
);
6060 size
= size
+ pad
+ size_of(state
, type
);
6065 size_t size_left
, size_right
;
6066 size_left
= size_of(state
, type
->left
);
6067 size_right
= size_of(state
, type
->right
);
6068 size
= (size_left
>= size_right
)? size_left
: size_right
;
6072 if (type
->elements
== ELEMENT_COUNT_UNSPECIFIED
) {
6073 internal_error(state
, 0, "Invalid array type");
6075 size
= size_of(state
, type
->left
) * type
->elements
;
6082 size
= size_of(state
, type
->left
);
6083 /* Pad structures so their size is a multiples of their alignment */
6084 pad
= needed_padding(state
, type
, size
);
6092 size
= size_of(state
, type
->left
);
6093 /* Pad unions so their size is a multiple of their alignment */
6094 pad
= needed_padding(state
, type
, size
);
6099 internal_error(state
, 0, "sizeof not yet defined for type");
6105 static size_t reg_size_of(struct compile_state
*state
, struct type
*type
)
6109 switch(type
->type
& TYPE_MASK
) {
6114 size
= type
->elements
;
6118 size
= REG_SIZEOF_CHAR
;
6122 size
= REG_SIZEOF_SHORT
;
6127 size
= REG_SIZEOF_INT
;
6131 size
= REG_SIZEOF_LONG
;
6134 size
= REG_SIZEOF_POINTER
;
6140 while((type
->type
& TYPE_MASK
) == TYPE_PRODUCT
) {
6141 pad
= reg_needed_padding(state
, type
->left
, size
);
6142 size
= size
+ pad
+ reg_size_of(state
, type
->left
);
6145 pad
= reg_needed_padding(state
, type
, size
);
6146 size
= size
+ pad
+ reg_size_of(state
, type
);
6151 size_t size_left
, size_right
;
6152 size_left
= reg_size_of(state
, type
->left
);
6153 size_right
= reg_size_of(state
, type
->right
);
6154 size
= (size_left
>= size_right
)? size_left
: size_right
;
6158 if (type
->elements
== ELEMENT_COUNT_UNSPECIFIED
) {
6159 internal_error(state
, 0, "Invalid array type");
6161 size
= reg_size_of(state
, type
->left
) * type
->elements
;
6168 size
= reg_size_of(state
, type
->left
);
6169 /* Pad structures so their size is a multiples of their alignment */
6170 pad
= reg_needed_padding(state
, type
, size
);
6178 size
= reg_size_of(state
, type
->left
);
6179 /* Pad unions so their size is a multiple of their alignment */
6180 pad
= reg_needed_padding(state
, type
, size
);
6185 internal_error(state
, 0, "sizeof not yet defined for type");
6191 static size_t registers_of(struct compile_state
*state
, struct type
*type
)
6194 registers
= reg_size_of(state
, type
);
6195 registers
+= REG_SIZEOF_REG
- 1;
6196 registers
/= REG_SIZEOF_REG
;
6200 static size_t size_of_in_bytes(struct compile_state
*state
, struct type
*type
)
6202 return bits_to_bytes(size_of(state
, type
));
6205 static size_t field_offset(struct compile_state
*state
,
6206 struct type
*type
, struct hash_entry
*field
)
6208 struct type
*member
;
6213 if ((type
->type
& TYPE_MASK
) == TYPE_STRUCT
) {
6214 member
= type
->left
;
6215 while(member
&& ((member
->type
& TYPE_MASK
) == TYPE_PRODUCT
)) {
6216 size
+= needed_padding(state
, member
->left
, size
);
6217 if (member
->left
->field_ident
== field
) {
6218 member
= member
->left
;
6221 size
+= size_of(state
, member
->left
);
6222 member
= member
->right
;
6224 size
+= needed_padding(state
, member
, size
);
6226 else if ((type
->type
& TYPE_MASK
) == TYPE_UNION
) {
6227 member
= type
->left
;
6228 while(member
&& ((member
->type
& TYPE_MASK
) == TYPE_OVERLAP
)) {
6229 if (member
->left
->field_ident
== field
) {
6230 member
= member
->left
;
6233 member
= member
->right
;
6237 internal_error(state
, 0, "field_offset only works on structures and unions");
6240 if (!member
|| (member
->field_ident
!= field
)) {
6241 error(state
, 0, "member %s not present", field
->name
);
6246 static size_t field_reg_offset(struct compile_state
*state
,
6247 struct type
*type
, struct hash_entry
*field
)
6249 struct type
*member
;
6254 if ((type
->type
& TYPE_MASK
) == TYPE_STRUCT
) {
6255 member
= type
->left
;
6256 while(member
&& ((member
->type
& TYPE_MASK
) == TYPE_PRODUCT
)) {
6257 size
+= reg_needed_padding(state
, member
->left
, size
);
6258 if (member
->left
->field_ident
== field
) {
6259 member
= member
->left
;
6262 size
+= reg_size_of(state
, member
->left
);
6263 member
= member
->right
;
6266 else if ((type
->type
& TYPE_MASK
) == TYPE_UNION
) {
6267 member
= type
->left
;
6268 while(member
&& ((member
->type
& TYPE_MASK
) == TYPE_OVERLAP
)) {
6269 if (member
->left
->field_ident
== field
) {
6270 member
= member
->left
;
6273 member
= member
->right
;
6277 internal_error(state
, 0, "field_reg_offset only works on structures and unions");
6280 size
+= reg_needed_padding(state
, member
, size
);
6281 if (!member
|| (member
->field_ident
!= field
)) {
6282 error(state
, 0, "member %s not present", field
->name
);
6287 static struct type
*field_type(struct compile_state
*state
,
6288 struct type
*type
, struct hash_entry
*field
)
6290 struct type
*member
;
6293 if ((type
->type
& TYPE_MASK
) == TYPE_STRUCT
) {
6294 member
= type
->left
;
6295 while(member
&& ((member
->type
& TYPE_MASK
) == TYPE_PRODUCT
)) {
6296 if (member
->left
->field_ident
== field
) {
6297 member
= member
->left
;
6300 member
= member
->right
;
6303 else if ((type
->type
& TYPE_MASK
) == TYPE_UNION
) {
6304 member
= type
->left
;
6305 while(member
&& ((member
->type
& TYPE_MASK
) == TYPE_OVERLAP
)) {
6306 if (member
->left
->field_ident
== field
) {
6307 member
= member
->left
;
6310 member
= member
->right
;
6314 internal_error(state
, 0, "field_type only works on structures and unions");
6317 if (!member
|| (member
->field_ident
!= field
)) {
6318 error(state
, 0, "member %s not present", field
->name
);
6323 static size_t index_offset(struct compile_state
*state
,
6324 struct type
*type
, ulong_t index
)
6326 struct type
*member
;
6329 if ((type
->type
& TYPE_MASK
) == TYPE_ARRAY
) {
6330 size
= size_of(state
, type
->left
) * index
;
6332 else if ((type
->type
& TYPE_MASK
) == TYPE_TUPLE
) {
6334 member
= type
->left
;
6336 while(member
&& ((member
->type
& TYPE_MASK
) == TYPE_PRODUCT
)) {
6337 size
+= needed_padding(state
, member
->left
, size
);
6339 member
= member
->left
;
6342 size
+= size_of(state
, member
->left
);
6344 member
= member
->right
;
6346 size
+= needed_padding(state
, member
, size
);
6348 internal_error(state
, 0, "Missing member index: %u", index
);
6351 else if ((type
->type
& TYPE_MASK
) == TYPE_JOIN
) {
6354 member
= type
->left
;
6356 while(member
&& ((member
->type
& TYPE_MASK
) == TYPE_OVERLAP
)) {
6358 member
= member
->left
;
6362 member
= member
->right
;
6365 internal_error(state
, 0, "Missing member index: %u", index
);
6369 internal_error(state
, 0,
6370 "request for index %u in something not an array, tuple or join",
6376 static size_t index_reg_offset(struct compile_state
*state
,
6377 struct type
*type
, ulong_t index
)
6379 struct type
*member
;
6382 if ((type
->type
& TYPE_MASK
) == TYPE_ARRAY
) {
6383 size
= reg_size_of(state
, type
->left
) * index
;
6385 else if ((type
->type
& TYPE_MASK
) == TYPE_TUPLE
) {
6387 member
= type
->left
;
6389 while(member
&& ((member
->type
& TYPE_MASK
) == TYPE_PRODUCT
)) {
6390 size
+= reg_needed_padding(state
, member
->left
, size
);
6392 member
= member
->left
;
6395 size
+= reg_size_of(state
, member
->left
);
6397 member
= member
->right
;
6399 size
+= reg_needed_padding(state
, member
, size
);
6401 internal_error(state
, 0, "Missing member index: %u", index
);
6405 else if ((type
->type
& TYPE_MASK
) == TYPE_JOIN
) {
6408 member
= type
->left
;
6410 while(member
&& ((member
->type
& TYPE_MASK
) == TYPE_OVERLAP
)) {
6412 member
= member
->left
;
6416 member
= member
->right
;
6419 internal_error(state
, 0, "Missing member index: %u", index
);
6423 internal_error(state
, 0,
6424 "request for index %u in something not an array, tuple or join",
6430 static struct type
*index_type(struct compile_state
*state
,
6431 struct type
*type
, ulong_t index
)
6433 struct type
*member
;
6434 if (index
>= type
->elements
) {
6435 internal_error(state
, 0, "Invalid element %u requested", index
);
6437 if ((type
->type
& TYPE_MASK
) == TYPE_ARRAY
) {
6438 member
= type
->left
;
6440 else if ((type
->type
& TYPE_MASK
) == TYPE_TUPLE
) {
6442 member
= type
->left
;
6444 while(member
&& ((member
->type
& TYPE_MASK
) == TYPE_PRODUCT
)) {
6446 member
= member
->left
;
6450 member
= member
->right
;
6453 internal_error(state
, 0, "Missing member index: %u", index
);
6456 else if ((type
->type
& TYPE_MASK
) == TYPE_JOIN
) {
6458 member
= type
->left
;
6460 while(member
&& ((member
->type
& TYPE_MASK
) == TYPE_OVERLAP
)) {
6462 member
= member
->left
;
6466 member
= member
->right
;
6469 internal_error(state
, 0, "Missing member index: %u", index
);
6474 internal_error(state
, 0,
6475 "request for index %u in something not an array, tuple or join",
6481 static struct type
*unpack_type(struct compile_state
*state
, struct type
*type
)
6483 /* If I have a single register compound type not a bit-field
6484 * find the real type.
6486 struct type
*start_type
;
6488 /* Get out early if I need multiple registers for this type */
6489 size
= reg_size_of(state
, type
);
6490 if (size
> REG_SIZEOF_REG
) {
6493 /* Get out early if I don't need any registers for this type */
6497 /* Loop until I have no more layers I can remove */
6500 switch(type
->type
& TYPE_MASK
) {
6502 /* If I have a single element the unpacked type
6505 if (type
->elements
== 1) {
6511 /* If I have a single element the unpacked type
6514 if (type
->elements
== 1) {
6517 /* If I have multiple elements the unpacked
6518 * type is the non-void element.
6521 struct type
*next
, *member
;
6522 struct type
*sub_type
;
6528 if ((member
->type
& TYPE_MASK
) == TYPE_PRODUCT
) {
6529 next
= member
->right
;
6530 member
= member
->left
;
6532 if (reg_size_of(state
, member
) > 0) {
6534 internal_error(state
, 0, "true compound type in a register");
6547 /* If I have a single element the unpacked type
6550 if (type
->elements
== 1) {
6553 /* I can't in general unpack union types */
6556 /* If I'm not a compound type I can't unpack it */
6559 } while(start_type
!= type
);
6560 switch(type
->type
& TYPE_MASK
) {
6564 internal_error(state
, 0, "irredicible type?");
6570 static int equiv_types(struct type
*left
, struct type
*right
);
6571 static int is_compound_type(struct type
*type
);
6573 static struct type
*reg_type(
6574 struct compile_state
*state
, struct type
*type
, int reg_offset
)
6576 struct type
*member
;
6579 struct type
*invalid
;
6580 invalid
= invalid_type(state
, type
);
6582 fprintf(state
->errout
, "type: ");
6583 name_of(state
->errout
, type
);
6584 fprintf(state
->errout
, "\n");
6585 fprintf(state
->errout
, "invalid: ");
6586 name_of(state
->errout
, invalid
);
6587 fprintf(state
->errout
, "\n");
6588 internal_error(state
, 0, "bad input type?");
6592 size
= reg_size_of(state
, type
);
6593 if (reg_offset
> size
) {
6595 fprintf(state
->errout
, "type: ");
6596 name_of(state
->errout
, type
);
6597 fprintf(state
->errout
, "\n");
6598 internal_error(state
, 0, "offset outside of type");
6601 switch(type
->type
& TYPE_MASK
) {
6602 /* Don't do anything with the basic types */
6604 case TYPE_CHAR
: case TYPE_UCHAR
:
6605 case TYPE_SHORT
: case TYPE_USHORT
:
6606 case TYPE_INT
: case TYPE_UINT
:
6607 case TYPE_LONG
: case TYPE_ULONG
:
6608 case TYPE_LLONG
: case TYPE_ULLONG
:
6609 case TYPE_FLOAT
: case TYPE_DOUBLE
:
6617 member
= type
->left
;
6618 size
= reg_size_of(state
, member
);
6619 if (size
> REG_SIZEOF_REG
) {
6620 member
= reg_type(state
, member
, reg_offset
% size
);
6628 member
= type
->left
;
6629 while(member
&& ((member
->type
& TYPE_MASK
) == TYPE_PRODUCT
)) {
6630 size
= reg_size_of(state
, member
->left
);
6631 offset
+= reg_needed_padding(state
, member
->left
, offset
);
6632 if ((offset
+ size
) > reg_offset
) {
6633 member
= member
->left
;
6637 member
= member
->right
;
6639 offset
+= reg_needed_padding(state
, member
, offset
);
6640 member
= reg_type(state
, member
, reg_offset
- offset
);
6646 struct type
*join
, **jnext
, *mnext
;
6647 join
= new_type(TYPE_JOIN
, 0, 0);
6648 jnext
= &join
->left
;
6654 if ((member
->type
& TYPE_MASK
) == TYPE_OVERLAP
) {
6655 mnext
= member
->right
;
6656 member
= member
->left
;
6658 size
= reg_size_of(state
, member
);
6659 if (size
> reg_offset
) {
6660 struct type
*part
, *hunt
;
6661 part
= reg_type(state
, member
, reg_offset
);
6662 /* See if this type is already in the union */
6665 struct type
*test
= hunt
;
6667 if ((test
->type
& TYPE_MASK
) == TYPE_OVERLAP
) {
6671 if (equiv_types(part
, test
)) {
6679 *jnext
= new_type(TYPE_OVERLAP
, *jnext
, part
);
6680 jnext
= &(*jnext
)->right
;
6687 if (join
->elements
== 0) {
6688 internal_error(state
, 0, "No elements?");
6695 fprintf(state
->errout
, "type: ");
6696 name_of(state
->errout
, type
);
6697 fprintf(state
->errout
, "\n");
6698 internal_error(state
, 0, "reg_type not yet defined for type");
6702 /* If I have a single register compound type not a bit-field
6703 * find the real type.
6705 member
= unpack_type(state
, member
);
6707 size
= reg_size_of(state
, member
);
6708 if (size
> REG_SIZEOF_REG
) {
6709 internal_error(state
, 0, "Cannot find type of single register");
6712 invalid
= invalid_type(state
, member
);
6714 fprintf(state
->errout
, "type: ");
6715 name_of(state
->errout
, member
);
6716 fprintf(state
->errout
, "\n");
6717 fprintf(state
->errout
, "invalid: ");
6718 name_of(state
->errout
, invalid
);
6719 fprintf(state
->errout
, "\n");
6720 internal_error(state
, 0, "returning bad type?");
6726 static struct type
*next_field(struct compile_state
*state
,
6727 struct type
*type
, struct type
*prev_member
)
6729 struct type
*member
;
6730 if ((type
->type
& TYPE_MASK
) != TYPE_STRUCT
) {
6731 internal_error(state
, 0, "next_field only works on structures");
6733 member
= type
->left
;
6734 while((member
->type
& TYPE_MASK
) == TYPE_PRODUCT
) {
6736 member
= member
->left
;
6739 if (member
->left
== prev_member
) {
6742 member
= member
->right
;
6744 if (member
== prev_member
) {
6748 internal_error(state
, 0, "prev_member %s not present",
6749 prev_member
->field_ident
->name
);
6754 typedef void (*walk_type_fields_cb_t
)(struct compile_state
*state
, struct type
*type
,
6755 size_t ret_offset
, size_t mem_offset
, void *arg
);
6757 static void walk_type_fields(struct compile_state
*state
,
6758 struct type
*type
, size_t reg_offset
, size_t mem_offset
,
6759 walk_type_fields_cb_t cb
, void *arg
);
6761 static void walk_struct_fields(struct compile_state
*state
,
6762 struct type
*type
, size_t reg_offset
, size_t mem_offset
,
6763 walk_type_fields_cb_t cb
, void *arg
)
6767 if ((type
->type
& TYPE_MASK
) != TYPE_STRUCT
) {
6768 internal_error(state
, 0, "walk_struct_fields only works on structures");
6771 for(i
= 0; i
< type
->elements
; i
++) {
6774 if ((mtype
->type
& TYPE_MASK
) == TYPE_PRODUCT
) {
6775 mtype
= mtype
->left
;
6777 walk_type_fields(state
, mtype
,
6779 field_reg_offset(state
, type
, mtype
->field_ident
),
6781 field_offset(state
, type
, mtype
->field_ident
),
6788 static void walk_type_fields(struct compile_state
*state
,
6789 struct type
*type
, size_t reg_offset
, size_t mem_offset
,
6790 walk_type_fields_cb_t cb
, void *arg
)
6792 switch(type
->type
& TYPE_MASK
) {
6794 walk_struct_fields(state
, type
, reg_offset
, mem_offset
, cb
, arg
);
6804 cb(state
, type
, reg_offset
, mem_offset
, arg
);
6809 internal_error(state
, 0, "walk_type_fields not yet implemented for type");
6813 static void arrays_complete(struct compile_state
*state
, struct type
*type
)
6815 if ((type
->type
& TYPE_MASK
) == TYPE_ARRAY
) {
6816 if (type
->elements
== ELEMENT_COUNT_UNSPECIFIED
) {
6817 error(state
, 0, "array size not specified");
6819 arrays_complete(state
, type
->left
);
6823 static unsigned int get_basic_type(struct type
*type
)
6826 basic
= type
->type
& TYPE_MASK
;
6827 /* Convert enums to ints */
6828 if (basic
== TYPE_ENUM
) {
6831 /* Convert bitfields to standard types */
6832 else if (basic
== TYPE_BITFIELD
) {
6833 if (type
->elements
<= SIZEOF_CHAR
) {
6836 else if (type
->elements
<= SIZEOF_SHORT
) {
6839 else if (type
->elements
<= SIZEOF_INT
) {
6842 else if (type
->elements
<= SIZEOF_LONG
) {
6845 if (!TYPE_SIGNED(type
->left
->type
)) {
6852 static unsigned int do_integral_promotion(unsigned int type
)
6854 if (TYPE_INTEGER(type
) && (TYPE_RANK(type
) < TYPE_RANK(TYPE_INT
))) {
6860 static unsigned int do_arithmetic_conversion(
6861 unsigned int left
, unsigned int right
)
6863 if ((left
== TYPE_LDOUBLE
) || (right
== TYPE_LDOUBLE
)) {
6864 return TYPE_LDOUBLE
;
6866 else if ((left
== TYPE_DOUBLE
) || (right
== TYPE_DOUBLE
)) {
6869 else if ((left
== TYPE_FLOAT
) || (right
== TYPE_FLOAT
)) {
6872 left
= do_integral_promotion(left
);
6873 right
= do_integral_promotion(right
);
6874 /* If both operands have the same size done */
6875 if (left
== right
) {
6878 /* If both operands have the same signedness pick the larger */
6879 else if (!!TYPE_UNSIGNED(left
) == !!TYPE_UNSIGNED(right
)) {
6880 return (TYPE_RANK(left
) >= TYPE_RANK(right
)) ? left
: right
;
6882 /* If the signed type can hold everything use it */
6883 else if (TYPE_SIGNED(left
) && (TYPE_RANK(left
) > TYPE_RANK(right
))) {
6886 else if (TYPE_SIGNED(right
) && (TYPE_RANK(right
) > TYPE_RANK(left
))) {
6889 /* Convert to the unsigned type with the same rank as the signed type */
6890 else if (TYPE_SIGNED(left
)) {
6891 return TYPE_MKUNSIGNED(left
);
6894 return TYPE_MKUNSIGNED(right
);
6898 /* see if two types are the same except for qualifiers */
6899 static int equiv_types(struct type
*left
, struct type
*right
)
6902 /* Error if the basic types do not match */
6903 if ((left
->type
& TYPE_MASK
) != (right
->type
& TYPE_MASK
)) {
6906 type
= left
->type
& TYPE_MASK
;
6907 /* If the basic types match and it is a void type we are done */
6908 if (type
== TYPE_VOID
) {
6911 /* For bitfields we need to compare the sizes */
6912 else if (type
== TYPE_BITFIELD
) {
6913 return (left
->elements
== right
->elements
) &&
6914 (TYPE_SIGNED(left
->left
->type
) == TYPE_SIGNED(right
->left
->type
));
6916 /* if the basic types match and it is an arithmetic type we are done */
6917 else if (TYPE_ARITHMETIC(type
)) {
6920 /* If it is a pointer type recurse and keep testing */
6921 else if (type
== TYPE_POINTER
) {
6922 return equiv_types(left
->left
, right
->left
);
6924 else if (type
== TYPE_ARRAY
) {
6925 return (left
->elements
== right
->elements
) &&
6926 equiv_types(left
->left
, right
->left
);
6928 /* test for struct equality */
6929 else if (type
== TYPE_STRUCT
) {
6930 return left
->type_ident
== right
->type_ident
;
6932 /* test for union equality */
6933 else if (type
== TYPE_UNION
) {
6934 return left
->type_ident
== right
->type_ident
;
6936 /* Test for equivalent functions */
6937 else if (type
== TYPE_FUNCTION
) {
6938 return equiv_types(left
->left
, right
->left
) &&
6939 equiv_types(left
->right
, right
->right
);
6941 /* We only see TYPE_PRODUCT as part of function equivalence matching */
6942 /* We also see TYPE_PRODUCT as part of of tuple equivalence matchin */
6943 else if (type
== TYPE_PRODUCT
) {
6944 return equiv_types(left
->left
, right
->left
) &&
6945 equiv_types(left
->right
, right
->right
);
6947 /* We should see TYPE_OVERLAP when comparing joins */
6948 else if (type
== TYPE_OVERLAP
) {
6949 return equiv_types(left
->left
, right
->left
) &&
6950 equiv_types(left
->right
, right
->right
);
6952 /* Test for equivalence of tuples */
6953 else if (type
== TYPE_TUPLE
) {
6954 return (left
->elements
== right
->elements
) &&
6955 equiv_types(left
->left
, right
->left
);
6957 /* Test for equivalence of joins */
6958 else if (type
== TYPE_JOIN
) {
6959 return (left
->elements
== right
->elements
) &&
6960 equiv_types(left
->left
, right
->left
);
6967 static int equiv_ptrs(struct type
*left
, struct type
*right
)
6969 if (((left
->type
& TYPE_MASK
) != TYPE_POINTER
) ||
6970 ((right
->type
& TYPE_MASK
) != TYPE_POINTER
)) {
6973 return equiv_types(left
->left
, right
->left
);
6976 static struct type
*compatible_types(struct type
*left
, struct type
*right
)
6978 struct type
*result
;
6979 unsigned int type
, qual_type
;
6980 /* Error if the basic types do not match */
6981 if ((left
->type
& TYPE_MASK
) != (right
->type
& TYPE_MASK
)) {
6984 type
= left
->type
& TYPE_MASK
;
6985 qual_type
= (left
->type
& ~STOR_MASK
) | (right
->type
& ~STOR_MASK
);
6987 /* if the basic types match and it is an arithmetic type we are done */
6988 if (TYPE_ARITHMETIC(type
)) {
6989 result
= new_type(qual_type
, 0, 0);
6991 /* If it is a pointer type recurse and keep testing */
6992 else if (type
== TYPE_POINTER
) {
6993 result
= compatible_types(left
->left
, right
->left
);
6995 result
= new_type(qual_type
, result
, 0);
6998 /* test for struct equality */
6999 else if (type
== TYPE_STRUCT
) {
7000 if (left
->type_ident
== right
->type_ident
) {
7004 /* test for union equality */
7005 else if (type
== TYPE_UNION
) {
7006 if (left
->type_ident
== right
->type_ident
) {
7010 /* Test for equivalent functions */
7011 else if (type
== TYPE_FUNCTION
) {
7012 struct type
*lf
, *rf
;
7013 lf
= compatible_types(left
->left
, right
->left
);
7014 rf
= compatible_types(left
->right
, right
->right
);
7016 result
= new_type(qual_type
, lf
, rf
);
7019 /* We only see TYPE_PRODUCT as part of function equivalence matching */
7020 else if (type
== TYPE_PRODUCT
) {
7021 struct type
*lf
, *rf
;
7022 lf
= compatible_types(left
->left
, right
->left
);
7023 rf
= compatible_types(left
->right
, right
->right
);
7025 result
= new_type(qual_type
, lf
, rf
);
7029 /* Nothing else is compatible */
7034 /* See if left is a equivalent to right or right is a union member of left */
7035 static int is_subset_type(struct type
*left
, struct type
*right
)
7037 if (equiv_types(left
, right
)) {
7040 if ((left
->type
& TYPE_MASK
) == TYPE_JOIN
) {
7041 struct type
*member
, *mnext
;
7046 if ((member
->type
& TYPE_MASK
) == TYPE_OVERLAP
) {
7047 mnext
= member
->right
;
7048 member
= member
->left
;
7050 if (is_subset_type( member
, right
)) {
7058 static struct type
*compatible_ptrs(struct type
*left
, struct type
*right
)
7060 struct type
*result
;
7061 if (((left
->type
& TYPE_MASK
) != TYPE_POINTER
) ||
7062 ((right
->type
& TYPE_MASK
) != TYPE_POINTER
)) {
7065 result
= compatible_types(left
->left
, right
->left
);
7067 unsigned int qual_type
;
7068 qual_type
= (left
->type
& ~STOR_MASK
) | (right
->type
& ~STOR_MASK
);
7069 result
= new_type(qual_type
, result
, 0);
7074 static struct triple
*integral_promotion(
7075 struct compile_state
*state
, struct triple
*def
)
7079 /* As all operations are carried out in registers
7080 * the values are converted on load I just convert
7081 * logical type of the operand.
7083 if (TYPE_INTEGER(type
->type
)) {
7084 unsigned int int_type
;
7085 int_type
= type
->type
& ~TYPE_MASK
;
7086 int_type
|= do_integral_promotion(get_basic_type(type
));
7087 if (int_type
!= type
->type
) {
7088 if (def
->op
!= OP_LOAD
) {
7089 def
->type
= new_type(int_type
, 0, 0);
7092 def
= triple(state
, OP_CONVERT
,
7093 new_type(int_type
, 0, 0), def
, 0);
7101 static void arithmetic(struct compile_state
*state
, struct triple
*def
)
7103 if (!TYPE_ARITHMETIC(def
->type
->type
)) {
7104 error(state
, 0, "arithmetic type expexted");
7108 static void ptr_arithmetic(struct compile_state
*state
, struct triple
*def
)
7110 if (!TYPE_PTR(def
->type
->type
) && !TYPE_ARITHMETIC(def
->type
->type
)) {
7111 error(state
, def
, "pointer or arithmetic type expected");
7115 static int is_integral(struct triple
*ins
)
7117 return TYPE_INTEGER(ins
->type
->type
);
7120 static void integral(struct compile_state
*state
, struct triple
*def
)
7122 if (!is_integral(def
)) {
7123 error(state
, 0, "integral type expected");
7128 static void bool(struct compile_state
*state
, struct triple
*def
)
7130 if (!TYPE_ARITHMETIC(def
->type
->type
) &&
7131 ((def
->type
->type
& TYPE_MASK
) != TYPE_POINTER
)) {
7132 error(state
, 0, "arithmetic or pointer type expected");
7136 static int is_signed(struct type
*type
)
7138 if ((type
->type
& TYPE_MASK
) == TYPE_BITFIELD
) {
7141 return !!TYPE_SIGNED(type
->type
);
7143 static int is_compound_type(struct type
*type
)
7146 switch((type
->type
& TYPE_MASK
)) {
7161 /* Is this value located in a register otherwise it must be in memory */
7162 static int is_in_reg(struct compile_state
*state
, struct triple
*def
)
7165 if (def
->op
== OP_ADECL
) {
7168 else if ((def
->op
== OP_SDECL
) || (def
->op
== OP_DEREF
)) {
7171 else if (triple_is_part(state
, def
)) {
7172 in_reg
= is_in_reg(state
, MISC(def
, 0));
7175 internal_error(state
, def
, "unknown expr storage location");
7181 /* Is this an auto or static variable location? Something that can
7182 * be assigned to. Otherwise it must must be a pure value, a temporary.
7184 static int is_lvalue(struct compile_state
*state
, struct triple
*def
)
7191 if ((def
->op
== OP_ADECL
) ||
7192 (def
->op
== OP_SDECL
) ||
7193 (def
->op
== OP_DEREF
) ||
7194 (def
->op
== OP_BLOBCONST
) ||
7195 (def
->op
== OP_LIST
)) {
7198 else if (triple_is_part(state
, def
)) {
7199 ret
= is_lvalue(state
, MISC(def
, 0));
7204 static void clvalue(struct compile_state
*state
, struct triple
*def
)
7207 internal_error(state
, def
, "nothing where lvalue expected?");
7209 if (!is_lvalue(state
, def
)) {
7210 error(state
, def
, "lvalue expected");
7213 static void lvalue(struct compile_state
*state
, struct triple
*def
)
7215 clvalue(state
, def
);
7216 if (def
->type
->type
& QUAL_CONST
) {
7217 error(state
, def
, "modifable lvalue expected");
7221 static int is_pointer(struct triple
*def
)
7223 return (def
->type
->type
& TYPE_MASK
) == TYPE_POINTER
;
7226 static void pointer(struct compile_state
*state
, struct triple
*def
)
7228 if (!is_pointer(def
)) {
7229 error(state
, def
, "pointer expected");
7233 static struct triple
*int_const(
7234 struct compile_state
*state
, struct type
*type
, ulong_t value
)
7236 struct triple
*result
;
7237 switch(type
->type
& TYPE_MASK
) {
7239 case TYPE_INT
: case TYPE_UINT
:
7240 case TYPE_LONG
: case TYPE_ULONG
:
7243 internal_error(state
, 0, "constant for unknown type");
7245 result
= triple(state
, OP_INTCONST
, type
, 0, 0);
7246 result
->u
.cval
= value
;
7251 static struct triple
*read_expr(struct compile_state
*state
, struct triple
*def
);
7253 static struct triple
*do_mk_addr_expr(struct compile_state
*state
,
7254 struct triple
*expr
, struct type
*type
, ulong_t offset
)
7256 struct triple
*result
;
7257 struct type
*ptr_type
;
7258 clvalue(state
, expr
);
7260 ptr_type
= new_type(TYPE_POINTER
| (type
->type
& QUAL_MASK
), type
, 0);
7264 if (expr
->op
== OP_ADECL
) {
7265 error(state
, expr
, "address of auto variables not supported");
7267 else if (expr
->op
== OP_SDECL
) {
7268 result
= triple(state
, OP_ADDRCONST
, ptr_type
, 0, 0);
7269 MISC(result
, 0) = expr
;
7270 result
->u
.cval
= offset
;
7272 else if (expr
->op
== OP_DEREF
) {
7273 result
= triple(state
, OP_ADD
, ptr_type
,
7275 int_const(state
, &ulong_type
, offset
));
7277 else if (expr
->op
== OP_BLOBCONST
) {
7279 internal_error(state
, expr
, "not yet implemented");
7281 else if (expr
->op
== OP_LIST
) {
7282 error(state
, 0, "Function addresses not supported");
7284 else if (triple_is_part(state
, expr
)) {
7285 struct triple
*part
;
7287 expr
= MISC(expr
, 0);
7288 if (part
->op
== OP_DOT
) {
7289 offset
+= bits_to_bytes(
7290 field_offset(state
, expr
->type
, part
->u
.field
));
7292 else if (part
->op
== OP_INDEX
) {
7293 offset
+= bits_to_bytes(
7294 index_offset(state
, expr
->type
, part
->u
.cval
));
7297 internal_error(state
, part
, "unhandled part type");
7299 result
= do_mk_addr_expr(state
, expr
, type
, offset
);
7302 internal_error(state
, expr
, "cannot take address of expression");
7307 static struct triple
*mk_addr_expr(
7308 struct compile_state
*state
, struct triple
*expr
, ulong_t offset
)
7310 return do_mk_addr_expr(state
, expr
, expr
->type
, offset
);
7313 static struct triple
*mk_deref_expr(
7314 struct compile_state
*state
, struct triple
*expr
)
7316 struct type
*base_type
;
7317 pointer(state
, expr
);
7318 base_type
= expr
->type
->left
;
7319 return triple(state
, OP_DEREF
, base_type
, expr
, 0);
7322 /* lvalue conversions always apply except when certain operators
7323 * are applied. So I apply apply it when I know no more
7324 * operators will be applied.
7326 static struct triple
*lvalue_conversion(struct compile_state
*state
, struct triple
*def
)
7328 /* Tranform an array to a pointer to the first element */
7329 if ((def
->type
->type
& TYPE_MASK
) == TYPE_ARRAY
) {
7332 TYPE_POINTER
| (def
->type
->type
& QUAL_MASK
),
7333 def
->type
->left
, 0);
7334 if ((def
->op
== OP_SDECL
) || IS_CONST_OP(def
->op
)) {
7335 struct triple
*addrconst
;
7336 if ((def
->op
!= OP_SDECL
) && (def
->op
!= OP_BLOBCONST
)) {
7337 internal_error(state
, def
, "bad array constant");
7339 addrconst
= triple(state
, OP_ADDRCONST
, type
, 0, 0);
7340 MISC(addrconst
, 0) = def
;
7344 def
= triple(state
, OP_CONVERT
, type
, def
, 0);
7347 /* Transform a function to a pointer to it */
7348 else if ((def
->type
->type
& TYPE_MASK
) == TYPE_FUNCTION
) {
7349 def
= mk_addr_expr(state
, def
, 0);
7354 static struct triple
*deref_field(
7355 struct compile_state
*state
, struct triple
*expr
, struct hash_entry
*field
)
7357 struct triple
*result
;
7358 struct type
*type
, *member
;
7361 internal_error(state
, 0, "No field passed to deref_field");
7365 if (((type
->type
& TYPE_MASK
) != TYPE_STRUCT
) &&
7366 ((type
->type
& TYPE_MASK
) != TYPE_UNION
)) {
7367 error(state
, 0, "request for member %s in something not a struct or union",
7370 member
= field_type(state
, type
, field
);
7371 if ((type
->type
& STOR_MASK
) == STOR_PERM
) {
7372 /* Do the pointer arithmetic to get a deref the field */
7373 offset
= bits_to_bytes(field_offset(state
, type
, field
));
7374 result
= do_mk_addr_expr(state
, expr
, member
, offset
);
7375 result
= mk_deref_expr(state
, result
);
7378 /* Find the variable for the field I want. */
7379 result
= triple(state
, OP_DOT
, member
, expr
, 0);
7380 result
->u
.field
= field
;
7385 static struct triple
*deref_index(
7386 struct compile_state
*state
, struct triple
*expr
, size_t index
)
7388 struct triple
*result
;
7389 struct type
*type
, *member
;
7394 member
= index_type(state
, type
, index
);
7396 if ((type
->type
& STOR_MASK
) == STOR_PERM
) {
7397 offset
= bits_to_bytes(index_offset(state
, type
, index
));
7398 result
= do_mk_addr_expr(state
, expr
, member
, offset
);
7399 result
= mk_deref_expr(state
, result
);
7402 result
= triple(state
, OP_INDEX
, member
, expr
, 0);
7403 result
->u
.cval
= index
;
7408 static struct triple
*read_expr(struct compile_state
*state
, struct triple
*def
)
7414 #if DEBUG_ROMCC_WARNINGS
7415 #warning "CHECK_ME is this the only place I need to do lvalue conversions?"
7417 /* Transform lvalues into something we can read */
7418 def
= lvalue_conversion(state
, def
);
7419 if (!is_lvalue(state
, def
)) {
7422 if (is_in_reg(state
, def
)) {
7425 if (def
->op
== OP_SDECL
) {
7426 def
= mk_addr_expr(state
, def
, 0);
7427 def
= mk_deref_expr(state
, def
);
7431 def
= triple(state
, op
, def
->type
, def
, 0);
7432 if (def
->type
->type
& QUAL_VOLATILE
) {
7433 def
->id
|= TRIPLE_FLAG_VOLATILE
;
7438 int is_write_compatible(struct compile_state
*state
,
7439 struct type
*dest
, struct type
*rval
)
7442 /* Both operands have arithmetic type */
7443 if (TYPE_ARITHMETIC(dest
->type
) && TYPE_ARITHMETIC(rval
->type
)) {
7446 /* One operand is a pointer and the other is a pointer to void */
7447 else if (((dest
->type
& TYPE_MASK
) == TYPE_POINTER
) &&
7448 ((rval
->type
& TYPE_MASK
) == TYPE_POINTER
) &&
7449 (((dest
->left
->type
& TYPE_MASK
) == TYPE_VOID
) ||
7450 ((rval
->left
->type
& TYPE_MASK
) == TYPE_VOID
))) {
7453 /* If both types are the same without qualifiers we are good */
7454 else if (equiv_ptrs(dest
, rval
)) {
7457 /* test for struct/union equality */
7458 else if (equiv_types(dest
, rval
)) {
7464 static void write_compatible(struct compile_state
*state
,
7465 struct type
*dest
, struct type
*rval
)
7467 if (!is_write_compatible(state
, dest
, rval
)) {
7468 FILE *fp
= state
->errout
;
7469 fprintf(fp
, "dest: ");
7471 fprintf(fp
,"\nrval: ");
7474 error(state
, 0, "Incompatible types in assignment");
7478 static int is_init_compatible(struct compile_state
*state
,
7479 struct type
*dest
, struct type
*rval
)
7482 if (is_write_compatible(state
, dest
, rval
)) {
7485 else if (equiv_types(dest
, rval
)) {
7491 static struct triple
*write_expr(
7492 struct compile_state
*state
, struct triple
*dest
, struct triple
*rval
)
7498 internal_error(state
, 0, "missing rval");
7501 if (rval
->op
== OP_LIST
) {
7502 internal_error(state
, 0, "expression of type OP_LIST?");
7504 if (!is_lvalue(state
, dest
)) {
7505 internal_error(state
, 0, "writing to a non lvalue?");
7507 if (dest
->type
->type
& QUAL_CONST
) {
7508 internal_error(state
, 0, "modifable lvalue expexted");
7511 write_compatible(state
, dest
->type
, rval
->type
);
7512 if (!equiv_types(dest
->type
, rval
->type
)) {
7513 rval
= triple(state
, OP_CONVERT
, dest
->type
, rval
, 0);
7516 /* Now figure out which assignment operator to use */
7517 if (is_in_reg(state
, dest
)) {
7518 def
= triple(state
, OP_WRITE
, dest
->type
, rval
, dest
);
7519 if (MISC(def
, 0) != dest
) {
7520 internal_error(state
, def
, "huh?");
7522 if (RHS(def
, 0) != rval
) {
7523 internal_error(state
, def
, "huh?");
7526 def
= triple(state
, OP_STORE
, dest
->type
, dest
, rval
);
7528 if (def
->type
->type
& QUAL_VOLATILE
) {
7529 def
->id
|= TRIPLE_FLAG_VOLATILE
;
7534 static struct triple
*init_expr(
7535 struct compile_state
*state
, struct triple
*dest
, struct triple
*rval
)
7541 internal_error(state
, 0, "missing rval");
7543 if ((dest
->type
->type
& STOR_MASK
) != STOR_PERM
) {
7544 rval
= read_expr(state
, rval
);
7545 def
= write_expr(state
, dest
, rval
);
7548 /* Fill in the array size if necessary */
7549 if (((dest
->type
->type
& TYPE_MASK
) == TYPE_ARRAY
) &&
7550 ((rval
->type
->type
& TYPE_MASK
) == TYPE_ARRAY
)) {
7551 if (dest
->type
->elements
== ELEMENT_COUNT_UNSPECIFIED
) {
7552 dest
->type
->elements
= rval
->type
->elements
;
7555 if (!equiv_types(dest
->type
, rval
->type
)) {
7556 error(state
, 0, "Incompatible types in inializer");
7558 MISC(dest
, 0) = rval
;
7559 insert_triple(state
, dest
, rval
);
7560 rval
->id
|= TRIPLE_FLAG_FLATTENED
;
7561 use_triple(MISC(dest
, 0), dest
);
7566 struct type
*arithmetic_result(
7567 struct compile_state
*state
, struct triple
*left
, struct triple
*right
)
7570 /* Sanity checks to ensure I am working with arithmetic types */
7571 arithmetic(state
, left
);
7572 arithmetic(state
, right
);
7574 do_arithmetic_conversion(
7575 get_basic_type(left
->type
),
7576 get_basic_type(right
->type
)),
7581 struct type
*ptr_arithmetic_result(
7582 struct compile_state
*state
, struct triple
*left
, struct triple
*right
)
7585 /* Sanity checks to ensure I am working with the proper types */
7586 ptr_arithmetic(state
, left
);
7587 arithmetic(state
, right
);
7588 if (TYPE_ARITHMETIC(left
->type
->type
) &&
7589 TYPE_ARITHMETIC(right
->type
->type
)) {
7590 type
= arithmetic_result(state
, left
, right
);
7592 else if (TYPE_PTR(left
->type
->type
)) {
7596 internal_error(state
, 0, "huh?");
7602 /* boolean helper function */
7604 static struct triple
*ltrue_expr(struct compile_state
*state
,
7605 struct triple
*expr
)
7608 case OP_LTRUE
: case OP_LFALSE
: case OP_EQ
: case OP_NOTEQ
:
7609 case OP_SLESS
: case OP_ULESS
: case OP_SMORE
: case OP_UMORE
:
7610 case OP_SLESSEQ
: case OP_ULESSEQ
: case OP_SMOREEQ
: case OP_UMOREEQ
:
7611 /* If the expression is already boolean do nothing */
7614 expr
= triple(state
, OP_LTRUE
, &int_type
, expr
, 0);
7620 static struct triple
*lfalse_expr(struct compile_state
*state
,
7621 struct triple
*expr
)
7623 return triple(state
, OP_LFALSE
, &int_type
, expr
, 0);
7626 static struct triple
*mkland_expr(
7627 struct compile_state
*state
,
7628 struct triple
*left
, struct triple
*right
)
7630 struct triple
*def
, *val
, *var
, *jmp
, *mid
, *end
;
7631 struct triple
*lstore
, *rstore
;
7633 /* Generate some intermediate triples */
7635 var
= variable(state
, &int_type
);
7637 /* Store the left hand side value */
7638 lstore
= write_expr(state
, var
, left
);
7640 /* Jump if the value is false */
7641 jmp
= branch(state
, end
,
7642 lfalse_expr(state
, read_expr(state
, var
)));
7645 /* Store the right hand side value */
7646 rstore
= write_expr(state
, var
, right
);
7648 /* An expression for the computed value */
7649 val
= read_expr(state
, var
);
7651 /* Generate the prog for a logical and */
7652 def
= mkprog(state
, var
, lstore
, jmp
, mid
, rstore
, end
, val
, 0UL);
7657 static struct triple
*mklor_expr(
7658 struct compile_state
*state
,
7659 struct triple
*left
, struct triple
*right
)
7661 struct triple
*def
, *val
, *var
, *jmp
, *mid
, *end
;
7663 /* Generate some intermediate triples */
7665 var
= variable(state
, &int_type
);
7667 /* Store the left hand side value */
7668 left
= write_expr(state
, var
, left
);
7670 /* Jump if the value is true */
7671 jmp
= branch(state
, end
, read_expr(state
, var
));
7674 /* Store the right hand side value */
7675 right
= write_expr(state
, var
, right
);
7677 /* An expression for the computed value*/
7678 val
= read_expr(state
, var
);
7680 /* Generate the prog for a logical or */
7681 def
= mkprog(state
, var
, left
, jmp
, mid
, right
, end
, val
, 0UL);
7686 static struct triple
*mkcond_expr(
7687 struct compile_state
*state
,
7688 struct triple
*test
, struct triple
*left
, struct triple
*right
)
7690 struct triple
*def
, *val
, *var
, *jmp1
, *jmp2
, *top
, *mid
, *end
;
7691 struct type
*result_type
;
7692 unsigned int left_type
, right_type
;
7694 left_type
= left
->type
->type
;
7695 right_type
= right
->type
->type
;
7697 /* Both operands have arithmetic type */
7698 if (TYPE_ARITHMETIC(left_type
) && TYPE_ARITHMETIC(right_type
)) {
7699 result_type
= arithmetic_result(state
, left
, right
);
7701 /* Both operands have void type */
7702 else if (((left_type
& TYPE_MASK
) == TYPE_VOID
) &&
7703 ((right_type
& TYPE_MASK
) == TYPE_VOID
)) {
7704 result_type
= &void_type
;
7706 /* pointers to the same type... */
7707 else if ((result_type
= compatible_ptrs(left
->type
, right
->type
))) {
7710 /* Both operands are pointers and left is a pointer to void */
7711 else if (((left_type
& TYPE_MASK
) == TYPE_POINTER
) &&
7712 ((right_type
& TYPE_MASK
) == TYPE_POINTER
) &&
7713 ((left
->type
->left
->type
& TYPE_MASK
) == TYPE_VOID
)) {
7714 result_type
= right
->type
;
7716 /* Both operands are pointers and right is a pointer to void */
7717 else if (((left_type
& TYPE_MASK
) == TYPE_POINTER
) &&
7718 ((right_type
& TYPE_MASK
) == TYPE_POINTER
) &&
7719 ((right
->type
->left
->type
& TYPE_MASK
) == TYPE_VOID
)) {
7720 result_type
= left
->type
;
7723 error(state
, 0, "Incompatible types in conditional expression");
7725 /* Generate some intermediate triples */
7728 var
= variable(state
, result_type
);
7730 /* Branch if the test is false */
7731 jmp1
= branch(state
, mid
, lfalse_expr(state
, read_expr(state
, test
)));
7734 /* Store the left hand side value */
7735 left
= write_expr(state
, var
, left
);
7737 /* Branch to the end */
7738 jmp2
= branch(state
, end
, 0);
7740 /* Store the right hand side value */
7741 right
= write_expr(state
, var
, right
);
7743 /* An expression for the computed value */
7744 val
= read_expr(state
, var
);
7746 /* Generate the prog for a conditional expression */
7747 def
= mkprog(state
, var
, jmp1
, top
, left
, jmp2
, mid
, right
, end
, val
, 0UL);
7753 static int expr_depth(struct compile_state
*state
, struct triple
*ins
)
7755 #if DEBUG_ROMCC_WARNINGS
7756 #warning "FIXME move optimal ordering of subexpressions into the optimizer"
7760 if (!ins
|| (ins
->id
& TRIPLE_FLAG_FLATTENED
)) {
7763 else if (ins
->op
== OP_DEREF
) {
7764 count
= expr_depth(state
, RHS(ins
, 0)) - 1;
7766 else if (ins
->op
== OP_VAL
) {
7767 count
= expr_depth(state
, RHS(ins
, 0)) - 1;
7769 else if (ins
->op
== OP_FCALL
) {
7770 /* Don't figure the depth of a call just guess it is huge */
7774 struct triple
**expr
;
7775 expr
= triple_rhs(state
, ins
, 0);
7776 for(;expr
; expr
= triple_rhs(state
, ins
, expr
)) {
7779 depth
= expr_depth(state
, *expr
);
7780 if (depth
> count
) {
7789 static struct triple
*flatten_generic(
7790 struct compile_state
*state
, struct triple
*first
, struct triple
*ptr
,
7795 struct triple
**ins
;
7798 /* Only operations with just a rhs and a lhs should come here */
7801 if (TRIPLE_SIZE(ptr
) != lhs
+ rhs
+ ignored
) {
7802 internal_error(state
, ptr
, "unexpected args for: %d %s",
7803 ptr
->op
, tops(ptr
->op
));
7805 /* Find the depth of the rhs elements */
7806 for(i
= 0; i
< rhs
; i
++) {
7807 vector
[i
].ins
= &RHS(ptr
, i
);
7808 vector
[i
].depth
= expr_depth(state
, *vector
[i
].ins
);
7810 /* Selection sort the rhs */
7811 for(i
= 0; i
< rhs
; i
++) {
7813 for(j
= i
+ 1; j
< rhs
; j
++ ) {
7814 if (vector
[j
].depth
> vector
[max
].depth
) {
7819 struct rhs_vector tmp
;
7821 vector
[i
] = vector
[max
];
7825 /* Now flatten the rhs elements */
7826 for(i
= 0; i
< rhs
; i
++) {
7827 *vector
[i
].ins
= flatten(state
, first
, *vector
[i
].ins
);
7828 use_triple(*vector
[i
].ins
, ptr
);
7831 insert_triple(state
, first
, ptr
);
7832 ptr
->id
|= TRIPLE_FLAG_FLATTENED
;
7833 ptr
->id
&= ~TRIPLE_FLAG_LOCAL
;
7835 /* Now flatten the lhs elements */
7836 for(i
= 0; i
< lhs
; i
++) {
7837 struct triple
**ins
= &LHS(ptr
, i
);
7838 *ins
= flatten(state
, first
, *ins
);
7839 use_triple(*ins
, ptr
);
7845 static struct triple
*flatten_prog(
7846 struct compile_state
*state
, struct triple
*first
, struct triple
*ptr
)
7848 struct triple
*head
, *body
, *val
;
7853 release_triple(state
, head
);
7854 release_triple(state
, ptr
);
7856 body
->prev
= first
->prev
;
7857 body
->prev
->next
= body
;
7858 val
->next
->prev
= val
;
7860 if (triple_is_cbranch(state
, body
->prev
) ||
7861 triple_is_call(state
, body
->prev
)) {
7862 unuse_triple(first
, body
->prev
);
7863 use_triple(body
, body
->prev
);
7866 if (!(val
->id
& TRIPLE_FLAG_FLATTENED
)) {
7867 internal_error(state
, val
, "val not flattened?");
7874 static struct triple
*flatten_part(
7875 struct compile_state
*state
, struct triple
*first
, struct triple
*ptr
)
7877 if (!triple_is_part(state
, ptr
)) {
7878 internal_error(state
, ptr
, "not a part");
7880 if (ptr
->rhs
|| ptr
->lhs
|| ptr
->targ
|| (ptr
->misc
!= 1)) {
7881 internal_error(state
, ptr
, "unexpected args for: %d %s",
7882 ptr
->op
, tops(ptr
->op
));
7884 MISC(ptr
, 0) = flatten(state
, first
, MISC(ptr
, 0));
7885 use_triple(MISC(ptr
, 0), ptr
);
7886 return flatten_generic(state
, first
, ptr
, 1);
7889 static struct triple
*flatten(
7890 struct compile_state
*state
, struct triple
*first
, struct triple
*ptr
)
7892 struct triple
*orig_ptr
;
7897 /* Only flatten triples once */
7898 if (ptr
->id
& TRIPLE_FLAG_FLATTENED
) {
7903 RHS(ptr
, 0) = flatten(state
, first
, RHS(ptr
, 0));
7904 return MISC(ptr
, 0);
7907 ptr
= flatten_prog(state
, first
, ptr
);
7910 ptr
= flatten_generic(state
, first
, ptr
, 1);
7911 insert_triple(state
, first
, ptr
);
7912 ptr
->id
|= TRIPLE_FLAG_FLATTENED
;
7913 ptr
->id
&= ~TRIPLE_FLAG_LOCAL
;
7914 if (ptr
->next
!= ptr
) {
7915 use_triple(ptr
->next
, ptr
);
7920 RHS(ptr
, 0) = flatten(state
, first
, RHS(ptr
, 0));
7921 use_triple(RHS(ptr
, 0), ptr
);
7924 ptr
= flatten_generic(state
, first
, ptr
, 1);
7925 MISC(ptr
, 0) = flatten(state
, first
, MISC(ptr
, 0));
7926 use_triple(MISC(ptr
, 0), ptr
);
7929 use_triple(TARG(ptr
, 0), ptr
);
7932 RHS(ptr
, 0) = flatten(state
, first
, RHS(ptr
, 0));
7933 use_triple(RHS(ptr
, 0), ptr
);
7934 use_triple(TARG(ptr
, 0), ptr
);
7935 insert_triple(state
, first
, ptr
);
7936 ptr
->id
|= TRIPLE_FLAG_FLATTENED
;
7937 ptr
->id
&= ~TRIPLE_FLAG_LOCAL
;
7938 if (ptr
->next
!= ptr
) {
7939 use_triple(ptr
->next
, ptr
);
7943 MISC(ptr
, 0) = flatten(state
, first
, MISC(ptr
, 0));
7944 use_triple(MISC(ptr
, 0), ptr
);
7945 use_triple(TARG(ptr
, 0), ptr
);
7946 insert_triple(state
, first
, ptr
);
7947 ptr
->id
|= TRIPLE_FLAG_FLATTENED
;
7948 ptr
->id
&= ~TRIPLE_FLAG_LOCAL
;
7949 if (ptr
->next
!= ptr
) {
7950 use_triple(ptr
->next
, ptr
);
7954 RHS(ptr
, 0) = flatten(state
, first
, RHS(ptr
, 0));
7955 use_triple(RHS(ptr
, 0), ptr
);
7958 insert_triple(state
, state
->global_pool
, ptr
);
7959 ptr
->id
|= TRIPLE_FLAG_FLATTENED
;
7960 ptr
->id
&= ~TRIPLE_FLAG_LOCAL
;
7961 ptr
= triple(state
, OP_SDECL
, ptr
->type
, ptr
, 0);
7962 use_triple(MISC(ptr
, 0), ptr
);
7965 /* Since OP_DEREF is just a marker delete it when I flatten it */
7967 RHS(orig_ptr
, 0) = 0;
7968 free_triple(state
, orig_ptr
);
7971 if (RHS(ptr
, 0)->op
== OP_DEREF
) {
7972 struct triple
*base
, *left
;
7974 base
= MISC(ptr
, 0);
7975 offset
= bits_to_bytes(field_offset(state
, base
->type
, ptr
->u
.field
));
7976 left
= RHS(base
, 0);
7977 ptr
= triple(state
, OP_ADD
, left
->type
,
7978 read_expr(state
, left
),
7979 int_const(state
, &ulong_type
, offset
));
7980 free_triple(state
, base
);
7983 ptr
= flatten_part(state
, first
, ptr
);
7987 if (RHS(ptr
, 0)->op
== OP_DEREF
) {
7988 struct triple
*base
, *left
;
7990 base
= MISC(ptr
, 0);
7991 offset
= bits_to_bytes(index_offset(state
, base
->type
, ptr
->u
.cval
));
7992 left
= RHS(base
, 0);
7993 ptr
= triple(state
, OP_ADD
, left
->type
,
7994 read_expr(state
, left
),
7995 int_const(state
, &long_type
, offset
));
7996 free_triple(state
, base
);
7999 ptr
= flatten_part(state
, first
, ptr
);
8003 ptr
= flatten_part(state
, first
, ptr
);
8004 use_triple(ptr
, MISC(ptr
, 0));
8007 MISC(ptr
, 0) = flatten(state
, first
, MISC(ptr
, 0));
8008 use_triple(MISC(ptr
, 0), ptr
);
8011 first
= state
->global_pool
;
8012 MISC(ptr
, 0) = flatten(state
, first
, MISC(ptr
, 0));
8013 use_triple(MISC(ptr
, 0), ptr
);
8014 insert_triple(state
, first
, ptr
);
8015 ptr
->id
|= TRIPLE_FLAG_FLATTENED
;
8016 ptr
->id
&= ~TRIPLE_FLAG_LOCAL
;
8019 ptr
= flatten_generic(state
, first
, ptr
, 0);
8022 /* Flatten the easy cases we don't override */
8023 ptr
= flatten_generic(state
, first
, ptr
, 0);
8026 } while(ptr
&& (ptr
!= orig_ptr
));
8027 if (ptr
&& !(ptr
->id
& TRIPLE_FLAG_FLATTENED
)) {
8028 insert_triple(state
, first
, ptr
);
8029 ptr
->id
|= TRIPLE_FLAG_FLATTENED
;
8030 ptr
->id
&= ~TRIPLE_FLAG_LOCAL
;
8035 static void release_expr(struct compile_state
*state
, struct triple
*expr
)
8037 struct triple
*head
;
8038 head
= label(state
);
8039 flatten(state
, head
, expr
);
8040 while(head
->next
!= head
) {
8041 release_triple(state
, head
->next
);
8043 free_triple(state
, head
);
8046 static int replace_rhs_use(struct compile_state
*state
,
8047 struct triple
*orig
, struct triple
*new, struct triple
*use
)
8049 struct triple
**expr
;
8052 expr
= triple_rhs(state
, use
, 0);
8053 for(;expr
; expr
= triple_rhs(state
, use
, expr
)) {
8054 if (*expr
== orig
) {
8060 unuse_triple(orig
, use
);
8061 use_triple(new, use
);
8066 static int replace_lhs_use(struct compile_state
*state
,
8067 struct triple
*orig
, struct triple
*new, struct triple
*use
)
8069 struct triple
**expr
;
8072 expr
= triple_lhs(state
, use
, 0);
8073 for(;expr
; expr
= triple_lhs(state
, use
, expr
)) {
8074 if (*expr
== orig
) {
8080 unuse_triple(orig
, use
);
8081 use_triple(new, use
);
8086 static int replace_misc_use(struct compile_state
*state
,
8087 struct triple
*orig
, struct triple
*new, struct triple
*use
)
8089 struct triple
**expr
;
8092 expr
= triple_misc(state
, use
, 0);
8093 for(;expr
; expr
= triple_misc(state
, use
, expr
)) {
8094 if (*expr
== orig
) {
8100 unuse_triple(orig
, use
);
8101 use_triple(new, use
);
8106 static int replace_targ_use(struct compile_state
*state
,
8107 struct triple
*orig
, struct triple
*new, struct triple
*use
)
8109 struct triple
**expr
;
8112 expr
= triple_targ(state
, use
, 0);
8113 for(;expr
; expr
= triple_targ(state
, use
, expr
)) {
8114 if (*expr
== orig
) {
8120 unuse_triple(orig
, use
);
8121 use_triple(new, use
);
8126 static void replace_use(struct compile_state
*state
,
8127 struct triple
*orig
, struct triple
*new, struct triple
*use
)
8131 found
|= replace_rhs_use(state
, orig
, new, use
);
8132 found
|= replace_lhs_use(state
, orig
, new, use
);
8133 found
|= replace_misc_use(state
, orig
, new, use
);
8134 found
|= replace_targ_use(state
, orig
, new, use
);
8136 internal_error(state
, use
, "use without use");
8140 static void propogate_use(struct compile_state
*state
,
8141 struct triple
*orig
, struct triple
*new)
8143 struct triple_set
*user
, *next
;
8144 for(user
= orig
->use
; user
; user
= next
) {
8145 /* Careful replace_use modifies the use chain and
8146 * removes use. So we must get a copy of the next
8150 replace_use(state
, orig
, new, user
->member
);
8153 internal_error(state
, orig
, "used after propogate_use");
8159 * ===========================
8162 static struct triple
*mk_cast_expr(
8163 struct compile_state
*state
, struct type
*type
, struct triple
*expr
)
8166 def
= read_expr(state
, expr
);
8167 def
= triple(state
, OP_CONVERT
, type
, def
, 0);
8171 static struct triple
*mk_add_expr(
8172 struct compile_state
*state
, struct triple
*left
, struct triple
*right
)
8174 struct type
*result_type
;
8175 /* Put pointer operands on the left */
8176 if (is_pointer(right
)) {
8182 left
= read_expr(state
, left
);
8183 right
= read_expr(state
, right
);
8184 result_type
= ptr_arithmetic_result(state
, left
, right
);
8185 if (is_pointer(left
)) {
8186 struct type
*ptr_math
;
8188 if (is_signed(right
->type
)) {
8189 ptr_math
= &long_type
;
8192 ptr_math
= &ulong_type
;
8195 if (!equiv_types(right
->type
, ptr_math
)) {
8196 right
= mk_cast_expr(state
, ptr_math
, right
);
8198 right
= triple(state
, op
, ptr_math
, right
,
8199 int_const(state
, ptr_math
,
8200 size_of_in_bytes(state
, left
->type
->left
)));
8202 return triple(state
, OP_ADD
, result_type
, left
, right
);
8205 static struct triple
*mk_sub_expr(
8206 struct compile_state
*state
, struct triple
*left
, struct triple
*right
)
8208 struct type
*result_type
;
8209 result_type
= ptr_arithmetic_result(state
, left
, right
);
8210 left
= read_expr(state
, left
);
8211 right
= read_expr(state
, right
);
8212 if (is_pointer(left
)) {
8213 struct type
*ptr_math
;
8215 if (is_signed(right
->type
)) {
8216 ptr_math
= &long_type
;
8219 ptr_math
= &ulong_type
;
8222 if (!equiv_types(right
->type
, ptr_math
)) {
8223 right
= mk_cast_expr(state
, ptr_math
, right
);
8225 right
= triple(state
, op
, ptr_math
, right
,
8226 int_const(state
, ptr_math
,
8227 size_of_in_bytes(state
, left
->type
->left
)));
8229 return triple(state
, OP_SUB
, result_type
, left
, right
);
8232 static struct triple
*mk_pre_inc_expr(
8233 struct compile_state
*state
, struct triple
*def
)
8237 val
= mk_add_expr(state
, def
, int_const(state
, &int_type
, 1));
8238 return triple(state
, OP_VAL
, def
->type
,
8239 write_expr(state
, def
, val
),
8243 static struct triple
*mk_pre_dec_expr(
8244 struct compile_state
*state
, struct triple
*def
)
8248 val
= mk_sub_expr(state
, def
, int_const(state
, &int_type
, 1));
8249 return triple(state
, OP_VAL
, def
->type
,
8250 write_expr(state
, def
, val
),
8254 static struct triple
*mk_post_inc_expr(
8255 struct compile_state
*state
, struct triple
*def
)
8259 val
= read_expr(state
, def
);
8260 return triple(state
, OP_VAL
, def
->type
,
8261 write_expr(state
, def
,
8262 mk_add_expr(state
, val
, int_const(state
, &int_type
, 1)))
8266 static struct triple
*mk_post_dec_expr(
8267 struct compile_state
*state
, struct triple
*def
)
8271 val
= read_expr(state
, def
);
8272 return triple(state
, OP_VAL
, def
->type
,
8273 write_expr(state
, def
,
8274 mk_sub_expr(state
, val
, int_const(state
, &int_type
, 1)))
8278 static struct triple
*mk_subscript_expr(
8279 struct compile_state
*state
, struct triple
*left
, struct triple
*right
)
8281 left
= read_expr(state
, left
);
8282 right
= read_expr(state
, right
);
8283 if (!is_pointer(left
) && !is_pointer(right
)) {
8284 error(state
, left
, "subscripted value is not a pointer");
8286 return mk_deref_expr(state
, mk_add_expr(state
, left
, right
));
8291 * Compile time evaluation
8292 * ===========================
8294 static int is_const(struct triple
*ins
)
8296 return IS_CONST_OP(ins
->op
);
8299 static int is_simple_const(struct triple
*ins
)
8301 /* Is this a constant that u.cval has the value.
8302 * Or equivalently is this a constant that read_const
8304 * So far only OP_INTCONST qualifies.
8306 return (ins
->op
== OP_INTCONST
);
8309 static int constants_equal(struct compile_state
*state
,
8310 struct triple
*left
, struct triple
*right
)
8313 if ((left
->op
== OP_UNKNOWNVAL
) || (right
->op
== OP_UNKNOWNVAL
)) {
8316 else if (!is_const(left
) || !is_const(right
)) {
8319 else if (left
->op
!= right
->op
) {
8322 else if (!equiv_types(left
->type
, right
->type
)) {
8329 if (left
->u
.cval
== right
->u
.cval
) {
8335 size_t lsize
, rsize
, bytes
;
8336 lsize
= size_of(state
, left
->type
);
8337 rsize
= size_of(state
, right
->type
);
8338 if (lsize
!= rsize
) {
8341 bytes
= bits_to_bytes(lsize
);
8342 if (memcmp(left
->u
.blob
, right
->u
.blob
, bytes
) == 0) {
8348 if ((MISC(left
, 0) == MISC(right
, 0)) &&
8349 (left
->u
.cval
== right
->u
.cval
)) {
8354 internal_error(state
, left
, "uknown constant type");
8361 static int is_zero(struct triple
*ins
)
8363 return is_simple_const(ins
) && (ins
->u
.cval
== 0);
8366 static int is_one(struct triple
*ins
)
8368 return is_simple_const(ins
) && (ins
->u
.cval
== 1);
8371 #if DEBUG_ROMCC_WARNING
8372 static long_t
bit_count(ulong_t value
)
8377 for(i
= (sizeof(ulong_t
)*8) -1; i
>= 0; i
--) {
8390 static long_t
bsr(ulong_t value
)
8393 for(i
= (sizeof(ulong_t
)*8) -1; i
>= 0; i
--) {
8404 static long_t
bsf(ulong_t value
)
8407 for(i
= 0; i
< (sizeof(ulong_t
)*8); i
++) {
8418 static long_t
ilog2(ulong_t value
)
8423 static long_t
tlog2(struct triple
*ins
)
8425 return ilog2(ins
->u
.cval
);
8428 static int is_pow2(struct triple
*ins
)
8430 ulong_t value
, mask
;
8432 if (!is_const(ins
)) {
8435 value
= ins
->u
.cval
;
8442 return ((value
& mask
) == value
);
8445 static ulong_t
read_const(struct compile_state
*state
,
8446 struct triple
*ins
, struct triple
*rhs
)
8448 switch(rhs
->type
->type
&TYPE_MASK
) {
8461 fprintf(state
->errout
, "type: ");
8462 name_of(state
->errout
, rhs
->type
);
8463 fprintf(state
->errout
, "\n");
8464 internal_warning(state
, rhs
, "bad type to read_const");
8467 if (!is_simple_const(rhs
)) {
8468 internal_error(state
, rhs
, "bad op to read_const");
8473 static long_t
read_sconst(struct compile_state
*state
,
8474 struct triple
*ins
, struct triple
*rhs
)
8476 return (long_t
)(rhs
->u
.cval
);
8479 int const_ltrue(struct compile_state
*state
, struct triple
*ins
, struct triple
*rhs
)
8481 if (!is_const(rhs
)) {
8482 internal_error(state
, 0, "non const passed to const_true");
8484 return !is_zero(rhs
);
8487 int const_eq(struct compile_state
*state
, struct triple
*ins
,
8488 struct triple
*left
, struct triple
*right
)
8491 if (!is_const(left
) || !is_const(right
)) {
8492 internal_warning(state
, ins
, "non const passed to const_eq");
8495 else if (left
== right
) {
8498 else if (is_simple_const(left
) && is_simple_const(right
)) {
8500 lval
= read_const(state
, ins
, left
);
8501 rval
= read_const(state
, ins
, right
);
8502 result
= (lval
== rval
);
8504 else if ((left
->op
== OP_ADDRCONST
) &&
8505 (right
->op
== OP_ADDRCONST
)) {
8506 result
= (MISC(left
, 0) == MISC(right
, 0)) &&
8507 (left
->u
.cval
== right
->u
.cval
);
8510 internal_warning(state
, ins
, "incomparable constants passed to const_eq");
8517 int const_ucmp(struct compile_state
*state
, struct triple
*ins
,
8518 struct triple
*left
, struct triple
*right
)
8521 if (!is_const(left
) || !is_const(right
)) {
8522 internal_warning(state
, ins
, "non const past to const_ucmp");
8525 else if (left
== right
) {
8528 else if (is_simple_const(left
) && is_simple_const(right
)) {
8530 lval
= read_const(state
, ins
, left
);
8531 rval
= read_const(state
, ins
, right
);
8535 } else if (rval
> lval
) {
8539 else if ((left
->op
== OP_ADDRCONST
) &&
8540 (right
->op
== OP_ADDRCONST
) &&
8541 (MISC(left
, 0) == MISC(right
, 0))) {
8543 if (left
->u
.cval
> right
->u
.cval
) {
8545 } else if (left
->u
.cval
< right
->u
.cval
) {
8550 internal_warning(state
, ins
, "incomparable constants passed to const_ucmp");
8556 int const_scmp(struct compile_state
*state
, struct triple
*ins
,
8557 struct triple
*left
, struct triple
*right
)
8560 if (!is_const(left
) || !is_const(right
)) {
8561 internal_warning(state
, ins
, "non const past to ucmp_const");
8564 else if (left
== right
) {
8567 else if (is_simple_const(left
) && is_simple_const(right
)) {
8569 lval
= read_sconst(state
, ins
, left
);
8570 rval
= read_sconst(state
, ins
, right
);
8574 } else if (rval
> lval
) {
8579 internal_warning(state
, ins
, "incomparable constants passed to const_scmp");
8585 static void unuse_rhs(struct compile_state
*state
, struct triple
*ins
)
8587 struct triple
**expr
;
8588 expr
= triple_rhs(state
, ins
, 0);
8589 for(;expr
;expr
= triple_rhs(state
, ins
, expr
)) {
8591 unuse_triple(*expr
, ins
);
8597 static void unuse_lhs(struct compile_state
*state
, struct triple
*ins
)
8599 struct triple
**expr
;
8600 expr
= triple_lhs(state
, ins
, 0);
8601 for(;expr
;expr
= triple_lhs(state
, ins
, expr
)) {
8602 unuse_triple(*expr
, ins
);
8607 #if DEBUG_ROMCC_WARNING
8608 static void unuse_misc(struct compile_state
*state
, struct triple
*ins
)
8610 struct triple
**expr
;
8611 expr
= triple_misc(state
, ins
, 0);
8612 for(;expr
;expr
= triple_misc(state
, ins
, expr
)) {
8613 unuse_triple(*expr
, ins
);
8618 static void unuse_targ(struct compile_state
*state
, struct triple
*ins
)
8621 struct triple
**slot
;
8622 slot
= &TARG(ins
, 0);
8623 for(i
= 0; i
< ins
->targ
; i
++) {
8624 unuse_triple(slot
[i
], ins
);
8629 static void check_lhs(struct compile_state
*state
, struct triple
*ins
)
8631 struct triple
**expr
;
8632 expr
= triple_lhs(state
, ins
, 0);
8633 for(;expr
;expr
= triple_lhs(state
, ins
, expr
)) {
8634 internal_error(state
, ins
, "unexpected lhs");
8640 static void check_misc(struct compile_state
*state
, struct triple
*ins
)
8642 struct triple
**expr
;
8643 expr
= triple_misc(state
, ins
, 0);
8644 for(;expr
;expr
= triple_misc(state
, ins
, expr
)) {
8646 internal_error(state
, ins
, "unexpected misc");
8651 static void check_targ(struct compile_state
*state
, struct triple
*ins
)
8653 struct triple
**expr
;
8654 expr
= triple_targ(state
, ins
, 0);
8655 for(;expr
;expr
= triple_targ(state
, ins
, expr
)) {
8656 internal_error(state
, ins
, "unexpected targ");
8660 static void wipe_ins(struct compile_state
*state
, struct triple
*ins
)
8662 /* Becareful which instructions you replace the wiped
8663 * instruction with, as there are not enough slots
8664 * in all instructions to hold all others.
8666 check_targ(state
, ins
);
8667 check_misc(state
, ins
);
8668 unuse_rhs(state
, ins
);
8669 unuse_lhs(state
, ins
);
8676 #if DEBUG_ROMCC_WARNING
8677 static void wipe_branch(struct compile_state
*state
, struct triple
*ins
)
8679 /* Becareful which instructions you replace the wiped
8680 * instruction with, as there are not enough slots
8681 * in all instructions to hold all others.
8683 unuse_rhs(state
, ins
);
8684 unuse_lhs(state
, ins
);
8685 unuse_misc(state
, ins
);
8686 unuse_targ(state
, ins
);
8694 static void mkcopy(struct compile_state
*state
,
8695 struct triple
*ins
, struct triple
*rhs
)
8697 struct block
*block
;
8698 if (!equiv_types(ins
->type
, rhs
->type
)) {
8699 FILE *fp
= state
->errout
;
8700 fprintf(fp
, "src type: ");
8701 name_of(fp
, rhs
->type
);
8702 fprintf(fp
, "\ndst type: ");
8703 name_of(fp
, ins
->type
);
8705 internal_error(state
, ins
, "mkcopy type mismatch");
8707 block
= block_of_triple(state
, ins
);
8708 wipe_ins(state
, ins
);
8711 ins
->u
.block
= block
;
8713 use_triple(RHS(ins
, 0), ins
);
8716 static void mkconst(struct compile_state
*state
,
8717 struct triple
*ins
, ulong_t value
)
8719 if (!is_integral(ins
) && !is_pointer(ins
)) {
8720 fprintf(state
->errout
, "type: ");
8721 name_of(state
->errout
, ins
->type
);
8722 fprintf(state
->errout
, "\n");
8723 internal_error(state
, ins
, "unknown type to make constant value: %ld",
8726 wipe_ins(state
, ins
);
8727 ins
->op
= OP_INTCONST
;
8728 ins
->u
.cval
= value
;
8731 static void mkaddr_const(struct compile_state
*state
,
8732 struct triple
*ins
, struct triple
*sdecl
, ulong_t value
)
8734 if ((sdecl
->op
!= OP_SDECL
) && (sdecl
->op
!= OP_LABEL
)) {
8735 internal_error(state
, ins
, "bad base for addrconst");
8737 wipe_ins(state
, ins
);
8738 ins
->op
= OP_ADDRCONST
;
8740 MISC(ins
, 0) = sdecl
;
8741 ins
->u
.cval
= value
;
8742 use_triple(sdecl
, ins
);
8745 #if DEBUG_DECOMPOSE_PRINT_TUPLES
8746 static void print_tuple(struct compile_state
*state
,
8747 struct triple
*ins
, struct triple
*tuple
)
8749 FILE *fp
= state
->dbgout
;
8750 fprintf(fp
, "%5s %p tuple: %p ", tops(ins
->op
), ins
, tuple
);
8751 name_of(fp
, tuple
->type
);
8752 if (tuple
->lhs
> 0) {
8753 fprintf(fp
, " lhs: ");
8754 name_of(fp
, LHS(tuple
, 0)->type
);
8761 static struct triple
*decompose_with_tuple(struct compile_state
*state
,
8762 struct triple
*ins
, struct triple
*tuple
)
8764 struct triple
*next
;
8766 flatten(state
, next
, tuple
);
8767 #if DEBUG_DECOMPOSE_PRINT_TUPLES
8768 print_tuple(state
, ins
, tuple
);
8771 if (!is_compound_type(tuple
->type
) && (tuple
->lhs
> 0)) {
8773 if (tuple
->lhs
!= 1) {
8774 internal_error(state
, tuple
, "plain type in multiple registers?");
8776 tmp
= LHS(tuple
, 0);
8777 release_triple(state
, tuple
);
8781 propogate_use(state
, ins
, tuple
);
8782 release_triple(state
, ins
);
8787 static struct triple
*decompose_unknownval(struct compile_state
*state
,
8790 struct triple
*tuple
;
8793 #if DEBUG_DECOMPOSE_HIRES
8794 FILE *fp
= state
->dbgout
;
8795 fprintf(fp
, "unknown type: ");
8796 name_of(fp
, ins
->type
);
8800 get_occurance(ins
->occurance
);
8801 tuple
= alloc_triple(state
, OP_TUPLE
, ins
->type
, -1, -1,
8804 for(i
= 0; i
< tuple
->lhs
; i
++) {
8805 struct type
*piece_type
;
8806 struct triple
*unknown
;
8808 piece_type
= reg_type(state
, ins
->type
, i
* REG_SIZEOF_REG
);
8809 get_occurance(tuple
->occurance
);
8810 unknown
= alloc_triple(state
, OP_UNKNOWNVAL
, piece_type
, 0, 0,
8812 LHS(tuple
, i
) = unknown
;
8814 return decompose_with_tuple(state
, ins
, tuple
);
8818 static struct triple
*decompose_read(struct compile_state
*state
,
8821 struct triple
*tuple
, *lval
;
8826 if (lval
->op
== OP_PIECE
) {
8829 get_occurance(ins
->occurance
);
8830 tuple
= alloc_triple(state
, OP_TUPLE
, lval
->type
, -1, -1,
8833 if ((tuple
->lhs
!= lval
->lhs
) &&
8834 (!triple_is_def(state
, lval
) || (tuple
->lhs
!= 1)))
8836 internal_error(state
, ins
, "lhs size inconsistency?");
8838 for(i
= 0; i
< tuple
->lhs
; i
++) {
8839 struct triple
*piece
, *read
, *bitref
;
8840 if ((i
!= 0) || !triple_is_def(state
, lval
)) {
8841 piece
= LHS(lval
, i
);
8846 /* See if the piece is really a bitref */
8848 if (piece
->op
== OP_BITREF
) {
8850 piece
= RHS(bitref
, 0);
8853 get_occurance(tuple
->occurance
);
8854 read
= alloc_triple(state
, OP_READ
, piece
->type
, -1, -1,
8856 RHS(read
, 0) = piece
;
8859 struct triple
*extract
;
8861 if (is_signed(bitref
->type
->left
)) {
8866 get_occurance(tuple
->occurance
);
8867 extract
= alloc_triple(state
, op
, bitref
->type
, -1, -1,
8869 RHS(extract
, 0) = read
;
8870 extract
->u
.bitfield
.size
= bitref
->u
.bitfield
.size
;
8871 extract
->u
.bitfield
.offset
= bitref
->u
.bitfield
.offset
;
8876 LHS(tuple
, i
) = read
;
8878 return decompose_with_tuple(state
, ins
, tuple
);
8881 static struct triple
*decompose_write(struct compile_state
*state
,
8884 struct triple
*tuple
, *lval
, *val
;
8887 lval
= MISC(ins
, 0);
8889 get_occurance(ins
->occurance
);
8890 tuple
= alloc_triple(state
, OP_TUPLE
, ins
->type
, -1, -1,
8893 if ((tuple
->lhs
!= lval
->lhs
) &&
8894 (!triple_is_def(state
, lval
) || tuple
->lhs
!= 1))
8896 internal_error(state
, ins
, "lhs size inconsistency?");
8898 for(i
= 0; i
< tuple
->lhs
; i
++) {
8899 struct triple
*piece
, *write
, *pval
, *bitref
;
8900 if ((i
!= 0) || !triple_is_def(state
, lval
)) {
8901 piece
= LHS(lval
, i
);
8905 if ((i
== 0) && (tuple
->lhs
== 1) && (val
->lhs
== 0)) {
8910 internal_error(state
, ins
, "lhs size inconsistency?");
8915 /* See if the piece is really a bitref */
8917 if (piece
->op
== OP_BITREF
) {
8918 struct triple
*read
, *deposit
;
8920 piece
= RHS(bitref
, 0);
8922 /* Read the destination register */
8923 get_occurance(tuple
->occurance
);
8924 read
= alloc_triple(state
, OP_READ
, piece
->type
, -1, -1,
8926 RHS(read
, 0) = piece
;
8928 /* Deposit the new bitfield value */
8929 get_occurance(tuple
->occurance
);
8930 deposit
= alloc_triple(state
, OP_DEPOSIT
, piece
->type
, -1, -1,
8932 RHS(deposit
, 0) = read
;
8933 RHS(deposit
, 1) = pval
;
8934 deposit
->u
.bitfield
.size
= bitref
->u
.bitfield
.size
;
8935 deposit
->u
.bitfield
.offset
= bitref
->u
.bitfield
.offset
;
8937 /* Now write the newly generated value */
8941 get_occurance(tuple
->occurance
);
8942 write
= alloc_triple(state
, OP_WRITE
, piece
->type
, -1, -1,
8944 MISC(write
, 0) = piece
;
8945 RHS(write
, 0) = pval
;
8946 LHS(tuple
, i
) = write
;
8948 return decompose_with_tuple(state
, ins
, tuple
);
8951 struct decompose_load_info
{
8952 struct occurance
*occurance
;
8953 struct triple
*lval
;
8954 struct triple
*tuple
;
8956 static void decompose_load_cb(struct compile_state
*state
,
8957 struct type
*type
, size_t reg_offset
, size_t mem_offset
, void *arg
)
8959 struct decompose_load_info
*info
= arg
;
8960 struct triple
*load
;
8962 if (reg_offset
> info
->tuple
->lhs
) {
8963 internal_error(state
, info
->tuple
, "lhs to small?");
8965 get_occurance(info
->occurance
);
8966 load
= alloc_triple(state
, OP_LOAD
, type
, -1, -1, info
->occurance
);
8967 RHS(load
, 0) = mk_addr_expr(state
, info
->lval
, mem_offset
);
8968 LHS(info
->tuple
, reg_offset
/REG_SIZEOF_REG
) = load
;
8971 static struct triple
*decompose_load(struct compile_state
*state
,
8974 struct triple
*tuple
;
8975 struct decompose_load_info info
;
8977 if (!is_compound_type(ins
->type
)) {
8980 get_occurance(ins
->occurance
);
8981 tuple
= alloc_triple(state
, OP_TUPLE
, ins
->type
, -1, -1,
8984 info
.occurance
= ins
->occurance
;
8985 info
.lval
= RHS(ins
, 0);
8987 walk_type_fields(state
, ins
->type
, 0, 0, decompose_load_cb
, &info
);
8989 return decompose_with_tuple(state
, ins
, tuple
);
8993 struct decompose_store_info
{
8994 struct occurance
*occurance
;
8995 struct triple
*lval
;
8997 struct triple
*tuple
;
8999 static void decompose_store_cb(struct compile_state
*state
,
9000 struct type
*type
, size_t reg_offset
, size_t mem_offset
, void *arg
)
9002 struct decompose_store_info
*info
= arg
;
9003 struct triple
*store
;
9005 if (reg_offset
> info
->tuple
->lhs
) {
9006 internal_error(state
, info
->tuple
, "lhs to small?");
9008 get_occurance(info
->occurance
);
9009 store
= alloc_triple(state
, OP_STORE
, type
, -1, -1, info
->occurance
);
9010 RHS(store
, 0) = mk_addr_expr(state
, info
->lval
, mem_offset
);
9011 RHS(store
, 1) = LHS(info
->val
, reg_offset
);
9012 LHS(info
->tuple
, reg_offset
/REG_SIZEOF_REG
) = store
;
9015 static struct triple
*decompose_store(struct compile_state
*state
,
9018 struct triple
*tuple
;
9019 struct decompose_store_info info
;
9021 if (!is_compound_type(ins
->type
)) {
9024 get_occurance(ins
->occurance
);
9025 tuple
= alloc_triple(state
, OP_TUPLE
, ins
->type
, -1, -1,
9028 info
.occurance
= ins
->occurance
;
9029 info
.lval
= RHS(ins
, 0);
9030 info
.val
= RHS(ins
, 1);
9032 walk_type_fields(state
, ins
->type
, 0, 0, decompose_store_cb
, &info
);
9034 return decompose_with_tuple(state
, ins
, tuple
);
9037 static struct triple
*decompose_dot(struct compile_state
*state
,
9040 struct triple
*tuple
, *lval
;
9045 lval
= MISC(ins
, 0);
9046 reg_offset
= field_reg_offset(state
, lval
->type
, ins
->u
.field
);
9047 idx
= reg_offset
/REG_SIZEOF_REG
;
9048 type
= field_type(state
, lval
->type
, ins
->u
.field
);
9049 #if DEBUG_DECOMPOSE_HIRES
9051 FILE *fp
= state
->dbgout
;
9052 fprintf(fp
, "field type: ");
9058 get_occurance(ins
->occurance
);
9059 tuple
= alloc_triple(state
, OP_TUPLE
, type
, -1, -1,
9062 if (((ins
->type
->type
& TYPE_MASK
) == TYPE_BITFIELD
) &&
9065 internal_error(state
, ins
, "multi register bitfield?");
9068 for(i
= 0; i
< tuple
->lhs
; i
++, idx
++) {
9069 struct triple
*piece
;
9070 if (!triple_is_def(state
, lval
)) {
9071 if (idx
> lval
->lhs
) {
9072 internal_error(state
, ins
, "inconsistent lhs count");
9074 piece
= LHS(lval
, idx
);
9077 internal_error(state
, ins
, "bad reg_offset into def");
9080 internal_error(state
, ins
, "bad reg count from def");
9085 /* Remember the offset of the bitfield */
9086 if ((type
->type
& TYPE_MASK
) == TYPE_BITFIELD
) {
9087 get_occurance(ins
->occurance
);
9088 piece
= build_triple(state
, OP_BITREF
, type
, piece
, 0,
9090 piece
->u
.bitfield
.size
= size_of(state
, type
);
9091 piece
->u
.bitfield
.offset
= reg_offset
% REG_SIZEOF_REG
;
9093 else if ((reg_offset
% REG_SIZEOF_REG
) != 0) {
9094 internal_error(state
, ins
,
9095 "request for a nonbitfield sub register?");
9098 LHS(tuple
, i
) = piece
;
9101 return decompose_with_tuple(state
, ins
, tuple
);
9104 static struct triple
*decompose_index(struct compile_state
*state
,
9107 struct triple
*tuple
, *lval
;
9111 lval
= MISC(ins
, 0);
9112 idx
= index_reg_offset(state
, lval
->type
, ins
->u
.cval
)/REG_SIZEOF_REG
;
9113 type
= index_type(state
, lval
->type
, ins
->u
.cval
);
9114 #if DEBUG_DECOMPOSE_HIRES
9116 FILE *fp
= state
->dbgout
;
9117 fprintf(fp
, "index type: ");
9123 get_occurance(ins
->occurance
);
9124 tuple
= alloc_triple(state
, OP_TUPLE
, type
, -1, -1,
9127 for(i
= 0; i
< tuple
->lhs
; i
++, idx
++) {
9128 struct triple
*piece
;
9129 if (!triple_is_def(state
, lval
)) {
9130 if (idx
> lval
->lhs
) {
9131 internal_error(state
, ins
, "inconsistent lhs count");
9133 piece
= LHS(lval
, idx
);
9136 internal_error(state
, ins
, "bad reg_offset into def");
9139 internal_error(state
, ins
, "bad reg count from def");
9143 LHS(tuple
, i
) = piece
;
9146 return decompose_with_tuple(state
, ins
, tuple
);
9149 static void decompose_compound_types(struct compile_state
*state
)
9151 struct triple
*ins
, *next
, *first
;
9152 first
= state
->first
;
9155 /* Pass one expand compound values into pseudo registers.
9163 next
= decompose_unknownval(state
, ins
);
9167 next
= decompose_read(state
, ins
);
9171 next
= decompose_write(state
, ins
);
9175 /* Be very careful with the load/store logic. These
9176 * operations must convert from the in register layout
9177 * to the in memory layout, which is nontrivial.
9180 next
= decompose_load(state
, ins
);
9183 next
= decompose_store(state
, ins
);
9187 next
= decompose_dot(state
, ins
);
9190 next
= decompose_index(state
, ins
);
9194 #if DEBUG_DECOMPOSE_HIRES
9195 fprintf(fp
, "decompose next: %p \n", next
);
9197 fprintf(fp
, "next->op: %d %s\n",
9198 next
->op
, tops(next
->op
));
9199 /* High resolution debugging mode */
9200 print_triples(state
);
9202 } while (next
!= first
);
9204 /* Pass two remove the tuples.
9209 if (ins
->op
== OP_TUPLE
) {
9211 internal_error(state
, ins
, "tuple used");
9214 release_triple(state
, ins
);
9218 } while(ins
!= first
);
9222 if (ins
->op
== OP_BITREF
) {
9224 internal_error(state
, ins
, "bitref used");
9227 release_triple(state
, ins
);
9231 } while(ins
!= first
);
9233 /* Pass three verify the state and set ->id to 0.
9239 ins
->id
&= ~TRIPLE_FLAG_FLATTENED
;
9240 if (triple_stores_block(state
, ins
)) {
9243 if (triple_is_def(state
, ins
)) {
9244 if (reg_size_of(state
, ins
->type
) > REG_SIZEOF_REG
) {
9245 internal_error(state
, ins
, "multi register value remains?");
9248 if (ins
->op
== OP_DOT
) {
9249 internal_error(state
, ins
, "OP_DOT remains?");
9251 if (ins
->op
== OP_INDEX
) {
9252 internal_error(state
, ins
, "OP_INDEX remains?");
9254 if (ins
->op
== OP_BITREF
) {
9255 internal_error(state
, ins
, "OP_BITREF remains?");
9257 if (ins
->op
== OP_TUPLE
) {
9258 internal_error(state
, ins
, "OP_TUPLE remains?");
9260 } while(next
!= first
);
9263 /* For those operations that cannot be simplified */
9264 static void simplify_noop(struct compile_state
*state
, struct triple
*ins
)
9269 static void simplify_smul(struct compile_state
*state
, struct triple
*ins
)
9271 if (is_const(RHS(ins
, 0)) && !is_const(RHS(ins
, 1))) {
9274 RHS(ins
, 0) = RHS(ins
, 1);
9277 if (is_const(RHS(ins
, 0)) && is_const(RHS(ins
, 1))) {
9279 left
= read_sconst(state
, ins
, RHS(ins
, 0));
9280 right
= read_sconst(state
, ins
, RHS(ins
, 1));
9281 mkconst(state
, ins
, left
* right
);
9283 else if (is_zero(RHS(ins
, 1))) {
9284 mkconst(state
, ins
, 0);
9286 else if (is_one(RHS(ins
, 1))) {
9287 mkcopy(state
, ins
, RHS(ins
, 0));
9289 else if (is_pow2(RHS(ins
, 1))) {
9291 val
= int_const(state
, ins
->type
, tlog2(RHS(ins
, 1)));
9293 insert_triple(state
, state
->global_pool
, val
);
9294 unuse_triple(RHS(ins
, 1), ins
);
9295 use_triple(val
, ins
);
9300 static void simplify_umul(struct compile_state
*state
, struct triple
*ins
)
9302 if (is_const(RHS(ins
, 0)) && !is_const(RHS(ins
, 1))) {
9305 RHS(ins
, 0) = RHS(ins
, 1);
9308 if (is_simple_const(RHS(ins
, 0)) && is_simple_const(RHS(ins
, 1))) {
9309 ulong_t left
, right
;
9310 left
= read_const(state
, ins
, RHS(ins
, 0));
9311 right
= read_const(state
, ins
, RHS(ins
, 1));
9312 mkconst(state
, ins
, left
* right
);
9314 else if (is_zero(RHS(ins
, 1))) {
9315 mkconst(state
, ins
, 0);
9317 else if (is_one(RHS(ins
, 1))) {
9318 mkcopy(state
, ins
, RHS(ins
, 0));
9320 else if (is_pow2(RHS(ins
, 1))) {
9322 val
= int_const(state
, ins
->type
, tlog2(RHS(ins
, 1)));
9324 insert_triple(state
, state
->global_pool
, val
);
9325 unuse_triple(RHS(ins
, 1), ins
);
9326 use_triple(val
, ins
);
9331 static void simplify_sdiv(struct compile_state
*state
, struct triple
*ins
)
9333 if (is_const(RHS(ins
, 0)) && is_const(RHS(ins
, 1))) {
9335 left
= read_sconst(state
, ins
, RHS(ins
, 0));
9336 right
= read_sconst(state
, ins
, RHS(ins
, 1));
9337 mkconst(state
, ins
, left
/ right
);
9339 else if (is_zero(RHS(ins
, 0))) {
9340 mkconst(state
, ins
, 0);
9342 else if (is_zero(RHS(ins
, 1))) {
9343 error(state
, ins
, "division by zero");
9345 else if (is_one(RHS(ins
, 1))) {
9346 mkcopy(state
, ins
, RHS(ins
, 0));
9348 else if (is_pow2(RHS(ins
, 1))) {
9350 val
= int_const(state
, ins
->type
, tlog2(RHS(ins
, 1)));
9352 insert_triple(state
, state
->global_pool
, val
);
9353 unuse_triple(RHS(ins
, 1), ins
);
9354 use_triple(val
, ins
);
9359 static void simplify_udiv(struct compile_state
*state
, struct triple
*ins
)
9361 if (is_simple_const(RHS(ins
, 0)) && is_simple_const(RHS(ins
, 1))) {
9362 ulong_t left
, right
;
9363 left
= read_const(state
, ins
, RHS(ins
, 0));
9364 right
= read_const(state
, ins
, RHS(ins
, 1));
9365 mkconst(state
, ins
, left
/ right
);
9367 else if (is_zero(RHS(ins
, 0))) {
9368 mkconst(state
, ins
, 0);
9370 else if (is_zero(RHS(ins
, 1))) {
9371 error(state
, ins
, "division by zero");
9373 else if (is_one(RHS(ins
, 1))) {
9374 mkcopy(state
, ins
, RHS(ins
, 0));
9376 else if (is_pow2(RHS(ins
, 1))) {
9378 val
= int_const(state
, ins
->type
, tlog2(RHS(ins
, 1)));
9380 insert_triple(state
, state
->global_pool
, val
);
9381 unuse_triple(RHS(ins
, 1), ins
);
9382 use_triple(val
, ins
);
9387 static void simplify_smod(struct compile_state
*state
, struct triple
*ins
)
9389 if (is_simple_const(RHS(ins
, 0)) && is_simple_const(RHS(ins
, 1))) {
9391 left
= read_const(state
, ins
, RHS(ins
, 0));
9392 right
= read_const(state
, ins
, RHS(ins
, 1));
9393 mkconst(state
, ins
, left
% right
);
9395 else if (is_zero(RHS(ins
, 0))) {
9396 mkconst(state
, ins
, 0);
9398 else if (is_zero(RHS(ins
, 1))) {
9399 error(state
, ins
, "division by zero");
9401 else if (is_one(RHS(ins
, 1))) {
9402 mkconst(state
, ins
, 0);
9404 else if (is_pow2(RHS(ins
, 1))) {
9406 val
= int_const(state
, ins
->type
, RHS(ins
, 1)->u
.cval
- 1);
9408 insert_triple(state
, state
->global_pool
, val
);
9409 unuse_triple(RHS(ins
, 1), ins
);
9410 use_triple(val
, ins
);
9415 static void simplify_umod(struct compile_state
*state
, struct triple
*ins
)
9417 if (is_simple_const(RHS(ins
, 0)) && is_simple_const(RHS(ins
, 1))) {
9418 ulong_t left
, right
;
9419 left
= read_const(state
, ins
, RHS(ins
, 0));
9420 right
= read_const(state
, ins
, RHS(ins
, 1));
9421 mkconst(state
, ins
, left
% right
);
9423 else if (is_zero(RHS(ins
, 0))) {
9424 mkconst(state
, ins
, 0);
9426 else if (is_zero(RHS(ins
, 1))) {
9427 error(state
, ins
, "division by zero");
9429 else if (is_one(RHS(ins
, 1))) {
9430 mkconst(state
, ins
, 0);
9432 else if (is_pow2(RHS(ins
, 1))) {
9434 val
= int_const(state
, ins
->type
, RHS(ins
, 1)->u
.cval
- 1);
9436 insert_triple(state
, state
->global_pool
, val
);
9437 unuse_triple(RHS(ins
, 1), ins
);
9438 use_triple(val
, ins
);
9443 static void simplify_add(struct compile_state
*state
, struct triple
*ins
)
9445 /* start with the pointer on the left */
9446 if (is_pointer(RHS(ins
, 1))) {
9449 RHS(ins
, 0) = RHS(ins
, 1);
9452 if (is_const(RHS(ins
, 0)) && is_simple_const(RHS(ins
, 1))) {
9453 if (RHS(ins
, 0)->op
== OP_INTCONST
) {
9454 ulong_t left
, right
;
9455 left
= read_const(state
, ins
, RHS(ins
, 0));
9456 right
= read_const(state
, ins
, RHS(ins
, 1));
9457 mkconst(state
, ins
, left
+ right
);
9459 else if (RHS(ins
, 0)->op
== OP_ADDRCONST
) {
9460 struct triple
*sdecl
;
9461 ulong_t left
, right
;
9462 sdecl
= MISC(RHS(ins
, 0), 0);
9463 left
= RHS(ins
, 0)->u
.cval
;
9464 right
= RHS(ins
, 1)->u
.cval
;
9465 mkaddr_const(state
, ins
, sdecl
, left
+ right
);
9468 internal_warning(state
, ins
, "Optimize me!");
9471 else if (is_const(RHS(ins
, 0)) && !is_const(RHS(ins
, 1))) {
9474 RHS(ins
, 1) = RHS(ins
, 0);
9479 static void simplify_sub(struct compile_state
*state
, struct triple
*ins
)
9481 if (is_const(RHS(ins
, 0)) && is_simple_const(RHS(ins
, 1))) {
9482 if (RHS(ins
, 0)->op
== OP_INTCONST
) {
9483 ulong_t left
, right
;
9484 left
= read_const(state
, ins
, RHS(ins
, 0));
9485 right
= read_const(state
, ins
, RHS(ins
, 1));
9486 mkconst(state
, ins
, left
- right
);
9488 else if (RHS(ins
, 0)->op
== OP_ADDRCONST
) {
9489 struct triple
*sdecl
;
9490 ulong_t left
, right
;
9491 sdecl
= MISC(RHS(ins
, 0), 0);
9492 left
= RHS(ins
, 0)->u
.cval
;
9493 right
= RHS(ins
, 1)->u
.cval
;
9494 mkaddr_const(state
, ins
, sdecl
, left
- right
);
9497 internal_warning(state
, ins
, "Optimize me!");
9502 static void simplify_sl(struct compile_state
*state
, struct triple
*ins
)
9504 if (is_simple_const(RHS(ins
, 1))) {
9506 right
= read_const(state
, ins
, RHS(ins
, 1));
9507 if (right
>= (size_of(state
, ins
->type
))) {
9508 warning(state
, ins
, "left shift count >= width of type");
9511 if (is_simple_const(RHS(ins
, 0)) && is_simple_const(RHS(ins
, 1))) {
9512 ulong_t left
, right
;
9513 left
= read_const(state
, ins
, RHS(ins
, 0));
9514 right
= read_const(state
, ins
, RHS(ins
, 1));
9515 mkconst(state
, ins
, left
<< right
);
9519 static void simplify_usr(struct compile_state
*state
, struct triple
*ins
)
9521 if (is_simple_const(RHS(ins
, 1))) {
9523 right
= read_const(state
, ins
, RHS(ins
, 1));
9524 if (right
>= (size_of(state
, ins
->type
))) {
9525 warning(state
, ins
, "right shift count >= width of type");
9528 if (is_simple_const(RHS(ins
, 0)) && is_simple_const(RHS(ins
, 1))) {
9529 ulong_t left
, right
;
9530 left
= read_const(state
, ins
, RHS(ins
, 0));
9531 right
= read_const(state
, ins
, RHS(ins
, 1));
9532 mkconst(state
, ins
, left
>> right
);
9536 static void simplify_ssr(struct compile_state
*state
, struct triple
*ins
)
9538 if (is_simple_const(RHS(ins
, 1))) {
9540 right
= read_const(state
, ins
, RHS(ins
, 1));
9541 if (right
>= (size_of(state
, ins
->type
))) {
9542 warning(state
, ins
, "right shift count >= width of type");
9545 if (is_simple_const(RHS(ins
, 0)) && is_simple_const(RHS(ins
, 1))) {
9547 left
= read_sconst(state
, ins
, RHS(ins
, 0));
9548 right
= read_sconst(state
, ins
, RHS(ins
, 1));
9549 mkconst(state
, ins
, left
>> right
);
9553 static void simplify_and(struct compile_state
*state
, struct triple
*ins
)
9555 struct triple
*left
, *right
;
9557 right
= RHS(ins
, 1);
9559 if (is_simple_const(left
) && is_simple_const(right
)) {
9561 lval
= read_const(state
, ins
, left
);
9562 rval
= read_const(state
, ins
, right
);
9563 mkconst(state
, ins
, lval
& rval
);
9565 else if (is_zero(right
) || is_zero(left
)) {
9566 mkconst(state
, ins
, 0);
9570 static void simplify_or(struct compile_state
*state
, struct triple
*ins
)
9572 struct triple
*left
, *right
;
9574 right
= RHS(ins
, 1);
9576 if (is_simple_const(left
) && is_simple_const(right
)) {
9578 lval
= read_const(state
, ins
, left
);
9579 rval
= read_const(state
, ins
, right
);
9580 mkconst(state
, ins
, lval
| rval
);
9582 #if 0 /* I need to handle type mismatches here... */
9583 else if (is_zero(right
)) {
9584 mkcopy(state
, ins
, left
);
9586 else if (is_zero(left
)) {
9587 mkcopy(state
, ins
, right
);
9592 static void simplify_xor(struct compile_state
*state
, struct triple
*ins
)
9594 if (is_simple_const(RHS(ins
, 0)) && is_simple_const(RHS(ins
, 1))) {
9595 ulong_t left
, right
;
9596 left
= read_const(state
, ins
, RHS(ins
, 0));
9597 right
= read_const(state
, ins
, RHS(ins
, 1));
9598 mkconst(state
, ins
, left
^ right
);
9602 static void simplify_pos(struct compile_state
*state
, struct triple
*ins
)
9604 if (is_const(RHS(ins
, 0))) {
9605 mkconst(state
, ins
, RHS(ins
, 0)->u
.cval
);
9608 mkcopy(state
, ins
, RHS(ins
, 0));
9612 static void simplify_neg(struct compile_state
*state
, struct triple
*ins
)
9614 if (is_simple_const(RHS(ins
, 0))) {
9616 left
= read_const(state
, ins
, RHS(ins
, 0));
9617 mkconst(state
, ins
, -left
);
9619 else if (RHS(ins
, 0)->op
== OP_NEG
) {
9620 mkcopy(state
, ins
, RHS(RHS(ins
, 0), 0));
9624 static void simplify_invert(struct compile_state
*state
, struct triple
*ins
)
9626 if (is_simple_const(RHS(ins
, 0))) {
9628 left
= read_const(state
, ins
, RHS(ins
, 0));
9629 mkconst(state
, ins
, ~left
);
9633 static void simplify_eq(struct compile_state
*state
, struct triple
*ins
)
9635 struct triple
*left
, *right
;
9637 right
= RHS(ins
, 1);
9639 if (is_const(left
) && is_const(right
)) {
9641 val
= const_eq(state
, ins
, left
, right
);
9643 mkconst(state
, ins
, val
== 1);
9646 else if (left
== right
) {
9647 mkconst(state
, ins
, 1);
9651 static void simplify_noteq(struct compile_state
*state
, struct triple
*ins
)
9653 struct triple
*left
, *right
;
9655 right
= RHS(ins
, 1);
9657 if (is_const(left
) && is_const(right
)) {
9659 val
= const_eq(state
, ins
, left
, right
);
9661 mkconst(state
, ins
, val
!= 1);
9664 if (left
== right
) {
9665 mkconst(state
, ins
, 0);
9669 static void simplify_sless(struct compile_state
*state
, struct triple
*ins
)
9671 struct triple
*left
, *right
;
9673 right
= RHS(ins
, 1);
9675 if (is_const(left
) && is_const(right
)) {
9677 val
= const_scmp(state
, ins
, left
, right
);
9678 if ((val
>= -1) && (val
<= 1)) {
9679 mkconst(state
, ins
, val
< 0);
9682 else if (left
== right
) {
9683 mkconst(state
, ins
, 0);
9687 static void simplify_uless(struct compile_state
*state
, struct triple
*ins
)
9689 struct triple
*left
, *right
;
9691 right
= RHS(ins
, 1);
9693 if (is_const(left
) && is_const(right
)) {
9695 val
= const_ucmp(state
, ins
, left
, right
);
9696 if ((val
>= -1) && (val
<= 1)) {
9697 mkconst(state
, ins
, val
< 0);
9700 else if (is_zero(right
)) {
9701 mkconst(state
, ins
, 0);
9703 else if (left
== right
) {
9704 mkconst(state
, ins
, 0);
9708 static void simplify_smore(struct compile_state
*state
, struct triple
*ins
)
9710 struct triple
*left
, *right
;
9712 right
= RHS(ins
, 1);
9714 if (is_const(left
) && is_const(right
)) {
9716 val
= const_scmp(state
, ins
, left
, right
);
9717 if ((val
>= -1) && (val
<= 1)) {
9718 mkconst(state
, ins
, val
> 0);
9721 else if (left
== right
) {
9722 mkconst(state
, ins
, 0);
9726 static void simplify_umore(struct compile_state
*state
, struct triple
*ins
)
9728 struct triple
*left
, *right
;
9730 right
= RHS(ins
, 1);
9732 if (is_const(left
) && is_const(right
)) {
9734 val
= const_ucmp(state
, ins
, left
, right
);
9735 if ((val
>= -1) && (val
<= 1)) {
9736 mkconst(state
, ins
, val
> 0);
9739 else if (is_zero(left
)) {
9740 mkconst(state
, ins
, 0);
9742 else if (left
== right
) {
9743 mkconst(state
, ins
, 0);
9748 static void simplify_slesseq(struct compile_state
*state
, struct triple
*ins
)
9750 struct triple
*left
, *right
;
9752 right
= RHS(ins
, 1);
9754 if (is_const(left
) && is_const(right
)) {
9756 val
= const_scmp(state
, ins
, left
, right
);
9757 if ((val
>= -1) && (val
<= 1)) {
9758 mkconst(state
, ins
, val
<= 0);
9761 else if (left
== right
) {
9762 mkconst(state
, ins
, 1);
9766 static void simplify_ulesseq(struct compile_state
*state
, struct triple
*ins
)
9768 struct triple
*left
, *right
;
9770 right
= RHS(ins
, 1);
9772 if (is_const(left
) && is_const(right
)) {
9774 val
= const_ucmp(state
, ins
, left
, right
);
9775 if ((val
>= -1) && (val
<= 1)) {
9776 mkconst(state
, ins
, val
<= 0);
9779 else if (is_zero(left
)) {
9780 mkconst(state
, ins
, 1);
9782 else if (left
== right
) {
9783 mkconst(state
, ins
, 1);
9787 static void simplify_smoreeq(struct compile_state
*state
, struct triple
*ins
)
9789 struct triple
*left
, *right
;
9791 right
= RHS(ins
, 1);
9793 if (is_const(left
) && is_const(right
)) {
9795 val
= const_scmp(state
, ins
, left
, right
);
9796 if ((val
>= -1) && (val
<= 1)) {
9797 mkconst(state
, ins
, val
>= 0);
9800 else if (left
== right
) {
9801 mkconst(state
, ins
, 1);
9805 static void simplify_umoreeq(struct compile_state
*state
, struct triple
*ins
)
9807 struct triple
*left
, *right
;
9809 right
= RHS(ins
, 1);
9811 if (is_const(left
) && is_const(right
)) {
9813 val
= const_ucmp(state
, ins
, left
, right
);
9814 if ((val
>= -1) && (val
<= 1)) {
9815 mkconst(state
, ins
, val
>= 0);
9818 else if (is_zero(right
)) {
9819 mkconst(state
, ins
, 1);
9821 else if (left
== right
) {
9822 mkconst(state
, ins
, 1);
9826 static void simplify_lfalse(struct compile_state
*state
, struct triple
*ins
)
9831 if (is_const(rhs
)) {
9832 mkconst(state
, ins
, !const_ltrue(state
, ins
, rhs
));
9834 /* Otherwise if I am the only user... */
9835 else if ((rhs
->use
) &&
9836 (rhs
->use
->member
== ins
) && (rhs
->use
->next
== 0)) {
9838 /* Invert a boolean operation */
9840 case OP_LTRUE
: rhs
->op
= OP_LFALSE
; break;
9841 case OP_LFALSE
: rhs
->op
= OP_LTRUE
; break;
9842 case OP_EQ
: rhs
->op
= OP_NOTEQ
; break;
9843 case OP_NOTEQ
: rhs
->op
= OP_EQ
; break;
9844 case OP_SLESS
: rhs
->op
= OP_SMOREEQ
; break;
9845 case OP_ULESS
: rhs
->op
= OP_UMOREEQ
; break;
9846 case OP_SMORE
: rhs
->op
= OP_SLESSEQ
; break;
9847 case OP_UMORE
: rhs
->op
= OP_ULESSEQ
; break;
9848 case OP_SLESSEQ
: rhs
->op
= OP_SMORE
; break;
9849 case OP_ULESSEQ
: rhs
->op
= OP_UMORE
; break;
9850 case OP_SMOREEQ
: rhs
->op
= OP_SLESS
; break;
9851 case OP_UMOREEQ
: rhs
->op
= OP_ULESS
; break;
9857 mkcopy(state
, ins
, rhs
);
9862 static void simplify_ltrue (struct compile_state
*state
, struct triple
*ins
)
9867 if (is_const(rhs
)) {
9868 mkconst(state
, ins
, const_ltrue(state
, ins
, rhs
));
9870 else switch(rhs
->op
) {
9871 case OP_LTRUE
: case OP_LFALSE
: case OP_EQ
: case OP_NOTEQ
:
9872 case OP_SLESS
: case OP_ULESS
: case OP_SMORE
: case OP_UMORE
:
9873 case OP_SLESSEQ
: case OP_ULESSEQ
: case OP_SMOREEQ
: case OP_UMOREEQ
:
9874 mkcopy(state
, ins
, rhs
);
9879 static void simplify_load(struct compile_state
*state
, struct triple
*ins
)
9881 struct triple
*addr
, *sdecl
, *blob
;
9883 /* If I am doing a load with a constant pointer from a constant
9884 * table get the value.
9887 if ((addr
->op
== OP_ADDRCONST
) && (sdecl
= MISC(addr
, 0)) &&
9888 (sdecl
->op
== OP_SDECL
) && (blob
= MISC(sdecl
, 0)) &&
9889 (blob
->op
== OP_BLOBCONST
)) {
9890 unsigned char buffer
[SIZEOF_WORD
];
9891 size_t reg_size
, mem_size
;
9892 const char *src
, *end
;
9894 reg_size
= reg_size_of(state
, ins
->type
);
9895 if (reg_size
> REG_SIZEOF_REG
) {
9896 internal_error(state
, ins
, "load size greater than register");
9898 mem_size
= size_of(state
, ins
->type
);
9900 end
+= bits_to_bytes(size_of(state
, sdecl
->type
));
9902 src
+= addr
->u
.cval
;
9905 error(state
, ins
, "Load address out of bounds");
9908 memset(buffer
, 0, sizeof(buffer
));
9909 memcpy(buffer
, src
, bits_to_bytes(mem_size
));
9912 case SIZEOF_I8
: val
= *((uint8_t *) buffer
); break;
9913 case SIZEOF_I16
: val
= *((uint16_t *)buffer
); break;
9914 case SIZEOF_I32
: val
= *((uint32_t *)buffer
); break;
9915 case SIZEOF_I64
: val
= *((uint64_t *)buffer
); break;
9917 internal_error(state
, ins
, "mem_size: %d not handled",
9922 mkconst(state
, ins
, val
);
9926 static void simplify_uextract(struct compile_state
*state
, struct triple
*ins
)
9928 if (is_simple_const(RHS(ins
, 0))) {
9931 val
= read_const(state
, ins
, RHS(ins
, 0));
9933 mask
<<= ins
->u
.bitfield
.size
;
9935 val
>>= ins
->u
.bitfield
.offset
;
9937 mkconst(state
, ins
, val
);
9941 static void simplify_sextract(struct compile_state
*state
, struct triple
*ins
)
9943 if (is_simple_const(RHS(ins
, 0))) {
9947 val
= read_const(state
, ins
, RHS(ins
, 0));
9949 mask
<<= ins
->u
.bitfield
.size
;
9951 val
>>= ins
->u
.bitfield
.offset
;
9953 val
<<= (SIZEOF_LONG
- ins
->u
.bitfield
.size
);
9955 sval
>>= (SIZEOF_LONG
- ins
->u
.bitfield
.size
);
9956 mkconst(state
, ins
, sval
);
9960 static void simplify_deposit(struct compile_state
*state
, struct triple
*ins
)
9962 if (is_simple_const(RHS(ins
, 0)) && is_simple_const(RHS(ins
, 1))) {
9965 targ
= read_const(state
, ins
, RHS(ins
, 0));
9966 val
= read_const(state
, ins
, RHS(ins
, 1));
9968 mask
<<= ins
->u
.bitfield
.size
;
9970 mask
<<= ins
->u
.bitfield
.offset
;
9972 val
<<= ins
->u
.bitfield
.offset
;
9975 mkconst(state
, ins
, targ
);
9979 static void simplify_copy(struct compile_state
*state
, struct triple
*ins
)
9981 struct triple
*right
;
9982 right
= RHS(ins
, 0);
9983 if (is_subset_type(ins
->type
, right
->type
)) {
9984 ins
->type
= right
->type
;
9986 if (equiv_types(ins
->type
, right
->type
)) {
9987 ins
->op
= OP_COPY
;/* I don't need to convert if the types match */
9989 if (ins
->op
== OP_COPY
) {
9990 internal_error(state
, ins
, "type mismatch on copy");
9993 if (is_const(right
) && (right
->op
== OP_ADDRCONST
) && is_pointer(ins
)) {
9994 struct triple
*sdecl
;
9996 sdecl
= MISC(right
, 0);
9997 offset
= right
->u
.cval
;
9998 mkaddr_const(state
, ins
, sdecl
, offset
);
10000 else if (is_const(right
) && is_write_compatible(state
, ins
->type
, right
->type
)) {
10001 switch(right
->op
) {
10005 left
= read_const(state
, ins
, right
);
10006 /* Ensure I have not overflowed the destination. */
10007 if (size_of(state
, right
->type
) > size_of(state
, ins
->type
)) {
10010 mask
<<= size_of(state
, ins
->type
);
10014 /* Ensure I am properly sign extended */
10015 if (size_of(state
, right
->type
) < size_of(state
, ins
->type
) &&
10016 is_signed(right
->type
)) {
10019 shift
= SIZEOF_LONG
- size_of(state
, right
->type
);
10025 mkconst(state
, ins
, left
);
10029 internal_error(state
, ins
, "uknown constant");
10035 static int phi_present(struct block
*block
)
10037 struct triple
*ptr
;
10041 ptr
= block
->first
;
10043 if (ptr
->op
== OP_PHI
) {
10047 } while(ptr
!= block
->last
);
10051 static int phi_dependency(struct block
*block
)
10053 /* A block has a phi dependency if a phi function
10054 * depends on that block to exist, and makes a block
10055 * that is otherwise useless unsafe to remove.
10058 struct block_set
*edge
;
10059 for(edge
= block
->edges
; edge
; edge
= edge
->next
) {
10060 if (phi_present(edge
->member
)) {
10068 static struct triple
*branch_target(struct compile_state
*state
, struct triple
*ins
)
10070 struct triple
*targ
;
10071 targ
= TARG(ins
, 0);
10072 /* During scc_transform temporary triples are allocated that
10073 * loop back onto themselves. If I see one don't advance the
10076 while(triple_is_structural(state
, targ
) &&
10077 (targ
->next
!= targ
) && (targ
->next
!= state
->first
)) {
10084 static void simplify_branch(struct compile_state
*state
, struct triple
*ins
)
10086 int simplified
, loops
;
10087 if ((ins
->op
!= OP_BRANCH
) && (ins
->op
!= OP_CBRANCH
)) {
10088 internal_error(state
, ins
, "not branch");
10090 if (ins
->use
!= 0) {
10091 internal_error(state
, ins
, "branch use");
10093 /* The challenge here with simplify branch is that I need to
10094 * make modifications to the control flow graph as well
10095 * as to the branch instruction itself. That is handled
10096 * by rebuilding the basic blocks after simplify all is called.
10099 /* If we have a branch to an unconditional branch update
10100 * our target. But watch out for dependencies from phi
10102 * Also only do this a limited number of times so
10103 * we don't get into an infinite loop.
10107 struct triple
*targ
;
10109 targ
= branch_target(state
, ins
);
10110 if ((targ
!= ins
) && (targ
->op
== OP_BRANCH
) &&
10111 !phi_dependency(targ
->u
.block
))
10113 unuse_triple(TARG(ins
, 0), ins
);
10114 TARG(ins
, 0) = TARG(targ
, 0);
10115 use_triple(TARG(ins
, 0), ins
);
10118 } while(simplified
&& (++loops
< 20));
10120 /* If we have a conditional branch with a constant condition
10121 * make it an unconditional branch.
10123 if ((ins
->op
== OP_CBRANCH
) && is_simple_const(RHS(ins
, 0))) {
10124 struct triple
*targ
;
10126 value
= read_const(state
, ins
, RHS(ins
, 0));
10127 unuse_triple(RHS(ins
, 0), ins
);
10128 targ
= TARG(ins
, 0);
10131 ins
->op
= OP_BRANCH
;
10133 unuse_triple(ins
->next
, ins
);
10134 TARG(ins
, 0) = targ
;
10137 unuse_triple(targ
, ins
);
10138 TARG(ins
, 0) = ins
->next
;
10142 /* If we have a branch to the next instruction,
10145 if (TARG(ins
, 0) == ins
->next
) {
10146 unuse_triple(TARG(ins
, 0), ins
);
10147 if (ins
->op
== OP_CBRANCH
) {
10148 unuse_triple(RHS(ins
, 0), ins
);
10149 unuse_triple(ins
->next
, ins
);
10157 internal_error(state
, ins
, "noop use != 0");
10162 static void simplify_label(struct compile_state
*state
, struct triple
*ins
)
10164 /* Ignore volatile labels */
10165 if (!triple_is_pure(state
, ins
, ins
->id
)) {
10168 if (ins
->use
== 0) {
10171 else if (ins
->prev
->op
== OP_LABEL
) {
10172 /* In general it is not safe to merge one label that
10173 * imediately follows another. The problem is that the empty
10174 * looking block may have phi functions that depend on it.
10176 if (!phi_dependency(ins
->prev
->u
.block
)) {
10177 struct triple_set
*user
, *next
;
10179 for(user
= ins
->use
; user
; user
= next
) {
10180 struct triple
*use
, **expr
;
10182 use
= user
->member
;
10183 expr
= triple_targ(state
, use
, 0);
10184 for(;expr
; expr
= triple_targ(state
, use
, expr
)) {
10185 if (*expr
== ins
) {
10187 unuse_triple(ins
, use
);
10188 use_triple(ins
->prev
, use
);
10194 internal_error(state
, ins
, "noop use != 0");
10200 static void simplify_phi(struct compile_state
*state
, struct triple
*ins
)
10202 struct triple
**slot
;
10203 struct triple
*value
;
10206 slot
= &RHS(ins
, 0);
10211 /* See if all of the rhs members of a phi have the same value */
10212 if (slot
[0] && is_simple_const(slot
[0])) {
10213 cvalue
= read_const(state
, ins
, slot
[0]);
10214 for(i
= 1; i
< zrhs
; i
++) {
10216 !is_simple_const(slot
[i
]) ||
10217 !equiv_types(slot
[0]->type
, slot
[i
]->type
) ||
10218 (cvalue
!= read_const(state
, ins
, slot
[i
]))) {
10223 mkconst(state
, ins
, cvalue
);
10228 /* See if all of rhs members of a phi are the same */
10230 for(i
= 1; i
< zrhs
; i
++) {
10231 if (slot
[i
] != value
) {
10236 /* If the phi has a single value just copy it */
10237 if (!is_subset_type(ins
->type
, value
->type
)) {
10238 internal_error(state
, ins
, "bad input type to phi");
10240 /* Make the types match */
10241 if (!equiv_types(ins
->type
, value
->type
)) {
10242 ins
->type
= value
->type
;
10244 /* Now make the actual copy */
10245 mkcopy(state
, ins
, value
);
10251 static void simplify_bsf(struct compile_state
*state
, struct triple
*ins
)
10253 if (is_simple_const(RHS(ins
, 0))) {
10255 left
= read_const(state
, ins
, RHS(ins
, 0));
10256 mkconst(state
, ins
, bsf(left
));
10260 static void simplify_bsr(struct compile_state
*state
, struct triple
*ins
)
10262 if (is_simple_const(RHS(ins
, 0))) {
10264 left
= read_const(state
, ins
, RHS(ins
, 0));
10265 mkconst(state
, ins
, bsr(left
));
10270 typedef void (*simplify_t
)(struct compile_state
*state
, struct triple
*ins
);
10271 static const struct simplify_table
{
10273 unsigned long flag
;
10274 } table_simplify
[] = {
10275 #define simplify_sdivt simplify_noop
10276 #define simplify_udivt simplify_noop
10277 #define simplify_piece simplify_noop
10279 [OP_SDIVT
] = { simplify_sdivt
, COMPILER_SIMPLIFY_ARITH
},
10280 [OP_UDIVT
] = { simplify_udivt
, COMPILER_SIMPLIFY_ARITH
},
10281 [OP_SMUL
] = { simplify_smul
, COMPILER_SIMPLIFY_ARITH
},
10282 [OP_UMUL
] = { simplify_umul
, COMPILER_SIMPLIFY_ARITH
},
10283 [OP_SDIV
] = { simplify_sdiv
, COMPILER_SIMPLIFY_ARITH
},
10284 [OP_UDIV
] = { simplify_udiv
, COMPILER_SIMPLIFY_ARITH
},
10285 [OP_SMOD
] = { simplify_smod
, COMPILER_SIMPLIFY_ARITH
},
10286 [OP_UMOD
] = { simplify_umod
, COMPILER_SIMPLIFY_ARITH
},
10287 [OP_ADD
] = { simplify_add
, COMPILER_SIMPLIFY_ARITH
},
10288 [OP_SUB
] = { simplify_sub
, COMPILER_SIMPLIFY_ARITH
},
10289 [OP_SL
] = { simplify_sl
, COMPILER_SIMPLIFY_SHIFT
},
10290 [OP_USR
] = { simplify_usr
, COMPILER_SIMPLIFY_SHIFT
},
10291 [OP_SSR
] = { simplify_ssr
, COMPILER_SIMPLIFY_SHIFT
},
10292 [OP_AND
] = { simplify_and
, COMPILER_SIMPLIFY_BITWISE
},
10293 [OP_XOR
] = { simplify_xor
, COMPILER_SIMPLIFY_BITWISE
},
10294 [OP_OR
] = { simplify_or
, COMPILER_SIMPLIFY_BITWISE
},
10295 [OP_POS
] = { simplify_pos
, COMPILER_SIMPLIFY_ARITH
},
10296 [OP_NEG
] = { simplify_neg
, COMPILER_SIMPLIFY_ARITH
},
10297 [OP_INVERT
] = { simplify_invert
, COMPILER_SIMPLIFY_BITWISE
},
10299 [OP_EQ
] = { simplify_eq
, COMPILER_SIMPLIFY_LOGICAL
},
10300 [OP_NOTEQ
] = { simplify_noteq
, COMPILER_SIMPLIFY_LOGICAL
},
10301 [OP_SLESS
] = { simplify_sless
, COMPILER_SIMPLIFY_LOGICAL
},
10302 [OP_ULESS
] = { simplify_uless
, COMPILER_SIMPLIFY_LOGICAL
},
10303 [OP_SMORE
] = { simplify_smore
, COMPILER_SIMPLIFY_LOGICAL
},
10304 [OP_UMORE
] = { simplify_umore
, COMPILER_SIMPLIFY_LOGICAL
},
10305 [OP_SLESSEQ
] = { simplify_slesseq
, COMPILER_SIMPLIFY_LOGICAL
},
10306 [OP_ULESSEQ
] = { simplify_ulesseq
, COMPILER_SIMPLIFY_LOGICAL
},
10307 [OP_SMOREEQ
] = { simplify_smoreeq
, COMPILER_SIMPLIFY_LOGICAL
},
10308 [OP_UMOREEQ
] = { simplify_umoreeq
, COMPILER_SIMPLIFY_LOGICAL
},
10309 [OP_LFALSE
] = { simplify_lfalse
, COMPILER_SIMPLIFY_LOGICAL
},
10310 [OP_LTRUE
] = { simplify_ltrue
, COMPILER_SIMPLIFY_LOGICAL
},
10312 [OP_LOAD
] = { simplify_load
, COMPILER_SIMPLIFY_OP
},
10313 [OP_STORE
] = { simplify_noop
, COMPILER_SIMPLIFY_OP
},
10315 [OP_UEXTRACT
] = { simplify_uextract
, COMPILER_SIMPLIFY_BITFIELD
},
10316 [OP_SEXTRACT
] = { simplify_sextract
, COMPILER_SIMPLIFY_BITFIELD
},
10317 [OP_DEPOSIT
] = { simplify_deposit
, COMPILER_SIMPLIFY_BITFIELD
},
10319 [OP_NOOP
] = { simplify_noop
, COMPILER_SIMPLIFY_OP
},
10321 [OP_INTCONST
] = { simplify_noop
, COMPILER_SIMPLIFY_OP
},
10322 [OP_BLOBCONST
] = { simplify_noop
, COMPILER_SIMPLIFY_OP
},
10323 [OP_ADDRCONST
] = { simplify_noop
, COMPILER_SIMPLIFY_OP
},
10324 [OP_UNKNOWNVAL
] = { simplify_noop
, COMPILER_SIMPLIFY_OP
},
10326 [OP_WRITE
] = { simplify_noop
, COMPILER_SIMPLIFY_OP
},
10327 [OP_READ
] = { simplify_noop
, COMPILER_SIMPLIFY_OP
},
10328 [OP_COPY
] = { simplify_copy
, COMPILER_SIMPLIFY_COPY
},
10329 [OP_CONVERT
] = { simplify_copy
, COMPILER_SIMPLIFY_COPY
},
10330 [OP_PIECE
] = { simplify_piece
, COMPILER_SIMPLIFY_OP
},
10331 [OP_ASM
] = { simplify_noop
, COMPILER_SIMPLIFY_OP
},
10333 [OP_DOT
] = { simplify_noop
, COMPILER_SIMPLIFY_OP
},
10334 [OP_INDEX
] = { simplify_noop
, COMPILER_SIMPLIFY_OP
},
10336 [OP_LIST
] = { simplify_noop
, COMPILER_SIMPLIFY_OP
},
10337 [OP_BRANCH
] = { simplify_branch
, COMPILER_SIMPLIFY_BRANCH
},
10338 [OP_CBRANCH
] = { simplify_branch
, COMPILER_SIMPLIFY_BRANCH
},
10339 [OP_CALL
] = { simplify_noop
, COMPILER_SIMPLIFY_BRANCH
},
10340 [OP_RET
] = { simplify_noop
, COMPILER_SIMPLIFY_BRANCH
},
10341 [OP_LABEL
] = { simplify_label
, COMPILER_SIMPLIFY_LABEL
},
10342 [OP_ADECL
] = { simplify_noop
, COMPILER_SIMPLIFY_OP
},
10343 [OP_SDECL
] = { simplify_noop
, COMPILER_SIMPLIFY_OP
},
10344 [OP_PHI
] = { simplify_phi
, COMPILER_SIMPLIFY_PHI
},
10346 [OP_INB
] = { simplify_noop
, COMPILER_SIMPLIFY_OP
},
10347 [OP_INW
] = { simplify_noop
, COMPILER_SIMPLIFY_OP
},
10348 [OP_INL
] = { simplify_noop
, COMPILER_SIMPLIFY_OP
},
10349 [OP_OUTB
] = { simplify_noop
, COMPILER_SIMPLIFY_OP
},
10350 [OP_OUTW
] = { simplify_noop
, COMPILER_SIMPLIFY_OP
},
10351 [OP_OUTL
] = { simplify_noop
, COMPILER_SIMPLIFY_OP
},
10352 [OP_BSF
] = { simplify_bsf
, COMPILER_SIMPLIFY_OP
},
10353 [OP_BSR
] = { simplify_bsr
, COMPILER_SIMPLIFY_OP
},
10354 [OP_RDMSR
] = { simplify_noop
, COMPILER_SIMPLIFY_OP
},
10355 [OP_WRMSR
] = { simplify_noop
, COMPILER_SIMPLIFY_OP
},
10356 [OP_HLT
] = { simplify_noop
, COMPILER_SIMPLIFY_OP
},
10359 static inline void debug_simplify(struct compile_state
*state
,
10360 simplify_t do_simplify
, struct triple
*ins
)
10362 #if DEBUG_SIMPLIFY_HIRES
10363 if (state
->functions_joined
&& (do_simplify
!= simplify_noop
)) {
10364 /* High resolution debugging mode */
10365 fprintf(state
->dbgout
, "simplifing: ");
10366 display_triple(state
->dbgout
, ins
);
10369 do_simplify(state
, ins
);
10370 #if DEBUG_SIMPLIFY_HIRES
10371 if (state
->functions_joined
&& (do_simplify
!= simplify_noop
)) {
10372 /* High resolution debugging mode */
10373 fprintf(state
->dbgout
, "simplified: ");
10374 display_triple(state
->dbgout
, ins
);
10378 static void simplify(struct compile_state
*state
, struct triple
*ins
)
10381 simplify_t do_simplify
;
10382 if (ins
== &unknown_triple
) {
10383 internal_error(state
, ins
, "simplifying the unknown triple?");
10388 if ((op
< 0) || (op
>= sizeof(table_simplify
)/sizeof(table_simplify
[0]))) {
10392 do_simplify
= table_simplify
[op
].func
;
10395 !(state
->compiler
->flags
& table_simplify
[op
].flag
)) {
10396 do_simplify
= simplify_noop
;
10398 if (do_simplify
&& (ins
->id
& TRIPLE_FLAG_VOLATILE
)) {
10399 do_simplify
= simplify_noop
;
10402 if (!do_simplify
) {
10403 internal_error(state
, ins
, "cannot simplify op: %d %s",
10407 debug_simplify(state
, do_simplify
, ins
);
10408 } while(ins
->op
!= op
);
10411 static void rebuild_ssa_form(struct compile_state
*state
);
10413 static void simplify_all(struct compile_state
*state
)
10415 struct triple
*ins
, *first
;
10416 if (!(state
->compiler
->flags
& COMPILER_SIMPLIFY
)) {
10419 first
= state
->first
;
10422 simplify(state
, ins
);
10424 } while(ins
!= first
->prev
);
10427 simplify(state
, ins
);
10429 }while(ins
!= first
);
10430 rebuild_ssa_form(state
);
10432 print_blocks(state
, __func__
, state
->dbgout
);
10437 * ============================
10440 static void register_builtin_function(struct compile_state
*state
,
10441 const char *name
, int op
, struct type
*rtype
, ...)
10443 struct type
*ftype
, *atype
, *ctype
, *crtype
, *param
, **next
;
10444 struct triple
*def
, *result
, *work
, *first
, *retvar
, *ret
;
10445 struct hash_entry
*ident
;
10446 struct file_state file
;
10452 /* Dummy file state to get debug handling right */
10453 memset(&file
, 0, sizeof(file
));
10454 file
.basename
= "<built-in>";
10456 file
.report_line
= 1;
10457 file
.report_name
= file
.basename
;
10458 file
.prev
= state
->file
;
10459 state
->file
= &file
;
10460 state
->function
= name
;
10462 /* Find the Parameter count */
10463 valid_op(state
, op
);
10464 parameters
= table_ops
[op
].rhs
;
10465 if (parameters
< 0 ) {
10466 internal_error(state
, 0, "Invalid builtin parameter count");
10469 /* Find the function type */
10470 ftype
= new_type(TYPE_FUNCTION
| STOR_INLINE
| STOR_STATIC
, rtype
, 0);
10471 ftype
->elements
= parameters
;
10472 next
= &ftype
->right
;
10473 va_start(args
, rtype
);
10474 for(i
= 0; i
< parameters
; i
++) {
10475 atype
= va_arg(args
, struct type
*);
10479 *next
= new_type(TYPE_PRODUCT
, *next
, atype
);
10480 next
= &((*next
)->right
);
10484 *next
= &void_type
;
10488 /* Get the initial closure type */
10489 ctype
= new_type(TYPE_JOIN
, &void_type
, 0);
10490 ctype
->elements
= 1;
10492 /* Get the return type */
10493 crtype
= new_type(TYPE_TUPLE
, new_type(TYPE_PRODUCT
, ctype
, rtype
), 0);
10494 crtype
->elements
= 2;
10496 /* Generate the needed triples */
10497 def
= triple(state
, OP_LIST
, ftype
, 0, 0);
10498 first
= label(state
);
10499 RHS(def
, 0) = first
;
10500 result
= flatten(state
, first
, variable(state
, crtype
));
10501 retvar
= flatten(state
, first
, variable(state
, &void_ptr_type
));
10502 ret
= triple(state
, OP_RET
, &void_type
, read_expr(state
, retvar
), 0);
10504 /* Now string them together */
10505 param
= ftype
->right
;
10506 for(i
= 0; i
< parameters
; i
++) {
10507 if ((param
->type
& TYPE_MASK
) == TYPE_PRODUCT
) {
10508 atype
= param
->left
;
10512 flatten(state
, first
, variable(state
, atype
));
10513 param
= param
->right
;
10515 work
= new_triple(state
, op
, rtype
, -1, parameters
);
10516 generate_lhs_pieces(state
, work
);
10517 for(i
= 0; i
< parameters
; i
++) {
10518 RHS(work
, i
) = read_expr(state
, farg(state
, def
, i
));
10520 if ((rtype
->type
& TYPE_MASK
) != TYPE_VOID
) {
10521 work
= write_expr(state
, deref_index(state
, result
, 1), work
);
10523 work
= flatten(state
, first
, work
);
10524 flatten(state
, first
, label(state
));
10525 ret
= flatten(state
, first
, ret
);
10526 name_len
= strlen(name
);
10527 ident
= lookup(state
, name
, name_len
);
10528 ftype
->type_ident
= ident
;
10529 symbol(state
, ident
, &ident
->sym_ident
, def
, ftype
);
10531 state
->file
= file
.prev
;
10532 state
->function
= 0;
10533 state
->main_function
= 0;
10535 if (!state
->functions
) {
10536 state
->functions
= def
;
10538 insert_triple(state
, state
->functions
, def
);
10540 if (state
->compiler
->debug
& DEBUG_INLINE
) {
10541 FILE *fp
= state
->dbgout
;
10544 fprintf(fp
, "\n__________ %s _________\n", __FUNCTION__
);
10545 display_func(state
, fp
, def
);
10546 fprintf(fp
, "__________ %s _________ done\n\n", __FUNCTION__
);
10550 static struct type
*partial_struct(struct compile_state
*state
,
10551 const char *field_name
, struct type
*type
, struct type
*rest
)
10553 struct hash_entry
*field_ident
;
10554 struct type
*result
;
10555 int field_name_len
;
10557 field_name_len
= strlen(field_name
);
10558 field_ident
= lookup(state
, field_name
, field_name_len
);
10560 result
= clone_type(0, type
);
10561 result
->field_ident
= field_ident
;
10564 result
= new_type(TYPE_PRODUCT
, result
, rest
);
10569 static struct type
*register_builtin_type(struct compile_state
*state
,
10570 const char *name
, struct type
*type
)
10572 struct hash_entry
*ident
;
10575 name_len
= strlen(name
);
10576 ident
= lookup(state
, name
, name_len
);
10578 if ((type
->type
& TYPE_MASK
) == TYPE_PRODUCT
) {
10579 ulong_t elements
= 0;
10580 struct type
*field
;
10581 type
= new_type(TYPE_STRUCT
, type
, 0);
10582 field
= type
->left
;
10583 while((field
->type
& TYPE_MASK
) == TYPE_PRODUCT
) {
10585 field
= field
->right
;
10588 symbol(state
, ident
, &ident
->sym_tag
, 0, type
);
10589 type
->type_ident
= ident
;
10590 type
->elements
= elements
;
10592 symbol(state
, ident
, &ident
->sym_ident
, 0, type
);
10593 ident
->tok
= TOK_TYPE_NAME
;
10598 static void register_builtins(struct compile_state
*state
)
10600 struct type
*div_type
, *ldiv_type
;
10601 struct type
*udiv_type
, *uldiv_type
;
10602 struct type
*msr_type
;
10604 div_type
= register_builtin_type(state
, "__builtin_div_t",
10605 partial_struct(state
, "quot", &int_type
,
10606 partial_struct(state
, "rem", &int_type
, 0)));
10607 ldiv_type
= register_builtin_type(state
, "__builtin_ldiv_t",
10608 partial_struct(state
, "quot", &long_type
,
10609 partial_struct(state
, "rem", &long_type
, 0)));
10610 udiv_type
= register_builtin_type(state
, "__builtin_udiv_t",
10611 partial_struct(state
, "quot", &uint_type
,
10612 partial_struct(state
, "rem", &uint_type
, 0)));
10613 uldiv_type
= register_builtin_type(state
, "__builtin_uldiv_t",
10614 partial_struct(state
, "quot", &ulong_type
,
10615 partial_struct(state
, "rem", &ulong_type
, 0)));
10617 register_builtin_function(state
, "__builtin_div", OP_SDIVT
, div_type
,
10618 &int_type
, &int_type
);
10619 register_builtin_function(state
, "__builtin_ldiv", OP_SDIVT
, ldiv_type
,
10620 &long_type
, &long_type
);
10621 register_builtin_function(state
, "__builtin_udiv", OP_UDIVT
, udiv_type
,
10622 &uint_type
, &uint_type
);
10623 register_builtin_function(state
, "__builtin_uldiv", OP_UDIVT
, uldiv_type
,
10624 &ulong_type
, &ulong_type
);
10626 register_builtin_function(state
, "__builtin_inb", OP_INB
, &uchar_type
,
10628 register_builtin_function(state
, "__builtin_inw", OP_INW
, &ushort_type
,
10630 register_builtin_function(state
, "__builtin_inl", OP_INL
, &uint_type
,
10633 register_builtin_function(state
, "__builtin_outb", OP_OUTB
, &void_type
,
10634 &uchar_type
, &ushort_type
);
10635 register_builtin_function(state
, "__builtin_outw", OP_OUTW
, &void_type
,
10636 &ushort_type
, &ushort_type
);
10637 register_builtin_function(state
, "__builtin_outl", OP_OUTL
, &void_type
,
10638 &uint_type
, &ushort_type
);
10640 register_builtin_function(state
, "__builtin_bsf", OP_BSF
, &int_type
,
10642 register_builtin_function(state
, "__builtin_bsr", OP_BSR
, &int_type
,
10645 msr_type
= register_builtin_type(state
, "__builtin_msr_t",
10646 partial_struct(state
, "lo", &ulong_type
,
10647 partial_struct(state
, "hi", &ulong_type
, 0)));
10649 register_builtin_function(state
, "__builtin_rdmsr", OP_RDMSR
, msr_type
,
10651 register_builtin_function(state
, "__builtin_wrmsr", OP_WRMSR
, &void_type
,
10652 &ulong_type
, &ulong_type
, &ulong_type
);
10654 register_builtin_function(state
, "__builtin_hlt", OP_HLT
, &void_type
,
10658 static struct type
*declarator(
10659 struct compile_state
*state
, struct type
*type
,
10660 struct hash_entry
**ident
, int need_ident
);
10661 static void decl(struct compile_state
*state
, struct triple
*first
);
10662 static struct type
*specifier_qualifier_list(struct compile_state
*state
);
10663 #if DEBUG_ROMCC_WARNING
10664 static int isdecl_specifier(int tok
);
10666 static struct type
*decl_specifiers(struct compile_state
*state
);
10667 static int istype(int tok
);
10668 static struct triple
*expr(struct compile_state
*state
);
10669 static struct triple
*assignment_expr(struct compile_state
*state
);
10670 static struct type
*type_name(struct compile_state
*state
);
10671 static void statement(struct compile_state
*state
, struct triple
*first
);
10673 static struct triple
*call_expr(
10674 struct compile_state
*state
, struct triple
*func
)
10676 struct triple
*def
;
10677 struct type
*param
, *type
;
10678 ulong_t pvals
, index
;
10680 if ((func
->type
->type
& TYPE_MASK
) != TYPE_FUNCTION
) {
10681 error(state
, 0, "Called object is not a function");
10683 if (func
->op
!= OP_LIST
) {
10684 internal_error(state
, 0, "improper function");
10686 eat(state
, TOK_LPAREN
);
10687 /* Find the return type without any specifiers */
10688 type
= clone_type(0, func
->type
->left
);
10689 /* Count the number of rhs entries for OP_FCALL */
10690 param
= func
->type
->right
;
10692 while((param
->type
& TYPE_MASK
) == TYPE_PRODUCT
) {
10694 param
= param
->right
;
10696 if ((param
->type
& TYPE_MASK
) != TYPE_VOID
) {
10699 def
= new_triple(state
, OP_FCALL
, type
, -1, pvals
);
10700 MISC(def
, 0) = func
;
10702 param
= func
->type
->right
;
10703 for(index
= 0; index
< pvals
; index
++) {
10704 struct triple
*val
;
10705 struct type
*arg_type
;
10706 val
= read_expr(state
, assignment_expr(state
));
10708 if ((param
->type
& TYPE_MASK
) == TYPE_PRODUCT
) {
10709 arg_type
= param
->left
;
10711 write_compatible(state
, arg_type
, val
->type
);
10712 RHS(def
, index
) = val
;
10713 if (index
!= (pvals
- 1)) {
10714 eat(state
, TOK_COMMA
);
10715 param
= param
->right
;
10718 eat(state
, TOK_RPAREN
);
10723 static struct triple
*character_constant(struct compile_state
*state
)
10725 struct triple
*def
;
10727 const signed char *str
, *end
;
10730 tk
= eat(state
, TOK_LIT_CHAR
);
10731 str
= (signed char *)tk
->val
.str
+ 1;
10732 str_len
= tk
->str_len
- 2;
10733 if (str_len
<= 0) {
10734 error(state
, 0, "empty character constant");
10736 end
= str
+ str_len
;
10737 c
= char_value(state
, &str
, end
);
10739 error(state
, 0, "multibyte character constant not supported");
10741 def
= int_const(state
, &char_type
, (ulong_t
)((long_t
)c
));
10745 static struct triple
*string_constant(struct compile_state
*state
)
10747 struct triple
*def
;
10750 const signed char *str
, *end
;
10751 signed char *buf
, *ptr
;
10755 type
= new_type(TYPE_ARRAY
, &char_type
, 0);
10756 type
->elements
= 0;
10757 /* The while loop handles string concatenation */
10759 tk
= eat(state
, TOK_LIT_STRING
);
10760 str
= (signed char *)tk
->val
.str
+ 1;
10761 str_len
= tk
->str_len
- 2;
10763 error(state
, 0, "negative string constant length");
10765 /* ignore empty string tokens */
10766 if ('"' == *str
&& 0 == str
[1])
10768 end
= str
+ str_len
;
10770 buf
= xmalloc(type
->elements
+ str_len
+ 1, "string_constant");
10771 memcpy(buf
, ptr
, type
->elements
);
10772 ptr
= buf
+ type
->elements
;
10774 *ptr
++ = char_value(state
, &str
, end
);
10775 } while(str
< end
);
10776 type
->elements
= ptr
- buf
;
10777 } while(peek(state
) == TOK_LIT_STRING
);
10779 type
->elements
+= 1;
10780 def
= triple(state
, OP_BLOBCONST
, type
, 0, 0);
10787 static struct triple
*integer_constant(struct compile_state
*state
)
10789 struct triple
*def
;
10796 tk
= eat(state
, TOK_LIT_INT
);
10798 decimal
= (tk
->val
.str
[0] != '0');
10799 val
= strtoul(tk
->val
.str
, &end
, 0);
10800 if (errno
== ERANGE
) {
10801 error(state
, 0, "Integer constant out of range");
10804 if ((*end
== 'u') || (*end
== 'U')) {
10808 if ((*end
== 'l') || (*end
== 'L')) {
10812 if ((*end
== 'u') || (*end
== 'U')) {
10817 error(state
, 0, "Junk at end of integer constant");
10820 type
= &ulong_type
;
10824 if (!decimal
&& (val
> LONG_T_MAX
)) {
10825 type
= &ulong_type
;
10830 if (val
> UINT_T_MAX
) {
10831 type
= &ulong_type
;
10836 if (!decimal
&& (val
> INT_T_MAX
) && (val
<= UINT_T_MAX
)) {
10839 else if (!decimal
&& (val
> LONG_T_MAX
)) {
10840 type
= &ulong_type
;
10842 else if (val
> INT_T_MAX
) {
10846 def
= int_const(state
, type
, val
);
10850 static struct triple
*primary_expr(struct compile_state
*state
)
10852 struct triple
*def
;
10858 struct hash_entry
*ident
;
10859 /* Here ident is either:
10863 ident
= eat(state
, TOK_IDENT
)->ident
;
10864 if (!ident
->sym_ident
) {
10865 error(state
, 0, "%s undeclared", ident
->name
);
10867 def
= ident
->sym_ident
->def
;
10870 case TOK_ENUM_CONST
:
10872 struct hash_entry
*ident
;
10873 /* Here ident is an enumeration constant */
10874 ident
= eat(state
, TOK_ENUM_CONST
)->ident
;
10875 if (!ident
->sym_ident
) {
10876 error(state
, 0, "%s undeclared", ident
->name
);
10878 def
= ident
->sym_ident
->def
;
10883 struct hash_entry
*ident
;
10884 ident
= eat(state
, TOK_MIDENT
)->ident
;
10885 warning(state
, 0, "Replacing undefined macro: %s with 0",
10887 def
= int_const(state
, &int_type
, 0);
10891 eat(state
, TOK_LPAREN
);
10893 eat(state
, TOK_RPAREN
);
10896 def
= integer_constant(state
);
10898 case TOK_LIT_FLOAT
:
10899 eat(state
, TOK_LIT_FLOAT
);
10900 error(state
, 0, "Floating point constants not supported");
10905 def
= character_constant(state
);
10907 case TOK_LIT_STRING
:
10908 def
= string_constant(state
);
10912 error(state
, 0, "Unexpected token: %s\n", tokens
[tok
]);
10917 static struct triple
*postfix_expr(struct compile_state
*state
)
10919 struct triple
*def
;
10921 def
= primary_expr(state
);
10923 struct triple
*left
;
10927 switch((tok
= peek(state
))) {
10929 eat(state
, TOK_LBRACKET
);
10930 def
= mk_subscript_expr(state
, left
, expr(state
));
10931 eat(state
, TOK_RBRACKET
);
10934 def
= call_expr(state
, def
);
10938 struct hash_entry
*field
;
10939 eat(state
, TOK_DOT
);
10940 field
= eat(state
, TOK_IDENT
)->ident
;
10941 def
= deref_field(state
, def
, field
);
10946 struct hash_entry
*field
;
10947 eat(state
, TOK_ARROW
);
10948 field
= eat(state
, TOK_IDENT
)->ident
;
10949 def
= mk_deref_expr(state
, read_expr(state
, def
));
10950 def
= deref_field(state
, def
, field
);
10954 eat(state
, TOK_PLUSPLUS
);
10955 def
= mk_post_inc_expr(state
, left
);
10957 case TOK_MINUSMINUS
:
10958 eat(state
, TOK_MINUSMINUS
);
10959 def
= mk_post_dec_expr(state
, left
);
10969 static struct triple
*cast_expr(struct compile_state
*state
);
10971 static struct triple
*unary_expr(struct compile_state
*state
)
10973 struct triple
*def
, *right
;
10975 switch((tok
= peek(state
))) {
10977 eat(state
, TOK_PLUSPLUS
);
10978 def
= mk_pre_inc_expr(state
, unary_expr(state
));
10980 case TOK_MINUSMINUS
:
10981 eat(state
, TOK_MINUSMINUS
);
10982 def
= mk_pre_dec_expr(state
, unary_expr(state
));
10985 eat(state
, TOK_AND
);
10986 def
= mk_addr_expr(state
, cast_expr(state
), 0);
10989 eat(state
, TOK_STAR
);
10990 def
= mk_deref_expr(state
, read_expr(state
, cast_expr(state
)));
10993 eat(state
, TOK_PLUS
);
10994 right
= read_expr(state
, cast_expr(state
));
10995 arithmetic(state
, right
);
10996 def
= integral_promotion(state
, right
);
10999 eat(state
, TOK_MINUS
);
11000 right
= read_expr(state
, cast_expr(state
));
11001 arithmetic(state
, right
);
11002 def
= integral_promotion(state
, right
);
11003 def
= triple(state
, OP_NEG
, def
->type
, def
, 0);
11006 eat(state
, TOK_TILDE
);
11007 right
= read_expr(state
, cast_expr(state
));
11008 integral(state
, right
);
11009 def
= integral_promotion(state
, right
);
11010 def
= triple(state
, OP_INVERT
, def
->type
, def
, 0);
11013 eat(state
, TOK_BANG
);
11014 right
= read_expr(state
, cast_expr(state
));
11015 bool(state
, right
);
11016 def
= lfalse_expr(state
, right
);
11022 eat(state
, TOK_SIZEOF
);
11023 tok1
= peek(state
);
11024 tok2
= peek2(state
);
11025 if ((tok1
== TOK_LPAREN
) && istype(tok2
)) {
11026 eat(state
, TOK_LPAREN
);
11027 type
= type_name(state
);
11028 eat(state
, TOK_RPAREN
);
11031 struct triple
*expr
;
11032 expr
= unary_expr(state
);
11034 release_expr(state
, expr
);
11036 def
= int_const(state
, &ulong_type
, size_of_in_bytes(state
, type
));
11043 eat(state
, TOK_ALIGNOF
);
11044 tok1
= peek(state
);
11045 tok2
= peek2(state
);
11046 if ((tok1
== TOK_LPAREN
) && istype(tok2
)) {
11047 eat(state
, TOK_LPAREN
);
11048 type
= type_name(state
);
11049 eat(state
, TOK_RPAREN
);
11052 struct triple
*expr
;
11053 expr
= unary_expr(state
);
11055 release_expr(state
, expr
);
11057 def
= int_const(state
, &ulong_type
, align_of_in_bytes(state
, type
));
11062 /* We only come here if we are called from the preprocessor */
11063 struct hash_entry
*ident
;
11065 eat(state
, TOK_MDEFINED
);
11067 if (pp_peek(state
) == TOK_LPAREN
) {
11068 pp_eat(state
, TOK_LPAREN
);
11071 ident
= pp_eat(state
, TOK_MIDENT
)->ident
;
11073 eat(state
, TOK_RPAREN
);
11075 def
= int_const(state
, &int_type
, ident
->sym_define
!= 0);
11079 def
= postfix_expr(state
);
11085 static struct triple
*cast_expr(struct compile_state
*state
)
11087 struct triple
*def
;
11089 tok1
= peek(state
);
11090 tok2
= peek2(state
);
11091 if ((tok1
== TOK_LPAREN
) && istype(tok2
)) {
11093 eat(state
, TOK_LPAREN
);
11094 type
= type_name(state
);
11095 eat(state
, TOK_RPAREN
);
11096 def
= mk_cast_expr(state
, type
, cast_expr(state
));
11099 def
= unary_expr(state
);
11104 static struct triple
*mult_expr(struct compile_state
*state
)
11106 struct triple
*def
;
11108 def
= cast_expr(state
);
11110 struct triple
*left
, *right
;
11111 struct type
*result_type
;
11119 left
= read_expr(state
, def
);
11120 arithmetic(state
, left
);
11124 right
= read_expr(state
, cast_expr(state
));
11125 arithmetic(state
, right
);
11127 result_type
= arithmetic_result(state
, left
, right
);
11128 sign
= is_signed(result_type
);
11131 case TOK_STAR
: op
= sign
? OP_SMUL
: OP_UMUL
; break;
11132 case TOK_DIV
: op
= sign
? OP_SDIV
: OP_UDIV
; break;
11133 case TOK_MOD
: op
= sign
? OP_SMOD
: OP_UMOD
; break;
11135 def
= triple(state
, op
, result_type
, left
, right
);
11145 static struct triple
*add_expr(struct compile_state
*state
)
11147 struct triple
*def
;
11149 def
= mult_expr(state
);
11152 switch( peek(state
)) {
11154 eat(state
, TOK_PLUS
);
11155 def
= mk_add_expr(state
, def
, mult_expr(state
));
11158 eat(state
, TOK_MINUS
);
11159 def
= mk_sub_expr(state
, def
, mult_expr(state
));
11169 static struct triple
*shift_expr(struct compile_state
*state
)
11171 struct triple
*def
;
11173 def
= add_expr(state
);
11175 struct triple
*left
, *right
;
11178 switch((tok
= peek(state
))) {
11181 left
= read_expr(state
, def
);
11182 integral(state
, left
);
11183 left
= integral_promotion(state
, left
);
11187 right
= read_expr(state
, add_expr(state
));
11188 integral(state
, right
);
11189 right
= integral_promotion(state
, right
);
11191 op
= (tok
== TOK_SL
)? OP_SL
:
11192 is_signed(left
->type
)? OP_SSR
: OP_USR
;
11194 def
= triple(state
, op
, left
->type
, left
, right
);
11204 static struct triple
*relational_expr(struct compile_state
*state
)
11206 #if DEBUG_ROMCC_WARNINGS
11207 #warning "Extend relational exprs to work on more than arithmetic types"
11209 struct triple
*def
;
11211 def
= shift_expr(state
);
11213 struct triple
*left
, *right
;
11214 struct type
*arg_type
;
11217 switch((tok
= peek(state
))) {
11222 left
= read_expr(state
, def
);
11223 arithmetic(state
, left
);
11227 right
= read_expr(state
, shift_expr(state
));
11228 arithmetic(state
, right
);
11230 arg_type
= arithmetic_result(state
, left
, right
);
11231 sign
= is_signed(arg_type
);
11234 case TOK_LESS
: op
= sign
? OP_SLESS
: OP_ULESS
; break;
11235 case TOK_MORE
: op
= sign
? OP_SMORE
: OP_UMORE
; break;
11236 case TOK_LESSEQ
: op
= sign
? OP_SLESSEQ
: OP_ULESSEQ
; break;
11237 case TOK_MOREEQ
: op
= sign
? OP_SMOREEQ
: OP_UMOREEQ
; break;
11239 def
= triple(state
, op
, &int_type
, left
, right
);
11249 static struct triple
*equality_expr(struct compile_state
*state
)
11251 #if DEBUG_ROMCC_WARNINGS
11252 #warning "Extend equality exprs to work on more than arithmetic types"
11254 struct triple
*def
;
11256 def
= relational_expr(state
);
11258 struct triple
*left
, *right
;
11261 switch((tok
= peek(state
))) {
11264 left
= read_expr(state
, def
);
11265 arithmetic(state
, left
);
11267 right
= read_expr(state
, relational_expr(state
));
11268 arithmetic(state
, right
);
11269 op
= (tok
== TOK_EQEQ
) ? OP_EQ
: OP_NOTEQ
;
11270 def
= triple(state
, op
, &int_type
, left
, right
);
11280 static struct triple
*and_expr(struct compile_state
*state
)
11282 struct triple
*def
;
11283 def
= equality_expr(state
);
11284 while(peek(state
) == TOK_AND
) {
11285 struct triple
*left
, *right
;
11286 struct type
*result_type
;
11287 left
= read_expr(state
, def
);
11288 integral(state
, left
);
11289 eat(state
, TOK_AND
);
11290 right
= read_expr(state
, equality_expr(state
));
11291 integral(state
, right
);
11292 result_type
= arithmetic_result(state
, left
, right
);
11293 def
= triple(state
, OP_AND
, result_type
, left
, right
);
11298 static struct triple
*xor_expr(struct compile_state
*state
)
11300 struct triple
*def
;
11301 def
= and_expr(state
);
11302 while(peek(state
) == TOK_XOR
) {
11303 struct triple
*left
, *right
;
11304 struct type
*result_type
;
11305 left
= read_expr(state
, def
);
11306 integral(state
, left
);
11307 eat(state
, TOK_XOR
);
11308 right
= read_expr(state
, and_expr(state
));
11309 integral(state
, right
);
11310 result_type
= arithmetic_result(state
, left
, right
);
11311 def
= triple(state
, OP_XOR
, result_type
, left
, right
);
11316 static struct triple
*or_expr(struct compile_state
*state
)
11318 struct triple
*def
;
11319 def
= xor_expr(state
);
11320 while(peek(state
) == TOK_OR
) {
11321 struct triple
*left
, *right
;
11322 struct type
*result_type
;
11323 left
= read_expr(state
, def
);
11324 integral(state
, left
);
11325 eat(state
, TOK_OR
);
11326 right
= read_expr(state
, xor_expr(state
));
11327 integral(state
, right
);
11328 result_type
= arithmetic_result(state
, left
, right
);
11329 def
= triple(state
, OP_OR
, result_type
, left
, right
);
11334 static struct triple
*land_expr(struct compile_state
*state
)
11336 struct triple
*def
;
11337 def
= or_expr(state
);
11338 while(peek(state
) == TOK_LOGAND
) {
11339 struct triple
*left
, *right
;
11340 left
= read_expr(state
, def
);
11342 eat(state
, TOK_LOGAND
);
11343 right
= read_expr(state
, or_expr(state
));
11344 bool(state
, right
);
11346 def
= mkland_expr(state
,
11347 ltrue_expr(state
, left
),
11348 ltrue_expr(state
, right
));
11353 static struct triple
*lor_expr(struct compile_state
*state
)
11355 struct triple
*def
;
11356 def
= land_expr(state
);
11357 while(peek(state
) == TOK_LOGOR
) {
11358 struct triple
*left
, *right
;
11359 left
= read_expr(state
, def
);
11361 eat(state
, TOK_LOGOR
);
11362 right
= read_expr(state
, land_expr(state
));
11363 bool(state
, right
);
11365 def
= mklor_expr(state
,
11366 ltrue_expr(state
, left
),
11367 ltrue_expr(state
, right
));
11372 static struct triple
*conditional_expr(struct compile_state
*state
)
11374 struct triple
*def
;
11375 def
= lor_expr(state
);
11376 if (peek(state
) == TOK_QUEST
) {
11377 struct triple
*test
, *left
, *right
;
11379 test
= ltrue_expr(state
, read_expr(state
, def
));
11380 eat(state
, TOK_QUEST
);
11381 left
= read_expr(state
, expr(state
));
11382 eat(state
, TOK_COLON
);
11383 right
= read_expr(state
, conditional_expr(state
));
11385 def
= mkcond_expr(state
, test
, left
, right
);
11391 struct triple
*val
;
11395 static void set_cv(struct compile_state
*state
, struct cv_triple
*cv
,
11396 struct triple
*dest
, struct triple
*val
)
11398 if (cv
[dest
->id
].val
) {
11399 free_triple(state
, cv
[dest
->id
].val
);
11401 cv
[dest
->id
].val
= val
;
11403 static struct triple
*get_cv(struct compile_state
*state
, struct cv_triple
*cv
,
11404 struct triple
*src
)
11406 return cv
[src
->id
].val
;
11409 static struct triple
*eval_const_expr(
11410 struct compile_state
*state
, struct triple
*expr
)
11412 struct triple
*def
;
11413 if (is_const(expr
)) {
11417 /* If we don't start out as a constant simplify into one */
11418 struct triple
*head
, *ptr
;
11419 struct cv_triple
*cv
;
11421 head
= label(state
); /* dummy initial triple */
11422 flatten(state
, head
, expr
);
11424 for(ptr
= head
->next
; ptr
!= head
; ptr
= ptr
->next
) {
11427 cv
= xcmalloc(sizeof(struct cv_triple
)*count
, "const value vector");
11429 for(ptr
= head
->next
; ptr
!= head
; ptr
= ptr
->next
) {
11431 cv
[i
].id
= ptr
->id
;
11437 valid_ins(state
, ptr
);
11438 if ((ptr
->op
== OP_PHI
) || (ptr
->op
== OP_LIST
)) {
11439 internal_error(state
, ptr
,
11440 "unexpected %s in constant expression",
11443 else if (ptr
->op
== OP_LIST
) {
11445 else if (triple_is_structural(state
, ptr
)) {
11448 else if (triple_is_ubranch(state
, ptr
)) {
11449 ptr
= TARG(ptr
, 0);
11451 else if (triple_is_cbranch(state
, ptr
)) {
11452 struct triple
*cond_val
;
11453 cond_val
= get_cv(state
, cv
, RHS(ptr
, 0));
11454 if (!cond_val
|| !is_const(cond_val
) ||
11455 (cond_val
->op
!= OP_INTCONST
))
11457 internal_error(state
, ptr
, "bad branch condition");
11459 if (cond_val
->u
.cval
== 0) {
11462 ptr
= TARG(ptr
, 0);
11465 else if (triple_is_branch(state
, ptr
)) {
11466 error(state
, ptr
, "bad branch type in constant expression");
11468 else if (ptr
->op
== OP_WRITE
) {
11469 struct triple
*val
;
11470 val
= get_cv(state
, cv
, RHS(ptr
, 0));
11472 set_cv(state
, cv
, MISC(ptr
, 0),
11473 copy_triple(state
, val
));
11474 set_cv(state
, cv
, ptr
,
11475 copy_triple(state
, val
));
11478 else if (ptr
->op
== OP_READ
) {
11479 set_cv(state
, cv
, ptr
,
11481 get_cv(state
, cv
, RHS(ptr
, 0))));
11484 else if (triple_is_pure(state
, ptr
, cv
[ptr
->id
].id
)) {
11485 struct triple
*val
, **rhs
;
11486 val
= copy_triple(state
, ptr
);
11487 rhs
= triple_rhs(state
, val
, 0);
11488 for(; rhs
; rhs
= triple_rhs(state
, val
, rhs
)) {
11490 internal_error(state
, ptr
, "Missing rhs");
11492 *rhs
= get_cv(state
, cv
, *rhs
);
11494 simplify(state
, val
);
11495 set_cv(state
, cv
, ptr
, val
);
11499 error(state
, ptr
, "impure operation in constant expression");
11502 } while(ptr
!= head
);
11504 /* Get the result value */
11505 def
= get_cv(state
, cv
, head
->prev
);
11506 cv
[head
->prev
->id
].val
= 0;
11508 /* Free the temporary values */
11509 for(i
= 0; i
< count
; i
++) {
11511 free_triple(state
, cv
[i
].val
);
11516 /* Free the intermediate expressions */
11517 while(head
->next
!= head
) {
11518 release_triple(state
, head
->next
);
11520 free_triple(state
, head
);
11522 if (!is_const(def
)) {
11523 error(state
, expr
, "Not a constant expression");
11528 static struct triple
*constant_expr(struct compile_state
*state
)
11530 return eval_const_expr(state
, conditional_expr(state
));
11533 static struct triple
*assignment_expr(struct compile_state
*state
)
11535 struct triple
*def
, *left
, *right
;
11537 /* The C grammer in K&R shows assignment expressions
11538 * only taking unary expressions as input on their
11539 * left hand side. But specifies the precedence of
11540 * assignemnt as the lowest operator except for comma.
11542 * Allowing conditional expressions on the left hand side
11543 * of an assignement results in a grammar that accepts
11544 * a larger set of statements than standard C. As long
11545 * as the subset of the grammar that is standard C behaves
11546 * correctly this should cause no problems.
11548 * For the extra token strings accepted by the grammar
11549 * none of them should produce a valid lvalue, so they
11550 * should not produce functioning programs.
11552 * GCC has this bug as well, so surprises should be minimal.
11554 def
= conditional_expr(state
);
11556 switch((tok
= peek(state
))) {
11558 lvalue(state
, left
);
11559 eat(state
, TOK_EQ
);
11560 def
= write_expr(state
, left
,
11561 read_expr(state
, assignment_expr(state
)));
11566 lvalue(state
, left
);
11567 arithmetic(state
, left
);
11569 right
= read_expr(state
, assignment_expr(state
));
11570 arithmetic(state
, right
);
11572 sign
= is_signed(left
->type
);
11575 case TOK_TIMESEQ
: op
= sign
? OP_SMUL
: OP_UMUL
; break;
11576 case TOK_DIVEQ
: op
= sign
? OP_SDIV
: OP_UDIV
; break;
11577 case TOK_MODEQ
: op
= sign
? OP_SMOD
: OP_UMOD
; break;
11579 def
= write_expr(state
, left
,
11580 triple(state
, op
, left
->type
,
11581 read_expr(state
, left
), right
));
11584 lvalue(state
, left
);
11585 eat(state
, TOK_PLUSEQ
);
11586 def
= write_expr(state
, left
,
11587 mk_add_expr(state
, left
, assignment_expr(state
)));
11590 lvalue(state
, left
);
11591 eat(state
, TOK_MINUSEQ
);
11592 def
= write_expr(state
, left
,
11593 mk_sub_expr(state
, left
, assignment_expr(state
)));
11600 lvalue(state
, left
);
11601 integral(state
, left
);
11603 right
= read_expr(state
, assignment_expr(state
));
11604 integral(state
, right
);
11605 right
= integral_promotion(state
, right
);
11606 sign
= is_signed(left
->type
);
11609 case TOK_SLEQ
: op
= OP_SL
; break;
11610 case TOK_SREQ
: op
= sign
? OP_SSR
: OP_USR
; break;
11611 case TOK_ANDEQ
: op
= OP_AND
; break;
11612 case TOK_XOREQ
: op
= OP_XOR
; break;
11613 case TOK_OREQ
: op
= OP_OR
; break;
11615 def
= write_expr(state
, left
,
11616 triple(state
, op
, left
->type
,
11617 read_expr(state
, left
), right
));
11623 static struct triple
*expr(struct compile_state
*state
)
11625 struct triple
*def
;
11626 def
= assignment_expr(state
);
11627 while(peek(state
) == TOK_COMMA
) {
11628 eat(state
, TOK_COMMA
);
11629 def
= mkprog(state
, def
, assignment_expr(state
), 0UL);
11634 static void expr_statement(struct compile_state
*state
, struct triple
*first
)
11636 if (peek(state
) != TOK_SEMI
) {
11637 /* lvalue conversions always apply except when certian operators
11638 * are applied. I apply the lvalue conversions here
11639 * as I know no more operators will be applied.
11641 flatten(state
, first
, lvalue_conversion(state
, expr(state
)));
11643 eat(state
, TOK_SEMI
);
11646 static void if_statement(struct compile_state
*state
, struct triple
*first
)
11648 struct triple
*test
, *jmp1
, *jmp2
, *middle
, *end
;
11650 jmp1
= jmp2
= middle
= 0;
11651 eat(state
, TOK_IF
);
11652 eat(state
, TOK_LPAREN
);
11653 test
= expr(state
);
11655 /* Cleanup and invert the test */
11656 test
= lfalse_expr(state
, read_expr(state
, test
));
11657 eat(state
, TOK_RPAREN
);
11658 /* Generate the needed pieces */
11659 middle
= label(state
);
11660 jmp1
= branch(state
, middle
, test
);
11661 /* Thread the pieces together */
11662 flatten(state
, first
, test
);
11663 flatten(state
, first
, jmp1
);
11664 flatten(state
, first
, label(state
));
11665 statement(state
, first
);
11666 if (peek(state
) == TOK_ELSE
) {
11667 eat(state
, TOK_ELSE
);
11668 /* Generate the rest of the pieces */
11669 end
= label(state
);
11670 jmp2
= branch(state
, end
, 0);
11671 /* Thread them together */
11672 flatten(state
, first
, jmp2
);
11673 flatten(state
, first
, middle
);
11674 statement(state
, first
);
11675 flatten(state
, first
, end
);
11678 flatten(state
, first
, middle
);
11682 static void for_statement(struct compile_state
*state
, struct triple
*first
)
11684 struct triple
*head
, *test
, *tail
, *jmp1
, *jmp2
, *end
;
11685 struct triple
*label1
, *label2
, *label3
;
11686 struct hash_entry
*ident
;
11688 eat(state
, TOK_FOR
);
11689 eat(state
, TOK_LPAREN
);
11690 head
= test
= tail
= jmp1
= jmp2
= 0;
11691 if (peek(state
) != TOK_SEMI
) {
11692 head
= expr(state
);
11694 eat(state
, TOK_SEMI
);
11695 if (peek(state
) != TOK_SEMI
) {
11696 test
= expr(state
);
11698 test
= ltrue_expr(state
, read_expr(state
, test
));
11700 eat(state
, TOK_SEMI
);
11701 if (peek(state
) != TOK_RPAREN
) {
11702 tail
= expr(state
);
11704 eat(state
, TOK_RPAREN
);
11705 /* Generate the needed pieces */
11706 label1
= label(state
);
11707 label2
= label(state
);
11708 label3
= label(state
);
11710 jmp1
= branch(state
, label3
, 0);
11711 jmp2
= branch(state
, label1
, test
);
11714 jmp2
= branch(state
, label1
, 0);
11716 end
= label(state
);
11717 /* Remember where break and continue go */
11718 start_scope(state
);
11719 ident
= state
->i_break
;
11720 symbol(state
, ident
, &ident
->sym_ident
, end
, end
->type
);
11721 ident
= state
->i_continue
;
11722 symbol(state
, ident
, &ident
->sym_ident
, label2
, label2
->type
);
11723 /* Now include the body */
11724 flatten(state
, first
, head
);
11725 flatten(state
, first
, jmp1
);
11726 flatten(state
, first
, label1
);
11727 statement(state
, first
);
11728 flatten(state
, first
, label2
);
11729 flatten(state
, first
, tail
);
11730 flatten(state
, first
, label3
);
11731 flatten(state
, first
, test
);
11732 flatten(state
, first
, jmp2
);
11733 flatten(state
, first
, end
);
11734 /* Cleanup the break/continue scope */
11738 static void while_statement(struct compile_state
*state
, struct triple
*first
)
11740 struct triple
*label1
, *test
, *label2
, *jmp1
, *jmp2
, *end
;
11741 struct hash_entry
*ident
;
11742 eat(state
, TOK_WHILE
);
11743 eat(state
, TOK_LPAREN
);
11744 test
= expr(state
);
11746 test
= ltrue_expr(state
, read_expr(state
, test
));
11747 eat(state
, TOK_RPAREN
);
11748 /* Generate the needed pieces */
11749 label1
= label(state
);
11750 label2
= label(state
);
11751 jmp1
= branch(state
, label2
, 0);
11752 jmp2
= branch(state
, label1
, test
);
11753 end
= label(state
);
11754 /* Remember where break and continue go */
11755 start_scope(state
);
11756 ident
= state
->i_break
;
11757 symbol(state
, ident
, &ident
->sym_ident
, end
, end
->type
);
11758 ident
= state
->i_continue
;
11759 symbol(state
, ident
, &ident
->sym_ident
, label2
, label2
->type
);
11760 /* Thread them together */
11761 flatten(state
, first
, jmp1
);
11762 flatten(state
, first
, label1
);
11763 statement(state
, first
);
11764 flatten(state
, first
, label2
);
11765 flatten(state
, first
, test
);
11766 flatten(state
, first
, jmp2
);
11767 flatten(state
, first
, end
);
11768 /* Cleanup the break/continue scope */
11772 static void do_statement(struct compile_state
*state
, struct triple
*first
)
11774 struct triple
*label1
, *label2
, *test
, *end
;
11775 struct hash_entry
*ident
;
11776 eat(state
, TOK_DO
);
11777 /* Generate the needed pieces */
11778 label1
= label(state
);
11779 label2
= label(state
);
11780 end
= label(state
);
11781 /* Remember where break and continue go */
11782 start_scope(state
);
11783 ident
= state
->i_break
;
11784 symbol(state
, ident
, &ident
->sym_ident
, end
, end
->type
);
11785 ident
= state
->i_continue
;
11786 symbol(state
, ident
, &ident
->sym_ident
, label2
, label2
->type
);
11787 /* Now include the body */
11788 flatten(state
, first
, label1
);
11789 statement(state
, first
);
11790 /* Cleanup the break/continue scope */
11792 /* Eat the rest of the loop */
11793 eat(state
, TOK_WHILE
);
11794 eat(state
, TOK_LPAREN
);
11795 test
= read_expr(state
, expr(state
));
11797 eat(state
, TOK_RPAREN
);
11798 eat(state
, TOK_SEMI
);
11799 /* Thread the pieces together */
11800 test
= ltrue_expr(state
, test
);
11801 flatten(state
, first
, label2
);
11802 flatten(state
, first
, test
);
11803 flatten(state
, first
, branch(state
, label1
, test
));
11804 flatten(state
, first
, end
);
11808 static void return_statement(struct compile_state
*state
, struct triple
*first
)
11810 struct triple
*jmp
, *mv
, *dest
, *var
, *val
;
11812 eat(state
, TOK_RETURN
);
11814 #if DEBUG_ROMCC_WARNINGS
11815 #warning "FIXME implement a more general excess branch elimination"
11818 /* If we have a return value do some more work */
11819 if (peek(state
) != TOK_SEMI
) {
11820 val
= read_expr(state
, expr(state
));
11822 eat(state
, TOK_SEMI
);
11824 /* See if this last statement in a function */
11825 last
= ((peek(state
) == TOK_RBRACE
) &&
11826 (state
->scope_depth
== GLOBAL_SCOPE_DEPTH
+2));
11828 /* Find the return variable */
11829 var
= fresult(state
, state
->main_function
);
11831 /* Find the return destination */
11832 dest
= state
->i_return
->sym_ident
->def
;
11834 /* If needed generate a jump instruction */
11836 jmp
= branch(state
, dest
, 0);
11838 /* If needed generate an assignment instruction */
11840 mv
= write_expr(state
, deref_index(state
, var
, 1), val
);
11842 /* Now put the code together */
11844 flatten(state
, first
, mv
);
11845 flatten(state
, first
, jmp
);
11848 flatten(state
, first
, jmp
);
11852 static void break_statement(struct compile_state
*state
, struct triple
*first
)
11854 struct triple
*dest
;
11855 eat(state
, TOK_BREAK
);
11856 eat(state
, TOK_SEMI
);
11857 if (!state
->i_break
->sym_ident
) {
11858 error(state
, 0, "break statement not within loop or switch");
11860 dest
= state
->i_break
->sym_ident
->def
;
11861 flatten(state
, first
, branch(state
, dest
, 0));
11864 static void continue_statement(struct compile_state
*state
, struct triple
*first
)
11866 struct triple
*dest
;
11867 eat(state
, TOK_CONTINUE
);
11868 eat(state
, TOK_SEMI
);
11869 if (!state
->i_continue
->sym_ident
) {
11870 error(state
, 0, "continue statement outside of a loop");
11872 dest
= state
->i_continue
->sym_ident
->def
;
11873 flatten(state
, first
, branch(state
, dest
, 0));
11876 static void goto_statement(struct compile_state
*state
, struct triple
*first
)
11878 struct hash_entry
*ident
;
11879 eat(state
, TOK_GOTO
);
11880 ident
= eat(state
, TOK_IDENT
)->ident
;
11881 if (!ident
->sym_label
) {
11882 /* If this is a forward branch allocate the label now,
11883 * it will be flattend in the appropriate location later.
11885 struct triple
*ins
;
11886 ins
= label(state
);
11887 label_symbol(state
, ident
, ins
, FUNCTION_SCOPE_DEPTH
);
11889 eat(state
, TOK_SEMI
);
11891 flatten(state
, first
, branch(state
, ident
->sym_label
->def
, 0));
11894 static void labeled_statement(struct compile_state
*state
, struct triple
*first
)
11896 struct triple
*ins
;
11897 struct hash_entry
*ident
;
11899 ident
= eat(state
, TOK_IDENT
)->ident
;
11900 if (ident
->sym_label
&& ident
->sym_label
->def
) {
11901 ins
= ident
->sym_label
->def
;
11902 put_occurance(ins
->occurance
);
11903 ins
->occurance
= new_occurance(state
);
11906 ins
= label(state
);
11907 label_symbol(state
, ident
, ins
, FUNCTION_SCOPE_DEPTH
);
11909 if (ins
->id
& TRIPLE_FLAG_FLATTENED
) {
11910 error(state
, 0, "label %s already defined", ident
->name
);
11912 flatten(state
, first
, ins
);
11914 eat(state
, TOK_COLON
);
11915 statement(state
, first
);
11918 static void switch_statement(struct compile_state
*state
, struct triple
*first
)
11920 struct triple
*value
, *top
, *end
, *dbranch
;
11921 struct hash_entry
*ident
;
11923 /* See if we have a valid switch statement */
11924 eat(state
, TOK_SWITCH
);
11925 eat(state
, TOK_LPAREN
);
11926 value
= expr(state
);
11927 integral(state
, value
);
11928 value
= read_expr(state
, value
);
11929 eat(state
, TOK_RPAREN
);
11930 /* Generate the needed pieces */
11931 top
= label(state
);
11932 end
= label(state
);
11933 dbranch
= branch(state
, end
, 0);
11934 /* Remember where case branches and break goes */
11935 start_scope(state
);
11936 ident
= state
->i_switch
;
11937 symbol(state
, ident
, &ident
->sym_ident
, value
, value
->type
);
11938 ident
= state
->i_case
;
11939 symbol(state
, ident
, &ident
->sym_ident
, top
, top
->type
);
11940 ident
= state
->i_break
;
11941 symbol(state
, ident
, &ident
->sym_ident
, end
, end
->type
);
11942 ident
= state
->i_default
;
11943 symbol(state
, ident
, &ident
->sym_ident
, dbranch
, dbranch
->type
);
11944 /* Thread them together */
11945 flatten(state
, first
, value
);
11946 flatten(state
, first
, top
);
11947 flatten(state
, first
, dbranch
);
11948 statement(state
, first
);
11949 flatten(state
, first
, end
);
11950 /* Cleanup the switch scope */
11954 static void case_statement(struct compile_state
*state
, struct triple
*first
)
11956 struct triple
*cvalue
, *dest
, *test
, *jmp
;
11957 struct triple
*ptr
, *value
, *top
, *dbranch
;
11959 /* See if w have a valid case statement */
11960 eat(state
, TOK_CASE
);
11961 cvalue
= constant_expr(state
);
11962 integral(state
, cvalue
);
11963 if (cvalue
->op
!= OP_INTCONST
) {
11964 error(state
, 0, "integer constant expected");
11966 eat(state
, TOK_COLON
);
11967 if (!state
->i_case
->sym_ident
) {
11968 error(state
, 0, "case statement not within a switch");
11971 /* Lookup the interesting pieces */
11972 top
= state
->i_case
->sym_ident
->def
;
11973 value
= state
->i_switch
->sym_ident
->def
;
11974 dbranch
= state
->i_default
->sym_ident
->def
;
11976 /* See if this case label has already been used */
11977 for(ptr
= top
; ptr
!= dbranch
; ptr
= ptr
->next
) {
11978 if (ptr
->op
!= OP_EQ
) {
11981 if (RHS(ptr
, 1)->u
.cval
== cvalue
->u
.cval
) {
11982 error(state
, 0, "duplicate case %d statement",
11986 /* Generate the needed pieces */
11987 dest
= label(state
);
11988 test
= triple(state
, OP_EQ
, &int_type
, value
, cvalue
);
11989 jmp
= branch(state
, dest
, test
);
11990 /* Thread the pieces together */
11991 flatten(state
, dbranch
, test
);
11992 flatten(state
, dbranch
, jmp
);
11993 flatten(state
, dbranch
, label(state
));
11994 flatten(state
, first
, dest
);
11995 statement(state
, first
);
11998 static void default_statement(struct compile_state
*state
, struct triple
*first
)
12000 struct triple
*dest
;
12001 struct triple
*dbranch
, *end
;
12003 /* See if we have a valid default statement */
12004 eat(state
, TOK_DEFAULT
);
12005 eat(state
, TOK_COLON
);
12007 if (!state
->i_case
->sym_ident
) {
12008 error(state
, 0, "default statement not within a switch");
12011 /* Lookup the interesting pieces */
12012 dbranch
= state
->i_default
->sym_ident
->def
;
12013 end
= state
->i_break
->sym_ident
->def
;
12015 /* See if a default statement has already happened */
12016 if (TARG(dbranch
, 0) != end
) {
12017 error(state
, 0, "duplicate default statement");
12020 /* Generate the needed pieces */
12021 dest
= label(state
);
12023 /* Blame the branch on the default statement */
12024 put_occurance(dbranch
->occurance
);
12025 dbranch
->occurance
= new_occurance(state
);
12027 /* Thread the pieces together */
12028 TARG(dbranch
, 0) = dest
;
12029 use_triple(dest
, dbranch
);
12030 flatten(state
, first
, dest
);
12031 statement(state
, first
);
12034 static void asm_statement(struct compile_state
*state
, struct triple
*first
)
12036 struct asm_info
*info
;
12038 struct triple
*constraint
;
12039 struct triple
*expr
;
12040 } out_param
[MAX_LHS
], in_param
[MAX_RHS
], clob_param
[MAX_LHS
];
12041 struct triple
*def
, *asm_str
;
12042 int out
, in
, clobbers
, more
, colons
, i
;
12046 eat(state
, TOK_ASM
);
12047 /* For now ignore the qualifiers */
12048 switch(peek(state
)) {
12050 eat(state
, TOK_CONST
);
12053 eat(state
, TOK_VOLATILE
);
12054 flags
|= TRIPLE_FLAG_VOLATILE
;
12057 eat(state
, TOK_LPAREN
);
12058 asm_str
= string_constant(state
);
12061 out
= in
= clobbers
= 0;
12063 if ((colons
== 0) && (peek(state
) == TOK_COLON
)) {
12064 eat(state
, TOK_COLON
);
12066 more
= (peek(state
) == TOK_LIT_STRING
);
12068 struct triple
*var
;
12069 struct triple
*constraint
;
12072 if (out
> MAX_LHS
) {
12073 error(state
, 0, "Maximum output count exceeded.");
12075 constraint
= string_constant(state
);
12076 str
= constraint
->u
.blob
;
12077 if (str
[0] != '=') {
12078 error(state
, 0, "Output constraint does not start with =");
12080 constraint
->u
.blob
= str
+ 1;
12081 eat(state
, TOK_LPAREN
);
12082 var
= conditional_expr(state
);
12083 eat(state
, TOK_RPAREN
);
12085 lvalue(state
, var
);
12086 out_param
[out
].constraint
= constraint
;
12087 out_param
[out
].expr
= var
;
12088 if (peek(state
) == TOK_COMMA
) {
12089 eat(state
, TOK_COMMA
);
12096 if ((colons
== 1) && (peek(state
) == TOK_COLON
)) {
12097 eat(state
, TOK_COLON
);
12099 more
= (peek(state
) == TOK_LIT_STRING
);
12101 struct triple
*val
;
12102 struct triple
*constraint
;
12105 if (in
> MAX_RHS
) {
12106 error(state
, 0, "Maximum input count exceeded.");
12108 constraint
= string_constant(state
);
12109 str
= constraint
->u
.blob
;
12110 if (digitp(str
[0] && str
[1] == '\0')) {
12112 val
= digval(str
[0]);
12113 if ((val
< 0) || (val
>= out
)) {
12114 error(state
, 0, "Invalid input constraint %d", val
);
12117 eat(state
, TOK_LPAREN
);
12118 val
= conditional_expr(state
);
12119 eat(state
, TOK_RPAREN
);
12121 in_param
[in
].constraint
= constraint
;
12122 in_param
[in
].expr
= val
;
12123 if (peek(state
) == TOK_COMMA
) {
12124 eat(state
, TOK_COMMA
);
12132 if ((colons
== 2) && (peek(state
) == TOK_COLON
)) {
12133 eat(state
, TOK_COLON
);
12135 more
= (peek(state
) == TOK_LIT_STRING
);
12137 struct triple
*clobber
;
12139 if ((clobbers
+ out
) > MAX_LHS
) {
12140 error(state
, 0, "Maximum clobber limit exceeded.");
12142 clobber
= string_constant(state
);
12144 clob_param
[clobbers
].constraint
= clobber
;
12145 if (peek(state
) == TOK_COMMA
) {
12146 eat(state
, TOK_COMMA
);
12152 eat(state
, TOK_RPAREN
);
12153 eat(state
, TOK_SEMI
);
12156 info
= xcmalloc(sizeof(*info
), "asm_info");
12157 info
->str
= asm_str
->u
.blob
;
12158 free_triple(state
, asm_str
);
12160 def
= new_triple(state
, OP_ASM
, &void_type
, clobbers
+ out
, in
);
12161 def
->u
.ainfo
= info
;
12164 /* Find the register constraints */
12165 for(i
= 0; i
< out
; i
++) {
12166 struct triple
*constraint
;
12167 constraint
= out_param
[i
].constraint
;
12168 info
->tmpl
.lhs
[i
] = arch_reg_constraint(state
,
12169 out_param
[i
].expr
->type
, constraint
->u
.blob
);
12170 free_triple(state
, constraint
);
12172 for(; i
- out
< clobbers
; i
++) {
12173 struct triple
*constraint
;
12174 constraint
= clob_param
[i
- out
].constraint
;
12175 info
->tmpl
.lhs
[i
] = arch_reg_clobber(state
, constraint
->u
.blob
);
12176 free_triple(state
, constraint
);
12178 for(i
= 0; i
< in
; i
++) {
12179 struct triple
*constraint
;
12181 constraint
= in_param
[i
].constraint
;
12182 str
= constraint
->u
.blob
;
12183 if (digitp(str
[0]) && str
[1] == '\0') {
12184 struct reg_info cinfo
;
12186 val
= digval(str
[0]);
12187 cinfo
.reg
= info
->tmpl
.lhs
[val
].reg
;
12188 cinfo
.regcm
= arch_type_to_regcm(state
, in_param
[i
].expr
->type
);
12189 cinfo
.regcm
&= info
->tmpl
.lhs
[val
].regcm
;
12190 if (cinfo
.reg
== REG_UNSET
) {
12191 cinfo
.reg
= REG_VIRT0
+ val
;
12193 if (cinfo
.regcm
== 0) {
12194 error(state
, 0, "No registers for %d", val
);
12196 info
->tmpl
.lhs
[val
] = cinfo
;
12197 info
->tmpl
.rhs
[i
] = cinfo
;
12200 info
->tmpl
.rhs
[i
] = arch_reg_constraint(state
,
12201 in_param
[i
].expr
->type
, str
);
12203 free_triple(state
, constraint
);
12206 /* Now build the helper expressions */
12207 for(i
= 0; i
< in
; i
++) {
12208 RHS(def
, i
) = read_expr(state
, in_param
[i
].expr
);
12210 flatten(state
, first
, def
);
12211 for(i
= 0; i
< (out
+ clobbers
); i
++) {
12213 struct triple
*piece
;
12215 type
= out_param
[i
].expr
->type
;
12217 size_t size
= arch_reg_size(info
->tmpl
.lhs
[i
].reg
);
12218 if (size
>= SIZEOF_LONG
) {
12219 type
= &ulong_type
;
12221 else if (size
>= SIZEOF_INT
) {
12224 else if (size
>= SIZEOF_SHORT
) {
12225 type
= &ushort_type
;
12228 type
= &uchar_type
;
12231 piece
= triple(state
, OP_PIECE
, type
, def
, 0);
12233 LHS(def
, i
) = piece
;
12234 flatten(state
, first
, piece
);
12236 /* And write the helpers to their destinations */
12237 for(i
= 0; i
< out
; i
++) {
12238 struct triple
*piece
;
12239 piece
= LHS(def
, i
);
12240 flatten(state
, first
,
12241 write_expr(state
, out_param
[i
].expr
, piece
));
12246 static int isdecl(int tok
)
12269 case TOK_TYPE_NAME
: /* typedef name */
12276 static void compound_statement(struct compile_state
*state
, struct triple
*first
)
12278 eat(state
, TOK_LBRACE
);
12279 start_scope(state
);
12281 /* statement-list opt */
12282 while (peek(state
) != TOK_RBRACE
) {
12283 statement(state
, first
);
12286 eat(state
, TOK_RBRACE
);
12289 static void statement(struct compile_state
*state
, struct triple
*first
)
12293 if (tok
== TOK_LBRACE
) {
12294 compound_statement(state
, first
);
12296 else if (tok
== TOK_IF
) {
12297 if_statement(state
, first
);
12299 else if (tok
== TOK_FOR
) {
12300 for_statement(state
, first
);
12302 else if (tok
== TOK_WHILE
) {
12303 while_statement(state
, first
);
12305 else if (tok
== TOK_DO
) {
12306 do_statement(state
, first
);
12308 else if (tok
== TOK_RETURN
) {
12309 return_statement(state
, first
);
12311 else if (tok
== TOK_BREAK
) {
12312 break_statement(state
, first
);
12314 else if (tok
== TOK_CONTINUE
) {
12315 continue_statement(state
, first
);
12317 else if (tok
== TOK_GOTO
) {
12318 goto_statement(state
, first
);
12320 else if (tok
== TOK_SWITCH
) {
12321 switch_statement(state
, first
);
12323 else if (tok
== TOK_ASM
) {
12324 asm_statement(state
, first
);
12326 else if ((tok
== TOK_IDENT
) && (peek2(state
) == TOK_COLON
)) {
12327 labeled_statement(state
, first
);
12329 else if (tok
== TOK_CASE
) {
12330 case_statement(state
, first
);
12332 else if (tok
== TOK_DEFAULT
) {
12333 default_statement(state
, first
);
12335 else if (isdecl(tok
)) {
12336 /* This handles C99 intermixing of statements and decls */
12337 decl(state
, first
);
12340 expr_statement(state
, first
);
12344 static struct type
*param_decl(struct compile_state
*state
)
12347 struct hash_entry
*ident
;
12348 /* Cheat so the declarator will know we are not global */
12349 start_scope(state
);
12351 type
= decl_specifiers(state
);
12352 type
= declarator(state
, type
, &ident
, 0);
12353 type
->field_ident
= ident
;
12358 static struct type
*param_type_list(struct compile_state
*state
, struct type
*type
)
12360 struct type
*ftype
, **next
;
12361 ftype
= new_type(TYPE_FUNCTION
| (type
->type
& STOR_MASK
), type
, param_decl(state
));
12362 next
= &ftype
->right
;
12363 ftype
->elements
= 1;
12364 while(peek(state
) == TOK_COMMA
) {
12365 eat(state
, TOK_COMMA
);
12366 if (peek(state
) == TOK_DOTS
) {
12367 eat(state
, TOK_DOTS
);
12368 error(state
, 0, "variadic functions not supported");
12371 *next
= new_type(TYPE_PRODUCT
, *next
, param_decl(state
));
12372 next
= &((*next
)->right
);
12379 static struct type
*type_name(struct compile_state
*state
)
12382 type
= specifier_qualifier_list(state
);
12383 /* abstract-declarator (may consume no tokens) */
12384 type
= declarator(state
, type
, 0, 0);
12388 static struct type
*direct_declarator(
12389 struct compile_state
*state
, struct type
*type
,
12390 struct hash_entry
**pident
, int need_ident
)
12392 struct hash_entry
*ident
;
12393 struct type
*outer
;
12396 arrays_complete(state
, type
);
12397 switch(peek(state
)) {
12399 ident
= eat(state
, TOK_IDENT
)->ident
;
12401 error(state
, 0, "Unexpected identifier found");
12403 /* The name of what we are declaring */
12407 eat(state
, TOK_LPAREN
);
12408 outer
= declarator(state
, type
, pident
, need_ident
);
12409 eat(state
, TOK_RPAREN
);
12413 error(state
, 0, "Identifier expected");
12419 arrays_complete(state
, type
);
12420 switch(peek(state
)) {
12422 eat(state
, TOK_LPAREN
);
12423 type
= param_type_list(state
, type
);
12424 eat(state
, TOK_RPAREN
);
12428 unsigned int qualifiers
;
12429 struct triple
*value
;
12431 eat(state
, TOK_LBRACKET
);
12432 if (peek(state
) != TOK_RBRACKET
) {
12433 value
= constant_expr(state
);
12434 integral(state
, value
);
12436 eat(state
, TOK_RBRACKET
);
12438 qualifiers
= type
->type
& (QUAL_MASK
| STOR_MASK
);
12439 type
= new_type(TYPE_ARRAY
| qualifiers
, type
, 0);
12441 type
->elements
= value
->u
.cval
;
12442 free_triple(state
, value
);
12444 type
->elements
= ELEMENT_COUNT_UNSPECIFIED
;
12455 struct type
*inner
;
12456 arrays_complete(state
, type
);
12458 for(inner
= outer
; inner
->left
; inner
= inner
->left
)
12460 inner
->left
= type
;
12466 static struct type
*declarator(
12467 struct compile_state
*state
, struct type
*type
,
12468 struct hash_entry
**pident
, int need_ident
)
12470 while(peek(state
) == TOK_STAR
) {
12471 eat(state
, TOK_STAR
);
12472 type
= new_type(TYPE_POINTER
| (type
->type
& STOR_MASK
), type
, 0);
12474 type
= direct_declarator(state
, type
, pident
, need_ident
);
12478 static struct type
*typedef_name(
12479 struct compile_state
*state
, unsigned int specifiers
)
12481 struct hash_entry
*ident
;
12483 ident
= eat(state
, TOK_TYPE_NAME
)->ident
;
12484 type
= ident
->sym_ident
->type
;
12485 specifiers
|= type
->type
& QUAL_MASK
;
12486 if ((specifiers
& (STOR_MASK
| QUAL_MASK
)) !=
12487 (type
->type
& (STOR_MASK
| QUAL_MASK
))) {
12488 type
= clone_type(specifiers
, type
);
12493 static struct type
*enum_specifier(
12494 struct compile_state
*state
, unsigned int spec
)
12496 struct hash_entry
*ident
;
12499 struct type
*enum_type
;
12502 eat(state
, TOK_ENUM
);
12504 if ((tok
== TOK_IDENT
) || (tok
== TOK_ENUM_CONST
) || (tok
== TOK_TYPE_NAME
)) {
12505 ident
= eat(state
, tok
)->ident
;
12508 if (!ident
|| (peek(state
) == TOK_LBRACE
)) {
12509 struct type
**next
;
12510 eat(state
, TOK_LBRACE
);
12511 enum_type
= new_type(TYPE_ENUM
| spec
, 0, 0);
12512 enum_type
->type_ident
= ident
;
12513 next
= &enum_type
->right
;
12515 struct hash_entry
*eident
;
12516 struct triple
*value
;
12517 struct type
*entry
;
12518 eident
= eat(state
, TOK_IDENT
)->ident
;
12519 if (eident
->sym_ident
) {
12520 error(state
, 0, "%s already declared",
12523 eident
->tok
= TOK_ENUM_CONST
;
12524 if (peek(state
) == TOK_EQ
) {
12525 struct triple
*val
;
12526 eat(state
, TOK_EQ
);
12527 val
= constant_expr(state
);
12528 integral(state
, val
);
12529 base
= val
->u
.cval
;
12531 value
= int_const(state
, &int_type
, base
);
12532 symbol(state
, eident
, &eident
->sym_ident
, value
, &int_type
);
12533 entry
= new_type(TYPE_LIST
, 0, 0);
12534 entry
->field_ident
= eident
;
12536 next
= &entry
->right
;
12538 if (peek(state
) == TOK_COMMA
) {
12539 eat(state
, TOK_COMMA
);
12541 } while(peek(state
) != TOK_RBRACE
);
12542 eat(state
, TOK_RBRACE
);
12544 symbol(state
, ident
, &ident
->sym_tag
, 0, enum_type
);
12547 if (ident
&& ident
->sym_tag
&&
12548 ident
->sym_tag
->type
&&
12549 ((ident
->sym_tag
->type
->type
& TYPE_MASK
) == TYPE_ENUM
)) {
12550 enum_type
= clone_type(spec
, ident
->sym_tag
->type
);
12552 else if (ident
&& !enum_type
) {
12553 error(state
, 0, "enum %s undeclared", ident
->name
);
12558 static struct type
*struct_declarator(
12559 struct compile_state
*state
, struct type
*type
, struct hash_entry
**ident
)
12561 if (peek(state
) != TOK_COLON
) {
12562 type
= declarator(state
, type
, ident
, 1);
12564 if (peek(state
) == TOK_COLON
) {
12565 struct triple
*value
;
12566 eat(state
, TOK_COLON
);
12567 value
= constant_expr(state
);
12568 if (value
->op
!= OP_INTCONST
) {
12569 error(state
, 0, "Invalid constant expression");
12571 if (value
->u
.cval
> size_of(state
, type
)) {
12572 error(state
, 0, "bitfield larger than base type");
12574 if (!TYPE_INTEGER(type
->type
) || ((type
->type
& TYPE_MASK
) == TYPE_BITFIELD
)) {
12575 error(state
, 0, "bitfield base not an integer type");
12577 type
= new_type(TYPE_BITFIELD
, type
, 0);
12578 type
->elements
= value
->u
.cval
;
12583 static struct type
*struct_or_union_specifier(
12584 struct compile_state
*state
, unsigned int spec
)
12586 struct type
*struct_type
;
12587 struct hash_entry
*ident
;
12588 unsigned int type_main
;
12589 unsigned int type_join
;
12593 switch(peek(state
)) {
12595 eat(state
, TOK_STRUCT
);
12596 type_main
= TYPE_STRUCT
;
12597 type_join
= TYPE_PRODUCT
;
12600 eat(state
, TOK_UNION
);
12601 type_main
= TYPE_UNION
;
12602 type_join
= TYPE_OVERLAP
;
12605 eat(state
, TOK_STRUCT
);
12606 type_main
= TYPE_STRUCT
;
12607 type_join
= TYPE_PRODUCT
;
12611 if ((tok
== TOK_IDENT
) || (tok
== TOK_ENUM_CONST
) || (tok
== TOK_TYPE_NAME
)) {
12612 ident
= eat(state
, tok
)->ident
;
12614 if (!ident
|| (peek(state
) == TOK_LBRACE
)) {
12616 struct type
**next
;
12618 eat(state
, TOK_LBRACE
);
12619 next
= &struct_type
;
12621 struct type
*base_type
;
12623 base_type
= specifier_qualifier_list(state
);
12626 struct hash_entry
*fident
;
12628 type
= struct_declarator(state
, base_type
, &fident
);
12630 if (peek(state
) == TOK_COMMA
) {
12632 eat(state
, TOK_COMMA
);
12634 type
= clone_type(0, type
);
12635 type
->field_ident
= fident
;
12637 *next
= new_type(type_join
, *next
, type
);
12638 next
= &((*next
)->right
);
12643 eat(state
, TOK_SEMI
);
12644 } while(peek(state
) != TOK_RBRACE
);
12645 eat(state
, TOK_RBRACE
);
12646 struct_type
= new_type(type_main
| spec
, struct_type
, 0);
12647 struct_type
->type_ident
= ident
;
12648 struct_type
->elements
= elements
;
12650 symbol(state
, ident
, &ident
->sym_tag
, 0, struct_type
);
12653 if (ident
&& ident
->sym_tag
&&
12654 ident
->sym_tag
->type
&&
12655 ((ident
->sym_tag
->type
->type
& TYPE_MASK
) == type_main
)) {
12656 struct_type
= clone_type(spec
, ident
->sym_tag
->type
);
12658 else if (ident
&& !struct_type
) {
12659 error(state
, 0, "%s %s undeclared",
12660 (type_main
== TYPE_STRUCT
)?"struct" : "union",
12663 return struct_type
;
12666 static unsigned int storage_class_specifier_opt(struct compile_state
*state
)
12668 unsigned int specifiers
;
12669 switch(peek(state
)) {
12671 eat(state
, TOK_AUTO
);
12672 specifiers
= STOR_AUTO
;
12675 eat(state
, TOK_REGISTER
);
12676 specifiers
= STOR_REGISTER
;
12679 eat(state
, TOK_STATIC
);
12680 specifiers
= STOR_STATIC
;
12683 eat(state
, TOK_EXTERN
);
12684 specifiers
= STOR_EXTERN
;
12687 eat(state
, TOK_TYPEDEF
);
12688 specifiers
= STOR_TYPEDEF
;
12691 if (state
->scope_depth
<= GLOBAL_SCOPE_DEPTH
) {
12692 specifiers
= STOR_LOCAL
;
12695 specifiers
= STOR_AUTO
;
12701 static unsigned int function_specifier_opt(struct compile_state
*state
)
12703 /* Ignore the inline keyword */
12704 unsigned int specifiers
;
12706 switch(peek(state
)) {
12708 eat(state
, TOK_INLINE
);
12709 specifiers
= STOR_INLINE
;
12714 static unsigned int attrib(struct compile_state
*state
, unsigned int attributes
)
12716 int tok
= peek(state
);
12720 /* The empty attribute ignore it */
12723 case TOK_ENUM_CONST
:
12724 case TOK_TYPE_NAME
:
12726 struct hash_entry
*ident
;
12727 ident
= eat(state
, TOK_IDENT
)->ident
;
12729 if (ident
== state
->i_noinline
) {
12730 if (attributes
& ATTRIB_ALWAYS_INLINE
) {
12731 error(state
, 0, "both always_inline and noinline attribtes");
12733 attributes
|= ATTRIB_NOINLINE
;
12735 else if (ident
== state
->i_always_inline
) {
12736 if (attributes
& ATTRIB_NOINLINE
) {
12737 error(state
, 0, "both noinline and always_inline attribtes");
12739 attributes
|= ATTRIB_ALWAYS_INLINE
;
12741 else if (ident
== state
->i_noreturn
) {
12742 // attribute((noreturn)) does nothing (yet?)
12744 else if (ident
== state
->i_unused
) {
12745 // attribute((unused)) does nothing (yet?)
12747 else if (ident
== state
->i_packed
) {
12748 // attribute((packed)) does nothing (yet?)
12751 error(state
, 0, "Unknown attribute:%s", ident
->name
);
12756 error(state
, 0, "Unexpected token: %s\n", tokens
[tok
]);
12762 static unsigned int attribute_list(struct compile_state
*state
, unsigned type
)
12764 type
= attrib(state
, type
);
12765 while(peek(state
) == TOK_COMMA
) {
12766 eat(state
, TOK_COMMA
);
12767 type
= attrib(state
, type
);
12772 static unsigned int attributes_opt(struct compile_state
*state
, unsigned type
)
12774 if (peek(state
) == TOK_ATTRIBUTE
) {
12775 eat(state
, TOK_ATTRIBUTE
);
12776 eat(state
, TOK_LPAREN
);
12777 eat(state
, TOK_LPAREN
);
12778 type
= attribute_list(state
, type
);
12779 eat(state
, TOK_RPAREN
);
12780 eat(state
, TOK_RPAREN
);
12785 static unsigned int type_qualifiers(struct compile_state
*state
)
12787 unsigned int specifiers
;
12790 specifiers
= QUAL_NONE
;
12792 switch(peek(state
)) {
12794 eat(state
, TOK_CONST
);
12795 specifiers
|= QUAL_CONST
;
12798 eat(state
, TOK_VOLATILE
);
12799 specifiers
|= QUAL_VOLATILE
;
12802 eat(state
, TOK_RESTRICT
);
12803 specifiers
|= QUAL_RESTRICT
;
12813 static struct type
*type_specifier(
12814 struct compile_state
*state
, unsigned int spec
)
12819 switch((tok
= peek(state
))) {
12821 eat(state
, TOK_VOID
);
12822 type
= new_type(TYPE_VOID
| spec
, 0, 0);
12825 eat(state
, TOK_CHAR
);
12826 type
= new_type(TYPE_CHAR
| spec
, 0, 0);
12829 eat(state
, TOK_SHORT
);
12830 if (peek(state
) == TOK_INT
) {
12831 eat(state
, TOK_INT
);
12833 type
= new_type(TYPE_SHORT
| spec
, 0, 0);
12836 eat(state
, TOK_INT
);
12837 type
= new_type(TYPE_INT
| spec
, 0, 0);
12840 eat(state
, TOK_LONG
);
12841 switch(peek(state
)) {
12843 eat(state
, TOK_LONG
);
12844 error(state
, 0, "long long not supported");
12847 eat(state
, TOK_DOUBLE
);
12848 error(state
, 0, "long double not supported");
12851 eat(state
, TOK_INT
);
12852 type
= new_type(TYPE_LONG
| spec
, 0, 0);
12855 type
= new_type(TYPE_LONG
| spec
, 0, 0);
12860 eat(state
, TOK_FLOAT
);
12861 error(state
, 0, "type float not supported");
12864 eat(state
, TOK_DOUBLE
);
12865 error(state
, 0, "type double not supported");
12868 eat(state
, TOK_SIGNED
);
12869 switch(peek(state
)) {
12871 eat(state
, TOK_LONG
);
12872 switch(peek(state
)) {
12874 eat(state
, TOK_LONG
);
12875 error(state
, 0, "type long long not supported");
12878 eat(state
, TOK_INT
);
12879 type
= new_type(TYPE_LONG
| spec
, 0, 0);
12882 type
= new_type(TYPE_LONG
| spec
, 0, 0);
12887 eat(state
, TOK_INT
);
12888 type
= new_type(TYPE_INT
| spec
, 0, 0);
12891 eat(state
, TOK_SHORT
);
12892 type
= new_type(TYPE_SHORT
| spec
, 0, 0);
12895 eat(state
, TOK_CHAR
);
12896 type
= new_type(TYPE_CHAR
| spec
, 0, 0);
12899 type
= new_type(TYPE_INT
| spec
, 0, 0);
12904 eat(state
, TOK_UNSIGNED
);
12905 switch(peek(state
)) {
12907 eat(state
, TOK_LONG
);
12908 switch(peek(state
)) {
12910 eat(state
, TOK_LONG
);
12911 error(state
, 0, "unsigned long long not supported");
12914 eat(state
, TOK_INT
);
12915 type
= new_type(TYPE_ULONG
| spec
, 0, 0);
12918 type
= new_type(TYPE_ULONG
| spec
, 0, 0);
12923 eat(state
, TOK_INT
);
12924 type
= new_type(TYPE_UINT
| spec
, 0, 0);
12927 eat(state
, TOK_SHORT
);
12928 type
= new_type(TYPE_USHORT
| spec
, 0, 0);
12931 eat(state
, TOK_CHAR
);
12932 type
= new_type(TYPE_UCHAR
| spec
, 0, 0);
12935 type
= new_type(TYPE_UINT
| spec
, 0, 0);
12939 /* struct or union specifier */
12942 type
= struct_or_union_specifier(state
, spec
);
12944 /* enum-spefifier */
12946 type
= enum_specifier(state
, spec
);
12949 case TOK_TYPE_NAME
:
12950 type
= typedef_name(state
, spec
);
12953 error(state
, 0, "bad type specifier %s",
12960 static int istype(int tok
)
12978 case TOK_TYPE_NAME
:
12986 static struct type
*specifier_qualifier_list(struct compile_state
*state
)
12989 unsigned int specifiers
= 0;
12991 /* type qualifiers */
12992 specifiers
|= type_qualifiers(state
);
12994 /* type specifier */
12995 type
= type_specifier(state
, specifiers
);
13000 #if DEBUG_ROMCC_WARNING
13001 static int isdecl_specifier(int tok
)
13004 /* storage class specifier */
13010 /* type qualifier */
13014 /* type specifiers */
13024 /* struct or union specifier */
13027 /* enum-spefifier */
13030 case TOK_TYPE_NAME
:
13031 /* function specifiers */
13040 static struct type
*decl_specifiers(struct compile_state
*state
)
13043 unsigned int specifiers
;
13044 /* I am overly restrictive in the arragement of specifiers supported.
13045 * C is overly flexible in this department it makes interpreting
13046 * the parse tree difficult.
13050 /* storage class specifier */
13051 specifiers
|= storage_class_specifier_opt(state
);
13053 /* function-specifier */
13054 specifiers
|= function_specifier_opt(state
);
13057 specifiers
|= attributes_opt(state
, 0);
13059 /* type qualifier */
13060 specifiers
|= type_qualifiers(state
);
13062 /* type specifier */
13063 type
= type_specifier(state
, specifiers
);
13067 struct field_info
{
13072 static struct field_info
designator(struct compile_state
*state
, struct type
*type
)
13075 struct field_info info
;
13079 switch(peek(state
)) {
13082 struct triple
*value
;
13083 if ((type
->type
& TYPE_MASK
) != TYPE_ARRAY
) {
13084 error(state
, 0, "Array designator not in array initializer");
13086 eat(state
, TOK_LBRACKET
);
13087 value
= constant_expr(state
);
13088 eat(state
, TOK_RBRACKET
);
13090 info
.type
= type
->left
;
13091 info
.offset
= value
->u
.cval
* size_of(state
, info
.type
);
13096 struct hash_entry
*field
;
13097 if (((type
->type
& TYPE_MASK
) != TYPE_STRUCT
) &&
13098 ((type
->type
& TYPE_MASK
) != TYPE_UNION
))
13100 error(state
, 0, "Struct designator not in struct initializer");
13102 eat(state
, TOK_DOT
);
13103 field
= eat(state
, TOK_IDENT
)->ident
;
13104 info
.offset
= field_offset(state
, type
, field
);
13105 info
.type
= field_type(state
, type
, field
);
13109 error(state
, 0, "Invalid designator");
13112 } while((tok
== TOK_LBRACKET
) || (tok
== TOK_DOT
));
13113 eat(state
, TOK_EQ
);
13117 static struct triple
*initializer(
13118 struct compile_state
*state
, struct type
*type
)
13120 struct triple
*result
;
13121 #if DEBUG_ROMCC_WARNINGS
13122 #warning "FIXME more consistent initializer handling (where should eval_const_expr go?"
13124 if (peek(state
) != TOK_LBRACE
) {
13125 result
= assignment_expr(state
);
13126 if (((type
->type
& TYPE_MASK
) == TYPE_ARRAY
) &&
13127 (type
->elements
== ELEMENT_COUNT_UNSPECIFIED
) &&
13128 ((result
->type
->type
& TYPE_MASK
) == TYPE_ARRAY
) &&
13129 (result
->type
->elements
!= ELEMENT_COUNT_UNSPECIFIED
) &&
13130 (equiv_types(type
->left
, result
->type
->left
))) {
13131 type
->elements
= result
->type
->elements
;
13133 if (is_lvalue(state
, result
) &&
13134 ((result
->type
->type
& TYPE_MASK
) == TYPE_ARRAY
) &&
13135 (type
->type
& TYPE_MASK
) != TYPE_ARRAY
)
13137 result
= lvalue_conversion(state
, result
);
13139 if (!is_init_compatible(state
, type
, result
->type
)) {
13140 error(state
, 0, "Incompatible types in initializer");
13142 if (!equiv_types(type
, result
->type
)) {
13143 result
= mk_cast_expr(state
, type
, result
);
13149 struct field_info info
;
13151 if (((type
->type
& TYPE_MASK
) != TYPE_ARRAY
) &&
13152 ((type
->type
& TYPE_MASK
) != TYPE_STRUCT
)) {
13153 internal_error(state
, 0, "unknown initializer type");
13156 info
.type
= type
->left
;
13157 if ((type
->type
& TYPE_MASK
) == TYPE_STRUCT
) {
13158 info
.type
= next_field(state
, type
, 0);
13160 if (type
->elements
== ELEMENT_COUNT_UNSPECIFIED
) {
13163 max_offset
= size_of(state
, type
);
13165 buf
= xcmalloc(bits_to_bytes(max_offset
), "initializer");
13166 eat(state
, TOK_LBRACE
);
13168 struct triple
*value
;
13169 struct type
*value_type
;
13175 if ((tok
== TOK_LBRACKET
) || (tok
== TOK_DOT
)) {
13176 info
= designator(state
, type
);
13178 if ((type
->elements
!= ELEMENT_COUNT_UNSPECIFIED
) &&
13179 (info
.offset
>= max_offset
)) {
13180 error(state
, 0, "element beyond bounds");
13182 value_type
= info
.type
;
13183 value
= eval_const_expr(state
, initializer(state
, value_type
));
13184 value_size
= size_of(state
, value_type
);
13185 if (((type
->type
& TYPE_MASK
) == TYPE_ARRAY
) &&
13186 (type
->elements
== ELEMENT_COUNT_UNSPECIFIED
) &&
13187 (max_offset
<= info
.offset
)) {
13191 old_size
= max_offset
;
13192 max_offset
= info
.offset
+ value_size
;
13193 buf
= xmalloc(bits_to_bytes(max_offset
), "initializer");
13194 memcpy(buf
, old_buf
, bits_to_bytes(old_size
));
13197 dest
= ((char *)buf
) + bits_to_bytes(info
.offset
);
13198 #if DEBUG_INITIALIZER
13199 fprintf(state
->errout
, "dest = buf + %d max_offset: %d value_size: %d op: %d\n",
13201 bits_to_bytes(max_offset
),
13202 bits_to_bytes(value_size
),
13205 if (value
->op
== OP_BLOBCONST
) {
13206 memcpy(dest
, value
->u
.blob
, bits_to_bytes(value_size
));
13208 else if ((value
->op
== OP_INTCONST
) && (value_size
== SIZEOF_I8
)) {
13209 #if DEBUG_INITIALIZER
13210 fprintf(state
->errout
, "byte: %02x\n", value
->u
.cval
& 0xff);
13212 *((uint8_t *)dest
) = value
->u
.cval
& 0xff;
13214 else if ((value
->op
== OP_INTCONST
) && (value_size
== SIZEOF_I16
)) {
13215 *((uint16_t *)dest
) = value
->u
.cval
& 0xffff;
13217 else if ((value
->op
== OP_INTCONST
) && (value_size
== SIZEOF_I32
)) {
13218 *((uint32_t *)dest
) = value
->u
.cval
& 0xffffffff;
13221 internal_error(state
, 0, "unhandled constant initializer");
13223 free_triple(state
, value
);
13224 if (peek(state
) == TOK_COMMA
) {
13225 eat(state
, TOK_COMMA
);
13228 info
.offset
+= value_size
;
13229 if ((type
->type
& TYPE_MASK
) == TYPE_STRUCT
) {
13230 info
.type
= next_field(state
, type
, info
.type
);
13231 info
.offset
= field_offset(state
, type
,
13232 info
.type
->field_ident
);
13234 } while(comma
&& (peek(state
) != TOK_RBRACE
));
13235 if ((type
->elements
== ELEMENT_COUNT_UNSPECIFIED
) &&
13236 ((type
->type
& TYPE_MASK
) == TYPE_ARRAY
)) {
13237 type
->elements
= max_offset
/ size_of(state
, type
->left
);
13239 eat(state
, TOK_RBRACE
);
13240 result
= triple(state
, OP_BLOBCONST
, type
, 0, 0);
13241 result
->u
.blob
= buf
;
13246 static void resolve_branches(struct compile_state
*state
, struct triple
*first
)
13248 /* Make a second pass and finish anything outstanding
13249 * with respect to branches. The only outstanding item
13250 * is to see if there are goto to labels that have not
13251 * been defined and to error about them.
13254 struct triple
*ins
;
13255 /* Also error on branches that do not use their targets */
13258 if (!triple_is_ret(state
, ins
)) {
13259 struct triple
**expr
;
13260 struct triple_set
*set
;
13261 expr
= triple_targ(state
, ins
, 0);
13262 for(; expr
; expr
= triple_targ(state
, ins
, expr
)) {
13263 struct triple
*targ
;
13265 for(set
= targ
?targ
->use
:0; set
; set
= set
->next
) {
13266 if (set
->member
== ins
) {
13271 internal_error(state
, ins
, "targ not used");
13276 } while(ins
!= first
);
13277 /* See if there are goto to labels that have not been defined */
13278 for(i
= 0; i
< HASH_TABLE_SIZE
; i
++) {
13279 struct hash_entry
*entry
;
13280 for(entry
= state
->hash_table
[i
]; entry
; entry
= entry
->next
) {
13281 struct triple
*ins
;
13282 if (!entry
->sym_label
) {
13285 ins
= entry
->sym_label
->def
;
13286 if (!(ins
->id
& TRIPLE_FLAG_FLATTENED
)) {
13287 error(state
, ins
, "label `%s' used but not defined",
13294 static struct triple
*function_definition(
13295 struct compile_state
*state
, struct type
*type
)
13297 struct triple
*def
, *tmp
, *first
, *end
, *retvar
, *ret
;
13298 struct triple
*fname
;
13299 struct type
*fname_type
;
13300 struct hash_entry
*ident
;
13301 struct type
*param
, *crtype
, *ctype
;
13303 if ((type
->type
&TYPE_MASK
) != TYPE_FUNCTION
) {
13304 error(state
, 0, "Invalid function header");
13307 /* Verify the function type */
13308 if (((type
->right
->type
& TYPE_MASK
) != TYPE_VOID
) &&
13309 ((type
->right
->type
& TYPE_MASK
) != TYPE_PRODUCT
) &&
13310 (type
->right
->field_ident
== 0)) {
13311 error(state
, 0, "Invalid function parameters");
13313 param
= type
->right
;
13315 while((param
->type
& TYPE_MASK
) == TYPE_PRODUCT
) {
13317 if (!param
->left
->field_ident
) {
13318 error(state
, 0, "No identifier for parameter %d\n", i
);
13320 param
= param
->right
;
13323 if (((param
->type
& TYPE_MASK
) != TYPE_VOID
) && !param
->field_ident
) {
13324 error(state
, 0, "No identifier for paramter %d\n", i
);
13327 /* Get a list of statements for this function. */
13328 def
= triple(state
, OP_LIST
, type
, 0, 0);
13330 /* Start a new scope for the passed parameters */
13331 start_scope(state
);
13333 /* Put a label at the very start of a function */
13334 first
= label(state
);
13335 RHS(def
, 0) = first
;
13337 /* Put a label at the very end of a function */
13338 end
= label(state
);
13339 flatten(state
, first
, end
);
13340 /* Remember where return goes */
13341 ident
= state
->i_return
;
13342 symbol(state
, ident
, &ident
->sym_ident
, end
, end
->type
);
13344 /* Get the initial closure type */
13345 ctype
= new_type(TYPE_JOIN
, &void_type
, 0);
13346 ctype
->elements
= 1;
13348 /* Add a variable for the return value */
13349 crtype
= new_type(TYPE_TUPLE
,
13350 /* Remove all type qualifiers from the return type */
13351 new_type(TYPE_PRODUCT
, ctype
, clone_type(0, type
->left
)), 0);
13352 crtype
->elements
= 2;
13353 flatten(state
, end
, variable(state
, crtype
));
13355 /* Allocate a variable for the return address */
13356 retvar
= flatten(state
, end
, variable(state
, &void_ptr_type
));
13358 /* Add in the return instruction */
13359 ret
= triple(state
, OP_RET
, &void_type
, read_expr(state
, retvar
), 0);
13360 ret
= flatten(state
, first
, ret
);
13362 /* Walk through the parameters and create symbol table entries
13365 param
= type
->right
;
13366 while((param
->type
& TYPE_MASK
) == TYPE_PRODUCT
) {
13367 ident
= param
->left
->field_ident
;
13368 tmp
= variable(state
, param
->left
);
13369 var_symbol(state
, ident
, tmp
);
13370 flatten(state
, end
, tmp
);
13371 param
= param
->right
;
13373 if ((param
->type
& TYPE_MASK
) != TYPE_VOID
) {
13374 /* And don't forget the last parameter */
13375 ident
= param
->field_ident
;
13376 tmp
= variable(state
, param
);
13377 symbol(state
, ident
, &ident
->sym_ident
, tmp
, tmp
->type
);
13378 flatten(state
, end
, tmp
);
13381 /* Add the declaration static const char __func__ [] = "func-name" */
13382 fname_type
= new_type(TYPE_ARRAY
,
13383 clone_type(QUAL_CONST
| STOR_STATIC
, &char_type
), 0);
13384 fname_type
->type
|= QUAL_CONST
| STOR_STATIC
;
13385 fname_type
->elements
= strlen(state
->function
) + 1;
13387 fname
= triple(state
, OP_BLOBCONST
, fname_type
, 0, 0);
13388 fname
->u
.blob
= (void *)state
->function
;
13389 fname
= flatten(state
, end
, fname
);
13391 ident
= state
->i___func__
;
13392 symbol(state
, ident
, &ident
->sym_ident
, fname
, fname_type
);
13394 /* Remember which function I am compiling.
13395 * Also assume the last defined function is the main function.
13397 state
->main_function
= def
;
13399 /* Now get the actual function definition */
13400 compound_statement(state
, end
);
13402 /* Finish anything unfinished with branches */
13403 resolve_branches(state
, first
);
13405 /* Remove the parameter scope */
13409 /* Remember I have defined a function */
13410 if (!state
->functions
) {
13411 state
->functions
= def
;
13413 insert_triple(state
, state
->functions
, def
);
13415 if (state
->compiler
->debug
& DEBUG_INLINE
) {
13416 FILE *fp
= state
->dbgout
;
13419 fprintf(fp
, "\n__________ %s _________\n", __FUNCTION__
);
13420 display_func(state
, fp
, def
);
13421 fprintf(fp
, "__________ %s _________ done\n\n", __FUNCTION__
);
13427 static struct triple
*do_decl(struct compile_state
*state
,
13428 struct type
*type
, struct hash_entry
*ident
)
13430 struct triple
*def
;
13432 /* Clean up the storage types used */
13433 switch (type
->type
& STOR_MASK
) {
13436 /* These are the good types I am aiming for */
13438 case STOR_REGISTER
:
13439 type
->type
&= ~STOR_MASK
;
13440 type
->type
|= STOR_AUTO
;
13444 type
->type
&= ~STOR_MASK
;
13445 type
->type
|= STOR_STATIC
;
13449 error(state
, 0, "typedef without name");
13451 symbol(state
, ident
, &ident
->sym_ident
, 0, type
);
13452 ident
->tok
= TOK_TYPE_NAME
;
13456 internal_error(state
, 0, "Undefined storage class");
13458 if ((type
->type
& TYPE_MASK
) == TYPE_FUNCTION
) {
13459 // ignore function prototypes
13463 ((type
->type
& TYPE_MASK
) == TYPE_ARRAY
) &&
13464 ((type
->type
& STOR_MASK
) != STOR_STATIC
))
13465 error(state
, 0, "non static arrays not supported");
13467 ((type
->type
& STOR_MASK
) == STOR_STATIC
) &&
13468 ((type
->type
& QUAL_CONST
) == 0)) {
13469 error(state
, 0, "non const static variables not supported");
13472 def
= variable(state
, type
);
13473 var_symbol(state
, ident
, def
);
13478 static void decl(struct compile_state
*state
, struct triple
*first
)
13480 struct type
*base_type
, *type
;
13481 struct hash_entry
*ident
;
13482 struct triple
*def
;
13484 global
= (state
->scope_depth
<= GLOBAL_SCOPE_DEPTH
);
13485 base_type
= decl_specifiers(state
);
13487 type
= declarator(state
, base_type
, &ident
, 0);
13488 type
->type
= attributes_opt(state
, type
->type
);
13489 if (global
&& ident
&& (peek(state
) == TOK_LBRACE
)) {
13491 type
->type_ident
= ident
;
13492 state
->function
= ident
->name
;
13493 def
= function_definition(state
, type
);
13494 symbol(state
, ident
, &ident
->sym_ident
, def
, type
);
13495 state
->function
= 0;
13499 flatten(state
, first
, do_decl(state
, type
, ident
));
13500 /* type or variable definition */
13503 if (peek(state
) == TOK_EQ
) {
13505 error(state
, 0, "cannot assign to a type");
13507 eat(state
, TOK_EQ
);
13508 flatten(state
, first
,
13510 ident
->sym_ident
->def
,
13511 initializer(state
, type
)));
13513 arrays_complete(state
, type
);
13514 if (peek(state
) == TOK_COMMA
) {
13515 eat(state
, TOK_COMMA
);
13517 type
= declarator(state
, base_type
, &ident
, 0);
13518 flatten(state
, first
, do_decl(state
, type
, ident
));
13522 eat(state
, TOK_SEMI
);
13526 static void decls(struct compile_state
*state
)
13528 struct triple
*list
;
13530 list
= label(state
);
13533 if (tok
== TOK_EOF
) {
13536 if (tok
== TOK_SPACE
) {
13537 eat(state
, TOK_SPACE
);
13540 if (list
->next
!= list
) {
13541 error(state
, 0, "global variables not supported");
13547 * Function inlining
13549 struct triple_reg_set
{
13550 struct triple_reg_set
*next
;
13551 struct triple
*member
;
13552 struct triple
*new;
13555 struct block
*block
;
13556 struct triple_reg_set
*in
;
13557 struct triple_reg_set
*out
;
13560 static void setup_basic_blocks(struct compile_state
*, struct basic_blocks
*bb
);
13561 static void analyze_basic_blocks(struct compile_state
*state
, struct basic_blocks
*bb
);
13562 static void free_basic_blocks(struct compile_state
*, struct basic_blocks
*bb
);
13563 static int tdominates(struct compile_state
*state
, struct triple
*dom
, struct triple
*sub
);
13564 static void walk_blocks(struct compile_state
*state
, struct basic_blocks
*bb
,
13565 void (*cb
)(struct compile_state
*state
, struct block
*block
, void *arg
),
13567 static void print_block(
13568 struct compile_state
*state
, struct block
*block
, void *arg
);
13569 static int do_triple_set(struct triple_reg_set
**head
,
13570 struct triple
*member
, struct triple
*new_member
);
13571 static void do_triple_unset(struct triple_reg_set
**head
, struct triple
*member
);
13572 static struct reg_block
*compute_variable_lifetimes(
13573 struct compile_state
*state
, struct basic_blocks
*bb
);
13574 static void free_variable_lifetimes(struct compile_state
*state
,
13575 struct basic_blocks
*bb
, struct reg_block
*blocks
);
13576 #if DEBUG_EXPLICIT_CLOSURES
13577 static void print_live_variables(struct compile_state
*state
,
13578 struct basic_blocks
*bb
, struct reg_block
*rb
, FILE *fp
);
13582 static struct triple
*call(struct compile_state
*state
,
13583 struct triple
*retvar
, struct triple
*ret_addr
,
13584 struct triple
*targ
, struct triple
*ret
)
13586 struct triple
*call
;
13588 if (!retvar
|| !is_lvalue(state
, retvar
)) {
13589 internal_error(state
, 0, "writing to a non lvalue?");
13591 write_compatible(state
, retvar
->type
, &void_ptr_type
);
13593 call
= new_triple(state
, OP_CALL
, &void_type
, 1, 0);
13594 TARG(call
, 0) = targ
;
13595 MISC(call
, 0) = ret
;
13596 if (!targ
|| (targ
->op
!= OP_LABEL
)) {
13597 internal_error(state
, 0, "call not to a label");
13599 if (!ret
|| (ret
->op
!= OP_RET
)) {
13600 internal_error(state
, 0, "call not matched with return");
13605 static void walk_functions(struct compile_state
*state
,
13606 void (*cb
)(struct compile_state
*state
, struct triple
*func
, void *arg
),
13609 struct triple
*func
, *first
;
13610 func
= first
= state
->functions
;
13612 cb(state
, func
, arg
);
13614 } while(func
!= first
);
13617 static void reverse_walk_functions(struct compile_state
*state
,
13618 void (*cb
)(struct compile_state
*state
, struct triple
*func
, void *arg
),
13621 struct triple
*func
, *first
;
13622 func
= first
= state
->functions
;
13625 cb(state
, func
, arg
);
13626 } while(func
!= first
);
13630 static void mark_live(struct compile_state
*state
, struct triple
*func
, void *arg
)
13632 struct triple
*ptr
, *first
;
13633 if (func
->u
.cval
== 0) {
13636 ptr
= first
= RHS(func
, 0);
13638 if (ptr
->op
== OP_FCALL
) {
13639 struct triple
*called_func
;
13640 called_func
= MISC(ptr
, 0);
13641 /* Mark the called function as used */
13642 if (!(func
->id
& TRIPLE_FLAG_FLATTENED
)) {
13643 called_func
->u
.cval
++;
13645 /* Remove the called function from the list */
13646 called_func
->prev
->next
= called_func
->next
;
13647 called_func
->next
->prev
= called_func
->prev
;
13649 /* Place the called function before me on the list */
13650 called_func
->next
= func
;
13651 called_func
->prev
= func
->prev
;
13652 called_func
->prev
->next
= called_func
;
13653 called_func
->next
->prev
= called_func
;
13656 } while(ptr
!= first
);
13657 func
->id
|= TRIPLE_FLAG_FLATTENED
;
13660 static void mark_live_functions(struct compile_state
*state
)
13662 /* Ensure state->main_function is the last function in
13663 * the list of functions.
13665 if ((state
->main_function
->next
!= state
->functions
) ||
13666 (state
->functions
->prev
!= state
->main_function
)) {
13667 internal_error(state
, 0,
13668 "state->main_function is not at the end of the function list ");
13670 state
->main_function
->u
.cval
= 1;
13671 reverse_walk_functions(state
, mark_live
, 0);
13674 static int local_triple(struct compile_state
*state
,
13675 struct triple
*func
, struct triple
*ins
)
13677 int local
= (ins
->id
& TRIPLE_FLAG_LOCAL
);
13680 FILE *fp
= state
->errout
;
13681 fprintf(fp
, "global: ");
13682 display_triple(fp
, ins
);
13688 struct triple
*copy_func(struct compile_state
*state
, struct triple
*ofunc
,
13689 struct occurance
*base_occurance
)
13691 struct triple
*nfunc
;
13692 struct triple
*nfirst
, *ofirst
;
13693 struct triple
*new, *old
;
13695 if (state
->compiler
->debug
& DEBUG_INLINE
) {
13696 FILE *fp
= state
->dbgout
;
13699 fprintf(fp
, "\n__________ %s _________\n", __FUNCTION__
);
13700 display_func(state
, fp
, ofunc
);
13701 fprintf(fp
, "__________ %s _________ done\n\n", __FUNCTION__
);
13704 /* Make a new copy of the old function */
13705 nfunc
= triple(state
, OP_LIST
, ofunc
->type
, 0, 0);
13707 ofirst
= old
= RHS(ofunc
, 0);
13709 struct triple
*new;
13710 struct occurance
*occurance
;
13711 int old_lhs
, old_rhs
;
13712 old_lhs
= old
->lhs
;
13713 old_rhs
= old
->rhs
;
13714 occurance
= inline_occurance(state
, base_occurance
, old
->occurance
);
13715 if (ofunc
->u
.cval
&& (old
->op
== OP_FCALL
)) {
13716 MISC(old
, 0)->u
.cval
+= 1;
13718 new = alloc_triple(state
, old
->op
, old
->type
, old_lhs
, old_rhs
,
13720 if (!triple_stores_block(state
, new)) {
13721 memcpy(&new->u
, &old
->u
, sizeof(new->u
));
13724 RHS(nfunc
, 0) = nfirst
= new;
13727 insert_triple(state
, nfirst
, new);
13729 new->id
|= TRIPLE_FLAG_FLATTENED
;
13730 new->id
|= old
->id
& TRIPLE_FLAG_COPY
;
13732 /* During the copy remember new as user of old */
13733 use_triple(old
, new);
13735 /* Remember which instructions are local */
13736 old
->id
|= TRIPLE_FLAG_LOCAL
;
13738 } while(old
!= ofirst
);
13740 /* Make a second pass to fix up any unresolved references */
13744 struct triple
**oexpr
, **nexpr
;
13746 /* Lookup where the copy is, to join pointers */
13747 count
= TRIPLE_SIZE(old
);
13748 for(i
= 0; i
< count
; i
++) {
13749 oexpr
= &old
->param
[i
];
13750 nexpr
= &new->param
[i
];
13751 if (*oexpr
&& !*nexpr
) {
13752 if (!local_triple(state
, ofunc
, *oexpr
)) {
13755 else if ((*oexpr
)->use
) {
13756 *nexpr
= (*oexpr
)->use
->member
;
13758 if (*nexpr
== old
) {
13759 internal_error(state
, 0, "new == old?");
13761 use_triple(*nexpr
, new);
13763 if (!*nexpr
&& *oexpr
) {
13764 internal_error(state
, 0, "Could not copy %d", i
);
13769 } while((old
!= ofirst
) && (new != nfirst
));
13771 /* Make a third pass to cleanup the extra useses */
13775 unuse_triple(old
, new);
13776 /* Forget which instructions are local */
13777 old
->id
&= ~TRIPLE_FLAG_LOCAL
;
13780 } while ((old
!= ofirst
) && (new != nfirst
));
13784 static void expand_inline_call(
13785 struct compile_state
*state
, struct triple
*me
, struct triple
*fcall
)
13787 /* Inline the function call */
13788 struct type
*ptype
;
13789 struct triple
*ofunc
, *nfunc
, *nfirst
, *result
, *retvar
, *ins
;
13790 struct triple
*end
, *nend
;
13793 /* Find the triples */
13794 ofunc
= MISC(fcall
, 0);
13795 if (ofunc
->op
!= OP_LIST
) {
13796 internal_error(state
, 0, "improper function");
13798 nfunc
= copy_func(state
, ofunc
, fcall
->occurance
);
13799 /* Prepend the parameter reading into the new function list */
13800 ptype
= nfunc
->type
->right
;
13801 pvals
= fcall
->rhs
;
13802 for(i
= 0; i
< pvals
; i
++) {
13803 struct type
*atype
;
13804 struct triple
*arg
, *param
;
13806 if ((ptype
->type
& TYPE_MASK
) == TYPE_PRODUCT
) {
13807 atype
= ptype
->left
;
13809 param
= farg(state
, nfunc
, i
);
13810 if ((param
->type
->type
& TYPE_MASK
) != (atype
->type
& TYPE_MASK
)) {
13811 internal_error(state
, fcall
, "param %d type mismatch", i
);
13813 arg
= RHS(fcall
, i
);
13814 flatten(state
, fcall
, write_expr(state
, param
, arg
));
13815 ptype
= ptype
->right
;
13818 if ((nfunc
->type
->left
->type
& TYPE_MASK
) != TYPE_VOID
) {
13819 result
= read_expr(state
,
13820 deref_index(state
, fresult(state
, nfunc
), 1));
13822 if (state
->compiler
->debug
& DEBUG_INLINE
) {
13823 FILE *fp
= state
->dbgout
;
13826 fprintf(fp
, "\n__________ %s _________\n", __FUNCTION__
);
13827 display_func(state
, fp
, nfunc
);
13828 fprintf(fp
, "__________ %s _________ done\n\n", __FUNCTION__
);
13832 * Get rid of the extra triples
13834 /* Remove the read of the return address */
13835 ins
= RHS(nfunc
, 0)->prev
->prev
;
13836 if ((ins
->op
!= OP_READ
) || (RHS(ins
, 0) != fretaddr(state
, nfunc
))) {
13837 internal_error(state
, ins
, "Not return addres read?");
13839 release_triple(state
, ins
);
13840 /* Remove the return instruction */
13841 ins
= RHS(nfunc
, 0)->prev
;
13842 if (ins
->op
!= OP_RET
) {
13843 internal_error(state
, ins
, "Not return?");
13845 release_triple(state
, ins
);
13846 /* Remove the retaddres variable */
13847 retvar
= fretaddr(state
, nfunc
);
13848 if ((retvar
->lhs
!= 1) ||
13849 (retvar
->op
!= OP_ADECL
) ||
13850 (retvar
->next
->op
!= OP_PIECE
) ||
13851 (MISC(retvar
->next
, 0) != retvar
)) {
13852 internal_error(state
, retvar
, "Not the return address?");
13854 release_triple(state
, retvar
->next
);
13855 release_triple(state
, retvar
);
13857 /* Remove the label at the start of the function */
13858 ins
= RHS(nfunc
, 0);
13859 if (ins
->op
!= OP_LABEL
) {
13860 internal_error(state
, ins
, "Not label?");
13862 nfirst
= ins
->next
;
13863 free_triple(state
, ins
);
13864 /* Release the new function header */
13866 free_triple(state
, nfunc
);
13868 /* Append the new function list onto the return list */
13870 nend
= nfirst
->prev
;
13871 end
->next
= nfirst
;
13872 nfirst
->prev
= end
;
13873 nend
->next
= fcall
;
13874 fcall
->prev
= nend
;
13876 /* Now the result reading code */
13878 result
= flatten(state
, fcall
, result
);
13879 propogate_use(state
, fcall
, result
);
13882 /* Release the original fcall instruction */
13883 release_triple(state
, fcall
);
13890 * Type of the result variable.
13894 * +----------+------------+
13896 * union of closures result_type
13898 * +------------------+---------------+
13900 * closure1 ... closuerN
13902 * +----+--+-+--------+-----+ +----+----+---+-----+
13903 * | | | | | | | | |
13904 * var1 var2 var3 ... varN result var1 var2 ... varN result
13906 * +--------+---------+
13908 * union of closures result_type
13910 * +-----+-------------------+
13912 * closure1 ... closureN
13914 * +-----+---+----+----+ +----+---+----+-----+
13916 * var1 var2 ... varN result var1 var2 ... varN result
13919 static int add_closure_type(struct compile_state
*state
,
13920 struct triple
*func
, struct type
*closure_type
)
13922 struct type
*type
, *ctype
, **next
;
13923 struct triple
*var
, *new_var
;
13927 FILE *fp
= state
->errout
;
13928 fprintf(fp
, "original_type: ");
13929 name_of(fp
, fresult(state
, func
)->type
);
13932 /* find the original type */
13933 var
= fresult(state
, func
);
13935 if (type
->elements
!= 2) {
13936 internal_error(state
, var
, "bad return type");
13939 /* Find the complete closure type and update it */
13940 ctype
= type
->left
->left
;
13941 next
= &ctype
->left
;
13942 while(((*next
)->type
& TYPE_MASK
) == TYPE_OVERLAP
) {
13943 next
= &(*next
)->right
;
13945 *next
= new_type(TYPE_OVERLAP
, *next
, dup_type(state
, closure_type
));
13946 ctype
->elements
+= 1;
13949 fprintf(fp
, "new_type: ");
13952 fprintf(fp
, "ctype: %p %d bits: %d ",
13953 ctype
, ctype
->elements
, reg_size_of(state
, ctype
));
13954 name_of(fp
, ctype
);
13958 /* Regenerate the variable with the new type definition */
13959 new_var
= pre_triple(state
, var
, OP_ADECL
, type
, 0, 0);
13960 new_var
->id
|= TRIPLE_FLAG_FLATTENED
;
13961 for(i
= 0; i
< new_var
->lhs
; i
++) {
13962 LHS(new_var
, i
)->id
|= TRIPLE_FLAG_FLATTENED
;
13965 /* Point everyone at the new variable */
13966 propogate_use(state
, var
, new_var
);
13968 /* Release the original variable */
13969 for(i
= 0; i
< var
->lhs
; i
++) {
13970 release_triple(state
, LHS(var
, i
));
13972 release_triple(state
, var
);
13974 /* Return the index of the added closure type */
13975 return ctype
->elements
- 1;
13978 static struct triple
*closure_expr(struct compile_state
*state
,
13979 struct triple
*func
, int closure_idx
, int var_idx
)
13981 return deref_index(state
,
13983 deref_index(state
, fresult(state
, func
), 0),
13989 static void insert_triple_set(
13990 struct triple_reg_set
**head
, struct triple
*member
)
13992 struct triple_reg_set
*new;
13993 new = xcmalloc(sizeof(*new), "triple_set");
13994 new->member
= member
;
14000 static int ordered_triple_set(
14001 struct triple_reg_set
**head
, struct triple
*member
)
14003 struct triple_reg_set
**ptr
;
14008 if (member
== (*ptr
)->member
) {
14011 /* keep the list ordered */
14012 if (member
->id
< (*ptr
)->member
->id
) {
14015 ptr
= &(*ptr
)->next
;
14017 insert_triple_set(ptr
, member
);
14022 static void free_closure_variables(struct compile_state
*state
,
14023 struct triple_reg_set
**enclose
)
14025 struct triple_reg_set
*entry
, *next
;
14026 for(entry
= *enclose
; entry
; entry
= next
) {
14027 next
= entry
->next
;
14028 do_triple_unset(enclose
, entry
->member
);
14032 static int lookup_closure_index(struct compile_state
*state
,
14033 struct triple
*me
, struct triple
*val
)
14035 struct triple
*first
, *ins
, *next
;
14036 first
= RHS(me
, 0);
14037 ins
= next
= first
;
14039 struct triple
*result
;
14040 struct triple
*index0
, *index1
, *index2
, *read
, *write
;
14043 if (ins
->op
!= OP_CALL
) {
14046 /* I am at a previous call point examine it closely */
14047 if (ins
->next
->op
!= OP_LABEL
) {
14048 internal_error(state
, ins
, "call not followed by label");
14050 /* Does this call does not enclose any variables? */
14051 if ((ins
->next
->next
->op
!= OP_INDEX
) ||
14052 (ins
->next
->next
->u
.cval
!= 0) ||
14053 (result
= MISC(ins
->next
->next
, 0)) ||
14054 (result
->id
& TRIPLE_FLAG_LOCAL
)) {
14057 index0
= ins
->next
->next
;
14059 * 0 index result < 0 >
14065 for(index0
= ins
->next
->next
;
14066 (index0
->op
== OP_INDEX
) &&
14067 (MISC(index0
, 0) == result
) &&
14068 (index0
->u
.cval
== 0) ;
14069 index0
= write
->next
)
14071 index1
= index0
->next
;
14072 index2
= index1
->next
;
14073 read
= index2
->next
;
14074 write
= read
->next
;
14075 if ((index0
->op
!= OP_INDEX
) ||
14076 (index1
->op
!= OP_INDEX
) ||
14077 (index2
->op
!= OP_INDEX
) ||
14078 (read
->op
!= OP_READ
) ||
14079 (write
->op
!= OP_WRITE
) ||
14080 (MISC(index1
, 0) != index0
) ||
14081 (MISC(index2
, 0) != index1
) ||
14082 (RHS(read
, 0) != index2
) ||
14083 (RHS(write
, 0) != read
)) {
14084 internal_error(state
, index0
, "bad var read");
14086 if (MISC(write
, 0) == val
) {
14087 return index2
->u
.cval
;
14090 } while(next
!= first
);
14094 static inline int enclose_triple(struct triple
*ins
)
14096 return (ins
&& ((ins
->type
->type
& TYPE_MASK
) != TYPE_VOID
));
14099 static void compute_closure_variables(struct compile_state
*state
,
14100 struct triple
*me
, struct triple
*fcall
, struct triple_reg_set
**enclose
)
14102 struct triple_reg_set
*set
, *vars
, **last_var
;
14103 struct basic_blocks bb
;
14104 struct reg_block
*rb
;
14105 struct block
*block
;
14106 struct triple
*old_result
, *first
, *ins
;
14108 unsigned long used_indicies
;
14110 #define MAX_INDICIES (sizeof(used_indicies)*CHAR_BIT)
14111 #define ID_BITS(X) ((X) & (TRIPLE_FLAG_LOCAL -1))
14118 /* Find the basic blocks of this function */
14120 bb
.first
= RHS(me
, 0);
14122 if (!triple_is_ret(state
, bb
.first
->prev
)) {
14125 old_result
= fresult(state
, me
);
14127 analyze_basic_blocks(state
, &bb
);
14129 /* Find which variables are currently alive in a given block */
14130 rb
= compute_variable_lifetimes(state
, &bb
);
14132 /* Find the variables that are currently alive */
14133 block
= block_of_triple(state
, fcall
);
14134 if (!block
|| (block
->vertex
<= 0) || (block
->vertex
> bb
.last_vertex
)) {
14135 internal_error(state
, fcall
, "No reg block? block: %p", block
);
14138 #if DEBUG_EXPLICIT_CLOSURES
14139 print_live_variables(state
, &bb
, rb
, state
->dbgout
);
14140 fflush(state
->dbgout
);
14143 /* Count the number of triples in the function */
14144 first
= RHS(me
, 0);
14150 } while(ins
!= first
);
14152 /* Allocate some memory to temorary hold the id info */
14153 info
= xcmalloc(sizeof(*info
) * (count
+1), "info");
14155 /* Mark the local function */
14156 first
= RHS(me
, 0);
14160 info
[idx
].id
= ins
->id
;
14161 ins
->id
= TRIPLE_FLAG_LOCAL
| idx
;
14164 } while(ins
!= first
);
14167 * Build the list of variables to enclose.
14169 * A target it to put the same variable in the
14170 * same slot for ever call of a given function.
14171 * After coloring this removes all of the variable
14172 * manipulation code.
14174 * The list of variables to enclose is built ordered
14175 * program order because except in corner cases this
14176 * gives me the stability of assignment I need.
14178 * To gurantee that stability I lookup the variables
14179 * to see where they have been used before and
14180 * I build my final list with the assigned indicies.
14183 if (enclose_triple(old_result
)) {
14184 ordered_triple_set(&vars
, old_result
);
14186 for(set
= rb
[block
->vertex
].out
; set
; set
= set
->next
) {
14187 if (!enclose_triple(set
->member
)) {
14190 if ((set
->member
== fcall
) || (set
->member
== old_result
)) {
14193 if (!local_triple(state
, me
, set
->member
)) {
14194 internal_error(state
, set
->member
, "not local?");
14196 ordered_triple_set(&vars
, set
->member
);
14199 /* Lookup the current indicies of the live varialbe */
14202 for(set
= vars
; set
; set
= set
->next
) {
14203 struct triple
*ins
;
14206 index
= lookup_closure_index(state
, me
, ins
);
14207 info
[ID_BITS(ins
->id
)].index
= index
;
14211 if (index
>= MAX_INDICIES
) {
14212 internal_error(state
, ins
, "index unexpectedly large");
14214 if (used_indicies
& (1 << index
)) {
14215 internal_error(state
, ins
, "index previously used?");
14217 /* Remember which indicies have been used */
14218 used_indicies
|= (1 << index
);
14219 if (index
> max_index
) {
14224 /* Walk through the live variables and make certain
14225 * everything is assigned an index.
14227 for(set
= vars
; set
; set
= set
->next
) {
14228 struct triple
*ins
;
14231 index
= info
[ID_BITS(ins
->id
)].index
;
14235 /* Find the lowest unused index value */
14236 for(index
= 0; index
< MAX_INDICIES
; index
++) {
14237 if (!(used_indicies
& (1 << index
))) {
14241 if (index
== MAX_INDICIES
) {
14242 internal_error(state
, ins
, "no free indicies?");
14244 info
[ID_BITS(ins
->id
)].index
= index
;
14245 /* Remember which indicies have been used */
14246 used_indicies
|= (1 << index
);
14247 if (index
> max_index
) {
14252 /* Build the return list of variables with positions matching
14256 last_var
= enclose
;
14257 for(i
= 0; i
<= max_index
; i
++) {
14258 struct triple
*var
;
14260 if (used_indicies
& (1 << i
)) {
14261 for(set
= vars
; set
; set
= set
->next
) {
14263 index
= info
[ID_BITS(set
->member
->id
)].index
;
14270 internal_error(state
, me
, "missing variable");
14273 insert_triple_set(last_var
, var
);
14274 last_var
= &(*last_var
)->next
;
14277 #if DEBUG_EXPLICIT_CLOSURES
14278 /* Print out the variables to be enclosed */
14279 loc(state
->dbgout
, state
, fcall
);
14280 fprintf(state
->dbgout
, "Alive: \n");
14281 for(set
= *enclose
; set
; set
= set
->next
) {
14282 display_triple(state
->dbgout
, set
->member
);
14284 fflush(state
->dbgout
);
14287 /* Clear the marks */
14290 ins
->id
= info
[ID_BITS(ins
->id
)].id
;
14292 } while(ins
!= first
);
14294 /* Release the ordered list of live variables */
14295 free_closure_variables(state
, &vars
);
14297 /* Release the storage of the old ids */
14300 /* Release the variable lifetime information */
14301 free_variable_lifetimes(state
, &bb
, rb
);
14303 /* Release the basic blocks of this function */
14304 free_basic_blocks(state
, &bb
);
14307 static void expand_function_call(
14308 struct compile_state
*state
, struct triple
*me
, struct triple
*fcall
)
14310 /* Generate an ordinary function call */
14311 struct type
*closure_type
, **closure_next
;
14312 struct triple
*func
, *func_first
, *func_last
, *retvar
;
14313 struct triple
*first
;
14314 struct type
*ptype
, *rtype
;
14315 struct triple
*ret_addr
, *ret_loc
;
14316 struct triple_reg_set
*enclose
, *set
;
14317 int closure_idx
, pvals
, i
;
14319 #if DEBUG_EXPLICIT_CLOSURES
14320 FILE *fp
= state
->dbgout
;
14321 fprintf(fp
, "\ndisplay_func(me) ptr: %p\n", fcall
);
14322 display_func(state
, fp
, MISC(fcall
, 0));
14323 display_func(state
, fp
, me
);
14324 fprintf(fp
, "__________ %s _________ done\n\n", __FUNCTION__
);
14327 /* Find the triples */
14328 func
= MISC(fcall
, 0);
14329 func_first
= RHS(func
, 0);
14330 retvar
= fretaddr(state
, func
);
14331 func_last
= func_first
->prev
;
14332 first
= fcall
->next
;
14334 /* Find what I need to enclose */
14335 compute_closure_variables(state
, me
, fcall
, &enclose
);
14337 /* Compute the closure type */
14338 closure_type
= new_type(TYPE_TUPLE
, 0, 0);
14339 closure_type
->elements
= 0;
14340 closure_next
= &closure_type
->left
;
14341 for(set
= enclose
; set
; set
= set
->next
) {
14345 type
= set
->member
->type
;
14347 if (!*closure_next
) {
14348 *closure_next
= type
;
14350 *closure_next
= new_type(TYPE_PRODUCT
, *closure_next
,
14352 closure_next
= &(*closure_next
)->right
;
14354 closure_type
->elements
+= 1;
14356 if (closure_type
->elements
== 0) {
14357 closure_type
->type
= TYPE_VOID
;
14361 #if DEBUG_EXPLICIT_CLOSURES
14362 fprintf(state
->dbgout
, "closure type: ");
14363 name_of(state
->dbgout
, closure_type
);
14364 fprintf(state
->dbgout
, "\n");
14367 /* Update the called functions closure variable */
14368 closure_idx
= add_closure_type(state
, func
, closure_type
);
14370 /* Generate some needed triples */
14371 ret_loc
= label(state
);
14372 ret_addr
= triple(state
, OP_ADDRCONST
, &void_ptr_type
, ret_loc
, 0);
14374 /* Pass the parameters to the new function */
14375 ptype
= func
->type
->right
;
14376 pvals
= fcall
->rhs
;
14377 for(i
= 0; i
< pvals
; i
++) {
14378 struct type
*atype
;
14379 struct triple
*arg
, *param
;
14381 if ((ptype
->type
& TYPE_MASK
) == TYPE_PRODUCT
) {
14382 atype
= ptype
->left
;
14384 param
= farg(state
, func
, i
);
14385 if ((param
->type
->type
& TYPE_MASK
) != (atype
->type
& TYPE_MASK
)) {
14386 internal_error(state
, fcall
, "param type mismatch");
14388 arg
= RHS(fcall
, i
);
14389 flatten(state
, first
, write_expr(state
, param
, arg
));
14390 ptype
= ptype
->right
;
14392 rtype
= func
->type
->left
;
14394 /* Thread the triples together */
14395 ret_loc
= flatten(state
, first
, ret_loc
);
14397 /* Save the active variables in the result variable */
14398 for(i
= 0, set
= enclose
; set
; set
= set
->next
, i
++) {
14399 if (!set
->member
) {
14402 flatten(state
, ret_loc
,
14404 closure_expr(state
, func
, closure_idx
, i
),
14405 read_expr(state
, set
->member
)));
14408 /* Initialize the return value */
14409 if ((rtype
->type
& TYPE_MASK
) != TYPE_VOID
) {
14410 flatten(state
, ret_loc
,
14412 deref_index(state
, fresult(state
, func
), 1),
14413 new_triple(state
, OP_UNKNOWNVAL
, rtype
, 0, 0)));
14416 ret_addr
= flatten(state
, ret_loc
, ret_addr
);
14417 flatten(state
, ret_loc
, write_expr(state
, retvar
, ret_addr
));
14418 flatten(state
, ret_loc
,
14419 call(state
, retvar
, ret_addr
, func_first
, func_last
));
14421 /* Find the result */
14422 if ((rtype
->type
& TYPE_MASK
) != TYPE_VOID
) {
14423 struct triple
* result
;
14424 result
= flatten(state
, first
,
14426 deref_index(state
, fresult(state
, func
), 1)));
14428 propogate_use(state
, fcall
, result
);
14431 /* Release the original fcall instruction */
14432 release_triple(state
, fcall
);
14434 /* Restore the active variables from the result variable */
14435 for(i
= 0, set
= enclose
; set
; set
= set
->next
, i
++) {
14436 struct triple_set
*use
, *next
;
14437 struct triple
*new;
14438 struct basic_blocks bb
;
14439 if (!set
->member
|| (set
->member
== fcall
)) {
14442 /* Generate an expression for the value */
14443 new = flatten(state
, first
,
14445 closure_expr(state
, func
, closure_idx
, i
)));
14448 /* If the original is an lvalue restore the preserved value */
14449 if (is_lvalue(state
, set
->member
)) {
14450 flatten(state
, first
,
14451 write_expr(state
, set
->member
, new));
14455 * If the original is a value update the dominated uses.
14458 /* Analyze the basic blocks so I can see who dominates whom */
14460 bb
.first
= RHS(me
, 0);
14461 if (!triple_is_ret(state
, bb
.first
->prev
)) {
14464 analyze_basic_blocks(state
, &bb
);
14467 #if DEBUG_EXPLICIT_CLOSURES
14468 fprintf(state
->errout
, "Updating domindated uses: %p -> %p\n",
14471 /* If fcall dominates the use update the expression */
14472 for(use
= set
->member
->use
; use
; use
= next
) {
14473 /* Replace use modifies the use chain and
14474 * removes use, so I must take a copy of the
14475 * next entry early.
14478 if (!tdominates(state
, fcall
, use
->member
)) {
14481 replace_use(state
, set
->member
, new, use
->member
);
14484 /* Release the basic blocks, the instructions will be
14485 * different next time, and flatten/insert_triple does
14486 * not update the block values so I can't cache the analysis.
14488 free_basic_blocks(state
, &bb
);
14491 /* Release the closure variable list */
14492 free_closure_variables(state
, &enclose
);
14494 if (state
->compiler
->debug
& DEBUG_INLINE
) {
14495 FILE *fp
= state
->dbgout
;
14498 fprintf(fp
, "\n__________ %s _________\n", __FUNCTION__
);
14499 display_func(state
, fp
, func
);
14500 display_func(state
, fp
, me
);
14501 fprintf(fp
, "__________ %s _________ done\n\n", __FUNCTION__
);
14507 static int do_inline(struct compile_state
*state
, struct triple
*func
)
14512 policy
= state
->compiler
->flags
& COMPILER_INLINE_MASK
;
14514 case COMPILER_INLINE_ALWAYS
:
14516 if (func
->type
->type
& ATTRIB_NOINLINE
) {
14517 error(state
, func
, "noinline with always_inline compiler option");
14520 case COMPILER_INLINE_NEVER
:
14522 if (func
->type
->type
& ATTRIB_ALWAYS_INLINE
) {
14523 error(state
, func
, "always_inline with noinline compiler option");
14526 case COMPILER_INLINE_DEFAULTON
:
14527 switch(func
->type
->type
& STOR_MASK
) {
14528 case STOR_STATIC
| STOR_INLINE
:
14529 case STOR_LOCAL
| STOR_INLINE
:
14530 case STOR_EXTERN
| STOR_INLINE
:
14538 case COMPILER_INLINE_DEFAULTOFF
:
14539 switch(func
->type
->type
& STOR_MASK
) {
14540 case STOR_STATIC
| STOR_INLINE
:
14541 case STOR_LOCAL
| STOR_INLINE
:
14542 case STOR_EXTERN
| STOR_INLINE
:
14550 case COMPILER_INLINE_NOPENALTY
:
14551 switch(func
->type
->type
& STOR_MASK
) {
14552 case STOR_STATIC
| STOR_INLINE
:
14553 case STOR_LOCAL
| STOR_INLINE
:
14554 case STOR_EXTERN
| STOR_INLINE
:
14558 do_inline
= (func
->u
.cval
== 1);
14564 internal_error(state
, 0, "Unimplemented inline policy");
14567 /* Force inlining */
14568 if (func
->type
->type
& ATTRIB_NOINLINE
) {
14571 if (func
->type
->type
& ATTRIB_ALWAYS_INLINE
) {
14577 static void inline_function(struct compile_state
*state
, struct triple
*me
, void *arg
)
14579 struct triple
*first
, *ptr
, *next
;
14580 /* If the function is not used don't bother */
14581 if (me
->u
.cval
<= 0) {
14584 if (state
->compiler
->debug
& DEBUG_CALLS2
) {
14585 FILE *fp
= state
->dbgout
;
14586 fprintf(fp
, "in: %s\n",
14587 me
->type
->type_ident
->name
);
14590 first
= RHS(me
, 0);
14591 ptr
= next
= first
;
14593 struct triple
*func
, *prev
;
14597 if (ptr
->op
!= OP_FCALL
) {
14600 func
= MISC(ptr
, 0);
14601 /* See if the function should be inlined */
14602 if (!do_inline(state
, func
)) {
14603 /* Put a label after the fcall */
14604 post_triple(state
, ptr
, OP_LABEL
, &void_type
, 0, 0);
14607 if (state
->compiler
->debug
& DEBUG_CALLS
) {
14608 FILE *fp
= state
->dbgout
;
14609 if (state
->compiler
->debug
& DEBUG_CALLS2
) {
14610 loc(fp
, state
, ptr
);
14612 fprintf(fp
, "inlining %s\n",
14613 func
->type
->type_ident
->name
);
14617 /* Update the function use counts */
14620 /* Replace the fcall with the called function */
14621 expand_inline_call(state
, me
, ptr
);
14624 } while (next
!= first
);
14626 ptr
= next
= first
;
14628 struct triple
*prev
, *func
;
14632 if (ptr
->op
!= OP_FCALL
) {
14635 func
= MISC(ptr
, 0);
14636 if (state
->compiler
->debug
& DEBUG_CALLS
) {
14637 FILE *fp
= state
->dbgout
;
14638 if (state
->compiler
->debug
& DEBUG_CALLS2
) {
14639 loc(fp
, state
, ptr
);
14641 fprintf(fp
, "calling %s\n",
14642 func
->type
->type_ident
->name
);
14645 /* Replace the fcall with the instruction sequence
14646 * needed to make the call.
14648 expand_function_call(state
, me
, ptr
);
14650 } while(next
!= first
);
14653 static void inline_functions(struct compile_state
*state
, struct triple
*func
)
14655 inline_function(state
, func
, 0);
14656 reverse_walk_functions(state
, inline_function
, 0);
14659 static void insert_function(struct compile_state
*state
,
14660 struct triple
*func
, void *arg
)
14662 struct triple
*first
, *end
, *ffirst
, *fend
;
14664 if (state
->compiler
->debug
& DEBUG_INLINE
) {
14665 FILE *fp
= state
->errout
;
14666 fprintf(fp
, "%s func count: %d\n",
14667 func
->type
->type_ident
->name
, func
->u
.cval
);
14669 if (func
->u
.cval
== 0) {
14673 /* Find the end points of the lists */
14676 ffirst
= RHS(func
, 0);
14677 fend
= ffirst
->prev
;
14679 /* splice the lists together */
14680 end
->next
= ffirst
;
14681 ffirst
->prev
= end
;
14682 fend
->next
= first
;
14683 first
->prev
= fend
;
14686 struct triple
*input_asm(struct compile_state
*state
)
14688 struct asm_info
*info
;
14689 struct triple
*def
;
14692 info
= xcmalloc(sizeof(*info
), "asm_info");
14695 out
= sizeof(arch_input_regs
)/sizeof(arch_input_regs
[0]);
14696 memcpy(&info
->tmpl
.lhs
, arch_input_regs
, sizeof(arch_input_regs
));
14698 def
= new_triple(state
, OP_ASM
, &void_type
, out
, 0);
14699 def
->u
.ainfo
= info
;
14700 def
->id
|= TRIPLE_FLAG_VOLATILE
;
14702 for(i
= 0; i
< out
; i
++) {
14703 struct triple
*piece
;
14704 piece
= triple(state
, OP_PIECE
, &int_type
, def
, 0);
14706 LHS(def
, i
) = piece
;
14712 struct triple
*output_asm(struct compile_state
*state
)
14714 struct asm_info
*info
;
14715 struct triple
*def
;
14718 info
= xcmalloc(sizeof(*info
), "asm_info");
14721 in
= sizeof(arch_output_regs
)/sizeof(arch_output_regs
[0]);
14722 memcpy(&info
->tmpl
.rhs
, arch_output_regs
, sizeof(arch_output_regs
));
14724 def
= new_triple(state
, OP_ASM
, &void_type
, 0, in
);
14725 def
->u
.ainfo
= info
;
14726 def
->id
|= TRIPLE_FLAG_VOLATILE
;
14731 static void join_functions(struct compile_state
*state
)
14733 struct triple
*start
, *end
, *call
, *in
, *out
, *func
;
14734 struct file_state file
;
14735 struct type
*pnext
, *param
;
14736 struct type
*result_type
, *args_type
;
14739 /* Be clear the functions have not been joined yet */
14740 state
->functions_joined
= 0;
14742 /* Dummy file state to get debug handing right */
14743 memset(&file
, 0, sizeof(file
));
14744 file
.basename
= "";
14746 file
.report_line
= 0;
14747 file
.report_name
= file
.basename
;
14748 file
.prev
= state
->file
;
14749 state
->file
= &file
;
14750 state
->function
= "";
14752 if (!state
->main_function
) {
14753 error(state
, 0, "No functions to compile\n");
14756 /* The type of arguments */
14757 args_type
= state
->main_function
->type
->right
;
14758 /* The return type without any specifiers */
14759 result_type
= clone_type(0, state
->main_function
->type
->left
);
14762 /* Verify the external arguments */
14763 if (registers_of(state
, args_type
) > ARCH_INPUT_REGS
) {
14764 error(state
, state
->main_function
,
14765 "Too many external input arguments");
14767 if (registers_of(state
, result_type
) > ARCH_OUTPUT_REGS
) {
14768 error(state
, state
->main_function
,
14769 "Too many external output arguments");
14772 /* Lay down the basic program structure */
14773 end
= label(state
);
14774 start
= label(state
);
14775 start
= flatten(state
, state
->first
, start
);
14776 end
= flatten(state
, state
->first
, end
);
14777 in
= input_asm(state
);
14778 out
= output_asm(state
);
14779 call
= new_triple(state
, OP_FCALL
, result_type
, -1, registers_of(state
, args_type
));
14780 MISC(call
, 0) = state
->main_function
;
14781 in
= flatten(state
, state
->first
, in
);
14782 call
= flatten(state
, state
->first
, call
);
14783 out
= flatten(state
, state
->first
, out
);
14786 /* Read the external input arguments */
14789 while(pnext
&& ((pnext
->type
& TYPE_MASK
) != TYPE_VOID
)) {
14790 struct triple
*expr
;
14793 if ((param
->type
& TYPE_MASK
) == TYPE_PRODUCT
) {
14794 pnext
= param
->right
;
14795 param
= param
->left
;
14797 if (registers_of(state
, param
) != 1) {
14798 error(state
, state
->main_function
,
14799 "Arg: %d %s requires multiple registers",
14800 idx
+ 1, param
->field_ident
->name
);
14802 expr
= read_expr(state
, LHS(in
, idx
));
14803 RHS(call
, idx
) = expr
;
14804 expr
= flatten(state
, call
, expr
);
14805 use_triple(expr
, call
);
14811 /* Write the external output arguments */
14812 pnext
= result_type
;
14813 if ((pnext
->type
& TYPE_MASK
) == TYPE_STRUCT
) {
14814 pnext
= result_type
->left
;
14816 for(idx
= 0; idx
< out
->rhs
; idx
++) {
14817 struct triple
*expr
;
14820 if (param
&& ((param
->type
& TYPE_MASK
) == TYPE_PRODUCT
)) {
14821 pnext
= param
->right
;
14822 param
= param
->left
;
14824 if (param
&& ((param
->type
& TYPE_MASK
) == TYPE_VOID
)) {
14828 if (registers_of(state
, param
) != 1) {
14829 error(state
, state
->main_function
,
14830 "Result: %d %s requires multiple registers",
14831 idx
, param
->field_ident
->name
);
14833 expr
= read_expr(state
, call
);
14834 if ((result_type
->type
& TYPE_MASK
) == TYPE_STRUCT
) {
14835 expr
= deref_field(state
, expr
, param
->field_ident
);
14838 expr
= triple(state
, OP_UNKNOWNVAL
, &int_type
, 0, 0);
14840 flatten(state
, out
, expr
);
14841 RHS(out
, idx
) = expr
;
14842 use_triple(expr
, out
);
14845 /* Allocate a dummy containing function */
14846 func
= triple(state
, OP_LIST
,
14847 new_type(TYPE_FUNCTION
, &void_type
, &void_type
), 0, 0);
14848 func
->type
->type_ident
= lookup(state
, "", 0);
14849 RHS(func
, 0) = state
->first
;
14852 /* See which functions are called, and how often */
14853 mark_live_functions(state
);
14854 inline_functions(state
, func
);
14855 walk_functions(state
, insert_function
, end
);
14857 if (start
->next
!= end
) {
14858 flatten(state
, start
, branch(state
, end
, 0));
14861 /* OK now the functions have been joined. */
14862 state
->functions_joined
= 1;
14864 /* Done now cleanup */
14865 state
->file
= file
.prev
;
14866 state
->function
= 0;
14870 * Data structurs for optimation.
14874 static int do_use_block(
14875 struct block
*used
, struct block_set
**head
, struct block
*user
,
14878 struct block_set
**ptr
, *new;
14885 if ((*ptr
)->member
== user
) {
14888 ptr
= &(*ptr
)->next
;
14890 new = xcmalloc(sizeof(*new), "block_set");
14891 new->member
= user
;
14902 static int do_unuse_block(
14903 struct block
*used
, struct block_set
**head
, struct block
*unuser
)
14905 struct block_set
*use
, **ptr
;
14911 if (use
->member
== unuser
) {
14913 memset(use
, -1, sizeof(*use
));
14924 static void use_block(struct block
*used
, struct block
*user
)
14927 /* Append new to the head of the list, print_block
14930 count
= do_use_block(used
, &used
->use
, user
, 1);
14931 used
->users
+= count
;
14933 static void unuse_block(struct block
*used
, struct block
*unuser
)
14936 count
= do_unuse_block(used
, &used
->use
, unuser
);
14937 used
->users
-= count
;
14940 static void add_block_edge(struct block
*block
, struct block
*edge
, int front
)
14943 count
= do_use_block(block
, &block
->edges
, edge
, front
);
14944 block
->edge_count
+= count
;
14947 static void remove_block_edge(struct block
*block
, struct block
*edge
)
14950 count
= do_unuse_block(block
, &block
->edges
, edge
);
14951 block
->edge_count
-= count
;
14954 static void idom_block(struct block
*idom
, struct block
*user
)
14956 do_use_block(idom
, &idom
->idominates
, user
, 0);
14959 static void unidom_block(struct block
*idom
, struct block
*unuser
)
14961 do_unuse_block(idom
, &idom
->idominates
, unuser
);
14964 static void domf_block(struct block
*block
, struct block
*domf
)
14966 do_use_block(block
, &block
->domfrontier
, domf
, 0);
14969 static void undomf_block(struct block
*block
, struct block
*undomf
)
14971 do_unuse_block(block
, &block
->domfrontier
, undomf
);
14974 static void ipdom_block(struct block
*ipdom
, struct block
*user
)
14976 do_use_block(ipdom
, &ipdom
->ipdominates
, user
, 0);
14979 static void unipdom_block(struct block
*ipdom
, struct block
*unuser
)
14981 do_unuse_block(ipdom
, &ipdom
->ipdominates
, unuser
);
14984 static void ipdomf_block(struct block
*block
, struct block
*ipdomf
)
14986 do_use_block(block
, &block
->ipdomfrontier
, ipdomf
, 0);
14989 static void unipdomf_block(struct block
*block
, struct block
*unipdomf
)
14991 do_unuse_block(block
, &block
->ipdomfrontier
, unipdomf
);
14994 static int walk_triples(
14995 struct compile_state
*state
,
14996 int (*cb
)(struct compile_state
*state
, struct triple
*ptr
, void *arg
),
14999 struct triple
*ptr
;
15001 ptr
= state
->first
;
15003 result
= cb(state
, ptr
, arg
);
15004 if (ptr
->next
->prev
!= ptr
) {
15005 internal_error(state
, ptr
->next
, "bad prev");
15008 } while((result
== 0) && (ptr
!= state
->first
));
15012 #define PRINT_LIST 1
15013 static int do_print_triple(struct compile_state
*state
, struct triple
*ins
, void *arg
)
15018 if (op
== OP_LIST
) {
15023 if ((op
== OP_LABEL
) && (ins
->use
)) {
15024 fprintf(fp
, "\n%p:\n", ins
);
15026 display_triple(fp
, ins
);
15028 if (triple_is_branch(state
, ins
) && ins
->use
&&
15029 (ins
->op
!= OP_RET
) && (ins
->op
!= OP_FCALL
)) {
15030 internal_error(state
, ins
, "branch used?");
15032 if (triple_is_branch(state
, ins
)) {
15038 static void print_triples(struct compile_state
*state
)
15040 if (state
->compiler
->debug
& DEBUG_TRIPLES
) {
15041 FILE *fp
= state
->dbgout
;
15042 fprintf(fp
, "--------------- triples ---------------\n");
15043 walk_triples(state
, do_print_triple
, fp
);
15049 struct block
*block
;
15051 static void find_cf_blocks(struct cf_block
*cf
, struct block
*block
)
15053 struct block_set
*edge
;
15054 if (!block
|| (cf
[block
->vertex
].block
== block
)) {
15057 cf
[block
->vertex
].block
= block
;
15058 for(edge
= block
->edges
; edge
; edge
= edge
->next
) {
15059 find_cf_blocks(cf
, edge
->member
);
15063 static void print_control_flow(struct compile_state
*state
,
15064 FILE *fp
, struct basic_blocks
*bb
)
15066 struct cf_block
*cf
;
15068 fprintf(fp
, "\ncontrol flow\n");
15069 cf
= xcmalloc(sizeof(*cf
) * (bb
->last_vertex
+ 1), "cf_block");
15070 find_cf_blocks(cf
, bb
->first_block
);
15072 for(i
= 1; i
<= bb
->last_vertex
; i
++) {
15073 struct block
*block
;
15074 struct block_set
*edge
;
15075 block
= cf
[i
].block
;
15078 fprintf(fp
, "(%p) %d:", block
, block
->vertex
);
15079 for(edge
= block
->edges
; edge
; edge
= edge
->next
) {
15080 fprintf(fp
, " %d", edge
->member
->vertex
);
15088 static void free_basic_block(struct compile_state
*state
, struct block
*block
)
15090 struct block_set
*edge
, *entry
;
15091 struct block
*child
;
15095 if (block
->vertex
== -1) {
15098 block
->vertex
= -1;
15099 for(edge
= block
->edges
; edge
; edge
= edge
->next
) {
15100 if (edge
->member
) {
15101 unuse_block(edge
->member
, block
);
15105 unidom_block(block
->idom
, block
);
15108 if (block
->ipdom
) {
15109 unipdom_block(block
->ipdom
, block
);
15112 while((entry
= block
->use
)) {
15113 child
= entry
->member
;
15114 unuse_block(block
, child
);
15115 if (child
&& (child
->vertex
!= -1)) {
15116 for(edge
= child
->edges
; edge
; edge
= edge
->next
) {
15121 while((entry
= block
->idominates
)) {
15122 child
= entry
->member
;
15123 unidom_block(block
, child
);
15124 if (child
&& (child
->vertex
!= -1)) {
15128 while((entry
= block
->domfrontier
)) {
15129 child
= entry
->member
;
15130 undomf_block(block
, child
);
15132 while((entry
= block
->ipdominates
)) {
15133 child
= entry
->member
;
15134 unipdom_block(block
, child
);
15135 if (child
&& (child
->vertex
!= -1)) {
15139 while((entry
= block
->ipdomfrontier
)) {
15140 child
= entry
->member
;
15141 unipdomf_block(block
, child
);
15143 if (block
->users
!= 0) {
15144 internal_error(state
, 0, "block still has users");
15146 while((edge
= block
->edges
)) {
15147 child
= edge
->member
;
15148 remove_block_edge(block
, child
);
15150 if (child
&& (child
->vertex
!= -1)) {
15151 free_basic_block(state
, child
);
15154 memset(block
, -1, sizeof(*block
));
15160 static void free_basic_blocks(struct compile_state
*state
,
15161 struct basic_blocks
*bb
)
15163 struct triple
*first
, *ins
;
15164 free_basic_block(state
, bb
->first_block
);
15165 bb
->last_vertex
= 0;
15166 bb
->first_block
= bb
->last_block
= 0;
15170 if (triple_stores_block(state
, ins
)) {
15174 } while(ins
!= first
);
15178 static struct block
*basic_block(struct compile_state
*state
,
15179 struct basic_blocks
*bb
, struct triple
*first
)
15181 struct block
*block
;
15182 struct triple
*ptr
;
15183 if (!triple_is_label(state
, first
)) {
15184 internal_error(state
, first
, "block does not start with a label");
15186 /* See if this basic block has already been setup */
15187 if (first
->u
.block
!= 0) {
15188 return first
->u
.block
;
15190 /* Allocate another basic block structure */
15191 bb
->last_vertex
+= 1;
15192 block
= xcmalloc(sizeof(*block
), "block");
15193 block
->first
= block
->last
= first
;
15194 block
->vertex
= bb
->last_vertex
;
15197 if ((ptr
!= first
) && triple_is_label(state
, ptr
) && (ptr
->use
)) {
15201 /* If ptr->u is not used remember where the baic block is */
15202 if (triple_stores_block(state
, ptr
)) {
15203 ptr
->u
.block
= block
;
15205 if (triple_is_branch(state
, ptr
)) {
15209 } while (ptr
!= bb
->first
);
15210 if ((ptr
== bb
->first
) ||
15211 ((ptr
->next
== bb
->first
) && (
15212 triple_is_end(state
, ptr
) ||
15213 triple_is_ret(state
, ptr
))))
15215 /* The block has no outflowing edges */
15217 else if (triple_is_label(state
, ptr
)) {
15218 struct block
*next
;
15219 next
= basic_block(state
, bb
, ptr
);
15220 add_block_edge(block
, next
, 0);
15221 use_block(next
, block
);
15223 else if (triple_is_branch(state
, ptr
)) {
15224 struct triple
**expr
, *first
;
15225 struct block
*child
;
15226 /* Find the branch targets.
15227 * I special case the first branch as that magically
15228 * avoids some difficult cases for the register allocator.
15230 expr
= triple_edge_targ(state
, ptr
, 0);
15232 internal_error(state
, ptr
, "branch without targets");
15235 expr
= triple_edge_targ(state
, ptr
, expr
);
15236 for(; expr
; expr
= triple_edge_targ(state
, ptr
, expr
)) {
15237 if (!*expr
) continue;
15238 child
= basic_block(state
, bb
, *expr
);
15239 use_block(child
, block
);
15240 add_block_edge(block
, child
, 0);
15243 child
= basic_block(state
, bb
, first
);
15244 use_block(child
, block
);
15245 add_block_edge(block
, child
, 1);
15247 /* Be certain the return block of a call is
15248 * in a basic block. When it is not find
15249 * start of the block, insert a label if
15250 * necessary and build the basic block.
15251 * Then add a fake edge from the start block
15252 * to the return block of the function.
15254 if (state
->functions_joined
&& triple_is_call(state
, ptr
)
15255 && !block_of_triple(state
, MISC(ptr
, 0))) {
15256 struct block
*tail
;
15257 struct triple
*start
;
15258 start
= triple_to_block_start(state
, MISC(ptr
, 0));
15259 if (!triple_is_label(state
, start
)) {
15260 start
= pre_triple(state
,
15261 start
, OP_LABEL
, &void_type
, 0, 0);
15263 tail
= basic_block(state
, bb
, start
);
15264 add_block_edge(child
, tail
, 0);
15265 use_block(tail
, child
);
15270 internal_error(state
, 0, "Bad basic block split");
15274 struct block_set
*edge
;
15275 FILE *fp
= state
->errout
;
15276 fprintf(fp
, "basic_block: %10p [%2d] ( %10p - %10p )",
15277 block
, block
->vertex
,
15278 block
->first
, block
->last
);
15279 for(edge
= block
->edges
; edge
; edge
= edge
->next
) {
15280 fprintf(fp
, " %10p [%2d]",
15281 edge
->member
? edge
->member
->first
: 0,
15282 edge
->member
? edge
->member
->vertex
: -1);
15291 static void walk_blocks(struct compile_state
*state
, struct basic_blocks
*bb
,
15292 void (*cb
)(struct compile_state
*state
, struct block
*block
, void *arg
),
15295 struct triple
*ptr
, *first
;
15296 struct block
*last_block
;
15301 if (triple_stores_block(state
, ptr
)) {
15302 struct block
*block
;
15303 block
= ptr
->u
.block
;
15304 if (block
&& (block
!= last_block
)) {
15305 cb(state
, block
, arg
);
15307 last_block
= block
;
15310 } while(ptr
!= first
);
15313 static void print_block(
15314 struct compile_state
*state
, struct block
*block
, void *arg
)
15316 struct block_set
*user
, *edge
;
15317 struct triple
*ptr
;
15320 fprintf(fp
, "\nblock: %p (%d) ",
15324 for(edge
= block
->edges
; edge
; edge
= edge
->next
) {
15325 fprintf(fp
, " %p<-%p",
15327 (edge
->member
&& edge
->member
->use
)?
15328 edge
->member
->use
->member
: 0);
15331 if (block
->first
->op
== OP_LABEL
) {
15332 fprintf(fp
, "%p:\n", block
->first
);
15334 for(ptr
= block
->first
; ; ) {
15335 display_triple(fp
, ptr
);
15336 if (ptr
== block
->last
)
15339 if (ptr
== block
->first
) {
15340 internal_error(state
, 0, "missing block last?");
15343 fprintf(fp
, "users %d: ", block
->users
);
15344 for(user
= block
->use
; user
; user
= user
->next
) {
15345 fprintf(fp
, "%p (%d) ",
15347 user
->member
->vertex
);
15349 fprintf(fp
,"\n\n");
15353 static void romcc_print_blocks(struct compile_state
*state
, FILE *fp
)
15355 fprintf(fp
, "--------------- blocks ---------------\n");
15356 walk_blocks(state
, &state
->bb
, print_block
, fp
);
15358 static void print_blocks(struct compile_state
*state
, const char *func
, FILE *fp
)
15360 if (state
->compiler
->debug
& DEBUG_BASIC_BLOCKS
) {
15361 fprintf(fp
, "After %s\n", func
);
15362 romcc_print_blocks(state
, fp
);
15363 if (state
->compiler
->debug
& DEBUG_FDOMINATORS
) {
15364 print_dominators(state
, fp
, &state
->bb
);
15365 print_dominance_frontiers(state
, fp
, &state
->bb
);
15367 print_control_flow(state
, fp
, &state
->bb
);
15371 static void prune_nonblock_triples(struct compile_state
*state
,
15372 struct basic_blocks
*bb
)
15374 struct block
*block
;
15375 struct triple
*first
, *ins
, *next
;
15376 /* Delete the triples not in a basic block */
15382 if (ins
->op
== OP_LABEL
) {
15383 block
= ins
->u
.block
;
15386 struct triple_set
*use
;
15387 for(use
= ins
->use
; use
; use
= use
->next
) {
15388 struct block
*block
;
15389 block
= block_of_triple(state
, use
->member
);
15391 internal_error(state
, ins
, "pruning used ins?");
15394 release_triple(state
, ins
);
15396 if (block
&& block
->last
== ins
) {
15400 } while(ins
!= first
);
15403 static void setup_basic_blocks(struct compile_state
*state
,
15404 struct basic_blocks
*bb
)
15406 if (!triple_stores_block(state
, bb
->first
)) {
15407 internal_error(state
, 0, "ins will not store block?");
15409 /* Initialize the state */
15410 bb
->first_block
= bb
->last_block
= 0;
15411 bb
->last_vertex
= 0;
15412 free_basic_blocks(state
, bb
);
15414 /* Find the basic blocks */
15415 bb
->first_block
= basic_block(state
, bb
, bb
->first
);
15417 /* Be certain the last instruction of a function, or the
15418 * entire program is in a basic block. When it is not find
15419 * the start of the block, insert a label if necessary and build
15420 * basic block. Then add a fake edge from the start block
15421 * to the final block.
15423 if (!block_of_triple(state
, bb
->first
->prev
)) {
15424 struct triple
*start
;
15425 struct block
*tail
;
15426 start
= triple_to_block_start(state
, bb
->first
->prev
);
15427 if (!triple_is_label(state
, start
)) {
15428 start
= pre_triple(state
,
15429 start
, OP_LABEL
, &void_type
, 0, 0);
15431 tail
= basic_block(state
, bb
, start
);
15432 add_block_edge(bb
->first_block
, tail
, 0);
15433 use_block(tail
, bb
->first_block
);
15436 /* Find the last basic block.
15438 bb
->last_block
= block_of_triple(state
, bb
->first
->prev
);
15440 /* Delete the triples not in a basic block */
15441 prune_nonblock_triples(state
, bb
);
15444 /* If we are debugging print what I have just done */
15445 if (state
->compiler
->debug
& DEBUG_BASIC_BLOCKS
) {
15446 print_blocks(state
, state
->dbgout
);
15447 print_control_flow(state
, bb
);
15453 struct sdom_block
{
15454 struct block
*block
;
15455 struct sdom_block
*sdominates
;
15456 struct sdom_block
*sdom_next
;
15457 struct sdom_block
*sdom
;
15458 struct sdom_block
*label
;
15459 struct sdom_block
*parent
;
15460 struct sdom_block
*ancestor
;
15465 static void unsdom_block(struct sdom_block
*block
)
15467 struct sdom_block
**ptr
;
15468 if (!block
->sdom_next
) {
15471 ptr
= &block
->sdom
->sdominates
;
15473 if ((*ptr
) == block
) {
15474 *ptr
= block
->sdom_next
;
15477 ptr
= &(*ptr
)->sdom_next
;
15481 static void sdom_block(struct sdom_block
*sdom
, struct sdom_block
*block
)
15483 unsdom_block(block
);
15484 block
->sdom
= sdom
;
15485 block
->sdom_next
= sdom
->sdominates
;
15486 sdom
->sdominates
= block
;
15491 static int initialize_sdblock(struct sdom_block
*sd
,
15492 struct block
*parent
, struct block
*block
, int vertex
)
15494 struct block_set
*edge
;
15495 if (!block
|| (sd
[block
->vertex
].block
== block
)) {
15499 /* Renumber the blocks in a convinient fashion */
15500 block
->vertex
= vertex
;
15501 sd
[vertex
].block
= block
;
15502 sd
[vertex
].sdom
= &sd
[vertex
];
15503 sd
[vertex
].label
= &sd
[vertex
];
15504 sd
[vertex
].parent
= parent
? &sd
[parent
->vertex
] : 0;
15505 sd
[vertex
].ancestor
= 0;
15506 sd
[vertex
].vertex
= vertex
;
15507 for(edge
= block
->edges
; edge
; edge
= edge
->next
) {
15508 vertex
= initialize_sdblock(sd
, block
, edge
->member
, vertex
);
15513 static int initialize_spdblock(
15514 struct compile_state
*state
, struct sdom_block
*sd
,
15515 struct block
*parent
, struct block
*block
, int vertex
)
15517 struct block_set
*user
;
15518 if (!block
|| (sd
[block
->vertex
].block
== block
)) {
15522 /* Renumber the blocks in a convinient fashion */
15523 block
->vertex
= vertex
;
15524 sd
[vertex
].block
= block
;
15525 sd
[vertex
].sdom
= &sd
[vertex
];
15526 sd
[vertex
].label
= &sd
[vertex
];
15527 sd
[vertex
].parent
= parent
? &sd
[parent
->vertex
] : 0;
15528 sd
[vertex
].ancestor
= 0;
15529 sd
[vertex
].vertex
= vertex
;
15530 for(user
= block
->use
; user
; user
= user
->next
) {
15531 vertex
= initialize_spdblock(state
, sd
, block
, user
->member
, vertex
);
15536 static int setup_spdblocks(struct compile_state
*state
,
15537 struct basic_blocks
*bb
, struct sdom_block
*sd
)
15539 struct block
*block
;
15541 /* Setup as many sdpblocks as possible without using fake edges */
15542 vertex
= initialize_spdblock(state
, sd
, 0, bb
->last_block
, 0);
15544 /* Walk through the graph and find unconnected blocks. Add a
15545 * fake edge from the unconnected blocks to the end of the
15548 block
= bb
->first_block
->last
->next
->u
.block
;
15549 for(; block
&& block
!= bb
->first_block
; block
= block
->last
->next
->u
.block
) {
15550 if (sd
[block
->vertex
].block
== block
) {
15553 #if DEBUG_SDP_BLOCKS
15555 FILE *fp
= state
->errout
;
15556 fprintf(fp
, "Adding %d\n", vertex
+1);
15559 add_block_edge(block
, bb
->last_block
, 0);
15560 use_block(bb
->last_block
, block
);
15562 vertex
= initialize_spdblock(state
, sd
, bb
->last_block
, block
, vertex
);
15567 static void compress_ancestors(struct sdom_block
*v
)
15569 /* This procedure assumes ancestor(v) != 0 */
15570 /* if (ancestor(ancestor(v)) != 0) {
15571 * compress(ancestor(ancestor(v)));
15572 * if (semi(label(ancestor(v))) < semi(label(v))) {
15573 * label(v) = label(ancestor(v));
15575 * ancestor(v) = ancestor(ancestor(v));
15578 if (!v
->ancestor
) {
15581 if (v
->ancestor
->ancestor
) {
15582 compress_ancestors(v
->ancestor
->ancestor
);
15583 if (v
->ancestor
->label
->sdom
->vertex
< v
->label
->sdom
->vertex
) {
15584 v
->label
= v
->ancestor
->label
;
15586 v
->ancestor
= v
->ancestor
->ancestor
;
15590 static void compute_sdom(struct compile_state
*state
,
15591 struct basic_blocks
*bb
, struct sdom_block
*sd
)
15595 * for each v <= pred(w) {
15597 * if (semi[u] < semi[w] {
15598 * semi[w] = semi[u];
15601 * add w to bucket(vertex(semi[w]));
15602 * LINK(parent(w), w);
15605 * for each v <= bucket(parent(w)) {
15606 * delete v from bucket(parent(w));
15608 * dom(v) = (semi[u] < semi[v]) ? u : parent(w);
15611 for(i
= bb
->last_vertex
; i
>= 2; i
--) {
15612 struct sdom_block
*v
, *parent
, *next
;
15613 struct block_set
*user
;
15614 struct block
*block
;
15615 block
= sd
[i
].block
;
15616 parent
= sd
[i
].parent
;
15618 for(user
= block
->use
; user
; user
= user
->next
) {
15619 struct sdom_block
*v
, *u
;
15620 v
= &sd
[user
->member
->vertex
];
15621 u
= !(v
->ancestor
)? v
: (compress_ancestors(v
), v
->label
);
15622 if (u
->sdom
->vertex
< sd
[i
].sdom
->vertex
) {
15623 sd
[i
].sdom
= u
->sdom
;
15626 sdom_block(sd
[i
].sdom
, &sd
[i
]);
15627 sd
[i
].ancestor
= parent
;
15629 for(v
= parent
->sdominates
; v
; v
= next
) {
15630 struct sdom_block
*u
;
15631 next
= v
->sdom_next
;
15633 u
= (!v
->ancestor
) ? v
: (compress_ancestors(v
), v
->label
);
15634 v
->block
->idom
= (u
->sdom
->vertex
< v
->sdom
->vertex
)?
15635 u
->block
: parent
->block
;
15640 static void compute_spdom(struct compile_state
*state
,
15641 struct basic_blocks
*bb
, struct sdom_block
*sd
)
15645 * for each v <= pred(w) {
15647 * if (semi[u] < semi[w] {
15648 * semi[w] = semi[u];
15651 * add w to bucket(vertex(semi[w]));
15652 * LINK(parent(w), w);
15655 * for each v <= bucket(parent(w)) {
15656 * delete v from bucket(parent(w));
15658 * dom(v) = (semi[u] < semi[v]) ? u : parent(w);
15661 for(i
= bb
->last_vertex
; i
>= 2; i
--) {
15662 struct sdom_block
*u
, *v
, *parent
, *next
;
15663 struct block_set
*edge
;
15664 struct block
*block
;
15665 block
= sd
[i
].block
;
15666 parent
= sd
[i
].parent
;
15668 for(edge
= block
->edges
; edge
; edge
= edge
->next
) {
15669 v
= &sd
[edge
->member
->vertex
];
15670 u
= !(v
->ancestor
)? v
: (compress_ancestors(v
), v
->label
);
15671 if (u
->sdom
->vertex
< sd
[i
].sdom
->vertex
) {
15672 sd
[i
].sdom
= u
->sdom
;
15675 sdom_block(sd
[i
].sdom
, &sd
[i
]);
15676 sd
[i
].ancestor
= parent
;
15678 for(v
= parent
->sdominates
; v
; v
= next
) {
15679 struct sdom_block
*u
;
15680 next
= v
->sdom_next
;
15682 u
= (!v
->ancestor
) ? v
: (compress_ancestors(v
), v
->label
);
15683 v
->block
->ipdom
= (u
->sdom
->vertex
< v
->sdom
->vertex
)?
15684 u
->block
: parent
->block
;
15689 static void compute_idom(struct compile_state
*state
,
15690 struct basic_blocks
*bb
, struct sdom_block
*sd
)
15693 for(i
= 2; i
<= bb
->last_vertex
; i
++) {
15694 struct block
*block
;
15695 block
= sd
[i
].block
;
15696 if (block
->idom
->vertex
!= sd
[i
].sdom
->vertex
) {
15697 block
->idom
= block
->idom
->idom
;
15699 idom_block(block
->idom
, block
);
15701 sd
[1].block
->idom
= 0;
15704 static void compute_ipdom(struct compile_state
*state
,
15705 struct basic_blocks
*bb
, struct sdom_block
*sd
)
15708 for(i
= 2; i
<= bb
->last_vertex
; i
++) {
15709 struct block
*block
;
15710 block
= sd
[i
].block
;
15711 if (block
->ipdom
->vertex
!= sd
[i
].sdom
->vertex
) {
15712 block
->ipdom
= block
->ipdom
->ipdom
;
15714 ipdom_block(block
->ipdom
, block
);
15716 sd
[1].block
->ipdom
= 0;
15720 * Every vertex of a flowgraph G = (V, E, r) except r has
15721 * a unique immediate dominator.
15722 * The edges {(idom(w), w) |w <= V - {r}} form a directed tree
15723 * rooted at r, called the dominator tree of G, such that
15724 * v dominates w if and only if v is a proper ancestor of w in
15725 * the dominator tree.
15728 * If v and w are vertices of G such that v <= w,
15729 * than any path from v to w must contain a common ancestor
15732 /* Lemma 2: For any vertex w != r, idom(w) -> w */
15733 /* Lemma 3: For any vertex w != r, sdom(w) -> w */
15734 /* Lemma 4: For any vertex w != r, idom(w) -> sdom(w) */
15736 * Let w != r. Suppose every u for which sdom(w) -> u -> w satisfies
15737 * sdom(u) >= sdom(w). Then idom(w) = sdom(w).
15740 * Let w != r and let u be a vertex for which sdom(u) is
15741 * minimum amoung vertices u satisfying sdom(w) -> u -> w.
15742 * Then sdom(u) <= sdom(w) and idom(u) = idom(w).
15744 /* Lemma 5: Let vertices v,w satisfy v -> w.
15745 * Then v -> idom(w) or idom(w) -> idom(v)
15748 static void find_immediate_dominators(struct compile_state
*state
,
15749 struct basic_blocks
*bb
)
15751 struct sdom_block
*sd
;
15752 /* w->sdom = min{v| there is a path v = v0,v1,...,vk = w such that:
15753 * vi > w for (1 <= i <= k - 1}
15756 * For any vertex w != r.
15758 * {v|(v,w) <= E and v < w } U
15759 * {sdom(u) | u > w and there is an edge (v, w) such that u -> v})
15762 * Let w != r and let u be a vertex for which sdom(u) is
15763 * minimum amoung vertices u satisfying sdom(w) -> u -> w.
15765 * { sdom(w) if sdom(w) = sdom(u),
15767 * { idom(u) otherwise
15769 /* The algorithm consists of the following 4 steps.
15770 * Step 1. Carry out a depth-first search of the problem graph.
15771 * Number the vertices from 1 to N as they are reached during
15772 * the search. Initialize the variables used in succeeding steps.
15773 * Step 2. Compute the semidominators of all vertices by applying
15774 * theorem 4. Carry out the computation vertex by vertex in
15775 * decreasing order by number.
15776 * Step 3. Implicitly define the immediate dominator of each vertex
15777 * by applying Corollary 1.
15778 * Step 4. Explicitly define the immediate dominator of each vertex,
15779 * carrying out the computation vertex by vertex in increasing order
15782 /* Step 1 initialize the basic block information */
15783 sd
= xcmalloc(sizeof(*sd
) * (bb
->last_vertex
+ 1), "sdom_state");
15784 initialize_sdblock(sd
, 0, bb
->first_block
, 0);
15790 /* Step 2 compute the semidominators */
15791 /* Step 3 implicitly define the immediate dominator of each vertex */
15792 compute_sdom(state
, bb
, sd
);
15793 /* Step 4 explicitly define the immediate dominator of each vertex */
15794 compute_idom(state
, bb
, sd
);
15798 static void find_post_dominators(struct compile_state
*state
,
15799 struct basic_blocks
*bb
)
15801 struct sdom_block
*sd
;
15803 /* Step 1 initialize the basic block information */
15804 sd
= xcmalloc(sizeof(*sd
) * (bb
->last_vertex
+ 1), "sdom_state");
15806 vertex
= setup_spdblocks(state
, bb
, sd
);
15807 if (vertex
!= bb
->last_vertex
) {
15808 internal_error(state
, 0, "missing %d blocks",
15809 bb
->last_vertex
- vertex
);
15812 /* Step 2 compute the semidominators */
15813 /* Step 3 implicitly define the immediate dominator of each vertex */
15814 compute_spdom(state
, bb
, sd
);
15815 /* Step 4 explicitly define the immediate dominator of each vertex */
15816 compute_ipdom(state
, bb
, sd
);
15822 static void find_block_domf(struct compile_state
*state
, struct block
*block
)
15824 struct block
*child
;
15825 struct block_set
*user
, *edge
;
15826 if (block
->domfrontier
!= 0) {
15827 internal_error(state
, block
->first
, "domfrontier present?");
15829 for(user
= block
->idominates
; user
; user
= user
->next
) {
15830 child
= user
->member
;
15831 if (child
->idom
!= block
) {
15832 internal_error(state
, block
->first
, "bad idom");
15834 find_block_domf(state
, child
);
15836 for(edge
= block
->edges
; edge
; edge
= edge
->next
) {
15837 if (edge
->member
->idom
!= block
) {
15838 domf_block(block
, edge
->member
);
15841 for(user
= block
->idominates
; user
; user
= user
->next
) {
15842 struct block_set
*frontier
;
15843 child
= user
->member
;
15844 for(frontier
= child
->domfrontier
; frontier
; frontier
= frontier
->next
) {
15845 if (frontier
->member
->idom
!= block
) {
15846 domf_block(block
, frontier
->member
);
15852 static void find_block_ipdomf(struct compile_state
*state
, struct block
*block
)
15854 struct block
*child
;
15855 struct block_set
*user
;
15856 if (block
->ipdomfrontier
!= 0) {
15857 internal_error(state
, block
->first
, "ipdomfrontier present?");
15859 for(user
= block
->ipdominates
; user
; user
= user
->next
) {
15860 child
= user
->member
;
15861 if (child
->ipdom
!= block
) {
15862 internal_error(state
, block
->first
, "bad ipdom");
15864 find_block_ipdomf(state
, child
);
15866 for(user
= block
->use
; user
; user
= user
->next
) {
15867 if (user
->member
->ipdom
!= block
) {
15868 ipdomf_block(block
, user
->member
);
15871 for(user
= block
->ipdominates
; user
; user
= user
->next
) {
15872 struct block_set
*frontier
;
15873 child
= user
->member
;
15874 for(frontier
= child
->ipdomfrontier
; frontier
; frontier
= frontier
->next
) {
15875 if (frontier
->member
->ipdom
!= block
) {
15876 ipdomf_block(block
, frontier
->member
);
15882 static void print_dominated(
15883 struct compile_state
*state
, struct block
*block
, void *arg
)
15885 struct block_set
*user
;
15888 fprintf(fp
, "%d:", block
->vertex
);
15889 for(user
= block
->idominates
; user
; user
= user
->next
) {
15890 fprintf(fp
, " %d", user
->member
->vertex
);
15891 if (user
->member
->idom
!= block
) {
15892 internal_error(state
, user
->member
->first
, "bad idom");
15898 static void print_dominated2(
15899 struct compile_state
*state
, FILE *fp
, int depth
, struct block
*block
)
15901 struct block_set
*user
;
15902 struct triple
*ins
;
15903 struct occurance
*ptr
, *ptr2
;
15904 const char *filename1
, *filename2
;
15905 int equal_filenames
;
15907 for(i
= 0; i
< depth
; i
++) {
15910 fprintf(fp
, "%3d: %p (%p - %p) @",
15911 block
->vertex
, block
, block
->first
, block
->last
);
15912 ins
= block
->first
;
15913 while(ins
!= block
->last
&& (ins
->occurance
->line
== 0)) {
15916 ptr
= ins
->occurance
;
15917 ptr2
= block
->last
->occurance
;
15918 filename1
= ptr
->filename
? ptr
->filename
: "";
15919 filename2
= ptr2
->filename
? ptr2
->filename
: "";
15920 equal_filenames
= (strcmp(filename1
, filename2
) == 0);
15921 if ((ptr
== ptr2
) || (equal_filenames
&& ptr
->line
== ptr2
->line
)) {
15922 fprintf(fp
, " %s:%d", ptr
->filename
, ptr
->line
);
15923 } else if (equal_filenames
) {
15924 fprintf(fp
, " %s:(%d - %d)",
15925 ptr
->filename
, ptr
->line
, ptr2
->line
);
15927 fprintf(fp
, " (%s:%d - %s:%d)",
15928 ptr
->filename
, ptr
->line
,
15929 ptr2
->filename
, ptr2
->line
);
15932 for(user
= block
->idominates
; user
; user
= user
->next
) {
15933 print_dominated2(state
, fp
, depth
+ 1, user
->member
);
15937 static void print_dominators(struct compile_state
*state
, FILE *fp
, struct basic_blocks
*bb
)
15939 fprintf(fp
, "\ndominates\n");
15940 walk_blocks(state
, bb
, print_dominated
, fp
);
15941 fprintf(fp
, "dominates\n");
15942 print_dominated2(state
, fp
, 0, bb
->first_block
);
15946 static int print_frontiers(
15947 struct compile_state
*state
, FILE *fp
, struct block
*block
, int vertex
)
15949 struct block_set
*user
, *edge
;
15951 if (!block
|| (block
->vertex
!= vertex
+ 1)) {
15956 fprintf(fp
, "%d:", block
->vertex
);
15957 for(user
= block
->domfrontier
; user
; user
= user
->next
) {
15958 fprintf(fp
, " %d", user
->member
->vertex
);
15962 for(edge
= block
->edges
; edge
; edge
= edge
->next
) {
15963 vertex
= print_frontiers(state
, fp
, edge
->member
, vertex
);
15967 static void print_dominance_frontiers(struct compile_state
*state
,
15968 FILE *fp
, struct basic_blocks
*bb
)
15970 fprintf(fp
, "\ndominance frontiers\n");
15971 print_frontiers(state
, fp
, bb
->first_block
, 0);
15975 static void analyze_idominators(struct compile_state
*state
, struct basic_blocks
*bb
)
15977 /* Find the immediate dominators */
15978 find_immediate_dominators(state
, bb
);
15979 /* Find the dominance frontiers */
15980 find_block_domf(state
, bb
->first_block
);
15981 /* If debuging print the print what I have just found */
15982 if (state
->compiler
->debug
& DEBUG_FDOMINATORS
) {
15983 print_dominators(state
, state
->dbgout
, bb
);
15984 print_dominance_frontiers(state
, state
->dbgout
, bb
);
15985 print_control_flow(state
, state
->dbgout
, bb
);
15990 static void print_ipdominated(
15991 struct compile_state
*state
, struct block
*block
, void *arg
)
15993 struct block_set
*user
;
15996 fprintf(fp
, "%d:", block
->vertex
);
15997 for(user
= block
->ipdominates
; user
; user
= user
->next
) {
15998 fprintf(fp
, " %d", user
->member
->vertex
);
15999 if (user
->member
->ipdom
!= block
) {
16000 internal_error(state
, user
->member
->first
, "bad ipdom");
16006 static void print_ipdominators(struct compile_state
*state
, FILE *fp
,
16007 struct basic_blocks
*bb
)
16009 fprintf(fp
, "\nipdominates\n");
16010 walk_blocks(state
, bb
, print_ipdominated
, fp
);
16013 static int print_pfrontiers(
16014 struct compile_state
*state
, FILE *fp
, struct block
*block
, int vertex
)
16016 struct block_set
*user
;
16018 if (!block
|| (block
->vertex
!= vertex
+ 1)) {
16023 fprintf(fp
, "%d:", block
->vertex
);
16024 for(user
= block
->ipdomfrontier
; user
; user
= user
->next
) {
16025 fprintf(fp
, " %d", user
->member
->vertex
);
16028 for(user
= block
->use
; user
; user
= user
->next
) {
16029 vertex
= print_pfrontiers(state
, fp
, user
->member
, vertex
);
16033 static void print_ipdominance_frontiers(struct compile_state
*state
,
16034 FILE *fp
, struct basic_blocks
*bb
)
16036 fprintf(fp
, "\nipdominance frontiers\n");
16037 print_pfrontiers(state
, fp
, bb
->last_block
, 0);
16041 static void analyze_ipdominators(struct compile_state
*state
,
16042 struct basic_blocks
*bb
)
16044 /* Find the post dominators */
16045 find_post_dominators(state
, bb
);
16046 /* Find the control dependencies (post dominance frontiers) */
16047 find_block_ipdomf(state
, bb
->last_block
);
16048 /* If debuging print the print what I have just found */
16049 if (state
->compiler
->debug
& DEBUG_RDOMINATORS
) {
16050 print_ipdominators(state
, state
->dbgout
, bb
);
16051 print_ipdominance_frontiers(state
, state
->dbgout
, bb
);
16052 print_control_flow(state
, state
->dbgout
, bb
);
16056 static int bdominates(struct compile_state
*state
,
16057 struct block
*dom
, struct block
*sub
)
16059 while(sub
&& (sub
!= dom
)) {
16065 static int tdominates(struct compile_state
*state
,
16066 struct triple
*dom
, struct triple
*sub
)
16068 struct block
*bdom
, *bsub
;
16070 bdom
= block_of_triple(state
, dom
);
16071 bsub
= block_of_triple(state
, sub
);
16072 if (bdom
!= bsub
) {
16073 result
= bdominates(state
, bdom
, bsub
);
16076 struct triple
*ins
;
16077 if (!bdom
|| !bsub
) {
16078 internal_error(state
, dom
, "huh?");
16081 while((ins
!= bsub
->first
) && (ins
!= dom
)) {
16084 result
= (ins
== dom
);
16089 static void analyze_basic_blocks(
16090 struct compile_state
*state
, struct basic_blocks
*bb
)
16092 setup_basic_blocks(state
, bb
);
16093 analyze_idominators(state
, bb
);
16094 analyze_ipdominators(state
, bb
);
16097 static void insert_phi_operations(struct compile_state
*state
)
16100 struct triple
*first
;
16101 int *has_already
, *work
;
16102 struct block
*work_list
, **work_list_tail
;
16104 struct triple
*var
, *vnext
;
16106 size
= sizeof(int) * (state
->bb
.last_vertex
+ 1);
16107 has_already
= xcmalloc(size
, "has_already");
16108 work
= xcmalloc(size
, "work");
16111 first
= state
->first
;
16112 for(var
= first
->next
; var
!= first
; var
= vnext
) {
16113 struct block
*block
;
16114 struct triple_set
*user
, *unext
;
16117 if (!triple_is_auto_var(state
, var
) || !var
->use
) {
16123 work_list_tail
= &work_list
;
16124 for(user
= var
->use
; user
; user
= unext
) {
16125 unext
= user
->next
;
16126 if (MISC(var
, 0) == user
->member
) {
16129 if (user
->member
->op
== OP_READ
) {
16132 if (user
->member
->op
!= OP_WRITE
) {
16133 internal_error(state
, user
->member
,
16134 "bad variable access");
16136 block
= user
->member
->u
.block
;
16138 warning(state
, user
->member
, "dead code");
16139 release_triple(state
, user
->member
);
16142 if (work
[block
->vertex
] >= iter
) {
16145 work
[block
->vertex
] = iter
;
16146 *work_list_tail
= block
;
16147 block
->work_next
= 0;
16148 work_list_tail
= &block
->work_next
;
16150 for(block
= work_list
; block
; block
= block
->work_next
) {
16151 struct block_set
*df
;
16152 for(df
= block
->domfrontier
; df
; df
= df
->next
) {
16153 struct triple
*phi
;
16154 struct block
*front
;
16156 front
= df
->member
;
16158 if (has_already
[front
->vertex
] >= iter
) {
16161 /* Count how many edges flow into this block */
16162 in_edges
= front
->users
;
16163 /* Insert a phi function for this variable */
16164 get_occurance(var
->occurance
);
16165 phi
= alloc_triple(
16166 state
, OP_PHI
, var
->type
, -1, in_edges
,
16168 phi
->u
.block
= front
;
16169 MISC(phi
, 0) = var
;
16170 use_triple(var
, phi
);
16172 if (phi
->rhs
!= in_edges
) {
16173 internal_error(state
, phi
, "phi->rhs: %d != in_edges: %d",
16174 phi
->rhs
, in_edges
);
16177 /* Insert the phi functions immediately after the label */
16178 insert_triple(state
, front
->first
->next
, phi
);
16179 if (front
->first
== front
->last
) {
16180 front
->last
= front
->first
->next
;
16182 has_already
[front
->vertex
] = iter
;
16183 transform_to_arch_instruction(state
, phi
);
16185 /* If necessary plan to visit the basic block */
16186 if (work
[front
->vertex
] >= iter
) {
16189 work
[front
->vertex
] = iter
;
16190 *work_list_tail
= front
;
16191 front
->work_next
= 0;
16192 work_list_tail
= &front
->work_next
;
16196 xfree(has_already
);
16202 struct triple_set
*top
;
16206 static int count_auto_vars(struct compile_state
*state
)
16208 struct triple
*first
, *ins
;
16210 first
= state
->first
;
16213 if (triple_is_auto_var(state
, ins
)) {
16217 } while(ins
!= first
);
16221 static void number_auto_vars(struct compile_state
*state
, struct stack
*stacks
)
16223 struct triple
*first
, *ins
;
16225 first
= state
->first
;
16228 if (triple_is_auto_var(state
, ins
)) {
16230 stacks
[auto_vars
].orig_id
= ins
->id
;
16231 ins
->id
= auto_vars
;
16234 } while(ins
!= first
);
16237 static void restore_auto_vars(struct compile_state
*state
, struct stack
*stacks
)
16239 struct triple
*first
, *ins
;
16240 first
= state
->first
;
16243 if (triple_is_auto_var(state
, ins
)) {
16244 ins
->id
= stacks
[ins
->id
].orig_id
;
16247 } while(ins
!= first
);
16250 static struct triple
*peek_triple(struct stack
*stacks
, struct triple
*var
)
16252 struct triple_set
*head
;
16253 struct triple
*top_val
;
16255 head
= stacks
[var
->id
].top
;
16257 top_val
= head
->member
;
16262 static void push_triple(struct stack
*stacks
, struct triple
*var
, struct triple
*val
)
16264 struct triple_set
*new;
16265 /* Append new to the head of the list,
16266 * it's the only sensible behavoir for a stack.
16268 new = xcmalloc(sizeof(*new), "triple_set");
16270 new->next
= stacks
[var
->id
].top
;
16271 stacks
[var
->id
].top
= new;
16274 static void pop_triple(struct stack
*stacks
, struct triple
*var
, struct triple
*oldval
)
16276 struct triple_set
*set
, **ptr
;
16277 ptr
= &stacks
[var
->id
].top
;
16280 if (set
->member
== oldval
) {
16283 /* Only free one occurance from the stack */
16296 static void fixup_block_phi_variables(
16297 struct compile_state
*state
, struct stack
*stacks
, struct block
*parent
, struct block
*block
)
16299 struct block_set
*set
;
16300 struct triple
*ptr
;
16302 if (!parent
|| !block
)
16304 /* Find the edge I am coming in on */
16306 for(set
= block
->use
; set
; set
= set
->next
, edge
++) {
16307 if (set
->member
== parent
) {
16312 internal_error(state
, 0, "phi input is not on a control predecessor");
16314 for(ptr
= block
->first
; ; ptr
= ptr
->next
) {
16315 if (ptr
->op
== OP_PHI
) {
16316 struct triple
*var
, *val
, **slot
;
16317 var
= MISC(ptr
, 0);
16319 internal_error(state
, ptr
, "no var???");
16321 /* Find the current value of the variable */
16322 val
= peek_triple(stacks
, var
);
16323 if (val
&& ((val
->op
== OP_WRITE
) || (val
->op
== OP_READ
))) {
16324 internal_error(state
, val
, "bad value in phi");
16326 if (edge
>= ptr
->rhs
) {
16327 internal_error(state
, ptr
, "edges > phi rhs");
16329 slot
= &RHS(ptr
, edge
);
16330 if ((*slot
!= 0) && (*slot
!= val
)) {
16331 internal_error(state
, ptr
, "phi already bound on this edge");
16334 use_triple(val
, ptr
);
16336 if (ptr
== block
->last
) {
16343 static void rename_block_variables(
16344 struct compile_state
*state
, struct stack
*stacks
, struct block
*block
)
16346 struct block_set
*user
, *edge
;
16347 struct triple
*ptr
, *next
, *last
;
16351 last
= block
->first
;
16353 for(ptr
= block
->first
; !done
; ptr
= next
) {
16355 if (ptr
== block
->last
) {
16359 if (ptr
->op
== OP_READ
) {
16360 struct triple
*var
, *val
;
16362 if (!triple_is_auto_var(state
, var
)) {
16363 internal_error(state
, ptr
, "read of non auto var!");
16365 unuse_triple(var
, ptr
);
16366 /* Find the current value of the variable */
16367 val
= peek_triple(stacks
, var
);
16369 /* Let the optimizer at variables that are not initially
16370 * set. But give it a bogus value so things seem to
16371 * work by accident. This is useful for bitfields because
16372 * setting them always involves a read-modify-write.
16374 if (TYPE_ARITHMETIC(ptr
->type
->type
)) {
16375 val
= pre_triple(state
, ptr
, OP_INTCONST
, ptr
->type
, 0, 0);
16376 val
->u
.cval
= 0xdeadbeaf;
16378 val
= pre_triple(state
, ptr
, OP_UNKNOWNVAL
, ptr
->type
, 0, 0);
16382 error(state
, ptr
, "variable used without being set");
16384 if ((val
->op
== OP_WRITE
) || (val
->op
== OP_READ
)) {
16385 internal_error(state
, val
, "bad value in read");
16387 propogate_use(state
, ptr
, val
);
16388 release_triple(state
, ptr
);
16392 if (ptr
->op
== OP_WRITE
) {
16393 struct triple
*var
, *val
, *tval
;
16394 var
= MISC(ptr
, 0);
16395 if (!triple_is_auto_var(state
, var
)) {
16396 internal_error(state
, ptr
, "write to non auto var!");
16398 tval
= val
= RHS(ptr
, 0);
16399 if ((val
->op
== OP_WRITE
) || (val
->op
== OP_READ
) ||
16400 triple_is_auto_var(state
, val
)) {
16401 internal_error(state
, ptr
, "bad value in write");
16403 /* Insert a cast if the types differ */
16404 if (!is_subset_type(ptr
->type
, val
->type
)) {
16405 if (val
->op
== OP_INTCONST
) {
16406 tval
= pre_triple(state
, ptr
, OP_INTCONST
, ptr
->type
, 0, 0);
16407 tval
->u
.cval
= val
->u
.cval
;
16410 tval
= pre_triple(state
, ptr
, OP_CONVERT
, ptr
->type
, val
, 0);
16411 use_triple(val
, tval
);
16413 transform_to_arch_instruction(state
, tval
);
16414 unuse_triple(val
, ptr
);
16415 RHS(ptr
, 0) = tval
;
16416 use_triple(tval
, ptr
);
16418 propogate_use(state
, ptr
, tval
);
16419 unuse_triple(var
, ptr
);
16420 /* Push OP_WRITE ptr->right onto a stack of variable uses */
16421 push_triple(stacks
, var
, tval
);
16423 if (ptr
->op
== OP_PHI
) {
16424 struct triple
*var
;
16425 var
= MISC(ptr
, 0);
16426 if (!triple_is_auto_var(state
, var
)) {
16427 internal_error(state
, ptr
, "phi references non auto var!");
16429 /* Push OP_PHI onto a stack of variable uses */
16430 push_triple(stacks
, var
, ptr
);
16434 block
->last
= last
;
16436 /* Fixup PHI functions in the cf successors */
16437 for(edge
= block
->edges
; edge
; edge
= edge
->next
) {
16438 fixup_block_phi_variables(state
, stacks
, block
, edge
->member
);
16440 /* rename variables in the dominated nodes */
16441 for(user
= block
->idominates
; user
; user
= user
->next
) {
16442 rename_block_variables(state
, stacks
, user
->member
);
16444 /* pop the renamed variable stack */
16445 last
= block
->first
;
16447 for(ptr
= block
->first
; !done
; ptr
= next
) {
16449 if (ptr
== block
->last
) {
16452 if (ptr
->op
== OP_WRITE
) {
16453 struct triple
*var
;
16454 var
= MISC(ptr
, 0);
16455 /* Pop OP_WRITE ptr->right from the stack of variable uses */
16456 pop_triple(stacks
, var
, RHS(ptr
, 0));
16457 release_triple(state
, ptr
);
16460 if (ptr
->op
== OP_PHI
) {
16461 struct triple
*var
;
16462 var
= MISC(ptr
, 0);
16463 /* Pop OP_WRITE ptr->right from the stack of variable uses */
16464 pop_triple(stacks
, var
, ptr
);
16468 block
->last
= last
;
16471 static void rename_variables(struct compile_state
*state
)
16473 struct stack
*stacks
;
16476 /* Allocate stacks for the Variables */
16477 auto_vars
= count_auto_vars(state
);
16478 stacks
= xcmalloc(sizeof(stacks
[0])*(auto_vars
+ 1), "auto var stacks");
16480 /* Give each auto_var a stack */
16481 number_auto_vars(state
, stacks
);
16483 /* Rename the variables */
16484 rename_block_variables(state
, stacks
, state
->bb
.first_block
);
16486 /* Remove the stacks from the auto_vars */
16487 restore_auto_vars(state
, stacks
);
16491 static void prune_block_variables(struct compile_state
*state
,
16492 struct block
*block
)
16494 struct block_set
*user
;
16495 struct triple
*next
, *ptr
;
16499 for(ptr
= block
->first
; !done
; ptr
= next
) {
16500 /* Be extremely careful I am deleting the list
16501 * as I walk trhough it.
16504 if (ptr
== block
->last
) {
16507 if (triple_is_auto_var(state
, ptr
)) {
16508 struct triple_set
*user
, *next
;
16509 for(user
= ptr
->use
; user
; user
= next
) {
16510 struct triple
*use
;
16512 use
= user
->member
;
16513 if (MISC(ptr
, 0) == user
->member
) {
16516 if (use
->op
!= OP_PHI
) {
16517 internal_error(state
, use
, "decl still used");
16519 if (MISC(use
, 0) != ptr
) {
16520 internal_error(state
, use
, "bad phi use of decl");
16522 unuse_triple(ptr
, use
);
16525 if ((ptr
->u
.cval
== 0) && (MISC(ptr
, 0)->lhs
== 1)) {
16526 /* Delete the adecl */
16527 release_triple(state
, MISC(ptr
, 0));
16528 /* And the piece */
16529 release_triple(state
, ptr
);
16534 for(user
= block
->idominates
; user
; user
= user
->next
) {
16535 prune_block_variables(state
, user
->member
);
16539 struct phi_triple
{
16540 struct triple
*phi
;
16545 static void keep_phi(struct compile_state
*state
, struct phi_triple
*live
, struct triple
*phi
)
16547 struct triple
**slot
;
16549 if (live
[phi
->id
].alive
) {
16552 live
[phi
->id
].alive
= 1;
16554 slot
= &RHS(phi
, 0);
16555 for(i
= 0; i
< zrhs
; i
++) {
16556 struct triple
*used
;
16558 if (used
&& (used
->op
== OP_PHI
)) {
16559 keep_phi(state
, live
, used
);
16564 static void prune_unused_phis(struct compile_state
*state
)
16566 struct triple
*first
, *phi
;
16567 struct phi_triple
*live
;
16570 /* Find the first instruction */
16571 first
= state
->first
;
16573 /* Count how many phi functions I need to process */
16575 for(phi
= first
->next
; phi
!= first
; phi
= phi
->next
) {
16576 if (phi
->op
== OP_PHI
) {
16581 /* Mark them all dead */
16582 live
= xcmalloc(sizeof(*live
) * (phis
+ 1), "phi_triple");
16584 for(phi
= first
->next
; phi
!= first
; phi
= phi
->next
) {
16585 if (phi
->op
!= OP_PHI
) {
16588 live
[phis
].alive
= 0;
16589 live
[phis
].orig_id
= phi
->id
;
16590 live
[phis
].phi
= phi
;
16595 /* Mark phis alive that are used by non phis */
16596 for(i
= 0; i
< phis
; i
++) {
16597 struct triple_set
*set
;
16598 for(set
= live
[i
].phi
->use
; !live
[i
].alive
&& set
; set
= set
->next
) {
16599 if (set
->member
->op
!= OP_PHI
) {
16600 keep_phi(state
, live
, live
[i
].phi
);
16606 /* Delete the extraneous phis */
16607 for(i
= 0; i
< phis
; i
++) {
16608 struct triple
**slot
;
16610 if (!live
[i
].alive
) {
16611 release_triple(state
, live
[i
].phi
);
16615 slot
= &RHS(phi
, 0);
16617 for(j
= 0; j
< zrhs
; j
++) {
16619 struct triple
*unknown
;
16620 get_occurance(phi
->occurance
);
16621 unknown
= flatten(state
, state
->global_pool
,
16622 alloc_triple(state
, OP_UNKNOWNVAL
,
16623 phi
->type
, 0, 0, phi
->occurance
));
16625 use_triple(unknown
, phi
);
16626 transform_to_arch_instruction(state
, unknown
);
16628 warning(state
, phi
, "variable not set at index %d on all paths to use", j
);
16636 static void transform_to_ssa_form(struct compile_state
*state
)
16638 insert_phi_operations(state
);
16639 rename_variables(state
);
16641 prune_block_variables(state
, state
->bb
.first_block
);
16642 prune_unused_phis(state
);
16644 print_blocks(state
, __func__
, state
->dbgout
);
16648 static void clear_vertex(
16649 struct compile_state
*state
, struct block
*block
, void *arg
)
16651 /* Clear the current blocks vertex and the vertex of all
16652 * of the current blocks neighbors in case there are malformed
16653 * blocks with now instructions at this point.
16655 struct block_set
*user
, *edge
;
16657 for(edge
= block
->edges
; edge
; edge
= edge
->next
) {
16658 edge
->member
->vertex
= 0;
16660 for(user
= block
->use
; user
; user
= user
->next
) {
16661 user
->member
->vertex
= 0;
16665 static void mark_live_block(
16666 struct compile_state
*state
, struct block
*block
, int *next_vertex
)
16668 /* See if this is a block that has not been marked */
16669 if (block
->vertex
!= 0) {
16672 block
->vertex
= *next_vertex
;
16674 if (triple_is_branch(state
, block
->last
)) {
16675 struct triple
**targ
;
16676 targ
= triple_edge_targ(state
, block
->last
, 0);
16677 for(; targ
; targ
= triple_edge_targ(state
, block
->last
, targ
)) {
16681 if (!triple_stores_block(state
, *targ
)) {
16682 internal_error(state
, 0, "bad targ");
16684 mark_live_block(state
, (*targ
)->u
.block
, next_vertex
);
16686 /* Ensure the last block of a function remains alive */
16687 if (triple_is_call(state
, block
->last
)) {
16688 mark_live_block(state
, MISC(block
->last
, 0)->u
.block
, next_vertex
);
16691 else if (block
->last
->next
!= state
->first
) {
16692 struct triple
*ins
;
16693 ins
= block
->last
->next
;
16694 if (!triple_stores_block(state
, ins
)) {
16695 internal_error(state
, 0, "bad block start");
16697 mark_live_block(state
, ins
->u
.block
, next_vertex
);
16701 static void transform_from_ssa_form(struct compile_state
*state
)
16703 /* To get out of ssa form we insert moves on the incoming
16704 * edges to blocks containting phi functions.
16706 struct triple
*first
;
16707 struct triple
*phi
, *var
, *next
;
16710 /* Walk the control flow to see which blocks remain alive */
16711 walk_blocks(state
, &state
->bb
, clear_vertex
, 0);
16713 mark_live_block(state
, state
->bb
.first_block
, &next_vertex
);
16715 /* Walk all of the operations to find the phi functions */
16716 first
= state
->first
;
16717 for(phi
= first
->next
; phi
!= first
; phi
= next
) {
16718 struct block_set
*set
;
16719 struct block
*block
;
16720 struct triple
**slot
;
16721 struct triple
*var
;
16722 struct triple_set
*use
, *use_next
;
16723 int edge
, writers
, readers
;
16725 if (phi
->op
!= OP_PHI
) {
16729 block
= phi
->u
.block
;
16730 slot
= &RHS(phi
, 0);
16732 /* If this phi is in a dead block just forget it */
16733 if (block
->vertex
== 0) {
16734 release_triple(state
, phi
);
16738 /* Forget uses from code in dead blocks */
16739 for(use
= phi
->use
; use
; use
= use_next
) {
16740 struct block
*ublock
;
16741 struct triple
**expr
;
16742 use_next
= use
->next
;
16743 ublock
= block_of_triple(state
, use
->member
);
16744 if ((use
->member
== phi
) || (ublock
->vertex
!= 0)) {
16747 expr
= triple_rhs(state
, use
->member
, 0);
16748 for(; expr
; expr
= triple_rhs(state
, use
->member
, expr
)) {
16749 if (*expr
== phi
) {
16753 unuse_triple(phi
, use
->member
);
16755 /* A variable to replace the phi function */
16756 if (registers_of(state
, phi
->type
) != 1) {
16757 internal_error(state
, phi
, "phi->type does not fit in a single register!");
16759 var
= post_triple(state
, phi
, OP_ADECL
, phi
->type
, 0, 0);
16760 var
= var
->next
; /* point at the var */
16762 /* Replaces use of phi with var */
16763 propogate_use(state
, phi
, var
);
16765 /* Count the readers */
16767 for(use
= var
->use
; use
; use
= use
->next
) {
16768 if (use
->member
!= MISC(var
, 0)) {
16773 /* Walk all of the incoming edges/blocks and insert moves.
16776 for(edge
= 0, set
= block
->use
; set
; set
= set
->next
, edge
++) {
16777 struct block
*eblock
, *vblock
;
16778 struct triple
*move
;
16779 struct triple
*val
, *base
;
16780 eblock
= set
->member
;
16783 unuse_triple(val
, phi
);
16784 vblock
= block_of_triple(state
, val
);
16786 /* If we don't have a value that belongs in an OP_WRITE
16789 if (!val
|| (val
== &unknown_triple
) || (val
== phi
)
16790 || (vblock
&& (vblock
->vertex
== 0))) {
16793 /* If the value should never occur error */
16795 internal_error(state
, val
, "no vblock?");
16799 /* If the value occurs in a dead block see if a replacement
16800 * block can be found.
16802 while(eblock
&& (eblock
->vertex
== 0)) {
16803 eblock
= eblock
->idom
;
16805 /* If not continue on with the next value. */
16806 if (!eblock
|| (eblock
->vertex
== 0)) {
16810 /* If we have an empty incoming block ignore it. */
16811 if (!eblock
->first
) {
16812 internal_error(state
, 0, "empty block?");
16815 /* Make certain the write is placed in the edge block... */
16816 /* Walk through the edge block backwards to find an
16817 * appropriate location for the OP_WRITE.
16819 for(base
= eblock
->last
; base
!= eblock
->first
; base
= base
->prev
) {
16820 struct triple
**expr
;
16821 if (base
->op
== OP_PIECE
) {
16822 base
= MISC(base
, 0);
16824 if ((base
== var
) || (base
== val
)) {
16827 expr
= triple_lhs(state
, base
, 0);
16828 for(; expr
; expr
= triple_lhs(state
, base
, expr
)) {
16829 if ((*expr
) == val
) {
16833 expr
= triple_rhs(state
, base
, 0);
16834 for(; expr
; expr
= triple_rhs(state
, base
, expr
)) {
16835 if ((*expr
) == var
) {
16841 if (triple_is_branch(state
, base
)) {
16842 internal_error(state
, base
,
16843 "Could not insert write to phi");
16845 move
= post_triple(state
, base
, OP_WRITE
, var
->type
, val
, var
);
16846 use_triple(val
, move
);
16847 use_triple(var
, move
);
16850 if (!writers
&& readers
) {
16851 internal_error(state
, var
, "no value written to in use phi?");
16853 /* If var is not used free it */
16855 release_triple(state
, MISC(var
, 0));
16856 release_triple(state
, var
);
16858 /* Release the phi function */
16859 release_triple(state
, phi
);
16862 /* Walk all of the operations to find the adecls */
16863 for(var
= first
->next
; var
!= first
; var
= var
->next
) {
16864 struct triple_set
*use
, *use_next
;
16865 if (!triple_is_auto_var(state
, var
)) {
16869 /* Walk through all of the rhs uses of var and
16870 * replace them with read of var.
16872 for(use
= var
->use
; use
; use
= use_next
) {
16873 struct triple
*read
, *user
;
16874 struct triple
**slot
;
16876 use_next
= use
->next
;
16877 user
= use
->member
;
16879 /* Generate a read of var */
16880 read
= pre_triple(state
, user
, OP_READ
, var
->type
, var
, 0);
16881 use_triple(var
, read
);
16883 /* Find the rhs uses and see if they need to be replaced */
16886 slot
= &RHS(user
, 0);
16887 for(i
= 0; i
< zrhs
; i
++) {
16888 if (slot
[i
] == var
) {
16893 /* If we did use it cleanup the uses */
16895 unuse_triple(var
, user
);
16896 use_triple(read
, user
);
16898 /* If we didn't use it release the extra triple */
16900 release_triple(state
, read
);
16906 #define HI() if (state->compiler->debug & DEBUG_REBUILD_SSA_FORM) { \
16907 FILE *fp = state->dbgout; \
16908 fprintf(fp, "@ %s:%d\n", __FILE__, __LINE__); romcc_print_blocks(state, fp); \
16911 static void rebuild_ssa_form(struct compile_state
*state
)
16914 transform_from_ssa_form(state
);
16916 state
->bb
.first
= state
->first
;
16917 free_basic_blocks(state
, &state
->bb
);
16918 analyze_basic_blocks(state
, &state
->bb
);
16920 insert_phi_operations(state
);
16922 rename_variables(state
);
16925 prune_block_variables(state
, state
->bb
.first_block
);
16927 prune_unused_phis(state
);
16933 * Register conflict resolution
16934 * =========================================================
16937 static struct reg_info
find_def_color(
16938 struct compile_state
*state
, struct triple
*def
)
16940 struct triple_set
*set
;
16941 struct reg_info info
;
16942 info
.reg
= REG_UNSET
;
16944 if (!triple_is_def(state
, def
)) {
16947 info
= arch_reg_lhs(state
, def
, 0);
16948 if (info
.reg
>= MAX_REGISTERS
) {
16949 info
.reg
= REG_UNSET
;
16951 for(set
= def
->use
; set
; set
= set
->next
) {
16952 struct reg_info tinfo
;
16954 i
= find_rhs_use(state
, set
->member
, def
);
16958 tinfo
= arch_reg_rhs(state
, set
->member
, i
);
16959 if (tinfo
.reg
>= MAX_REGISTERS
) {
16960 tinfo
.reg
= REG_UNSET
;
16962 if ((tinfo
.reg
!= REG_UNSET
) &&
16963 (info
.reg
!= REG_UNSET
) &&
16964 (tinfo
.reg
!= info
.reg
)) {
16965 internal_error(state
, def
, "register conflict");
16967 if ((info
.regcm
& tinfo
.regcm
) == 0) {
16968 internal_error(state
, def
, "regcm conflict %x & %x == 0",
16969 info
.regcm
, tinfo
.regcm
);
16971 if (info
.reg
== REG_UNSET
) {
16972 info
.reg
= tinfo
.reg
;
16974 info
.regcm
&= tinfo
.regcm
;
16976 if (info
.reg
>= MAX_REGISTERS
) {
16977 internal_error(state
, def
, "register out of range");
16982 static struct reg_info
find_lhs_pre_color(
16983 struct compile_state
*state
, struct triple
*ins
, int index
)
16985 struct reg_info info
;
16989 if (!zlhs
&& triple_is_def(state
, ins
)) {
16992 if (index
>= zlhs
) {
16993 internal_error(state
, ins
, "Bad lhs %d", index
);
16995 info
= arch_reg_lhs(state
, ins
, index
);
16996 for(i
= 0; i
< zrhs
; i
++) {
16997 struct reg_info rinfo
;
16998 rinfo
= arch_reg_rhs(state
, ins
, i
);
16999 if ((info
.reg
== rinfo
.reg
) &&
17000 (rinfo
.reg
>= MAX_REGISTERS
)) {
17001 struct reg_info tinfo
;
17002 tinfo
= find_lhs_pre_color(state
, RHS(ins
, index
), 0);
17003 info
.reg
= tinfo
.reg
;
17004 info
.regcm
&= tinfo
.regcm
;
17008 if (info
.reg
>= MAX_REGISTERS
) {
17009 info
.reg
= REG_UNSET
;
17014 static struct reg_info
find_rhs_post_color(
17015 struct compile_state
*state
, struct triple
*ins
, int index
);
17017 static struct reg_info
find_lhs_post_color(
17018 struct compile_state
*state
, struct triple
*ins
, int index
)
17020 struct triple_set
*set
;
17021 struct reg_info info
;
17022 struct triple
*lhs
;
17023 #if DEBUG_TRIPLE_COLOR
17024 fprintf(state
->errout
, "find_lhs_post_color(%p, %d)\n",
17027 if ((index
== 0) && triple_is_def(state
, ins
)) {
17030 else if (index
< ins
->lhs
) {
17031 lhs
= LHS(ins
, index
);
17034 internal_error(state
, ins
, "Bad lhs %d", index
);
17037 info
= arch_reg_lhs(state
, ins
, index
);
17038 if (info
.reg
>= MAX_REGISTERS
) {
17039 info
.reg
= REG_UNSET
;
17041 for(set
= lhs
->use
; set
; set
= set
->next
) {
17042 struct reg_info rinfo
;
17043 struct triple
*user
;
17045 user
= set
->member
;
17047 for(i
= 0; i
< zrhs
; i
++) {
17048 if (RHS(user
, i
) != lhs
) {
17051 rinfo
= find_rhs_post_color(state
, user
, i
);
17052 if ((info
.reg
!= REG_UNSET
) &&
17053 (rinfo
.reg
!= REG_UNSET
) &&
17054 (info
.reg
!= rinfo
.reg
)) {
17055 internal_error(state
, ins
, "register conflict");
17057 if ((info
.regcm
& rinfo
.regcm
) == 0) {
17058 internal_error(state
, ins
, "regcm conflict %x & %x == 0",
17059 info
.regcm
, rinfo
.regcm
);
17061 if (info
.reg
== REG_UNSET
) {
17062 info
.reg
= rinfo
.reg
;
17064 info
.regcm
&= rinfo
.regcm
;
17067 #if DEBUG_TRIPLE_COLOR
17068 fprintf(state
->errout
, "find_lhs_post_color(%p, %d) -> ( %d, %x)\n",
17069 ins
, index
, info
.reg
, info
.regcm
);
17074 static struct reg_info
find_rhs_post_color(
17075 struct compile_state
*state
, struct triple
*ins
, int index
)
17077 struct reg_info info
, rinfo
;
17079 #if DEBUG_TRIPLE_COLOR
17080 fprintf(state
->errout
, "find_rhs_post_color(%p, %d)\n",
17083 rinfo
= arch_reg_rhs(state
, ins
, index
);
17085 if (!zlhs
&& triple_is_def(state
, ins
)) {
17089 if (info
.reg
>= MAX_REGISTERS
) {
17090 info
.reg
= REG_UNSET
;
17092 for(i
= 0; i
< zlhs
; i
++) {
17093 struct reg_info linfo
;
17094 linfo
= arch_reg_lhs(state
, ins
, i
);
17095 if ((linfo
.reg
== rinfo
.reg
) &&
17096 (linfo
.reg
>= MAX_REGISTERS
)) {
17097 struct reg_info tinfo
;
17098 tinfo
= find_lhs_post_color(state
, ins
, i
);
17099 if (tinfo
.reg
>= MAX_REGISTERS
) {
17100 tinfo
.reg
= REG_UNSET
;
17102 info
.regcm
&= linfo
.regcm
;
17103 info
.regcm
&= tinfo
.regcm
;
17104 if (info
.reg
!= REG_UNSET
) {
17105 internal_error(state
, ins
, "register conflict");
17107 if (info
.regcm
== 0) {
17108 internal_error(state
, ins
, "regcm conflict");
17110 info
.reg
= tinfo
.reg
;
17113 #if DEBUG_TRIPLE_COLOR
17114 fprintf(state
->errout
, "find_rhs_post_color(%p, %d) -> ( %d, %x)\n",
17115 ins
, index
, info
.reg
, info
.regcm
);
17120 static struct reg_info
find_lhs_color(
17121 struct compile_state
*state
, struct triple
*ins
, int index
)
17123 struct reg_info pre
, post
, info
;
17124 #if DEBUG_TRIPLE_COLOR
17125 fprintf(state
->errout
, "find_lhs_color(%p, %d)\n",
17128 pre
= find_lhs_pre_color(state
, ins
, index
);
17129 post
= find_lhs_post_color(state
, ins
, index
);
17130 if ((pre
.reg
!= post
.reg
) &&
17131 (pre
.reg
!= REG_UNSET
) &&
17132 (post
.reg
!= REG_UNSET
)) {
17133 internal_error(state
, ins
, "register conflict");
17135 info
.regcm
= pre
.regcm
& post
.regcm
;
17136 info
.reg
= pre
.reg
;
17137 if (info
.reg
== REG_UNSET
) {
17138 info
.reg
= post
.reg
;
17140 #if DEBUG_TRIPLE_COLOR
17141 fprintf(state
->errout
, "find_lhs_color(%p, %d) -> ( %d, %x) ... (%d, %x) (%d, %x)\n",
17142 ins
, index
, info
.reg
, info
.regcm
,
17143 pre
.reg
, pre
.regcm
, post
.reg
, post
.regcm
);
17148 static struct triple
*post_copy(struct compile_state
*state
, struct triple
*ins
)
17150 struct triple_set
*entry
, *next
;
17151 struct triple
*out
;
17152 struct reg_info info
, rinfo
;
17154 info
= arch_reg_lhs(state
, ins
, 0);
17155 out
= post_triple(state
, ins
, OP_COPY
, ins
->type
, ins
, 0);
17156 use_triple(RHS(out
, 0), out
);
17157 /* Get the users of ins to use out instead */
17158 for(entry
= ins
->use
; entry
; entry
= next
) {
17160 next
= entry
->next
;
17161 if (entry
->member
== out
) {
17164 i
= find_rhs_use(state
, entry
->member
, ins
);
17168 rinfo
= arch_reg_rhs(state
, entry
->member
, i
);
17169 if ((info
.reg
== REG_UNNEEDED
) && (rinfo
.reg
== REG_UNNEEDED
)) {
17172 replace_rhs_use(state
, ins
, out
, entry
->member
);
17174 transform_to_arch_instruction(state
, out
);
17178 static struct triple
*typed_pre_copy(
17179 struct compile_state
*state
, struct type
*type
, struct triple
*ins
, int index
)
17181 /* Carefully insert enough operations so that I can
17182 * enter any operation with a GPR32.
17185 struct triple
**expr
;
17187 struct reg_info info
;
17189 if (ins
->op
== OP_PHI
) {
17190 internal_error(state
, ins
, "pre_copy on a phi?");
17192 classes
= arch_type_to_regcm(state
, type
);
17193 info
= arch_reg_rhs(state
, ins
, index
);
17194 expr
= &RHS(ins
, index
);
17195 if ((info
.regcm
& classes
) == 0) {
17196 FILE *fp
= state
->errout
;
17197 fprintf(fp
, "src_type: ");
17198 name_of(fp
, ins
->type
);
17199 fprintf(fp
, "\ndst_type: ");
17202 internal_error(state
, ins
, "pre_copy with no register classes");
17205 if (!equiv_types(type
, (*expr
)->type
)) {
17208 in
= pre_triple(state
, ins
, op
, type
, *expr
, 0);
17209 unuse_triple(*expr
, ins
);
17211 use_triple(RHS(in
, 0), in
);
17212 use_triple(in
, ins
);
17213 transform_to_arch_instruction(state
, in
);
17217 static struct triple
*pre_copy(
17218 struct compile_state
*state
, struct triple
*ins
, int index
)
17220 return typed_pre_copy(state
, RHS(ins
, index
)->type
, ins
, index
);
17224 static void insert_copies_to_phi(struct compile_state
*state
)
17226 /* To get out of ssa form we insert moves on the incoming
17227 * edges to blocks containting phi functions.
17229 struct triple
*first
;
17230 struct triple
*phi
;
17232 /* Walk all of the operations to find the phi functions */
17233 first
= state
->first
;
17234 for(phi
= first
->next
; phi
!= first
; phi
= phi
->next
) {
17235 struct block_set
*set
;
17236 struct block
*block
;
17237 struct triple
**slot
, *copy
;
17239 if (phi
->op
!= OP_PHI
) {
17242 phi
->id
|= TRIPLE_FLAG_POST_SPLIT
;
17243 block
= phi
->u
.block
;
17244 slot
= &RHS(phi
, 0);
17245 /* Phi's that feed into mandatory live range joins
17246 * cause nasty complications. Insert a copy of
17247 * the phi value so I never have to deal with
17248 * that in the rest of the code.
17250 copy
= post_copy(state
, phi
);
17251 copy
->id
|= TRIPLE_FLAG_PRE_SPLIT
;
17252 /* Walk all of the incoming edges/blocks and insert moves.
17254 for(edge
= 0, set
= block
->use
; set
; set
= set
->next
, edge
++) {
17255 struct block
*eblock
;
17256 struct triple
*move
;
17257 struct triple
*val
;
17258 struct triple
*ptr
;
17259 eblock
= set
->member
;
17266 get_occurance(val
->occurance
);
17267 move
= build_triple(state
, OP_COPY
, val
->type
, val
, 0,
17269 move
->u
.block
= eblock
;
17270 move
->id
|= TRIPLE_FLAG_PRE_SPLIT
;
17271 use_triple(val
, move
);
17274 unuse_triple(val
, phi
);
17275 use_triple(move
, phi
);
17277 /* Walk up the dominator tree until I have found the appropriate block */
17278 while(eblock
&& !tdominates(state
, val
, eblock
->last
)) {
17279 eblock
= eblock
->idom
;
17282 internal_error(state
, phi
, "Cannot find block dominated by %p",
17286 /* Walk through the block backwards to find
17287 * an appropriate location for the OP_COPY.
17289 for(ptr
= eblock
->last
; ptr
!= eblock
->first
; ptr
= ptr
->prev
) {
17290 struct triple
**expr
;
17291 if (ptr
->op
== OP_PIECE
) {
17292 ptr
= MISC(ptr
, 0);
17294 if ((ptr
== phi
) || (ptr
== val
)) {
17297 expr
= triple_lhs(state
, ptr
, 0);
17298 for(;expr
; expr
= triple_lhs(state
, ptr
, expr
)) {
17299 if ((*expr
) == val
) {
17303 expr
= triple_rhs(state
, ptr
, 0);
17304 for(;expr
; expr
= triple_rhs(state
, ptr
, expr
)) {
17305 if ((*expr
) == phi
) {
17311 if (triple_is_branch(state
, ptr
)) {
17312 internal_error(state
, ptr
,
17313 "Could not insert write to phi");
17315 insert_triple(state
, after_lhs(state
, ptr
), move
);
17316 if (eblock
->last
== after_lhs(state
, ptr
)->prev
) {
17317 eblock
->last
= move
;
17319 transform_to_arch_instruction(state
, move
);
17322 print_blocks(state
, __func__
, state
->dbgout
);
17325 struct triple_reg_set
;
17329 static int do_triple_set(struct triple_reg_set
**head
,
17330 struct triple
*member
, struct triple
*new_member
)
17332 struct triple_reg_set
**ptr
, *new;
17337 if ((*ptr
)->member
== member
) {
17340 ptr
= &(*ptr
)->next
;
17342 new = xcmalloc(sizeof(*new), "triple_set");
17343 new->member
= member
;
17344 new->new = new_member
;
17350 static void do_triple_unset(struct triple_reg_set
**head
, struct triple
*member
)
17352 struct triple_reg_set
*entry
, **ptr
;
17356 if (entry
->member
== member
) {
17357 *ptr
= entry
->next
;
17362 ptr
= &entry
->next
;
17367 static int in_triple(struct reg_block
*rb
, struct triple
*in
)
17369 return do_triple_set(&rb
->in
, in
, 0);
17372 #if DEBUG_ROMCC_WARNING
17373 static void unin_triple(struct reg_block
*rb
, struct triple
*unin
)
17375 do_triple_unset(&rb
->in
, unin
);
17379 static int out_triple(struct reg_block
*rb
, struct triple
*out
)
17381 return do_triple_set(&rb
->out
, out
, 0);
17383 #if DEBUG_ROMCC_WARNING
17384 static void unout_triple(struct reg_block
*rb
, struct triple
*unout
)
17386 do_triple_unset(&rb
->out
, unout
);
17390 static int initialize_regblock(struct reg_block
*blocks
,
17391 struct block
*block
, int vertex
)
17393 struct block_set
*user
;
17394 if (!block
|| (blocks
[block
->vertex
].block
== block
)) {
17398 /* Renumber the blocks in a convinient fashion */
17399 block
->vertex
= vertex
;
17400 blocks
[vertex
].block
= block
;
17401 blocks
[vertex
].vertex
= vertex
;
17402 for(user
= block
->use
; user
; user
= user
->next
) {
17403 vertex
= initialize_regblock(blocks
, user
->member
, vertex
);
17408 static struct triple
*part_to_piece(struct compile_state
*state
, struct triple
*ins
)
17410 /* Part to piece is a best attempt and it cannot be correct all by
17411 * itself. If various values are read as different sizes in different
17412 * parts of the code this function cannot work. Or rather it cannot
17413 * work in conjunction with compute_variable_liftimes. As the
17414 * analysis will get confused.
17416 struct triple
*base
;
17418 if (!is_lvalue(state
, ins
)) {
17423 while(ins
&& triple_is_part(state
, ins
) && (ins
->op
!= OP_PIECE
)) {
17424 base
= MISC(ins
, 0);
17427 reg
+= index_reg_offset(state
, base
->type
, ins
->u
.cval
)/REG_SIZEOF_REG
;
17430 reg
+= field_reg_offset(state
, base
->type
, ins
->u
.field
)/REG_SIZEOF_REG
;
17433 internal_error(state
, ins
, "unhandled part");
17439 if (reg
> base
->lhs
) {
17440 internal_error(state
, base
, "part out of range?");
17442 ins
= LHS(base
, reg
);
17447 static int this_def(struct compile_state
*state
,
17448 struct triple
*ins
, struct triple
*other
)
17450 if (ins
== other
) {
17453 if (ins
->op
== OP_WRITE
) {
17454 ins
= part_to_piece(state
, MISC(ins
, 0));
17456 return ins
== other
;
17459 static int phi_in(struct compile_state
*state
, struct reg_block
*blocks
,
17460 struct reg_block
*rb
, struct block
*suc
)
17462 /* Read the conditional input set of a successor block
17463 * (i.e. the input to the phi nodes) and place it in the
17464 * current blocks output set.
17466 struct block_set
*set
;
17467 struct triple
*ptr
;
17471 /* Find the edge I am coming in on */
17472 for(edge
= 0, set
= suc
->use
; set
; set
= set
->next
, edge
++) {
17473 if (set
->member
== rb
->block
) {
17478 internal_error(state
, 0, "Not coming on a control edge?");
17480 for(done
= 0, ptr
= suc
->first
; !done
; ptr
= ptr
->next
) {
17481 struct triple
**slot
, *expr
, *ptr2
;
17482 int out_change
, done2
;
17483 done
= (ptr
== suc
->last
);
17484 if (ptr
->op
!= OP_PHI
) {
17487 slot
= &RHS(ptr
, 0);
17489 out_change
= out_triple(rb
, expr
);
17493 /* If we don't define the variable also plast it
17494 * in the current blocks input set.
17496 ptr2
= rb
->block
->first
;
17497 for(done2
= 0; !done2
; ptr2
= ptr2
->next
) {
17498 if (this_def(state
, ptr2
, expr
)) {
17501 done2
= (ptr2
== rb
->block
->last
);
17506 change
|= in_triple(rb
, expr
);
17511 static int reg_in(struct compile_state
*state
, struct reg_block
*blocks
,
17512 struct reg_block
*rb
, struct block
*suc
)
17514 struct triple_reg_set
*in_set
;
17517 /* Read the input set of a successor block
17518 * and place it in the current blocks output set.
17520 in_set
= blocks
[suc
->vertex
].in
;
17521 for(; in_set
; in_set
= in_set
->next
) {
17522 int out_change
, done
;
17523 struct triple
*first
, *last
, *ptr
;
17524 out_change
= out_triple(rb
, in_set
->member
);
17528 /* If we don't define the variable also place it
17529 * in the current blocks input set.
17531 first
= rb
->block
->first
;
17532 last
= rb
->block
->last
;
17534 for(ptr
= first
; !done
; ptr
= ptr
->next
) {
17535 if (this_def(state
, ptr
, in_set
->member
)) {
17538 done
= (ptr
== last
);
17543 change
|= in_triple(rb
, in_set
->member
);
17545 change
|= phi_in(state
, blocks
, rb
, suc
);
17549 static int use_in(struct compile_state
*state
, struct reg_block
*rb
)
17551 /* Find the variables we use but don't define and add
17552 * it to the current blocks input set.
17554 #if DEBUG_ROMCC_WARNINGS
17555 #warning "FIXME is this O(N^2) algorithm bad?"
17557 struct block
*block
;
17558 struct triple
*ptr
;
17563 for(done
= 0, ptr
= block
->last
; !done
; ptr
= ptr
->prev
) {
17564 struct triple
**expr
;
17565 done
= (ptr
== block
->first
);
17566 /* The variable a phi function uses depends on the
17567 * control flow, and is handled in phi_in, not
17570 if (ptr
->op
== OP_PHI
) {
17573 expr
= triple_rhs(state
, ptr
, 0);
17574 for(;expr
; expr
= triple_rhs(state
, ptr
, expr
)) {
17575 struct triple
*rhs
, *test
;
17577 rhs
= part_to_piece(state
, *expr
);
17582 /* See if rhs is defined in this block.
17583 * A write counts as a definition.
17585 for(tdone
= 0, test
= ptr
; !tdone
; test
= test
->prev
) {
17586 tdone
= (test
== block
->first
);
17587 if (this_def(state
, test
, rhs
)) {
17592 /* If I still have a valid rhs add it to in */
17593 change
|= in_triple(rb
, rhs
);
17599 static struct reg_block
*compute_variable_lifetimes(
17600 struct compile_state
*state
, struct basic_blocks
*bb
)
17602 struct reg_block
*blocks
;
17605 sizeof(*blocks
)*(bb
->last_vertex
+ 1), "reg_block");
17606 initialize_regblock(blocks
, bb
->last_block
, 0);
17610 for(i
= 1; i
<= bb
->last_vertex
; i
++) {
17611 struct block_set
*edge
;
17612 struct reg_block
*rb
;
17614 /* Add the all successor's input set to in */
17615 for(edge
= rb
->block
->edges
; edge
; edge
= edge
->next
) {
17616 change
|= reg_in(state
, blocks
, rb
, edge
->member
);
17618 /* Add use to in... */
17619 change
|= use_in(state
, rb
);
17625 static void free_variable_lifetimes(struct compile_state
*state
,
17626 struct basic_blocks
*bb
, struct reg_block
*blocks
)
17629 /* free in_set && out_set on each block */
17630 for(i
= 1; i
<= bb
->last_vertex
; i
++) {
17631 struct triple_reg_set
*entry
, *next
;
17632 struct reg_block
*rb
;
17634 for(entry
= rb
->in
; entry
; entry
= next
) {
17635 next
= entry
->next
;
17636 do_triple_unset(&rb
->in
, entry
->member
);
17638 for(entry
= rb
->out
; entry
; entry
= next
) {
17639 next
= entry
->next
;
17640 do_triple_unset(&rb
->out
, entry
->member
);
17647 typedef void (*wvl_cb_t
)(
17648 struct compile_state
*state
,
17649 struct reg_block
*blocks
, struct triple_reg_set
*live
,
17650 struct reg_block
*rb
, struct triple
*ins
, void *arg
);
17652 static void walk_variable_lifetimes(struct compile_state
*state
,
17653 struct basic_blocks
*bb
, struct reg_block
*blocks
,
17654 wvl_cb_t cb
, void *arg
)
17658 for(i
= 1; i
<= state
->bb
.last_vertex
; i
++) {
17659 struct triple_reg_set
*live
;
17660 struct triple_reg_set
*entry
, *next
;
17661 struct triple
*ptr
, *prev
;
17662 struct reg_block
*rb
;
17663 struct block
*block
;
17666 /* Get the blocks */
17670 /* Copy out into live */
17672 for(entry
= rb
->out
; entry
; entry
= next
) {
17673 next
= entry
->next
;
17674 do_triple_set(&live
, entry
->member
, entry
->new);
17676 /* Walk through the basic block calculating live */
17677 for(done
= 0, ptr
= block
->last
; !done
; ptr
= prev
) {
17678 struct triple
**expr
;
17681 done
= (ptr
== block
->first
);
17683 /* Ensure the current definition is in live */
17684 if (triple_is_def(state
, ptr
)) {
17685 do_triple_set(&live
, ptr
, 0);
17688 /* Inform the callback function of what is
17691 cb(state
, blocks
, live
, rb
, ptr
, arg
);
17693 /* Remove the current definition from live */
17694 do_triple_unset(&live
, ptr
);
17696 /* Add the current uses to live.
17698 * It is safe to skip phi functions because they do
17699 * not have any block local uses, and the block
17700 * output sets already properly account for what
17701 * control flow depedent uses phi functions do have.
17703 if (ptr
->op
== OP_PHI
) {
17706 expr
= triple_rhs(state
, ptr
, 0);
17707 for(;expr
; expr
= triple_rhs(state
, ptr
, expr
)) {
17708 /* If the triple is not a definition skip it. */
17709 if (!*expr
|| !triple_is_def(state
, *expr
)) {
17712 do_triple_set(&live
, *expr
, 0);
17716 for(entry
= live
; entry
; entry
= next
) {
17717 next
= entry
->next
;
17718 do_triple_unset(&live
, entry
->member
);
17723 struct print_live_variable_info
{
17724 struct reg_block
*rb
;
17727 #if DEBUG_EXPLICIT_CLOSURES
17728 static void print_live_variables_block(
17729 struct compile_state
*state
, struct block
*block
, void *arg
)
17732 struct print_live_variable_info
*info
= arg
;
17733 struct block_set
*edge
;
17734 FILE *fp
= info
->fp
;
17735 struct reg_block
*rb
;
17736 struct triple
*ptr
;
17739 rb
= &info
->rb
[block
->vertex
];
17741 fprintf(fp
, "\nblock: %p (%d),",
17742 block
, block
->vertex
);
17743 for(edge
= block
->edges
; edge
; edge
= edge
->next
) {
17744 fprintf(fp
, " %p<-%p",
17746 edge
->member
&& edge
->member
->use
?edge
->member
->use
->member
: 0);
17750 struct triple_reg_set
*in_set
;
17751 fprintf(fp
, " in:");
17752 for(in_set
= rb
->in
; in_set
; in_set
= in_set
->next
) {
17753 fprintf(fp
, " %-10p", in_set
->member
);
17758 for(done
= 0, ptr
= block
->first
; !done
; ptr
= ptr
->next
) {
17759 done
= (ptr
== block
->last
);
17760 if (ptr
->op
== OP_PHI
) {
17767 for(edge
= 0; edge
< block
->users
; edge
++) {
17768 fprintf(fp
, " in(%d):", edge
);
17769 for(done
= 0, ptr
= block
->first
; !done
; ptr
= ptr
->next
) {
17770 struct triple
**slot
;
17771 done
= (ptr
== block
->last
);
17772 if (ptr
->op
!= OP_PHI
) {
17775 slot
= &RHS(ptr
, 0);
17776 fprintf(fp
, " %-10p", slot
[edge
]);
17781 if (block
->first
->op
== OP_LABEL
) {
17782 fprintf(fp
, "%p:\n", block
->first
);
17784 for(done
= 0, ptr
= block
->first
; !done
; ptr
= ptr
->next
) {
17785 done
= (ptr
== block
->last
);
17786 display_triple(fp
, ptr
);
17789 struct triple_reg_set
*out_set
;
17790 fprintf(fp
, " out:");
17791 for(out_set
= rb
->out
; out_set
; out_set
= out_set
->next
) {
17792 fprintf(fp
, " %-10p", out_set
->member
);
17799 static void print_live_variables(struct compile_state
*state
,
17800 struct basic_blocks
*bb
, struct reg_block
*rb
, FILE *fp
)
17802 struct print_live_variable_info info
;
17805 fprintf(fp
, "\nlive variables by block\n");
17806 walk_blocks(state
, bb
, print_live_variables_block
, &info
);
17811 static int count_triples(struct compile_state
*state
)
17813 struct triple
*first
, *ins
;
17815 first
= state
->first
;
17820 } while (ins
!= first
);
17825 struct dead_triple
{
17826 struct triple
*triple
;
17827 struct dead_triple
*work_next
;
17828 struct block
*block
;
17831 #define TRIPLE_FLAG_ALIVE 1
17832 #define TRIPLE_FLAG_FREE 1
17835 static void print_dead_triples(struct compile_state
*state
,
17836 struct dead_triple
*dtriple
)
17838 struct triple
*first
, *ins
;
17839 struct dead_triple
*dt
;
17841 if (!(state
->compiler
->debug
& DEBUG_TRIPLES
)) {
17844 fp
= state
->dbgout
;
17845 fprintf(fp
, "--------------- dtriples ---------------\n");
17846 first
= state
->first
;
17849 dt
= &dtriple
[ins
->id
];
17850 if ((ins
->op
== OP_LABEL
) && (ins
->use
)) {
17851 fprintf(fp
, "\n%p:\n", ins
);
17854 (dt
->flags
& TRIPLE_FLAG_ALIVE
)?' ': '-');
17855 display_triple(fp
, ins
);
17856 if (triple_is_branch(state
, ins
)) {
17860 } while(ins
!= first
);
17865 static void awaken(
17866 struct compile_state
*state
,
17867 struct dead_triple
*dtriple
, struct triple
**expr
,
17868 struct dead_triple
***work_list_tail
)
17870 struct triple
*triple
;
17871 struct dead_triple
*dt
;
17879 if (triple
->id
<= 0) {
17880 internal_error(state
, triple
, "bad triple id: %d",
17883 if (triple
->op
== OP_NOOP
) {
17884 internal_error(state
, triple
, "awakening noop?");
17887 dt
= &dtriple
[triple
->id
];
17888 if (!(dt
->flags
& TRIPLE_FLAG_ALIVE
)) {
17889 dt
->flags
|= TRIPLE_FLAG_ALIVE
;
17890 if (!dt
->work_next
) {
17891 **work_list_tail
= dt
;
17892 *work_list_tail
= &dt
->work_next
;
17897 static void eliminate_inefectual_code(struct compile_state
*state
)
17899 struct dead_triple
*dtriple
, *work_list
, **work_list_tail
, *dt
;
17901 struct triple
*first
, *ins
;
17903 if (!(state
->compiler
->flags
& COMPILER_ELIMINATE_INEFECTUAL_CODE
)) {
17907 /* Setup the work list */
17909 work_list_tail
= &work_list
;
17911 first
= state
->first
;
17913 /* Count how many triples I have */
17914 triples
= count_triples(state
);
17916 /* Now put then in an array and mark all of the triples dead */
17917 dtriple
= xcmalloc(sizeof(*dtriple
) * (triples
+ 1), "dtriples");
17922 dtriple
[i
].triple
= ins
;
17923 dtriple
[i
].block
= block_of_triple(state
, ins
);
17924 dtriple
[i
].flags
= 0;
17925 dtriple
[i
].old_id
= ins
->id
;
17927 /* See if it is an operation we always keep */
17928 if (!triple_is_pure(state
, ins
, dtriple
[i
].old_id
)) {
17929 awaken(state
, dtriple
, &ins
, &work_list_tail
);
17933 } while(ins
!= first
);
17935 struct block
*block
;
17936 struct dead_triple
*dt
;
17937 struct block_set
*user
;
17938 struct triple
**expr
;
17940 work_list
= dt
->work_next
;
17942 work_list_tail
= &work_list
;
17944 /* Make certain the block the current instruction is in lives */
17945 block
= block_of_triple(state
, dt
->triple
);
17946 awaken(state
, dtriple
, &block
->first
, &work_list_tail
);
17947 if (triple_is_branch(state
, block
->last
)) {
17948 awaken(state
, dtriple
, &block
->last
, &work_list_tail
);
17950 awaken(state
, dtriple
, &block
->last
->next
, &work_list_tail
);
17953 /* Wake up the data depencencies of this triple */
17956 expr
= triple_rhs(state
, dt
->triple
, expr
);
17957 awaken(state
, dtriple
, expr
, &work_list_tail
);
17960 expr
= triple_lhs(state
, dt
->triple
, expr
);
17961 awaken(state
, dtriple
, expr
, &work_list_tail
);
17964 expr
= triple_misc(state
, dt
->triple
, expr
);
17965 awaken(state
, dtriple
, expr
, &work_list_tail
);
17967 /* Wake up the forward control dependencies */
17969 expr
= triple_targ(state
, dt
->triple
, expr
);
17970 awaken(state
, dtriple
, expr
, &work_list_tail
);
17972 /* Wake up the reverse control dependencies of this triple */
17973 for(user
= dt
->block
->ipdomfrontier
; user
; user
= user
->next
) {
17974 struct triple
*last
;
17975 last
= user
->member
->last
;
17976 while((last
->op
== OP_NOOP
) && (last
!= user
->member
->first
)) {
17977 #if DEBUG_ROMCC_WARNINGS
17978 #warning "Should we bring the awakening noops back?"
17980 // internal_warning(state, last, "awakening noop?");
17983 awaken(state
, dtriple
, &last
, &work_list_tail
);
17986 print_dead_triples(state
, dtriple
);
17987 for(dt
= &dtriple
[1]; dt
<= &dtriple
[triples
]; dt
++) {
17988 if ((dt
->triple
->op
== OP_NOOP
) &&
17989 (dt
->flags
& TRIPLE_FLAG_ALIVE
)) {
17990 internal_error(state
, dt
->triple
, "noop effective?");
17992 dt
->triple
->id
= dt
->old_id
; /* Restore the color */
17993 if (!(dt
->flags
& TRIPLE_FLAG_ALIVE
)) {
17994 release_triple(state
, dt
->triple
);
17999 rebuild_ssa_form(state
);
18001 print_blocks(state
, __func__
, state
->dbgout
);
18005 static void insert_mandatory_copies(struct compile_state
*state
)
18007 struct triple
*ins
, *first
;
18009 /* The object is with a minimum of inserted copies,
18010 * to resolve in fundamental register conflicts between
18011 * register value producers and consumers.
18012 * Theoretically we may be greater than minimal when we
18013 * are inserting copies before instructions but that
18014 * case should be rare.
18016 first
= state
->first
;
18019 struct triple_set
*entry
, *next
;
18020 struct triple
*tmp
;
18021 struct reg_info info
;
18022 unsigned reg
, regcm
;
18023 int do_post_copy
, do_pre_copy
;
18025 if (!triple_is_def(state
, ins
)) {
18028 /* Find the architecture specific color information */
18029 info
= find_lhs_pre_color(state
, ins
, 0);
18030 if (info
.reg
>= MAX_REGISTERS
) {
18031 info
.reg
= REG_UNSET
;
18035 regcm
= arch_type_to_regcm(state
, ins
->type
);
18036 do_post_copy
= do_pre_copy
= 0;
18038 /* Walk through the uses of ins and check for conflicts */
18039 for(entry
= ins
->use
; entry
; entry
= next
) {
18040 struct reg_info rinfo
;
18042 next
= entry
->next
;
18043 i
= find_rhs_use(state
, entry
->member
, ins
);
18048 /* Find the users color requirements */
18049 rinfo
= arch_reg_rhs(state
, entry
->member
, i
);
18050 if (rinfo
.reg
>= MAX_REGISTERS
) {
18051 rinfo
.reg
= REG_UNSET
;
18054 /* See if I need a pre_copy */
18055 if (rinfo
.reg
!= REG_UNSET
) {
18056 if ((reg
!= REG_UNSET
) && (reg
!= rinfo
.reg
)) {
18061 regcm
&= rinfo
.regcm
;
18062 regcm
= arch_regcm_normalize(state
, regcm
);
18066 /* Always use pre_copies for constants.
18067 * They do not take up any registers until a
18068 * copy places them in one.
18070 if ((info
.reg
== REG_UNNEEDED
) &&
18071 (rinfo
.reg
!= REG_UNNEEDED
)) {
18077 (((info
.reg
!= REG_UNSET
) &&
18078 (reg
!= REG_UNSET
) &&
18079 (info
.reg
!= reg
)) ||
18080 ((info
.regcm
& regcm
) == 0));
18083 regcm
= info
.regcm
;
18084 /* Walk through the uses of ins and do a pre_copy or see if a post_copy is warranted */
18085 for(entry
= ins
->use
; entry
; entry
= next
) {
18086 struct reg_info rinfo
;
18088 next
= entry
->next
;
18089 i
= find_rhs_use(state
, entry
->member
, ins
);
18094 /* Find the users color requirements */
18095 rinfo
= arch_reg_rhs(state
, entry
->member
, i
);
18096 if (rinfo
.reg
>= MAX_REGISTERS
) {
18097 rinfo
.reg
= REG_UNSET
;
18100 /* Now see if it is time to do the pre_copy */
18101 if (rinfo
.reg
!= REG_UNSET
) {
18102 if (((reg
!= REG_UNSET
) && (reg
!= rinfo
.reg
)) ||
18103 ((regcm
& rinfo
.regcm
) == 0) ||
18104 /* Don't let a mandatory coalesce sneak
18105 * into a operation that is marked to prevent
18108 ((reg
!= REG_UNNEEDED
) &&
18109 ((ins
->id
& TRIPLE_FLAG_POST_SPLIT
) ||
18110 (entry
->member
->id
& TRIPLE_FLAG_PRE_SPLIT
)))
18113 struct triple
*user
;
18114 user
= entry
->member
;
18115 if (RHS(user
, i
) != ins
) {
18116 internal_error(state
, user
, "bad rhs");
18118 tmp
= pre_copy(state
, user
, i
);
18119 tmp
->id
|= TRIPLE_FLAG_PRE_SPLIT
;
18127 if ((regcm
& rinfo
.regcm
) == 0) {
18129 struct triple
*user
;
18130 user
= entry
->member
;
18131 if (RHS(user
, i
) != ins
) {
18132 internal_error(state
, user
, "bad rhs");
18134 tmp
= pre_copy(state
, user
, i
);
18135 tmp
->id
|= TRIPLE_FLAG_PRE_SPLIT
;
18141 regcm
&= rinfo
.regcm
;
18144 if (do_post_copy
) {
18145 struct reg_info pre
, post
;
18146 tmp
= post_copy(state
, ins
);
18147 tmp
->id
|= TRIPLE_FLAG_PRE_SPLIT
;
18148 pre
= arch_reg_lhs(state
, ins
, 0);
18149 post
= arch_reg_lhs(state
, tmp
, 0);
18150 if ((pre
.reg
== post
.reg
) && (pre
.regcm
== post
.regcm
)) {
18151 internal_error(state
, tmp
, "useless copy");
18156 } while(ins
!= first
);
18158 print_blocks(state
, __func__
, state
->dbgout
);
18162 struct live_range_edge
;
18163 struct live_range_def
;
18164 struct live_range
{
18165 struct live_range_edge
*edges
;
18166 struct live_range_def
*defs
;
18167 /* Note. The list pointed to by defs is kept in order.
18168 * That is baring splits in the flow control
18169 * defs dominates defs->next wich dominates defs->next->next
18176 struct live_range
*group_next
, **group_prev
;
18179 struct live_range_edge
{
18180 struct live_range_edge
*next
;
18181 struct live_range
*node
;
18184 struct live_range_def
{
18185 struct live_range_def
*next
;
18186 struct live_range_def
*prev
;
18187 struct live_range
*lr
;
18188 struct triple
*def
;
18192 #define LRE_HASH_SIZE 2048
18194 struct lre_hash
*next
;
18195 struct live_range
*left
;
18196 struct live_range
*right
;
18201 struct lre_hash
*hash
[LRE_HASH_SIZE
];
18202 struct reg_block
*blocks
;
18203 struct live_range_def
*lrd
;
18204 struct live_range
*lr
;
18205 struct live_range
*low
, **low_tail
;
18206 struct live_range
*high
, **high_tail
;
18209 int passes
, max_passes
;
18213 struct print_interference_block_info
{
18214 struct reg_state
*rstate
;
18218 static void print_interference_block(
18219 struct compile_state
*state
, struct block
*block
, void *arg
)
18222 struct print_interference_block_info
*info
= arg
;
18223 struct reg_state
*rstate
= info
->rstate
;
18224 struct block_set
*edge
;
18225 FILE *fp
= info
->fp
;
18226 struct reg_block
*rb
;
18227 struct triple
*ptr
;
18230 rb
= &rstate
->blocks
[block
->vertex
];
18232 fprintf(fp
, "\nblock: %p (%d),",
18233 block
, block
->vertex
);
18234 for(edge
= block
->edges
; edge
; edge
= edge
->next
) {
18235 fprintf(fp
, " %p<-%p",
18237 edge
->member
&& edge
->member
->use
?edge
->member
->use
->member
: 0);
18241 struct triple_reg_set
*in_set
;
18242 fprintf(fp
, " in:");
18243 for(in_set
= rb
->in
; in_set
; in_set
= in_set
->next
) {
18244 fprintf(fp
, " %-10p", in_set
->member
);
18249 for(done
= 0, ptr
= block
->first
; !done
; ptr
= ptr
->next
) {
18250 done
= (ptr
== block
->last
);
18251 if (ptr
->op
== OP_PHI
) {
18258 for(edge
= 0; edge
< block
->users
; edge
++) {
18259 fprintf(fp
, " in(%d):", edge
);
18260 for(done
= 0, ptr
= block
->first
; !done
; ptr
= ptr
->next
) {
18261 struct triple
**slot
;
18262 done
= (ptr
== block
->last
);
18263 if (ptr
->op
!= OP_PHI
) {
18266 slot
= &RHS(ptr
, 0);
18267 fprintf(fp
, " %-10p", slot
[edge
]);
18272 if (block
->first
->op
== OP_LABEL
) {
18273 fprintf(fp
, "%p:\n", block
->first
);
18275 for(done
= 0, ptr
= block
->first
; !done
; ptr
= ptr
->next
) {
18276 struct live_range
*lr
;
18278 done
= (ptr
== block
->last
);
18279 lr
= rstate
->lrd
[ptr
->id
].lr
;
18282 ptr
->id
= rstate
->lrd
[id
].orig_id
;
18283 SET_REG(ptr
->id
, lr
->color
);
18284 display_triple(fp
, ptr
);
18287 if (triple_is_def(state
, ptr
) && (lr
->defs
== 0)) {
18288 internal_error(state
, ptr
, "lr has no defs!");
18290 if (info
->need_edges
) {
18292 struct live_range_def
*lrd
;
18293 fprintf(fp
, " range:");
18296 fprintf(fp
, " %-10p", lrd
->def
);
18298 } while(lrd
!= lr
->defs
);
18301 if (lr
->edges
> 0) {
18302 struct live_range_edge
*edge
;
18303 fprintf(fp
, " edges:");
18304 for(edge
= lr
->edges
; edge
; edge
= edge
->next
) {
18305 struct live_range_def
*lrd
;
18306 lrd
= edge
->node
->defs
;
18308 fprintf(fp
, " %-10p", lrd
->def
);
18310 } while(lrd
!= edge
->node
->defs
);
18316 /* Do a bunch of sanity checks */
18317 valid_ins(state
, ptr
);
18318 if (ptr
->id
> rstate
->defs
) {
18319 internal_error(state
, ptr
, "Invalid triple id: %d",
18324 struct triple_reg_set
*out_set
;
18325 fprintf(fp
, " out:");
18326 for(out_set
= rb
->out
; out_set
; out_set
= out_set
->next
) {
18327 fprintf(fp
, " %-10p", out_set
->member
);
18334 static void print_interference_blocks(
18335 struct compile_state
*state
, struct reg_state
*rstate
, FILE *fp
, int need_edges
)
18337 struct print_interference_block_info info
;
18338 info
.rstate
= rstate
;
18340 info
.need_edges
= need_edges
;
18341 fprintf(fp
, "\nlive variables by block\n");
18342 walk_blocks(state
, &state
->bb
, print_interference_block
, &info
);
18346 static unsigned regc_max_size(struct compile_state
*state
, int classes
)
18351 for(i
= 0; i
< MAX_REGC
; i
++) {
18352 if (classes
& (1 << i
)) {
18354 size
= arch_regc_size(state
, i
);
18355 if (size
> max_size
) {
18363 static int reg_is_reg(struct compile_state
*state
, int reg1
, int reg2
)
18365 unsigned equivs
[MAX_REG_EQUIVS
];
18367 if ((reg1
< 0) || (reg1
>= MAX_REGISTERS
)) {
18368 internal_error(state
, 0, "invalid register");
18370 if ((reg2
< 0) || (reg2
>= MAX_REGISTERS
)) {
18371 internal_error(state
, 0, "invalid register");
18373 arch_reg_equivs(state
, equivs
, reg1
);
18374 for(i
= 0; (i
< MAX_REG_EQUIVS
) && equivs
[i
] != REG_UNSET
; i
++) {
18375 if (equivs
[i
] == reg2
) {
18382 static void reg_fill_used(struct compile_state
*state
, char *used
, int reg
)
18384 unsigned equivs
[MAX_REG_EQUIVS
];
18386 if (reg
== REG_UNNEEDED
) {
18389 arch_reg_equivs(state
, equivs
, reg
);
18390 for(i
= 0; (i
< MAX_REG_EQUIVS
) && equivs
[i
] != REG_UNSET
; i
++) {
18391 used
[equivs
[i
]] = 1;
18396 static void reg_inc_used(struct compile_state
*state
, char *used
, int reg
)
18398 unsigned equivs
[MAX_REG_EQUIVS
];
18400 if (reg
== REG_UNNEEDED
) {
18403 arch_reg_equivs(state
, equivs
, reg
);
18404 for(i
= 0; (i
< MAX_REG_EQUIVS
) && equivs
[i
] != REG_UNSET
; i
++) {
18405 used
[equivs
[i
]] += 1;
18410 static unsigned int hash_live_edge(
18411 struct live_range
*left
, struct live_range
*right
)
18413 unsigned int hash
, val
;
18414 unsigned long lval
, rval
;
18415 lval
= ((unsigned long)left
)/sizeof(struct live_range
);
18416 rval
= ((unsigned long)right
)/sizeof(struct live_range
);
18421 hash
= (hash
*263) + val
;
18426 hash
= (hash
*263) + val
;
18428 hash
= hash
& (LRE_HASH_SIZE
- 1);
18432 static struct lre_hash
**lre_probe(struct reg_state
*rstate
,
18433 struct live_range
*left
, struct live_range
*right
)
18435 struct lre_hash
**ptr
;
18436 unsigned int index
;
18437 /* Ensure left <= right */
18438 if (left
> right
) {
18439 struct live_range
*tmp
;
18444 index
= hash_live_edge(left
, right
);
18446 ptr
= &rstate
->hash
[index
];
18448 if (((*ptr
)->left
== left
) && ((*ptr
)->right
== right
)) {
18451 ptr
= &(*ptr
)->next
;
18456 static int interfere(struct reg_state
*rstate
,
18457 struct live_range
*left
, struct live_range
*right
)
18459 struct lre_hash
**ptr
;
18460 ptr
= lre_probe(rstate
, left
, right
);
18461 return ptr
&& *ptr
;
18464 static void add_live_edge(struct reg_state
*rstate
,
18465 struct live_range
*left
, struct live_range
*right
)
18467 /* FIXME the memory allocation overhead is noticeable here... */
18468 struct lre_hash
**ptr
, *new_hash
;
18469 struct live_range_edge
*edge
;
18471 if (left
== right
) {
18474 if ((left
== &rstate
->lr
[0]) || (right
== &rstate
->lr
[0])) {
18477 /* Ensure left <= right */
18478 if (left
> right
) {
18479 struct live_range
*tmp
;
18484 ptr
= lre_probe(rstate
, left
, right
);
18489 fprintf(state
->errout
, "new_live_edge(%p, %p)\n",
18492 new_hash
= xmalloc(sizeof(*new_hash
), "lre_hash");
18493 new_hash
->next
= *ptr
;
18494 new_hash
->left
= left
;
18495 new_hash
->right
= right
;
18498 edge
= xmalloc(sizeof(*edge
), "live_range_edge");
18499 edge
->next
= left
->edges
;
18500 edge
->node
= right
;
18501 left
->edges
= edge
;
18504 edge
= xmalloc(sizeof(*edge
), "live_range_edge");
18505 edge
->next
= right
->edges
;
18507 right
->edges
= edge
;
18508 right
->degree
+= 1;
18511 static void remove_live_edge(struct reg_state
*rstate
,
18512 struct live_range
*left
, struct live_range
*right
)
18514 struct live_range_edge
*edge
, **ptr
;
18515 struct lre_hash
**hptr
, *entry
;
18516 hptr
= lre_probe(rstate
, left
, right
);
18517 if (!hptr
|| !*hptr
) {
18521 *hptr
= entry
->next
;
18524 for(ptr
= &left
->edges
; *ptr
; ptr
= &(*ptr
)->next
) {
18526 if (edge
->node
== right
) {
18528 memset(edge
, 0, sizeof(*edge
));
18534 for(ptr
= &right
->edges
; *ptr
; ptr
= &(*ptr
)->next
) {
18536 if (edge
->node
== left
) {
18538 memset(edge
, 0, sizeof(*edge
));
18546 static void remove_live_edges(struct reg_state
*rstate
, struct live_range
*range
)
18548 struct live_range_edge
*edge
, *next
;
18549 for(edge
= range
->edges
; edge
; edge
= next
) {
18551 remove_live_edge(rstate
, range
, edge
->node
);
18555 static void transfer_live_edges(struct reg_state
*rstate
,
18556 struct live_range
*dest
, struct live_range
*src
)
18558 struct live_range_edge
*edge
, *next
;
18559 for(edge
= src
->edges
; edge
; edge
= next
) {
18560 struct live_range
*other
;
18562 other
= edge
->node
;
18563 remove_live_edge(rstate
, src
, other
);
18564 add_live_edge(rstate
, dest
, other
);
18569 /* Interference graph...
18571 * new(n) --- Return a graph with n nodes but no edges.
18572 * add(g,x,y) --- Return a graph including g with an between x and y
18573 * interfere(g, x, y) --- Return true if there exists an edge between the nodes
18574 * x and y in the graph g
18575 * degree(g, x) --- Return the degree of the node x in the graph g
18576 * neighbors(g, x, f) --- Apply function f to each neighbor of node x in the graph g
18578 * Implement with a hash table && a set of adjcency vectors.
18579 * The hash table supports constant time implementations of add and interfere.
18580 * The adjacency vectors support an efficient implementation of neighbors.
18584 * +---------------------------------------------------+
18585 * | +--------------+ |
18587 * renumber -> build graph -> colalesce -> spill_costs -> simplify -> select
18589 * -- In simplify implment optimistic coloring... (No backtracking)
18590 * -- Implement Rematerialization it is the only form of spilling we can perform
18591 * Essentially this means dropping a constant from a register because
18592 * we can regenerate it later.
18594 * --- Very conservative colalescing (don't colalesce just mark the opportunities)
18595 * coalesce at phi points...
18596 * --- Bias coloring if at all possible do the coalesing a compile time.
18601 #if DEBUG_ROMCC_WARNING
18602 static void different_colored(
18603 struct compile_state
*state
, struct reg_state
*rstate
,
18604 struct triple
*parent
, struct triple
*ins
)
18606 struct live_range
*lr
;
18607 struct triple
**expr
;
18608 lr
= rstate
->lrd
[ins
->id
].lr
;
18609 expr
= triple_rhs(state
, ins
, 0);
18610 for(;expr
; expr
= triple_rhs(state
, ins
, expr
)) {
18611 struct live_range
*lr2
;
18612 if (!*expr
|| (*expr
== parent
) || (*expr
== ins
)) {
18615 lr2
= rstate
->lrd
[(*expr
)->id
].lr
;
18616 if (lr
->color
== lr2
->color
) {
18617 internal_error(state
, ins
, "live range too big");
18623 static struct live_range
*coalesce_ranges(
18624 struct compile_state
*state
, struct reg_state
*rstate
,
18625 struct live_range
*lr1
, struct live_range
*lr2
)
18627 struct live_range_def
*head
, *mid1
, *mid2
, *end
, *lrd
;
18633 if (!lr1
->defs
|| !lr2
->defs
) {
18634 internal_error(state
, 0,
18635 "cannot coalese dead live ranges");
18637 if ((lr1
->color
== REG_UNNEEDED
) ||
18638 (lr2
->color
== REG_UNNEEDED
)) {
18639 internal_error(state
, 0,
18640 "cannot coalesce live ranges without a possible color");
18642 if ((lr1
->color
!= lr2
->color
) &&
18643 (lr1
->color
!= REG_UNSET
) &&
18644 (lr2
->color
!= REG_UNSET
)) {
18645 internal_error(state
, lr1
->defs
->def
,
18646 "cannot coalesce live ranges of different colors");
18648 color
= lr1
->color
;
18649 if (color
== REG_UNSET
) {
18650 color
= lr2
->color
;
18652 classes
= lr1
->classes
& lr2
->classes
;
18654 internal_error(state
, lr1
->defs
->def
,
18655 "cannot coalesce live ranges with dissimilar register classes");
18657 if (state
->compiler
->debug
& DEBUG_COALESCING
) {
18658 FILE *fp
= state
->errout
;
18659 fprintf(fp
, "coalescing:");
18662 fprintf(fp
, " %p", lrd
->def
);
18664 } while(lrd
!= lr1
->defs
);
18668 fprintf(fp
, " %p", lrd
->def
);
18670 } while(lrd
!= lr2
->defs
);
18673 /* If there is a clear dominate live range put it in lr1,
18674 * For purposes of this test phi functions are
18675 * considered dominated by the definitions that feed into
18678 if ((lr1
->defs
->prev
->def
->op
== OP_PHI
) ||
18679 ((lr2
->defs
->prev
->def
->op
!= OP_PHI
) &&
18680 tdominates(state
, lr2
->defs
->def
, lr1
->defs
->def
))) {
18681 struct live_range
*tmp
;
18687 if (lr1
->defs
->orig_id
& TRIPLE_FLAG_POST_SPLIT
) {
18688 fprintf(state
->errout
, "lr1 post\n");
18690 if (lr1
->defs
->orig_id
& TRIPLE_FLAG_PRE_SPLIT
) {
18691 fprintf(state
->errout
, "lr1 pre\n");
18693 if (lr2
->defs
->orig_id
& TRIPLE_FLAG_POST_SPLIT
) {
18694 fprintf(state
->errout
, "lr2 post\n");
18696 if (lr2
->defs
->orig_id
& TRIPLE_FLAG_PRE_SPLIT
) {
18697 fprintf(state
->errout
, "lr2 pre\n");
18701 fprintf(state
->errout
, "coalesce color1(%p): %3d color2(%p) %3d\n",
18708 /* Append lr2 onto lr1 */
18709 #if DEBUG_ROMCC_WARNINGS
18710 #warning "FIXME should this be a merge instead of a splice?"
18712 /* This FIXME item applies to the correctness of live_range_end
18713 * and to the necessity of making multiple passes of coalesce_live_ranges.
18714 * A failure to find some coalesce opportunities in coaleace_live_ranges
18715 * does not impact the correct of the compiler just the efficiency with
18716 * which registers are allocated.
18719 mid1
= lr1
->defs
->prev
;
18721 end
= lr2
->defs
->prev
;
18729 /* Fixup the live range in the added live range defs */
18734 } while(lrd
!= head
);
18736 /* Mark lr2 as free. */
18738 lr2
->color
= REG_UNNEEDED
;
18742 internal_error(state
, 0, "lr1->defs == 0 ?");
18745 lr1
->color
= color
;
18746 lr1
->classes
= classes
;
18748 /* Keep the graph in sync by transfering the edges from lr2 to lr1 */
18749 transfer_live_edges(rstate
, lr1
, lr2
);
18754 static struct live_range_def
*live_range_head(
18755 struct compile_state
*state
, struct live_range
*lr
,
18756 struct live_range_def
*last
)
18758 struct live_range_def
*result
;
18763 else if (!tdominates(state
, lr
->defs
->def
, last
->next
->def
)) {
18764 result
= last
->next
;
18769 static struct live_range_def
*live_range_end(
18770 struct compile_state
*state
, struct live_range
*lr
,
18771 struct live_range_def
*last
)
18773 struct live_range_def
*result
;
18776 result
= lr
->defs
->prev
;
18778 else if (!tdominates(state
, last
->prev
->def
, lr
->defs
->prev
->def
)) {
18779 result
= last
->prev
;
18785 static void initialize_live_ranges(
18786 struct compile_state
*state
, struct reg_state
*rstate
)
18788 struct triple
*ins
, *first
;
18789 size_t count
, size
;
18792 first
= state
->first
;
18793 /* First count how many instructions I have.
18795 count
= count_triples(state
);
18796 /* Potentially I need one live range definitions for each
18799 rstate
->defs
= count
;
18800 /* Potentially I need one live range for each instruction
18801 * plus an extra for the dummy live range.
18803 rstate
->ranges
= count
+ 1;
18804 size
= sizeof(rstate
->lrd
[0]) * rstate
->defs
;
18805 rstate
->lrd
= xcmalloc(size
, "live_range_def");
18806 size
= sizeof(rstate
->lr
[0]) * rstate
->ranges
;
18807 rstate
->lr
= xcmalloc(size
, "live_range");
18809 /* Setup the dummy live range */
18810 rstate
->lr
[0].classes
= 0;
18811 rstate
->lr
[0].color
= REG_UNSET
;
18812 rstate
->lr
[0].defs
= 0;
18816 /* If the triple is a variable give it a live range */
18817 if (triple_is_def(state
, ins
)) {
18818 struct reg_info info
;
18819 /* Find the architecture specific color information */
18820 info
= find_def_color(state
, ins
);
18822 rstate
->lr
[i
].defs
= &rstate
->lrd
[j
];
18823 rstate
->lr
[i
].color
= info
.reg
;
18824 rstate
->lr
[i
].classes
= info
.regcm
;
18825 rstate
->lr
[i
].degree
= 0;
18826 rstate
->lrd
[j
].lr
= &rstate
->lr
[i
];
18828 /* Otherwise give the triple the dummy live range. */
18830 rstate
->lrd
[j
].lr
= &rstate
->lr
[0];
18833 /* Initalize the live_range_def */
18834 rstate
->lrd
[j
].next
= &rstate
->lrd
[j
];
18835 rstate
->lrd
[j
].prev
= &rstate
->lrd
[j
];
18836 rstate
->lrd
[j
].def
= ins
;
18837 rstate
->lrd
[j
].orig_id
= ins
->id
;
18842 } while(ins
!= first
);
18843 rstate
->ranges
= i
;
18845 /* Make a second pass to handle achitecture specific register
18850 int zlhs
, zrhs
, i
, j
;
18851 if (ins
->id
> rstate
->defs
) {
18852 internal_error(state
, ins
, "bad id");
18855 /* Walk through the template of ins and coalesce live ranges */
18857 if ((zlhs
== 0) && triple_is_def(state
, ins
)) {
18862 if (state
->compiler
->debug
& DEBUG_COALESCING2
) {
18863 fprintf(state
->errout
, "mandatory coalesce: %p %d %d\n",
18867 for(i
= 0; i
< zlhs
; i
++) {
18868 struct reg_info linfo
;
18869 struct live_range_def
*lhs
;
18870 linfo
= arch_reg_lhs(state
, ins
, i
);
18871 if (linfo
.reg
< MAX_REGISTERS
) {
18874 if (triple_is_def(state
, ins
)) {
18875 lhs
= &rstate
->lrd
[ins
->id
];
18877 lhs
= &rstate
->lrd
[LHS(ins
, i
)->id
];
18880 if (state
->compiler
->debug
& DEBUG_COALESCING2
) {
18881 fprintf(state
->errout
, "coalesce lhs(%d): %p %d\n",
18882 i
, lhs
, linfo
.reg
);
18885 for(j
= 0; j
< zrhs
; j
++) {
18886 struct reg_info rinfo
;
18887 struct live_range_def
*rhs
;
18888 rinfo
= arch_reg_rhs(state
, ins
, j
);
18889 if (rinfo
.reg
< MAX_REGISTERS
) {
18892 rhs
= &rstate
->lrd
[RHS(ins
, j
)->id
];
18894 if (state
->compiler
->debug
& DEBUG_COALESCING2
) {
18895 fprintf(state
->errout
, "coalesce rhs(%d): %p %d\n",
18896 j
, rhs
, rinfo
.reg
);
18899 if (rinfo
.reg
== linfo
.reg
) {
18900 coalesce_ranges(state
, rstate
,
18906 } while(ins
!= first
);
18909 static void graph_ins(
18910 struct compile_state
*state
,
18911 struct reg_block
*blocks
, struct triple_reg_set
*live
,
18912 struct reg_block
*rb
, struct triple
*ins
, void *arg
)
18914 struct reg_state
*rstate
= arg
;
18915 struct live_range
*def
;
18916 struct triple_reg_set
*entry
;
18918 /* If the triple is not a definition
18919 * we do not have a definition to add to
18920 * the interference graph.
18922 if (!triple_is_def(state
, ins
)) {
18925 def
= rstate
->lrd
[ins
->id
].lr
;
18927 /* Create an edge between ins and everything that is
18928 * alive, unless the live_range cannot share
18929 * a physical register with ins.
18931 for(entry
= live
; entry
; entry
= entry
->next
) {
18932 struct live_range
*lr
;
18933 if (entry
->member
->id
> rstate
->defs
) {
18934 internal_error(state
, 0, "bad entry?");
18936 lr
= rstate
->lrd
[entry
->member
->id
].lr
;
18940 if (!arch_regcm_intersect(def
->classes
, lr
->classes
)) {
18943 add_live_edge(rstate
, def
, lr
);
18948 #if DEBUG_CONSISTENCY > 1
18949 static struct live_range
*get_verify_live_range(
18950 struct compile_state
*state
, struct reg_state
*rstate
, struct triple
*ins
)
18952 struct live_range
*lr
;
18953 struct live_range_def
*lrd
;
18955 if ((ins
->id
< 0) || (ins
->id
> rstate
->defs
)) {
18956 internal_error(state
, ins
, "bad ins?");
18958 lr
= rstate
->lrd
[ins
->id
].lr
;
18962 if (lrd
->def
== ins
) {
18966 } while(lrd
!= lr
->defs
);
18968 internal_error(state
, ins
, "ins not in live range");
18973 static void verify_graph_ins(
18974 struct compile_state
*state
,
18975 struct reg_block
*blocks
, struct triple_reg_set
*live
,
18976 struct reg_block
*rb
, struct triple
*ins
, void *arg
)
18978 struct reg_state
*rstate
= arg
;
18979 struct triple_reg_set
*entry1
, *entry2
;
18982 /* Compare live against edges and make certain the code is working */
18983 for(entry1
= live
; entry1
; entry1
= entry1
->next
) {
18984 struct live_range
*lr1
;
18985 lr1
= get_verify_live_range(state
, rstate
, entry1
->member
);
18986 for(entry2
= live
; entry2
; entry2
= entry2
->next
) {
18987 struct live_range
*lr2
;
18988 struct live_range_edge
*edge2
;
18991 if (entry2
== entry1
) {
18994 lr2
= get_verify_live_range(state
, rstate
, entry2
->member
);
18996 internal_error(state
, entry2
->member
,
18997 "live range with 2 values simultaneously alive");
18999 if (!arch_regcm_intersect(lr1
->classes
, lr2
->classes
)) {
19002 if (!interfere(rstate
, lr1
, lr2
)) {
19003 internal_error(state
, entry2
->member
,
19004 "edges don't interfere?");
19009 for(edge2
= lr2
->edges
; edge2
; edge2
= edge2
->next
) {
19011 if (edge2
->node
== lr1
) {
19015 if (lr2_degree
!= lr2
->degree
) {
19016 internal_error(state
, entry2
->member
,
19017 "computed degree: %d does not match reported degree: %d\n",
19018 lr2_degree
, lr2
->degree
);
19021 internal_error(state
, entry2
->member
, "missing edge");
19029 static void print_interference_ins(
19030 struct compile_state
*state
,
19031 struct reg_block
*blocks
, struct triple_reg_set
*live
,
19032 struct reg_block
*rb
, struct triple
*ins
, void *arg
)
19034 struct reg_state
*rstate
= arg
;
19035 struct live_range
*lr
;
19037 FILE *fp
= state
->dbgout
;
19039 lr
= rstate
->lrd
[ins
->id
].lr
;
19041 ins
->id
= rstate
->lrd
[id
].orig_id
;
19042 SET_REG(ins
->id
, lr
->color
);
19043 display_triple(state
->dbgout
, ins
);
19047 struct live_range_def
*lrd
;
19048 fprintf(fp
, " range:");
19051 fprintf(fp
, " %-10p", lrd
->def
);
19053 } while(lrd
!= lr
->defs
);
19057 struct triple_reg_set
*entry
;
19058 fprintf(fp
, " live:");
19059 for(entry
= live
; entry
; entry
= entry
->next
) {
19060 fprintf(fp
, " %-10p", entry
->member
);
19065 struct live_range_edge
*entry
;
19066 fprintf(fp
, " edges:");
19067 for(entry
= lr
->edges
; entry
; entry
= entry
->next
) {
19068 struct live_range_def
*lrd
;
19069 lrd
= entry
->node
->defs
;
19071 fprintf(fp
, " %-10p", lrd
->def
);
19073 } while(lrd
!= entry
->node
->defs
);
19078 if (triple_is_branch(state
, ins
)) {
19084 static int coalesce_live_ranges(
19085 struct compile_state
*state
, struct reg_state
*rstate
)
19087 /* At the point where a value is moved from one
19088 * register to another that value requires two
19089 * registers, thus increasing register pressure.
19090 * Live range coaleescing reduces the register
19091 * pressure by keeping a value in one register
19094 * In the case of a phi function all paths leading
19095 * into it must be allocated to the same register
19096 * otherwise the phi function may not be removed.
19098 * Forcing a value to stay in a single register
19099 * for an extended period of time does have
19100 * limitations when applied to non homogenous
19103 * The two cases I have identified are:
19104 * 1) Two forced register assignments may
19106 * 2) Registers may go unused because they
19107 * are only good for storing the value
19108 * and not manipulating it.
19110 * Because of this I need to split live ranges,
19111 * even outside of the context of coalesced live
19112 * ranges. The need to split live ranges does
19113 * impose some constraints on live range coalescing.
19115 * - Live ranges may not be coalesced across phi
19116 * functions. This creates a 2 headed live
19117 * range that cannot be sanely split.
19119 * - phi functions (coalesced in initialize_live_ranges)
19120 * are handled as pre split live ranges so we will
19121 * never attempt to split them.
19127 for(i
= 0; i
<= rstate
->ranges
; i
++) {
19128 struct live_range
*lr1
;
19129 struct live_range_def
*lrd1
;
19130 lr1
= &rstate
->lr
[i
];
19134 lrd1
= live_range_end(state
, lr1
, 0);
19135 for(; lrd1
; lrd1
= live_range_end(state
, lr1
, lrd1
)) {
19136 struct triple_set
*set
;
19137 if (lrd1
->def
->op
!= OP_COPY
) {
19140 /* Skip copies that are the result of a live range split. */
19141 if (lrd1
->orig_id
& TRIPLE_FLAG_POST_SPLIT
) {
19144 for(set
= lrd1
->def
->use
; set
; set
= set
->next
) {
19145 struct live_range_def
*lrd2
;
19146 struct live_range
*lr2
, *res
;
19148 lrd2
= &rstate
->lrd
[set
->member
->id
];
19150 /* Don't coalesce with instructions
19151 * that are the result of a live range
19154 if (lrd2
->orig_id
& TRIPLE_FLAG_PRE_SPLIT
) {
19157 lr2
= rstate
->lrd
[set
->member
->id
].lr
;
19161 if ((lr1
->color
!= lr2
->color
) &&
19162 (lr1
->color
!= REG_UNSET
) &&
19163 (lr2
->color
!= REG_UNSET
)) {
19166 if ((lr1
->classes
& lr2
->classes
) == 0) {
19170 if (interfere(rstate
, lr1
, lr2
)) {
19174 res
= coalesce_ranges(state
, rstate
, lr1
, lr2
);
19188 static void fix_coalesce_conflicts(struct compile_state
*state
,
19189 struct reg_block
*blocks
, struct triple_reg_set
*live
,
19190 struct reg_block
*rb
, struct triple
*ins
, void *arg
)
19192 int *conflicts
= arg
;
19193 int zlhs
, zrhs
, i
, j
;
19195 /* See if we have a mandatory coalesce operation between
19196 * a lhs and a rhs value. If so and the rhs value is also
19197 * alive then this triple needs to be pre copied. Otherwise
19198 * we would have two definitions in the same live range simultaneously
19202 if ((zlhs
== 0) && triple_is_def(state
, ins
)) {
19206 for(i
= 0; i
< zlhs
; i
++) {
19207 struct reg_info linfo
;
19208 linfo
= arch_reg_lhs(state
, ins
, i
);
19209 if (linfo
.reg
< MAX_REGISTERS
) {
19212 for(j
= 0; j
< zrhs
; j
++) {
19213 struct reg_info rinfo
;
19214 struct triple
*rhs
;
19215 struct triple_reg_set
*set
;
19218 rinfo
= arch_reg_rhs(state
, ins
, j
);
19219 if (rinfo
.reg
!= linfo
.reg
) {
19223 for(set
= live
; set
&& !found
; set
= set
->next
) {
19224 if (set
->member
== rhs
) {
19229 struct triple
*copy
;
19230 copy
= pre_copy(state
, ins
, j
);
19231 copy
->id
|= TRIPLE_FLAG_PRE_SPLIT
;
19239 static int correct_coalesce_conflicts(
19240 struct compile_state
*state
, struct reg_block
*blocks
)
19244 walk_variable_lifetimes(state
, &state
->bb
, blocks
,
19245 fix_coalesce_conflicts
, &conflicts
);
19249 static void replace_set_use(struct compile_state
*state
,
19250 struct triple_reg_set
*head
, struct triple
*orig
, struct triple
*new)
19252 struct triple_reg_set
*set
;
19253 for(set
= head
; set
; set
= set
->next
) {
19254 if (set
->member
== orig
) {
19260 static void replace_block_use(struct compile_state
*state
,
19261 struct reg_block
*blocks
, struct triple
*orig
, struct triple
*new)
19264 #if DEBUG_ROMCC_WARNINGS
19265 #warning "WISHLIST visit just those blocks that need it *"
19267 for(i
= 1; i
<= state
->bb
.last_vertex
; i
++) {
19268 struct reg_block
*rb
;
19270 replace_set_use(state
, rb
->in
, orig
, new);
19271 replace_set_use(state
, rb
->out
, orig
, new);
19275 static void color_instructions(struct compile_state
*state
)
19277 struct triple
*ins
, *first
;
19278 first
= state
->first
;
19281 if (triple_is_def(state
, ins
)) {
19282 struct reg_info info
;
19283 info
= find_lhs_color(state
, ins
, 0);
19284 if (info
.reg
>= MAX_REGISTERS
) {
19285 info
.reg
= REG_UNSET
;
19287 SET_INFO(ins
->id
, info
);
19290 } while(ins
!= first
);
19293 static struct reg_info
read_lhs_color(
19294 struct compile_state
*state
, struct triple
*ins
, int index
)
19296 struct reg_info info
;
19297 if ((index
== 0) && triple_is_def(state
, ins
)) {
19298 info
.reg
= ID_REG(ins
->id
);
19299 info
.regcm
= ID_REGCM(ins
->id
);
19301 else if (index
< ins
->lhs
) {
19302 info
= read_lhs_color(state
, LHS(ins
, index
), 0);
19305 internal_error(state
, ins
, "Bad lhs %d", index
);
19306 info
.reg
= REG_UNSET
;
19312 static struct triple
*resolve_tangle(
19313 struct compile_state
*state
, struct triple
*tangle
)
19315 struct reg_info info
, uinfo
;
19316 struct triple_set
*set
, *next
;
19317 struct triple
*copy
;
19319 #if DEBUG_ROMCC_WARNINGS
19320 #warning "WISHLIST recalculate all affected instructions colors"
19322 info
= find_lhs_color(state
, tangle
, 0);
19323 for(set
= tangle
->use
; set
; set
= next
) {
19324 struct triple
*user
;
19327 user
= set
->member
;
19329 for(i
= 0; i
< zrhs
; i
++) {
19330 if (RHS(user
, i
) != tangle
) {
19333 uinfo
= find_rhs_post_color(state
, user
, i
);
19334 if (uinfo
.reg
== info
.reg
) {
19335 copy
= pre_copy(state
, user
, i
);
19336 copy
->id
|= TRIPLE_FLAG_PRE_SPLIT
;
19337 SET_INFO(copy
->id
, uinfo
);
19342 uinfo
= find_lhs_pre_color(state
, tangle
, 0);
19343 if (uinfo
.reg
== info
.reg
) {
19344 struct reg_info linfo
;
19345 copy
= post_copy(state
, tangle
);
19346 copy
->id
|= TRIPLE_FLAG_PRE_SPLIT
;
19347 linfo
= find_lhs_color(state
, copy
, 0);
19348 SET_INFO(copy
->id
, linfo
);
19350 info
= find_lhs_color(state
, tangle
, 0);
19351 SET_INFO(tangle
->id
, info
);
19357 static void fix_tangles(struct compile_state
*state
,
19358 struct reg_block
*blocks
, struct triple_reg_set
*live
,
19359 struct reg_block
*rb
, struct triple
*ins
, void *arg
)
19361 int *tangles
= arg
;
19362 struct triple
*tangle
;
19364 char used
[MAX_REGISTERS
];
19365 struct triple_reg_set
*set
;
19368 /* Find out which registers have multiple uses at this point */
19369 memset(used
, 0, sizeof(used
));
19370 for(set
= live
; set
; set
= set
->next
) {
19371 struct reg_info info
;
19372 info
= read_lhs_color(state
, set
->member
, 0);
19373 if (info
.reg
== REG_UNSET
) {
19376 reg_inc_used(state
, used
, info
.reg
);
19379 /* Now find the least dominated definition of a register in
19380 * conflict I have seen so far.
19382 for(set
= live
; set
; set
= set
->next
) {
19383 struct reg_info info
;
19384 info
= read_lhs_color(state
, set
->member
, 0);
19385 if (used
[info
.reg
] < 2) {
19388 /* Changing copies that feed into phi functions
19391 if (set
->member
->use
&&
19392 (set
->member
->use
->member
->op
== OP_PHI
)) {
19395 if (!tangle
|| tdominates(state
, set
->member
, tangle
)) {
19396 tangle
= set
->member
;
19399 /* If I have found a tangle resolve it */
19401 struct triple
*post_copy
;
19403 post_copy
= resolve_tangle(state
, tangle
);
19405 replace_block_use(state
, blocks
, tangle
, post_copy
);
19407 if (post_copy
&& (tangle
!= ins
)) {
19408 replace_set_use(state
, live
, tangle
, post_copy
);
19415 static int correct_tangles(
19416 struct compile_state
*state
, struct reg_block
*blocks
)
19420 color_instructions(state
);
19421 walk_variable_lifetimes(state
, &state
->bb
, blocks
,
19422 fix_tangles
, &tangles
);
19427 static void ids_from_rstate(struct compile_state
*state
, struct reg_state
*rstate
);
19428 static void cleanup_rstate(struct compile_state
*state
, struct reg_state
*rstate
);
19430 struct triple
*find_constrained_def(
19431 struct compile_state
*state
, struct live_range
*range
, struct triple
*constrained
)
19433 struct live_range_def
*lrd
, *lrd_next
;
19434 lrd_next
= range
->defs
;
19436 struct reg_info info
;
19440 lrd_next
= lrd
->next
;
19442 regcm
= arch_type_to_regcm(state
, lrd
->def
->type
);
19443 info
= find_lhs_color(state
, lrd
->def
, 0);
19444 regcm
= arch_regcm_reg_normalize(state
, regcm
);
19445 info
.regcm
= arch_regcm_reg_normalize(state
, info
.regcm
);
19446 /* If the 2 register class masks are equal then
19447 * the current register class is not constrained.
19449 if (regcm
== info
.regcm
) {
19453 /* If there is just one use.
19454 * That use cannot accept a larger register class.
19455 * There are no intervening definitions except
19456 * definitions that feed into that use.
19457 * Then a triple is not constrained.
19458 * FIXME handle this case!
19460 #if DEBUG_ROMCC_WARNINGS
19461 #warning "FIXME ignore cases that cannot be fixed (a definition followed by a use)"
19465 /* Of the constrained live ranges deal with the
19466 * least dominated one first.
19468 if (state
->compiler
->debug
& DEBUG_RANGE_CONFLICTS
) {
19469 fprintf(state
->errout
, "canidate: %p %-8s regcm: %x %x\n",
19470 lrd
->def
, tops(lrd
->def
->op
), regcm
, info
.regcm
);
19472 if (!constrained
||
19473 tdominates(state
, lrd
->def
, constrained
))
19475 constrained
= lrd
->def
;
19477 } while(lrd_next
!= range
->defs
);
19478 return constrained
;
19481 static int split_constrained_ranges(
19482 struct compile_state
*state
, struct reg_state
*rstate
,
19483 struct live_range
*range
)
19485 /* Walk through the edges in conflict and our current live
19486 * range, and find definitions that are more severly constrained
19487 * than they type of data they contain require.
19489 * Then pick one of those ranges and relax the constraints.
19491 struct live_range_edge
*edge
;
19492 struct triple
*constrained
;
19495 for(edge
= range
->edges
; edge
; edge
= edge
->next
) {
19496 constrained
= find_constrained_def(state
, edge
->node
, constrained
);
19498 #if DEBUG_ROMCC_WARNINGS
19499 #warning "FIXME should I call find_constrained_def here only if no previous constrained def was found?"
19501 if (!constrained
) {
19502 constrained
= find_constrained_def(state
, range
, constrained
);
19505 if (state
->compiler
->debug
& DEBUG_RANGE_CONFLICTS
) {
19506 fprintf(state
->errout
, "constrained: ");
19507 display_triple(state
->errout
, constrained
);
19510 ids_from_rstate(state
, rstate
);
19511 cleanup_rstate(state
, rstate
);
19512 resolve_tangle(state
, constrained
);
19514 return !!constrained
;
19517 static int split_ranges(
19518 struct compile_state
*state
, struct reg_state
*rstate
,
19519 char *used
, struct live_range
*range
)
19522 if (state
->compiler
->debug
& DEBUG_RANGE_CONFLICTS
) {
19523 fprintf(state
->errout
, "split_ranges %d %s %p\n",
19524 rstate
->passes
, tops(range
->defs
->def
->op
), range
->defs
->def
);
19526 if ((range
->color
== REG_UNNEEDED
) ||
19527 (rstate
->passes
>= rstate
->max_passes
)) {
19530 split
= split_constrained_ranges(state
, rstate
, range
);
19532 /* Ideally I would split the live range that will not be used
19533 * for the longest period of time in hopes that this will
19534 * (a) allow me to spill a register or
19535 * (b) allow me to place a value in another register.
19537 * So far I don't have a test case for this, the resolving
19538 * of mandatory constraints has solved all of my
19539 * know issues. So I have choosen not to write any
19540 * code until I cat get a better feel for cases where
19541 * it would be useful to have.
19544 #if DEBUG_ROMCC_WARNINGS
19545 #warning "WISHLIST implement live range splitting..."
19548 if (!split
&& (state
->compiler
->debug
& DEBUG_RANGE_CONFLICTS2
)) {
19549 FILE *fp
= state
->errout
;
19550 print_interference_blocks(state
, rstate
, fp
, 0);
19551 print_dominators(state
, fp
, &state
->bb
);
19556 static FILE *cgdebug_fp(struct compile_state
*state
)
19560 if (!fp
&& (state
->compiler
->debug
& DEBUG_COLOR_GRAPH2
)) {
19561 fp
= state
->errout
;
19563 if (!fp
&& (state
->compiler
->debug
& DEBUG_COLOR_GRAPH
)) {
19564 fp
= state
->dbgout
;
19569 static void cgdebug_printf(struct compile_state
*state
, const char *fmt
, ...)
19572 fp
= cgdebug_fp(state
);
19575 va_start(args
, fmt
);
19576 vfprintf(fp
, fmt
, args
);
19581 static void cgdebug_flush(struct compile_state
*state
)
19584 fp
= cgdebug_fp(state
);
19590 static void cgdebug_loc(struct compile_state
*state
, struct triple
*ins
)
19593 fp
= cgdebug_fp(state
);
19595 loc(fp
, state
, ins
);
19599 static int select_free_color(struct compile_state
*state
,
19600 struct reg_state
*rstate
, struct live_range
*range
)
19602 struct triple_set
*entry
;
19603 struct live_range_def
*lrd
;
19604 struct live_range_def
*phi
;
19605 struct live_range_edge
*edge
;
19606 char used
[MAX_REGISTERS
];
19607 struct triple
**expr
;
19609 /* Instead of doing just the trivial color select here I try
19610 * a few extra things because a good color selection will help reduce
19614 /* Find the registers currently in use */
19615 memset(used
, 0, sizeof(used
));
19616 for(edge
= range
->edges
; edge
; edge
= edge
->next
) {
19617 if (edge
->node
->color
== REG_UNSET
) {
19620 reg_fill_used(state
, used
, edge
->node
->color
);
19623 if (state
->compiler
->debug
& DEBUG_COLOR_GRAPH2
) {
19626 for(edge
= range
->edges
; edge
; edge
= edge
->next
) {
19629 cgdebug_printf(state
, "\n%s edges: %d",
19630 tops(range
->defs
->def
->op
), i
);
19631 cgdebug_loc(state
, range
->defs
->def
);
19632 cgdebug_printf(state
, "\n");
19633 for(i
= 0; i
< MAX_REGISTERS
; i
++) {
19635 cgdebug_printf(state
, "used: %s\n",
19641 /* If a color is already assigned see if it will work */
19642 if (range
->color
!= REG_UNSET
) {
19643 struct live_range_def
*lrd
;
19644 if (!used
[range
->color
]) {
19647 for(edge
= range
->edges
; edge
; edge
= edge
->next
) {
19648 if (edge
->node
->color
!= range
->color
) {
19651 warning(state
, edge
->node
->defs
->def
, "edge: ");
19652 lrd
= edge
->node
->defs
;
19654 warning(state
, lrd
->def
, " %p %s",
19655 lrd
->def
, tops(lrd
->def
->op
));
19657 } while(lrd
!= edge
->node
->defs
);
19660 warning(state
, range
->defs
->def
, "def: ");
19662 warning(state
, lrd
->def
, " %p %s",
19663 lrd
->def
, tops(lrd
->def
->op
));
19665 } while(lrd
!= range
->defs
);
19666 internal_error(state
, range
->defs
->def
,
19667 "live range with already used color %s",
19668 arch_reg_str(range
->color
));
19671 /* If I feed into an expression reuse it's color.
19672 * This should help remove copies in the case of 2 register instructions
19673 * and phi functions.
19676 lrd
= live_range_end(state
, range
, 0);
19677 for(; (range
->color
== REG_UNSET
) && lrd
; lrd
= live_range_end(state
, range
, lrd
)) {
19678 entry
= lrd
->def
->use
;
19679 for(;(range
->color
== REG_UNSET
) && entry
; entry
= entry
->next
) {
19680 struct live_range_def
*insd
;
19682 insd
= &rstate
->lrd
[entry
->member
->id
];
19683 if (insd
->lr
->defs
== 0) {
19686 if (!phi
&& (insd
->def
->op
== OP_PHI
) &&
19687 !interfere(rstate
, range
, insd
->lr
)) {
19690 if (insd
->lr
->color
== REG_UNSET
) {
19693 regcm
= insd
->lr
->classes
;
19694 if (((regcm
& range
->classes
) == 0) ||
19695 (used
[insd
->lr
->color
])) {
19698 if (interfere(rstate
, range
, insd
->lr
)) {
19701 range
->color
= insd
->lr
->color
;
19704 /* If I feed into a phi function reuse it's color or the color
19705 * of something else that feeds into the phi function.
19708 if (phi
->lr
->color
!= REG_UNSET
) {
19709 if (used
[phi
->lr
->color
]) {
19710 range
->color
= phi
->lr
->color
;
19714 expr
= triple_rhs(state
, phi
->def
, 0);
19715 for(; expr
; expr
= triple_rhs(state
, phi
->def
, expr
)) {
19716 struct live_range
*lr
;
19721 lr
= rstate
->lrd
[(*expr
)->id
].lr
;
19722 if (lr
->color
== REG_UNSET
) {
19725 regcm
= lr
->classes
;
19726 if (((regcm
& range
->classes
) == 0) ||
19727 (used
[lr
->color
])) {
19730 if (interfere(rstate
, range
, lr
)) {
19733 range
->color
= lr
->color
;
19737 /* If I don't interfere with a rhs node reuse it's color */
19738 lrd
= live_range_head(state
, range
, 0);
19739 for(; (range
->color
== REG_UNSET
) && lrd
; lrd
= live_range_head(state
, range
, lrd
)) {
19740 expr
= triple_rhs(state
, lrd
->def
, 0);
19741 for(; expr
; expr
= triple_rhs(state
, lrd
->def
, expr
)) {
19742 struct live_range
*lr
;
19747 lr
= rstate
->lrd
[(*expr
)->id
].lr
;
19748 if (lr
->color
== REG_UNSET
) {
19751 regcm
= lr
->classes
;
19752 if (((regcm
& range
->classes
) == 0) ||
19753 (used
[lr
->color
])) {
19756 if (interfere(rstate
, range
, lr
)) {
19759 range
->color
= lr
->color
;
19763 /* If I have not opportunitically picked a useful color
19764 * pick the first color that is free.
19766 if (range
->color
== REG_UNSET
) {
19768 arch_select_free_register(state
, used
, range
->classes
);
19770 if (range
->color
== REG_UNSET
) {
19771 struct live_range_def
*lrd
;
19773 if (split_ranges(state
, rstate
, used
, range
)) {
19776 for(edge
= range
->edges
; edge
; edge
= edge
->next
) {
19777 warning(state
, edge
->node
->defs
->def
, "edge reg %s",
19778 arch_reg_str(edge
->node
->color
));
19779 lrd
= edge
->node
->defs
;
19781 warning(state
, lrd
->def
, " %s %p",
19782 tops(lrd
->def
->op
), lrd
->def
);
19784 } while(lrd
!= edge
->node
->defs
);
19786 warning(state
, range
->defs
->def
, "range: ");
19789 warning(state
, lrd
->def
, " %s %p",
19790 tops(lrd
->def
->op
), lrd
->def
);
19792 } while(lrd
!= range
->defs
);
19794 warning(state
, range
->defs
->def
, "classes: %x",
19796 for(i
= 0; i
< MAX_REGISTERS
; i
++) {
19798 warning(state
, range
->defs
->def
, "used: %s",
19802 error(state
, range
->defs
->def
, "too few registers");
19804 range
->classes
&= arch_reg_regcm(state
, range
->color
);
19805 if ((range
->color
== REG_UNSET
) || (range
->classes
== 0)) {
19806 internal_error(state
, range
->defs
->def
, "select_free_color did not?");
19811 static int color_graph(struct compile_state
*state
, struct reg_state
*rstate
)
19814 struct live_range_edge
*edge
;
19815 struct live_range
*range
;
19817 cgdebug_printf(state
, "Lo: ");
19818 range
= rstate
->low
;
19819 if (*range
->group_prev
!= range
) {
19820 internal_error(state
, 0, "lo: *prev != range?");
19822 *range
->group_prev
= range
->group_next
;
19823 if (range
->group_next
) {
19824 range
->group_next
->group_prev
= range
->group_prev
;
19826 if (&range
->group_next
== rstate
->low_tail
) {
19827 rstate
->low_tail
= range
->group_prev
;
19829 if (rstate
->low
== range
) {
19830 internal_error(state
, 0, "low: next != prev?");
19833 else if (rstate
->high
) {
19834 cgdebug_printf(state
, "Hi: ");
19835 range
= rstate
->high
;
19836 if (*range
->group_prev
!= range
) {
19837 internal_error(state
, 0, "hi: *prev != range?");
19839 *range
->group_prev
= range
->group_next
;
19840 if (range
->group_next
) {
19841 range
->group_next
->group_prev
= range
->group_prev
;
19843 if (&range
->group_next
== rstate
->high_tail
) {
19844 rstate
->high_tail
= range
->group_prev
;
19846 if (rstate
->high
== range
) {
19847 internal_error(state
, 0, "high: next != prev?");
19853 cgdebug_printf(state
, " %d\n", range
- rstate
->lr
);
19854 range
->group_prev
= 0;
19855 for(edge
= range
->edges
; edge
; edge
= edge
->next
) {
19856 struct live_range
*node
;
19858 /* Move nodes from the high to the low list */
19859 if (node
->group_prev
&& (node
->color
== REG_UNSET
) &&
19860 (node
->degree
== regc_max_size(state
, node
->classes
))) {
19861 if (*node
->group_prev
!= node
) {
19862 internal_error(state
, 0, "move: *prev != node?");
19864 *node
->group_prev
= node
->group_next
;
19865 if (node
->group_next
) {
19866 node
->group_next
->group_prev
= node
->group_prev
;
19868 if (&node
->group_next
== rstate
->high_tail
) {
19869 rstate
->high_tail
= node
->group_prev
;
19871 cgdebug_printf(state
, "Moving...%d to low\n", node
- rstate
->lr
);
19872 node
->group_prev
= rstate
->low_tail
;
19873 node
->group_next
= 0;
19874 *rstate
->low_tail
= node
;
19875 rstate
->low_tail
= &node
->group_next
;
19876 if (*node
->group_prev
!= node
) {
19877 internal_error(state
, 0, "move2: *prev != node?");
19882 colored
= color_graph(state
, rstate
);
19884 cgdebug_printf(state
, "Coloring %d @", range
- rstate
->lr
);
19885 cgdebug_loc(state
, range
->defs
->def
);
19886 cgdebug_flush(state
);
19887 colored
= select_free_color(state
, rstate
, range
);
19889 cgdebug_printf(state
, " %s\n", arch_reg_str(range
->color
));
19895 static void verify_colors(struct compile_state
*state
, struct reg_state
*rstate
)
19897 struct live_range
*lr
;
19898 struct live_range_edge
*edge
;
19899 struct triple
*ins
, *first
;
19900 char used
[MAX_REGISTERS
];
19901 first
= state
->first
;
19904 if (triple_is_def(state
, ins
)) {
19905 if (ins
->id
> rstate
->defs
) {
19906 internal_error(state
, ins
,
19907 "triple without a live range def");
19909 lr
= rstate
->lrd
[ins
->id
].lr
;
19910 if (lr
->color
== REG_UNSET
) {
19911 internal_error(state
, ins
,
19912 "triple without a color");
19914 /* Find the registers used by the edges */
19915 memset(used
, 0, sizeof(used
));
19916 for(edge
= lr
->edges
; edge
; edge
= edge
->next
) {
19917 if (edge
->node
->color
== REG_UNSET
) {
19918 internal_error(state
, 0,
19919 "live range without a color");
19921 reg_fill_used(state
, used
, edge
->node
->color
);
19923 if (used
[lr
->color
]) {
19924 internal_error(state
, ins
,
19925 "triple with already used color");
19929 } while(ins
!= first
);
19932 static void color_triples(struct compile_state
*state
, struct reg_state
*rstate
)
19934 struct live_range_def
*lrd
;
19935 struct live_range
*lr
;
19936 struct triple
*first
, *ins
;
19937 first
= state
->first
;
19940 if (ins
->id
> rstate
->defs
) {
19941 internal_error(state
, ins
,
19942 "triple without a live range");
19944 lrd
= &rstate
->lrd
[ins
->id
];
19946 ins
->id
= lrd
->orig_id
;
19947 SET_REG(ins
->id
, lr
->color
);
19949 } while (ins
!= first
);
19952 static struct live_range
*merge_sort_lr(
19953 struct live_range
*first
, struct live_range
*last
)
19955 struct live_range
*mid
, *join
, **join_tail
, *pick
;
19957 size
= (last
- first
) + 1;
19959 mid
= first
+ size
/2;
19960 first
= merge_sort_lr(first
, mid
-1);
19961 mid
= merge_sort_lr(mid
, last
);
19965 /* merge the two lists */
19966 while(first
&& mid
) {
19967 if ((first
->degree
< mid
->degree
) ||
19968 ((first
->degree
== mid
->degree
) &&
19969 (first
->length
< mid
->length
))) {
19971 first
= first
->group_next
;
19973 first
->group_prev
= 0;
19978 mid
= mid
->group_next
;
19980 mid
->group_prev
= 0;
19983 pick
->group_next
= 0;
19984 pick
->group_prev
= join_tail
;
19986 join_tail
= &pick
->group_next
;
19988 /* Splice the remaining list */
19989 pick
= (first
)? first
: mid
;
19992 pick
->group_prev
= join_tail
;
19996 if (!first
->defs
) {
20004 static void ids_from_rstate(struct compile_state
*state
,
20005 struct reg_state
*rstate
)
20007 struct triple
*ins
, *first
;
20008 if (!rstate
->defs
) {
20011 /* Display the graph if desired */
20012 if (state
->compiler
->debug
& DEBUG_INTERFERENCE
) {
20013 FILE *fp
= state
->dbgout
;
20014 print_interference_blocks(state
, rstate
, fp
, 0);
20015 print_control_flow(state
, fp
, &state
->bb
);
20018 first
= state
->first
;
20022 struct live_range_def
*lrd
;
20023 lrd
= &rstate
->lrd
[ins
->id
];
20024 ins
->id
= lrd
->orig_id
;
20027 } while(ins
!= first
);
20030 static void cleanup_live_edges(struct reg_state
*rstate
)
20033 /* Free the edges on each node */
20034 for(i
= 1; i
<= rstate
->ranges
; i
++) {
20035 remove_live_edges(rstate
, &rstate
->lr
[i
]);
20039 static void cleanup_rstate(struct compile_state
*state
, struct reg_state
*rstate
)
20041 cleanup_live_edges(rstate
);
20042 xfree(rstate
->lrd
);
20045 /* Free the variable lifetime information */
20046 if (rstate
->blocks
) {
20047 free_variable_lifetimes(state
, &state
->bb
, rstate
->blocks
);
20050 rstate
->ranges
= 0;
20053 rstate
->blocks
= 0;
20056 static void verify_consistency(struct compile_state
*state
);
20057 static void allocate_registers(struct compile_state
*state
)
20059 struct reg_state rstate
;
20062 /* Clear out the reg_state */
20063 memset(&rstate
, 0, sizeof(rstate
));
20064 rstate
.max_passes
= state
->compiler
->max_allocation_passes
;
20067 struct live_range
**point
, **next
;
20071 if (state
->compiler
->debug
& DEBUG_RANGE_CONFLICTS
) {
20072 FILE *fp
= state
->errout
;
20073 fprintf(fp
, "pass: %d\n", rstate
.passes
);
20078 ids_from_rstate(state
, &rstate
);
20080 /* Cleanup the temporary data structures */
20081 cleanup_rstate(state
, &rstate
);
20083 /* Compute the variable lifetimes */
20084 rstate
.blocks
= compute_variable_lifetimes(state
, &state
->bb
);
20086 /* Fix invalid mandatory live range coalesce conflicts */
20087 correct_coalesce_conflicts(state
, rstate
.blocks
);
20089 /* Fix two simultaneous uses of the same register.
20090 * In a few pathlogical cases a partial untangle moves
20091 * the tangle to a part of the graph we won't revisit.
20092 * So we keep looping until we have no more tangle fixes
20096 tangles
= correct_tangles(state
, rstate
.blocks
);
20100 print_blocks(state
, "resolve_tangles", state
->dbgout
);
20101 verify_consistency(state
);
20103 /* Allocate and initialize the live ranges */
20104 initialize_live_ranges(state
, &rstate
);
20106 /* Note currently doing coalescing in a loop appears to
20107 * buys me nothing. The code is left this way in case
20108 * there is some value in it. Or if a future bugfix
20109 * yields some benefit.
20112 if (state
->compiler
->debug
& DEBUG_COALESCING
) {
20113 fprintf(state
->errout
, "coalescing\n");
20116 /* Remove any previous live edge calculations */
20117 cleanup_live_edges(&rstate
);
20119 /* Compute the interference graph */
20120 walk_variable_lifetimes(
20121 state
, &state
->bb
, rstate
.blocks
,
20122 graph_ins
, &rstate
);
20124 /* Display the interference graph if desired */
20125 if (state
->compiler
->debug
& DEBUG_INTERFERENCE
) {
20126 print_interference_blocks(state
, &rstate
, state
->dbgout
, 1);
20127 fprintf(state
->dbgout
, "\nlive variables by instruction\n");
20128 walk_variable_lifetimes(
20129 state
, &state
->bb
, rstate
.blocks
,
20130 print_interference_ins
, &rstate
);
20133 coalesced
= coalesce_live_ranges(state
, &rstate
);
20135 if (state
->compiler
->debug
& DEBUG_COALESCING
) {
20136 fprintf(state
->errout
, "coalesced: %d\n", coalesced
);
20138 } while(coalesced
);
20140 #if DEBUG_CONSISTENCY > 1
20142 fprintf(state
->errout
, "verify_graph_ins...\n");
20144 /* Verify the interference graph */
20145 walk_variable_lifetimes(
20146 state
, &state
->bb
, rstate
.blocks
,
20147 verify_graph_ins
, &rstate
);
20149 fprintf(state
->errout
, "verify_graph_ins done\n");
20153 /* Build the groups low and high. But with the nodes
20154 * first sorted by degree order.
20156 rstate
.low_tail
= &rstate
.low
;
20157 rstate
.high_tail
= &rstate
.high
;
20158 rstate
.high
= merge_sort_lr(&rstate
.lr
[1], &rstate
.lr
[rstate
.ranges
]);
20160 rstate
.high
->group_prev
= &rstate
.high
;
20162 for(point
= &rstate
.high
; *point
; point
= &(*point
)->group_next
)
20164 rstate
.high_tail
= point
;
20165 /* Walk through the high list and move everything that needs
20168 for(point
= &rstate
.high
; *point
; point
= next
) {
20169 struct live_range
*range
;
20170 next
= &(*point
)->group_next
;
20173 /* If it has a low degree or it already has a color
20174 * place the node in low.
20176 if ((range
->degree
< regc_max_size(state
, range
->classes
)) ||
20177 (range
->color
!= REG_UNSET
)) {
20178 cgdebug_printf(state
, "Lo: %5d degree %5d%s\n",
20179 range
- rstate
.lr
, range
->degree
,
20180 (range
->color
!= REG_UNSET
) ? " (colored)": "");
20181 *range
->group_prev
= range
->group_next
;
20182 if (range
->group_next
) {
20183 range
->group_next
->group_prev
= range
->group_prev
;
20185 if (&range
->group_next
== rstate
.high_tail
) {
20186 rstate
.high_tail
= range
->group_prev
;
20188 range
->group_prev
= rstate
.low_tail
;
20189 range
->group_next
= 0;
20190 *rstate
.low_tail
= range
;
20191 rstate
.low_tail
= &range
->group_next
;
20195 cgdebug_printf(state
, "hi: %5d degree %5d%s\n",
20196 range
- rstate
.lr
, range
->degree
,
20197 (range
->color
!= REG_UNSET
) ? " (colored)": "");
20200 /* Color the live_ranges */
20201 colored
= color_graph(state
, &rstate
);
20203 } while (!colored
);
20205 /* Verify the graph was properly colored */
20206 verify_colors(state
, &rstate
);
20208 /* Move the colors from the graph to the triples */
20209 color_triples(state
, &rstate
);
20211 /* Cleanup the temporary data structures */
20212 cleanup_rstate(state
, &rstate
);
20214 /* Display the new graph */
20215 print_blocks(state
, __func__
, state
->dbgout
);
20218 /* Sparce Conditional Constant Propogation
20219 * =========================================
20223 struct lattice_node
{
20225 struct triple
*def
;
20226 struct ssa_edge
*out
;
20227 struct flow_block
*fblock
;
20228 struct triple
*val
;
20229 /* lattice high val == def
20230 * lattice const is_const(val)
20231 * lattice low other
20235 struct lattice_node
*src
;
20236 struct lattice_node
*dst
;
20237 struct ssa_edge
*work_next
;
20238 struct ssa_edge
*work_prev
;
20239 struct ssa_edge
*out_next
;
20242 struct flow_block
*src
;
20243 struct flow_block
*dst
;
20244 struct flow_edge
*work_next
;
20245 struct flow_edge
*work_prev
;
20246 struct flow_edge
*in_next
;
20247 struct flow_edge
*out_next
;
20250 #define MAX_FLOW_BLOCK_EDGES 3
20251 struct flow_block
{
20252 struct block
*block
;
20253 struct flow_edge
*in
;
20254 struct flow_edge
*out
;
20255 struct flow_edge
*edges
;
20260 struct lattice_node
*lattice
;
20261 struct ssa_edge
*ssa_edges
;
20262 struct flow_block
*flow_blocks
;
20263 struct flow_edge
*flow_work_list
;
20264 struct ssa_edge
*ssa_work_list
;
20268 static int is_scc_const(struct compile_state
*state
, struct triple
*ins
)
20270 return ins
&& (triple_is_ubranch(state
, ins
) || is_const(ins
));
20273 static int is_lattice_hi(struct compile_state
*state
, struct lattice_node
*lnode
)
20275 return !is_scc_const(state
, lnode
->val
) && (lnode
->val
== lnode
->def
);
20278 static int is_lattice_const(struct compile_state
*state
, struct lattice_node
*lnode
)
20280 return is_scc_const(state
, lnode
->val
);
20283 static int is_lattice_lo(struct compile_state
*state
, struct lattice_node
*lnode
)
20285 return (lnode
->val
!= lnode
->def
) && !is_scc_const(state
, lnode
->val
);
20288 static void scc_add_fedge(struct compile_state
*state
, struct scc_state
*scc
,
20289 struct flow_edge
*fedge
)
20291 if (state
->compiler
->debug
& DEBUG_SCC_TRANSFORM2
) {
20292 fprintf(state
->errout
, "adding fedge: %p (%4d -> %5d)\n",
20294 fedge
->src
->block
?fedge
->src
->block
->last
->id
: 0,
20295 fedge
->dst
->block
?fedge
->dst
->block
->first
->id
: 0);
20297 if ((fedge
== scc
->flow_work_list
) ||
20298 (fedge
->work_next
!= fedge
) ||
20299 (fedge
->work_prev
!= fedge
)) {
20301 if (state
->compiler
->debug
& DEBUG_SCC_TRANSFORM2
) {
20302 fprintf(state
->errout
, "dupped fedge: %p\n",
20307 if (!scc
->flow_work_list
) {
20308 scc
->flow_work_list
= fedge
;
20309 fedge
->work_next
= fedge
->work_prev
= fedge
;
20312 struct flow_edge
*ftail
;
20313 ftail
= scc
->flow_work_list
->work_prev
;
20314 fedge
->work_next
= ftail
->work_next
;
20315 fedge
->work_prev
= ftail
;
20316 fedge
->work_next
->work_prev
= fedge
;
20317 fedge
->work_prev
->work_next
= fedge
;
20321 static struct flow_edge
*scc_next_fedge(
20322 struct compile_state
*state
, struct scc_state
*scc
)
20324 struct flow_edge
*fedge
;
20325 fedge
= scc
->flow_work_list
;
20327 fedge
->work_next
->work_prev
= fedge
->work_prev
;
20328 fedge
->work_prev
->work_next
= fedge
->work_next
;
20329 if (fedge
->work_next
!= fedge
) {
20330 scc
->flow_work_list
= fedge
->work_next
;
20332 scc
->flow_work_list
= 0;
20334 fedge
->work_next
= fedge
->work_prev
= fedge
;
20339 static void scc_add_sedge(struct compile_state
*state
, struct scc_state
*scc
,
20340 struct ssa_edge
*sedge
)
20342 if (state
->compiler
->debug
& DEBUG_SCC_TRANSFORM2
) {
20343 fprintf(state
->errout
, "adding sedge: %5ld (%4d -> %5d)\n",
20344 (long)(sedge
- scc
->ssa_edges
),
20345 sedge
->src
->def
->id
,
20346 sedge
->dst
->def
->id
);
20348 if ((sedge
== scc
->ssa_work_list
) ||
20349 (sedge
->work_next
!= sedge
) ||
20350 (sedge
->work_prev
!= sedge
)) {
20352 if (state
->compiler
->debug
& DEBUG_SCC_TRANSFORM2
) {
20353 fprintf(state
->errout
, "dupped sedge: %5ld\n",
20354 (long)(sedge
- scc
->ssa_edges
));
20358 if (!scc
->ssa_work_list
) {
20359 scc
->ssa_work_list
= sedge
;
20360 sedge
->work_next
= sedge
->work_prev
= sedge
;
20363 struct ssa_edge
*stail
;
20364 stail
= scc
->ssa_work_list
->work_prev
;
20365 sedge
->work_next
= stail
->work_next
;
20366 sedge
->work_prev
= stail
;
20367 sedge
->work_next
->work_prev
= sedge
;
20368 sedge
->work_prev
->work_next
= sedge
;
20372 static struct ssa_edge
*scc_next_sedge(
20373 struct compile_state
*state
, struct scc_state
*scc
)
20375 struct ssa_edge
*sedge
;
20376 sedge
= scc
->ssa_work_list
;
20378 sedge
->work_next
->work_prev
= sedge
->work_prev
;
20379 sedge
->work_prev
->work_next
= sedge
->work_next
;
20380 if (sedge
->work_next
!= sedge
) {
20381 scc
->ssa_work_list
= sedge
->work_next
;
20383 scc
->ssa_work_list
= 0;
20385 sedge
->work_next
= sedge
->work_prev
= sedge
;
20390 static void initialize_scc_state(
20391 struct compile_state
*state
, struct scc_state
*scc
)
20393 int ins_count
, ssa_edge_count
;
20394 int ins_index
, ssa_edge_index
, fblock_index
;
20395 struct triple
*first
, *ins
;
20396 struct block
*block
;
20397 struct flow_block
*fblock
;
20399 memset(scc
, 0, sizeof(*scc
));
20401 /* Inialize pass zero find out how much memory we need */
20402 first
= state
->first
;
20404 ins_count
= ssa_edge_count
= 0;
20406 struct triple_set
*edge
;
20408 for(edge
= ins
->use
; edge
; edge
= edge
->next
) {
20412 } while(ins
!= first
);
20413 if (state
->compiler
->debug
& DEBUG_SCC_TRANSFORM
) {
20414 fprintf(state
->errout
, "ins_count: %d ssa_edge_count: %d vertex_count: %d\n",
20415 ins_count
, ssa_edge_count
, state
->bb
.last_vertex
);
20417 scc
->ins_count
= ins_count
;
20419 xcmalloc(sizeof(*scc
->lattice
)*(ins_count
+ 1), "lattice");
20421 xcmalloc(sizeof(*scc
->ssa_edges
)*(ssa_edge_count
+ 1), "ssa_edges");
20423 xcmalloc(sizeof(*scc
->flow_blocks
)*(state
->bb
.last_vertex
+ 1),
20426 /* Initialize pass one collect up the nodes */
20429 ins_index
= ssa_edge_index
= fblock_index
= 0;
20432 if ((ins
->op
== OP_LABEL
) && (block
!= ins
->u
.block
)) {
20433 block
= ins
->u
.block
;
20435 internal_error(state
, ins
, "label without block");
20438 block
->vertex
= fblock_index
;
20439 fblock
= &scc
->flow_blocks
[fblock_index
];
20440 fblock
->block
= block
;
20441 fblock
->edges
= xcmalloc(sizeof(*fblock
->edges
)*block
->edge_count
,
20445 struct lattice_node
*lnode
;
20447 lnode
= &scc
->lattice
[ins_index
];
20450 lnode
->fblock
= fblock
;
20451 lnode
->val
= ins
; /* LATTICE HIGH */
20452 if (lnode
->val
->op
== OP_UNKNOWNVAL
) {
20453 lnode
->val
= 0; /* LATTICE LOW by definition */
20455 lnode
->old_id
= ins
->id
;
20456 ins
->id
= ins_index
;
20459 } while(ins
!= first
);
20460 /* Initialize pass two collect up the edges */
20466 struct triple_set
*edge
;
20467 struct ssa_edge
**stail
;
20468 struct lattice_node
*lnode
;
20469 lnode
= &scc
->lattice
[ins
->id
];
20471 stail
= &lnode
->out
;
20472 for(edge
= ins
->use
; edge
; edge
= edge
->next
) {
20473 struct ssa_edge
*sedge
;
20474 ssa_edge_index
+= 1;
20475 sedge
= &scc
->ssa_edges
[ssa_edge_index
];
20477 stail
= &sedge
->out_next
;
20478 sedge
->src
= lnode
;
20479 sedge
->dst
= &scc
->lattice
[edge
->member
->id
];
20480 sedge
->work_next
= sedge
->work_prev
= sedge
;
20481 sedge
->out_next
= 0;
20484 if ((ins
->op
== OP_LABEL
) && (block
!= ins
->u
.block
)) {
20485 struct flow_edge
*fedge
, **ftail
;
20486 struct block_set
*bedge
;
20487 block
= ins
->u
.block
;
20488 fblock
= &scc
->flow_blocks
[block
->vertex
];
20491 ftail
= &fblock
->out
;
20493 fedge
= fblock
->edges
;
20494 bedge
= block
->edges
;
20495 for(; bedge
; bedge
= bedge
->next
, fedge
++) {
20496 fedge
->dst
= &scc
->flow_blocks
[bedge
->member
->vertex
];
20497 if (fedge
->dst
->block
!= bedge
->member
) {
20498 internal_error(state
, 0, "block mismatch");
20501 ftail
= &fedge
->out_next
;
20502 fedge
->out_next
= 0;
20504 for(fedge
= fblock
->out
; fedge
; fedge
= fedge
->out_next
) {
20505 fedge
->src
= fblock
;
20506 fedge
->work_next
= fedge
->work_prev
= fedge
;
20507 fedge
->executable
= 0;
20511 } while (ins
!= first
);
20516 if ((ins
->op
== OP_LABEL
) && (block
!= ins
->u
.block
)) {
20517 struct flow_edge
**ftail
;
20518 struct block_set
*bedge
;
20519 block
= ins
->u
.block
;
20520 fblock
= &scc
->flow_blocks
[block
->vertex
];
20521 ftail
= &fblock
->in
;
20522 for(bedge
= block
->use
; bedge
; bedge
= bedge
->next
) {
20523 struct block
*src_block
;
20524 struct flow_block
*sfblock
;
20525 struct flow_edge
*sfedge
;
20526 src_block
= bedge
->member
;
20527 sfblock
= &scc
->flow_blocks
[src_block
->vertex
];
20528 for(sfedge
= sfblock
->out
; sfedge
; sfedge
= sfedge
->out_next
) {
20529 if (sfedge
->dst
== fblock
) {
20534 internal_error(state
, 0, "edge mismatch");
20537 ftail
= &sfedge
->in_next
;
20538 sfedge
->in_next
= 0;
20542 } while(ins
!= first
);
20543 /* Setup a dummy block 0 as a node above the start node */
20545 struct flow_block
*fblock
, *dst
;
20546 struct flow_edge
*fedge
;
20547 fblock
= &scc
->flow_blocks
[0];
20549 fblock
->edges
= xcmalloc(sizeof(*fblock
->edges
)*1, "flow_edges");
20551 fblock
->out
= fblock
->edges
;
20552 dst
= &scc
->flow_blocks
[state
->bb
.first_block
->vertex
];
20553 fedge
= fblock
->edges
;
20554 fedge
->src
= fblock
;
20556 fedge
->work_next
= fedge
;
20557 fedge
->work_prev
= fedge
;
20558 fedge
->in_next
= fedge
->dst
->in
;
20559 fedge
->out_next
= 0;
20560 fedge
->executable
= 0;
20561 fedge
->dst
->in
= fedge
;
20563 /* Initialize the work lists */
20564 scc
->flow_work_list
= 0;
20565 scc
->ssa_work_list
= 0;
20566 scc_add_fedge(state
, scc
, fedge
);
20568 if (state
->compiler
->debug
& DEBUG_SCC_TRANSFORM
) {
20569 fprintf(state
->errout
, "ins_index: %d ssa_edge_index: %d fblock_index: %d\n",
20570 ins_index
, ssa_edge_index
, fblock_index
);
20575 static void free_scc_state(
20576 struct compile_state
*state
, struct scc_state
*scc
)
20579 for(i
= 0; i
< state
->bb
.last_vertex
+ 1; i
++) {
20580 struct flow_block
*fblock
;
20581 fblock
= &scc
->flow_blocks
[i
];
20582 if (fblock
->edges
) {
20583 xfree(fblock
->edges
);
20587 xfree(scc
->flow_blocks
);
20588 xfree(scc
->ssa_edges
);
20589 xfree(scc
->lattice
);
20593 static struct lattice_node
*triple_to_lattice(
20594 struct compile_state
*state
, struct scc_state
*scc
, struct triple
*ins
)
20596 if (ins
->id
<= 0) {
20597 internal_error(state
, ins
, "bad id");
20599 return &scc
->lattice
[ins
->id
];
20602 static struct triple
*preserve_lval(
20603 struct compile_state
*state
, struct lattice_node
*lnode
)
20605 struct triple
*old
;
20606 /* Preserve the original value */
20608 old
= dup_triple(state
, lnode
->val
);
20609 if (lnode
->val
!= lnode
->def
) {
20619 static int lval_changed(struct compile_state
*state
,
20620 struct triple
*old
, struct lattice_node
*lnode
)
20623 /* See if the lattice value has changed */
20625 if (!old
&& !lnode
->val
) {
20629 lnode
->val
&& old
&&
20630 (memcmp(lnode
->val
->param
, old
->param
,
20631 TRIPLE_SIZE(lnode
->val
) * sizeof(lnode
->val
->param
[0])) == 0) &&
20632 (memcmp(&lnode
->val
->u
, &old
->u
, sizeof(old
->u
)) == 0)) {
20642 static void scc_debug_lnode(
20643 struct compile_state
*state
, struct scc_state
*scc
,
20644 struct lattice_node
*lnode
, int changed
)
20646 if ((state
->compiler
->debug
& DEBUG_SCC_TRANSFORM2
) && lnode
->val
) {
20647 display_triple_changes(state
->errout
, lnode
->val
, lnode
->def
);
20649 if (state
->compiler
->debug
& DEBUG_SCC_TRANSFORM
) {
20650 FILE *fp
= state
->errout
;
20651 struct triple
*val
, **expr
;
20652 val
= lnode
->val
? lnode
->val
: lnode
->def
;
20653 fprintf(fp
, "%p %s %3d %10s (",
20655 ((lnode
->def
->op
== OP_PHI
)? "phi: ": "expr:"),
20657 tops(lnode
->def
->op
));
20658 expr
= triple_rhs(state
, lnode
->def
, 0);
20659 for(;expr
;expr
= triple_rhs(state
, lnode
->def
, expr
)) {
20661 fprintf(fp
, " %d", (*expr
)->id
);
20664 if (val
->op
== OP_INTCONST
) {
20665 fprintf(fp
, " <0x%08lx>", (unsigned long)(val
->u
.cval
));
20667 fprintf(fp
, " ) -> %s %s\n",
20668 (is_lattice_hi(state
, lnode
)? "hi":
20669 is_lattice_const(state
, lnode
)? "const" : "lo"),
20670 changed
? "changed" : ""
20675 static int compute_lnode_val(struct compile_state
*state
, struct scc_state
*scc
,
20676 struct lattice_node
*lnode
)
20679 struct triple
*old
, *scratch
;
20680 struct triple
**dexpr
, **vexpr
;
20683 /* Store the original value */
20684 old
= preserve_lval(state
, lnode
);
20686 /* Reinitialize the value */
20687 lnode
->val
= scratch
= dup_triple(state
, lnode
->def
);
20688 scratch
->id
= lnode
->old_id
;
20689 scratch
->next
= scratch
;
20690 scratch
->prev
= scratch
;
20693 count
= TRIPLE_SIZE(scratch
);
20694 for(i
= 0; i
< count
; i
++) {
20695 dexpr
= &lnode
->def
->param
[i
];
20696 vexpr
= &scratch
->param
[i
];
20698 if (((i
< TRIPLE_MISC_OFF(scratch
)) ||
20699 (i
>= TRIPLE_TARG_OFF(scratch
))) &&
20701 struct lattice_node
*tmp
;
20702 tmp
= triple_to_lattice(state
, scc
, *dexpr
);
20703 *vexpr
= (tmp
->val
)? tmp
->val
: tmp
->def
;
20706 if (triple_is_branch(state
, scratch
)) {
20707 scratch
->next
= lnode
->def
->next
;
20709 /* Recompute the value */
20710 #if DEBUG_ROMCC_WARNINGS
20711 #warning "FIXME see if simplify does anything bad"
20713 /* So far it looks like only the strength reduction
20714 * optimization are things I need to worry about.
20716 simplify(state
, scratch
);
20717 /* Cleanup my value */
20718 if (scratch
->use
) {
20719 internal_error(state
, lnode
->def
, "scratch used?");
20721 if ((scratch
->prev
!= scratch
) ||
20722 ((scratch
->next
!= scratch
) &&
20723 (!triple_is_branch(state
, lnode
->def
) ||
20724 (scratch
->next
!= lnode
->def
->next
)))) {
20725 internal_error(state
, lnode
->def
, "scratch in list?");
20727 /* undo any uses... */
20728 count
= TRIPLE_SIZE(scratch
);
20729 for(i
= 0; i
< count
; i
++) {
20730 vexpr
= &scratch
->param
[i
];
20732 unuse_triple(*vexpr
, scratch
);
20735 if (lnode
->val
->op
== OP_UNKNOWNVAL
) {
20736 lnode
->val
= 0; /* Lattice low by definition */
20738 /* Find the case when I am lattice high */
20740 (lnode
->val
->op
== lnode
->def
->op
) &&
20741 (memcmp(lnode
->val
->param
, lnode
->def
->param
,
20742 count
* sizeof(lnode
->val
->param
[0])) == 0) &&
20743 (memcmp(&lnode
->val
->u
, &lnode
->def
->u
, sizeof(lnode
->def
->u
)) == 0)) {
20744 lnode
->val
= lnode
->def
;
20746 /* Only allow lattice high when all of my inputs
20747 * are also lattice high. Occassionally I can
20748 * have constants with a lattice low input, so
20749 * I do not need to check that case.
20751 if (is_lattice_hi(state
, lnode
)) {
20752 struct lattice_node
*tmp
;
20754 rhs
= lnode
->val
->rhs
;
20755 for(i
= 0; i
< rhs
; i
++) {
20756 tmp
= triple_to_lattice(state
, scc
, RHS(lnode
->val
, i
));
20757 if (!is_lattice_hi(state
, tmp
)) {
20763 /* Find the cases that are always lattice lo */
20765 triple_is_def(state
, lnode
->val
) &&
20766 !triple_is_pure(state
, lnode
->val
, lnode
->old_id
)) {
20769 /* See if the lattice value has changed */
20770 changed
= lval_changed(state
, old
, lnode
);
20771 /* See if this value should not change */
20772 if ((lnode
->val
!= lnode
->def
) &&
20773 (( !triple_is_def(state
, lnode
->def
) &&
20774 !triple_is_cbranch(state
, lnode
->def
)) ||
20775 (lnode
->def
->op
== OP_PIECE
))) {
20776 #if DEBUG_ROMCC_WARNINGS
20777 #warning "FIXME constant propogate through expressions with multiple left hand sides"
20780 internal_warning(state
, lnode
->def
, "non def changes value?");
20785 /* See if we need to free the scratch value */
20786 if (lnode
->val
!= scratch
) {
20794 static void scc_visit_cbranch(struct compile_state
*state
, struct scc_state
*scc
,
20795 struct lattice_node
*lnode
)
20797 struct lattice_node
*cond
;
20798 struct flow_edge
*left
, *right
;
20801 /* Update the branch value */
20802 changed
= compute_lnode_val(state
, scc
, lnode
);
20803 scc_debug_lnode(state
, scc
, lnode
, changed
);
20805 /* This only applies to conditional branches */
20806 if (!triple_is_cbranch(state
, lnode
->def
)) {
20807 internal_error(state
, lnode
->def
, "not a conditional branch");
20810 if (state
->compiler
->debug
& DEBUG_SCC_TRANSFORM
) {
20811 struct flow_edge
*fedge
;
20812 FILE *fp
= state
->errout
;
20813 fprintf(fp
, "%s: %d (",
20814 tops(lnode
->def
->op
),
20817 for(fedge
= lnode
->fblock
->out
; fedge
; fedge
= fedge
->out_next
) {
20818 fprintf(fp
, " %d", fedge
->dst
->block
->vertex
);
20821 if (lnode
->def
->rhs
> 0) {
20822 fprintf(fp
, " <- %d",
20823 RHS(lnode
->def
, 0)->id
);
20827 cond
= triple_to_lattice(state
, scc
, RHS(lnode
->def
,0));
20828 for(left
= cond
->fblock
->out
; left
; left
= left
->out_next
) {
20829 if (left
->dst
->block
->first
== lnode
->def
->next
) {
20834 internal_error(state
, lnode
->def
, "Cannot find left branch edge");
20836 for(right
= cond
->fblock
->out
; right
; right
= right
->out_next
) {
20837 if (right
->dst
->block
->first
== TARG(lnode
->def
, 0)) {
20842 internal_error(state
, lnode
->def
, "Cannot find right branch edge");
20844 /* I should only come here if the controlling expressions value
20845 * has changed, which means it must be either a constant or lo.
20847 if (is_lattice_hi(state
, cond
)) {
20848 internal_error(state
, cond
->def
, "condition high?");
20851 if (is_lattice_lo(state
, cond
)) {
20852 scc_add_fedge(state
, scc
, left
);
20853 scc_add_fedge(state
, scc
, right
);
20855 else if (cond
->val
->u
.cval
) {
20856 scc_add_fedge(state
, scc
, right
);
20858 scc_add_fedge(state
, scc
, left
);
20864 static void scc_add_sedge_dst(struct compile_state
*state
,
20865 struct scc_state
*scc
, struct ssa_edge
*sedge
)
20867 if (triple_is_cbranch(state
, sedge
->dst
->def
)) {
20868 scc_visit_cbranch(state
, scc
, sedge
->dst
);
20870 else if (triple_is_def(state
, sedge
->dst
->def
)) {
20871 scc_add_sedge(state
, scc
, sedge
);
20875 static void scc_visit_phi(struct compile_state
*state
, struct scc_state
*scc
,
20876 struct lattice_node
*lnode
)
20878 struct lattice_node
*tmp
;
20879 struct triple
**slot
, *old
;
20880 struct flow_edge
*fedge
;
20883 if (lnode
->def
->op
!= OP_PHI
) {
20884 internal_error(state
, lnode
->def
, "not phi");
20886 /* Store the original value */
20887 old
= preserve_lval(state
, lnode
);
20889 /* default to lattice high */
20890 lnode
->val
= lnode
->def
;
20891 slot
= &RHS(lnode
->def
, 0);
20893 for(fedge
= lnode
->fblock
->in
; fedge
; index
++, fedge
= fedge
->in_next
) {
20894 if (state
->compiler
->debug
& DEBUG_SCC_TRANSFORM
) {
20895 fprintf(state
->errout
, "Examining edge: %d vertex: %d executable: %d\n",
20897 fedge
->dst
->block
->vertex
,
20901 if (!fedge
->executable
) {
20904 if (!slot
[index
]) {
20905 internal_error(state
, lnode
->def
, "no phi value");
20907 tmp
= triple_to_lattice(state
, scc
, slot
[index
]);
20908 /* meet(X, lattice low) = lattice low */
20909 if (is_lattice_lo(state
, tmp
)) {
20912 /* meet(X, lattice high) = X */
20913 else if (is_lattice_hi(state
, tmp
)) {
20914 lnode
->val
= lnode
->val
;
20916 /* meet(lattice high, X) = X */
20917 else if (is_lattice_hi(state
, lnode
)) {
20918 lnode
->val
= dup_triple(state
, tmp
->val
);
20919 /* Only change the type if necessary */
20920 if (!is_subset_type(lnode
->def
->type
, tmp
->val
->type
)) {
20921 lnode
->val
->type
= lnode
->def
->type
;
20924 /* meet(const, const) = const or lattice low */
20925 else if (!constants_equal(state
, lnode
->val
, tmp
->val
)) {
20929 /* meet(lattice low, X) = lattice low */
20930 if (is_lattice_lo(state
, lnode
)) {
20935 changed
= lval_changed(state
, old
, lnode
);
20936 scc_debug_lnode(state
, scc
, lnode
, changed
);
20938 /* If the lattice value has changed update the work lists. */
20940 struct ssa_edge
*sedge
;
20941 for(sedge
= lnode
->out
; sedge
; sedge
= sedge
->out_next
) {
20942 scc_add_sedge_dst(state
, scc
, sedge
);
20948 static void scc_visit_expr(struct compile_state
*state
, struct scc_state
*scc
,
20949 struct lattice_node
*lnode
)
20953 if (!triple_is_def(state
, lnode
->def
)) {
20954 internal_warning(state
, lnode
->def
, "not visiting an expression?");
20956 changed
= compute_lnode_val(state
, scc
, lnode
);
20957 scc_debug_lnode(state
, scc
, lnode
, changed
);
20960 struct ssa_edge
*sedge
;
20961 for(sedge
= lnode
->out
; sedge
; sedge
= sedge
->out_next
) {
20962 scc_add_sedge_dst(state
, scc
, sedge
);
20967 static void scc_writeback_values(
20968 struct compile_state
*state
, struct scc_state
*scc
)
20970 struct triple
*first
, *ins
;
20971 first
= state
->first
;
20974 struct lattice_node
*lnode
;
20975 lnode
= triple_to_lattice(state
, scc
, ins
);
20976 if (state
->compiler
->debug
& DEBUG_SCC_TRANSFORM
) {
20977 if (is_lattice_hi(state
, lnode
) &&
20978 (lnode
->val
->op
!= OP_NOOP
))
20980 struct flow_edge
*fedge
;
20983 for(fedge
= lnode
->fblock
->in
;
20984 !executable
&& fedge
; fedge
= fedge
->in_next
) {
20985 executable
|= fedge
->executable
;
20988 internal_warning(state
, lnode
->def
,
20989 "lattice node %d %s->%s still high?",
20991 tops(lnode
->def
->op
),
20992 tops(lnode
->val
->op
));
20998 ins
->id
= lnode
->old_id
;
20999 if (lnode
->val
&& (lnode
->val
!= ins
)) {
21000 /* See if it something I know how to write back */
21001 switch(lnode
->val
->op
) {
21003 mkconst(state
, ins
, lnode
->val
->u
.cval
);
21006 mkaddr_const(state
, ins
,
21007 MISC(lnode
->val
, 0), lnode
->val
->u
.cval
);
21010 /* By default don't copy the changes,
21011 * recompute them in place instead.
21013 simplify(state
, ins
);
21016 if (is_const(lnode
->val
) &&
21017 !constants_equal(state
, lnode
->val
, ins
)) {
21018 internal_error(state
, 0, "constants not equal");
21020 /* Free the lattice nodes */
21025 } while(ins
!= first
);
21028 static void scc_transform(struct compile_state
*state
)
21030 struct scc_state scc
;
21031 if (!(state
->compiler
->flags
& COMPILER_SCC_TRANSFORM
)) {
21035 initialize_scc_state(state
, &scc
);
21037 while(scc
.flow_work_list
|| scc
.ssa_work_list
) {
21038 struct flow_edge
*fedge
;
21039 struct ssa_edge
*sedge
;
21040 struct flow_edge
*fptr
;
21041 while((fedge
= scc_next_fedge(state
, &scc
))) {
21042 struct block
*block
;
21043 struct triple
*ptr
;
21044 struct flow_block
*fblock
;
21047 if (fedge
->executable
) {
21051 internal_error(state
, 0, "fedge without dst");
21054 internal_error(state
, 0, "fedge without src");
21056 fedge
->executable
= 1;
21057 fblock
= fedge
->dst
;
21058 block
= fblock
->block
;
21060 for(fptr
= fblock
->in
; fptr
; fptr
= fptr
->in_next
) {
21061 if (fptr
->executable
) {
21066 if (state
->compiler
->debug
& DEBUG_SCC_TRANSFORM
) {
21067 fprintf(state
->errout
, "vertex: %d reps: %d\n",
21068 block
->vertex
, reps
);
21072 for(ptr
= block
->first
; !done
; ptr
= ptr
->next
) {
21073 struct lattice_node
*lnode
;
21074 done
= (ptr
== block
->last
);
21075 lnode
= &scc
.lattice
[ptr
->id
];
21076 if (ptr
->op
== OP_PHI
) {
21077 scc_visit_phi(state
, &scc
, lnode
);
21079 else if ((reps
== 1) && triple_is_def(state
, ptr
))
21081 scc_visit_expr(state
, &scc
, lnode
);
21084 /* Add unconditional branch edges */
21085 if (!triple_is_cbranch(state
, fblock
->block
->last
)) {
21086 struct flow_edge
*out
;
21087 for(out
= fblock
->out
; out
; out
= out
->out_next
) {
21088 scc_add_fedge(state
, &scc
, out
);
21092 while((sedge
= scc_next_sedge(state
, &scc
))) {
21093 struct lattice_node
*lnode
;
21094 struct flow_block
*fblock
;
21095 lnode
= sedge
->dst
;
21096 fblock
= lnode
->fblock
;
21098 if (state
->compiler
->debug
& DEBUG_SCC_TRANSFORM
) {
21099 fprintf(state
->errout
, "sedge: %5ld (%5d -> %5d)\n",
21100 (unsigned long)sedge
- (unsigned long)scc
.ssa_edges
,
21101 sedge
->src
->def
->id
,
21102 sedge
->dst
->def
->id
);
21105 if (lnode
->def
->op
== OP_PHI
) {
21106 scc_visit_phi(state
, &scc
, lnode
);
21109 for(fptr
= fblock
->in
; fptr
; fptr
= fptr
->in_next
) {
21110 if (fptr
->executable
) {
21115 scc_visit_expr(state
, &scc
, lnode
);
21121 scc_writeback_values(state
, &scc
);
21122 free_scc_state(state
, &scc
);
21123 rebuild_ssa_form(state
);
21125 print_blocks(state
, __func__
, state
->dbgout
);
21129 static void transform_to_arch_instructions(struct compile_state
*state
)
21131 struct triple
*ins
, *first
;
21132 first
= state
->first
;
21135 ins
= transform_to_arch_instruction(state
, ins
);
21136 } while(ins
!= first
);
21138 print_blocks(state
, __func__
, state
->dbgout
);
21141 #if DEBUG_CONSISTENCY
21142 static void verify_uses(struct compile_state
*state
)
21144 struct triple
*first
, *ins
;
21145 struct triple_set
*set
;
21146 first
= state
->first
;
21149 struct triple
**expr
;
21150 expr
= triple_rhs(state
, ins
, 0);
21151 for(; expr
; expr
= triple_rhs(state
, ins
, expr
)) {
21152 struct triple
*rhs
;
21154 for(set
= rhs
?rhs
->use
:0; set
; set
= set
->next
) {
21155 if (set
->member
== ins
) {
21160 internal_error(state
, ins
, "rhs not used");
21163 expr
= triple_lhs(state
, ins
, 0);
21164 for(; expr
; expr
= triple_lhs(state
, ins
, expr
)) {
21165 struct triple
*lhs
;
21167 for(set
= lhs
?lhs
->use
:0; set
; set
= set
->next
) {
21168 if (set
->member
== ins
) {
21173 internal_error(state
, ins
, "lhs not used");
21176 expr
= triple_misc(state
, ins
, 0);
21177 if (ins
->op
!= OP_PHI
) {
21178 for(; expr
; expr
= triple_targ(state
, ins
, expr
)) {
21179 struct triple
*misc
;
21181 for(set
= misc
?misc
->use
:0; set
; set
= set
->next
) {
21182 if (set
->member
== ins
) {
21187 internal_error(state
, ins
, "misc not used");
21191 if (!triple_is_ret(state
, ins
)) {
21192 expr
= triple_targ(state
, ins
, 0);
21193 for(; expr
; expr
= triple_targ(state
, ins
, expr
)) {
21194 struct triple
*targ
;
21196 for(set
= targ
?targ
->use
:0; set
; set
= set
->next
) {
21197 if (set
->member
== ins
) {
21202 internal_error(state
, ins
, "targ not used");
21207 } while(ins
!= first
);
21210 static void verify_blocks_present(struct compile_state
*state
)
21212 struct triple
*first
, *ins
;
21213 if (!state
->bb
.first_block
) {
21216 first
= state
->first
;
21219 valid_ins(state
, ins
);
21220 if (triple_stores_block(state
, ins
)) {
21221 if (!ins
->u
.block
) {
21222 internal_error(state
, ins
,
21223 "%p not in a block?", ins
);
21227 } while(ins
!= first
);
21232 static int edge_present(struct compile_state
*state
, struct block
*block
, struct triple
*edge
)
21234 struct block_set
*bedge
;
21235 struct block
*targ
;
21236 targ
= block_of_triple(state
, edge
);
21237 for(bedge
= block
->edges
; bedge
; bedge
= bedge
->next
) {
21238 if (bedge
->member
== targ
) {
21245 static void verify_blocks(struct compile_state
*state
)
21247 struct triple
*ins
;
21248 struct block
*block
;
21250 block
= state
->bb
.first_block
;
21257 struct block_set
*user
, *edge
;
21259 for(ins
= block
->first
; ins
!= block
->last
->next
; ins
= ins
->next
) {
21260 if (triple_stores_block(state
, ins
) && (ins
->u
.block
!= block
)) {
21261 internal_error(state
, ins
, "inconsitent block specified");
21263 valid_ins(state
, ins
);
21266 for(user
= block
->use
; user
; user
= user
->next
) {
21268 if (!user
->member
->first
) {
21269 internal_error(state
, block
->first
, "user is empty");
21271 if ((block
== state
->bb
.last_block
) &&
21272 (user
->member
== state
->bb
.first_block
)) {
21275 for(edge
= user
->member
->edges
; edge
; edge
= edge
->next
) {
21276 if (edge
->member
== block
) {
21281 internal_error(state
, user
->member
->first
,
21282 "user does not use block");
21285 if (triple_is_branch(state
, block
->last
)) {
21286 struct triple
**expr
;
21287 expr
= triple_edge_targ(state
, block
->last
, 0);
21288 for(;expr
; expr
= triple_edge_targ(state
, block
->last
, expr
)) {
21289 if (*expr
&& !edge_present(state
, block
, *expr
)) {
21290 internal_error(state
, block
->last
, "no edge to targ");
21294 if (!triple_is_ubranch(state
, block
->last
) &&
21295 (block
!= state
->bb
.last_block
) &&
21296 !edge_present(state
, block
, block
->last
->next
)) {
21297 internal_error(state
, block
->last
, "no edge to block->last->next");
21299 for(edge
= block
->edges
; edge
; edge
= edge
->next
) {
21300 for(user
= edge
->member
->use
; user
; user
= user
->next
) {
21301 if (user
->member
== block
) {
21305 if (!user
|| user
->member
!= block
) {
21306 internal_error(state
, block
->first
,
21307 "block does not use edge");
21309 if (!edge
->member
->first
) {
21310 internal_error(state
, block
->first
, "edge block is empty");
21313 if (block
->users
!= users
) {
21314 internal_error(state
, block
->first
,
21315 "computed users %d != stored users %d",
21316 users
, block
->users
);
21318 if (!triple_stores_block(state
, block
->last
->next
)) {
21319 internal_error(state
, block
->last
->next
,
21320 "cannot find next block");
21322 block
= block
->last
->next
->u
.block
;
21324 internal_error(state
, block
->last
->next
,
21327 } while(block
!= state
->bb
.first_block
);
21328 if (blocks
!= state
->bb
.last_vertex
) {
21329 internal_error(state
, 0, "computed blocks: %d != stored blocks %d",
21330 blocks
, state
->bb
.last_vertex
);
21334 static void verify_domination(struct compile_state
*state
)
21336 struct triple
*first
, *ins
;
21337 struct triple_set
*set
;
21338 if (!state
->bb
.first_block
) {
21342 first
= state
->first
;
21345 for(set
= ins
->use
; set
; set
= set
->next
) {
21346 struct triple
**slot
;
21347 struct triple
*use_point
;
21350 zrhs
= set
->member
->rhs
;
21351 slot
= &RHS(set
->member
, 0);
21352 /* See if the use is on the right hand side */
21353 for(i
= 0; i
< zrhs
; i
++) {
21354 if (slot
[i
] == ins
) {
21359 use_point
= set
->member
;
21360 if (set
->member
->op
== OP_PHI
) {
21361 struct block_set
*bset
;
21363 bset
= set
->member
->u
.block
->use
;
21364 for(edge
= 0; bset
&& (edge
< i
); edge
++) {
21368 internal_error(state
, set
->member
,
21369 "no edge for phi rhs %d", i
);
21371 use_point
= bset
->member
->last
;
21375 !tdominates(state
, ins
, use_point
)) {
21376 if (is_const(ins
)) {
21377 internal_warning(state
, ins
,
21378 "non dominated rhs use point %p?", use_point
);
21381 internal_error(state
, ins
,
21382 "non dominated rhs use point %p?", use_point
);
21387 } while(ins
!= first
);
21390 static void verify_rhs(struct compile_state
*state
)
21392 struct triple
*first
, *ins
;
21393 first
= state
->first
;
21396 struct triple
**slot
;
21399 slot
= &RHS(ins
, 0);
21400 for(i
= 0; i
< zrhs
; i
++) {
21401 if (slot
[i
] == 0) {
21402 internal_error(state
, ins
,
21403 "missing rhs %d on %s",
21406 if ((ins
->op
!= OP_PHI
) && (slot
[i
] == ins
)) {
21407 internal_error(state
, ins
,
21408 "ins == rhs[%d] on %s",
21413 } while(ins
!= first
);
21416 static void verify_piece(struct compile_state
*state
)
21418 struct triple
*first
, *ins
;
21419 first
= state
->first
;
21422 struct triple
*ptr
;
21425 for(ptr
= ins
->next
, i
= 0; i
< lhs
; i
++, ptr
= ptr
->next
) {
21426 if (ptr
!= LHS(ins
, i
)) {
21427 internal_error(state
, ins
, "malformed lhs on %s",
21430 if (ptr
->op
!= OP_PIECE
) {
21431 internal_error(state
, ins
, "bad lhs op %s at %d on %s",
21432 tops(ptr
->op
), i
, tops(ins
->op
));
21434 if (ptr
->u
.cval
!= i
) {
21435 internal_error(state
, ins
, "bad u.cval of %d %d expected",
21440 } while(ins
!= first
);
21443 static void verify_ins_colors(struct compile_state
*state
)
21445 struct triple
*first
, *ins
;
21447 first
= state
->first
;
21451 } while(ins
!= first
);
21454 static void verify_unknown(struct compile_state
*state
)
21456 struct triple
*first
, *ins
;
21457 if ( (unknown_triple
.next
!= &unknown_triple
) ||
21458 (unknown_triple
.prev
!= &unknown_triple
) ||
21460 (unknown_triple
.use
!= 0) ||
21462 (unknown_triple
.op
!= OP_UNKNOWNVAL
) ||
21463 (unknown_triple
.lhs
!= 0) ||
21464 (unknown_triple
.rhs
!= 0) ||
21465 (unknown_triple
.misc
!= 0) ||
21466 (unknown_triple
.targ
!= 0) ||
21467 (unknown_triple
.template_id
!= 0) ||
21468 (unknown_triple
.id
!= -1) ||
21469 (unknown_triple
.type
!= &unknown_type
) ||
21470 (unknown_triple
.occurance
!= &dummy_occurance
) ||
21471 (unknown_triple
.param
[0] != 0) ||
21472 (unknown_triple
.param
[1] != 0)) {
21473 internal_error(state
, &unknown_triple
, "unknown_triple corrupted!");
21475 if ( (dummy_occurance
.count
!= 2) ||
21476 (strcmp(dummy_occurance
.filename
, __FILE__
) != 0) ||
21477 (strcmp(dummy_occurance
.function
, "") != 0) ||
21478 (dummy_occurance
.col
!= 0) ||
21479 (dummy_occurance
.parent
!= 0)) {
21480 internal_error(state
, &unknown_triple
, "dummy_occurance corrupted!");
21482 if ( (unknown_type
.type
!= TYPE_UNKNOWN
)) {
21483 internal_error(state
, &unknown_triple
, "unknown_type corrupted!");
21485 first
= state
->first
;
21489 if (ins
== &unknown_triple
) {
21490 internal_error(state
, ins
, "unknown triple in list");
21492 params
= TRIPLE_SIZE(ins
);
21493 for(i
= 0; i
< params
; i
++) {
21494 if (ins
->param
[i
] == &unknown_triple
) {
21495 internal_error(state
, ins
, "unknown triple used!");
21499 } while(ins
!= first
);
21502 static void verify_types(struct compile_state
*state
)
21504 struct triple
*first
, *ins
;
21505 first
= state
->first
;
21508 struct type
*invalid
;
21509 invalid
= invalid_type(state
, ins
->type
);
21511 FILE *fp
= state
->errout
;
21512 fprintf(fp
, "type: ");
21513 name_of(fp
, ins
->type
);
21515 fprintf(fp
, "invalid type: ");
21516 name_of(fp
, invalid
);
21518 internal_error(state
, ins
, "invalid ins type");
21520 } while(ins
!= first
);
21523 static void verify_copy(struct compile_state
*state
)
21525 struct triple
*first
, *ins
, *next
;
21526 first
= state
->first
;
21527 next
= ins
= first
;
21531 if (ins
->op
!= OP_COPY
) {
21534 if (!equiv_types(ins
->type
, RHS(ins
, 0)->type
)) {
21535 FILE *fp
= state
->errout
;
21536 fprintf(fp
, "src type: ");
21537 name_of(fp
, RHS(ins
, 0)->type
);
21539 fprintf(fp
, "dst type: ");
21540 name_of(fp
, ins
->type
);
21542 internal_error(state
, ins
, "type mismatch in copy");
21544 } while(next
!= first
);
21547 static void verify_consistency(struct compile_state
*state
)
21549 verify_unknown(state
);
21550 verify_uses(state
);
21551 verify_blocks_present(state
);
21552 verify_blocks(state
);
21553 verify_domination(state
);
21555 verify_piece(state
);
21556 verify_ins_colors(state
);
21557 verify_types(state
);
21558 verify_copy(state
);
21559 if (state
->compiler
->debug
& DEBUG_VERIFICATION
) {
21560 fprintf(state
->dbgout
, "consistency verified\n");
21564 static void verify_consistency(struct compile_state
*state
) {}
21565 #endif /* DEBUG_CONSISTENCY */
21567 static void optimize(struct compile_state
*state
)
21569 /* Join all of the functions into one giant function */
21570 join_functions(state
);
21572 /* Dump what the instruction graph intially looks like */
21573 print_triples(state
);
21575 /* Replace structures with simpler data types */
21576 decompose_compound_types(state
);
21577 print_triples(state
);
21579 verify_consistency(state
);
21580 /* Analyze the intermediate code */
21581 state
->bb
.first
= state
->first
;
21582 analyze_basic_blocks(state
, &state
->bb
);
21584 /* Transform the code to ssa form. */
21586 * The transformation to ssa form puts a phi function
21587 * on each of edge of a dominance frontier where that
21588 * phi function might be needed. At -O2 if we don't
21589 * eleminate the excess phi functions we can get an
21590 * exponential code size growth. So I kill the extra
21591 * phi functions early and I kill them often.
21593 transform_to_ssa_form(state
);
21594 verify_consistency(state
);
21596 /* Remove dead code */
21597 eliminate_inefectual_code(state
);
21598 verify_consistency(state
);
21600 /* Do strength reduction and simple constant optimizations */
21601 simplify_all(state
);
21602 verify_consistency(state
);
21603 /* Propogate constants throughout the code */
21604 scc_transform(state
);
21605 verify_consistency(state
);
21606 #if DEBUG_ROMCC_WARNINGS
21607 #warning "WISHLIST implement single use constants (least possible register pressure)"
21608 #warning "WISHLIST implement induction variable elimination"
21610 /* Select architecture instructions and an initial partial
21611 * coloring based on architecture constraints.
21613 transform_to_arch_instructions(state
);
21614 verify_consistency(state
);
21616 /* Remove dead code */
21617 eliminate_inefectual_code(state
);
21618 verify_consistency(state
);
21620 /* Color all of the variables to see if they will fit in registers */
21621 insert_copies_to_phi(state
);
21622 verify_consistency(state
);
21624 insert_mandatory_copies(state
);
21625 verify_consistency(state
);
21627 allocate_registers(state
);
21628 verify_consistency(state
);
21630 /* Remove the optimization information.
21631 * This is more to check for memory consistency than to free memory.
21633 free_basic_blocks(state
, &state
->bb
);
21636 static void print_op_asm(struct compile_state
*state
,
21637 struct triple
*ins
, FILE *fp
)
21639 struct asm_info
*info
;
21641 unsigned lhs
, rhs
, i
;
21642 info
= ins
->u
.ainfo
;
21645 /* Don't count the clobbers in lhs */
21646 for(i
= 0; i
< lhs
; i
++) {
21647 if (LHS(ins
, i
)->type
== &void_type
) {
21652 fprintf(fp
, "#ASM\n");
21654 for(ptr
= info
->str
; *ptr
; ptr
++) {
21656 unsigned long param
;
21657 struct triple
*piece
;
21667 param
= strtoul(ptr
, &next
, 10);
21669 error(state
, ins
, "Invalid asm template");
21671 if (param
>= (lhs
+ rhs
)) {
21672 error(state
, ins
, "Invalid param %%%u in asm template",
21675 piece
= (param
< lhs
)? LHS(ins
, param
) : RHS(ins
, param
- lhs
);
21677 arch_reg_str(ID_REG(piece
->id
)));
21680 fprintf(fp
, "\n#NOT ASM\n");
21684 /* Only use the low x86 byte registers. This allows me
21685 * allocate the entire register when a byte register is used.
21687 #define X86_4_8BIT_GPRS 1
21690 #define X86_MMX_REGS (1<<0)
21691 #define X86_XMM_REGS (1<<1)
21692 #define X86_NOOP_COPY (1<<2)
21694 /* The x86 register classes */
21695 #define REGC_FLAGS 0
21696 #define REGC_GPR8 1
21697 #define REGC_GPR16 2
21698 #define REGC_GPR32 3
21699 #define REGC_DIVIDEND64 4
21700 #define REGC_DIVIDEND32 5
21703 #define REGC_GPR32_8 8
21704 #define REGC_GPR16_8 9
21705 #define REGC_GPR8_LO 10
21706 #define REGC_IMM32 11
21707 #define REGC_IMM16 12
21708 #define REGC_IMM8 13
21709 #define LAST_REGC REGC_IMM8
21710 #if LAST_REGC >= MAX_REGC
21711 #error "MAX_REGC is to low"
21714 /* Register class masks */
21715 #define REGCM_FLAGS (1 << REGC_FLAGS)
21716 #define REGCM_GPR8 (1 << REGC_GPR8)
21717 #define REGCM_GPR16 (1 << REGC_GPR16)
21718 #define REGCM_GPR32 (1 << REGC_GPR32)
21719 #define REGCM_DIVIDEND64 (1 << REGC_DIVIDEND64)
21720 #define REGCM_DIVIDEND32 (1 << REGC_DIVIDEND32)
21721 #define REGCM_MMX (1 << REGC_MMX)
21722 #define REGCM_XMM (1 << REGC_XMM)
21723 #define REGCM_GPR32_8 (1 << REGC_GPR32_8)
21724 #define REGCM_GPR16_8 (1 << REGC_GPR16_8)
21725 #define REGCM_GPR8_LO (1 << REGC_GPR8_LO)
21726 #define REGCM_IMM32 (1 << REGC_IMM32)
21727 #define REGCM_IMM16 (1 << REGC_IMM16)
21728 #define REGCM_IMM8 (1 << REGC_IMM8)
21729 #define REGCM_ALL ((1 << (LAST_REGC + 1)) - 1)
21730 #define REGCM_IMMALL (REGCM_IMM32 | REGCM_IMM16 | REGCM_IMM8)
21732 /* The x86 registers */
21733 #define REG_EFLAGS 2
21734 #define REGC_FLAGS_FIRST REG_EFLAGS
21735 #define REGC_FLAGS_LAST REG_EFLAGS
21744 #define REGC_GPR8_LO_FIRST REG_AL
21745 #define REGC_GPR8_LO_LAST REG_DL
21746 #define REGC_GPR8_FIRST REG_AL
21747 #define REGC_GPR8_LAST REG_DH
21756 #define REGC_GPR16_FIRST REG_AX
21757 #define REGC_GPR16_LAST REG_SP
21766 #define REGC_GPR32_FIRST REG_EAX
21767 #define REGC_GPR32_LAST REG_ESP
21768 #define REG_EDXEAX 27
21769 #define REGC_DIVIDEND64_FIRST REG_EDXEAX
21770 #define REGC_DIVIDEND64_LAST REG_EDXEAX
21771 #define REG_DXAX 28
21772 #define REGC_DIVIDEND32_FIRST REG_DXAX
21773 #define REGC_DIVIDEND32_LAST REG_DXAX
21774 #define REG_MMX0 29
21775 #define REG_MMX1 30
21776 #define REG_MMX2 31
21777 #define REG_MMX3 32
21778 #define REG_MMX4 33
21779 #define REG_MMX5 34
21780 #define REG_MMX6 35
21781 #define REG_MMX7 36
21782 #define REGC_MMX_FIRST REG_MMX0
21783 #define REGC_MMX_LAST REG_MMX7
21784 #define REG_XMM0 37
21785 #define REG_XMM1 38
21786 #define REG_XMM2 39
21787 #define REG_XMM3 40
21788 #define REG_XMM4 41
21789 #define REG_XMM5 42
21790 #define REG_XMM6 43
21791 #define REG_XMM7 44
21792 #define REGC_XMM_FIRST REG_XMM0
21793 #define REGC_XMM_LAST REG_XMM7
21795 #if DEBUG_ROMCC_WARNINGS
21796 #warning "WISHLIST figure out how to use pinsrw and pextrw to better use extended regs"
21799 #define LAST_REG REG_XMM7
21801 #define REGC_GPR32_8_FIRST REG_EAX
21802 #define REGC_GPR32_8_LAST REG_EDX
21803 #define REGC_GPR16_8_FIRST REG_AX
21804 #define REGC_GPR16_8_LAST REG_DX
21806 #define REGC_IMM8_FIRST -1
21807 #define REGC_IMM8_LAST -1
21808 #define REGC_IMM16_FIRST -2
21809 #define REGC_IMM16_LAST -1
21810 #define REGC_IMM32_FIRST -4
21811 #define REGC_IMM32_LAST -1
21813 #if LAST_REG >= MAX_REGISTERS
21814 #error "MAX_REGISTERS to low"
21818 static unsigned regc_size
[LAST_REGC
+1] = {
21819 [REGC_FLAGS
] = REGC_FLAGS_LAST
- REGC_FLAGS_FIRST
+ 1,
21820 [REGC_GPR8
] = REGC_GPR8_LAST
- REGC_GPR8_FIRST
+ 1,
21821 [REGC_GPR16
] = REGC_GPR16_LAST
- REGC_GPR16_FIRST
+ 1,
21822 [REGC_GPR32
] = REGC_GPR32_LAST
- REGC_GPR32_FIRST
+ 1,
21823 [REGC_DIVIDEND64
] = REGC_DIVIDEND64_LAST
- REGC_DIVIDEND64_FIRST
+ 1,
21824 [REGC_DIVIDEND32
] = REGC_DIVIDEND32_LAST
- REGC_DIVIDEND32_FIRST
+ 1,
21825 [REGC_MMX
] = REGC_MMX_LAST
- REGC_MMX_FIRST
+ 1,
21826 [REGC_XMM
] = REGC_XMM_LAST
- REGC_XMM_FIRST
+ 1,
21827 [REGC_GPR32_8
] = REGC_GPR32_8_LAST
- REGC_GPR32_8_FIRST
+ 1,
21828 [REGC_GPR16_8
] = REGC_GPR16_8_LAST
- REGC_GPR16_8_FIRST
+ 1,
21829 [REGC_GPR8_LO
] = REGC_GPR8_LO_LAST
- REGC_GPR8_LO_FIRST
+ 1,
21835 static const struct {
21837 } regcm_bound
[LAST_REGC
+ 1] = {
21838 [REGC_FLAGS
] = { REGC_FLAGS_FIRST
, REGC_FLAGS_LAST
},
21839 [REGC_GPR8
] = { REGC_GPR8_FIRST
, REGC_GPR8_LAST
},
21840 [REGC_GPR16
] = { REGC_GPR16_FIRST
, REGC_GPR16_LAST
},
21841 [REGC_GPR32
] = { REGC_GPR32_FIRST
, REGC_GPR32_LAST
},
21842 [REGC_DIVIDEND64
] = { REGC_DIVIDEND64_FIRST
, REGC_DIVIDEND64_LAST
},
21843 [REGC_DIVIDEND32
] = { REGC_DIVIDEND32_FIRST
, REGC_DIVIDEND32_LAST
},
21844 [REGC_MMX
] = { REGC_MMX_FIRST
, REGC_MMX_LAST
},
21845 [REGC_XMM
] = { REGC_XMM_FIRST
, REGC_XMM_LAST
},
21846 [REGC_GPR32_8
] = { REGC_GPR32_8_FIRST
, REGC_GPR32_8_LAST
},
21847 [REGC_GPR16_8
] = { REGC_GPR16_8_FIRST
, REGC_GPR16_8_LAST
},
21848 [REGC_GPR8_LO
] = { REGC_GPR8_LO_FIRST
, REGC_GPR8_LO_LAST
},
21849 [REGC_IMM32
] = { REGC_IMM32_FIRST
, REGC_IMM32_LAST
},
21850 [REGC_IMM16
] = { REGC_IMM16_FIRST
, REGC_IMM16_LAST
},
21851 [REGC_IMM8
] = { REGC_IMM8_FIRST
, REGC_IMM8_LAST
},
21854 #if ARCH_INPUT_REGS != 4
21855 #error ARCH_INPUT_REGS size mismatch
21857 static const struct reg_info arch_input_regs
[ARCH_INPUT_REGS
] = {
21858 { .reg
= REG_EAX
, .regcm
= REGCM_GPR32
},
21859 { .reg
= REG_EBX
, .regcm
= REGCM_GPR32
},
21860 { .reg
= REG_ECX
, .regcm
= REGCM_GPR32
},
21861 { .reg
= REG_EDX
, .regcm
= REGCM_GPR32
},
21864 #if ARCH_OUTPUT_REGS != 4
21865 #error ARCH_INPUT_REGS size mismatch
21867 static const struct reg_info arch_output_regs
[ARCH_OUTPUT_REGS
] = {
21868 { .reg
= REG_EAX
, .regcm
= REGCM_GPR32
},
21869 { .reg
= REG_EBX
, .regcm
= REGCM_GPR32
},
21870 { .reg
= REG_ECX
, .regcm
= REGCM_GPR32
},
21871 { .reg
= REG_EDX
, .regcm
= REGCM_GPR32
},
21874 static void init_arch_state(struct arch_state
*arch
)
21876 memset(arch
, 0, sizeof(*arch
));
21877 arch
->features
= 0;
21880 static const struct compiler_flag arch_flags
[] = {
21881 { "mmx", X86_MMX_REGS
},
21882 { "sse", X86_XMM_REGS
},
21883 { "noop-copy", X86_NOOP_COPY
},
21886 static const struct compiler_flag arch_cpus
[] = {
21888 { "p2", X86_MMX_REGS
},
21889 { "p3", X86_MMX_REGS
| X86_XMM_REGS
},
21890 { "p4", X86_MMX_REGS
| X86_XMM_REGS
},
21891 { "k7", X86_MMX_REGS
},
21892 { "k8", X86_MMX_REGS
| X86_XMM_REGS
},
21893 { "c3", X86_MMX_REGS
},
21894 { "c3-2", X86_MMX_REGS
| X86_XMM_REGS
}, /* Nehemiah */
21897 static int arch_encode_flag(struct arch_state
*arch
, const char *flag
)
21904 if (strncmp(flag
, "no-", 3) == 0) {
21908 if (act
&& strncmp(flag
, "cpu=", 4) == 0) {
21910 result
= set_flag(arch_cpus
, &arch
->features
, 1, flag
);
21913 result
= set_flag(arch_flags
, &arch
->features
, act
, flag
);
21918 static void arch_usage(FILE *fp
)
21920 flag_usage(fp
, arch_flags
, "-m", "-mno-");
21921 flag_usage(fp
, arch_cpus
, "-mcpu=", 0);
21924 static unsigned arch_regc_size(struct compile_state
*state
, int class)
21926 if ((class < 0) || (class > LAST_REGC
)) {
21929 return regc_size
[class];
21932 static int arch_regcm_intersect(unsigned regcm1
, unsigned regcm2
)
21934 /* See if two register classes may have overlapping registers */
21935 unsigned gpr_mask
= REGCM_GPR8
| REGCM_GPR8_LO
| REGCM_GPR16_8
| REGCM_GPR16
|
21936 REGCM_GPR32_8
| REGCM_GPR32
|
21937 REGCM_DIVIDEND32
| REGCM_DIVIDEND64
;
21939 /* Special case for the immediates */
21940 if ((regcm1
& (REGCM_IMM32
| REGCM_IMM16
| REGCM_IMM8
)) &&
21941 ((regcm1
& ~(REGCM_IMM32
| REGCM_IMM16
| REGCM_IMM8
)) == 0) &&
21942 (regcm2
& (REGCM_IMM32
| REGCM_IMM16
| REGCM_IMM8
)) &&
21943 ((regcm2
& ~(REGCM_IMM32
| REGCM_IMM16
| REGCM_IMM8
)) == 0)) {
21946 return (regcm1
& regcm2
) ||
21947 ((regcm1
& gpr_mask
) && (regcm2
& gpr_mask
));
21950 static void arch_reg_equivs(
21951 struct compile_state
*state
, unsigned *equiv
, int reg
)
21953 if ((reg
< 0) || (reg
> LAST_REG
)) {
21954 internal_error(state
, 0, "invalid register");
21959 #if X86_4_8BIT_GPRS
21963 *equiv
++ = REG_EAX
;
21964 *equiv
++ = REG_DXAX
;
21965 *equiv
++ = REG_EDXEAX
;
21968 #if X86_4_8BIT_GPRS
21972 *equiv
++ = REG_EAX
;
21973 *equiv
++ = REG_DXAX
;
21974 *equiv
++ = REG_EDXEAX
;
21977 #if X86_4_8BIT_GPRS
21981 *equiv
++ = REG_EBX
;
21985 #if X86_4_8BIT_GPRS
21989 *equiv
++ = REG_EBX
;
21992 #if X86_4_8BIT_GPRS
21996 *equiv
++ = REG_ECX
;
22000 #if X86_4_8BIT_GPRS
22004 *equiv
++ = REG_ECX
;
22007 #if X86_4_8BIT_GPRS
22011 *equiv
++ = REG_EDX
;
22012 *equiv
++ = REG_DXAX
;
22013 *equiv
++ = REG_EDXEAX
;
22016 #if X86_4_8BIT_GPRS
22020 *equiv
++ = REG_EDX
;
22021 *equiv
++ = REG_DXAX
;
22022 *equiv
++ = REG_EDXEAX
;
22027 *equiv
++ = REG_EAX
;
22028 *equiv
++ = REG_DXAX
;
22029 *equiv
++ = REG_EDXEAX
;
22034 *equiv
++ = REG_EBX
;
22039 *equiv
++ = REG_ECX
;
22044 *equiv
++ = REG_EDX
;
22045 *equiv
++ = REG_DXAX
;
22046 *equiv
++ = REG_EDXEAX
;
22049 *equiv
++ = REG_ESI
;
22052 *equiv
++ = REG_EDI
;
22055 *equiv
++ = REG_EBP
;
22058 *equiv
++ = REG_ESP
;
22064 *equiv
++ = REG_DXAX
;
22065 *equiv
++ = REG_EDXEAX
;
22081 *equiv
++ = REG_DXAX
;
22082 *equiv
++ = REG_EDXEAX
;
22103 *equiv
++ = REG_EAX
;
22104 *equiv
++ = REG_EDX
;
22105 *equiv
++ = REG_EDXEAX
;
22114 *equiv
++ = REG_EAX
;
22115 *equiv
++ = REG_EDX
;
22116 *equiv
++ = REG_DXAX
;
22119 *equiv
++ = REG_UNSET
;
22122 static unsigned arch_avail_mask(struct compile_state
*state
)
22124 unsigned avail_mask
;
22125 /* REGCM_GPR8 is not available */
22126 avail_mask
= REGCM_GPR8_LO
| REGCM_GPR16_8
| REGCM_GPR16
|
22127 REGCM_GPR32
| REGCM_GPR32_8
|
22128 REGCM_DIVIDEND32
| REGCM_DIVIDEND64
|
22129 REGCM_IMM32
| REGCM_IMM16
| REGCM_IMM8
| REGCM_FLAGS
;
22130 if (state
->arch
->features
& X86_MMX_REGS
) {
22131 avail_mask
|= REGCM_MMX
;
22133 if (state
->arch
->features
& X86_XMM_REGS
) {
22134 avail_mask
|= REGCM_XMM
;
22139 static unsigned arch_regcm_normalize(struct compile_state
*state
, unsigned regcm
)
22141 unsigned mask
, result
;
22145 for(class = 0, mask
= 1; mask
; mask
<<= 1, class++) {
22146 if ((result
& mask
) == 0) {
22149 if (class > LAST_REGC
) {
22152 for(class2
= 0; class2
<= LAST_REGC
; class2
++) {
22153 if ((regcm_bound
[class2
].first
>= regcm_bound
[class].first
) &&
22154 (regcm_bound
[class2
].last
<= regcm_bound
[class].last
)) {
22155 result
|= (1 << class2
);
22159 result
&= arch_avail_mask(state
);
22163 static unsigned arch_regcm_reg_normalize(struct compile_state
*state
, unsigned regcm
)
22165 /* Like arch_regcm_normalize except immediate register classes are excluded */
22166 regcm
= arch_regcm_normalize(state
, regcm
);
22167 /* Remove the immediate register classes */
22168 regcm
&= ~(REGCM_IMM32
| REGCM_IMM16
| REGCM_IMM8
);
22173 static unsigned arch_reg_regcm(struct compile_state
*state
, int reg
)
22178 for(class = 0; class <= LAST_REGC
; class++) {
22179 if ((reg
>= regcm_bound
[class].first
) &&
22180 (reg
<= regcm_bound
[class].last
)) {
22181 mask
|= (1 << class);
22185 internal_error(state
, 0, "reg %d not in any class", reg
);
22190 static struct reg_info
arch_reg_constraint(
22191 struct compile_state
*state
, struct type
*type
, const char *constraint
)
22193 static const struct {
22197 } constraints
[] = {
22198 { 'r', REGCM_GPR32
, REG_UNSET
},
22199 { 'g', REGCM_GPR32
, REG_UNSET
},
22200 { 'p', REGCM_GPR32
, REG_UNSET
},
22201 { 'q', REGCM_GPR8_LO
, REG_UNSET
},
22202 { 'Q', REGCM_GPR32_8
, REG_UNSET
},
22203 { 'x', REGCM_XMM
, REG_UNSET
},
22204 { 'y', REGCM_MMX
, REG_UNSET
},
22205 { 'a', REGCM_GPR32
, REG_EAX
},
22206 { 'b', REGCM_GPR32
, REG_EBX
},
22207 { 'c', REGCM_GPR32
, REG_ECX
},
22208 { 'd', REGCM_GPR32
, REG_EDX
},
22209 { 'D', REGCM_GPR32
, REG_EDI
},
22210 { 'S', REGCM_GPR32
, REG_ESI
},
22211 { '\0', 0, REG_UNSET
},
22213 unsigned int regcm
;
22214 unsigned int mask
, reg
;
22215 struct reg_info result
;
22217 regcm
= arch_type_to_regcm(state
, type
);
22220 for(ptr
= constraint
; *ptr
; ptr
++) {
22225 for(i
= 0; constraints
[i
].class != '\0'; i
++) {
22226 if (constraints
[i
].class == *ptr
) {
22230 if (constraints
[i
].class == '\0') {
22231 error(state
, 0, "invalid register constraint ``%c''", *ptr
);
22234 if ((constraints
[i
].mask
& regcm
) == 0) {
22235 error(state
, 0, "invalid register class %c specified",
22238 mask
|= constraints
[i
].mask
;
22239 if (constraints
[i
].reg
!= REG_UNSET
) {
22240 if ((reg
!= REG_UNSET
) && (reg
!= constraints
[i
].reg
)) {
22241 error(state
, 0, "Only one register may be specified");
22243 reg
= constraints
[i
].reg
;
22247 result
.regcm
= mask
;
22251 static struct reg_info
arch_reg_clobber(
22252 struct compile_state
*state
, const char *clobber
)
22254 struct reg_info result
;
22255 if (strcmp(clobber
, "memory") == 0) {
22256 result
.reg
= REG_UNSET
;
22259 else if (strcmp(clobber
, "eax") == 0) {
22260 result
.reg
= REG_EAX
;
22261 result
.regcm
= REGCM_GPR32
;
22263 else if (strcmp(clobber
, "ebx") == 0) {
22264 result
.reg
= REG_EBX
;
22265 result
.regcm
= REGCM_GPR32
;
22267 else if (strcmp(clobber
, "ecx") == 0) {
22268 result
.reg
= REG_ECX
;
22269 result
.regcm
= REGCM_GPR32
;
22271 else if (strcmp(clobber
, "edx") == 0) {
22272 result
.reg
= REG_EDX
;
22273 result
.regcm
= REGCM_GPR32
;
22275 else if (strcmp(clobber
, "esi") == 0) {
22276 result
.reg
= REG_ESI
;
22277 result
.regcm
= REGCM_GPR32
;
22279 else if (strcmp(clobber
, "edi") == 0) {
22280 result
.reg
= REG_EDI
;
22281 result
.regcm
= REGCM_GPR32
;
22283 else if (strcmp(clobber
, "ebp") == 0) {
22284 result
.reg
= REG_EBP
;
22285 result
.regcm
= REGCM_GPR32
;
22287 else if (strcmp(clobber
, "esp") == 0) {
22288 result
.reg
= REG_ESP
;
22289 result
.regcm
= REGCM_GPR32
;
22291 else if (strcmp(clobber
, "cc") == 0) {
22292 result
.reg
= REG_EFLAGS
;
22293 result
.regcm
= REGCM_FLAGS
;
22295 else if ((strncmp(clobber
, "xmm", 3) == 0) &&
22296 octdigitp(clobber
[3]) && (clobber
[4] == '\0')) {
22297 result
.reg
= REG_XMM0
+ octdigval(clobber
[3]);
22298 result
.regcm
= REGCM_XMM
;
22300 else if ((strncmp(clobber
, "mm", 2) == 0) &&
22301 octdigitp(clobber
[3]) && (clobber
[4] == '\0')) {
22302 result
.reg
= REG_MMX0
+ octdigval(clobber
[3]);
22303 result
.regcm
= REGCM_MMX
;
22306 error(state
, 0, "unknown register name `%s' in asm",
22308 result
.reg
= REG_UNSET
;
22314 static int do_select_reg(struct compile_state
*state
,
22315 char *used
, int reg
, unsigned classes
)
22321 mask
= arch_reg_regcm(state
, reg
);
22322 return (classes
& mask
) ? reg
: REG_UNSET
;
22325 static int arch_select_free_register(
22326 struct compile_state
*state
, char *used
, int classes
)
22328 /* Live ranges with the most neighbors are colored first.
22330 * Generally it does not matter which colors are given
22331 * as the register allocator attempts to color live ranges
22332 * in an order where you are guaranteed not to run out of colors.
22334 * Occasionally the register allocator cannot find an order
22335 * of register selection that will find a free color. To
22336 * increase the odds the register allocator will work when
22337 * it guesses first give out registers from register classes
22338 * least likely to run out of registers.
22343 for(i
= REGC_XMM_FIRST
; (reg
== REG_UNSET
) && (i
<= REGC_XMM_LAST
); i
++) {
22344 reg
= do_select_reg(state
, used
, i
, classes
);
22346 for(i
= REGC_MMX_FIRST
; (reg
== REG_UNSET
) && (i
<= REGC_MMX_LAST
); i
++) {
22347 reg
= do_select_reg(state
, used
, i
, classes
);
22349 for(i
= REGC_GPR32_LAST
; (reg
== REG_UNSET
) && (i
>= REGC_GPR32_FIRST
); i
--) {
22350 reg
= do_select_reg(state
, used
, i
, classes
);
22352 for(i
= REGC_GPR16_FIRST
; (reg
== REG_UNSET
) && (i
<= REGC_GPR16_LAST
); i
++) {
22353 reg
= do_select_reg(state
, used
, i
, classes
);
22355 for(i
= REGC_GPR8_FIRST
; (reg
== REG_UNSET
) && (i
<= REGC_GPR8_LAST
); i
++) {
22356 reg
= do_select_reg(state
, used
, i
, classes
);
22358 for(i
= REGC_GPR8_LO_FIRST
; (reg
== REG_UNSET
) && (i
<= REGC_GPR8_LO_LAST
); i
++) {
22359 reg
= do_select_reg(state
, used
, i
, classes
);
22361 for(i
= REGC_DIVIDEND32_FIRST
; (reg
== REG_UNSET
) && (i
<= REGC_DIVIDEND32_LAST
); i
++) {
22362 reg
= do_select_reg(state
, used
, i
, classes
);
22364 for(i
= REGC_DIVIDEND64_FIRST
; (reg
== REG_UNSET
) && (i
<= REGC_DIVIDEND64_LAST
); i
++) {
22365 reg
= do_select_reg(state
, used
, i
, classes
);
22367 for(i
= REGC_FLAGS_FIRST
; (reg
== REG_UNSET
) && (i
<= REGC_FLAGS_LAST
); i
++) {
22368 reg
= do_select_reg(state
, used
, i
, classes
);
22374 static unsigned arch_type_to_regcm(struct compile_state
*state
, struct type
*type
)
22377 #if DEBUG_ROMCC_WARNINGS
22378 #warning "FIXME force types smaller (if legal) before I get here"
22382 switch(type
->type
& TYPE_MASK
) {
22389 mask
= REGCM_GPR8
| REGCM_GPR8_LO
|
22390 REGCM_GPR16
| REGCM_GPR16_8
|
22391 REGCM_GPR32
| REGCM_GPR32_8
|
22392 REGCM_DIVIDEND32
| REGCM_DIVIDEND64
|
22393 REGCM_MMX
| REGCM_XMM
|
22394 REGCM_IMM32
| REGCM_IMM16
| REGCM_IMM8
;
22398 mask
= REGCM_GPR16
| REGCM_GPR16_8
|
22399 REGCM_GPR32
| REGCM_GPR32_8
|
22400 REGCM_DIVIDEND32
| REGCM_DIVIDEND64
|
22401 REGCM_MMX
| REGCM_XMM
|
22402 REGCM_IMM32
| REGCM_IMM16
;
22410 mask
= REGCM_GPR32
| REGCM_GPR32_8
|
22411 REGCM_DIVIDEND32
| REGCM_DIVIDEND64
|
22412 REGCM_MMX
| REGCM_XMM
|
22417 mask
= arch_type_to_regcm(state
, type
->left
);
22420 mask
= arch_type_to_regcm(state
, type
->left
) &
22421 arch_type_to_regcm(state
, type
->right
);
22423 case TYPE_BITFIELD
:
22424 mask
= arch_type_to_regcm(state
, type
->left
);
22427 fprintf(state
->errout
, "type: ");
22428 name_of(state
->errout
, type
);
22429 fprintf(state
->errout
, "\n");
22430 internal_error(state
, 0, "no register class for type");
22433 mask
= arch_regcm_normalize(state
, mask
);
22437 static int is_imm32(struct triple
*imm
)
22439 // second condition commented out to prevent compiler warning:
22440 // imm->u.cval is always 32bit unsigned, so the comparison is
22442 return ((imm
->op
== OP_INTCONST
) /* && (imm->u.cval <= 0xffffffffUL) */ ) ||
22443 (imm
->op
== OP_ADDRCONST
);
22446 static int is_imm16(struct triple
*imm
)
22448 return ((imm
->op
== OP_INTCONST
) && (imm
->u
.cval
<= 0xffff));
22450 static int is_imm8(struct triple
*imm
)
22452 return ((imm
->op
== OP_INTCONST
) && (imm
->u
.cval
<= 0xff));
22455 static int get_imm32(struct triple
*ins
, struct triple
**expr
)
22457 struct triple
*imm
;
22459 while(imm
->op
== OP_COPY
) {
22462 if (!is_imm32(imm
)) {
22465 unuse_triple(*expr
, ins
);
22466 use_triple(imm
, ins
);
22471 static int get_imm8(struct triple
*ins
, struct triple
**expr
)
22473 struct triple
*imm
;
22475 while(imm
->op
== OP_COPY
) {
22478 if (!is_imm8(imm
)) {
22481 unuse_triple(*expr
, ins
);
22482 use_triple(imm
, ins
);
22487 #define TEMPLATE_NOP 0
22488 #define TEMPLATE_INTCONST8 1
22489 #define TEMPLATE_INTCONST32 2
22490 #define TEMPLATE_UNKNOWNVAL 3
22491 #define TEMPLATE_COPY8_REG 5
22492 #define TEMPLATE_COPY16_REG 6
22493 #define TEMPLATE_COPY32_REG 7
22494 #define TEMPLATE_COPY_IMM8 8
22495 #define TEMPLATE_COPY_IMM16 9
22496 #define TEMPLATE_COPY_IMM32 10
22497 #define TEMPLATE_PHI8 11
22498 #define TEMPLATE_PHI16 12
22499 #define TEMPLATE_PHI32 13
22500 #define TEMPLATE_STORE8 14
22501 #define TEMPLATE_STORE16 15
22502 #define TEMPLATE_STORE32 16
22503 #define TEMPLATE_LOAD8 17
22504 #define TEMPLATE_LOAD16 18
22505 #define TEMPLATE_LOAD32 19
22506 #define TEMPLATE_BINARY8_REG 20
22507 #define TEMPLATE_BINARY16_REG 21
22508 #define TEMPLATE_BINARY32_REG 22
22509 #define TEMPLATE_BINARY8_IMM 23
22510 #define TEMPLATE_BINARY16_IMM 24
22511 #define TEMPLATE_BINARY32_IMM 25
22512 #define TEMPLATE_SL8_CL 26
22513 #define TEMPLATE_SL16_CL 27
22514 #define TEMPLATE_SL32_CL 28
22515 #define TEMPLATE_SL8_IMM 29
22516 #define TEMPLATE_SL16_IMM 30
22517 #define TEMPLATE_SL32_IMM 31
22518 #define TEMPLATE_UNARY8 32
22519 #define TEMPLATE_UNARY16 33
22520 #define TEMPLATE_UNARY32 34
22521 #define TEMPLATE_CMP8_REG 35
22522 #define TEMPLATE_CMP16_REG 36
22523 #define TEMPLATE_CMP32_REG 37
22524 #define TEMPLATE_CMP8_IMM 38
22525 #define TEMPLATE_CMP16_IMM 39
22526 #define TEMPLATE_CMP32_IMM 40
22527 #define TEMPLATE_TEST8 41
22528 #define TEMPLATE_TEST16 42
22529 #define TEMPLATE_TEST32 43
22530 #define TEMPLATE_SET 44
22531 #define TEMPLATE_JMP 45
22532 #define TEMPLATE_RET 46
22533 #define TEMPLATE_INB_DX 47
22534 #define TEMPLATE_INB_IMM 48
22535 #define TEMPLATE_INW_DX 49
22536 #define TEMPLATE_INW_IMM 50
22537 #define TEMPLATE_INL_DX 51
22538 #define TEMPLATE_INL_IMM 52
22539 #define TEMPLATE_OUTB_DX 53
22540 #define TEMPLATE_OUTB_IMM 54
22541 #define TEMPLATE_OUTW_DX 55
22542 #define TEMPLATE_OUTW_IMM 56
22543 #define TEMPLATE_OUTL_DX 57
22544 #define TEMPLATE_OUTL_IMM 58
22545 #define TEMPLATE_BSF 59
22546 #define TEMPLATE_RDMSR 60
22547 #define TEMPLATE_WRMSR 61
22548 #define TEMPLATE_UMUL8 62
22549 #define TEMPLATE_UMUL16 63
22550 #define TEMPLATE_UMUL32 64
22551 #define TEMPLATE_DIV8 65
22552 #define TEMPLATE_DIV16 66
22553 #define TEMPLATE_DIV32 67
22554 #define LAST_TEMPLATE TEMPLATE_DIV32
22555 #if LAST_TEMPLATE >= MAX_TEMPLATES
22556 #error "MAX_TEMPLATES to low"
22559 #define COPY8_REGCM (REGCM_DIVIDEND64 | REGCM_DIVIDEND32 | REGCM_GPR32 | REGCM_GPR16 | REGCM_GPR8_LO | REGCM_MMX | REGCM_XMM)
22560 #define COPY16_REGCM (REGCM_DIVIDEND64 | REGCM_DIVIDEND32 | REGCM_GPR32 | REGCM_GPR16 | REGCM_MMX | REGCM_XMM)
22561 #define COPY32_REGCM (REGCM_DIVIDEND64 | REGCM_DIVIDEND32 | REGCM_GPR32 | REGCM_MMX | REGCM_XMM)
22564 static struct ins_template templates
[] = {
22567 [ 0] = { REG_UNNEEDED
, REGCM_IMMALL
},
22568 [ 1] = { REG_UNNEEDED
, REGCM_IMMALL
},
22569 [ 2] = { REG_UNNEEDED
, REGCM_IMMALL
},
22570 [ 3] = { REG_UNNEEDED
, REGCM_IMMALL
},
22571 [ 4] = { REG_UNNEEDED
, REGCM_IMMALL
},
22572 [ 5] = { REG_UNNEEDED
, REGCM_IMMALL
},
22573 [ 6] = { REG_UNNEEDED
, REGCM_IMMALL
},
22574 [ 7] = { REG_UNNEEDED
, REGCM_IMMALL
},
22575 [ 8] = { REG_UNNEEDED
, REGCM_IMMALL
},
22576 [ 9] = { REG_UNNEEDED
, REGCM_IMMALL
},
22577 [10] = { REG_UNNEEDED
, REGCM_IMMALL
},
22578 [11] = { REG_UNNEEDED
, REGCM_IMMALL
},
22579 [12] = { REG_UNNEEDED
, REGCM_IMMALL
},
22580 [13] = { REG_UNNEEDED
, REGCM_IMMALL
},
22581 [14] = { REG_UNNEEDED
, REGCM_IMMALL
},
22582 [15] = { REG_UNNEEDED
, REGCM_IMMALL
},
22583 [16] = { REG_UNNEEDED
, REGCM_IMMALL
},
22584 [17] = { REG_UNNEEDED
, REGCM_IMMALL
},
22585 [18] = { REG_UNNEEDED
, REGCM_IMMALL
},
22586 [19] = { REG_UNNEEDED
, REGCM_IMMALL
},
22587 [20] = { REG_UNNEEDED
, REGCM_IMMALL
},
22588 [21] = { REG_UNNEEDED
, REGCM_IMMALL
},
22589 [22] = { REG_UNNEEDED
, REGCM_IMMALL
},
22590 [23] = { REG_UNNEEDED
, REGCM_IMMALL
},
22591 [24] = { REG_UNNEEDED
, REGCM_IMMALL
},
22592 [25] = { REG_UNNEEDED
, REGCM_IMMALL
},
22593 [26] = { REG_UNNEEDED
, REGCM_IMMALL
},
22594 [27] = { REG_UNNEEDED
, REGCM_IMMALL
},
22595 [28] = { REG_UNNEEDED
, REGCM_IMMALL
},
22596 [29] = { REG_UNNEEDED
, REGCM_IMMALL
},
22597 [30] = { REG_UNNEEDED
, REGCM_IMMALL
},
22598 [31] = { REG_UNNEEDED
, REGCM_IMMALL
},
22599 [32] = { REG_UNNEEDED
, REGCM_IMMALL
},
22600 [33] = { REG_UNNEEDED
, REGCM_IMMALL
},
22601 [34] = { REG_UNNEEDED
, REGCM_IMMALL
},
22602 [35] = { REG_UNNEEDED
, REGCM_IMMALL
},
22603 [36] = { REG_UNNEEDED
, REGCM_IMMALL
},
22604 [37] = { REG_UNNEEDED
, REGCM_IMMALL
},
22605 [38] = { REG_UNNEEDED
, REGCM_IMMALL
},
22606 [39] = { REG_UNNEEDED
, REGCM_IMMALL
},
22607 [40] = { REG_UNNEEDED
, REGCM_IMMALL
},
22608 [41] = { REG_UNNEEDED
, REGCM_IMMALL
},
22609 [42] = { REG_UNNEEDED
, REGCM_IMMALL
},
22610 [43] = { REG_UNNEEDED
, REGCM_IMMALL
},
22611 [44] = { REG_UNNEEDED
, REGCM_IMMALL
},
22612 [45] = { REG_UNNEEDED
, REGCM_IMMALL
},
22613 [46] = { REG_UNNEEDED
, REGCM_IMMALL
},
22614 [47] = { REG_UNNEEDED
, REGCM_IMMALL
},
22615 [48] = { REG_UNNEEDED
, REGCM_IMMALL
},
22616 [49] = { REG_UNNEEDED
, REGCM_IMMALL
},
22617 [50] = { REG_UNNEEDED
, REGCM_IMMALL
},
22618 [51] = { REG_UNNEEDED
, REGCM_IMMALL
},
22619 [52] = { REG_UNNEEDED
, REGCM_IMMALL
},
22620 [53] = { REG_UNNEEDED
, REGCM_IMMALL
},
22621 [54] = { REG_UNNEEDED
, REGCM_IMMALL
},
22622 [55] = { REG_UNNEEDED
, REGCM_IMMALL
},
22623 [56] = { REG_UNNEEDED
, REGCM_IMMALL
},
22624 [57] = { REG_UNNEEDED
, REGCM_IMMALL
},
22625 [58] = { REG_UNNEEDED
, REGCM_IMMALL
},
22626 [59] = { REG_UNNEEDED
, REGCM_IMMALL
},
22627 [60] = { REG_UNNEEDED
, REGCM_IMMALL
},
22628 [61] = { REG_UNNEEDED
, REGCM_IMMALL
},
22629 [62] = { REG_UNNEEDED
, REGCM_IMMALL
},
22630 [63] = { REG_UNNEEDED
, REGCM_IMMALL
},
22633 [TEMPLATE_INTCONST8
] = {
22634 .lhs
= { [0] = { REG_UNNEEDED
, REGCM_IMM8
} },
22636 [TEMPLATE_INTCONST32
] = {
22637 .lhs
= { [0] = { REG_UNNEEDED
, REGCM_IMM32
} },
22639 [TEMPLATE_UNKNOWNVAL
] = {
22640 .lhs
= { [0] = { REG_UNSET
, COPY32_REGCM
} },
22642 [TEMPLATE_COPY8_REG
] = {
22643 .lhs
= { [0] = { REG_UNSET
, COPY8_REGCM
} },
22644 .rhs
= { [0] = { REG_UNSET
, COPY8_REGCM
} },
22646 [TEMPLATE_COPY16_REG
] = {
22647 .lhs
= { [0] = { REG_UNSET
, COPY16_REGCM
} },
22648 .rhs
= { [0] = { REG_UNSET
, COPY16_REGCM
} },
22650 [TEMPLATE_COPY32_REG
] = {
22651 .lhs
= { [0] = { REG_UNSET
, COPY32_REGCM
} },
22652 .rhs
= { [0] = { REG_UNSET
, COPY32_REGCM
} },
22654 [TEMPLATE_COPY_IMM8
] = {
22655 .lhs
= { [0] = { REG_UNSET
, COPY8_REGCM
} },
22656 .rhs
= { [0] = { REG_UNNEEDED
, REGCM_IMM8
} },
22658 [TEMPLATE_COPY_IMM16
] = {
22659 .lhs
= { [0] = { REG_UNSET
, COPY16_REGCM
} },
22660 .rhs
= { [0] = { REG_UNNEEDED
, REGCM_IMM16
| REGCM_IMM8
} },
22662 [TEMPLATE_COPY_IMM32
] = {
22663 .lhs
= { [0] = { REG_UNSET
, COPY32_REGCM
} },
22664 .rhs
= { [0] = { REG_UNNEEDED
, REGCM_IMM32
| REGCM_IMM16
| REGCM_IMM8
} },
22666 [TEMPLATE_PHI8
] = {
22667 .lhs
= { [0] = { REG_VIRT0
, COPY8_REGCM
} },
22668 .rhs
= { [0] = { REG_VIRT0
, COPY8_REGCM
} },
22670 [TEMPLATE_PHI16
] = {
22671 .lhs
= { [0] = { REG_VIRT0
, COPY16_REGCM
} },
22672 .rhs
= { [0] = { REG_VIRT0
, COPY16_REGCM
} },
22674 [TEMPLATE_PHI32
] = {
22675 .lhs
= { [0] = { REG_VIRT0
, COPY32_REGCM
} },
22676 .rhs
= { [0] = { REG_VIRT0
, COPY32_REGCM
} },
22678 [TEMPLATE_STORE8
] = {
22680 [0] = { REG_UNSET
, REGCM_GPR32
},
22681 [1] = { REG_UNSET
, REGCM_GPR8_LO
},
22684 [TEMPLATE_STORE16
] = {
22686 [0] = { REG_UNSET
, REGCM_GPR32
},
22687 [1] = { REG_UNSET
, REGCM_GPR16
},
22690 [TEMPLATE_STORE32
] = {
22692 [0] = { REG_UNSET
, REGCM_GPR32
},
22693 [1] = { REG_UNSET
, REGCM_GPR32
},
22696 [TEMPLATE_LOAD8
] = {
22697 .lhs
= { [0] = { REG_UNSET
, REGCM_GPR8_LO
} },
22698 .rhs
= { [0] = { REG_UNSET
, REGCM_GPR32
} },
22700 [TEMPLATE_LOAD16
] = {
22701 .lhs
= { [0] = { REG_UNSET
, REGCM_GPR16
} },
22702 .rhs
= { [0] = { REG_UNSET
, REGCM_GPR32
} },
22704 [TEMPLATE_LOAD32
] = {
22705 .lhs
= { [0] = { REG_UNSET
, REGCM_GPR32
} },
22706 .rhs
= { [0] = { REG_UNSET
, REGCM_GPR32
} },
22708 [TEMPLATE_BINARY8_REG
] = {
22709 .lhs
= { [0] = { REG_VIRT0
, REGCM_GPR8_LO
} },
22711 [0] = { REG_VIRT0
, REGCM_GPR8_LO
},
22712 [1] = { REG_UNSET
, REGCM_GPR8_LO
},
22715 [TEMPLATE_BINARY16_REG
] = {
22716 .lhs
= { [0] = { REG_VIRT0
, REGCM_GPR16
} },
22718 [0] = { REG_VIRT0
, REGCM_GPR16
},
22719 [1] = { REG_UNSET
, REGCM_GPR16
},
22722 [TEMPLATE_BINARY32_REG
] = {
22723 .lhs
= { [0] = { REG_VIRT0
, REGCM_GPR32
} },
22725 [0] = { REG_VIRT0
, REGCM_GPR32
},
22726 [1] = { REG_UNSET
, REGCM_GPR32
},
22729 [TEMPLATE_BINARY8_IMM
] = {
22730 .lhs
= { [0] = { REG_VIRT0
, REGCM_GPR8_LO
} },
22732 [0] = { REG_VIRT0
, REGCM_GPR8_LO
},
22733 [1] = { REG_UNNEEDED
, REGCM_IMM8
},
22736 [TEMPLATE_BINARY16_IMM
] = {
22737 .lhs
= { [0] = { REG_VIRT0
, REGCM_GPR16
} },
22739 [0] = { REG_VIRT0
, REGCM_GPR16
},
22740 [1] = { REG_UNNEEDED
, REGCM_IMM16
},
22743 [TEMPLATE_BINARY32_IMM
] = {
22744 .lhs
= { [0] = { REG_VIRT0
, REGCM_GPR32
} },
22746 [0] = { REG_VIRT0
, REGCM_GPR32
},
22747 [1] = { REG_UNNEEDED
, REGCM_IMM32
},
22750 [TEMPLATE_SL8_CL
] = {
22751 .lhs
= { [0] = { REG_VIRT0
, REGCM_GPR8_LO
} },
22753 [0] = { REG_VIRT0
, REGCM_GPR8_LO
},
22754 [1] = { REG_CL
, REGCM_GPR8_LO
},
22757 [TEMPLATE_SL16_CL
] = {
22758 .lhs
= { [0] = { REG_VIRT0
, REGCM_GPR16
} },
22760 [0] = { REG_VIRT0
, REGCM_GPR16
},
22761 [1] = { REG_CL
, REGCM_GPR8_LO
},
22764 [TEMPLATE_SL32_CL
] = {
22765 .lhs
= { [0] = { REG_VIRT0
, REGCM_GPR32
} },
22767 [0] = { REG_VIRT0
, REGCM_GPR32
},
22768 [1] = { REG_CL
, REGCM_GPR8_LO
},
22771 [TEMPLATE_SL8_IMM
] = {
22772 .lhs
= { [0] = { REG_VIRT0
, REGCM_GPR8_LO
} },
22774 [0] = { REG_VIRT0
, REGCM_GPR8_LO
},
22775 [1] = { REG_UNNEEDED
, REGCM_IMM8
},
22778 [TEMPLATE_SL16_IMM
] = {
22779 .lhs
= { [0] = { REG_VIRT0
, REGCM_GPR16
} },
22781 [0] = { REG_VIRT0
, REGCM_GPR16
},
22782 [1] = { REG_UNNEEDED
, REGCM_IMM8
},
22785 [TEMPLATE_SL32_IMM
] = {
22786 .lhs
= { [0] = { REG_VIRT0
, REGCM_GPR32
} },
22788 [0] = { REG_VIRT0
, REGCM_GPR32
},
22789 [1] = { REG_UNNEEDED
, REGCM_IMM8
},
22792 [TEMPLATE_UNARY8
] = {
22793 .lhs
= { [0] = { REG_VIRT0
, REGCM_GPR8_LO
} },
22794 .rhs
= { [0] = { REG_VIRT0
, REGCM_GPR8_LO
} },
22796 [TEMPLATE_UNARY16
] = {
22797 .lhs
= { [0] = { REG_VIRT0
, REGCM_GPR16
} },
22798 .rhs
= { [0] = { REG_VIRT0
, REGCM_GPR16
} },
22800 [TEMPLATE_UNARY32
] = {
22801 .lhs
= { [0] = { REG_VIRT0
, REGCM_GPR32
} },
22802 .rhs
= { [0] = { REG_VIRT0
, REGCM_GPR32
} },
22804 [TEMPLATE_CMP8_REG
] = {
22805 .lhs
= { [0] = { REG_EFLAGS
, REGCM_FLAGS
} },
22807 [0] = { REG_UNSET
, REGCM_GPR8_LO
},
22808 [1] = { REG_UNSET
, REGCM_GPR8_LO
},
22811 [TEMPLATE_CMP16_REG
] = {
22812 .lhs
= { [0] = { REG_EFLAGS
, REGCM_FLAGS
} },
22814 [0] = { REG_UNSET
, REGCM_GPR16
},
22815 [1] = { REG_UNSET
, REGCM_GPR16
},
22818 [TEMPLATE_CMP32_REG
] = {
22819 .lhs
= { [0] = { REG_EFLAGS
, REGCM_FLAGS
} },
22821 [0] = { REG_UNSET
, REGCM_GPR32
},
22822 [1] = { REG_UNSET
, REGCM_GPR32
},
22825 [TEMPLATE_CMP8_IMM
] = {
22826 .lhs
= { [0] = { REG_EFLAGS
, REGCM_FLAGS
} },
22828 [0] = { REG_UNSET
, REGCM_GPR8_LO
},
22829 [1] = { REG_UNNEEDED
, REGCM_IMM8
},
22832 [TEMPLATE_CMP16_IMM
] = {
22833 .lhs
= { [0] = { REG_EFLAGS
, REGCM_FLAGS
} },
22835 [0] = { REG_UNSET
, REGCM_GPR16
},
22836 [1] = { REG_UNNEEDED
, REGCM_IMM16
},
22839 [TEMPLATE_CMP32_IMM
] = {
22840 .lhs
= { [0] = { REG_EFLAGS
, REGCM_FLAGS
} },
22842 [0] = { REG_UNSET
, REGCM_GPR32
},
22843 [1] = { REG_UNNEEDED
, REGCM_IMM32
},
22846 [TEMPLATE_TEST8
] = {
22847 .lhs
= { [0] = { REG_EFLAGS
, REGCM_FLAGS
} },
22848 .rhs
= { [0] = { REG_UNSET
, REGCM_GPR8_LO
} },
22850 [TEMPLATE_TEST16
] = {
22851 .lhs
= { [0] = { REG_EFLAGS
, REGCM_FLAGS
} },
22852 .rhs
= { [0] = { REG_UNSET
, REGCM_GPR16
} },
22854 [TEMPLATE_TEST32
] = {
22855 .lhs
= { [0] = { REG_EFLAGS
, REGCM_FLAGS
} },
22856 .rhs
= { [0] = { REG_UNSET
, REGCM_GPR32
} },
22859 .lhs
= { [0] = { REG_UNSET
, REGCM_GPR8_LO
} },
22860 .rhs
= { [0] = { REG_EFLAGS
, REGCM_FLAGS
} },
22863 .rhs
= { [0] = { REG_EFLAGS
, REGCM_FLAGS
} },
22866 .rhs
= { [0] = { REG_UNSET
, REGCM_GPR32
} },
22868 [TEMPLATE_INB_DX
] = {
22869 .lhs
= { [0] = { REG_AL
, REGCM_GPR8_LO
} },
22870 .rhs
= { [0] = { REG_DX
, REGCM_GPR16
} },
22872 [TEMPLATE_INB_IMM
] = {
22873 .lhs
= { [0] = { REG_AL
, REGCM_GPR8_LO
} },
22874 .rhs
= { [0] = { REG_UNNEEDED
, REGCM_IMM8
} },
22876 [TEMPLATE_INW_DX
] = {
22877 .lhs
= { [0] = { REG_AX
, REGCM_GPR16
} },
22878 .rhs
= { [0] = { REG_DX
, REGCM_GPR16
} },
22880 [TEMPLATE_INW_IMM
] = {
22881 .lhs
= { [0] = { REG_AX
, REGCM_GPR16
} },
22882 .rhs
= { [0] = { REG_UNNEEDED
, REGCM_IMM8
} },
22884 [TEMPLATE_INL_DX
] = {
22885 .lhs
= { [0] = { REG_EAX
, REGCM_GPR32
} },
22886 .rhs
= { [0] = { REG_DX
, REGCM_GPR16
} },
22888 [TEMPLATE_INL_IMM
] = {
22889 .lhs
= { [0] = { REG_EAX
, REGCM_GPR32
} },
22890 .rhs
= { [0] = { REG_UNNEEDED
, REGCM_IMM8
} },
22892 [TEMPLATE_OUTB_DX
] = {
22894 [0] = { REG_AL
, REGCM_GPR8_LO
},
22895 [1] = { REG_DX
, REGCM_GPR16
},
22898 [TEMPLATE_OUTB_IMM
] = {
22900 [0] = { REG_AL
, REGCM_GPR8_LO
},
22901 [1] = { REG_UNNEEDED
, REGCM_IMM8
},
22904 [TEMPLATE_OUTW_DX
] = {
22906 [0] = { REG_AX
, REGCM_GPR16
},
22907 [1] = { REG_DX
, REGCM_GPR16
},
22910 [TEMPLATE_OUTW_IMM
] = {
22912 [0] = { REG_AX
, REGCM_GPR16
},
22913 [1] = { REG_UNNEEDED
, REGCM_IMM8
},
22916 [TEMPLATE_OUTL_DX
] = {
22918 [0] = { REG_EAX
, REGCM_GPR32
},
22919 [1] = { REG_DX
, REGCM_GPR16
},
22922 [TEMPLATE_OUTL_IMM
] = {
22924 [0] = { REG_EAX
, REGCM_GPR32
},
22925 [1] = { REG_UNNEEDED
, REGCM_IMM8
},
22929 .lhs
= { [0] = { REG_UNSET
, REGCM_GPR32
} },
22930 .rhs
= { [0] = { REG_UNSET
, REGCM_GPR32
} },
22932 [TEMPLATE_RDMSR
] = {
22934 [0] = { REG_EAX
, REGCM_GPR32
},
22935 [1] = { REG_EDX
, REGCM_GPR32
},
22937 .rhs
= { [0] = { REG_ECX
, REGCM_GPR32
} },
22939 [TEMPLATE_WRMSR
] = {
22941 [0] = { REG_ECX
, REGCM_GPR32
},
22942 [1] = { REG_EAX
, REGCM_GPR32
},
22943 [2] = { REG_EDX
, REGCM_GPR32
},
22946 [TEMPLATE_UMUL8
] = {
22947 .lhs
= { [0] = { REG_AX
, REGCM_GPR16
} },
22949 [0] = { REG_AL
, REGCM_GPR8_LO
},
22950 [1] = { REG_UNSET
, REGCM_GPR8_LO
},
22953 [TEMPLATE_UMUL16
] = {
22954 .lhs
= { [0] = { REG_DXAX
, REGCM_DIVIDEND32
} },
22956 [0] = { REG_AX
, REGCM_GPR16
},
22957 [1] = { REG_UNSET
, REGCM_GPR16
},
22960 [TEMPLATE_UMUL32
] = {
22961 .lhs
= { [0] = { REG_EDXEAX
, REGCM_DIVIDEND64
} },
22963 [0] = { REG_EAX
, REGCM_GPR32
},
22964 [1] = { REG_UNSET
, REGCM_GPR32
},
22967 [TEMPLATE_DIV8
] = {
22969 [0] = { REG_AL
, REGCM_GPR8_LO
},
22970 [1] = { REG_AH
, REGCM_GPR8
},
22973 [0] = { REG_AX
, REGCM_GPR16
},
22974 [1] = { REG_UNSET
, REGCM_GPR8_LO
},
22977 [TEMPLATE_DIV16
] = {
22979 [0] = { REG_AX
, REGCM_GPR16
},
22980 [1] = { REG_DX
, REGCM_GPR16
},
22983 [0] = { REG_DXAX
, REGCM_DIVIDEND32
},
22984 [1] = { REG_UNSET
, REGCM_GPR16
},
22987 [TEMPLATE_DIV32
] = {
22989 [0] = { REG_EAX
, REGCM_GPR32
},
22990 [1] = { REG_EDX
, REGCM_GPR32
},
22993 [0] = { REG_EDXEAX
, REGCM_DIVIDEND64
},
22994 [1] = { REG_UNSET
, REGCM_GPR32
},
22999 static void fixup_branch(struct compile_state
*state
,
23000 struct triple
*branch
, int jmp_op
, int cmp_op
, struct type
*cmp_type
,
23001 struct triple
*left
, struct triple
*right
)
23003 struct triple
*test
;
23005 internal_error(state
, branch
, "no branch test?");
23007 test
= pre_triple(state
, branch
,
23008 cmp_op
, cmp_type
, left
, right
);
23009 test
->template_id
= TEMPLATE_TEST32
;
23010 if (cmp_op
== OP_CMP
) {
23011 test
->template_id
= TEMPLATE_CMP32_REG
;
23012 if (get_imm32(test
, &RHS(test
, 1))) {
23013 test
->template_id
= TEMPLATE_CMP32_IMM
;
23016 use_triple(RHS(test
, 0), test
);
23017 use_triple(RHS(test
, 1), test
);
23018 unuse_triple(RHS(branch
, 0), branch
);
23019 RHS(branch
, 0) = test
;
23020 branch
->op
= jmp_op
;
23021 branch
->template_id
= TEMPLATE_JMP
;
23022 use_triple(RHS(branch
, 0), branch
);
23025 static void fixup_branches(struct compile_state
*state
,
23026 struct triple
*cmp
, struct triple
*use
, int jmp_op
)
23028 struct triple_set
*entry
, *next
;
23029 for(entry
= use
->use
; entry
; entry
= next
) {
23030 next
= entry
->next
;
23031 if (entry
->member
->op
== OP_COPY
) {
23032 fixup_branches(state
, cmp
, entry
->member
, jmp_op
);
23034 else if (entry
->member
->op
== OP_CBRANCH
) {
23035 struct triple
*branch
;
23036 struct triple
*left
, *right
;
23038 left
= RHS(cmp
, 0);
23039 if (cmp
->rhs
> 1) {
23040 right
= RHS(cmp
, 1);
23042 branch
= entry
->member
;
23043 fixup_branch(state
, branch
, jmp_op
,
23044 cmp
->op
, cmp
->type
, left
, right
);
23049 static void bool_cmp(struct compile_state
*state
,
23050 struct triple
*ins
, int cmp_op
, int jmp_op
, int set_op
)
23052 struct triple_set
*entry
, *next
;
23053 struct triple
*set
, *convert
;
23055 /* Put a barrier up before the cmp which preceeds the
23056 * copy instruction. If a set actually occurs this gives
23057 * us a chance to move variables in registers out of the way.
23060 /* Modify the comparison operator */
23062 ins
->template_id
= TEMPLATE_TEST32
;
23063 if (cmp_op
== OP_CMP
) {
23064 ins
->template_id
= TEMPLATE_CMP32_REG
;
23065 if (get_imm32(ins
, &RHS(ins
, 1))) {
23066 ins
->template_id
= TEMPLATE_CMP32_IMM
;
23069 /* Generate the instruction sequence that will transform the
23070 * result of the comparison into a logical value.
23072 set
= post_triple(state
, ins
, set_op
, &uchar_type
, ins
, 0);
23073 use_triple(ins
, set
);
23074 set
->template_id
= TEMPLATE_SET
;
23077 if (!equiv_types(ins
->type
, set
->type
)) {
23078 convert
= post_triple(state
, set
, OP_CONVERT
, ins
->type
, set
, 0);
23079 use_triple(set
, convert
);
23080 convert
->template_id
= TEMPLATE_COPY32_REG
;
23083 for(entry
= ins
->use
; entry
; entry
= next
) {
23084 next
= entry
->next
;
23085 if (entry
->member
== set
) {
23088 replace_rhs_use(state
, ins
, convert
, entry
->member
);
23090 fixup_branches(state
, ins
, convert
, jmp_op
);
23093 struct reg_info
arch_reg_lhs(struct compile_state
*state
, struct triple
*ins
, int index
)
23095 struct ins_template
*template;
23096 struct reg_info result
;
23098 if (ins
->op
== OP_PIECE
) {
23099 index
= ins
->u
.cval
;
23100 ins
= MISC(ins
, 0);
23103 if (triple_is_def(state
, ins
)) {
23106 if (index
>= zlhs
) {
23107 internal_error(state
, ins
, "index %d out of range for %s",
23108 index
, tops(ins
->op
));
23112 template = &ins
->u
.ainfo
->tmpl
;
23115 if (ins
->template_id
> LAST_TEMPLATE
) {
23116 internal_error(state
, ins
, "bad template number %d",
23119 template = &templates
[ins
->template_id
];
23122 result
= template->lhs
[index
];
23123 result
.regcm
= arch_regcm_normalize(state
, result
.regcm
);
23124 if (result
.reg
!= REG_UNNEEDED
) {
23125 result
.regcm
&= ~(REGCM_IMM32
| REGCM_IMM16
| REGCM_IMM8
);
23127 if (result
.regcm
== 0) {
23128 internal_error(state
, ins
, "lhs %d regcm == 0", index
);
23133 struct reg_info
arch_reg_rhs(struct compile_state
*state
, struct triple
*ins
, int index
)
23135 struct reg_info result
;
23136 struct ins_template
*template;
23137 if ((index
> ins
->rhs
) ||
23138 (ins
->op
== OP_PIECE
)) {
23139 internal_error(state
, ins
, "index %d out of range for %s\n",
23140 index
, tops(ins
->op
));
23144 template = &ins
->u
.ainfo
->tmpl
;
23150 if (ins
->template_id
> LAST_TEMPLATE
) {
23151 internal_error(state
, ins
, "bad template number %d",
23154 template = &templates
[ins
->template_id
];
23157 result
= template->rhs
[index
];
23158 result
.regcm
= arch_regcm_normalize(state
, result
.regcm
);
23159 if (result
.regcm
== 0) {
23160 internal_error(state
, ins
, "rhs %d regcm == 0", index
);
23165 static struct triple
*mod_div(struct compile_state
*state
,
23166 struct triple
*ins
, int div_op
, int index
)
23168 struct triple
*div
, *piece1
;
23170 /* Generate the appropriate division instruction */
23171 div
= post_triple(state
, ins
, div_op
, ins
->type
, 0, 0);
23172 RHS(div
, 0) = RHS(ins
, 0);
23173 RHS(div
, 1) = RHS(ins
, 1);
23174 piece1
= LHS(div
, 1);
23175 div
->template_id
= TEMPLATE_DIV32
;
23176 use_triple(RHS(div
, 0), div
);
23177 use_triple(RHS(div
, 1), div
);
23178 use_triple(LHS(div
, 0), div
);
23179 use_triple(LHS(div
, 1), div
);
23181 /* Replate uses of ins with the appropriate piece of the div */
23182 propogate_use(state
, ins
, LHS(div
, index
));
23183 release_triple(state
, ins
);
23185 /* Return the address of the next instruction */
23186 return piece1
->next
;
23189 static int noop_adecl(struct triple
*adecl
)
23191 struct triple_set
*use
;
23192 /* It's a noop if it doesn't specify stoorage */
23193 if (adecl
->lhs
== 0) {
23196 /* Is the adecl used? If not it's a noop */
23197 for(use
= adecl
->use
; use
; use
= use
->next
) {
23198 if ((use
->member
->op
!= OP_PIECE
) ||
23199 (MISC(use
->member
, 0) != adecl
)) {
23206 static struct triple
*x86_deposit(struct compile_state
*state
, struct triple
*ins
)
23208 struct triple
*mask
, *nmask
, *shift
;
23209 struct triple
*val
, *val_mask
, *val_shift
;
23210 struct triple
*targ
, *targ_mask
;
23211 struct triple
*new;
23212 ulong_t the_mask
, the_nmask
;
23214 targ
= RHS(ins
, 0);
23217 /* Get constant for the mask value */
23219 the_mask
<<= ins
->u
.bitfield
.size
;
23221 the_mask
<<= ins
->u
.bitfield
.offset
;
23222 mask
= pre_triple(state
, ins
, OP_INTCONST
, &uint_type
, 0, 0);
23223 mask
->u
.cval
= the_mask
;
23225 /* Get the inverted mask value */
23226 the_nmask
= ~the_mask
;
23227 nmask
= pre_triple(state
, ins
, OP_INTCONST
, &uint_type
, 0, 0);
23228 nmask
->u
.cval
= the_nmask
;
23230 /* Get constant for the shift value */
23231 shift
= pre_triple(state
, ins
, OP_INTCONST
, &uint_type
, 0, 0);
23232 shift
->u
.cval
= ins
->u
.bitfield
.offset
;
23234 /* Shift and mask the source value */
23236 if (shift
->u
.cval
!= 0) {
23237 val_shift
= pre_triple(state
, ins
, OP_SL
, val
->type
, val
, shift
);
23238 use_triple(val
, val_shift
);
23239 use_triple(shift
, val_shift
);
23241 val_mask
= val_shift
;
23242 if (is_signed(val
->type
)) {
23243 val_mask
= pre_triple(state
, ins
, OP_AND
, val
->type
, val_shift
, mask
);
23244 use_triple(val_shift
, val_mask
);
23245 use_triple(mask
, val_mask
);
23248 /* Mask the target value */
23249 targ_mask
= pre_triple(state
, ins
, OP_AND
, targ
->type
, targ
, nmask
);
23250 use_triple(targ
, targ_mask
);
23251 use_triple(nmask
, targ_mask
);
23253 /* Now combined them together */
23254 new = pre_triple(state
, ins
, OP_OR
, targ
->type
, targ_mask
, val_mask
);
23255 use_triple(targ_mask
, new);
23256 use_triple(val_mask
, new);
23258 /* Move all of the users over to the new expression */
23259 propogate_use(state
, ins
, new);
23261 /* Delete the original triple */
23262 release_triple(state
, ins
);
23264 /* Restart the transformation at mask */
23268 static struct triple
*x86_extract(struct compile_state
*state
, struct triple
*ins
)
23270 struct triple
*mask
, *shift
;
23271 struct triple
*val
, *val_mask
, *val_shift
;
23276 /* Get constant for the mask value */
23278 the_mask
<<= ins
->u
.bitfield
.size
;
23280 mask
= pre_triple(state
, ins
, OP_INTCONST
, &int_type
, 0, 0);
23281 mask
->u
.cval
= the_mask
;
23283 /* Get constant for the right shift value */
23284 shift
= pre_triple(state
, ins
, OP_INTCONST
, &int_type
, 0, 0);
23285 shift
->u
.cval
= ins
->u
.bitfield
.offset
;
23287 /* Shift arithmetic right, to correct the sign */
23289 if (shift
->u
.cval
!= 0) {
23291 if (ins
->op
== OP_SEXTRACT
) {
23296 val_shift
= pre_triple(state
, ins
, op
, val
->type
, val
, shift
);
23297 use_triple(val
, val_shift
);
23298 use_triple(shift
, val_shift
);
23301 /* Finally mask the value */
23302 val_mask
= pre_triple(state
, ins
, OP_AND
, ins
->type
, val_shift
, mask
);
23303 use_triple(val_shift
, val_mask
);
23304 use_triple(mask
, val_mask
);
23306 /* Move all of the users over to the new expression */
23307 propogate_use(state
, ins
, val_mask
);
23309 /* Release the original instruction */
23310 release_triple(state
, ins
);
23316 static struct triple
*transform_to_arch_instruction(
23317 struct compile_state
*state
, struct triple
*ins
)
23319 /* Transform from generic 3 address instructions
23320 * to archtecture specific instructions.
23321 * And apply architecture specific constraints to instructions.
23322 * Copies are inserted to preserve the register flexibility
23323 * of 3 address instructions.
23325 struct triple
*next
, *value
;
23330 ins
->template_id
= TEMPLATE_INTCONST32
;
23331 if (ins
->u
.cval
< 256) {
23332 ins
->template_id
= TEMPLATE_INTCONST8
;
23336 ins
->template_id
= TEMPLATE_INTCONST32
;
23338 case OP_UNKNOWNVAL
:
23339 ins
->template_id
= TEMPLATE_UNKNOWNVAL
;
23345 ins
->template_id
= TEMPLATE_NOP
;
23349 size
= size_of(state
, ins
->type
);
23350 value
= RHS(ins
, 0);
23351 if (is_imm8(value
) && (size
<= SIZEOF_I8
)) {
23352 ins
->template_id
= TEMPLATE_COPY_IMM8
;
23354 else if (is_imm16(value
) && (size
<= SIZEOF_I16
)) {
23355 ins
->template_id
= TEMPLATE_COPY_IMM16
;
23357 else if (is_imm32(value
) && (size
<= SIZEOF_I32
)) {
23358 ins
->template_id
= TEMPLATE_COPY_IMM32
;
23360 else if (is_const(value
)) {
23361 internal_error(state
, ins
, "bad constant passed to copy");
23363 else if (size
<= SIZEOF_I8
) {
23364 ins
->template_id
= TEMPLATE_COPY8_REG
;
23366 else if (size
<= SIZEOF_I16
) {
23367 ins
->template_id
= TEMPLATE_COPY16_REG
;
23369 else if (size
<= SIZEOF_I32
) {
23370 ins
->template_id
= TEMPLATE_COPY32_REG
;
23373 internal_error(state
, ins
, "bad type passed to copy");
23377 size
= size_of(state
, ins
->type
);
23378 if (size
<= SIZEOF_I8
) {
23379 ins
->template_id
= TEMPLATE_PHI8
;
23381 else if (size
<= SIZEOF_I16
) {
23382 ins
->template_id
= TEMPLATE_PHI16
;
23384 else if (size
<= SIZEOF_I32
) {
23385 ins
->template_id
= TEMPLATE_PHI32
;
23388 internal_error(state
, ins
, "bad type passed to phi");
23392 /* Adecls should always be treated as dead code and
23393 * removed. If we are not optimizing they may linger.
23395 if (!noop_adecl(ins
)) {
23396 internal_error(state
, ins
, "adecl remains?");
23398 ins
->template_id
= TEMPLATE_NOP
;
23399 next
= after_lhs(state
, ins
);
23402 switch(ins
->type
->type
& TYPE_MASK
) {
23403 case TYPE_CHAR
: case TYPE_UCHAR
:
23404 ins
->template_id
= TEMPLATE_STORE8
;
23406 case TYPE_SHORT
: case TYPE_USHORT
:
23407 ins
->template_id
= TEMPLATE_STORE16
;
23409 case TYPE_INT
: case TYPE_UINT
:
23410 case TYPE_LONG
: case TYPE_ULONG
:
23412 ins
->template_id
= TEMPLATE_STORE32
;
23415 internal_error(state
, ins
, "unknown type in store");
23420 switch(ins
->type
->type
& TYPE_MASK
) {
23421 case TYPE_CHAR
: case TYPE_UCHAR
:
23422 case TYPE_SHORT
: case TYPE_USHORT
:
23423 case TYPE_INT
: case TYPE_UINT
:
23424 case TYPE_LONG
: case TYPE_ULONG
:
23428 internal_error(state
, ins
, "unknown type in load");
23431 ins
->template_id
= TEMPLATE_LOAD32
;
23439 ins
->template_id
= TEMPLATE_BINARY32_REG
;
23440 if (get_imm32(ins
, &RHS(ins
, 1))) {
23441 ins
->template_id
= TEMPLATE_BINARY32_IMM
;
23446 ins
->template_id
= TEMPLATE_DIV32
;
23447 next
= after_lhs(state
, ins
);
23450 ins
->template_id
= TEMPLATE_UMUL32
;
23453 next
= mod_div(state
, ins
, OP_UDIVT
, 0);
23456 next
= mod_div(state
, ins
, OP_SDIVT
, 0);
23459 next
= mod_div(state
, ins
, OP_UDIVT
, 1);
23462 next
= mod_div(state
, ins
, OP_SDIVT
, 1);
23467 ins
->template_id
= TEMPLATE_SL32_CL
;
23468 if (get_imm8(ins
, &RHS(ins
, 1))) {
23469 ins
->template_id
= TEMPLATE_SL32_IMM
;
23470 } else if (size_of(state
, RHS(ins
, 1)->type
) > SIZEOF_CHAR
) {
23471 typed_pre_copy(state
, &uchar_type
, ins
, 1);
23476 ins
->template_id
= TEMPLATE_UNARY32
;
23479 bool_cmp(state
, ins
, OP_CMP
, OP_JMP_EQ
, OP_SET_EQ
);
23482 bool_cmp(state
, ins
, OP_CMP
, OP_JMP_NOTEQ
, OP_SET_NOTEQ
);
23485 bool_cmp(state
, ins
, OP_CMP
, OP_JMP_SLESS
, OP_SET_SLESS
);
23488 bool_cmp(state
, ins
, OP_CMP
, OP_JMP_ULESS
, OP_SET_ULESS
);
23491 bool_cmp(state
, ins
, OP_CMP
, OP_JMP_SMORE
, OP_SET_SMORE
);
23494 bool_cmp(state
, ins
, OP_CMP
, OP_JMP_UMORE
, OP_SET_UMORE
);
23497 bool_cmp(state
, ins
, OP_CMP
, OP_JMP_SLESSEQ
, OP_SET_SLESSEQ
);
23500 bool_cmp(state
, ins
, OP_CMP
, OP_JMP_ULESSEQ
, OP_SET_ULESSEQ
);
23503 bool_cmp(state
, ins
, OP_CMP
, OP_JMP_SMOREEQ
, OP_SET_SMOREEQ
);
23506 bool_cmp(state
, ins
, OP_CMP
, OP_JMP_UMOREEQ
, OP_SET_UMOREEQ
);
23509 bool_cmp(state
, ins
, OP_TEST
, OP_JMP_NOTEQ
, OP_SET_NOTEQ
);
23512 bool_cmp(state
, ins
, OP_TEST
, OP_JMP_EQ
, OP_SET_EQ
);
23516 ins
->template_id
= TEMPLATE_NOP
;
23519 fixup_branch(state
, ins
, OP_JMP_NOTEQ
, OP_TEST
,
23520 RHS(ins
, 0)->type
, RHS(ins
, 0), 0);
23523 ins
->template_id
= TEMPLATE_NOP
;
23526 ins
->template_id
= TEMPLATE_RET
;
23532 case OP_INB
: ins
->template_id
= TEMPLATE_INB_DX
; break;
23533 case OP_INW
: ins
->template_id
= TEMPLATE_INW_DX
; break;
23534 case OP_INL
: ins
->template_id
= TEMPLATE_INL_DX
; break;
23536 if (get_imm8(ins
, &RHS(ins
, 0))) {
23537 ins
->template_id
+= 1;
23544 case OP_OUTB
: ins
->template_id
= TEMPLATE_OUTB_DX
; break;
23545 case OP_OUTW
: ins
->template_id
= TEMPLATE_OUTW_DX
; break;
23546 case OP_OUTL
: ins
->template_id
= TEMPLATE_OUTL_DX
; break;
23548 if (get_imm8(ins
, &RHS(ins
, 1))) {
23549 ins
->template_id
+= 1;
23554 ins
->template_id
= TEMPLATE_BSF
;
23557 ins
->template_id
= TEMPLATE_RDMSR
;
23558 next
= after_lhs(state
, ins
);
23561 ins
->template_id
= TEMPLATE_WRMSR
;
23564 ins
->template_id
= TEMPLATE_NOP
;
23567 ins
->template_id
= TEMPLATE_NOP
;
23568 next
= after_lhs(state
, ins
);
23570 /* Already transformed instructions */
23572 ins
->template_id
= TEMPLATE_TEST32
;
23575 ins
->template_id
= TEMPLATE_CMP32_REG
;
23576 if (get_imm32(ins
, &RHS(ins
, 1))) {
23577 ins
->template_id
= TEMPLATE_CMP32_IMM
;
23581 ins
->template_id
= TEMPLATE_NOP
;
23583 case OP_JMP_EQ
: case OP_JMP_NOTEQ
:
23584 case OP_JMP_SLESS
: case OP_JMP_ULESS
:
23585 case OP_JMP_SMORE
: case OP_JMP_UMORE
:
23586 case OP_JMP_SLESSEQ
: case OP_JMP_ULESSEQ
:
23587 case OP_JMP_SMOREEQ
: case OP_JMP_UMOREEQ
:
23588 ins
->template_id
= TEMPLATE_JMP
;
23590 case OP_SET_EQ
: case OP_SET_NOTEQ
:
23591 case OP_SET_SLESS
: case OP_SET_ULESS
:
23592 case OP_SET_SMORE
: case OP_SET_UMORE
:
23593 case OP_SET_SLESSEQ
: case OP_SET_ULESSEQ
:
23594 case OP_SET_SMOREEQ
: case OP_SET_UMOREEQ
:
23595 ins
->template_id
= TEMPLATE_SET
;
23598 next
= x86_deposit(state
, ins
);
23602 next
= x86_extract(state
, ins
);
23604 /* Unhandled instructions */
23607 internal_error(state
, ins
, "unhandled ins: %d %s",
23608 ins
->op
, tops(ins
->op
));
23614 static long next_label(struct compile_state
*state
)
23616 static long label_counter
= 1000;
23617 return ++label_counter
;
23619 static void generate_local_labels(struct compile_state
*state
)
23621 struct triple
*first
, *label
;
23622 first
= state
->first
;
23625 if ((label
->op
== OP_LABEL
) ||
23626 (label
->op
== OP_SDECL
)) {
23628 label
->u
.cval
= next_label(state
);
23634 label
= label
->next
;
23635 } while(label
!= first
);
23638 static int check_reg(struct compile_state
*state
,
23639 struct triple
*triple
, int classes
)
23643 reg
= ID_REG(triple
->id
);
23644 if (reg
== REG_UNSET
) {
23645 internal_error(state
, triple
, "register not set");
23647 mask
= arch_reg_regcm(state
, reg
);
23648 if (!(classes
& mask
)) {
23649 internal_error(state
, triple
, "reg %d in wrong class",
23657 #error "Registers have renumberd fix arch_reg_str"
23659 static const char *arch_regs
[] = {
23663 "%al", "%bl", "%cl", "%dl", "%ah", "%bh", "%ch", "%dh",
23664 "%ax", "%bx", "%cx", "%dx", "%si", "%di", "%bp", "%sp",
23665 "%eax", "%ebx", "%ecx", "%edx", "%esi", "%edi", "%ebp", "%esp",
23668 "%mm0", "%mm1", "%mm2", "%mm3", "%mm4", "%mm5", "%mm6", "%mm7",
23669 "%xmm0", "%xmm1", "%xmm2", "%xmm3",
23670 "%xmm4", "%xmm5", "%xmm6", "%xmm7",
23672 static const char *arch_reg_str(int reg
)
23674 if (!((reg
>= REG_EFLAGS
) && (reg
<= REG_XMM7
))) {
23677 return arch_regs
[reg
];
23680 static const char *reg(struct compile_state
*state
, struct triple
*triple
,
23684 reg
= check_reg(state
, triple
, classes
);
23685 return arch_reg_str(reg
);
23688 static int arch_reg_size(int reg
)
23692 if (reg
== REG_EFLAGS
) {
23695 else if ((reg
>= REG_AL
) && (reg
<= REG_DH
)) {
23698 else if ((reg
>= REG_AX
) && (reg
<= REG_SP
)) {
23701 else if ((reg
>= REG_EAX
) && (reg
<= REG_ESP
)) {
23704 else if (reg
== REG_EDXEAX
) {
23707 else if (reg
== REG_DXAX
) {
23710 else if ((reg
>= REG_MMX0
) && (reg
<= REG_MMX7
)) {
23713 else if ((reg
>= REG_XMM0
) && (reg
<= REG_XMM7
)) {
23719 static int reg_size(struct compile_state
*state
, struct triple
*ins
)
23722 reg
= ID_REG(ins
->id
);
23723 if (reg
== REG_UNSET
) {
23724 internal_error(state
, ins
, "register not set");
23726 return arch_reg_size(reg
);
23731 const char *type_suffix(struct compile_state
*state
, struct type
*type
)
23733 const char *suffix
;
23734 switch(size_of(state
, type
)) {
23735 case SIZEOF_I8
: suffix
= "b"; break;
23736 case SIZEOF_I16
: suffix
= "w"; break;
23737 case SIZEOF_I32
: suffix
= "l"; break;
23739 internal_error(state
, 0, "unknown suffix");
23746 static void print_const_val(
23747 struct compile_state
*state
, struct triple
*ins
, FILE *fp
)
23751 fprintf(fp
, " $%ld ",
23752 (long)(ins
->u
.cval
));
23755 if ((MISC(ins
, 0)->op
!= OP_SDECL
) &&
23756 (MISC(ins
, 0)->op
!= OP_LABEL
))
23758 internal_error(state
, ins
, "bad base for addrconst");
23760 if (MISC(ins
, 0)->u
.cval
<= 0) {
23761 internal_error(state
, ins
, "unlabeled constant");
23763 fprintf(fp
, " $L%s%lu+%lu ",
23764 state
->compiler
->label_prefix
,
23765 (unsigned long)(MISC(ins
, 0)->u
.cval
),
23766 (unsigned long)(ins
->u
.cval
));
23769 internal_error(state
, ins
, "unknown constant type");
23774 static void print_const(struct compile_state
*state
,
23775 struct triple
*ins
, FILE *fp
)
23779 switch(ins
->type
->type
& TYPE_MASK
) {
23782 fprintf(fp
, ".byte 0x%02lx\n",
23783 (unsigned long)(ins
->u
.cval
));
23787 fprintf(fp
, ".short 0x%04lx\n",
23788 (unsigned long)(ins
->u
.cval
));
23795 fprintf(fp
, ".int %lu\n",
23796 (unsigned long)(ins
->u
.cval
));
23799 fprintf(state
->errout
, "type: ");
23800 name_of(state
->errout
, ins
->type
);
23801 fprintf(state
->errout
, "\n");
23802 internal_error(state
, ins
, "Unknown constant type. Val: %lu",
23803 (unsigned long)(ins
->u
.cval
));
23808 if ((MISC(ins
, 0)->op
!= OP_SDECL
) &&
23809 (MISC(ins
, 0)->op
!= OP_LABEL
)) {
23810 internal_error(state
, ins
, "bad base for addrconst");
23812 if (MISC(ins
, 0)->u
.cval
<= 0) {
23813 internal_error(state
, ins
, "unlabeled constant");
23815 fprintf(fp
, ".int L%s%lu+%lu\n",
23816 state
->compiler
->label_prefix
,
23817 (unsigned long)(MISC(ins
, 0)->u
.cval
),
23818 (unsigned long)(ins
->u
.cval
));
23822 unsigned char *blob
;
23824 size
= size_of_in_bytes(state
, ins
->type
);
23825 blob
= ins
->u
.blob
;
23826 for(i
= 0; i
< size
; i
++) {
23827 fprintf(fp
, ".byte 0x%02x\n",
23833 internal_error(state
, ins
, "Unknown constant type");
23838 #define TEXT_SECTION ".rom.text"
23839 #define DATA_SECTION ".rom.data"
23841 static long get_const_pool_ref(
23842 struct compile_state
*state
, struct triple
*ins
, size_t size
, FILE *fp
)
23846 ref
= next_label(state
);
23847 fprintf(fp
, ".section \"" DATA_SECTION
"\"\n");
23848 fprintf(fp
, ".balign %ld\n", (long int)align_of_in_bytes(state
, ins
->type
));
23849 fprintf(fp
, "L%s%lu:\n", state
->compiler
->label_prefix
, ref
);
23850 print_const(state
, ins
, fp
);
23851 fill_bytes
= bits_to_bytes(size
- size_of(state
, ins
->type
));
23853 fprintf(fp
, ".fill %ld, 1, 0\n", (long int)fill_bytes
);
23855 fprintf(fp
, ".section \"" TEXT_SECTION
"\"\n");
23859 static long get_mask_pool_ref(
23860 struct compile_state
*state
, struct triple
*ins
, unsigned long mask
, FILE *fp
)
23863 if (mask
== 0xff) {
23866 else if (mask
== 0xffff) {
23871 internal_error(state
, ins
, "unhandled mask value");
23876 static void print_binary_op(struct compile_state
*state
,
23877 const char *op
, struct triple
*ins
, FILE *fp
)
23880 mask
= REGCM_GPR32
| REGCM_GPR16
| REGCM_GPR8_LO
;
23881 if (ID_REG(RHS(ins
, 0)->id
) != ID_REG(ins
->id
)) {
23882 internal_error(state
, ins
, "invalid register assignment");
23884 if (is_const(RHS(ins
, 1))) {
23885 fprintf(fp
, "\t%s ", op
);
23886 print_const_val(state
, RHS(ins
, 1), fp
);
23887 fprintf(fp
, ", %s\n",
23888 reg(state
, RHS(ins
, 0), mask
));
23891 unsigned lmask
, rmask
;
23893 lreg
= check_reg(state
, RHS(ins
, 0), mask
);
23894 rreg
= check_reg(state
, RHS(ins
, 1), mask
);
23895 lmask
= arch_reg_regcm(state
, lreg
);
23896 rmask
= arch_reg_regcm(state
, rreg
);
23897 mask
= lmask
& rmask
;
23898 fprintf(fp
, "\t%s %s, %s\n",
23900 reg(state
, RHS(ins
, 1), mask
),
23901 reg(state
, RHS(ins
, 0), mask
));
23904 static void print_unary_op(struct compile_state
*state
,
23905 const char *op
, struct triple
*ins
, FILE *fp
)
23908 mask
= REGCM_GPR32
| REGCM_GPR16
| REGCM_GPR8_LO
;
23909 fprintf(fp
, "\t%s %s\n",
23911 reg(state
, RHS(ins
, 0), mask
));
23914 static void print_op_shift(struct compile_state
*state
,
23915 const char *op
, struct triple
*ins
, FILE *fp
)
23918 mask
= REGCM_GPR32
| REGCM_GPR16
| REGCM_GPR8_LO
;
23919 if (ID_REG(RHS(ins
, 0)->id
) != ID_REG(ins
->id
)) {
23920 internal_error(state
, ins
, "invalid register assignment");
23922 if (is_const(RHS(ins
, 1))) {
23923 fprintf(fp
, "\t%s ", op
);
23924 print_const_val(state
, RHS(ins
, 1), fp
);
23925 fprintf(fp
, ", %s\n",
23926 reg(state
, RHS(ins
, 0), mask
));
23929 fprintf(fp
, "\t%s %s, %s\n",
23931 reg(state
, RHS(ins
, 1), REGCM_GPR8_LO
),
23932 reg(state
, RHS(ins
, 0), mask
));
23936 static void print_op_in(struct compile_state
*state
, struct triple
*ins
, FILE *fp
)
23943 case OP_INB
: op
= "inb", mask
= REGCM_GPR8_LO
; break;
23944 case OP_INW
: op
= "inw", mask
= REGCM_GPR16
; break;
23945 case OP_INL
: op
= "inl", mask
= REGCM_GPR32
; break;
23947 internal_error(state
, ins
, "not an in operation");
23951 dreg
= check_reg(state
, ins
, mask
);
23952 if (!reg_is_reg(state
, dreg
, REG_EAX
)) {
23953 internal_error(state
, ins
, "dst != %%eax");
23955 if (is_const(RHS(ins
, 0))) {
23956 fprintf(fp
, "\t%s ", op
);
23957 print_const_val(state
, RHS(ins
, 0), fp
);
23958 fprintf(fp
, ", %s\n",
23959 reg(state
, ins
, mask
));
23963 addr_reg
= check_reg(state
, RHS(ins
, 0), REGCM_GPR16
);
23964 if (!reg_is_reg(state
, addr_reg
, REG_DX
)) {
23965 internal_error(state
, ins
, "src != %%dx");
23967 fprintf(fp
, "\t%s %s, %s\n",
23969 reg(state
, RHS(ins
, 0), REGCM_GPR16
),
23970 reg(state
, ins
, mask
));
23974 static void print_op_out(struct compile_state
*state
, struct triple
*ins
, FILE *fp
)
23981 case OP_OUTB
: op
= "outb", mask
= REGCM_GPR8_LO
; break;
23982 case OP_OUTW
: op
= "outw", mask
= REGCM_GPR16
; break;
23983 case OP_OUTL
: op
= "outl", mask
= REGCM_GPR32
; break;
23985 internal_error(state
, ins
, "not an out operation");
23989 lreg
= check_reg(state
, RHS(ins
, 0), mask
);
23990 if (!reg_is_reg(state
, lreg
, REG_EAX
)) {
23991 internal_error(state
, ins
, "src != %%eax");
23993 if (is_const(RHS(ins
, 1))) {
23994 fprintf(fp
, "\t%s %s,",
23995 op
, reg(state
, RHS(ins
, 0), mask
));
23996 print_const_val(state
, RHS(ins
, 1), fp
);
24001 addr_reg
= check_reg(state
, RHS(ins
, 1), REGCM_GPR16
);
24002 if (!reg_is_reg(state
, addr_reg
, REG_DX
)) {
24003 internal_error(state
, ins
, "dst != %%dx");
24005 fprintf(fp
, "\t%s %s, %s\n",
24007 reg(state
, RHS(ins
, 0), mask
),
24008 reg(state
, RHS(ins
, 1), REGCM_GPR16
));
24012 static void print_op_move(struct compile_state
*state
,
24013 struct triple
*ins
, FILE *fp
)
24015 /* op_move is complex because there are many types
24016 * of registers we can move between.
24017 * Because OP_COPY will be introduced in arbitrary locations
24018 * OP_COPY must not affect flags.
24019 * OP_CONVERT can change the flags and it is the only operation
24020 * where it is expected the types in the registers can change.
24022 int omit_copy
= 1; /* Is it o.k. to omit a noop copy? */
24023 struct triple
*dst
, *src
;
24024 if (state
->arch
->features
& X86_NOOP_COPY
) {
24027 if ((ins
->op
== OP_COPY
) || (ins
->op
== OP_CONVERT
)) {
24032 internal_error(state
, ins
, "unknown move operation");
24035 if (reg_size(state
, dst
) < size_of(state
, dst
->type
)) {
24036 internal_error(state
, ins
, "Invalid destination register");
24038 if (!equiv_types(src
->type
, dst
->type
) && (dst
->op
== OP_COPY
)) {
24039 fprintf(state
->errout
, "src type: ");
24040 name_of(state
->errout
, src
->type
);
24041 fprintf(state
->errout
, "\n");
24042 fprintf(state
->errout
, "dst type: ");
24043 name_of(state
->errout
, dst
->type
);
24044 fprintf(state
->errout
, "\n");
24045 internal_error(state
, ins
, "Type mismatch for OP_COPY");
24048 if (!is_const(src
)) {
24049 int src_reg
, dst_reg
;
24050 int src_regcm
, dst_regcm
;
24051 src_reg
= ID_REG(src
->id
);
24052 dst_reg
= ID_REG(dst
->id
);
24053 src_regcm
= arch_reg_regcm(state
, src_reg
);
24054 dst_regcm
= arch_reg_regcm(state
, dst_reg
);
24055 /* If the class is the same just move the register */
24056 if (src_regcm
& dst_regcm
&
24057 (REGCM_GPR8_LO
| REGCM_GPR16
| REGCM_GPR32
)) {
24058 if ((src_reg
!= dst_reg
) || !omit_copy
) {
24059 fprintf(fp
, "\tmov %s, %s\n",
24060 reg(state
, src
, src_regcm
),
24061 reg(state
, dst
, dst_regcm
));
24064 /* Move 32bit to 16bit */
24065 else if ((src_regcm
& REGCM_GPR32
) &&
24066 (dst_regcm
& REGCM_GPR16
)) {
24067 src_reg
= (src_reg
- REGC_GPR32_FIRST
) + REGC_GPR16_FIRST
;
24068 if ((src_reg
!= dst_reg
) || !omit_copy
) {
24069 fprintf(fp
, "\tmovw %s, %s\n",
24070 arch_reg_str(src_reg
),
24071 arch_reg_str(dst_reg
));
24074 /* Move from 32bit gprs to 16bit gprs */
24075 else if ((src_regcm
& REGCM_GPR32
) &&
24076 (dst_regcm
& REGCM_GPR16
)) {
24077 dst_reg
= (dst_reg
- REGC_GPR16_FIRST
) + REGC_GPR32_FIRST
;
24078 if ((src_reg
!= dst_reg
) || !omit_copy
) {
24079 fprintf(fp
, "\tmov %s, %s\n",
24080 arch_reg_str(src_reg
),
24081 arch_reg_str(dst_reg
));
24084 /* Move 32bit to 8bit */
24085 else if ((src_regcm
& REGCM_GPR32_8
) &&
24086 (dst_regcm
& REGCM_GPR8_LO
))
24088 src_reg
= (src_reg
- REGC_GPR32_8_FIRST
) + REGC_GPR8_FIRST
;
24089 if ((src_reg
!= dst_reg
) || !omit_copy
) {
24090 fprintf(fp
, "\tmovb %s, %s\n",
24091 arch_reg_str(src_reg
),
24092 arch_reg_str(dst_reg
));
24095 /* Move 16bit to 8bit */
24096 else if ((src_regcm
& REGCM_GPR16_8
) &&
24097 (dst_regcm
& REGCM_GPR8_LO
))
24099 src_reg
= (src_reg
- REGC_GPR16_8_FIRST
) + REGC_GPR8_FIRST
;
24100 if ((src_reg
!= dst_reg
) || !omit_copy
) {
24101 fprintf(fp
, "\tmovb %s, %s\n",
24102 arch_reg_str(src_reg
),
24103 arch_reg_str(dst_reg
));
24106 /* Move 8/16bit to 16/32bit */
24107 else if ((src_regcm
& (REGCM_GPR8_LO
| REGCM_GPR16
)) &&
24108 (dst_regcm
& (REGCM_GPR16
| REGCM_GPR32
))) {
24110 op
= is_signed(src
->type
)? "movsx": "movzx";
24111 fprintf(fp
, "\t%s %s, %s\n",
24113 reg(state
, src
, src_regcm
),
24114 reg(state
, dst
, dst_regcm
));
24116 /* Move between sse registers */
24117 else if ((src_regcm
& dst_regcm
& REGCM_XMM
)) {
24118 if ((src_reg
!= dst_reg
) || !omit_copy
) {
24119 fprintf(fp
, "\tmovdqa %s, %s\n",
24120 reg(state
, src
, src_regcm
),
24121 reg(state
, dst
, dst_regcm
));
24124 /* Move between mmx registers */
24125 else if ((src_regcm
& dst_regcm
& REGCM_MMX
)) {
24126 if ((src_reg
!= dst_reg
) || !omit_copy
) {
24127 fprintf(fp
, "\tmovq %s, %s\n",
24128 reg(state
, src
, src_regcm
),
24129 reg(state
, dst
, dst_regcm
));
24132 /* Move from sse to mmx registers */
24133 else if ((src_regcm
& REGCM_XMM
) && (dst_regcm
& REGCM_MMX
)) {
24134 fprintf(fp
, "\tmovdq2q %s, %s\n",
24135 reg(state
, src
, src_regcm
),
24136 reg(state
, dst
, dst_regcm
));
24138 /* Move from mmx to sse registers */
24139 else if ((src_regcm
& REGCM_MMX
) && (dst_regcm
& REGCM_XMM
)) {
24140 fprintf(fp
, "\tmovq2dq %s, %s\n",
24141 reg(state
, src
, src_regcm
),
24142 reg(state
, dst
, dst_regcm
));
24144 /* Move between 32bit gprs & mmx/sse registers */
24145 else if ((src_regcm
& (REGCM_GPR32
| REGCM_MMX
| REGCM_XMM
)) &&
24146 (dst_regcm
& (REGCM_GPR32
| REGCM_MMX
| REGCM_XMM
))) {
24147 fprintf(fp
, "\tmovd %s, %s\n",
24148 reg(state
, src
, src_regcm
),
24149 reg(state
, dst
, dst_regcm
));
24151 /* Move from 16bit gprs & mmx/sse registers */
24152 else if ((src_regcm
& REGCM_GPR16
) &&
24153 (dst_regcm
& (REGCM_MMX
| REGCM_XMM
))) {
24156 op
= is_signed(src
->type
)? "movsx":"movzx";
24157 mid_reg
= (src_reg
- REGC_GPR16_FIRST
) + REGC_GPR32_FIRST
;
24158 fprintf(fp
, "\t%s %s, %s\n\tmovd %s, %s\n",
24160 arch_reg_str(src_reg
),
24161 arch_reg_str(mid_reg
),
24162 arch_reg_str(mid_reg
),
24163 arch_reg_str(dst_reg
));
24165 /* Move from mmx/sse registers to 16bit gprs */
24166 else if ((src_regcm
& (REGCM_MMX
| REGCM_XMM
)) &&
24167 (dst_regcm
& REGCM_GPR16
)) {
24168 dst_reg
= (dst_reg
- REGC_GPR16_FIRST
) + REGC_GPR32_FIRST
;
24169 fprintf(fp
, "\tmovd %s, %s\n",
24170 arch_reg_str(src_reg
),
24171 arch_reg_str(dst_reg
));
24173 /* Move from gpr to 64bit dividend */
24174 else if ((src_regcm
& (REGCM_GPR32
| REGCM_GPR16
| REGCM_GPR8_LO
)) &&
24175 (dst_regcm
& REGCM_DIVIDEND64
)) {
24176 const char *extend
;
24177 extend
= is_signed(src
->type
)? "cltd":"movl $0, %edx";
24178 fprintf(fp
, "\tmov %s, %%eax\n\t%s\n",
24179 arch_reg_str(src_reg
),
24182 /* Move from 64bit gpr to gpr */
24183 else if ((src_regcm
& REGCM_DIVIDEND64
) &&
24184 (dst_regcm
& (REGCM_GPR32
| REGCM_GPR16
| REGCM_GPR8_LO
))) {
24185 if (dst_regcm
& REGCM_GPR32
) {
24188 else if (dst_regcm
& REGCM_GPR16
) {
24191 else if (dst_regcm
& REGCM_GPR8_LO
) {
24194 fprintf(fp
, "\tmov %s, %s\n",
24195 arch_reg_str(src_reg
),
24196 arch_reg_str(dst_reg
));
24198 /* Move from mmx/sse registers to 64bit gpr */
24199 else if ((src_regcm
& (REGCM_MMX
| REGCM_XMM
)) &&
24200 (dst_regcm
& REGCM_DIVIDEND64
)) {
24201 const char *extend
;
24202 extend
= is_signed(src
->type
)? "cltd": "movl $0, %edx";
24203 fprintf(fp
, "\tmovd %s, %%eax\n\t%s\n",
24204 arch_reg_str(src_reg
),
24207 /* Move from 64bit gpr to mmx/sse register */
24208 else if ((src_regcm
& REGCM_DIVIDEND64
) &&
24209 (dst_regcm
& (REGCM_XMM
| REGCM_MMX
))) {
24210 fprintf(fp
, "\tmovd %%eax, %s\n",
24211 arch_reg_str(dst_reg
));
24213 #if X86_4_8BIT_GPRS
24214 /* Move from 8bit gprs to mmx/sse registers */
24215 else if ((src_regcm
& REGCM_GPR8_LO
) && (src_reg
<= REG_DL
) &&
24216 (dst_regcm
& (REGCM_MMX
| REGCM_XMM
))) {
24219 op
= is_signed(src
->type
)? "movsx":"movzx";
24220 mid_reg
= (src_reg
- REGC_GPR8_FIRST
) + REGC_GPR32_FIRST
;
24221 fprintf(fp
, "\t%s %s, %s\n\tmovd %s, %s\n",
24223 reg(state
, src
, src_regcm
),
24224 arch_reg_str(mid_reg
),
24225 arch_reg_str(mid_reg
),
24226 reg(state
, dst
, dst_regcm
));
24228 /* Move from mmx/sse registers and 8bit gprs */
24229 else if ((src_regcm
& (REGCM_MMX
| REGCM_XMM
)) &&
24230 (dst_regcm
& REGCM_GPR8_LO
) && (dst_reg
<= REG_DL
)) {
24232 mid_reg
= (dst_reg
- REGC_GPR8_FIRST
) + REGC_GPR32_FIRST
;
24233 fprintf(fp
, "\tmovd %s, %s\n",
24234 reg(state
, src
, src_regcm
),
24235 arch_reg_str(mid_reg
));
24237 /* Move from 32bit gprs to 8bit gprs */
24238 else if ((src_regcm
& REGCM_GPR32
) &&
24239 (dst_regcm
& REGCM_GPR8_LO
)) {
24240 dst_reg
= (dst_reg
- REGC_GPR8_FIRST
) + REGC_GPR32_FIRST
;
24241 if ((src_reg
!= dst_reg
) || !omit_copy
) {
24242 fprintf(fp
, "\tmov %s, %s\n",
24243 arch_reg_str(src_reg
),
24244 arch_reg_str(dst_reg
));
24247 /* Move from 16bit gprs to 8bit gprs */
24248 else if ((src_regcm
& REGCM_GPR16
) &&
24249 (dst_regcm
& REGCM_GPR8_LO
)) {
24250 dst_reg
= (dst_reg
- REGC_GPR8_FIRST
) + REGC_GPR16_FIRST
;
24251 if ((src_reg
!= dst_reg
) || !omit_copy
) {
24252 fprintf(fp
, "\tmov %s, %s\n",
24253 arch_reg_str(src_reg
),
24254 arch_reg_str(dst_reg
));
24257 #endif /* X86_4_8BIT_GPRS */
24258 /* Move from %eax:%edx to %eax:%edx */
24259 else if ((src_regcm
& REGCM_DIVIDEND64
) &&
24260 (dst_regcm
& REGCM_DIVIDEND64
) &&
24261 (src_reg
== dst_reg
)) {
24263 fprintf(fp
, "\t/*mov %s, %s*/\n",
24264 arch_reg_str(src_reg
),
24265 arch_reg_str(dst_reg
));
24269 if ((src_regcm
& ~REGCM_FLAGS
) == 0) {
24270 internal_error(state
, ins
, "attempt to copy from %%eflags!");
24272 internal_error(state
, ins
, "unknown copy type");
24279 dst_size
= size_of(state
, dst
->type
);
24280 dst_reg
= ID_REG(dst
->id
);
24281 dst_regcm
= arch_reg_regcm(state
, dst_reg
);
24282 if (dst_regcm
& (REGCM_GPR32
| REGCM_GPR16
| REGCM_GPR8_LO
)) {
24283 fprintf(fp
, "\tmov ");
24284 print_const_val(state
, src
, fp
);
24285 fprintf(fp
, ", %s\n",
24286 reg(state
, dst
, REGCM_GPR32
| REGCM_GPR16
| REGCM_GPR8_LO
));
24288 else if (dst_regcm
& REGCM_DIVIDEND64
) {
24289 if (dst_size
> SIZEOF_I32
) {
24290 internal_error(state
, ins
, "%dbit constant...", dst_size
);
24292 fprintf(fp
, "\tmov $0, %%edx\n");
24293 fprintf(fp
, "\tmov ");
24294 print_const_val(state
, src
, fp
);
24295 fprintf(fp
, ", %%eax\n");
24297 else if (dst_regcm
& REGCM_DIVIDEND32
) {
24298 if (dst_size
> SIZEOF_I16
) {
24299 internal_error(state
, ins
, "%dbit constant...", dst_size
);
24301 fprintf(fp
, "\tmov $0, %%dx\n");
24302 fprintf(fp
, "\tmov ");
24303 print_const_val(state
, src
, fp
);
24304 fprintf(fp
, ", %%ax");
24306 else if (dst_regcm
& (REGCM_XMM
| REGCM_MMX
)) {
24308 if (dst_size
> SIZEOF_I32
) {
24309 internal_error(state
, ins
, "%d bit constant...", dst_size
);
24311 ref
= get_const_pool_ref(state
, src
, SIZEOF_I32
, fp
);
24312 fprintf(fp
, "\tmovd L%s%lu, %s\n",
24313 state
->compiler
->label_prefix
, ref
,
24314 reg(state
, dst
, (REGCM_XMM
| REGCM_MMX
)));
24317 internal_error(state
, ins
, "unknown copy immediate type");
24320 /* Leave now if this is not a type conversion */
24321 if (ins
->op
!= OP_CONVERT
) {
24324 /* Now make certain I have not logically overflowed the destination */
24325 if ((size_of(state
, src
->type
) > size_of(state
, dst
->type
)) &&
24326 (size_of(state
, dst
->type
) < reg_size(state
, dst
)))
24328 unsigned long mask
;
24331 if (size_of(state
, dst
->type
) >= 32) {
24332 fprintf(state
->errout
, "dst type: ");
24333 name_of(state
->errout
, dst
->type
);
24334 fprintf(state
->errout
, "\n");
24335 internal_error(state
, dst
, "unhandled dst type size");
24338 mask
<<= size_of(state
, dst
->type
);
24341 dst_reg
= ID_REG(dst
->id
);
24342 dst_regcm
= arch_reg_regcm(state
, dst_reg
);
24344 if (dst_regcm
& (REGCM_GPR32
| REGCM_GPR16
| REGCM_GPR8_LO
)) {
24345 fprintf(fp
, "\tand $0x%lx, %s\n",
24346 mask
, reg(state
, dst
, REGCM_GPR32
| REGCM_GPR16
| REGCM_GPR8_LO
));
24348 else if (dst_regcm
& REGCM_MMX
) {
24350 ref
= get_mask_pool_ref(state
, dst
, mask
, fp
);
24351 fprintf(fp
, "\tpand L%s%lu, %s\n",
24352 state
->compiler
->label_prefix
, ref
,
24353 reg(state
, dst
, REGCM_MMX
));
24355 else if (dst_regcm
& REGCM_XMM
) {
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_XMM
));
24363 fprintf(state
->errout
, "dst type: ");
24364 name_of(state
->errout
, dst
->type
);
24365 fprintf(state
->errout
, "\n");
24366 fprintf(state
->errout
, "dst: %s\n", reg(state
, dst
, REGCM_ALL
));
24367 internal_error(state
, dst
, "failed to trunc value: mask %lx", mask
);
24370 /* Make certain I am properly sign extended */
24371 if ((size_of(state
, src
->type
) < size_of(state
, dst
->type
)) &&
24372 (is_signed(src
->type
)))
24374 int reg_bits
, shift_bits
;
24378 reg_bits
= reg_size(state
, dst
);
24379 if (reg_bits
> 32) {
24382 shift_bits
= reg_bits
- size_of(state
, src
->type
);
24383 dst_reg
= ID_REG(dst
->id
);
24384 dst_regcm
= arch_reg_regcm(state
, dst_reg
);
24386 if (shift_bits
< 0) {
24387 internal_error(state
, dst
, "negative shift?");
24390 if (dst_regcm
& (REGCM_GPR32
| REGCM_GPR16
| REGCM_GPR8_LO
)) {
24391 fprintf(fp
, "\tshl $%d, %s\n",
24393 reg(state
, dst
, REGCM_GPR32
| REGCM_GPR16
| REGCM_GPR8_LO
));
24394 fprintf(fp
, "\tsar $%d, %s\n",
24396 reg(state
, dst
, REGCM_GPR32
| REGCM_GPR16
| REGCM_GPR8_LO
));
24398 else if (dst_regcm
& (REGCM_MMX
| REGCM_XMM
)) {
24399 fprintf(fp
, "\tpslld $%d, %s\n",
24401 reg(state
, dst
, REGCM_MMX
| REGCM_XMM
));
24402 fprintf(fp
, "\tpsrad $%d, %s\n",
24404 reg(state
, dst
, REGCM_MMX
| REGCM_XMM
));
24407 fprintf(state
->errout
, "dst type: ");
24408 name_of(state
->errout
, dst
->type
);
24409 fprintf(state
->errout
, "\n");
24410 fprintf(state
->errout
, "dst: %s\n", reg(state
, dst
, REGCM_ALL
));
24411 internal_error(state
, dst
, "failed to signed extend value");
24416 static void print_op_load(struct compile_state
*state
,
24417 struct triple
*ins
, FILE *fp
)
24419 struct triple
*dst
, *src
;
24423 if (is_const(src
) || is_const(dst
)) {
24424 internal_error(state
, ins
, "unknown load operation");
24426 switch(ins
->type
->type
& TYPE_MASK
) {
24427 case TYPE_CHAR
: op
= "movsbl"; break;
24428 case TYPE_UCHAR
: op
= "movzbl"; break;
24429 case TYPE_SHORT
: op
= "movswl"; break;
24430 case TYPE_USHORT
: op
= "movzwl"; break;
24431 case TYPE_INT
: case TYPE_UINT
:
24432 case TYPE_LONG
: case TYPE_ULONG
:
24437 internal_error(state
, ins
, "unknown type in load");
24438 op
= "<invalid opcode>";
24441 fprintf(fp
, "\t%s (%s), %s\n",
24443 reg(state
, src
, REGCM_GPR32
),
24444 reg(state
, dst
, REGCM_GPR32
));
24448 static void print_op_store(struct compile_state
*state
,
24449 struct triple
*ins
, FILE *fp
)
24451 struct triple
*dst
, *src
;
24454 if (is_const(src
) && (src
->op
== OP_INTCONST
)) {
24456 value
= (long_t
)(src
->u
.cval
);
24457 fprintf(fp
, "\tmov%s $%ld, (%s)\n",
24458 type_suffix(state
, src
->type
),
24460 reg(state
, dst
, REGCM_GPR32
));
24462 else if (is_const(dst
) && (dst
->op
== OP_INTCONST
)) {
24463 fprintf(fp
, "\tmov%s %s, 0x%08lx\n",
24464 type_suffix(state
, src
->type
),
24465 reg(state
, src
, REGCM_GPR8_LO
| REGCM_GPR16
| REGCM_GPR32
),
24466 (unsigned long)(dst
->u
.cval
));
24469 if (is_const(src
) || is_const(dst
)) {
24470 internal_error(state
, ins
, "unknown store operation");
24472 fprintf(fp
, "\tmov%s %s, (%s)\n",
24473 type_suffix(state
, src
->type
),
24474 reg(state
, src
, REGCM_GPR8_LO
| REGCM_GPR16
| REGCM_GPR32
),
24475 reg(state
, dst
, REGCM_GPR32
));
24481 static void print_op_smul(struct compile_state
*state
,
24482 struct triple
*ins
, FILE *fp
)
24484 if (!is_const(RHS(ins
, 1))) {
24485 fprintf(fp
, "\timul %s, %s\n",
24486 reg(state
, RHS(ins
, 1), REGCM_GPR32
),
24487 reg(state
, RHS(ins
, 0), REGCM_GPR32
));
24490 fprintf(fp
, "\timul ");
24491 print_const_val(state
, RHS(ins
, 1), fp
);
24492 fprintf(fp
, ", %s\n", reg(state
, RHS(ins
, 0), REGCM_GPR32
));
24496 static void print_op_cmp(struct compile_state
*state
,
24497 struct triple
*ins
, FILE *fp
)
24501 mask
= REGCM_GPR32
| REGCM_GPR16
| REGCM_GPR8_LO
;
24502 dreg
= check_reg(state
, ins
, REGCM_FLAGS
);
24503 if (!reg_is_reg(state
, dreg
, REG_EFLAGS
)) {
24504 internal_error(state
, ins
, "bad dest register for cmp");
24506 if (is_const(RHS(ins
, 1))) {
24507 fprintf(fp
, "\tcmp ");
24508 print_const_val(state
, RHS(ins
, 1), fp
);
24509 fprintf(fp
, ", %s\n", reg(state
, RHS(ins
, 0), mask
));
24512 unsigned lmask
, rmask
;
24514 lreg
= check_reg(state
, RHS(ins
, 0), mask
);
24515 rreg
= check_reg(state
, RHS(ins
, 1), mask
);
24516 lmask
= arch_reg_regcm(state
, lreg
);
24517 rmask
= arch_reg_regcm(state
, rreg
);
24518 mask
= lmask
& rmask
;
24519 fprintf(fp
, "\tcmp %s, %s\n",
24520 reg(state
, RHS(ins
, 1), mask
),
24521 reg(state
, RHS(ins
, 0), mask
));
24525 static void print_op_test(struct compile_state
*state
,
24526 struct triple
*ins
, FILE *fp
)
24529 mask
= REGCM_GPR32
| REGCM_GPR16
| REGCM_GPR8_LO
;
24530 fprintf(fp
, "\ttest %s, %s\n",
24531 reg(state
, RHS(ins
, 0), mask
),
24532 reg(state
, RHS(ins
, 0), mask
));
24535 static void print_op_branch(struct compile_state
*state
,
24536 struct triple
*branch
, FILE *fp
)
24538 const char *bop
= "j";
24539 if ((branch
->op
== OP_JMP
) || (branch
->op
== OP_CALL
)) {
24540 if (branch
->rhs
!= 0) {
24541 internal_error(state
, branch
, "jmp with condition?");
24546 struct triple
*ptr
;
24547 if (branch
->rhs
!= 1) {
24548 internal_error(state
, branch
, "jmpcc without condition?");
24550 check_reg(state
, RHS(branch
, 0), REGCM_FLAGS
);
24551 if ((RHS(branch
, 0)->op
!= OP_CMP
) &&
24552 (RHS(branch
, 0)->op
!= OP_TEST
)) {
24553 internal_error(state
, branch
, "bad branch test");
24555 #if DEBUG_ROMCC_WARNINGS
24556 #warning "FIXME I have observed instructions between the test and branch instructions"
24558 ptr
= RHS(branch
, 0);
24559 for(ptr
= RHS(branch
, 0)->next
; ptr
!= branch
; ptr
= ptr
->next
) {
24560 if (ptr
->op
!= OP_COPY
) {
24561 internal_error(state
, branch
, "branch does not follow test");
24564 switch(branch
->op
) {
24565 case OP_JMP_EQ
: bop
= "jz"; break;
24566 case OP_JMP_NOTEQ
: bop
= "jnz"; break;
24567 case OP_JMP_SLESS
: bop
= "jl"; break;
24568 case OP_JMP_ULESS
: bop
= "jb"; break;
24569 case OP_JMP_SMORE
: bop
= "jg"; break;
24570 case OP_JMP_UMORE
: bop
= "ja"; break;
24571 case OP_JMP_SLESSEQ
: bop
= "jle"; break;
24572 case OP_JMP_ULESSEQ
: bop
= "jbe"; break;
24573 case OP_JMP_SMOREEQ
: bop
= "jge"; break;
24574 case OP_JMP_UMOREEQ
: bop
= "jae"; break;
24576 internal_error(state
, branch
, "Invalid branch op");
24582 if (branch
->op
== OP_CALL
) {
24583 fprintf(fp
, "\t/* call */\n");
24586 fprintf(fp
, "\t%s L%s%lu\n",
24588 state
->compiler
->label_prefix
,
24589 (unsigned long)(TARG(branch
, 0)->u
.cval
));
24592 static void print_op_ret(struct compile_state
*state
,
24593 struct triple
*branch
, FILE *fp
)
24595 fprintf(fp
, "\tjmp *%s\n",
24596 reg(state
, RHS(branch
, 0), REGCM_GPR32
));
24599 static void print_op_set(struct compile_state
*state
,
24600 struct triple
*set
, FILE *fp
)
24602 const char *sop
= "set";
24603 if (set
->rhs
!= 1) {
24604 internal_error(state
, set
, "setcc without condition?");
24606 check_reg(state
, RHS(set
, 0), REGCM_FLAGS
);
24607 if ((RHS(set
, 0)->op
!= OP_CMP
) &&
24608 (RHS(set
, 0)->op
!= OP_TEST
)) {
24609 internal_error(state
, set
, "bad set test");
24611 if (RHS(set
, 0)->next
!= set
) {
24612 internal_error(state
, set
, "set does not follow test");
24615 case OP_SET_EQ
: sop
= "setz"; break;
24616 case OP_SET_NOTEQ
: sop
= "setnz"; break;
24617 case OP_SET_SLESS
: sop
= "setl"; break;
24618 case OP_SET_ULESS
: sop
= "setb"; break;
24619 case OP_SET_SMORE
: sop
= "setg"; break;
24620 case OP_SET_UMORE
: sop
= "seta"; break;
24621 case OP_SET_SLESSEQ
: sop
= "setle"; break;
24622 case OP_SET_ULESSEQ
: sop
= "setbe"; break;
24623 case OP_SET_SMOREEQ
: sop
= "setge"; break;
24624 case OP_SET_UMOREEQ
: sop
= "setae"; break;
24626 internal_error(state
, set
, "Invalid set op");
24629 fprintf(fp
, "\t%s %s\n",
24630 sop
, reg(state
, set
, REGCM_GPR8_LO
));
24633 static void print_op_bit_scan(struct compile_state
*state
,
24634 struct triple
*ins
, FILE *fp
)
24638 case OP_BSF
: op
= "bsf"; break;
24639 case OP_BSR
: op
= "bsr"; break;
24641 internal_error(state
, ins
, "unknown bit scan");
24651 reg(state
, RHS(ins
, 0), REGCM_GPR32
),
24652 reg(state
, ins
, REGCM_GPR32
),
24653 reg(state
, ins
, REGCM_GPR32
));
24657 static void print_sdecl(struct compile_state
*state
,
24658 struct triple
*ins
, FILE *fp
)
24660 fprintf(fp
, ".section \"" DATA_SECTION
"\"\n");
24661 fprintf(fp
, ".balign %ld\n", (long int)align_of_in_bytes(state
, ins
->type
));
24662 fprintf(fp
, "L%s%lu:\n",
24663 state
->compiler
->label_prefix
, (unsigned long)(ins
->u
.cval
));
24664 print_const(state
, MISC(ins
, 0), fp
);
24665 fprintf(fp
, ".section \"" TEXT_SECTION
"\"\n");
24669 static void print_instruction(struct compile_state
*state
,
24670 struct triple
*ins
, FILE *fp
)
24672 /* Assumption: after I have exted the register allocator
24673 * everything is in a valid register.
24677 print_op_asm(state
, ins
, fp
);
24679 case OP_ADD
: print_binary_op(state
, "add", ins
, fp
); break;
24680 case OP_SUB
: print_binary_op(state
, "sub", ins
, fp
); break;
24681 case OP_AND
: print_binary_op(state
, "and", ins
, fp
); break;
24682 case OP_XOR
: print_binary_op(state
, "xor", ins
, fp
); break;
24683 case OP_OR
: print_binary_op(state
, "or", ins
, fp
); break;
24684 case OP_SL
: print_op_shift(state
, "shl", ins
, fp
); break;
24685 case OP_USR
: print_op_shift(state
, "shr", ins
, fp
); break;
24686 case OP_SSR
: print_op_shift(state
, "sar", ins
, fp
); break;
24687 case OP_POS
: break;
24688 case OP_NEG
: print_unary_op(state
, "neg", ins
, fp
); break;
24689 case OP_INVERT
: print_unary_op(state
, "not", ins
, fp
); break;
24694 /* Don't generate anything here for constants */
24696 /* Don't generate anything for variable declarations. */
24698 case OP_UNKNOWNVAL
:
24699 fprintf(fp
, " /* unknown %s */\n",
24700 reg(state
, ins
, REGCM_ALL
));
24703 print_sdecl(state
, ins
, fp
);
24707 print_op_move(state
, ins
, fp
);
24710 print_op_load(state
, ins
, fp
);
24713 print_op_store(state
, ins
, fp
);
24716 print_op_smul(state
, ins
, fp
);
24718 case OP_CMP
: print_op_cmp(state
, ins
, fp
); break;
24719 case OP_TEST
: print_op_test(state
, ins
, fp
); break;
24721 case OP_JMP_EQ
: case OP_JMP_NOTEQ
:
24722 case OP_JMP_SLESS
: case OP_JMP_ULESS
:
24723 case OP_JMP_SMORE
: case OP_JMP_UMORE
:
24724 case OP_JMP_SLESSEQ
: case OP_JMP_ULESSEQ
:
24725 case OP_JMP_SMOREEQ
: case OP_JMP_UMOREEQ
:
24727 print_op_branch(state
, ins
, fp
);
24730 print_op_ret(state
, ins
, fp
);
24732 case OP_SET_EQ
: case OP_SET_NOTEQ
:
24733 case OP_SET_SLESS
: case OP_SET_ULESS
:
24734 case OP_SET_SMORE
: case OP_SET_UMORE
:
24735 case OP_SET_SLESSEQ
: case OP_SET_ULESSEQ
:
24736 case OP_SET_SMOREEQ
: case OP_SET_UMOREEQ
:
24737 print_op_set(state
, ins
, fp
);
24739 case OP_INB
: case OP_INW
: case OP_INL
:
24740 print_op_in(state
, ins
, fp
);
24742 case OP_OUTB
: case OP_OUTW
: case OP_OUTL
:
24743 print_op_out(state
, ins
, fp
);
24747 print_op_bit_scan(state
, ins
, fp
);
24750 after_lhs(state
, ins
);
24751 fprintf(fp
, "\trdmsr\n");
24754 fprintf(fp
, "\twrmsr\n");
24757 fprintf(fp
, "\thlt\n");
24760 fprintf(fp
, "\tidiv %s\n", reg(state
, RHS(ins
, 1), REGCM_GPR32
));
24763 fprintf(fp
, "\tdiv %s\n", reg(state
, RHS(ins
, 1), REGCM_GPR32
));
24766 fprintf(fp
, "\tmul %s\n", reg(state
, RHS(ins
, 1), REGCM_GPR32
));
24772 fprintf(fp
, "L%s%lu:\n",
24773 state
->compiler
->label_prefix
, (unsigned long)(ins
->u
.cval
));
24776 /* Ignore adecls with no registers error otherwise */
24777 if (!noop_adecl(ins
)) {
24778 internal_error(state
, ins
, "adecl remains?");
24781 /* Ignore OP_PIECE */
24784 /* Operations that should never get here */
24785 case OP_SDIV
: case OP_UDIV
:
24786 case OP_SMOD
: case OP_UMOD
:
24787 case OP_LTRUE
: case OP_LFALSE
: case OP_EQ
: case OP_NOTEQ
:
24788 case OP_SLESS
: case OP_ULESS
: case OP_SMORE
: case OP_UMORE
:
24789 case OP_SLESSEQ
: case OP_ULESSEQ
: case OP_SMOREEQ
: case OP_UMOREEQ
:
24791 internal_error(state
, ins
, "unknown op: %d %s",
24792 ins
->op
, tops(ins
->op
));
24797 static void print_instructions(struct compile_state
*state
)
24799 struct triple
*first
, *ins
;
24800 int print_location
;
24801 struct occurance
*last_occurance
;
24803 int max_inline_depth
;
24804 max_inline_depth
= 0;
24805 print_location
= 1;
24806 last_occurance
= 0;
24807 fp
= state
->output
;
24808 /* Masks for common sizes */
24809 fprintf(fp
, ".section \"" DATA_SECTION
"\"\n");
24810 fprintf(fp
, ".balign 16\n");
24811 fprintf(fp
, "L%s1:\n", state
->compiler
->label_prefix
);
24812 fprintf(fp
, ".int 0xff, 0, 0, 0\n");
24813 fprintf(fp
, "L%s2:\n", state
->compiler
->label_prefix
);
24814 fprintf(fp
, ".int 0xffff, 0, 0, 0\n");
24815 fprintf(fp
, ".section \"" TEXT_SECTION
"\"\n");
24816 first
= state
->first
;
24819 if (print_location
&&
24820 last_occurance
!= ins
->occurance
) {
24821 if (!ins
->occurance
->parent
) {
24822 fprintf(fp
, "\t/* %s,%s:%d.%d */\n",
24823 ins
->occurance
->function
?ins
->occurance
->function
:"(null)",
24824 ins
->occurance
->filename
?ins
->occurance
->filename
:"(null)",
24825 ins
->occurance
->line
,
24826 ins
->occurance
->col
);
24829 struct occurance
*ptr
;
24831 fprintf(fp
, "\t/*\n");
24833 for(ptr
= ins
->occurance
; ptr
; ptr
= ptr
->parent
) {
24835 fprintf(fp
, "\t * %s,%s:%d.%d\n",
24841 fprintf(fp
, "\t */\n");
24842 if (inline_depth
> max_inline_depth
) {
24843 max_inline_depth
= inline_depth
;
24846 if (last_occurance
) {
24847 put_occurance(last_occurance
);
24849 get_occurance(ins
->occurance
);
24850 last_occurance
= ins
->occurance
;
24853 print_instruction(state
, ins
, fp
);
24855 } while(ins
!= first
);
24856 if (print_location
) {
24857 fprintf(fp
, "/* max inline depth %d */\n",
24862 static void generate_code(struct compile_state
*state
)
24864 generate_local_labels(state
);
24865 print_instructions(state
);
24869 static void print_preprocessed_tokens(struct compile_state
*state
)
24874 const char *filename
;
24875 fp
= state
->output
;
24879 struct file_state
*file
;
24881 const char *token_str
;
24883 if (tok
== TOK_EOF
) {
24886 tk
= eat(state
, tok
);
24888 tk
->ident
? tk
->ident
->name
:
24889 tk
->str_len
? tk
->val
.str
:
24892 file
= state
->file
;
24893 while(file
->macro
&& file
->prev
) {
24896 if (!file
->macro
&&
24897 ((file
->line
!= line
) || (file
->basename
!= filename
)))
24900 if ((file
->basename
== filename
) &&
24901 (line
< file
->line
)) {
24902 while(line
< file
->line
) {
24908 fprintf(fp
, "\n#line %d \"%s\"\n",
24909 file
->line
, file
->basename
);
24912 filename
= file
->basename
;
24913 col
= get_col(file
) - strlen(token_str
);
24914 for(i
= 0; i
< col
; i
++) {
24919 fprintf(fp
, "%s ", token_str
);
24921 if (state
->compiler
->debug
& DEBUG_TOKENS
) {
24922 loc(state
->dbgout
, state
, 0);
24923 fprintf(state
->dbgout
, "%s <- `%s'\n",
24924 tokens
[tok
], token_str
);
24929 static void compile(const char *filename
,
24930 struct compiler_state
*compiler
, struct arch_state
*arch
)
24933 struct compile_state state
;
24934 struct triple
*ptr
;
24935 struct filelist
*includes
= include_filelist
;
24936 memset(&state
, 0, sizeof(state
));
24937 state
.compiler
= compiler
;
24940 for(i
= 0; i
< sizeof(state
.token
)/sizeof(state
.token
[0]); i
++) {
24941 memset(&state
.token
[i
], 0, sizeof(state
.token
[i
]));
24942 state
.token
[i
].tok
= -1;
24944 /* Remember the output descriptors */
24945 state
.errout
= stderr
;
24946 state
.dbgout
= stdout
;
24947 /* Remember the output filename */
24948 if ((state
.compiler
->flags
& COMPILER_PP_ONLY
) && (strcmp("auto.inc",state
.compiler
->ofilename
) == 0)) {
24949 state
.output
= stdout
;
24951 state
.output
= fopen(state
.compiler
->ofilename
, "w");
24952 if (!state
.output
) {
24953 error(&state
, 0, "Cannot open output file %s\n",
24954 state
.compiler
->ofilename
);
24957 /* Make certain a good cleanup happens */
24958 exit_state
= &state
;
24959 atexit(exit_cleanup
);
24961 /* Prep the preprocessor */
24962 state
.if_depth
= 0;
24963 memset(state
.if_bytes
, 0, sizeof(state
.if_bytes
));
24964 /* register the C keywords */
24965 register_keywords(&state
);
24966 /* register the keywords the macro preprocessor knows */
24967 register_macro_keywords(&state
);
24968 /* generate some builtin macros */
24969 register_builtin_macros(&state
);
24970 /* Memorize where some special keywords are. */
24971 state
.i_switch
= lookup(&state
, "switch", 6);
24972 state
.i_case
= lookup(&state
, "case", 4);
24973 state
.i_continue
= lookup(&state
, "continue", 8);
24974 state
.i_break
= lookup(&state
, "break", 5);
24975 state
.i_default
= lookup(&state
, "default", 7);
24976 state
.i_return
= lookup(&state
, "return", 6);
24977 /* Memorize where predefined macros are. */
24978 state
.i___VA_ARGS__
= lookup(&state
, "__VA_ARGS__", 11);
24979 state
.i___FILE__
= lookup(&state
, "__FILE__", 8);
24980 state
.i___LINE__
= lookup(&state
, "__LINE__", 8);
24981 /* Memorize where predefined identifiers are. */
24982 state
.i___func__
= lookup(&state
, "__func__", 8);
24983 /* Memorize where some attribute keywords are. */
24984 state
.i_noinline
= lookup(&state
, "noinline", 8);
24985 state
.i_always_inline
= lookup(&state
, "always_inline", 13);
24986 state
.i_noreturn
= lookup(&state
, "noreturn", 8);
24987 state
.i_unused
= lookup(&state
, "unused", 6);
24988 state
.i_packed
= lookup(&state
, "packed", 6);
24990 /* Process the command line macros */
24991 process_cmdline_macros(&state
);
24993 /* Allocate beginning bounding labels for the function list */
24994 state
.first
= label(&state
);
24995 state
.first
->id
|= TRIPLE_FLAG_VOLATILE
;
24996 use_triple(state
.first
, state
.first
);
24997 ptr
= label(&state
);
24998 ptr
->id
|= TRIPLE_FLAG_VOLATILE
;
24999 use_triple(ptr
, ptr
);
25000 flatten(&state
, state
.first
, ptr
);
25002 /* Allocate a label for the pool of global variables */
25003 state
.global_pool
= label(&state
);
25004 state
.global_pool
->id
|= TRIPLE_FLAG_VOLATILE
;
25005 flatten(&state
, state
.first
, state
.global_pool
);
25007 /* Enter the globl definition scope */
25008 start_scope(&state
);
25009 register_builtins(&state
);
25011 compile_file(&state
, filename
, 1);
25014 compile_file(&state
, includes
->filename
, 1);
25015 includes
=includes
->next
;
25018 /* Stop if all we want is preprocessor output */
25019 if (state
.compiler
->flags
& COMPILER_PP_ONLY
) {
25020 print_preprocessed_tokens(&state
);
25026 /* Exit the global definition scope */
25029 /* Now that basic compilation has happened
25030 * optimize the intermediate code
25034 generate_code(&state
);
25035 if (state
.compiler
->debug
) {
25036 fprintf(state
.errout
, "done\n");
25041 static void version(FILE *fp
)
25043 fprintf(fp
, "romcc " VERSION
" released " RELEASE_DATE
"\n");
25046 static void usage(void)
25051 "\nUsage: romcc [options] <source>.c\n"
25052 "Compile a C source file generating a binary that does not implicilty use RAM\n"
25054 "-o <output file name>\n"
25055 "-f<option> Specify a generic compiler option\n"
25056 "-m<option> Specify a arch dependent option\n"
25057 "-- Specify this is the last option\n"
25058 "\nGeneric compiler options:\n"
25060 compiler_usage(fp
);
25062 "\nArchitecture compiler options:\n"
25070 static void arg_error(char *fmt
, ...)
25073 va_start(args
, fmt
);
25074 vfprintf(stderr
, fmt
, args
);
25080 int main(int argc
, char **argv
)
25082 const char *filename
;
25083 struct compiler_state compiler
;
25084 struct arch_state arch
;
25088 /* I don't want any surprises */
25089 setlocale(LC_ALL
, "C");
25091 init_compiler_state(&compiler
);
25092 init_arch_state(&arch
);
25096 if (!all_opts
&& (strcmp(argv
[1], "-o") == 0) && (argc
> 2)) {
25097 compiler
.ofilename
= argv
[2];
25101 else if (!all_opts
&& argv
[1][0] == '-') {
25104 if (strcmp(argv
[1], "--") == 0) {
25108 else if (strncmp(argv
[1], "-E", 2) == 0) {
25109 result
= compiler_encode_flag(&compiler
, argv
[1]);
25111 else if (strncmp(argv
[1], "-O", 2) == 0) {
25112 result
= compiler_encode_flag(&compiler
, argv
[1]);
25114 else if (strncmp(argv
[1], "-I", 2) == 0) {
25115 result
= compiler_encode_flag(&compiler
, argv
[1]);
25117 else if (strncmp(argv
[1], "-D", 2) == 0) {
25118 result
= compiler_encode_flag(&compiler
, argv
[1]);
25120 else if (strncmp(argv
[1], "-U", 2) == 0) {
25121 result
= compiler_encode_flag(&compiler
, argv
[1]);
25123 else if (strncmp(argv
[1], "--label-prefix=", 15) == 0) {
25124 result
= compiler_encode_flag(&compiler
, argv
[1]+2);
25126 else if (strncmp(argv
[1], "-f", 2) == 0) {
25127 result
= compiler_encode_flag(&compiler
, argv
[1]+2);
25129 else if (strncmp(argv
[1], "-m", 2) == 0) {
25130 result
= arch_encode_flag(&arch
, argv
[1]+2);
25132 else if (strncmp(argv
[1], "-c", 2) == 0) {
25135 else if (strncmp(argv
[1], "-S", 2) == 0) {
25138 else if (strncmp(argv
[1], "-include", 10) == 0) {
25139 struct filelist
*old_head
= include_filelist
;
25140 include_filelist
= malloc(sizeof(struct filelist
));
25141 if (!include_filelist
) {
25142 die("Out of memory.\n");
25146 include_filelist
->filename
= strdup(argv
[1]);
25147 include_filelist
->next
= old_head
;
25151 arg_error("Invalid option specified: %s\n",
25159 arg_error("Only one filename may be specified\n");
25161 filename
= argv
[1];
25167 arg_error("No filename specified\n");
25169 compile(filename
, &compiler
, &arch
);