2 * sparse/compile-i386.c
4 * Copyright (C) 2003 Transmeta Corp.
6 * Copyright 2003 Jeff Garzik
8 * Licensed under the Open Software License version 1.1
27 #include "expression.h"
33 unsigned int len
; /* does NOT include terminating null */
41 struct ptr_list
*pseudo_list
;
42 struct ptr_list
*atom_list
;
49 STOR_PSEUDO
, /* variable stored on the stack */
50 STOR_ARG
, /* function argument */
51 STOR_SYM
, /* a symbol we can directly ref in the asm */
52 STOR_REG
, /* scratch register */
53 STOR_VALUE
, /* integer constant */
54 STOR_LABEL
, /* label / jump target */
62 enum storage_type type
;
91 struct symbol_private
{
101 ATOM_FREE_OP1
= (1 << 0),
102 ATOM_FREE_OP2
= (1 << 1),
111 unsigned int text_len
; /* w/o terminating null */
114 /* stuff for insns */
126 struct function
*current_func
= NULL
;
127 struct textbuf
*unit_post_text
= NULL
;
128 static const char *current_section
;
130 static struct reg_info reg_info_table
[] = {
138 static struct storage hardreg_storage_table
[] = {
141 .reg
= ®_info_table
[0],
146 .reg
= ®_info_table
[1],
151 .reg
= ®_info_table
[2],
156 .reg
= ®_info_table
[3],
161 .reg
= ®_info_table
[4],
165 #define REG_EAX (&hardreg_storage_table[0])
166 #define REG_ECX (&hardreg_storage_table[1])
167 #define REG_EDX (&hardreg_storage_table[2])
168 #define REG_ESP (&hardreg_storage_table[3])
169 #define REG_DL (&hardreg_storage_table[4])
172 static void emit_move(struct storage
*src
, struct storage
*dest
,
173 struct symbol
*ctype
, const char *comment
,
174 unsigned long flags
);
175 static int type_is_signed(struct symbol
*sym
);
176 static struct storage
*x86_address_gen(struct expression
*expr
);
177 static struct storage
*x86_symbol_expr(struct symbol
*sym
);
178 static void x86_symbol(struct symbol
*sym
);
179 static struct storage
*x86_statement(struct statement
*stmt
);
180 static struct storage
*x86_expression(struct expression
*expr
);
183 static inline unsigned int pseudo_offset(struct storage
*s
)
185 if (s
->type
!= STOR_PSEUDO
)
186 return 123456; /* intentionally bogus value */
188 return ((s
->pseudo
- 1) * 4);
191 static inline unsigned int arg_offset(struct storage
*s
)
193 if (s
->type
!= STOR_ARG
)
194 return 123456; /* intentionally bogus value */
196 /* FIXME: this is wrong wrong wrong */
197 return (current_func
->pseudo_nr
+ 1 + s
->idx
) * 4;
200 static const char *pretty_offset(int ofs
)
202 static char esp_buf
[64];
205 sprintf(esp_buf
, "%d(%%esp)", ofs
);
207 strcpy(esp_buf
, "(%esp)");
212 static void stor_sym_init(struct symbol
*sym
)
214 struct storage
*stor
;
215 struct symbol_private
*priv
;
217 priv
= calloc(1, sizeof(*priv
) + sizeof(*stor
));
219 die("OOM in stor_sym_init");
221 stor
= (struct storage
*) (priv
+ 1);
224 stor
->type
= STOR_SYM
;
228 static const char *stor_op_name(struct storage
*s
)
230 static char name
[32];
234 strcpy(name
, pretty_offset((int) pseudo_offset(s
)));
237 strcpy(name
, pretty_offset((int) arg_offset(s
)));
240 strcpy(name
, show_ident(s
->sym
->ident
));
243 strcpy(name
, s
->reg
->name
);
246 sprintf(name
, "$%Ld", s
->value
);
249 sprintf(name
, ".L%d", s
->label
);
256 static struct atom
*new_atom(enum atom_type type
)
260 atom
= calloc(1, sizeof(*atom
)); /* TODO: chunked alloc */
269 static inline void push_atom(struct function
*f
, struct atom
*atom
)
271 add_ptr_list(&f
->atom_list
, atom
);
274 static void push_text_atom(struct function
*f
, const char *text
)
276 struct atom
*atom
= new_atom(ATOM_TEXT
);
278 atom
->text
= strdup(text
);
279 atom
->text_len
= strlen(text
);
284 static struct storage
*new_storage(enum storage_type type
)
286 struct storage
*stor
;
288 stor
= calloc(1, sizeof(*stor
));
290 die("OOM in new_storage");
297 static struct storage
*new_pseudo(void)
299 struct function
*f
= current_func
;
300 struct storage
*stor
;
304 stor
= new_storage(STOR_PSEUDO
);
305 stor
->type
= STOR_PSEUDO
;
306 stor
->pseudo
= ++f
->pseudo_nr
;
308 add_ptr_list(&f
->pseudo_list
, stor
);
313 static int new_label(void)
315 static int label
= 0;
319 static void textbuf_push(struct textbuf
**buf_p
, const char *text
)
321 struct textbuf
*tmp
, *list
= *buf_p
;
322 unsigned int text_len
= strlen(text
);
323 unsigned int alloc_len
= text_len
+ 1 + sizeof(*list
);
325 tmp
= calloc(1, alloc_len
);
327 die("OOM on textbuf alloc");
329 tmp
->text
= ((void *) tmp
) + sizeof(*tmp
);
330 memcpy(tmp
->text
, text
, text_len
+ 1);
333 /* add to end of list */
338 tmp
->prev
= list
->prev
;
339 tmp
->prev
->next
= tmp
;
347 static void textbuf_emit(struct textbuf
**buf_p
)
349 struct textbuf
*tmp
, *list
= *buf_p
;
353 if (tmp
->next
== tmp
)
356 tmp
->prev
->next
= tmp
->next
;
357 tmp
->next
->prev
= tmp
->prev
;
361 fputs(tmp
->text
, stdout
);
369 static void insn(const char *insn
, struct storage
*op1
, struct storage
*op2
,
370 const char *comment_in
, unsigned long flags
)
372 struct function
*f
= current_func
;
373 struct atom
*atom
= new_atom(ATOM_INSN
);
375 assert(insn
!= NULL
);
377 strcpy(atom
->insn
, insn
);
378 if (comment_in
&& (*comment_in
))
379 strncpy(atom
->comment
, comment_in
,
380 sizeof(atom
->comment
) - 1);
389 static void emit_unit_pre(const char *basename
)
391 printf("\t.file\t\"%s\"\n", basename
);
394 static void emit_unit_post(void)
396 textbuf_emit(&unit_post_text
);
397 printf("\t.ident\t\"sparse silly x86 backend (built %s)\"\n", __DATE__
);
400 /* conditionally switch sections */
401 static void emit_section(const char *s
)
403 if (s
== current_section
)
405 if (current_section
&& (!strcmp(s
, current_section
)))
412 static void emit_insn_atom(struct function
*f
, struct atom
*atom
)
417 if (atom
->comment
[0])
418 sprintf(comment
, "\t\t# %s", atom
->comment
);
424 strcpy(tmp
, stor_op_name(atom
->op1
));
425 sprintf(s
, "\t%s\t%s, %s%s\n",
426 atom
->insn
, tmp
, stor_op_name(atom
->op2
), comment
);
427 } else if (atom
->op1
)
428 sprintf(s
, "\t%s\t%s%s%s\n",
429 atom
->insn
, stor_op_name(atom
->op1
),
430 comment
[0] ? "\t" : "", comment
);
432 sprintf(s
, "\t%s\t%s%s\n",
434 comment
[0] ? "\t\t" : "", comment
);
436 write(STDOUT_FILENO
, s
, strlen(s
));
439 static void emit_atom_list(struct function
*f
)
443 FOR_EACH_PTR(f
->atom_list
, atom
) {
444 switch (atom
->type
) {
446 ssize_t rc
= write(STDOUT_FILENO
, atom
->text
,
448 (void) rc
; /* FIXME */
452 emit_insn_atom(f
, atom
);
458 static void func_cleanup(struct function
*f
)
460 struct storage
*stor
;
463 FOR_EACH_PTR(f
->pseudo_list
, stor
) {
467 FOR_EACH_PTR(f
->atom_list
, atom
) {
468 if ((atom
->type
== ATOM_TEXT
) && (atom
->text
))
470 if (atom
->flags
& ATOM_FREE_OP1
)
472 if (atom
->flags
& ATOM_FREE_OP2
)
477 free_ptr_list(&f
->pseudo_list
);
481 /* function prologue */
482 static void emit_func_pre(struct symbol
*sym
)
484 const char *name
= show_ident(sym
->ident
);
487 unsigned int i
, argc
= 0, alloc_len
;
489 struct symbol_private
*privbase
;
490 struct storage
*storage_base
;
491 struct symbol
*base_type
= sym
->ctype
.base_type
;
493 FOR_EACH_PTR(base_type
->arguments
, arg
) {
499 (argc
* sizeof(struct symbol
*)) +
500 (argc
* sizeof(struct symbol_private
)) +
501 (argc
* sizeof(struct storage
));
502 mem
= calloc(1, alloc_len
);
504 die("OOM on func info");
506 f
= (struct function
*) mem
;
508 f
->argv
= (struct symbol
**) mem
;
509 mem
+= (argc
* sizeof(struct symbol
*));
510 privbase
= (struct symbol_private
*) mem
;
511 mem
+= (argc
* sizeof(struct symbol_private
));
512 storage_base
= (struct storage
*) mem
;
515 f
->ret_target
= new_label();
518 FOR_EACH_PTR(base_type
->arguments
, arg
) {
520 arg
->aux
= &privbase
[i
];
521 storage_base
[i
].type
= STOR_ARG
;
522 storage_base
[i
].idx
= i
;
523 privbase
[i
].addr
= &storage_base
[i
];
527 assert(current_func
== NULL
);
530 emit_section(".text");
531 if ((sym
->ctype
.modifiers
& MOD_STATIC
) == 0)
532 printf(".globl %s\n", name
);
533 printf("\t.type\t%s, @function\n", name
);
534 printf("%s:\n", name
);
537 /* function epilogue */
538 static void emit_func_post(struct symbol
*sym
, struct storage
*ret_val
)
540 const char *name
= show_ident(sym
->ident
);
541 struct function
*f
= current_func
;
543 int pseudo_nr
= f
->pseudo_nr
;
544 char pseudo_const
[16], jump_target
[16];
546 /* function epilogue */
547 sprintf(pseudo_const
, "$%d", pseudo_nr
* 4);
548 printf("\tsubl\t%s, %%esp\n", pseudo_const
);
550 /* jump target for 'return' statements */
551 sprintf(jump_target
, ".L%d:\n", f
->ret_target
);
552 push_text_atom(f
, jump_target
);
554 /* function prologue */
556 /* FIXME: mem operand hardcoded at 32 bits */
557 emit_move(ret_val
, REG_EAX
, NULL
, NULL
, 0);
560 val
= new_storage(STOR_VALUE
);
561 val
->value
= (long long) (pseudo_nr
* 4);
563 insn("addl", val
, REG_ESP
, NULL
, ATOM_FREE_OP1
);
564 insn("ret", NULL
, NULL
, NULL
, 0);
566 /* output everything to stdout */
567 fflush(stdout
); /* paranoia; needed? */
570 /* function footer */
571 printf("\t.size\t%s, .-%s\n", name
, name
);
577 /* emit object (a.k.a. variable, a.k.a. data) prologue */
578 static void emit_object_pre(const char *name
, unsigned long modifiers
,
579 unsigned long alignment
, unsigned int byte_size
)
581 if ((modifiers
& MOD_STATIC
) == 0)
582 printf(".globl %s\n", name
);
583 emit_section(".data");
585 printf("\t.align %lu\n", alignment
);
586 printf("\t.type\t%s, @object\n", name
);
587 printf("\t.size\t%s, %d\n", name
, byte_size
);
588 printf("%s:\n", name
);
591 /* emit value (only) for an initializer scalar */
592 static void emit_scalar(struct expression
*expr
, unsigned int bit_size
)
597 assert(expr
->type
== EXPR_VALUE
);
599 if (expr
->value
== 0ULL) {
600 printf("\t.zero\t%d\n", bit_size
/ 8);
604 ll
= (long long) expr
->value
;
607 case 8: type
= "byte"; ll
= (char) ll
; break;
608 case 16: type
= "value"; ll
= (short) ll
; break;
609 case 32: type
= "long"; ll
= (int) ll
; break;
610 case 64: type
= "quad"; break;
611 default: type
= NULL
; break;
614 assert(type
!= NULL
);
616 printf("\t.%s\t%Ld\n", type
, ll
);
619 static void emit_global_noinit(const char *name
, unsigned long modifiers
,
620 unsigned long alignment
, unsigned int byte_size
)
624 if (modifiers
& MOD_STATIC
) {
625 sprintf(s
, "\t.local\t%s\n", name
);
626 textbuf_push(&unit_post_text
, s
);
629 sprintf(s
, "\t.comm\t%s,%d,%lu\n", name
, byte_size
, alignment
);
631 sprintf(s
, "\t.comm\t%s,%d\n", name
, byte_size
);
632 textbuf_push(&unit_post_text
, s
);
635 static int ea_current
, ea_last
;
637 static void emit_initializer(struct symbol
*sym
,
638 struct expression
*expr
)
640 int distance
= ea_current
- ea_last
- 1;
643 printf("\t.zero\t%d\n", (sym
->bit_size
/ 8) * distance
);
645 if (expr
->type
== EXPR_VALUE
) {
646 struct symbol
*base_type
= sym
->ctype
.base_type
;
647 assert(base_type
!= NULL
);
649 emit_scalar(expr
, sym
->bit_size
/ base_type
->array_size
);
652 if (expr
->type
!= EXPR_INITIALIZER
)
655 assert(0); /* FIXME */
658 static int sort_array_cmp(const struct expression
*a
,
659 const struct expression
*b
)
661 int a_ofs
= 0, b_ofs
= 0;
663 if (a
->type
== EXPR_POS
)
664 a_ofs
= (int) a
->init_offset
;
665 if (b
->type
== EXPR_POS
)
666 b_ofs
= (int) b
->init_offset
;
668 return a_ofs
- b_ofs
;
671 /* move to front-end? */
672 static void sort_array(struct expression
*expr
)
674 struct expression
*entry
, **list
;
675 unsigned int elem
, sorted
, i
;
678 FOR_EACH_PTR(expr
->expr_list
, entry
) {
685 list
= malloc(sizeof(entry
) * elem
);
687 die("OOM in sort_array");
689 /* this code is no doubt evil and ignores EXPR_INDEX possibly
690 * to its detriment and other nasty things. improvements
695 FOR_EACH_PTR(expr
->expr_list
, entry
) {
696 if ((entry
->type
== EXPR_POS
) || (entry
->type
== EXPR_VALUE
)) {
697 /* add entry to list[], in sorted order */
704 for (i
= 0; i
< sorted
; i
++)
705 if (sort_array_cmp(entry
, list
[i
]) <= 0)
708 /* If inserting into the middle of list[]
709 * instead of appending, we memmove.
710 * This is ugly, but thankfully
711 * uncommon. Input data with tons of
712 * entries very rarely have explicit
713 * offsets. convert to qsort eventually...
716 memmove(&list
[i
+ 1], &list
[i
],
717 (sorted
- i
) * sizeof(entry
));
725 FOR_EACH_PTR(expr
->expr_list
, entry
) {
726 if ((entry
->type
== EXPR_POS
) || (entry
->type
== EXPR_VALUE
))
727 __list
->list
[__i
] = list
[i
++];
732 static void emit_array(struct symbol
*sym
)
734 struct symbol
*base_type
= sym
->ctype
.base_type
;
735 struct expression
*expr
= sym
->initializer
;
736 struct expression
*entry
;
738 assert(base_type
!= NULL
);
744 emit_object_pre(show_ident(sym
->ident
), sym
->ctype
.modifiers
,
745 sym
->ctype
.alignment
,
750 FOR_EACH_PTR(expr
->expr_list
, entry
) {
751 if (entry
->type
== EXPR_VALUE
) {
753 emit_initializer(sym
, entry
);
754 ea_last
= ea_current
;
755 } else if (entry
->type
== EXPR_POS
) {
757 entry
->init_offset
/ (base_type
->bit_size
/ 8);
758 emit_initializer(sym
, entry
->init_expr
);
759 ea_last
= ea_current
;
764 static void emit_one_symbol(struct symbol
*sym
, void *dummy
, int flags
)
769 void emit_unit(const char *basename
, struct symbol_list
*list
)
771 emit_unit_pre(basename
);
772 symbol_iterate(list
, emit_one_symbol
, NULL
);
776 static void emit_copy(struct storage
*src
, struct symbol
*src_ctype
,
777 struct storage
*dest
, struct symbol
*dest_ctype
)
779 /* FIXME: Bitfield move! */
781 emit_move(src
, REG_EAX
, src_ctype
, "begin copy ...", 0);
782 emit_move(REG_EAX
, dest
, dest_ctype
, "... end copy", 0);
785 static void emit_store(struct expression
*dest_expr
, struct storage
*dest
,
786 struct storage
*src
, int bits
)
788 /* FIXME: Bitfield store! */
789 printf("\tst.%d\t\tv%d,[v%d]\n", bits
, src
->pseudo
, dest
->pseudo
);
792 static void emit_scalar_noinit(struct symbol
*sym
)
794 emit_global_noinit(show_ident(sym
->ident
),
795 sym
->ctype
.modifiers
, sym
->ctype
.alignment
,
800 static void emit_array_noinit(struct symbol
*sym
)
802 emit_global_noinit(show_ident(sym
->ident
),
803 sym
->ctype
.modifiers
, sym
->ctype
.alignment
,
804 sym
->array_size
* (sym
->bit_size
/ 8));
808 static const char *opbits(const char *insn
, unsigned int bits
)
810 static char opbits_str
[32];
814 case 8: c
= 'b'; break;
815 case 16: c
= 'w'; break;
816 case 32: c
= 'l'; break;
817 case 64: c
= 'q'; break;
818 default: assert(0); break;
821 sprintf(opbits_str
, "%s%c", insn
, bits
);
826 static void emit_move(struct storage
*src
, struct storage
*dest
,
827 struct symbol
*ctype
, const char *comment
,
831 unsigned int is_signed
;
832 unsigned int is_dest
= (src
->type
== STOR_REG
);
836 bits
= ctype
->bit_size
;
837 is_signed
= type_is_signed(ctype
);
843 if ((dest
->type
== STOR_REG
) && (src
->type
== STOR_REG
)) {
844 insn("mov", src
, dest
, NULL
, 0);
853 if (is_signed
) opname
= "movsxb";
854 else opname
= "movzxb";
861 if (is_signed
) opname
= "movsxw";
862 else opname
= "movzxw";
866 case 32: opname
= "movl"; break;
867 case 64: opname
= "movq"; break;
869 default: assert(0); break;
872 insn(opname
, src
, dest
, comment
, flags
);
875 static struct storage
*emit_compare(struct expression
*expr
)
877 struct storage
*left
= x86_expression(expr
->left
);
878 struct storage
*right
= x86_expression(expr
->right
);
880 const char *opname
= NULL
;
881 unsigned int is_signed
= type_is_signed(expr
->left
->ctype
); /* FIXME */
882 unsigned int right_bits
= expr
->right
->ctype
->bit_size
;
886 if (is_signed
) opname
= "setl";
887 else opname
= "setb";
890 if (is_signed
) opname
= "setg";
891 else opname
= "seta";
894 if (is_signed
) opname
= "setle";
895 else opname
= "setbe";
898 if (is_signed
) opname
= "setge";
899 else opname
= "setae";
902 case SPECIAL_EQUAL
: opname
= "sete"; break;
903 case SPECIAL_NOTEQUAL
: opname
= "setne"; break;
911 insn("xor", REG_EDX
, REG_EDX
, "begin EXPR_COMPARE", 0);
913 /* move op1 into EAX */
914 emit_move(left
, REG_EAX
, expr
->left
->ctype
, NULL
, 0);
916 /* perform comparison, RHS (op1, right) and LHS (op2, EAX) */
917 insn(opbits("cmp", right_bits
), right
, REG_EAX
, NULL
, 0);
919 /* store result of operation, 0 or 1, in DL using SETcc */
920 insn(opname
, REG_DL
, NULL
, NULL
, 0);
922 /* finally, store the result (DL) in a new pseudo / stack slot */
924 emit_move(REG_EDX
, new, NULL
, "end EXPR_COMPARE", 0);
930 * TODO: use new type STOR_VALUE. This will allow us to store
931 * the constant internally, and avoid assigning stack slots to them.
933 static struct storage
*emit_value(struct expression
*expr
)
935 struct storage
*new = new_pseudo();
938 val
= new_storage(STOR_VALUE
);
939 val
->value
= (long long) expr
->value
;
940 insn("movl", val
, new, NULL
, ATOM_FREE_OP1
);
945 static struct storage
*emit_binop(struct expression
*expr
)
947 struct storage
*left
= x86_expression(expr
->left
);
948 struct storage
*right
= x86_expression(expr
->right
);
951 static const char *name
[] = {
952 ['+'] = "addl", ['-'] = "subl",
953 ['*'] = "mull", ['/'] = "divl",
954 ['%'] = "modl", ['&'] = "andl",
955 ['|'] = "orl", ['^'] = "xorl"
957 unsigned int op
= expr
->op
;
960 * FIXME FIXME this routine is so wrong it's not even funny.
961 * On x86 both mod/div are handled with the same instruction.
962 * We don't pay attention to signed/unsigned issues,
963 * and like elsewhere we hardcode the operand size at 32 bits.
966 opname
= show_special(op
);
967 if (op
< sizeof(name
)/sizeof(*name
)) {
969 assert(opname
!= NULL
);
971 assert(0); /* FIXME: no operations other than name[], ATM */
973 /* load op2 into EAX */
974 insn("movl", right
, REG_EAX
, "EXPR_BINOP/COMMA/LOGICAL", 0);
977 insn(opname
, left
, REG_EAX
, NULL
, 0);
979 /* store result (EAX) in new pseudo / stack slot */
981 insn("movl", REG_EAX
, new, "end EXPR_BINOP", 0);
986 static void emit_if_conditional(struct statement
*stmt
)
988 struct function
*f
= current_func
;
989 struct storage
*val
, *target_val
;
991 struct expression
*cond
= stmt
->if_conditional
;
994 /* This is only valid if nobody can jump into the "dead" statement */
996 if (cond
->type
== EXPR_VALUE
) {
997 struct statement
*s
= stmt
->if_true
;
1004 val
= x86_expression(cond
);
1006 /* load 'if' test result into EAX */
1007 insn("movl", val
, REG_EAX
, "begin if conditional", 0);
1010 insn("xorl", REG_ECX
, REG_ECX
, NULL
, 0);
1012 /* compare 'if' test result */
1013 insn("cmpl", REG_EAX
, REG_ECX
, NULL
, 0);
1015 /* create end-of-if label / if-failed labelto jump to,
1016 * and jump to it if the expression returned zero.
1018 target
= new_label();
1019 target_val
= new_storage(STOR_LABEL
);
1020 target_val
->label
= target
;
1021 insn("je", target_val
, NULL
, NULL
, ATOM_FREE_OP1
);
1023 x86_statement(stmt
->if_true
);
1024 if (stmt
->if_false
) {
1025 struct storage
*last_val
;
1028 /* finished generating code for if-true statement.
1029 * add a jump-to-end jump to avoid falling through
1030 * to the if-false statement code.
1033 last_val
= new_storage(STOR_LABEL
);
1034 last_val
->label
= last
;
1035 insn("jmp", last_val
, NULL
, NULL
, ATOM_FREE_OP1
);
1037 /* if we have both if-true and if-false statements,
1038 * the failed-conditional case will fall through to here
1040 sprintf(s
, ".L%d:\n", target
);
1041 push_text_atom(f
, s
);
1044 x86_statement(stmt
->if_false
);
1047 sprintf(s
, ".L%d:\t\t\t\t\t# end if\n", target
);
1048 push_text_atom(f
, s
);
1051 static struct storage
*emit_inc_dec(struct expression
*expr
, int postop
)
1053 struct storage
*addr
= x86_address_gen(expr
->unop
);
1054 struct storage
*retval
;
1055 const char *opname
= expr
->op
== SPECIAL_INCREMENT
? "incl" : "decl";
1057 /* FIXME: don't hardware operand size */
1058 int bits
= expr
->ctype
->bit_size
;
1062 struct storage
*new = new_pseudo();
1064 emit_copy(addr
, expr
->unop
->ctype
, new, NULL
);
1070 insn(opname
, addr
, NULL
, NULL
, 0);
1075 static struct storage
*emit_postop(struct expression
*expr
)
1077 return emit_inc_dec(expr
, 1);
1080 static struct storage
*emit_return_stmt(struct statement
*stmt
)
1082 struct function
*f
= current_func
;
1083 struct expression
*expr
= stmt
->ret_value
;
1084 struct storage
*val
= NULL
;
1087 if (expr
&& expr
->ctype
)
1088 val
= x86_expression(expr
);
1090 sprintf(s
, "\tjmp\t.L%d\n", f
->ret_target
);
1091 push_text_atom(f
, s
);
1096 static void x86_struct_member(struct symbol
*sym
, void *data
, int flags
)
1098 if (flags
& ITERATE_FIRST
)
1100 printf("%s:%d:%ld at offset %ld", show_ident(sym
->ident
), sym
->bit_size
, sym
->ctype
.alignment
, sym
->offset
);
1101 if (sym
->fieldwidth
)
1102 printf("[%d..%d]", sym
->bit_offset
, sym
->bit_offset
+sym
->fieldwidth
-1);
1103 if (flags
& ITERATE_LAST
)
1109 static void x86_symbol(struct symbol
*sym
)
1111 struct symbol
*type
;
1116 type
= sym
->ctype
.base_type
;
1121 * Show actual implementation information
1123 switch (type
->type
) {
1126 if (sym
->initializer
)
1129 emit_array_noinit(sym
);
1133 if (sym
->initializer
) {
1134 emit_object_pre(show_ident(sym
->ident
),
1135 sym
->ctype
.modifiers
,
1136 sym
->ctype
.alignment
,
1138 emit_scalar(sym
->initializer
, sym
->bit_size
);
1141 emit_scalar_noinit(sym
);
1145 symbol_iterate(type
->symbol_list
, x86_struct_member
, NULL
);
1149 symbol_iterate(type
->symbol_list
, x86_struct_member
, NULL
);
1153 struct statement
*stmt
= type
->stmt
;
1155 struct storage
*val
;
1158 val
= x86_statement(stmt
);
1159 emit_func_post(sym
, val
);
1168 if (sym
->initializer
&& (type
->type
!= SYM_BASETYPE
) &&
1169 (type
->type
!= SYM_ARRAY
)) {
1171 x86_expression(sym
->initializer
);
1175 static void x86_symbol_init(struct symbol
*sym
);
1177 static void x86_switch_statement(struct statement
*stmt
)
1179 struct storage
*val
= x86_expression(stmt
->switch_expression
);
1181 printf("\tswitch v%d\n", val
->pseudo
);
1184 * Debugging only: Check that the case list is correct
1185 * by printing it out.
1187 * This is where a _real_ back-end would go through the
1188 * cases to decide whether to use a lookup table or a
1189 * series of comparisons etc
1191 printf("# case table:\n");
1192 FOR_EACH_PTR(stmt
->switch_case
->symbol_list
, sym
) {
1193 struct statement
*case_stmt
= sym
->stmt
;
1194 struct expression
*expr
= case_stmt
->case_expression
;
1195 struct expression
*to
= case_stmt
->case_to
;
1200 if (expr
->type
== EXPR_VALUE
) {
1201 printf(" case %lld", expr
->value
);
1203 if (to
->type
== EXPR_VALUE
) {
1204 printf(" .. %lld", to
->value
);
1206 printf(" .. what?");
1212 printf(": .L%p\n", sym
);
1214 printf("# end case table\n");
1216 x86_statement(stmt
->switch_statement
);
1218 if (stmt
->switch_break
->used
)
1219 printf(".L%p:\n", stmt
->switch_break
);
1222 static void x86_symbol_decl(struct symbol_list
*syms
)
1225 FOR_EACH_PTR(syms
, sym
) {
1226 x86_symbol_init(sym
);
1231 * Print out a statement
1233 static struct storage
*x86_statement(struct statement
*stmt
)
1237 switch (stmt
->type
) {
1239 return emit_return_stmt(stmt
);
1240 case STMT_COMPOUND
: {
1241 struct statement
*s
;
1242 struct storage
*last
= NULL
;
1244 x86_symbol_decl(stmt
->syms
);
1245 FOR_EACH_PTR(stmt
->stmts
, s
) {
1246 last
= x86_statement(s
);
1252 case STMT_EXPRESSION
:
1253 return x86_expression(stmt
->expression
);
1255 emit_if_conditional(stmt
);
1258 x86_switch_statement(stmt
);
1262 printf(".L%p:\n", stmt
->case_label
);
1263 x86_statement(stmt
->case_statement
);
1266 case STMT_ITERATOR
: {
1267 struct statement
*pre_statement
= stmt
->iterator_pre_statement
;
1268 struct expression
*pre_condition
= stmt
->iterator_pre_condition
;
1269 struct statement
*statement
= stmt
->iterator_statement
;
1270 struct statement
*post_statement
= stmt
->iterator_post_statement
;
1271 struct expression
*post_condition
= stmt
->iterator_post_condition
;
1272 int loop_top
= 0, loop_bottom
= 0;
1273 struct storage
*val
;
1275 x86_symbol_decl(stmt
->iterator_syms
);
1276 x86_statement(pre_statement
);
1277 if (pre_condition
) {
1278 if (pre_condition
->type
== EXPR_VALUE
) {
1279 if (!pre_condition
->value
) {
1280 loop_bottom
= new_label();
1281 printf("\tjmp\t\t.L%d\n", loop_bottom
);
1284 loop_bottom
= new_label();
1285 val
= x86_expression(pre_condition
);
1286 printf("\tje\t\tv%d, .L%d\n", val
->pseudo
, loop_bottom
);
1289 if (!post_condition
|| post_condition
->type
!= EXPR_VALUE
|| post_condition
->value
) {
1290 loop_top
= new_label();
1291 printf(".L%d:\n", loop_top
);
1293 x86_statement(statement
);
1294 if (stmt
->iterator_continue
->used
)
1295 printf(".L%p:\n", stmt
->iterator_continue
);
1296 x86_statement(post_statement
);
1297 if (!post_condition
) {
1298 printf("\tjmp\t\t.L%d\n", loop_top
);
1299 } else if (post_condition
->type
== EXPR_VALUE
) {
1300 if (post_condition
->value
)
1301 printf("\tjmp\t\t.L%d\n", loop_top
);
1303 val
= x86_expression(post_condition
);
1304 printf("\tjne\t\tv%d, .L%d\n", val
->pseudo
, loop_top
);
1306 if (stmt
->iterator_break
->used
)
1307 printf(".L%p:\n", stmt
->iterator_break
);
1309 printf(".L%d:\n", loop_bottom
);
1316 printf(".L%p:\n", stmt
->label_identifier
);
1317 x86_statement(stmt
->label_statement
);
1321 if (stmt
->goto_expression
) {
1322 struct storage
*val
= x86_expression(stmt
->goto_expression
);
1323 printf("\tgoto *v%d\n", val
->pseudo
);
1325 printf("\tgoto .L%p\n", stmt
->goto_label
);
1329 printf("\tasm( .... )\n");
1336 static struct storage
*x86_call_expression(struct expression
*expr
)
1338 struct function
*f
= current_func
;
1339 struct symbol
*direct
;
1340 struct expression
*arg
, *fn
;
1341 struct storage
*retval
, *fncall
;
1345 warn(expr
->pos
, "\tcall with no type!");
1350 FOR_EACH_PTR_REVERSE(expr
->args
, arg
) {
1351 struct storage
*new = x86_expression(arg
);
1352 int size
= arg
->ctype
->bit_size
;
1354 /* FIXME: pay attention to 'size' */
1355 insn("pushl", new, NULL
,
1356 !framesize
? "begin function call" : NULL
, 0);
1358 framesize
+= size
>> 3;
1359 } END_FOR_EACH_PTR_REVERSE
;
1363 /* Remove dereference, if any */
1365 if (fn
->type
== EXPR_PREOP
) {
1366 if (fn
->unop
->type
== EXPR_SYMBOL
) {
1367 struct symbol
*sym
= fn
->unop
->symbol
;
1368 if (sym
->ctype
.base_type
->type
== SYM_FN
)
1374 sprintf(s
, "\tcall\t%s\n", show_ident(direct
->ident
));
1375 push_text_atom(f
, s
);
1377 fncall
= x86_expression(fn
);
1378 printf("\tcall\t*v%d\n", fncall
->pseudo
);
1381 /* FIXME: pay attention to BITS_IN_POINTER */
1383 struct storage
*val
= new_storage(STOR_VALUE
);
1384 val
->value
= (long long) framesize
;
1385 insn("addl", val
, REG_ESP
, "end function call", ATOM_FREE_OP1
);
1388 retval
= new_pseudo();
1389 printf("\tmov.%d\t\tv%d,retval\n", expr
->ctype
->bit_size
, retval
->pseudo
);
1393 static struct storage
*x86_regular_preop(struct expression
*expr
)
1395 struct storage
*target
= x86_expression(expr
->unop
);
1396 struct storage
*new = new_pseudo();
1397 static const char *name
[] = {
1398 ['!'] = "nonzero", ['-'] = "neg",
1401 unsigned int op
= expr
->op
;
1404 opname
= show_special(op
);
1405 if (op
< sizeof(name
)/sizeof(*name
))
1407 printf("\t%s.%d\t\tv%d,v%d\n", opname
, expr
->ctype
->bit_size
, new->pseudo
, target
->pseudo
);
1412 * FIXME! Not all accesses are memory loads. We should
1413 * check what kind of symbol is behind the dereference.
1415 static struct storage
*x86_address_gen(struct expression
*expr
)
1417 if (expr
->type
== EXPR_PREOP
)
1418 return x86_expression(expr
->unop
);
1419 return x86_expression(expr
->address
);
1422 static struct storage
*x86_assignment(struct expression
*expr
)
1424 struct expression
*target
= expr
->left
;
1425 struct storage
*val
, *addr
;
1431 bits
= expr
->ctype
->bit_size
;
1432 val
= x86_expression(expr
->right
);
1433 addr
= x86_address_gen(target
);
1434 emit_copy(val
, expr
->right
->ctype
, addr
, expr
->left
->ctype
);
1438 static int x86_initialization(struct symbol
*sym
, struct expression
*expr
)
1440 struct storage
*val
, *addr
;
1446 bits
= expr
->ctype
->bit_size
;
1447 val
= x86_expression(expr
);
1448 addr
= x86_symbol_expr(sym
);
1449 // FIXME! The "target" expression is for bitfield store information.
1450 // Leave it NULL, which works fine.
1451 emit_store(NULL
, addr
, val
, bits
);
1455 static struct storage
*x86_access(struct expression
*expr
)
1457 return x86_address_gen(expr
);
1460 static struct storage
*x86_preop(struct expression
*expr
)
1463 * '*' is an lvalue access, and is fundamentally different
1464 * from an arithmetic operation. Maybe it should have an
1465 * expression type of its own..
1467 if (expr
->op
== '*')
1468 return x86_access(expr
);
1469 if (expr
->op
== SPECIAL_INCREMENT
|| expr
->op
== SPECIAL_DECREMENT
)
1470 return emit_inc_dec(expr
, 0);
1471 return x86_regular_preop(expr
);
1474 static struct storage
*x86_symbol_expr(struct symbol
*sym
)
1476 struct storage
*new = new_pseudo();
1478 if (sym
->ctype
.modifiers
& (MOD_TOPLEVEL
| MOD_EXTERN
| MOD_STATIC
)) {
1479 printf("\tmovi.%d\t\tv%d,$%s\n", BITS_IN_POINTER
, new->pseudo
, show_ident(sym
->ident
));
1482 if (sym
->ctype
.modifiers
& MOD_ADDRESSABLE
) {
1483 printf("\taddi.%d\t\tv%d,vFP,$%lld\n", BITS_IN_POINTER
, new->pseudo
, sym
->value
);
1486 printf("\taddi.%d\t\tv%d,vFP,$offsetof(%s:%p)\n", BITS_IN_POINTER
, new->pseudo
, show_ident(sym
->ident
), sym
);
1490 static void x86_symbol_init(struct symbol
*sym
)
1492 struct symbol_private
*priv
= sym
->aux
;
1493 struct expression
*expr
= sym
->initializer
;
1494 struct storage
*new;
1497 new = x86_expression(expr
);
1502 priv
= calloc(1, sizeof(*priv
));
1504 /* FIXME: leak! we don't free... */
1505 /* (well, we don't free symbols either) */
1511 static int type_is_signed(struct symbol
*sym
)
1513 if (sym
->type
== SYM_NODE
)
1514 sym
= sym
->ctype
.base_type
;
1515 if (sym
->type
== SYM_PTR
)
1517 return !(sym
->ctype
.modifiers
& MOD_UNSIGNED
);
1520 static struct storage
*x86_cast_expr(struct expression
*expr
)
1522 struct symbol
*old_type
, *new_type
;
1523 struct storage
*op
= x86_expression(expr
->cast_expression
);
1524 int oldbits
, newbits
;
1526 struct storage
*new;
1528 old_type
= expr
->cast_expression
->ctype
;
1529 new_type
= expr
->cast_type
;
1531 oldbits
= old_type
->bit_size
;
1532 newbits
= new_type
->bit_size
;
1533 if (oldbits
>= newbits
)
1536 is_signed
= type_is_signed(old_type
);
1538 printf("\tsext%d.%d\tv%d,v%d\n", oldbits
, newbits
, new->pseudo
, op
->pseudo
);
1540 printf("\tandl.%d\t\tv%d,v%d,$%lu\n", newbits
, new->pseudo
, op
->pseudo
, (1UL << oldbits
)-1);
1545 static struct storage
*show_string_expr(struct expression
*expr
)
1547 struct storage
*new = new_pseudo();
1549 printf("\tmovi.%d\t\tv%d,&%s\n", BITS_IN_POINTER
, new->pseudo
,
1550 show_string(expr
->string
));
1554 static struct storage
*x86_bitfield_expr(struct expression
*expr
)
1556 return x86_access(expr
);
1559 static struct storage
*x86_label_expr(struct expression
*expr
)
1561 struct storage
*new = new_pseudo();
1562 printf("\tmovi.%d\t\tv%d,.L%p\n",BITS_IN_POINTER
, new->pseudo
, expr
->label_symbol
);
1566 static struct storage
*x86_conditional_expr(struct expression
*expr
)
1568 struct storage
*cond
= x86_expression(expr
->conditional
);
1569 struct storage
*true = x86_expression(expr
->cond_true
);
1570 struct storage
*false = x86_expression(expr
->cond_false
);
1571 struct storage
*new = new_pseudo();
1575 printf("[v%d]\tcmov.%d\t\tv%d,v%d,v%d\n",
1576 cond
->pseudo
, expr
->ctype
->bit_size
, new->pseudo
,
1577 true->pseudo
, false->pseudo
);
1581 static struct storage
*x86_statement_expr(struct expression
*expr
)
1583 return x86_statement(expr
->statement
);
1586 static int x86_position_expr(struct expression
*expr
, struct symbol
*base
)
1588 struct storage
*new = x86_expression(expr
->init_expr
);
1589 struct symbol
*ctype
= expr
->init_sym
;
1591 printf("\tinsert v%d at [%d:%d] of %s\n", new->pseudo
,
1592 expr
->init_offset
, ctype
->bit_offset
,
1593 show_ident(base
->ident
));
1597 static void x86_initializer_expr(struct expression
*expr
, struct symbol
*ctype
)
1599 struct expression
*entry
;
1601 FOR_EACH_PTR(expr
->expr_list
, entry
) {
1602 // Nested initializers have their positions already
1603 // recursively calculated - just output them too
1604 if (entry
->type
== EXPR_INITIALIZER
) {
1605 x86_initializer_expr(entry
, ctype
);
1609 // Ignore initializer indexes and identifiers - the
1610 // evaluator has taken them into account
1611 if (entry
->type
== EXPR_IDENTIFIER
|| entry
->type
== EXPR_INDEX
)
1613 if (entry
->type
== EXPR_POS
) {
1614 x86_position_expr(entry
, ctype
);
1617 x86_initialization(ctype
, entry
);
1621 static struct storage
*x86_symbol_expr_init(struct symbol
*sym
)
1623 struct expression
*expr
= sym
->initializer
;
1624 struct symbol_private
*priv
= sym
->aux
;
1627 x86_initializer_expr(expr
, expr
->ctype
);
1630 fprintf(stderr
, "WARNING! priv == NULL\n");
1631 priv
= calloc(1, sizeof(*priv
));
1633 priv
->addr
= new_pseudo(); /* this is wrong! */
1640 * Print out an expression. Return the pseudo that contains the
1643 static struct storage
*x86_expression(struct expression
*expr
)
1649 struct position
*pos
= &expr
->pos
;
1650 printf("\tno type at %s:%d:%d\n",
1651 input_streams
[pos
->stream
].name
,
1652 pos
->line
, pos
->pos
);
1656 switch (expr
->type
) {
1658 return x86_call_expression(expr
);
1660 case EXPR_ASSIGNMENT
:
1661 return x86_assignment(expr
);
1664 return emit_compare(expr
);
1668 return emit_binop(expr
);
1670 return x86_preop(expr
);
1672 return emit_postop(expr
);
1674 return x86_symbol_expr_init(expr
->symbol
);
1677 warn(expr
->pos
, "invalid expression after evaluation");
1680 return x86_cast_expr(expr
);
1682 return emit_value(expr
);
1684 return show_string_expr(expr
);
1686 return x86_bitfield_expr(expr
);
1687 case EXPR_INITIALIZER
:
1688 x86_initializer_expr(expr
, expr
->ctype
);
1690 case EXPR_CONDITIONAL
:
1691 return x86_conditional_expr(expr
);
1692 case EXPR_STATEMENT
:
1693 return x86_statement_expr(expr
);
1695 return x86_label_expr(expr
);
1697 // None of these should exist as direct expressions: they are only
1698 // valid as sub-expressions of initializers.
1700 warn(expr
->pos
, "unable to show plain initializer position expression");
1702 case EXPR_IDENTIFIER
:
1703 warn(expr
->pos
, "unable to show identifier expression");
1706 warn(expr
->pos
, "unable to show index expression");