2 * Linearize - walk the statement tree (but _not_ the expressions)
3 * to generate a linear version of it and the basic blocks.
5 * NOTE! We're not interested in the actual sub-expressions yet,
6 * even though they can generate conditional branches and
7 * subroutine calls. That's all "local" behaviour.
9 * Copyright (C) 2004 Linus Torvalds
10 * Copyright (C) 2004 Christopher Li
20 #include "expression.h"
21 #include "linearize.h"
26 static pseudo_t
linearize_statement(struct entrypoint
*ep
, struct statement
*stmt
);
27 static pseudo_t
linearize_expression(struct entrypoint
*ep
, struct expression
*expr
);
29 static pseudo_t
add_cast(struct entrypoint
*ep
, struct symbol
*to
, struct symbol
*from
, int op
, pseudo_t src
);
30 static pseudo_t
add_binary_op(struct entrypoint
*ep
, struct symbol
*ctype
, int op
, pseudo_t left
, pseudo_t right
);
31 static pseudo_t
add_setval(struct entrypoint
*ep
, struct symbol
*ctype
, struct expression
*val
);
32 static pseudo_t
linearize_one_symbol(struct entrypoint
*ep
, struct symbol
*sym
);
35 static pseudo_t
add_load(struct entrypoint
*ep
, struct access_data
*);
36 static pseudo_t
linearize_initializer(struct entrypoint
*ep
, struct expression
*initializer
, struct access_data
*);
37 static pseudo_t
cast_pseudo(struct entrypoint
*ep
, pseudo_t src
, struct symbol
*from
, struct symbol
*to
);
39 struct pseudo void_pseudo
= {};
41 static struct position current_pos
;
43 ALLOCATOR(pseudo_user
, "pseudo_user");
45 static struct instruction
*alloc_instruction(int opcode
, int size
)
47 struct instruction
* insn
= __alloc_instruction(0);
48 insn
->opcode
= opcode
;
50 insn
->pos
= current_pos
;
54 static inline int type_size(struct symbol
*type
)
56 return type
? type
->bit_size
> 0 ? type
->bit_size
: 0 : 0;
59 static struct instruction
*alloc_typed_instruction(int opcode
, struct symbol
*type
)
61 struct instruction
*insn
= alloc_instruction(opcode
, type_size(type
));
66 static struct entrypoint
*alloc_entrypoint(void)
68 return __alloc_entrypoint(0);
71 static struct basic_block
*alloc_basic_block(struct entrypoint
*ep
, struct position pos
)
74 struct basic_block
*bb
= __alloc_basic_block(0);
81 static struct multijmp
*alloc_multijmp(struct basic_block
*target
, long long begin
, long long end
)
83 struct multijmp
*multijmp
= __alloc_multijmp(0);
84 multijmp
->target
= target
;
85 multijmp
->begin
= begin
;
90 const char *show_label(struct basic_block
*bb
)
93 static char buffer
[4][16];
94 char *buf
= buffer
[3 & ++n
];
98 snprintf(buf
, 64, ".L%u", bb
->nr
);
102 const char *show_pseudo(pseudo_t pseudo
)
105 static char buffer
[4][64];
113 buf
= buffer
[3 & ++n
];
114 switch(pseudo
->type
) {
116 struct symbol
*sym
= pseudo
->sym
;
117 struct expression
*expr
;
120 snprintf(buf
, 64, "<bad symbol>");
123 if (sym
->bb_target
) {
124 snprintf(buf
, 64, "%s", show_label(sym
->bb_target
));
128 snprintf(buf
, 64, "%s", show_ident(sym
->ident
));
131 expr
= sym
->initializer
;
132 snprintf(buf
, 64, "<anon symbol:%p>", verbose
? sym
: NULL
);
134 switch (expr
->type
) {
136 snprintf(buf
, 64, "<symbol value: %lld>", expr
->value
);
139 return show_string(expr
->string
);
147 i
= snprintf(buf
, 64, "%%r%d", pseudo
->nr
);
149 sprintf(buf
+i
, "(%s)", show_ident(pseudo
->ident
));
152 long long value
= pseudo
->value
;
153 if (value
> 1000 || value
< -1000)
154 snprintf(buf
, 64, "$%#llx", value
);
156 snprintf(buf
, 64, "$%lld", value
);
160 snprintf(buf
, 64, "%%arg%d", pseudo
->nr
);
163 i
= snprintf(buf
, 64, "%%phi%d", pseudo
->nr
);
165 sprintf(buf
+i
, "(%s)", show_ident(pseudo
->ident
));
170 snprintf(buf
, 64, "<bad pseudo type %d>", pseudo
->type
);
175 static const char *opcodes
[] = {
176 [OP_BADOP
] = "bad_op",
179 [OP_ENTRY
] = "<entry-point>",
185 [OP_SWITCH
] = "switch",
186 [OP_UNREACH
] = "unreachable",
187 [OP_COMPUTEDGOTO
] = "jmp *",
201 /* Floating-point Binary */
212 /* Binary comparison */
213 [OP_SET_EQ
] = "seteq",
214 [OP_SET_NE
] = "setne",
215 [OP_SET_LE
] = "setle",
216 [OP_SET_GE
] = "setge",
217 [OP_SET_LT
] = "setlt",
218 [OP_SET_GT
] = "setgt",
221 [OP_SET_BE
] = "setbe",
222 [OP_SET_AE
] = "setae",
224 /* floating-point comparison */
225 [OP_FCMP_ORD
] = "fcmpord",
226 [OP_FCMP_OEQ
] = "fcmpoeq",
227 [OP_FCMP_ONE
] = "fcmpone",
228 [OP_FCMP_OLE
] = "fcmpole",
229 [OP_FCMP_OGE
] = "fcmpoge",
230 [OP_FCMP_OLT
] = "fcmpolt",
231 [OP_FCMP_OGT
] = "fcmpogt",
232 [OP_FCMP_UEQ
] = "fcmpueq",
233 [OP_FCMP_UNE
] = "fcmpune",
234 [OP_FCMP_ULE
] = "fcmpule",
235 [OP_FCMP_UGE
] = "fcmpuge",
236 [OP_FCMP_ULT
] = "fcmpult",
237 [OP_FCMP_UGT
] = "fcmpugt",
238 [OP_FCMP_UNO
] = "fcmpuno",
245 /* Special three-input */
250 [OP_STORE
] = "store",
252 [OP_SETFVAL
] = "setfval",
253 [OP_SYMADDR
] = "symaddr",
257 [OP_PHISOURCE
] = "phisrc",
260 [OP_TRUNC
] = "trunc",
261 [OP_FCVTU
] = "fcvtu",
262 [OP_FCVTS
] = "fcvts",
263 [OP_UCVTF
] = "ucvtf",
264 [OP_SCVTF
] = "scvtf",
265 [OP_FCVTF
] = "fcvtf",
266 [OP_UTPTR
] = "utptr",
267 [OP_PTRTU
] = "ptrtu",
268 [OP_PTRCAST
] = "ptrcast",
269 [OP_INLINED_CALL
] = "# call",
271 [OP_SLICE
] = "slice",
273 [OP_DEATHNOTE
] = "dead",
276 /* Sparse tagging (line numbers, context, whatever) */
277 [OP_CONTEXT
] = "context",
278 [OP_RANGE
] = "range-check",
283 static char *show_asm_constraints(char *buf
, const char *sep
, struct asm_constraint_list
*list
)
285 struct asm_constraint
*entry
;
287 FOR_EACH_PTR(list
, entry
) {
288 buf
+= sprintf(buf
, "%s\"%s\"", sep
, entry
->constraint
);
290 buf
+= sprintf(buf
, " (%s)", show_pseudo(entry
->pseudo
));
292 buf
+= sprintf(buf
, " [%s]", show_ident(entry
->ident
));
294 } END_FOR_EACH_PTR(entry
);
298 static char *show_asm(char *buf
, struct instruction
*insn
)
300 struct asm_rules
*rules
= insn
->asm_rules
;
302 buf
+= sprintf(buf
, "\"%s\"", insn
->string
);
303 buf
= show_asm_constraints(buf
, "\n\t\tout: ", rules
->outputs
);
304 buf
= show_asm_constraints(buf
, "\n\t\tin: ", rules
->inputs
);
305 buf
= show_asm_constraints(buf
, "\n\t\tclobber: ", rules
->clobbers
);
309 const char *show_instruction(struct instruction
*insn
)
311 int opcode
= insn
->opcode
;
312 static char buffer
[4096];
317 buf
+= sprintf(buf
, "# ");
319 if (opcode
< ARRAY_SIZE(opcodes
)) {
320 const char *op
= opcodes
[opcode
];
322 buf
+= sprintf(buf
, "opcode:%d", opcode
);
324 buf
+= sprintf(buf
, "%s", op
);
326 buf
+= sprintf(buf
, ".%d", insn
->size
);
327 memset(buf
, ' ', 20);
331 if (buf
< buffer
+ 12)
335 if (insn
->src
&& insn
->src
!= VOID
)
336 buf
+= sprintf(buf
, "%s", show_pseudo(insn
->src
));
340 buf
+= sprintf(buf
, "%s, %s, %s", show_pseudo(insn
->cond
), show_label(insn
->bb_true
), show_label(insn
->bb_false
));
344 buf
+= sprintf(buf
, "%s", show_label(insn
->bb_true
));
348 struct expression
*expr
= insn
->val
;
349 buf
+= sprintf(buf
, "%s <- ", show_pseudo(insn
->target
));
352 buf
+= sprintf(buf
, "%s", "<none>");
356 switch (expr
->type
) {
358 buf
+= sprintf(buf
, "%lld", expr
->value
);
361 buf
+= sprintf(buf
, "%Le", expr
->fvalue
);
364 buf
+= sprintf(buf
, "%.40s", show_string(expr
->string
));
367 buf
+= sprintf(buf
, "%s", show_ident(expr
->symbol
->ident
));
370 buf
+= sprintf(buf
, "%s", show_label(expr
->symbol
->bb_target
));
373 buf
+= sprintf(buf
, "SETVAL EXPR TYPE %d", expr
->type
);
378 buf
+= sprintf(buf
, "%s <- ", show_pseudo(insn
->target
));
379 buf
+= sprintf(buf
, "%Le", insn
->fvalue
);
383 struct multijmp
*jmp
;
384 buf
+= sprintf(buf
, "%s", show_pseudo(insn
->cond
));
385 FOR_EACH_PTR(insn
->multijmp_list
, jmp
) {
386 if (jmp
->begin
== jmp
->end
)
387 buf
+= sprintf(buf
, ", %lld -> %s", jmp
->begin
, show_label(jmp
->target
));
388 else if (jmp
->begin
< jmp
->end
)
389 buf
+= sprintf(buf
, ", %lld ... %lld -> %s", jmp
->begin
, jmp
->end
, show_label(jmp
->target
));
391 buf
+= sprintf(buf
, ", default -> %s", show_label(jmp
->target
));
392 } END_FOR_EACH_PTR(jmp
);
395 case OP_COMPUTEDGOTO
: {
396 struct multijmp
*jmp
;
397 buf
+= sprintf(buf
, "%s", show_pseudo(insn
->src
));
398 FOR_EACH_PTR(insn
->multijmp_list
, jmp
) {
399 buf
+= sprintf(buf
, ", %s", show_label(jmp
->target
));
400 } END_FOR_EACH_PTR(jmp
);
407 struct instruction
*phi
;
408 buf
+= sprintf(buf
, "%s <- %s ", show_pseudo(insn
->target
), show_pseudo(insn
->phi_src
));
409 FOR_EACH_PTR(insn
->phi_users
, phi
) {
410 buf
+= sprintf(buf
, " (%s)", show_pseudo(phi
->target
));
411 } END_FOR_EACH_PTR(phi
);
417 const char *s
= " <-";
418 buf
+= sprintf(buf
, "%s", show_pseudo(insn
->target
));
419 FOR_EACH_PTR(insn
->phi_list
, phi
) {
420 if (phi
== VOID
&& !verbose
)
422 buf
+= sprintf(buf
, "%s %s", s
, show_pseudo(phi
));
424 } END_FOR_EACH_PTR(phi
);
428 buf
+= sprintf(buf
, "%s <- %d[%s]", show_pseudo(insn
->target
), insn
->offset
, show_pseudo(insn
->src
));
431 buf
+= sprintf(buf
, "%s -> %d[%s]", show_pseudo(insn
->target
), insn
->offset
, show_pseudo(insn
->src
));
433 case OP_INLINED_CALL
:
436 if (insn
->target
&& insn
->target
!= VOID
)
437 buf
+= sprintf(buf
, "%s <- ", show_pseudo(insn
->target
));
438 buf
+= sprintf(buf
, "%s", show_pseudo(insn
->func
));
439 FOR_EACH_PTR(insn
->arguments
, arg
) {
440 buf
+= sprintf(buf
, ", %s", show_pseudo(arg
));
441 } END_FOR_EACH_PTR(arg
);
444 case OP_SEXT
: case OP_ZEXT
:
446 case OP_FCVTU
: case OP_FCVTS
:
447 case OP_UCVTF
: case OP_SCVTF
:
452 buf
+= sprintf(buf
, "%s <- (%d) %s",
453 show_pseudo(insn
->target
),
454 type_size(insn
->orig_type
),
455 show_pseudo(insn
->src
));
457 case OP_BINARY
... OP_BINARY_END
:
458 case OP_FPCMP
... OP_FPCMP_END
:
459 case OP_BINCMP
... OP_BINCMP_END
:
460 buf
+= sprintf(buf
, "%s <- %s, %s", show_pseudo(insn
->target
), show_pseudo(insn
->src1
), show_pseudo(insn
->src2
));
464 buf
+= sprintf(buf
, "%s <- %s, %s, %s", show_pseudo(insn
->target
),
465 show_pseudo(insn
->src1
), show_pseudo(insn
->src2
), show_pseudo(insn
->src3
));
469 buf
+= sprintf(buf
, "%s <- %s, %d, %d", show_pseudo(insn
->target
), show_pseudo(insn
->base
), insn
->from
, insn
->len
);
472 case OP_NOT
: case OP_NEG
:
475 buf
+= sprintf(buf
, "%s <- %s", show_pseudo(insn
->target
), show_pseudo(insn
->src1
));
479 buf
+= sprintf(buf
, "%s%d", insn
->check
? "check: " : "", insn
->increment
);
482 buf
+= sprintf(buf
, "%s between %s..%s", show_pseudo(insn
->src1
), show_pseudo(insn
->src2
), show_pseudo(insn
->src3
));
485 buf
+= sprintf(buf
, "%s <- %s", show_pseudo(insn
->target
), show_pseudo(insn
->src1
));
488 buf
+= sprintf(buf
, "%s", show_pseudo(insn
->target
));
491 buf
= show_asm(buf
, insn
);
494 buf
+= sprintf(buf
, "%s <- %s", show_pseudo(insn
->target
), show_pseudo(insn
->src
));
500 if (buf
>= buffer
+ sizeof(buffer
))
501 die("instruction buffer overflowed %td\n", buf
- buffer
);
502 do { --buf
; } while (*buf
== ' ');
507 void show_bb(struct basic_block
*bb
)
509 struct instruction
*insn
;
511 printf("%s:\n", show_label(bb
));
513 pseudo_t needs
, defines
;
514 printf("%s:%d\n", stream_name(bb
->pos
.stream
), bb
->pos
.line
);
516 FOR_EACH_PTR(bb
->needs
, needs
) {
517 struct instruction
*def
= needs
->def
;
518 if (def
->opcode
!= OP_PHI
) {
519 printf(" **uses %s (from %s)**\n", show_pseudo(needs
), show_label(def
->bb
));
522 const char *sep
= " ";
523 printf(" **uses %s (from", show_pseudo(needs
));
524 FOR_EACH_PTR(def
->phi_list
, phi
) {
527 printf("%s(%s:%s)", sep
, show_pseudo(phi
), show_label(phi
->def
->bb
));
529 } END_FOR_EACH_PTR(phi
);
532 } END_FOR_EACH_PTR(needs
);
534 FOR_EACH_PTR(bb
->defines
, defines
) {
535 printf(" **defines %s **\n", show_pseudo(defines
));
536 } END_FOR_EACH_PTR(defines
);
539 struct basic_block
*from
;
540 FOR_EACH_PTR(bb
->parents
, from
) {
541 printf(" **from %s (%s:%d:%d)**\n", show_label(from
),
542 stream_name(from
->pos
.stream
), from
->pos
.line
, from
->pos
.pos
);
543 } END_FOR_EACH_PTR(from
);
547 struct basic_block
*to
;
548 FOR_EACH_PTR(bb
->children
, to
) {
549 printf(" **to %s (%s:%d:%d)**\n", show_label(to
),
550 stream_name(to
->pos
.stream
), to
->pos
.line
, to
->pos
.pos
);
551 } END_FOR_EACH_PTR(to
);
555 FOR_EACH_PTR(bb
->insns
, insn
) {
556 if (!insn
->bb
&& verbose
< 2)
558 printf("\t%s\n", show_instruction(insn
));
559 } END_FOR_EACH_PTR(insn
);
560 if (!bb_terminated(bb
))
564 static void show_symbol_usage(pseudo_t pseudo
)
566 struct pseudo_user
*pu
;
569 FOR_EACH_PTR(pseudo
->users
, pu
) {
570 printf("\t%s\n", show_instruction(pu
->insn
));
571 } END_FOR_EACH_PTR(pu
);
575 void show_entry(struct entrypoint
*ep
)
578 struct basic_block
*bb
;
580 printf("%s:\n", show_ident(ep
->name
->ident
));
583 printf("ep %p: %s\n", ep
, show_ident(ep
->name
->ident
));
585 FOR_EACH_PTR(ep
->syms
, sym
) {
588 if (!sym
->pseudo
->users
)
590 printf(" sym: %p %s\n", sym
, show_ident(sym
->ident
));
591 if (sym
->ctype
.modifiers
& (MOD_EXTERN
| MOD_STATIC
| MOD_ADDRESSABLE
))
592 printf("\texternal visibility\n");
593 show_symbol_usage(sym
->pseudo
);
594 } END_FOR_EACH_PTR(sym
);
599 FOR_EACH_PTR(ep
->bbs
, bb
) {
602 if (!bb
->parents
&& !bb
->children
&& !bb
->insns
&& verbose
< 2)
606 } END_FOR_EACH_PTR(bb
);
611 static void bind_label(struct symbol
*label
, struct basic_block
*bb
, struct position pos
)
613 if (label
->bb_target
)
614 warning(pos
, "label '%s' already bound", show_ident(label
->ident
));
615 label
->bb_target
= bb
;
618 static struct basic_block
* get_bound_block(struct entrypoint
*ep
, struct symbol
*label
)
620 struct basic_block
*bb
= label
->bb_target
;
623 bb
= alloc_basic_block(ep
, label
->pos
);
624 label
->bb_target
= bb
;
629 static void finish_block(struct entrypoint
*ep
)
631 struct basic_block
*src
= ep
->active
;
632 if (bb_reachable(src
))
636 static void add_goto(struct entrypoint
*ep
, struct basic_block
*dst
)
638 struct basic_block
*src
= ep
->active
;
639 if (bb_reachable(src
)) {
640 struct instruction
*br
= alloc_instruction(OP_BR
, 0);
642 add_bb(&dst
->parents
, src
);
643 add_bb(&src
->children
, dst
);
645 add_instruction(&src
->insns
, br
);
650 static void add_one_insn(struct entrypoint
*ep
, struct instruction
*insn
)
652 struct basic_block
*bb
= ep
->active
;
654 if (bb_reachable(bb
)) {
656 add_instruction(&bb
->insns
, insn
);
660 static void add_unreachable(struct entrypoint
*ep
)
662 struct instruction
*insn
= alloc_instruction(OP_UNREACH
, 0);
663 add_one_insn(ep
, insn
);
667 static void set_activeblock(struct entrypoint
*ep
, struct basic_block
*bb
)
669 if (!bb_terminated(ep
->active
))
673 if (bb_reachable(bb
))
674 add_bb(&ep
->bbs
, bb
);
677 static void remove_parent(struct basic_block
*child
, struct basic_block
*parent
)
679 remove_bb_from_list(&child
->parents
, parent
, 1);
681 repeat_phase
|= REPEAT_CFG_CLEANUP
;
684 /* Change a "switch" or a conditional branch into a branch */
685 void insert_branch(struct basic_block
*bb
, struct instruction
*jmp
, struct basic_block
*target
)
687 struct instruction
*br
, *old
;
688 struct basic_block
*child
;
690 /* Remove the switch */
691 old
= delete_last_instruction(&bb
->insns
);
693 kill_instruction(old
);
695 br
= alloc_instruction(OP_BR
, 0);
697 br
->bb_true
= target
;
698 add_instruction(&bb
->insns
, br
);
700 FOR_EACH_PTR(bb
->children
, child
) {
701 if (child
== target
) {
702 target
= NULL
; /* Trigger just once */
705 DELETE_CURRENT_PTR(child
);
706 remove_parent(child
, bb
);
707 } END_FOR_EACH_PTR(child
);
708 PACK_PTR_LIST(&bb
->children
);
712 void insert_select(struct basic_block
*bb
, struct instruction
*br
, struct instruction
*phi_node
, pseudo_t if_true
, pseudo_t if_false
)
715 struct instruction
*select
;
717 /* Remove the 'br' */
718 delete_last_instruction(&bb
->insns
);
720 select
= alloc_typed_instruction(OP_SEL
, phi_node
->type
);
724 use_pseudo(select
, br
->cond
, &select
->src1
);
726 target
= phi_node
->target
;
727 assert(target
->def
== phi_node
);
728 select
->target
= target
;
729 target
->def
= select
;
731 use_pseudo(select
, if_true
, &select
->src2
);
732 use_pseudo(select
, if_false
, &select
->src3
);
734 add_instruction(&bb
->insns
, select
);
735 add_instruction(&bb
->insns
, br
);
738 static inline int bb_empty(struct basic_block
*bb
)
743 /* Add a label to the currently active block, return new active block */
744 static struct basic_block
* add_label(struct entrypoint
*ep
, struct symbol
*label
)
746 struct basic_block
*bb
= label
->bb_target
;
749 set_activeblock(ep
, bb
);
753 if (!bb_reachable(bb
) || !bb_empty(bb
)) {
754 bb
= alloc_basic_block(ep
, label
->pos
);
755 set_activeblock(ep
, bb
);
757 label
->bb_target
= bb
;
761 static void add_branch(struct entrypoint
*ep
, pseudo_t cond
, struct basic_block
*bb_true
, struct basic_block
*bb_false
)
763 struct basic_block
*bb
= ep
->active
;
764 struct instruction
*br
;
766 if (bb_reachable(bb
)) {
767 br
= alloc_instruction(OP_CBR
, 0);
768 use_pseudo(br
, cond
, &br
->cond
);
769 br
->bb_true
= bb_true
;
770 br
->bb_false
= bb_false
;
771 add_bb(&bb_true
->parents
, bb
);
772 add_bb(&bb_false
->parents
, bb
);
773 add_bb(&bb
->children
, bb_true
);
774 add_bb(&bb
->children
, bb_false
);
775 add_one_insn(ep
, br
);
779 pseudo_t
alloc_pseudo(struct instruction
*def
)
782 struct pseudo
* pseudo
= __alloc_pseudo(0);
783 pseudo
->type
= PSEUDO_REG
;
789 static pseudo_t
symbol_pseudo(struct entrypoint
*ep
, struct symbol
*sym
)
796 pseudo
= sym
->pseudo
;
798 pseudo
= __alloc_pseudo(0);
800 pseudo
->type
= PSEUDO_SYM
;
802 pseudo
->ident
= sym
->ident
;
803 sym
->pseudo
= pseudo
;
804 add_pseudo(&ep
->accesses
, pseudo
);
806 /* Symbol pseudos have neither nr nor def */
810 pseudo_t
value_pseudo(long long val
)
812 #define MAX_VAL_HASH 64
813 static struct pseudo_list
*prev
[MAX_VAL_HASH
];
814 int hash
= val
& (MAX_VAL_HASH
-1);
815 struct pseudo_list
**list
= prev
+ hash
;
818 FOR_EACH_PTR(*list
, pseudo
) {
819 if (pseudo
->value
== val
)
821 } END_FOR_EACH_PTR(pseudo
);
823 pseudo
= __alloc_pseudo(0);
824 pseudo
->type
= PSEUDO_VAL
;
826 add_pseudo(list
, pseudo
);
828 /* Value pseudos have neither nr, usage nor def */
832 pseudo_t
undef_pseudo(void)
834 pseudo_t pseudo
= __alloc_pseudo(0);
835 pseudo
->type
= PSEUDO_UNDEF
;
839 static pseudo_t
argument_pseudo(struct entrypoint
*ep
, int nr
)
841 pseudo_t pseudo
= __alloc_pseudo(0);
842 struct instruction
*entry
= ep
->entry
;
844 pseudo
->type
= PSEUDO_ARG
;
847 add_pseudo(&entry
->arg_list
, pseudo
);
849 /* Argument pseudos have neither usage nor def */
853 struct instruction
*alloc_phisrc(pseudo_t pseudo
, struct symbol
*type
)
855 struct instruction
*insn
= alloc_typed_instruction(OP_PHISOURCE
, type
);
856 pseudo_t phi
= __alloc_pseudo(0);
859 phi
->type
= PSEUDO_PHI
;
863 use_pseudo(insn
, pseudo
, &insn
->phi_src
);
868 pseudo_t
alloc_phi(struct basic_block
*source
, pseudo_t pseudo
, struct symbol
*type
)
870 struct instruction
*insn
;
875 insn
= alloc_phisrc(pseudo
, type
);
877 add_instruction(&source
->insns
, insn
);
881 struct instruction
*alloc_phi_node(struct basic_block
*bb
, struct symbol
*type
, struct ident
*ident
)
883 struct instruction
*phi_node
= alloc_typed_instruction(OP_PHI
, type
);
886 phi
= alloc_pseudo(phi_node
);
889 phi_node
->target
= phi
;
894 void add_phi_node(struct basic_block
*bb
, struct instruction
*phi_node
)
896 struct instruction
*insn
;
898 FOR_EACH_PTR(bb
->insns
, insn
) {
899 enum opcode op
= insn
->opcode
;
902 INSERT_CURRENT(phi_node
, insn
);
904 } END_FOR_EACH_PTR(insn
);
907 add_instruction(&bb
->insns
, phi_node
);
910 struct instruction
*insert_phi_node(struct basic_block
*bb
, struct symbol
*var
)
912 struct instruction
*phi_node
= alloc_phi_node(bb
, var
, var
->ident
);
913 add_phi_node(bb
, phi_node
);
918 * We carry the "access_data" structure around for any accesses,
919 * which simplifies things a lot. It contains all the access
920 * information in one place.
923 struct symbol
*type
; // ctype
924 struct symbol
*btype
; // base type of bitfields
925 pseudo_t address
; // pseudo containing address ..
926 unsigned int offset
; // byte offset
929 static int linearize_simple_address(struct entrypoint
*ep
,
930 struct expression
*addr
,
931 struct access_data
*ad
)
933 if (addr
->type
== EXPR_SYMBOL
) {
934 linearize_one_symbol(ep
, addr
->symbol
);
935 ad
->address
= symbol_pseudo(ep
, addr
->symbol
);
938 if (addr
->type
== EXPR_BINOP
) {
939 if (addr
->right
->type
== EXPR_VALUE
) {
940 if (addr
->op
== '+') {
941 ad
->offset
+= get_expression_value(addr
->right
);
942 return linearize_simple_address(ep
, addr
->left
, ad
);
946 ad
->address
= linearize_expression(ep
, addr
);
950 static struct symbol
*bitfield_base_type(struct symbol
*sym
)
952 struct symbol
*base
= sym
;
955 if (sym
->type
== SYM_NODE
)
956 base
= base
->ctype
.base_type
;
957 if (base
->type
== SYM_BITFIELD
)
958 return base
->ctype
.base_type
;
963 static int linearize_address_gen(struct entrypoint
*ep
,
964 struct expression
*expr
,
965 struct access_data
*ad
)
967 struct symbol
*ctype
= expr
->ctype
;
972 if (expr
->type
== EXPR_PREOP
&& expr
->op
== '*')
973 return linearize_simple_address(ep
, expr
->unop
, ad
);
975 warning(expr
->pos
, "generating address of non-lvalue (%d)", expr
->type
);
979 static pseudo_t
add_load(struct entrypoint
*ep
, struct access_data
*ad
)
981 struct instruction
*insn
;
987 insn
= alloc_typed_instruction(OP_LOAD
, ad
->btype
);
988 new = alloc_pseudo(insn
);
991 insn
->offset
= ad
->offset
;
992 insn
->is_volatile
= ad
->type
&& (ad
->type
->ctype
.modifiers
& MOD_VOLATILE
);
993 use_pseudo(insn
, ad
->address
, &insn
->src
);
994 add_one_insn(ep
, insn
);
998 static void add_store(struct entrypoint
*ep
, struct access_data
*ad
, pseudo_t value
)
1000 struct basic_block
*bb
= ep
->active
;
1001 struct instruction
*store
;
1006 store
= alloc_typed_instruction(OP_STORE
, ad
->btype
);
1007 store
->offset
= ad
->offset
;
1008 store
->is_volatile
= ad
->type
&& (ad
->type
->ctype
.modifiers
& MOD_VOLATILE
);
1009 use_pseudo(store
, value
, &store
->target
);
1010 use_pseudo(store
, ad
->address
, &store
->src
);
1011 add_one_insn(ep
, store
);
1014 static pseudo_t
linearize_bitfield_insert(struct entrypoint
*ep
,
1015 pseudo_t ori
, pseudo_t val
, struct symbol
*ctype
, struct symbol
*btype
)
1017 unsigned int shift
= ctype
->bit_offset
;
1018 unsigned int size
= ctype
->bit_size
;
1019 unsigned long long mask
= ((1ULL << size
) - 1);
1020 unsigned long long smask
= bits_mask(btype
->bit_size
);
1022 val
= add_cast(ep
, btype
, ctype
, OP_ZEXT
, val
);
1024 val
= add_binary_op(ep
, btype
, OP_SHL
, val
, value_pseudo(shift
));
1027 ori
= add_binary_op(ep
, btype
, OP_AND
, ori
, value_pseudo(~mask
& smask
));
1028 val
= add_binary_op(ep
, btype
, OP_OR
, ori
, val
);
1033 static pseudo_t
linearize_store_gen(struct entrypoint
*ep
,
1035 struct access_data
*ad
)
1037 struct symbol
*ctype
= ad
->type
;
1038 struct symbol
*btype
;
1039 pseudo_t store
= value
;
1044 btype
= ad
->btype
= bitfield_base_type(ctype
);
1045 if (type_size(btype
) != type_size(ctype
)) {
1046 pseudo_t orig
= add_load(ep
, ad
);
1047 store
= linearize_bitfield_insert(ep
, orig
, value
, ctype
, btype
);
1049 add_store(ep
, ad
, store
);
1053 static void taint_undefined_behaviour(struct instruction
*insn
)
1057 switch (insn
->opcode
) {
1062 if (src2
->type
!= PSEUDO_VAL
)
1064 if ((unsigned long long)src2
->value
>= insn
->size
)
1070 static pseudo_t
add_binary_op(struct entrypoint
*ep
, struct symbol
*ctype
, int op
, pseudo_t left
, pseudo_t right
)
1072 struct instruction
*insn
= alloc_typed_instruction(op
, ctype
);
1073 pseudo_t target
= alloc_pseudo(insn
);
1074 insn
->target
= target
;
1075 use_pseudo(insn
, left
, &insn
->src1
);
1076 use_pseudo(insn
, right
, &insn
->src2
);
1077 add_one_insn(ep
, insn
);
1081 static pseudo_t
add_setval(struct entrypoint
*ep
, struct symbol
*ctype
, struct expression
*val
)
1083 struct instruction
*insn
= alloc_typed_instruction(OP_SETVAL
, ctype
);
1084 pseudo_t target
= alloc_pseudo(insn
);
1085 insn
->target
= target
;
1087 add_one_insn(ep
, insn
);
1091 static pseudo_t
add_setfval(struct entrypoint
*ep
, struct symbol
*ctype
, long double fval
)
1093 struct instruction
*insn
= alloc_typed_instruction(OP_SETFVAL
, ctype
);
1094 pseudo_t target
= alloc_pseudo(insn
);
1095 insn
->target
= target
;
1096 insn
->fvalue
= fval
;
1097 add_one_insn(ep
, insn
);
1101 static pseudo_t
add_symbol_address(struct entrypoint
*ep
, struct symbol
*sym
)
1103 struct instruction
*insn
= alloc_instruction(OP_SYMADDR
, bits_in_pointer
);
1104 pseudo_t target
= alloc_pseudo(insn
);
1106 insn
->target
= target
;
1107 use_pseudo(insn
, symbol_pseudo(ep
, sym
), &insn
->src
);
1108 add_one_insn(ep
, insn
);
1112 static pseudo_t
linearize_bitfield_extract(struct entrypoint
*ep
,
1113 pseudo_t val
, struct symbol
*ctype
, struct symbol
*btype
)
1115 unsigned int off
= ctype
->bit_offset
;
1118 pseudo_t shift
= value_pseudo(off
);
1119 val
= add_binary_op(ep
, btype
, OP_LSR
, val
, shift
);
1121 val
= cast_pseudo(ep
, val
, btype
, ctype
);
1125 static pseudo_t
linearize_load_gen(struct entrypoint
*ep
, struct access_data
*ad
)
1127 struct symbol
*ctype
= ad
->type
;
1128 struct symbol
*btype
;
1134 btype
= ad
->btype
= bitfield_base_type(ctype
);
1135 new = add_load(ep
, ad
);
1136 if (ctype
->bit_size
!= type_size(btype
))
1137 new = linearize_bitfield_extract(ep
, new, ctype
, btype
);
1141 static pseudo_t
linearize_access(struct entrypoint
*ep
, struct expression
*expr
)
1143 struct access_data ad
= { NULL
, };
1146 if (!linearize_address_gen(ep
, expr
, &ad
))
1148 value
= linearize_load_gen(ep
, &ad
);
1152 static pseudo_t
linearize_inc_dec(struct entrypoint
*ep
, struct expression
*expr
, int postop
)
1154 struct access_data ad
= { NULL
, };
1155 pseudo_t old
, new, one
;
1156 int op
= expr
->op
== SPECIAL_INCREMENT
? OP_ADD
: OP_SUB
;
1158 if (!linearize_address_gen(ep
, expr
->unop
, &ad
))
1161 old
= linearize_load_gen(ep
, &ad
);
1162 op
= opcode_float(op
, expr
->ctype
);
1163 if (is_float_type(expr
->ctype
))
1164 one
= add_setfval(ep
, expr
->ctype
, expr
->op_value
);
1166 one
= value_pseudo(expr
->op_value
);
1167 if (ad
.btype
!= ad
.type
)
1168 old
= cast_pseudo(ep
, old
, ad
.type
, ad
.btype
);
1169 new = add_binary_op(ep
, ad
.btype
, op
, old
, one
);
1170 if (ad
.btype
!= ad
.type
)
1171 new = cast_pseudo(ep
, new, ad
.btype
, ad
.type
);
1172 linearize_store_gen(ep
, new, &ad
);
1173 return postop
? old
: new;
1176 static pseudo_t
add_unop(struct entrypoint
*ep
, struct symbol
*ctype
, int op
, pseudo_t src
)
1178 struct instruction
*insn
= alloc_typed_instruction(op
, ctype
);
1179 pseudo_t
new = alloc_pseudo(insn
);
1182 use_pseudo(insn
, src
, &insn
->src1
);
1183 add_one_insn(ep
, insn
);
1187 static pseudo_t
add_cast(struct entrypoint
*ep
, struct symbol
*to
,
1188 struct symbol
*from
, int op
, pseudo_t src
)
1190 pseudo_t
new = add_unop(ep
, to
, op
, src
);
1191 new->def
->orig_type
= from
;
1195 static pseudo_t
linearize_slice(struct entrypoint
*ep
, struct expression
*expr
)
1197 pseudo_t pre
= linearize_expression(ep
, expr
->base
);
1198 struct instruction
*insn
= alloc_typed_instruction(OP_SLICE
, expr
->ctype
);
1199 pseudo_t
new = alloc_pseudo(insn
);
1202 insn
->from
= expr
->r_bitpos
;
1203 insn
->len
= expr
->r_nrbits
;
1204 use_pseudo(insn
, pre
, &insn
->base
);
1205 add_one_insn(ep
, insn
);
1209 static pseudo_t
linearize_regular_preop(struct entrypoint
*ep
, struct expression
*expr
)
1211 pseudo_t pre
= linearize_expression(ep
, expr
->unop
);
1212 struct symbol
*ctype
= expr
->ctype
;
1217 pseudo_t zero
= value_pseudo(0);
1218 return add_binary_op(ep
, ctype
, OP_SET_EQ
, pre
, zero
);
1221 return add_unop(ep
, ctype
, OP_NOT
, pre
);
1223 return add_unop(ep
, ctype
, opcode_float(OP_NEG
, ctype
), pre
);
1228 static pseudo_t
linearize_preop(struct entrypoint
*ep
, struct expression
*expr
)
1231 * '*' is an lvalue access, and is fundamentally different
1232 * from an arithmetic operation. Maybe it should have an
1233 * expression type of its own..
1235 if (expr
->op
== '*')
1236 return linearize_access(ep
, expr
);
1237 if (expr
->op
== SPECIAL_INCREMENT
|| expr
->op
== SPECIAL_DECREMENT
)
1238 return linearize_inc_dec(ep
, expr
, 0);
1239 return linearize_regular_preop(ep
, expr
);
1242 static pseudo_t
linearize_postop(struct entrypoint
*ep
, struct expression
*expr
)
1244 return linearize_inc_dec(ep
, expr
, 1);
1248 * Casts to pointers are "less safe" than other casts, since
1249 * they imply type-unsafe accesses. "void *" is a special
1250 * case, since you can't access through it anyway without another
1257 MTYPE_VPTR
, // TODO: must be removed ?
1262 static enum mtype
get_mtype(struct symbol
*s
)
1264 int sign
= (s
->ctype
.modifiers
& MOD_SIGNED
) ? 1 : 0;
1266 retry
: switch (s
->type
) {
1268 s
= s
->ctype
.base_type
;
1271 if (s
->ctype
.base_type
== &void_ctype
)
1278 s
= s
->ctype
.base_type
;
1281 return sign
? MTYPE_SINT
: MTYPE_UINT
;
1283 if (s
->ctype
.base_type
== &fp_type
)
1285 if (s
->ctype
.base_type
== &int_type
)
1293 static int get_cast_opcode(struct symbol
*dst
, struct symbol
*src
)
1295 enum mtype stype
= get_mtype(src
);
1296 enum mtype dtype
= get_mtype(dst
);
1302 if (dst
->bit_size
== src
->bit_size
)
1340 return dtype
== MTYPE_UINT
? OP_FCVTU
: OP_FCVTS
;
1346 if (dst
->bit_size
==src
->bit_size
)
1348 if (dst
->bit_size
< src
->bit_size
)
1350 return stype
== MTYPE_SINT
? OP_SEXT
: OP_ZEXT
;
1356 if (src
->type
== SYM_NODE
)
1357 src
= src
->ctype
.base_type
;
1358 if (dst
->type
== SYM_NODE
)
1359 dst
= dst
->ctype
.base_type
;
1366 static pseudo_t
cast_pseudo(struct entrypoint
*ep
, pseudo_t src
, struct symbol
*from
, struct symbol
*to
)
1368 const struct position pos
= current_pos
;
1370 struct instruction
*insn
;
1377 if (from
->bit_size
< 0 || to
->bit_size
< 0)
1379 opcode
= get_cast_opcode(to
, from
);
1384 if (from
->bit_size
== to
->bit_size
)
1386 if (src
== value_pseudo(0))
1388 if (Wint_to_pointer_cast
)
1389 warning(pos
, "non size-preserving integer to pointer cast");
1390 src
= cast_pseudo(ep
, src
, from
, size_t_ctype
);
1391 from
= size_t_ctype
;
1394 if (from
->bit_size
== to
->bit_size
)
1396 if (Wpointer_to_int_cast
)
1397 warning(pos
, "non size-preserving pointer to integer cast");
1398 src
= cast_pseudo(ep
, src
, from
, size_t_ctype
);
1399 return cast_pseudo(ep
, src
, size_t_ctype
, to
);
1405 insn
= alloc_typed_instruction(opcode
, to
);
1406 result
= alloc_pseudo(insn
);
1407 insn
->target
= result
;
1408 insn
->orig_type
= from
;
1409 use_pseudo(insn
, src
, &insn
->src
);
1410 add_one_insn(ep
, insn
);
1414 static int map_opcode(int opcode
, struct symbol
*ctype
)
1416 if (ctype
&& is_float_type(ctype
))
1417 return opcode_table
[opcode
].to_float
;
1418 if (ctype
&& (ctype
->ctype
.modifiers
& MOD_SIGNED
)) {
1420 case OP_DIVU
: case OP_MODU
: case OP_LSR
:
1427 static inline pseudo_t
add_convert_to_bool(struct entrypoint
*ep
, pseudo_t src
, struct symbol
*type
)
1432 if (!type
|| src
== VOID
)
1434 if (is_bool_type(type
))
1436 if (src
->type
== PSEUDO_VAL
&& (src
->value
== 0 || src
->value
== 1))
1438 if (is_float_type(type
)) {
1439 zero
= add_setfval(ep
, type
, 0.0);
1440 op
= map_opcode(OP_SET_NE
, type
);
1442 zero
= value_pseudo(0);
1445 return add_binary_op(ep
, &bool_ctype
, op
, src
, zero
);
1448 static pseudo_t
linearize_expression_to_bool(struct entrypoint
*ep
, struct expression
*expr
)
1451 dst
= linearize_expression(ep
, expr
);
1452 dst
= add_convert_to_bool(ep
, dst
, expr
->ctype
);
1456 static pseudo_t
linearize_assignment(struct entrypoint
*ep
, struct expression
*expr
)
1458 struct access_data ad
= { NULL
, };
1459 struct expression
*target
= expr
->left
;
1460 struct expression
*src
= expr
->right
;
1461 struct symbol
*ctype
;
1464 value
= linearize_expression(ep
, src
);
1465 if (!target
|| !linearize_address_gen(ep
, target
, &ad
))
1467 if (expr
->op
!= '=') {
1468 pseudo_t oldvalue
= linearize_load_gen(ep
, &ad
);
1470 static const int op_trans
[] = {
1471 [SPECIAL_ADD_ASSIGN
- SPECIAL_BASE
] = OP_ADD
,
1472 [SPECIAL_SUB_ASSIGN
- SPECIAL_BASE
] = OP_SUB
,
1473 [SPECIAL_MUL_ASSIGN
- SPECIAL_BASE
] = OP_MUL
,
1474 [SPECIAL_DIV_ASSIGN
- SPECIAL_BASE
] = OP_DIVU
,
1475 [SPECIAL_MOD_ASSIGN
- SPECIAL_BASE
] = OP_MODU
,
1476 [SPECIAL_SHL_ASSIGN
- SPECIAL_BASE
] = OP_SHL
,
1477 [SPECIAL_SHR_ASSIGN
- SPECIAL_BASE
] = OP_LSR
,
1478 [SPECIAL_AND_ASSIGN
- SPECIAL_BASE
] = OP_AND
,
1479 [SPECIAL_OR_ASSIGN
- SPECIAL_BASE
] = OP_OR
,
1480 [SPECIAL_XOR_ASSIGN
- SPECIAL_BASE
] = OP_XOR
1488 oldvalue
= cast_pseudo(ep
, oldvalue
, target
->ctype
, ctype
);
1489 opcode
= map_opcode(op_trans
[expr
->op
- SPECIAL_BASE
], ctype
);
1490 dst
= add_binary_op(ep
, ctype
, opcode
, oldvalue
, value
);
1491 taint_undefined_behaviour(dst
->def
);
1492 value
= cast_pseudo(ep
, dst
, ctype
, expr
->ctype
);
1494 value
= linearize_store_gen(ep
, value
, &ad
);
1498 static pseudo_t
linearize_call_expression(struct entrypoint
*ep
, struct expression
*expr
)
1500 struct expression
*arg
, *fn
;
1501 struct instruction
*insn
= alloc_typed_instruction(OP_CALL
, expr
->ctype
);
1502 pseudo_t retval
, call
;
1503 struct ctype
*ctype
= NULL
;
1504 struct symbol
*fntype
;
1505 struct context
*context
;
1514 if (fntype
->op
&& fntype
->op
->linearize
)
1515 return fntype
->op
->linearize(ep
, expr
);
1517 ctype
= &fntype
->ctype
;
1518 if (fntype
->type
== SYM_NODE
)
1519 fntype
= fntype
->ctype
.base_type
;
1521 add_symbol(&insn
->fntypes
, fntype
);
1522 FOR_EACH_PTR(expr
->args
, arg
) {
1523 pseudo_t
new = linearize_expression(ep
, arg
);
1524 use_pseudo(insn
, new, add_pseudo(&insn
->arguments
, new));
1525 add_symbol(&insn
->fntypes
, arg
->ctype
);
1526 } END_FOR_EACH_PTR(arg
);
1528 if (fn
->type
== EXPR_PREOP
&& fn
->op
== '*' && is_func_type(fn
->ctype
))
1531 if (fn
->type
== EXPR_SYMBOL
) {
1532 call
= symbol_pseudo(ep
, fn
->symbol
);
1534 call
= linearize_expression(ep
, fn
);
1536 use_pseudo(insn
, call
, &insn
->func
);
1538 if (expr
->ctype
!= &void_ctype
)
1539 retval
= alloc_pseudo(insn
);
1540 insn
->target
= retval
;
1541 add_one_insn(ep
, insn
);
1544 FOR_EACH_PTR(ctype
->contexts
, context
) {
1545 int in
= context
->in
;
1546 int out
= context
->out
;
1557 context_diff
= out
- in
;
1558 if (check
|| context_diff
) {
1559 insn
= alloc_instruction(OP_CONTEXT
, 0);
1560 insn
->increment
= context_diff
;
1561 insn
->check
= check
;
1562 insn
->context_expr
= context
->context
;
1563 add_one_insn(ep
, insn
);
1565 } END_FOR_EACH_PTR(context
);
1567 if (ctype
->modifiers
& MOD_NORETURN
)
1568 add_unreachable(ep
);
1574 static pseudo_t
linearize_binop_bool(struct entrypoint
*ep
, struct expression
*expr
)
1576 pseudo_t src1
, src2
, dst
;
1577 int op
= (expr
->op
== SPECIAL_LOGICAL_OR
) ? OP_OR
: OP_AND
;
1579 src1
= linearize_expression_to_bool(ep
, expr
->left
);
1580 src2
= linearize_expression_to_bool(ep
, expr
->right
);
1581 dst
= add_binary_op(ep
, &bool_ctype
, op
, src1
, src2
);
1582 if (expr
->ctype
!= &bool_ctype
)
1583 dst
= cast_pseudo(ep
, dst
, &bool_ctype
, expr
->ctype
);
1587 static pseudo_t
linearize_binop(struct entrypoint
*ep
, struct expression
*expr
)
1589 pseudo_t src1
, src2
, dst
;
1590 static const int opcode
[] = {
1591 ['+'] = OP_ADD
, ['-'] = OP_SUB
,
1592 ['*'] = OP_MUL
, ['/'] = OP_DIVU
,
1593 ['%'] = OP_MODU
, ['&'] = OP_AND
,
1594 ['|'] = OP_OR
, ['^'] = OP_XOR
,
1595 [SPECIAL_LEFTSHIFT
] = OP_SHL
,
1596 [SPECIAL_RIGHTSHIFT
] = OP_LSR
,
1600 src1
= linearize_expression(ep
, expr
->left
);
1601 src2
= linearize_expression(ep
, expr
->right
);
1602 op
= map_opcode(opcode
[expr
->op
], expr
->ctype
);
1603 dst
= add_binary_op(ep
, expr
->ctype
, op
, src1
, src2
);
1604 taint_undefined_behaviour(dst
->def
);
1608 static pseudo_t
linearize_logical_branch(struct entrypoint
*ep
, struct expression
*expr
, struct basic_block
*bb_true
, struct basic_block
*bb_false
);
1610 static pseudo_t
linearize_cond_branch(struct entrypoint
*ep
, struct expression
*expr
, struct basic_block
*bb_true
, struct basic_block
*bb_false
);
1612 static pseudo_t
linearize_select(struct entrypoint
*ep
, struct expression
*expr
)
1614 pseudo_t cond
, valt
, valf
, res
;
1615 struct instruction
*insn
;
1617 valt
= linearize_expression(ep
, expr
->cond_true
);
1618 valf
= linearize_expression(ep
, expr
->cond_false
);
1619 cond
= linearize_expression(ep
, expr
->conditional
);
1621 insn
= alloc_typed_instruction(OP_SEL
, expr
->ctype
);
1622 if (!expr
->cond_true
)
1624 use_pseudo(insn
, cond
, &insn
->src1
);
1625 use_pseudo(insn
, valt
, &insn
->src2
);
1626 use_pseudo(insn
, valf
, &insn
->src3
);
1628 res
= alloc_pseudo(insn
);
1630 add_one_insn(ep
, insn
);
1634 static pseudo_t
add_join_conditional(struct entrypoint
*ep
, struct expression
*expr
,
1635 pseudo_t phi1
, pseudo_t phi2
)
1638 struct instruction
*phi_node
;
1645 phi_node
= alloc_typed_instruction(OP_PHI
, expr
->ctype
);
1646 use_pseudo(phi_node
, phi1
, add_pseudo(&phi_node
->phi_list
, phi1
));
1647 use_pseudo(phi_node
, phi2
, add_pseudo(&phi_node
->phi_list
, phi2
));
1648 phi_node
->target
= target
= alloc_pseudo(phi_node
);
1649 add_one_insn(ep
, phi_node
);
1653 static pseudo_t
linearize_short_conditional(struct entrypoint
*ep
, struct expression
*expr
,
1654 struct expression
*cond
,
1655 struct expression
*expr_false
)
1657 pseudo_t src1
, src2
;
1658 struct basic_block
*bb_false
;
1659 struct basic_block
*merge
;
1660 pseudo_t phi1
, phi2
;
1662 if (!expr_false
|| !ep
->active
)
1665 bb_false
= alloc_basic_block(ep
, expr_false
->pos
);
1666 merge
= alloc_basic_block(ep
, expr
->pos
);
1668 src1
= linearize_expression(ep
, cond
);
1669 phi1
= alloc_phi(ep
->active
, src1
, expr
->ctype
);
1670 add_branch(ep
, src1
, merge
, bb_false
);
1672 set_activeblock(ep
, bb_false
);
1673 src2
= linearize_expression(ep
, expr_false
);
1674 phi2
= alloc_phi(ep
->active
, src2
, expr
->ctype
);
1675 set_activeblock(ep
, merge
);
1677 return add_join_conditional(ep
, expr
, phi1
, phi2
);
1680 static pseudo_t
linearize_conditional(struct entrypoint
*ep
, struct expression
*expr
,
1681 struct expression
*cond
,
1682 struct expression
*expr_true
,
1683 struct expression
*expr_false
)
1685 pseudo_t src1
, src2
;
1686 pseudo_t phi1
, phi2
;
1687 struct basic_block
*bb_true
, *bb_false
, *merge
;
1689 if (!cond
|| !expr_true
|| !expr_false
|| !ep
->active
)
1691 bb_true
= alloc_basic_block(ep
, expr_true
->pos
);
1692 bb_false
= alloc_basic_block(ep
, expr_false
->pos
);
1693 merge
= alloc_basic_block(ep
, expr
->pos
);
1695 linearize_cond_branch(ep
, cond
, bb_true
, bb_false
);
1697 set_activeblock(ep
, bb_true
);
1698 src1
= linearize_expression(ep
, expr_true
);
1699 phi1
= alloc_phi(ep
->active
, src1
, expr
->ctype
);
1700 add_goto(ep
, merge
);
1702 set_activeblock(ep
, bb_false
);
1703 src2
= linearize_expression(ep
, expr_false
);
1704 phi2
= alloc_phi(ep
->active
, src2
, expr
->ctype
);
1705 set_activeblock(ep
, merge
);
1707 return add_join_conditional(ep
, expr
, phi1
, phi2
);
1710 static void insert_phis(struct basic_block
*bb
, pseudo_t src
, struct symbol
*ctype
,
1711 struct instruction
*node
)
1713 struct basic_block
*parent
;
1715 FOR_EACH_PTR(bb
->parents
, parent
) {
1716 struct instruction
*br
= delete_last_instruction(&parent
->insns
);
1717 pseudo_t phi
= alloc_phi(parent
, src
, ctype
);
1718 add_instruction(&parent
->insns
, br
);
1719 use_pseudo(node
, phi
, add_pseudo(&node
->phi_list
, phi
));
1720 } END_FOR_EACH_PTR(parent
);
1723 static pseudo_t
linearize_logical(struct entrypoint
*ep
, struct expression
*expr
)
1725 struct symbol
*ctype
= expr
->ctype
;
1726 struct basic_block
*other
, *merge
;
1727 struct instruction
*node
;
1728 pseudo_t src1
, src2
, phi2
;
1730 if (!ep
->active
|| !expr
->left
|| !expr
->right
)
1733 other
= alloc_basic_block(ep
, expr
->right
->pos
);
1734 merge
= alloc_basic_block(ep
, expr
->pos
);
1735 node
= alloc_phi_node(merge
, ctype
, NULL
);
1737 // LHS and its shortcut
1738 if (expr
->op
== SPECIAL_LOGICAL_OR
) {
1739 linearize_cond_branch(ep
, expr
->left
, merge
, other
);
1740 src1
= value_pseudo(1);
1742 linearize_cond_branch(ep
, expr
->left
, other
, merge
);
1743 src1
= value_pseudo(0);
1745 insert_phis(merge
, src1
, ctype
, node
);
1748 set_activeblock(ep
, other
);
1749 src2
= linearize_expression_to_bool(ep
, expr
->right
);
1750 src2
= cast_pseudo(ep
, src2
, &bool_ctype
, ctype
);
1751 phi2
= alloc_phi(ep
->active
, src2
, ctype
);
1752 use_pseudo(node
, phi2
, add_pseudo(&node
->phi_list
, phi2
));
1755 set_activeblock(ep
, merge
);
1756 add_instruction(&merge
->insns
, node
);
1757 return node
->target
;
1760 static pseudo_t
linearize_compare(struct entrypoint
*ep
, struct expression
*expr
)
1762 static const int cmpop
[] = {
1763 ['>'] = OP_SET_GT
, ['<'] = OP_SET_LT
,
1764 [SPECIAL_EQUAL
] = OP_SET_EQ
,
1765 [SPECIAL_NOTEQUAL
] = OP_SET_NE
,
1766 [SPECIAL_GTE
] = OP_SET_GE
,
1767 [SPECIAL_LTE
] = OP_SET_LE
,
1768 [SPECIAL_UNSIGNED_LT
] = OP_SET_B
,
1769 [SPECIAL_UNSIGNED_GT
] = OP_SET_A
,
1770 [SPECIAL_UNSIGNED_LTE
] = OP_SET_BE
,
1771 [SPECIAL_UNSIGNED_GTE
] = OP_SET_AE
,
1773 int op
= opcode_float(cmpop
[expr
->op
], expr
->right
->ctype
);
1774 pseudo_t src1
= linearize_expression(ep
, expr
->left
);
1775 pseudo_t src2
= linearize_expression(ep
, expr
->right
);
1776 pseudo_t dst
= add_binary_op(ep
, expr
->ctype
, op
, src1
, src2
);
1781 static pseudo_t
linearize_cond_branch(struct entrypoint
*ep
, struct expression
*expr
, struct basic_block
*bb_true
, struct basic_block
*bb_false
)
1785 if (!expr
|| !valid_type(expr
->ctype
) || !bb_reachable(ep
->active
))
1788 switch (expr
->type
) {
1792 add_goto(ep
, expr
->value
? bb_true
: bb_false
);
1796 add_goto(ep
, expr
->fvalue
? bb_true
: bb_false
);
1800 linearize_logical_branch(ep
, expr
, bb_true
, bb_false
);
1804 cond
= linearize_compare(ep
, expr
);
1805 add_branch(ep
, cond
, bb_true
, bb_false
);
1809 if (expr
->op
== '!')
1810 return linearize_cond_branch(ep
, expr
->unop
, bb_false
, bb_true
);
1813 cond
= linearize_expression_to_bool(ep
, expr
);
1814 add_branch(ep
, cond
, bb_true
, bb_false
);
1824 static pseudo_t
linearize_logical_branch(struct entrypoint
*ep
, struct expression
*expr
, struct basic_block
*bb_true
, struct basic_block
*bb_false
)
1826 struct basic_block
*next
= alloc_basic_block(ep
, expr
->pos
);
1828 if (expr
->op
== SPECIAL_LOGICAL_OR
)
1829 linearize_cond_branch(ep
, expr
->left
, bb_true
, next
);
1831 linearize_cond_branch(ep
, expr
->left
, next
, bb_false
);
1832 set_activeblock(ep
, next
);
1833 linearize_cond_branch(ep
, expr
->right
, bb_true
, bb_false
);
1837 static pseudo_t
linearize_cast(struct entrypoint
*ep
, struct expression
*expr
)
1840 struct expression
*orig
= expr
->cast_expression
;
1845 src
= linearize_expression(ep
, orig
);
1846 return cast_pseudo(ep
, src
, orig
->ctype
, expr
->ctype
);
1849 static pseudo_t
linearize_initializer(struct entrypoint
*ep
, struct expression
*initializer
, struct access_data
*ad
)
1851 switch (initializer
->type
) {
1852 case EXPR_INITIALIZER
: {
1853 struct expression
*expr
;
1854 FOR_EACH_PTR(initializer
->expr_list
, expr
) {
1855 linearize_initializer(ep
, expr
, ad
);
1856 } END_FOR_EACH_PTR(expr
);
1860 ad
->offset
= initializer
->init_offset
;
1861 linearize_initializer(ep
, initializer
->init_expr
, ad
);
1864 pseudo_t value
= linearize_expression(ep
, initializer
);
1865 ad
->type
= initializer
->ctype
;
1866 linearize_store_gen(ep
, value
, ad
);
1874 static void linearize_argument(struct entrypoint
*ep
, struct symbol
*arg
, int nr
)
1876 struct access_data ad
= { NULL
, };
1879 ad
.address
= symbol_pseudo(ep
, arg
);
1880 linearize_store_gen(ep
, argument_pseudo(ep
, nr
), &ad
);
1883 static pseudo_t
linearize_expression(struct entrypoint
*ep
, struct expression
*expr
)
1885 if (!expr
|| !valid_type(expr
->ctype
))
1888 current_pos
= expr
->pos
;
1889 switch (expr
->type
) {
1891 linearize_one_symbol(ep
, expr
->symbol
);
1892 return add_symbol_address(ep
, expr
->symbol
);
1895 return value_pseudo(expr
->value
);
1899 return add_setval(ep
, expr
->ctype
, expr
);
1902 return add_setfval(ep
, expr
->ctype
, expr
->fvalue
);
1904 case EXPR_STATEMENT
:
1905 return linearize_statement(ep
, expr
->statement
);
1908 return linearize_call_expression(ep
, expr
);
1911 if (expr
->op
== SPECIAL_LOGICAL_AND
|| expr
->op
== SPECIAL_LOGICAL_OR
)
1912 return linearize_binop_bool(ep
, expr
);
1913 return linearize_binop(ep
, expr
);
1916 return linearize_logical(ep
, expr
);
1919 return linearize_compare(ep
, expr
);
1922 return linearize_select(ep
, expr
);
1924 case EXPR_CONDITIONAL
:
1925 if (!expr
->cond_true
)
1926 return linearize_short_conditional(ep
, expr
, expr
->conditional
, expr
->cond_false
);
1928 return linearize_conditional(ep
, expr
, expr
->conditional
,
1929 expr
->cond_true
, expr
->cond_false
);
1932 linearize_expression(ep
, expr
->left
);
1933 return linearize_expression(ep
, expr
->right
);
1935 case EXPR_ASSIGNMENT
:
1936 return linearize_assignment(ep
, expr
);
1939 return linearize_preop(ep
, expr
);
1942 return linearize_postop(ep
, expr
);
1945 case EXPR_FORCE_CAST
:
1946 case EXPR_IMPLIED_CAST
:
1947 return linearize_cast(ep
, expr
);
1950 return linearize_slice(ep
, expr
);
1952 case EXPR_INITIALIZER
:
1954 warning(expr
->pos
, "unexpected initializer expression (%d %d)", expr
->type
, expr
->op
);
1957 warning(expr
->pos
, "unknown expression (%d %d)", expr
->type
, expr
->op
);
1963 static pseudo_t
linearize_one_symbol(struct entrypoint
*ep
, struct symbol
*sym
)
1965 struct access_data ad
= { NULL
, };
1968 if (!sym
|| !sym
->initializer
|| sym
->initialized
)
1971 /* We need to output these puppies some day too.. */
1972 if (sym
->ctype
.modifiers
& (MOD_STATIC
| MOD_TOPLEVEL
))
1975 sym
->initialized
= 1;
1976 ad
.address
= symbol_pseudo(ep
, sym
);
1978 if (sym
->initializer
&& !is_scalar_type(sym
)) {
1979 // default zero initialization [6.7.9.21]
1980 // FIXME: this init the whole aggregate while
1981 // only the existing fields need to be initialized.
1982 // FIXME: this init the whole aggregate even if
1983 // all fields arelater explicitely initialized.
1985 ad
.address
= symbol_pseudo(ep
, sym
);
1986 linearize_store_gen(ep
, value_pseudo(0), &ad
);
1989 value
= linearize_initializer(ep
, sym
->initializer
, &ad
);
1993 static pseudo_t
linearize_compound_statement(struct entrypoint
*ep
, struct statement
*stmt
)
1996 struct statement
*s
;
1999 FOR_EACH_PTR(stmt
->stmts
, s
) {
2000 pseudo
= linearize_statement(ep
, s
);
2001 } END_FOR_EACH_PTR(s
);
2006 static void add_return(struct entrypoint
*ep
, struct basic_block
*bb
, struct symbol
*ctype
, pseudo_t src
)
2008 struct instruction
*phi_node
= first_instruction(bb
->insns
);
2011 phi_node
= alloc_typed_instruction(OP_PHI
, ctype
);
2012 phi_node
->target
= alloc_pseudo(phi_node
);
2014 add_instruction(&bb
->insns
, phi_node
);
2016 phi
= alloc_phi(ep
->active
, src
, ctype
);
2017 phi
->ident
= &return_ident
;
2018 use_pseudo(phi_node
, phi
, add_pseudo(&phi_node
->phi_list
, phi
));
2021 static pseudo_t
linearize_fn_statement(struct entrypoint
*ep
, struct statement
*stmt
)
2023 struct instruction
*phi_node
;
2024 struct basic_block
*bb
;
2027 pseudo
= linearize_compound_statement(ep
, stmt
);
2028 if (!is_void_type(stmt
->ret
)) { // non-void function
2029 struct basic_block
*active
= ep
->active
;
2030 if (active
&& !bb_terminated(active
)) { // missing return
2031 struct basic_block
*bb_ret
;
2032 bb_ret
= get_bound_block(ep
, stmt
->ret
);
2033 add_return(ep
, bb_ret
, stmt
->ret
, undef_pseudo());
2036 bb
= add_label(ep
, stmt
->ret
);
2037 phi_node
= first_instruction(bb
->insns
);
2039 pseudo
= phi_node
->target
;
2043 static pseudo_t
linearize_inlined_call(struct entrypoint
*ep
, struct statement
*stmt
)
2045 struct instruction
*insn
= alloc_instruction(OP_INLINED_CALL
, 0);
2046 struct statement
*args
= stmt
->args
;
2047 struct basic_block
*bb
;
2053 concat_symbol_list(args
->declaration
, &ep
->syms
);
2054 FOR_EACH_PTR(args
->declaration
, sym
) {
2055 pseudo_t value
= linearize_one_symbol(ep
, sym
);
2056 add_pseudo(&insn
->arguments
, value
);
2057 } END_FOR_EACH_PTR(sym
);
2060 pseudo
= linearize_fn_statement(ep
, stmt
);
2061 insn
->target
= pseudo
;
2063 use_pseudo(insn
, symbol_pseudo(ep
, stmt
->inline_fn
), &insn
->func
);
2066 bb
->pos
= stmt
->pos
;
2067 add_one_insn(ep
, insn
);
2071 static pseudo_t
linearize_context(struct entrypoint
*ep
, struct statement
*stmt
)
2073 struct instruction
*insn
= alloc_instruction(OP_CONTEXT
, 0);
2074 struct expression
*expr
= stmt
->expression
;
2076 insn
->increment
= get_expression_value(expr
);
2077 insn
->context_expr
= stmt
->context
;
2078 add_one_insn(ep
, insn
);
2082 static pseudo_t
linearize_range(struct entrypoint
*ep
, struct statement
*stmt
)
2084 struct instruction
*insn
= alloc_instruction(OP_RANGE
, 0);
2086 use_pseudo(insn
, linearize_expression(ep
, stmt
->range_expression
), &insn
->src1
);
2087 use_pseudo(insn
, linearize_expression(ep
, stmt
->range_low
), &insn
->src2
);
2088 use_pseudo(insn
, linearize_expression(ep
, stmt
->range_high
), &insn
->src3
);
2089 add_one_insn(ep
, insn
);
2093 ALLOCATOR(asm_rules
, "asm rules");
2094 ALLOCATOR(asm_constraint
, "asm constraints");
2096 static void add_asm_input(struct entrypoint
*ep
, struct instruction
*insn
, struct asm_operand
*op
)
2098 pseudo_t pseudo
= linearize_expression(ep
, op
->expr
);
2099 struct asm_constraint
*rule
= __alloc_asm_constraint(0);
2101 rule
->ident
= op
->name
;
2102 rule
->constraint
= op
->constraint
? op
->constraint
->string
->data
: "";
2103 use_pseudo(insn
, pseudo
, &rule
->pseudo
);
2104 add_ptr_list(&insn
->asm_rules
->inputs
, rule
);
2107 static void add_asm_output(struct entrypoint
*ep
, struct instruction
*insn
, struct asm_operand
*op
)
2109 struct access_data ad
= { NULL
, };
2111 struct asm_constraint
*rule
;
2113 if (op
->is_memory
) {
2114 pseudo
= linearize_expression(ep
, op
->expr
);
2116 if (!linearize_address_gen(ep
, op
->expr
, &ad
))
2118 pseudo
= alloc_pseudo(insn
);
2119 linearize_store_gen(ep
, pseudo
, &ad
);
2121 rule
= __alloc_asm_constraint(0);
2122 rule
->is_memory
= op
->is_memory
;
2123 rule
->ident
= op
->name
;
2124 rule
->constraint
= op
->constraint
? op
->constraint
->string
->data
: "";
2125 use_pseudo(insn
, pseudo
, &rule
->pseudo
);
2126 add_ptr_list(&insn
->asm_rules
->outputs
, rule
);
2129 static pseudo_t
linearize_asm_statement(struct entrypoint
*ep
, struct statement
*stmt
)
2131 struct instruction
*insn
;
2132 struct expression
*expr
;
2133 struct asm_rules
*rules
;
2134 struct asm_operand
*op
;
2136 insn
= alloc_instruction(OP_ASM
, 0);
2137 expr
= stmt
->asm_string
;
2138 if (!expr
|| expr
->type
!= EXPR_STRING
) {
2139 warning(stmt
->pos
, "expected string in inline asm");
2142 insn
->string
= expr
->string
->data
;
2144 rules
= __alloc_asm_rules(0);
2145 insn
->asm_rules
= rules
;
2147 /* Gather the inputs.. */
2148 FOR_EACH_PTR(stmt
->asm_inputs
, op
) {
2149 add_asm_input(ep
, insn
, op
);
2150 } END_FOR_EACH_PTR(op
);
2152 add_one_insn(ep
, insn
);
2154 /* Assign the outputs */
2155 FOR_EACH_PTR(stmt
->asm_outputs
, op
) {
2156 add_asm_output(ep
, insn
, op
);
2157 } END_FOR_EACH_PTR(op
);
2162 static int multijmp_cmp(const void *_a
, const void *_b
)
2164 const struct multijmp
*a
= _a
;
2165 const struct multijmp
*b
= _b
;
2168 if (a
->begin
> a
->end
) {
2169 if (b
->begin
> b
->end
)
2173 if (b
->begin
> b
->end
)
2175 if (a
->begin
== b
->begin
) {
2176 if (a
->end
== b
->end
)
2178 return (a
->end
< b
->end
) ? -1 : 1;
2180 return a
->begin
< b
->begin
? -1 : 1;
2183 static void sort_switch_cases(struct instruction
*insn
)
2185 sort_list((struct ptr_list
**)&insn
->multijmp_list
, multijmp_cmp
);
2188 static pseudo_t
linearize_declaration(struct entrypoint
*ep
, struct statement
*stmt
)
2192 concat_symbol_list(stmt
->declaration
, &ep
->syms
);
2194 FOR_EACH_PTR(stmt
->declaration
, sym
) {
2195 linearize_one_symbol(ep
, sym
);
2196 } END_FOR_EACH_PTR(sym
);
2200 static pseudo_t
linearize_return(struct entrypoint
*ep
, struct statement
*stmt
)
2202 struct expression
*expr
= stmt
->expression
;
2203 struct symbol
*ret
= stmt
->ret_target
;
2204 struct basic_block
*bb_return
= get_bound_block(ep
, ret
);
2205 struct basic_block
*active
;
2206 pseudo_t src
= linearize_expression(ep
, expr
);
2207 active
= ep
->active
;
2208 if (active
&& !is_void_type(ret
)) {
2209 add_return(ep
, bb_return
, ret
, src
);
2211 add_goto(ep
, bb_return
);
2215 static pseudo_t
linearize_switch(struct entrypoint
*ep
, struct statement
*stmt
)
2218 struct instruction
*switch_ins
;
2219 struct basic_block
*switch_end
= alloc_basic_block(ep
, stmt
->pos
);
2220 struct basic_block
*active
, *default_case
;
2221 struct expression
*expr
= stmt
->switch_expression
;
2222 struct multijmp
*jmp
;
2225 if (!expr
|| !expr
->ctype
)
2227 pseudo
= linearize_expression(ep
, expr
);
2228 active
= ep
->active
;
2230 active
= alloc_basic_block(ep
, stmt
->pos
);
2231 set_activeblock(ep
, active
);
2234 switch_ins
= alloc_typed_instruction(OP_SWITCH
, expr
->ctype
);
2235 use_pseudo(switch_ins
, pseudo
, &switch_ins
->cond
);
2236 add_one_insn(ep
, switch_ins
);
2239 default_case
= NULL
;
2240 FOR_EACH_PTR(stmt
->switch_case
->symbol_list
, sym
) {
2241 struct statement
*case_stmt
= sym
->stmt
;
2242 struct basic_block
*bb_case
= get_bound_block(ep
, sym
);
2244 if (!case_stmt
->case_expression
) {
2245 default_case
= bb_case
;
2247 } else if (case_stmt
->case_expression
->type
!= EXPR_VALUE
) {
2250 struct expression
*case_to
= case_stmt
->case_to
;
2251 long long begin
, end
;
2253 begin
= end
= case_stmt
->case_expression
->value
;
2254 if (case_to
&& case_to
->type
== EXPR_VALUE
)
2255 end
= case_to
->value
;
2257 jmp
= alloc_multijmp(bb_case
, end
, begin
);
2259 jmp
= alloc_multijmp(bb_case
, begin
, end
);
2262 add_multijmp(&switch_ins
->multijmp_list
, jmp
);
2263 add_bb(&bb_case
->parents
, active
);
2264 add_bb(&active
->children
, bb_case
);
2265 } END_FOR_EACH_PTR(sym
);
2267 bind_label(stmt
->switch_break
, switch_end
, stmt
->pos
);
2269 /* And linearize the actual statement */
2270 linearize_statement(ep
, stmt
->switch_statement
);
2271 set_activeblock(ep
, switch_end
);
2274 default_case
= switch_end
;
2276 jmp
= alloc_multijmp(default_case
, 1, 0);
2277 add_multijmp(&switch_ins
->multijmp_list
, jmp
);
2278 add_bb(&default_case
->parents
, active
);
2279 add_bb(&active
->children
, default_case
);
2280 sort_switch_cases(switch_ins
);
2285 static pseudo_t
linearize_iterator(struct entrypoint
*ep
, struct statement
*stmt
)
2287 struct statement
*pre_statement
= stmt
->iterator_pre_statement
;
2288 struct expression
*pre_condition
= stmt
->iterator_pre_condition
;
2289 struct statement
*statement
= stmt
->iterator_statement
;
2290 struct statement
*post_statement
= stmt
->iterator_post_statement
;
2291 struct expression
*post_condition
= stmt
->iterator_post_condition
;
2292 struct basic_block
*loop_top
, *loop_body
, *loop_continue
, *loop_end
;
2295 FOR_EACH_PTR(stmt
->iterator_syms
, sym
) {
2296 linearize_one_symbol(ep
, sym
);
2297 } END_FOR_EACH_PTR(sym
);
2298 concat_symbol_list(stmt
->iterator_syms
, &ep
->syms
);
2299 linearize_statement(ep
, pre_statement
);
2301 loop_body
= loop_top
= alloc_basic_block(ep
, stmt
->pos
);
2302 loop_continue
= alloc_basic_block(ep
, stmt
->pos
);
2303 loop_end
= alloc_basic_block(ep
, stmt
->pos
);
2305 /* An empty post-condition means that it's the same as the pre-condition */
2306 if (!post_condition
) {
2307 loop_top
= alloc_basic_block(ep
, stmt
->pos
);
2308 set_activeblock(ep
, loop_top
);
2312 linearize_cond_branch(ep
, pre_condition
, loop_body
, loop_end
);
2314 bind_label(stmt
->iterator_continue
, loop_continue
, stmt
->pos
);
2315 bind_label(stmt
->iterator_break
, loop_end
, stmt
->pos
);
2317 set_activeblock(ep
, loop_body
);
2318 linearize_statement(ep
, statement
);
2319 add_goto(ep
, loop_continue
);
2321 set_activeblock(ep
, loop_continue
);
2322 linearize_statement(ep
, post_statement
);
2323 if (!post_condition
)
2324 add_goto(ep
, loop_top
);
2326 linearize_cond_branch(ep
, post_condition
, loop_top
, loop_end
);
2327 set_activeblock(ep
, loop_end
);
2332 static pseudo_t
linearize_statement(struct entrypoint
*ep
, struct statement
*stmt
)
2334 struct basic_block
*bb
;
2340 if (bb
&& !bb
->insns
)
2341 bb
->pos
= stmt
->pos
;
2342 current_pos
= stmt
->pos
;
2344 switch (stmt
->type
) {
2348 case STMT_DECLARATION
:
2349 return linearize_declaration(ep
, stmt
);
2352 return linearize_context(ep
, stmt
);
2355 return linearize_range(ep
, stmt
);
2357 case STMT_EXPRESSION
:
2358 return linearize_expression(ep
, stmt
->expression
);
2361 return linearize_asm_statement(ep
, stmt
);
2364 return linearize_return(ep
, stmt
);
2367 add_label(ep
, stmt
->case_label
);
2368 linearize_statement(ep
, stmt
->case_statement
);
2373 struct symbol
*label
= stmt
->label_identifier
;
2376 add_label(ep
, label
);
2378 return linearize_statement(ep
, stmt
->label_statement
);
2383 struct expression
*expr
;
2384 struct instruction
*goto_ins
;
2385 struct basic_block
*active
;
2388 active
= ep
->active
;
2389 if (!bb_reachable(active
))
2392 if (stmt
->goto_label
) {
2393 add_goto(ep
, get_bound_block(ep
, stmt
->goto_label
));
2397 expr
= stmt
->goto_expression
;
2401 /* This can happen as part of simplification */
2402 if (expr
->type
== EXPR_LABEL
) {
2403 add_goto(ep
, get_bound_block(ep
, expr
->label_symbol
));
2407 pseudo
= linearize_expression(ep
, expr
);
2408 goto_ins
= alloc_instruction(OP_COMPUTEDGOTO
, 0);
2409 use_pseudo(goto_ins
, pseudo
, &goto_ins
->src
);
2410 add_one_insn(ep
, goto_ins
);
2412 FOR_EACH_PTR(stmt
->target_list
, sym
) {
2413 struct basic_block
*bb_computed
= get_bound_block(ep
, sym
);
2414 struct multijmp
*jmp
= alloc_multijmp(bb_computed
, 1, 0);
2415 add_multijmp(&goto_ins
->multijmp_list
, jmp
);
2416 add_bb(&bb_computed
->parents
, ep
->active
);
2417 add_bb(&active
->children
, bb_computed
);
2418 } END_FOR_EACH_PTR(sym
);
2425 if (stmt
->inline_fn
)
2426 return linearize_inlined_call(ep
, stmt
);
2427 return linearize_compound_statement(ep
, stmt
);
2430 * This could take 'likely/unlikely' into account, and
2431 * switch the arms around appropriately..
2434 struct basic_block
*bb_true
, *bb_false
, *endif
;
2435 struct expression
*cond
= stmt
->if_conditional
;
2437 bb_true
= alloc_basic_block(ep
, stmt
->pos
);
2438 bb_false
= endif
= alloc_basic_block(ep
, stmt
->pos
);
2440 // If the condition is invalid, the following
2441 // statement(s) are not evaluated.
2442 if (!cond
|| !valid_type(cond
->ctype
))
2444 linearize_cond_branch(ep
, cond
, bb_true
, bb_false
);
2446 set_activeblock(ep
, bb_true
);
2447 linearize_statement(ep
, stmt
->if_true
);
2449 if (stmt
->if_false
) {
2450 endif
= alloc_basic_block(ep
, stmt
->pos
);
2451 add_goto(ep
, endif
);
2452 set_activeblock(ep
, bb_false
);
2453 linearize_statement(ep
, stmt
->if_false
);
2455 set_activeblock(ep
, endif
);
2460 return linearize_switch(ep
, stmt
);
2463 return linearize_iterator(ep
, stmt
);
2471 static struct entrypoint
*linearize_fn(struct symbol
*sym
, struct symbol
*base_type
)
2473 struct statement
*stmt
= base_type
->stmt
;
2474 struct entrypoint
*ep
;
2475 struct basic_block
*bb
;
2476 struct symbol
*ret_type
;
2478 struct instruction
*entry
;
2479 struct instruction
*ret
;
2483 if (!stmt
|| sym
->bogus_linear
)
2486 ep
= alloc_entrypoint();
2489 bb
= alloc_basic_block(ep
, sym
->pos
);
2490 set_activeblock(ep
, bb
);
2492 if (stmt
->type
== STMT_ASM
) { // top-level asm
2493 linearize_asm_statement(ep
, stmt
);
2497 entry
= alloc_instruction(OP_ENTRY
, 0);
2498 add_one_insn(ep
, entry
);
2501 concat_symbol_list(base_type
->arguments
, &ep
->syms
);
2503 /* FIXME!! We should do something else about varargs.. */
2505 FOR_EACH_PTR(base_type
->arguments
, arg
) {
2506 linearize_argument(ep
, arg
, ++i
);
2507 } END_FOR_EACH_PTR(arg
);
2509 result
= linearize_fn_statement(ep
, stmt
);
2510 ret_type
= base_type
->ctype
.base_type
;
2511 ret
= alloc_typed_instruction(OP_RET
, ret_type
);
2512 if (type_size(ret_type
) > 0)
2513 use_pseudo(ret
, result
, &ret
->src
);
2514 add_one_insn(ep
, ret
);
2520 struct entrypoint
*linearize_symbol(struct symbol
*sym
)
2522 struct symbol
*base_type
;
2526 current_pos
= sym
->pos
;
2527 base_type
= sym
->ctype
.base_type
;
2530 if (base_type
->type
== SYM_FN
)
2531 return linearize_fn(sym
, base_type
);
2539 static pseudo_t
linearize_unreachable(struct entrypoint
*ep
, struct expression
*exp
)
2541 add_unreachable(ep
);
2545 static struct sym_init
{
2547 pseudo_t (*linearize
)(struct entrypoint
*, struct expression
*);
2548 struct symbol_op op
;
2549 } builtins_table
[] = {
2550 // must be declared in builtin.c:declare_builtins[]
2551 { "__builtin_unreachable", linearize_unreachable
},
2555 void init_linearized_builtins(int stream
)
2557 struct sym_init
*ptr
;
2559 for (ptr
= builtins_table
; ptr
->name
; ptr
++) {
2561 sym
= create_symbol(stream
, ptr
->name
, SYM_NODE
, NS_SYMBOL
);
2564 sym
->op
->type
|= KW_BUILTIN
;
2565 ptr
->op
.linearize
= ptr
->linearize
;