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
;
43 struct ptr_list
*str_list
;
50 STOR_PSEUDO
, /* variable stored on the stack */
51 STOR_ARG
, /* function argument */
52 STOR_SYM
, /* a symbol we can directly ref in the asm */
53 STOR_REG
, /* scratch register */
54 STOR_VALUE
, /* integer constant */
55 STOR_LABEL
, /* label / jump target */
63 enum storage_type type
;
94 STOR_LABEL_VAL
= (1 << 0),
97 struct symbol_private
{
108 ATOM_FREE_OP1
= (1 << 0),
109 ATOM_FREE_OP2
= (1 << 1),
118 unsigned int text_len
; /* w/o terminating null */
121 /* stuff for insns */
130 /* stuff for C strings */
132 struct string
*string
;
139 struct function
*current_func
= NULL
;
140 struct textbuf
*unit_post_text
= NULL
;
141 static const char *current_section
;
143 static struct reg_info reg_info_table
[] = {
151 static struct storage hardreg_storage_table
[] = {
154 .reg
= ®_info_table
[0],
159 .reg
= ®_info_table
[1],
164 .reg
= ®_info_table
[2],
169 .reg
= ®_info_table
[3],
174 .reg
= ®_info_table
[4],
178 #define REG_EAX (&hardreg_storage_table[0])
179 #define REG_ECX (&hardreg_storage_table[1])
180 #define REG_EDX (&hardreg_storage_table[2])
181 #define REG_ESP (&hardreg_storage_table[3])
182 #define REG_DL (&hardreg_storage_table[4])
185 static void emit_move(struct storage
*src
, struct storage
*dest
,
186 struct symbol
*ctype
, const char *comment
,
187 unsigned long flags
);
188 static int type_is_signed(struct symbol
*sym
);
189 static struct storage
*x86_address_gen(struct expression
*expr
);
190 static struct storage
*x86_symbol_expr(struct symbol
*sym
);
191 static void x86_symbol(struct symbol
*sym
);
192 static struct storage
*x86_statement(struct statement
*stmt
);
193 static struct storage
*x86_expression(struct expression
*expr
);
196 static inline unsigned int pseudo_offset(struct storage
*s
)
198 if (s
->type
!= STOR_PSEUDO
)
199 return 123456; /* intentionally bogus value */
201 return ((s
->pseudo
- 1) * 4);
204 static inline unsigned int arg_offset(struct storage
*s
)
206 if (s
->type
!= STOR_ARG
)
207 return 123456; /* intentionally bogus value */
209 /* FIXME: this is wrong wrong wrong */
210 return (current_func
->pseudo_nr
+ 1 + s
->idx
) * 4;
213 static const char *pretty_offset(int ofs
)
215 static char esp_buf
[64];
218 sprintf(esp_buf
, "%d(%%esp)", ofs
);
220 strcpy(esp_buf
, "(%esp)");
225 static void stor_sym_init(struct symbol
*sym
)
227 struct storage
*stor
;
228 struct symbol_private
*priv
;
230 priv
= calloc(1, sizeof(*priv
) + sizeof(*stor
));
232 die("OOM in stor_sym_init");
234 stor
= (struct storage
*) (priv
+ 1);
237 stor
->type
= STOR_SYM
;
241 static const char *stor_op_name(struct storage
*s
, unsigned long flags
)
243 static char name
[32];
247 strcpy(name
, pretty_offset((int) pseudo_offset(s
)));
250 strcpy(name
, pretty_offset((int) arg_offset(s
)));
253 strcpy(name
, show_ident(s
->sym
->ident
));
256 strcpy(name
, s
->reg
->name
);
259 sprintf(name
, "$%Ld", s
->value
);
262 sprintf(name
, "%s.L%d", flags
& STOR_LABEL_VAL
? "$" : "",
270 static struct atom
*new_atom(enum atom_type type
)
274 atom
= calloc(1, sizeof(*atom
)); /* TODO: chunked alloc */
283 static inline void push_cstring(struct function
*f
, struct string
*str
,
288 atom
= new_atom(ATOM_CSTR
);
292 add_ptr_list(&f
->str_list
, atom
); /* note: _not_ atom_list */
295 static inline void push_atom(struct function
*f
, struct atom
*atom
)
297 add_ptr_list(&f
->atom_list
, atom
);
300 static void push_text_atom(struct function
*f
, const char *text
)
302 struct atom
*atom
= new_atom(ATOM_TEXT
);
304 atom
->text
= strdup(text
);
305 atom
->text_len
= strlen(text
);
310 static struct storage
*new_storage(enum storage_type type
)
312 struct storage
*stor
;
314 stor
= calloc(1, sizeof(*stor
));
316 die("OOM in new_storage");
323 static struct storage
*new_pseudo(void)
325 struct function
*f
= current_func
;
326 struct storage
*stor
;
330 stor
= new_storage(STOR_PSEUDO
);
331 stor
->type
= STOR_PSEUDO
;
332 stor
->pseudo
= ++f
->pseudo_nr
;
334 add_ptr_list(&f
->pseudo_list
, stor
);
339 static int new_label(void)
341 static int label
= 0;
345 static void textbuf_push(struct textbuf
**buf_p
, const char *text
)
347 struct textbuf
*tmp
, *list
= *buf_p
;
348 unsigned int text_len
= strlen(text
);
349 unsigned int alloc_len
= text_len
+ 1 + sizeof(*list
);
351 tmp
= calloc(1, alloc_len
);
353 die("OOM on textbuf alloc");
355 tmp
->text
= ((void *) tmp
) + sizeof(*tmp
);
356 memcpy(tmp
->text
, text
, text_len
+ 1);
359 /* add to end of list */
364 tmp
->prev
= list
->prev
;
365 tmp
->prev
->next
= tmp
;
373 static void textbuf_emit(struct textbuf
**buf_p
)
375 struct textbuf
*tmp
, *list
= *buf_p
;
379 if (tmp
->next
== tmp
)
382 tmp
->prev
->next
= tmp
->next
;
383 tmp
->next
->prev
= tmp
->prev
;
387 fputs(tmp
->text
, stdout
);
395 static void insn(const char *insn
, struct storage
*op1
, struct storage
*op2
,
396 const char *comment_in
, unsigned long flags
)
398 struct function
*f
= current_func
;
399 struct atom
*atom
= new_atom(ATOM_INSN
);
401 assert(insn
!= NULL
);
403 strcpy(atom
->insn
, insn
);
404 if (comment_in
&& (*comment_in
))
405 strncpy(atom
->comment
, comment_in
,
406 sizeof(atom
->comment
) - 1);
415 static void emit_unit_pre(const char *basename
)
417 printf("\t.file\t\"%s\"\n", basename
);
420 static void emit_unit_post(void)
422 textbuf_emit(&unit_post_text
);
423 printf("\t.ident\t\"sparse silly x86 backend (built %s)\"\n", __DATE__
);
426 /* conditionally switch sections */
427 static void emit_section(const char *s
)
429 if (s
== current_section
)
431 if (current_section
&& (!strcmp(s
, current_section
)))
438 static void emit_insn_atom(struct function
*f
, struct atom
*atom
)
442 struct storage
*op1
= atom
->op1
;
443 struct storage
*op2
= atom
->op2
;
445 if (atom
->comment
[0])
446 sprintf(comment
, "\t\t# %s", atom
->comment
);
452 strcpy(tmp
, stor_op_name(op1
, op1
->flags
));
453 sprintf(s
, "\t%s\t%s, %s%s\n",
454 atom
->insn
, tmp
, stor_op_name(op2
, op2
->flags
), comment
);
455 } else if (atom
->op1
)
456 sprintf(s
, "\t%s\t%s%s%s\n",
457 atom
->insn
, stor_op_name(op1
, op1
->flags
),
458 comment
[0] ? "\t" : "", comment
);
460 sprintf(s
, "\t%s\t%s%s\n",
462 comment
[0] ? "\t\t" : "", comment
);
464 write(STDOUT_FILENO
, s
, strlen(s
));
467 static void emit_atom_list(struct function
*f
)
471 FOR_EACH_PTR(f
->atom_list
, atom
) {
472 switch (atom
->type
) {
474 ssize_t rc
= write(STDOUT_FILENO
, atom
->text
,
476 (void) rc
; /* FIXME */
480 emit_insn_atom(f
, atom
);
489 static void emit_string_list(struct function
*f
)
493 emit_section(".section\t.rodata");
495 FOR_EACH_PTR(f
->str_list
, atom
) {
496 /* FIXME: escape " in string */
497 printf(".L%d:\n", atom
->label
);
498 printf("\t.string\t%s\n", show_string(atom
->string
));
504 static void func_cleanup(struct function
*f
)
506 struct storage
*stor
;
509 FOR_EACH_PTR(f
->pseudo_list
, stor
) {
513 FOR_EACH_PTR(f
->atom_list
, atom
) {
514 if ((atom
->type
== ATOM_TEXT
) && (atom
->text
))
516 if (atom
->flags
& ATOM_FREE_OP1
)
518 if (atom
->flags
& ATOM_FREE_OP2
)
523 free_ptr_list(&f
->pseudo_list
);
527 /* function prologue */
528 static void emit_func_pre(struct symbol
*sym
)
532 unsigned int i
, argc
= 0, alloc_len
;
534 struct symbol_private
*privbase
;
535 struct storage
*storage_base
;
536 struct symbol
*base_type
= sym
->ctype
.base_type
;
538 FOR_EACH_PTR(base_type
->arguments
, arg
) {
544 (argc
* sizeof(struct symbol
*)) +
545 (argc
* sizeof(struct symbol_private
)) +
546 (argc
* sizeof(struct storage
));
547 mem
= calloc(1, alloc_len
);
549 die("OOM on func info");
551 f
= (struct function
*) mem
;
553 f
->argv
= (struct symbol
**) mem
;
554 mem
+= (argc
* sizeof(struct symbol
*));
555 privbase
= (struct symbol_private
*) mem
;
556 mem
+= (argc
* sizeof(struct symbol_private
));
557 storage_base
= (struct storage
*) mem
;
560 f
->ret_target
= new_label();
563 FOR_EACH_PTR(base_type
->arguments
, arg
) {
565 arg
->aux
= &privbase
[i
];
566 storage_base
[i
].type
= STOR_ARG
;
567 storage_base
[i
].idx
= i
;
568 privbase
[i
].addr
= &storage_base
[i
];
572 assert(current_func
== NULL
);
576 /* function epilogue */
577 static void emit_func_post(struct symbol
*sym
, struct storage
*ret_val
)
579 const char *name
= show_ident(sym
->ident
);
580 struct function
*f
= current_func
;
582 int pseudo_nr
= f
->pseudo_nr
;
583 char pseudo_const
[16], jump_target
[16];
588 /* function prologue */
589 emit_section(".text");
590 if ((sym
->ctype
.modifiers
& MOD_STATIC
) == 0)
591 printf(".globl %s\n", name
);
592 printf("\t.type\t%s, @function\n", name
);
593 printf("%s:\n", name
);
594 sprintf(pseudo_const
, "$%d", pseudo_nr
* 4);
595 printf("\tsubl\t%s, %%esp\n", pseudo_const
);
597 /* function epilogue */
599 /* jump target for 'return' statements */
600 sprintf(jump_target
, ".L%d:\n", f
->ret_target
);
601 push_text_atom(f
, jump_target
);
604 /* FIXME: mem operand hardcoded at 32 bits */
605 emit_move(ret_val
, REG_EAX
, NULL
, NULL
, 0);
608 val
= new_storage(STOR_VALUE
);
609 val
->value
= (long long) (pseudo_nr
* 4);
611 insn("addl", val
, REG_ESP
, NULL
, ATOM_FREE_OP1
);
612 insn("ret", NULL
, NULL
, NULL
, 0);
614 /* output everything to stdout */
615 fflush(stdout
); /* paranoia; needed? */
618 /* function footer */
619 printf("\t.size\t%s, .-%s\n", name
, name
);
625 /* emit object (a.k.a. variable, a.k.a. data) prologue */
626 static void emit_object_pre(const char *name
, unsigned long modifiers
,
627 unsigned long alignment
, unsigned int byte_size
)
629 if ((modifiers
& MOD_STATIC
) == 0)
630 printf(".globl %s\n", name
);
631 emit_section(".data");
633 printf("\t.align %lu\n", alignment
);
634 printf("\t.type\t%s, @object\n", name
);
635 printf("\t.size\t%s, %d\n", name
, byte_size
);
636 printf("%s:\n", name
);
639 /* emit value (only) for an initializer scalar */
640 static void emit_scalar(struct expression
*expr
, unsigned int bit_size
)
645 assert(expr
->type
== EXPR_VALUE
);
647 if (expr
->value
== 0ULL) {
648 printf("\t.zero\t%d\n", bit_size
/ 8);
652 ll
= (long long) expr
->value
;
655 case 8: type
= "byte"; ll
= (char) ll
; break;
656 case 16: type
= "value"; ll
= (short) ll
; break;
657 case 32: type
= "long"; ll
= (int) ll
; break;
658 case 64: type
= "quad"; break;
659 default: type
= NULL
; break;
662 assert(type
!= NULL
);
664 printf("\t.%s\t%Ld\n", type
, ll
);
667 static void emit_global_noinit(const char *name
, unsigned long modifiers
,
668 unsigned long alignment
, unsigned int byte_size
)
672 if (modifiers
& MOD_STATIC
) {
673 sprintf(s
, "\t.local\t%s\n", name
);
674 textbuf_push(&unit_post_text
, s
);
677 sprintf(s
, "\t.comm\t%s,%d,%lu\n", name
, byte_size
, alignment
);
679 sprintf(s
, "\t.comm\t%s,%d\n", name
, byte_size
);
680 textbuf_push(&unit_post_text
, s
);
683 static int ea_current
, ea_last
;
685 static void emit_initializer(struct symbol
*sym
,
686 struct expression
*expr
)
688 int distance
= ea_current
- ea_last
- 1;
691 printf("\t.zero\t%d\n", (sym
->bit_size
/ 8) * distance
);
693 if (expr
->type
== EXPR_VALUE
) {
694 struct symbol
*base_type
= sym
->ctype
.base_type
;
695 assert(base_type
!= NULL
);
697 emit_scalar(expr
, sym
->bit_size
/ base_type
->array_size
);
700 if (expr
->type
!= EXPR_INITIALIZER
)
703 assert(0); /* FIXME */
706 static int sort_array_cmp(const struct expression
*a
,
707 const struct expression
*b
)
709 int a_ofs
= 0, b_ofs
= 0;
711 if (a
->type
== EXPR_POS
)
712 a_ofs
= (int) a
->init_offset
;
713 if (b
->type
== EXPR_POS
)
714 b_ofs
= (int) b
->init_offset
;
716 return a_ofs
- b_ofs
;
719 /* move to front-end? */
720 static void sort_array(struct expression
*expr
)
722 struct expression
*entry
, **list
;
723 unsigned int elem
, sorted
, i
;
726 FOR_EACH_PTR(expr
->expr_list
, entry
) {
733 list
= malloc(sizeof(entry
) * elem
);
735 die("OOM in sort_array");
737 /* this code is no doubt evil and ignores EXPR_INDEX possibly
738 * to its detriment and other nasty things. improvements
743 FOR_EACH_PTR(expr
->expr_list
, entry
) {
744 if ((entry
->type
== EXPR_POS
) || (entry
->type
== EXPR_VALUE
)) {
745 /* add entry to list[], in sorted order */
752 for (i
= 0; i
< sorted
; i
++)
753 if (sort_array_cmp(entry
, list
[i
]) <= 0)
756 /* If inserting into the middle of list[]
757 * instead of appending, we memmove.
758 * This is ugly, but thankfully
759 * uncommon. Input data with tons of
760 * entries very rarely have explicit
761 * offsets. convert to qsort eventually...
764 memmove(&list
[i
+ 1], &list
[i
],
765 (sorted
- i
) * sizeof(entry
));
773 FOR_EACH_PTR(expr
->expr_list
, entry
) {
774 if ((entry
->type
== EXPR_POS
) || (entry
->type
== EXPR_VALUE
))
775 __list
->list
[__i
] = list
[i
++];
780 static void emit_array(struct symbol
*sym
)
782 struct symbol
*base_type
= sym
->ctype
.base_type
;
783 struct expression
*expr
= sym
->initializer
;
784 struct expression
*entry
;
786 assert(base_type
!= NULL
);
792 emit_object_pre(show_ident(sym
->ident
), sym
->ctype
.modifiers
,
793 sym
->ctype
.alignment
,
798 FOR_EACH_PTR(expr
->expr_list
, entry
) {
799 if (entry
->type
== EXPR_VALUE
) {
801 emit_initializer(sym
, entry
);
802 ea_last
= ea_current
;
803 } else if (entry
->type
== EXPR_POS
) {
805 entry
->init_offset
/ (base_type
->bit_size
/ 8);
806 emit_initializer(sym
, entry
->init_expr
);
807 ea_last
= ea_current
;
812 static void emit_one_symbol(struct symbol
*sym
, void *dummy
, int flags
)
817 void emit_unit(const char *basename
, struct symbol_list
*list
)
819 emit_unit_pre(basename
);
820 symbol_iterate(list
, emit_one_symbol
, NULL
);
824 static void emit_copy(struct storage
*src
, struct symbol
*src_ctype
,
825 struct storage
*dest
, struct symbol
*dest_ctype
)
827 /* FIXME: Bitfield move! */
829 emit_move(src
, REG_EAX
, src_ctype
, "begin copy ..", 0);
830 emit_move(REG_EAX
, dest
, dest_ctype
, ".... end copy", 0);
833 static void emit_store(struct expression
*dest_expr
, struct storage
*dest
,
834 struct storage
*src
, int bits
)
836 /* FIXME: Bitfield store! */
837 printf("\tst.%d\t\tv%d,[v%d]\n", bits
, src
->pseudo
, dest
->pseudo
);
840 static void emit_scalar_noinit(struct symbol
*sym
)
842 emit_global_noinit(show_ident(sym
->ident
),
843 sym
->ctype
.modifiers
, sym
->ctype
.alignment
,
848 static void emit_array_noinit(struct symbol
*sym
)
850 emit_global_noinit(show_ident(sym
->ident
),
851 sym
->ctype
.modifiers
, sym
->ctype
.alignment
,
852 sym
->array_size
* (sym
->bit_size
/ 8));
856 static const char *opbits(const char *insn
, unsigned int bits
)
858 static char opbits_str
[32];
862 case 8: c
= 'b'; break;
863 case 16: c
= 'w'; break;
864 case 32: c
= 'l'; break;
865 case 64: c
= 'q'; break;
866 default: assert(0); break;
869 sprintf(opbits_str
, "%s%c", insn
, bits
);
874 static void emit_move(struct storage
*src
, struct storage
*dest
,
875 struct symbol
*ctype
, const char *comment
,
879 unsigned int is_signed
;
880 unsigned int is_dest
= (src
->type
== STOR_REG
);
884 bits
= ctype
->bit_size
;
885 is_signed
= type_is_signed(ctype
);
891 if ((dest
->type
== STOR_REG
) && (src
->type
== STOR_REG
)) {
892 insn("mov", src
, dest
, NULL
, 0);
901 if (is_signed
) opname
= "movsxb";
902 else opname
= "movzxb";
909 if (is_signed
) opname
= "movsxw";
910 else opname
= "movzxw";
914 case 32: opname
= "movl"; break;
915 case 64: opname
= "movq"; break;
917 default: assert(0); break;
920 insn(opname
, src
, dest
, comment
, flags
);
923 static struct storage
*emit_compare(struct expression
*expr
)
925 struct storage
*left
= x86_expression(expr
->left
);
926 struct storage
*right
= x86_expression(expr
->right
);
928 const char *opname
= NULL
;
929 unsigned int is_signed
= type_is_signed(expr
->left
->ctype
); /* FIXME */
930 unsigned int right_bits
= expr
->right
->ctype
->bit_size
;
934 if (is_signed
) opname
= "setl";
935 else opname
= "setb";
938 if (is_signed
) opname
= "setg";
939 else opname
= "seta";
942 if (is_signed
) opname
= "setle";
943 else opname
= "setbe";
946 if (is_signed
) opname
= "setge";
947 else opname
= "setae";
950 case SPECIAL_EQUAL
: opname
= "sete"; break;
951 case SPECIAL_NOTEQUAL
: opname
= "setne"; break;
959 insn("xor", REG_EDX
, REG_EDX
, "begin EXPR_COMPARE", 0);
961 /* move op1 into EAX */
962 emit_move(left
, REG_EAX
, expr
->left
->ctype
, NULL
, 0);
964 /* perform comparison, RHS (op1, right) and LHS (op2, EAX) */
965 insn(opbits("cmp", right_bits
), right
, REG_EAX
, NULL
, 0);
967 /* store result of operation, 0 or 1, in DL using SETcc */
968 insn(opname
, REG_DL
, NULL
, NULL
, 0);
970 /* finally, store the result (DL) in a new pseudo / stack slot */
972 emit_move(REG_EDX
, new, NULL
, "end EXPR_COMPARE", 0);
977 static struct storage
*emit_value(struct expression
*expr
)
979 #if 0 /* old and slow way */
980 struct storage
*new = new_pseudo();
983 val
= new_storage(STOR_VALUE
);
984 val
->value
= (long long) expr
->value
;
985 insn("movl", val
, new, NULL
, ATOM_FREE_OP1
);
991 val
= new_storage(STOR_VALUE
);
992 val
->value
= (long long) expr
->value
;
994 return val
; /* FIXME: memory leak */
998 static struct storage
*emit_binop(struct expression
*expr
)
1000 struct storage
*left
= x86_expression(expr
->left
);
1001 struct storage
*right
= x86_expression(expr
->right
);
1002 struct storage
*new;
1004 static const char *name
[] = {
1005 ['+'] = "addl", ['-'] = "subl",
1006 ['*'] = "mull", ['/'] = "divl",
1007 ['%'] = "modl", ['&'] = "andl",
1008 ['|'] = "orl", ['^'] = "xorl"
1010 unsigned int op
= expr
->op
;
1013 * FIXME FIXME this routine is so wrong it's not even funny.
1014 * On x86 both mod/div are handled with the same instruction.
1015 * We don't pay attention to signed/unsigned issues,
1016 * and like elsewhere we hardcode the operand size at 32 bits.
1019 opname
= show_special(op
);
1020 if (op
< sizeof(name
)/sizeof(*name
)) {
1022 assert(opname
!= NULL
);
1024 assert(0); /* FIXME: no operations other than name[], ATM */
1026 /* load op2 into EAX */
1027 insn("movl", right
, REG_EAX
, "EXPR_BINOP/COMMA/LOGICAL", 0);
1030 insn(opname
, left
, REG_EAX
, NULL
, 0);
1032 /* store result (EAX) in new pseudo / stack slot */
1034 insn("movl", REG_EAX
, new, "end EXPR_BINOP", 0);
1039 static void emit_if_conditional(struct statement
*stmt
)
1041 struct function
*f
= current_func
;
1042 struct storage
*val
, *target_val
;
1044 struct expression
*cond
= stmt
->if_conditional
;
1047 /* This is only valid if nobody can jump into the "dead" statement */
1049 if (cond
->type
== EXPR_VALUE
) {
1050 struct statement
*s
= stmt
->if_true
;
1057 val
= x86_expression(cond
);
1059 /* load 'if' test result into EAX */
1060 insn("movl", val
, REG_EAX
, "begin if conditional", 0);
1062 /* compare 'if' test result */
1063 insn("test", REG_EAX
, REG_EAX
, NULL
, 0);
1065 /* create end-of-if label / if-failed labelto jump to,
1066 * and jump to it if the expression returned zero.
1068 target
= new_label();
1069 target_val
= new_storage(STOR_LABEL
);
1070 target_val
->label
= target
;
1071 insn("jz", target_val
, NULL
, NULL
, ATOM_FREE_OP1
);
1073 x86_statement(stmt
->if_true
);
1074 if (stmt
->if_false
) {
1075 struct storage
*last_val
;
1078 /* finished generating code for if-true statement.
1079 * add a jump-to-end jump to avoid falling through
1080 * to the if-false statement code.
1083 last_val
= new_storage(STOR_LABEL
);
1084 last_val
->label
= last
;
1085 insn("jmp", last_val
, NULL
, NULL
, ATOM_FREE_OP1
);
1087 /* if we have both if-true and if-false statements,
1088 * the failed-conditional case will fall through to here
1090 sprintf(s
, ".L%d:\n", target
);
1091 push_text_atom(f
, s
);
1094 x86_statement(stmt
->if_false
);
1097 sprintf(s
, ".L%d:\t\t\t\t\t# end if\n", target
);
1098 push_text_atom(f
, s
);
1101 static struct storage
*emit_inc_dec(struct expression
*expr
, int postop
)
1103 struct storage
*addr
= x86_address_gen(expr
->unop
);
1104 struct storage
*retval
;
1105 const char *opname
= expr
->op
== SPECIAL_INCREMENT
? "incl" : "decl";
1107 /* FIXME: don't hardware operand size */
1108 int bits
= expr
->ctype
->bit_size
;
1112 struct storage
*new = new_pseudo();
1114 emit_copy(addr
, expr
->unop
->ctype
, new, NULL
);
1120 insn(opname
, addr
, NULL
, NULL
, 0);
1125 static struct storage
*emit_postop(struct expression
*expr
)
1127 return emit_inc_dec(expr
, 1);
1130 static struct storage
*emit_return_stmt(struct statement
*stmt
)
1132 struct function
*f
= current_func
;
1133 struct expression
*expr
= stmt
->ret_value
;
1134 struct storage
*val
= NULL
;
1137 if (expr
&& expr
->ctype
)
1138 val
= x86_expression(expr
);
1140 sprintf(s
, "\tjmp\t.L%d\n", f
->ret_target
);
1141 push_text_atom(f
, s
);
1146 static struct storage
*emit_conditional_expr(struct expression
*expr
)
1148 struct storage
*cond
= x86_expression(expr
->conditional
);
1149 struct storage
*true = x86_expression(expr
->cond_true
);
1150 struct storage
*false = x86_expression(expr
->cond_false
);
1151 struct storage
*new = new_pseudo();
1156 emit_move(cond
, REG_EAX
, expr
->conditional
->ctype
,
1157 "begin EXPR_CONDITIONAL", 0);
1158 emit_move(true, REG_ECX
, expr
->cond_true
->ctype
, NULL
, 0);
1159 emit_move(false, REG_EDX
, expr
->cond_false
->ctype
, NULL
, 0);
1161 /* test EAX (for zero/non-zero) */
1162 insn("test", REG_EAX
, REG_EAX
, NULL
, 0);
1164 /* if false, move EDX to ECX */
1165 insn("cmovz", REG_EDX
, REG_ECX
, NULL
, 0);
1167 /* finally, store the result (ECX) in a new pseudo / stack slot */
1169 emit_move(REG_ECX
, new, expr
->ctype
, "end EXPR_CONDITIONAL", 0);
1170 /* FIXME: we lose type knowledge of expression result at this point */
1175 static struct storage
*emit_symbol_expr_init(struct symbol
*sym
)
1177 struct expression
*expr
= sym
->initializer
;
1178 struct symbol_private
*priv
= sym
->aux
;
1180 if (sym
->ctype
.modifiers
& (MOD_TOPLEVEL
| MOD_EXTERN
| MOD_STATIC
))
1184 priv
= calloc(1, sizeof(*priv
));
1188 struct storage
*new = new_pseudo();
1189 fprintf(stderr
, "FIXME! no value for symbol. creating pseudo %d (stack offset %d)\n",
1190 new->pseudo
, new->pseudo
* 4);
1193 priv
->addr
= x86_expression(expr
);
1200 static struct storage
*emit_string_expr(struct expression
*expr
)
1202 struct function
*f
= current_func
;
1203 int label
= new_label();
1204 struct storage
*new = new_pseudo();
1206 push_cstring(f
, expr
->string
, label
);
1208 new = new_storage(STOR_LABEL
);
1210 new->flags
= STOR_LABEL_VAL
;
1214 static struct storage
*emit_cast_expr(struct expression
*expr
)
1216 struct symbol
*old_type
, *new_type
;
1217 struct storage
*op
= x86_expression(expr
->cast_expression
);
1218 int oldbits
, newbits
;
1219 struct storage
*new;
1221 old_type
= expr
->cast_expression
->ctype
;
1222 new_type
= expr
->cast_type
;
1224 oldbits
= old_type
->bit_size
;
1225 newbits
= new_type
->bit_size
;
1226 if (oldbits
>= newbits
)
1229 emit_move(op
, REG_EAX
, old_type
, "begin cast ..", 0);
1232 emit_move(REG_EAX
, new, new_type
, ".... end cast", 0);
1237 static void x86_struct_member(struct symbol
*sym
, void *data
, int flags
)
1239 if (flags
& ITERATE_FIRST
)
1241 printf("%s:%d:%ld at offset %ld", show_ident(sym
->ident
), sym
->bit_size
, sym
->ctype
.alignment
, sym
->offset
);
1242 if (sym
->fieldwidth
)
1243 printf("[%d..%d]", sym
->bit_offset
, sym
->bit_offset
+sym
->fieldwidth
-1);
1244 if (flags
& ITERATE_LAST
)
1250 static void x86_symbol(struct symbol
*sym
)
1252 struct symbol
*type
;
1257 type
= sym
->ctype
.base_type
;
1262 * Show actual implementation information
1264 switch (type
->type
) {
1267 if (sym
->initializer
)
1270 emit_array_noinit(sym
);
1274 if (sym
->initializer
) {
1275 emit_object_pre(show_ident(sym
->ident
),
1276 sym
->ctype
.modifiers
,
1277 sym
->ctype
.alignment
,
1279 emit_scalar(sym
->initializer
, sym
->bit_size
);
1282 emit_scalar_noinit(sym
);
1286 symbol_iterate(type
->symbol_list
, x86_struct_member
, NULL
);
1290 symbol_iterate(type
->symbol_list
, x86_struct_member
, NULL
);
1294 struct statement
*stmt
= type
->stmt
;
1296 struct storage
*val
;
1299 val
= x86_statement(stmt
);
1300 emit_func_post(sym
, val
);
1309 if (sym
->initializer
&& (type
->type
!= SYM_BASETYPE
) &&
1310 (type
->type
!= SYM_ARRAY
)) {
1312 x86_expression(sym
->initializer
);
1316 static void x86_symbol_init(struct symbol
*sym
);
1318 static void x86_switch_statement(struct statement
*stmt
)
1320 struct storage
*val
= x86_expression(stmt
->switch_expression
);
1322 printf("\tswitch v%d\n", val
->pseudo
);
1325 * Debugging only: Check that the case list is correct
1326 * by printing it out.
1328 * This is where a _real_ back-end would go through the
1329 * cases to decide whether to use a lookup table or a
1330 * series of comparisons etc
1332 printf("# case table:\n");
1333 FOR_EACH_PTR(stmt
->switch_case
->symbol_list
, sym
) {
1334 struct statement
*case_stmt
= sym
->stmt
;
1335 struct expression
*expr
= case_stmt
->case_expression
;
1336 struct expression
*to
= case_stmt
->case_to
;
1341 if (expr
->type
== EXPR_VALUE
) {
1342 printf(" case %lld", expr
->value
);
1344 if (to
->type
== EXPR_VALUE
) {
1345 printf(" .. %lld", to
->value
);
1347 printf(" .. what?");
1353 printf(": .L%p\n", sym
);
1355 printf("# end case table\n");
1357 x86_statement(stmt
->switch_statement
);
1359 if (stmt
->switch_break
->used
)
1360 printf(".L%p:\n", stmt
->switch_break
);
1363 static void x86_symbol_decl(struct symbol_list
*syms
)
1366 FOR_EACH_PTR(syms
, sym
) {
1367 x86_symbol_init(sym
);
1372 * Print out a statement
1374 static struct storage
*x86_statement(struct statement
*stmt
)
1378 switch (stmt
->type
) {
1380 return emit_return_stmt(stmt
);
1381 case STMT_COMPOUND
: {
1382 struct statement
*s
;
1383 struct storage
*last
= NULL
;
1385 x86_symbol_decl(stmt
->syms
);
1386 FOR_EACH_PTR(stmt
->stmts
, s
) {
1387 last
= x86_statement(s
);
1393 case STMT_EXPRESSION
:
1394 return x86_expression(stmt
->expression
);
1396 emit_if_conditional(stmt
);
1399 x86_switch_statement(stmt
);
1403 printf(".L%p:\n", stmt
->case_label
);
1404 x86_statement(stmt
->case_statement
);
1407 case STMT_ITERATOR
: {
1408 struct statement
*pre_statement
= stmt
->iterator_pre_statement
;
1409 struct expression
*pre_condition
= stmt
->iterator_pre_condition
;
1410 struct statement
*statement
= stmt
->iterator_statement
;
1411 struct statement
*post_statement
= stmt
->iterator_post_statement
;
1412 struct expression
*post_condition
= stmt
->iterator_post_condition
;
1413 int loop_top
= 0, loop_bottom
= 0;
1414 struct storage
*val
;
1416 x86_symbol_decl(stmt
->iterator_syms
);
1417 x86_statement(pre_statement
);
1418 if (pre_condition
) {
1419 if (pre_condition
->type
== EXPR_VALUE
) {
1420 if (!pre_condition
->value
) {
1421 loop_bottom
= new_label();
1422 printf("\tjmp\t\t.L%d\n", loop_bottom
);
1425 loop_bottom
= new_label();
1426 val
= x86_expression(pre_condition
);
1427 printf("\tje\t\tv%d, .L%d\n", val
->pseudo
, loop_bottom
);
1430 if (!post_condition
|| post_condition
->type
!= EXPR_VALUE
|| post_condition
->value
) {
1431 loop_top
= new_label();
1432 printf(".L%d:\n", loop_top
);
1434 x86_statement(statement
);
1435 if (stmt
->iterator_continue
->used
)
1436 printf(".L%p:\n", stmt
->iterator_continue
);
1437 x86_statement(post_statement
);
1438 if (!post_condition
) {
1439 printf("\tjmp\t\t.L%d\n", loop_top
);
1440 } else if (post_condition
->type
== EXPR_VALUE
) {
1441 if (post_condition
->value
)
1442 printf("\tjmp\t\t.L%d\n", loop_top
);
1444 val
= x86_expression(post_condition
);
1445 printf("\tjne\t\tv%d, .L%d\n", val
->pseudo
, loop_top
);
1447 if (stmt
->iterator_break
->used
)
1448 printf(".L%p:\n", stmt
->iterator_break
);
1450 printf(".L%d:\n", loop_bottom
);
1457 printf(".L%p:\n", stmt
->label_identifier
);
1458 x86_statement(stmt
->label_statement
);
1462 if (stmt
->goto_expression
) {
1463 struct storage
*val
= x86_expression(stmt
->goto_expression
);
1464 printf("\tgoto *v%d\n", val
->pseudo
);
1466 printf("\tgoto .L%p\n", stmt
->goto_label
);
1470 printf("\tasm( .... )\n");
1477 static struct storage
*x86_call_expression(struct expression
*expr
)
1479 struct function
*f
= current_func
;
1480 struct symbol
*direct
;
1481 struct expression
*arg
, *fn
;
1482 struct storage
*retval
, *fncall
;
1487 warn(expr
->pos
, "\tcall with no type!");
1492 FOR_EACH_PTR_REVERSE(expr
->args
, arg
) {
1493 struct storage
*new = x86_expression(arg
);
1494 int size
= arg
->ctype
->bit_size
;
1496 /* FIXME: pay attention to 'size' */
1497 insn("pushl", new, NULL
,
1498 !framesize
? "begin function call" : NULL
, 0);
1500 framesize
+= size
>> 3;
1501 } END_FOR_EACH_PTR_REVERSE
;
1505 /* Remove dereference, if any */
1507 if (fn
->type
== EXPR_PREOP
) {
1508 if (fn
->unop
->type
== EXPR_SYMBOL
) {
1509 struct symbol
*sym
= fn
->unop
->symbol
;
1510 if (sym
->ctype
.base_type
->type
== SYM_FN
)
1515 sprintf(s
, "\tcall\t%s\n", show_ident(direct
->ident
));
1516 push_text_atom(f
, s
);
1518 fncall
= x86_expression(fn
);
1519 emit_move(fncall
, REG_EAX
, fn
->ctype
, NULL
, 0);
1521 strcpy(s
, "\tcall\t*%%eax\n");
1522 push_text_atom(f
, s
);
1525 /* FIXME: pay attention to BITS_IN_POINTER */
1527 struct storage
*val
= new_storage(STOR_VALUE
);
1528 val
->value
= (long long) framesize
;
1529 insn("addl", val
, REG_ESP
, NULL
, ATOM_FREE_OP1
);
1532 retval
= new_pseudo();
1533 emit_move(REG_EAX
, retval
, expr
->ctype
, "end function call", 0);
1538 static struct storage
*x86_regular_preop(struct expression
*expr
)
1540 struct storage
*target
= x86_expression(expr
->unop
);
1541 struct storage
*new = new_pseudo();
1542 static const char *name
[] = {
1543 ['!'] = "nonzero", ['-'] = "neg",
1546 unsigned int op
= expr
->op
;
1549 opname
= show_special(op
);
1550 if (op
< sizeof(name
)/sizeof(*name
))
1552 printf("\t%s.%d\t\tv%d,v%d\n", opname
, expr
->ctype
->bit_size
, new->pseudo
, target
->pseudo
);
1557 * FIXME! Not all accesses are memory loads. We should
1558 * check what kind of symbol is behind the dereference.
1560 static struct storage
*x86_address_gen(struct expression
*expr
)
1562 if (expr
->type
== EXPR_PREOP
)
1563 return x86_expression(expr
->unop
);
1564 return x86_expression(expr
->address
);
1567 static struct storage
*x86_assignment(struct expression
*expr
)
1569 struct expression
*target
= expr
->left
;
1570 struct storage
*val
, *addr
;
1576 bits
= expr
->ctype
->bit_size
;
1577 val
= x86_expression(expr
->right
);
1578 addr
= x86_address_gen(target
);
1579 emit_copy(val
, expr
->right
->ctype
, addr
, expr
->left
->ctype
);
1583 static int x86_initialization(struct symbol
*sym
, struct expression
*expr
)
1585 struct storage
*val
, *addr
;
1591 bits
= expr
->ctype
->bit_size
;
1592 val
= x86_expression(expr
);
1593 addr
= x86_symbol_expr(sym
);
1594 // FIXME! The "target" expression is for bitfield store information.
1595 // Leave it NULL, which works fine.
1596 emit_store(NULL
, addr
, val
, bits
);
1600 static struct storage
*x86_access(struct expression
*expr
)
1602 return x86_address_gen(expr
);
1605 static struct storage
*x86_preop(struct expression
*expr
)
1608 * '*' is an lvalue access, and is fundamentally different
1609 * from an arithmetic operation. Maybe it should have an
1610 * expression type of its own..
1612 if (expr
->op
== '*')
1613 return x86_access(expr
);
1614 if (expr
->op
== SPECIAL_INCREMENT
|| expr
->op
== SPECIAL_DECREMENT
)
1615 return emit_inc_dec(expr
, 0);
1616 return x86_regular_preop(expr
);
1619 static struct storage
*x86_symbol_expr(struct symbol
*sym
)
1621 struct storage
*new = new_pseudo();
1623 if (sym
->ctype
.modifiers
& (MOD_TOPLEVEL
| MOD_EXTERN
| MOD_STATIC
)) {
1624 printf("\tmovi.%d\t\tv%d,$%s\n", BITS_IN_POINTER
, new->pseudo
, show_ident(sym
->ident
));
1627 if (sym
->ctype
.modifiers
& MOD_ADDRESSABLE
) {
1628 printf("\taddi.%d\t\tv%d,vFP,$%lld\n", BITS_IN_POINTER
, new->pseudo
, sym
->value
);
1631 printf("\taddi.%d\t\tv%d,vFP,$offsetof(%s:%p)\n", BITS_IN_POINTER
, new->pseudo
, show_ident(sym
->ident
), sym
);
1635 static void x86_symbol_init(struct symbol
*sym
)
1637 struct symbol_private
*priv
= sym
->aux
;
1638 struct expression
*expr
= sym
->initializer
;
1639 struct storage
*new;
1642 new = x86_expression(expr
);
1647 priv
= calloc(1, sizeof(*priv
));
1649 /* FIXME: leak! we don't free... */
1650 /* (well, we don't free symbols either) */
1656 static int type_is_signed(struct symbol
*sym
)
1658 if (sym
->type
== SYM_NODE
)
1659 sym
= sym
->ctype
.base_type
;
1660 if (sym
->type
== SYM_PTR
)
1662 return !(sym
->ctype
.modifiers
& MOD_UNSIGNED
);
1665 static struct storage
*x86_bitfield_expr(struct expression
*expr
)
1667 return x86_access(expr
);
1670 static struct storage
*x86_label_expr(struct expression
*expr
)
1672 struct storage
*new = new_pseudo();
1673 printf("\tmovi.%d\t\tv%d,.L%p\n",BITS_IN_POINTER
, new->pseudo
, expr
->label_symbol
);
1677 static struct storage
*x86_statement_expr(struct expression
*expr
)
1679 return x86_statement(expr
->statement
);
1682 static int x86_position_expr(struct expression
*expr
, struct symbol
*base
)
1684 struct storage
*new = x86_expression(expr
->init_expr
);
1685 struct symbol
*ctype
= expr
->init_sym
;
1687 printf("\tinsert v%d at [%d:%d] of %s\n", new->pseudo
,
1688 expr
->init_offset
, ctype
->bit_offset
,
1689 show_ident(base
->ident
));
1693 static void x86_initializer_expr(struct expression
*expr
, struct symbol
*ctype
)
1695 struct expression
*entry
;
1697 FOR_EACH_PTR(expr
->expr_list
, entry
) {
1698 // Nested initializers have their positions already
1699 // recursively calculated - just output them too
1700 if (entry
->type
== EXPR_INITIALIZER
) {
1701 x86_initializer_expr(entry
, ctype
);
1705 // Ignore initializer indexes and identifiers - the
1706 // evaluator has taken them into account
1707 if (entry
->type
== EXPR_IDENTIFIER
|| entry
->type
== EXPR_INDEX
)
1709 if (entry
->type
== EXPR_POS
) {
1710 x86_position_expr(entry
, ctype
);
1713 x86_initialization(ctype
, entry
);
1718 * Print out an expression. Return the pseudo that contains the
1721 static struct storage
*x86_expression(struct expression
*expr
)
1727 struct position
*pos
= &expr
->pos
;
1728 printf("\tno type at %s:%d:%d\n",
1729 input_streams
[pos
->stream
].name
,
1730 pos
->line
, pos
->pos
);
1734 switch (expr
->type
) {
1736 return x86_call_expression(expr
);
1738 case EXPR_ASSIGNMENT
:
1739 return x86_assignment(expr
);
1742 return emit_compare(expr
);
1746 return emit_binop(expr
);
1748 return x86_preop(expr
);
1750 return emit_postop(expr
);
1752 return emit_symbol_expr_init(expr
->symbol
);
1755 warn(expr
->pos
, "invalid expression after evaluation");
1758 return emit_cast_expr(expr
);
1760 return emit_value(expr
);
1762 return emit_string_expr(expr
);
1764 return x86_bitfield_expr(expr
);
1765 case EXPR_INITIALIZER
:
1766 x86_initializer_expr(expr
, expr
->ctype
);
1768 case EXPR_CONDITIONAL
:
1769 return emit_conditional_expr(expr
);
1770 case EXPR_STATEMENT
:
1771 return x86_statement_expr(expr
);
1773 return x86_label_expr(expr
);
1775 // None of these should exist as direct expressions: they are only
1776 // valid as sub-expressions of initializers.
1778 warn(expr
->pos
, "unable to show plain initializer position expression");
1780 case EXPR_IDENTIFIER
:
1781 warn(expr
->pos
, "unable to show identifier expression");
1784 warn(expr
->pos
, "unable to show index expression");