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
)
579 const char *name
= show_ident(sym
->ident
);
580 struct function
*f
= current_func
;
581 int pseudo_nr
= f
->pseudo_nr
;
582 char jump_target
[16];
587 /* function prologue */
588 emit_section(".text");
589 if ((sym
->ctype
.modifiers
& MOD_STATIC
) == 0)
590 printf(".globl %s\n", name
);
591 printf("\t.type\t%s, @function\n", name
);
592 printf("%s:\n", name
);
595 char pseudo_const
[16];
597 sprintf(pseudo_const
, "$%d", pseudo_nr
* 4);
598 printf("\tsubl\t%s, %%esp\n", pseudo_const
);
601 /* function epilogue */
603 /* jump target for 'return' statements */
604 sprintf(jump_target
, ".L%d:\n", f
->ret_target
);
605 push_text_atom(f
, jump_target
);
610 val
= new_storage(STOR_VALUE
);
611 val
->value
= (long long) (pseudo_nr
* 4);
613 insn("addl", val
, REG_ESP
, NULL
, ATOM_FREE_OP1
);
616 insn("ret", NULL
, NULL
, NULL
, 0);
618 /* output everything to stdout */
619 fflush(stdout
); /* paranoia; needed? */
622 /* function footer */
623 printf("\t.size\t%s, .-%s\n", name
, name
);
629 /* emit object (a.k.a. variable, a.k.a. data) prologue */
630 static void emit_object_pre(const char *name
, unsigned long modifiers
,
631 unsigned long alignment
, unsigned int byte_size
)
633 if ((modifiers
& MOD_STATIC
) == 0)
634 printf(".globl %s\n", name
);
635 emit_section(".data");
637 printf("\t.align %lu\n", alignment
);
638 printf("\t.type\t%s, @object\n", name
);
639 printf("\t.size\t%s, %d\n", name
, byte_size
);
640 printf("%s:\n", name
);
643 /* emit value (only) for an initializer scalar */
644 static void emit_scalar(struct expression
*expr
, unsigned int bit_size
)
649 assert(expr
->type
== EXPR_VALUE
);
651 if (expr
->value
== 0ULL) {
652 printf("\t.zero\t%d\n", bit_size
/ 8);
656 ll
= (long long) expr
->value
;
659 case 8: type
= "byte"; ll
= (char) ll
; break;
660 case 16: type
= "value"; ll
= (short) ll
; break;
661 case 32: type
= "long"; ll
= (int) ll
; break;
662 case 64: type
= "quad"; break;
663 default: type
= NULL
; break;
666 assert(type
!= NULL
);
668 printf("\t.%s\t%Ld\n", type
, ll
);
671 static void emit_global_noinit(const char *name
, unsigned long modifiers
,
672 unsigned long alignment
, unsigned int byte_size
)
676 if (modifiers
& MOD_STATIC
) {
677 sprintf(s
, "\t.local\t%s\n", name
);
678 textbuf_push(&unit_post_text
, s
);
681 sprintf(s
, "\t.comm\t%s,%d,%lu\n", name
, byte_size
, alignment
);
683 sprintf(s
, "\t.comm\t%s,%d\n", name
, byte_size
);
684 textbuf_push(&unit_post_text
, s
);
687 static int ea_current
, ea_last
;
689 static void emit_initializer(struct symbol
*sym
,
690 struct expression
*expr
)
692 int distance
= ea_current
- ea_last
- 1;
695 printf("\t.zero\t%d\n", (sym
->bit_size
/ 8) * distance
);
697 if (expr
->type
== EXPR_VALUE
) {
698 struct symbol
*base_type
= sym
->ctype
.base_type
;
699 assert(base_type
!= NULL
);
701 emit_scalar(expr
, sym
->bit_size
/ base_type
->array_size
);
704 if (expr
->type
!= EXPR_INITIALIZER
)
707 assert(0); /* FIXME */
710 static int sort_array_cmp(const struct expression
*a
,
711 const struct expression
*b
)
713 int a_ofs
= 0, b_ofs
= 0;
715 if (a
->type
== EXPR_POS
)
716 a_ofs
= (int) a
->init_offset
;
717 if (b
->type
== EXPR_POS
)
718 b_ofs
= (int) b
->init_offset
;
720 return a_ofs
- b_ofs
;
723 /* move to front-end? */
724 static void sort_array(struct expression
*expr
)
726 struct expression
*entry
, **list
;
727 unsigned int elem
, sorted
, i
;
730 FOR_EACH_PTR(expr
->expr_list
, entry
) {
737 list
= malloc(sizeof(entry
) * elem
);
739 die("OOM in sort_array");
741 /* this code is no doubt evil and ignores EXPR_INDEX possibly
742 * to its detriment and other nasty things. improvements
747 FOR_EACH_PTR(expr
->expr_list
, entry
) {
748 if ((entry
->type
== EXPR_POS
) || (entry
->type
== EXPR_VALUE
)) {
749 /* add entry to list[], in sorted order */
756 for (i
= 0; i
< sorted
; i
++)
757 if (sort_array_cmp(entry
, list
[i
]) <= 0)
760 /* If inserting into the middle of list[]
761 * instead of appending, we memmove.
762 * This is ugly, but thankfully
763 * uncommon. Input data with tons of
764 * entries very rarely have explicit
765 * offsets. convert to qsort eventually...
768 memmove(&list
[i
+ 1], &list
[i
],
769 (sorted
- i
) * sizeof(entry
));
777 FOR_EACH_PTR(expr
->expr_list
, entry
) {
778 if ((entry
->type
== EXPR_POS
) || (entry
->type
== EXPR_VALUE
))
779 __list
->list
[__i
] = list
[i
++];
784 static void emit_array(struct symbol
*sym
)
786 struct symbol
*base_type
= sym
->ctype
.base_type
;
787 struct expression
*expr
= sym
->initializer
;
788 struct expression
*entry
;
790 assert(base_type
!= NULL
);
796 emit_object_pre(show_ident(sym
->ident
), sym
->ctype
.modifiers
,
797 sym
->ctype
.alignment
,
802 FOR_EACH_PTR(expr
->expr_list
, entry
) {
803 if (entry
->type
== EXPR_VALUE
) {
805 emit_initializer(sym
, entry
);
806 ea_last
= ea_current
;
807 } else if (entry
->type
== EXPR_POS
) {
809 entry
->init_offset
/ (base_type
->bit_size
/ 8);
810 emit_initializer(sym
, entry
->init_expr
);
811 ea_last
= ea_current
;
816 static void emit_one_symbol(struct symbol
*sym
, void *dummy
, int flags
)
821 void emit_unit(const char *basename
, struct symbol_list
*list
)
823 emit_unit_pre(basename
);
824 symbol_iterate(list
, emit_one_symbol
, NULL
);
828 static void emit_copy(struct storage
*src
, struct symbol
*src_ctype
,
829 struct storage
*dest
, struct symbol
*dest_ctype
)
831 /* FIXME: Bitfield move! */
833 emit_move(src
, REG_EAX
, src_ctype
, "begin copy ..", 0);
834 emit_move(REG_EAX
, dest
, dest_ctype
, ".... end copy", 0);
837 static void emit_store(struct expression
*dest_expr
, struct storage
*dest
,
838 struct storage
*src
, int bits
)
840 /* FIXME: Bitfield store! */
841 printf("\tst.%d\t\tv%d,[v%d]\n", bits
, src
->pseudo
, dest
->pseudo
);
844 static void emit_scalar_noinit(struct symbol
*sym
)
846 emit_global_noinit(show_ident(sym
->ident
),
847 sym
->ctype
.modifiers
, sym
->ctype
.alignment
,
852 static void emit_array_noinit(struct symbol
*sym
)
854 emit_global_noinit(show_ident(sym
->ident
),
855 sym
->ctype
.modifiers
, sym
->ctype
.alignment
,
856 sym
->array_size
* (sym
->bit_size
/ 8));
860 static const char *opbits(const char *insn
, unsigned int bits
)
862 static char opbits_str
[32];
866 case 8: c
= 'b'; break;
867 case 16: c
= 'w'; break;
868 case 32: c
= 'l'; break;
869 case 64: c
= 'q'; break;
870 default: assert(0); break;
873 sprintf(opbits_str
, "%s%c", insn
, bits
);
878 static void emit_move(struct storage
*src
, struct storage
*dest
,
879 struct symbol
*ctype
, const char *comment
,
883 unsigned int is_signed
;
884 unsigned int is_dest
= (src
->type
== STOR_REG
);
888 bits
= ctype
->bit_size
;
889 is_signed
= type_is_signed(ctype
);
895 if ((dest
->type
== STOR_REG
) && (src
->type
== STOR_REG
)) {
896 insn("mov", src
, dest
, NULL
, 0);
905 if (is_signed
) opname
= "movsxb";
906 else opname
= "movzxb";
913 if (is_signed
) opname
= "movsxw";
914 else opname
= "movzxw";
918 case 32: opname
= "movl"; break;
919 case 64: opname
= "movq"; break;
921 default: assert(0); break;
924 insn(opname
, src
, dest
, comment
, flags
);
927 static struct storage
*emit_compare(struct expression
*expr
)
929 struct storage
*left
= x86_expression(expr
->left
);
930 struct storage
*right
= x86_expression(expr
->right
);
932 const char *opname
= NULL
;
933 unsigned int is_signed
= type_is_signed(expr
->left
->ctype
); /* FIXME */
934 unsigned int right_bits
= expr
->right
->ctype
->bit_size
;
938 if (is_signed
) opname
= "setl";
939 else opname
= "setb";
942 if (is_signed
) opname
= "setg";
943 else opname
= "seta";
946 if (is_signed
) opname
= "setle";
947 else opname
= "setbe";
950 if (is_signed
) opname
= "setge";
951 else opname
= "setae";
954 case SPECIAL_EQUAL
: opname
= "sete"; break;
955 case SPECIAL_NOTEQUAL
: opname
= "setne"; break;
963 insn("xor", REG_EDX
, REG_EDX
, "begin EXPR_COMPARE", 0);
965 /* move op1 into EAX */
966 emit_move(left
, REG_EAX
, expr
->left
->ctype
, NULL
, 0);
968 /* perform comparison, RHS (op1, right) and LHS (op2, EAX) */
969 insn(opbits("cmp", right_bits
), right
, REG_EAX
, NULL
, 0);
971 /* store result of operation, 0 or 1, in DL using SETcc */
972 insn(opname
, REG_DL
, NULL
, NULL
, 0);
974 /* finally, store the result (DL) in a new pseudo / stack slot */
976 emit_move(REG_EDX
, new, NULL
, "end EXPR_COMPARE", 0);
981 static struct storage
*emit_value(struct expression
*expr
)
983 #if 0 /* old and slow way */
984 struct storage
*new = new_pseudo();
987 val
= new_storage(STOR_VALUE
);
988 val
->value
= (long long) expr
->value
;
989 insn("movl", val
, new, NULL
, ATOM_FREE_OP1
);
995 val
= new_storage(STOR_VALUE
);
996 val
->value
= (long long) expr
->value
;
998 return val
; /* FIXME: memory leak */
1002 static struct storage
*emit_binop(struct expression
*expr
)
1004 struct storage
*left
= x86_expression(expr
->left
);
1005 struct storage
*right
= x86_expression(expr
->right
);
1006 struct storage
*new;
1008 static const char *name
[] = {
1009 ['+'] = "addl", ['-'] = "subl",
1010 ['*'] = "mull", ['/'] = "divl",
1011 ['%'] = "modl", ['&'] = "andl",
1012 ['|'] = "orl", ['^'] = "xorl"
1014 unsigned int op
= expr
->op
;
1017 * FIXME FIXME this routine is so wrong it's not even funny.
1018 * On x86 both mod/div are handled with the same instruction.
1019 * We don't pay attention to signed/unsigned issues,
1020 * and like elsewhere we hardcode the operand size at 32 bits.
1023 opname
= show_special(op
);
1024 if (op
< sizeof(name
)/sizeof(*name
)) {
1026 assert(opname
!= NULL
);
1028 assert(0); /* FIXME: no operations other than name[], ATM */
1030 /* load op2 into EAX */
1031 insn("movl", right
, REG_EAX
, "EXPR_BINOP/COMMA/LOGICAL", 0);
1034 insn(opname
, left
, REG_EAX
, NULL
, 0);
1036 /* store result (EAX) in new pseudo / stack slot */
1038 insn("movl", REG_EAX
, new, "end EXPR_BINOP", 0);
1043 static void emit_if_conditional(struct statement
*stmt
)
1045 struct function
*f
= current_func
;
1046 struct storage
*val
, *target_val
;
1048 struct expression
*cond
= stmt
->if_conditional
;
1051 /* This is only valid if nobody can jump into the "dead" statement */
1053 if (cond
->type
== EXPR_VALUE
) {
1054 struct statement
*s
= stmt
->if_true
;
1061 val
= x86_expression(cond
);
1063 /* load 'if' test result into EAX */
1064 insn("movl", val
, REG_EAX
, "begin if conditional", 0);
1066 /* compare 'if' test result */
1067 insn("test", REG_EAX
, REG_EAX
, NULL
, 0);
1069 /* create end-of-if label / if-failed labelto jump to,
1070 * and jump to it if the expression returned zero.
1072 target
= new_label();
1073 target_val
= new_storage(STOR_LABEL
);
1074 target_val
->label
= target
;
1075 insn("jz", target_val
, NULL
, NULL
, ATOM_FREE_OP1
);
1077 x86_statement(stmt
->if_true
);
1078 if (stmt
->if_false
) {
1079 struct storage
*last_val
;
1082 /* finished generating code for if-true statement.
1083 * add a jump-to-end jump to avoid falling through
1084 * to the if-false statement code.
1087 last_val
= new_storage(STOR_LABEL
);
1088 last_val
->label
= last
;
1089 insn("jmp", last_val
, NULL
, NULL
, ATOM_FREE_OP1
);
1091 /* if we have both if-true and if-false statements,
1092 * the failed-conditional case will fall through to here
1094 sprintf(s
, ".L%d:\n", target
);
1095 push_text_atom(f
, s
);
1098 x86_statement(stmt
->if_false
);
1101 sprintf(s
, ".L%d:\t\t\t\t\t# end if\n", target
);
1102 push_text_atom(f
, s
);
1105 static struct storage
*emit_inc_dec(struct expression
*expr
, int postop
)
1107 struct storage
*addr
= x86_address_gen(expr
->unop
);
1108 struct storage
*retval
;
1111 strcpy(opname
, opbits(expr
->op
== SPECIAL_INCREMENT
? "inc" : "dec",
1112 expr
->ctype
->bit_size
));
1115 struct storage
*new = new_pseudo();
1117 emit_copy(addr
, expr
->unop
->ctype
, new, NULL
);
1123 insn(opname
, addr
, NULL
, NULL
, 0);
1128 static struct storage
*emit_postop(struct expression
*expr
)
1130 return emit_inc_dec(expr
, 1);
1133 static struct storage
*emit_return_stmt(struct statement
*stmt
)
1135 struct function
*f
= current_func
;
1136 struct expression
*expr
= stmt
->ret_value
;
1137 struct storage
*val
= NULL
;
1140 if (expr
&& expr
->ctype
) {
1141 val
= x86_expression(expr
);
1142 assert(val
!= NULL
);
1143 emit_move(val
, REG_EAX
, expr
->ctype
, "return", 0);
1146 sprintf(s
, "\tjmp\t.L%d\n", f
->ret_target
);
1147 push_text_atom(f
, s
);
1152 static struct storage
*emit_conditional_expr(struct expression
*expr
)
1154 struct storage
*cond
= x86_expression(expr
->conditional
);
1155 struct storage
*true = x86_expression(expr
->cond_true
);
1156 struct storage
*false = x86_expression(expr
->cond_false
);
1157 struct storage
*new = new_pseudo();
1162 emit_move(cond
, REG_EAX
, expr
->conditional
->ctype
,
1163 "begin EXPR_CONDITIONAL", 0);
1164 emit_move(true, REG_ECX
, expr
->cond_true
->ctype
, NULL
, 0);
1165 emit_move(false, REG_EDX
, expr
->cond_false
->ctype
, NULL
, 0);
1167 /* test EAX (for zero/non-zero) */
1168 insn("test", REG_EAX
, REG_EAX
, NULL
, 0);
1170 /* if false, move EDX to ECX */
1171 insn("cmovz", REG_EDX
, REG_ECX
, NULL
, 0);
1173 /* finally, store the result (ECX) in a new pseudo / stack slot */
1175 emit_move(REG_ECX
, new, expr
->ctype
, "end EXPR_CONDITIONAL", 0);
1176 /* FIXME: we lose type knowledge of expression result at this point */
1181 static struct storage
*emit_symbol_expr_init(struct symbol
*sym
)
1183 struct expression
*expr
= sym
->initializer
;
1184 struct symbol_private
*priv
= sym
->aux
;
1187 priv
= calloc(1, sizeof(*priv
));
1191 struct storage
*new = new_pseudo();
1192 fprintf(stderr
, "FIXME! no value for symbol. creating pseudo %d (stack offset %d)\n",
1193 new->pseudo
, new->pseudo
* 4);
1196 priv
->addr
= x86_expression(expr
);
1203 static struct storage
*emit_string_expr(struct expression
*expr
)
1205 struct function
*f
= current_func
;
1206 int label
= new_label();
1207 struct storage
*new = new_pseudo();
1209 push_cstring(f
, expr
->string
, label
);
1211 new = new_storage(STOR_LABEL
);
1213 new->flags
= STOR_LABEL_VAL
;
1217 static struct storage
*emit_cast_expr(struct expression
*expr
)
1219 struct symbol
*old_type
, *new_type
;
1220 struct storage
*op
= x86_expression(expr
->cast_expression
);
1221 int oldbits
, newbits
;
1222 struct storage
*new;
1224 old_type
= expr
->cast_expression
->ctype
;
1225 new_type
= expr
->cast_type
;
1227 oldbits
= old_type
->bit_size
;
1228 newbits
= new_type
->bit_size
;
1229 if (oldbits
>= newbits
)
1232 emit_move(op
, REG_EAX
, old_type
, "begin cast ..", 0);
1235 emit_move(REG_EAX
, new, new_type
, ".... end cast", 0);
1240 static struct storage
*emit_regular_preop(struct expression
*expr
)
1242 struct storage
*target
= x86_expression(expr
->unop
);
1243 struct storage
*new = new_pseudo();
1244 const char *opname
= NULL
;
1248 insn("xor", REG_EDX
, REG_EDX
, NULL
, 0);
1249 emit_move(target
, REG_EAX
, expr
->unop
->ctype
, NULL
, 0);
1250 insn("test", REG_EAX
, REG_EAX
, NULL
, 0);
1251 insn("setz", REG_DL
, NULL
, NULL
, 0);
1252 emit_move(REG_EDX
, new, expr
->unop
->ctype
, NULL
, 0);
1260 emit_move(target
, REG_EAX
, expr
->unop
->ctype
, NULL
, 0);
1261 insn(opname
, REG_EAX
, NULL
, NULL
, 0);
1262 emit_move(REG_EAX
, new, expr
->unop
->ctype
, NULL
, 0);
1272 static void x86_struct_member(struct symbol
*sym
, void *data
, int flags
)
1274 if (flags
& ITERATE_FIRST
)
1276 printf("%s:%d:%ld at offset %ld", show_ident(sym
->ident
), sym
->bit_size
, sym
->ctype
.alignment
, sym
->offset
);
1277 if (sym
->fieldwidth
)
1278 printf("[%d..%d]", sym
->bit_offset
, sym
->bit_offset
+sym
->fieldwidth
-1);
1279 if (flags
& ITERATE_LAST
)
1285 static void x86_symbol(struct symbol
*sym
)
1287 struct symbol
*type
;
1292 type
= sym
->ctype
.base_type
;
1297 * Show actual implementation information
1299 switch (type
->type
) {
1302 if (sym
->initializer
)
1305 emit_array_noinit(sym
);
1309 if (sym
->initializer
) {
1310 emit_object_pre(show_ident(sym
->ident
),
1311 sym
->ctype
.modifiers
,
1312 sym
->ctype
.alignment
,
1314 emit_scalar(sym
->initializer
, sym
->bit_size
);
1317 emit_scalar_noinit(sym
);
1321 symbol_iterate(type
->symbol_list
, x86_struct_member
, NULL
);
1325 symbol_iterate(type
->symbol_list
, x86_struct_member
, NULL
);
1329 struct statement
*stmt
= type
->stmt
;
1332 x86_statement(stmt
);
1333 emit_func_post(sym
);
1342 if (sym
->initializer
&& (type
->type
!= SYM_BASETYPE
) &&
1343 (type
->type
!= SYM_ARRAY
)) {
1345 x86_expression(sym
->initializer
);
1349 static void x86_symbol_init(struct symbol
*sym
);
1351 static void x86_switch_statement(struct statement
*stmt
)
1353 struct storage
*val
= x86_expression(stmt
->switch_expression
);
1355 printf("\tswitch v%d\n", val
->pseudo
);
1358 * Debugging only: Check that the case list is correct
1359 * by printing it out.
1361 * This is where a _real_ back-end would go through the
1362 * cases to decide whether to use a lookup table or a
1363 * series of comparisons etc
1365 printf("# case table:\n");
1366 FOR_EACH_PTR(stmt
->switch_case
->symbol_list
, sym
) {
1367 struct statement
*case_stmt
= sym
->stmt
;
1368 struct expression
*expr
= case_stmt
->case_expression
;
1369 struct expression
*to
= case_stmt
->case_to
;
1374 if (expr
->type
== EXPR_VALUE
) {
1375 printf(" case %lld", expr
->value
);
1377 if (to
->type
== EXPR_VALUE
) {
1378 printf(" .. %lld", to
->value
);
1380 printf(" .. what?");
1386 printf(": .L%p\n", sym
);
1388 printf("# end case table\n");
1390 x86_statement(stmt
->switch_statement
);
1392 if (stmt
->switch_break
->used
)
1393 printf(".L%p:\n", stmt
->switch_break
);
1396 static void x86_symbol_decl(struct symbol_list
*syms
)
1399 FOR_EACH_PTR(syms
, sym
) {
1400 x86_symbol_init(sym
);
1404 static void x86_loop(struct statement
*stmt
)
1406 struct statement
*pre_statement
= stmt
->iterator_pre_statement
;
1407 struct expression
*pre_condition
= stmt
->iterator_pre_condition
;
1408 struct statement
*statement
= stmt
->iterator_statement
;
1409 struct statement
*post_statement
= stmt
->iterator_post_statement
;
1410 struct expression
*post_condition
= stmt
->iterator_post_condition
;
1411 int loop_top
= 0, loop_bottom
= 0;
1412 struct storage
*val
;
1414 x86_symbol_decl(stmt
->iterator_syms
);
1415 x86_statement(pre_statement
);
1416 if (pre_condition
) {
1417 if (pre_condition
->type
== EXPR_VALUE
) {
1418 if (!pre_condition
->value
) {
1419 loop_bottom
= new_label();
1420 printf("\tjmp\t\t.L%d\n", loop_bottom
);
1423 loop_bottom
= new_label();
1424 val
= x86_expression(pre_condition
);
1425 printf("\tje\t\tv%d, .L%d\n", val
->pseudo
, loop_bottom
);
1428 if (!post_condition
|| post_condition
->type
!= EXPR_VALUE
|| post_condition
->value
) {
1429 loop_top
= new_label();
1430 printf(".L%d:\n", loop_top
);
1432 x86_statement(statement
);
1433 if (stmt
->iterator_continue
->used
)
1434 printf(".L%p:\n", stmt
->iterator_continue
);
1435 x86_statement(post_statement
);
1436 if (!post_condition
) {
1437 printf("\tjmp\t\t.L%d\n", loop_top
);
1438 } else if (post_condition
->type
== EXPR_VALUE
) {
1439 if (post_condition
->value
)
1440 printf("\tjmp\t\t.L%d\n", loop_top
);
1442 val
= x86_expression(post_condition
);
1443 printf("\tjne\t\tv%d, .L%d\n", val
->pseudo
, loop_top
);
1445 if (stmt
->iterator_break
->used
)
1446 printf(".L%p:\n", stmt
->iterator_break
);
1448 printf(".L%d:\n", loop_bottom
);
1452 * Print out a statement
1454 static struct storage
*x86_statement(struct statement
*stmt
)
1458 switch (stmt
->type
) {
1460 return emit_return_stmt(stmt
);
1461 case STMT_COMPOUND
: {
1462 struct statement
*s
;
1463 struct storage
*last
= NULL
;
1465 x86_symbol_decl(stmt
->syms
);
1466 FOR_EACH_PTR(stmt
->stmts
, s
) {
1467 last
= x86_statement(s
);
1473 case STMT_EXPRESSION
:
1474 return x86_expression(stmt
->expression
);
1476 emit_if_conditional(stmt
);
1479 x86_switch_statement(stmt
);
1483 printf(".L%p:\n", stmt
->case_label
);
1484 x86_statement(stmt
->case_statement
);
1495 printf(".L%p:\n", stmt
->label_identifier
);
1496 x86_statement(stmt
->label_statement
);
1500 if (stmt
->goto_expression
) {
1501 struct storage
*val
= x86_expression(stmt
->goto_expression
);
1502 printf("\tgoto *v%d\n", val
->pseudo
);
1504 printf("\tgoto .L%p\n", stmt
->goto_label
);
1508 printf("\tasm( .... )\n");
1515 static struct storage
*x86_call_expression(struct expression
*expr
)
1517 struct function
*f
= current_func
;
1518 struct symbol
*direct
;
1519 struct expression
*arg
, *fn
;
1520 struct storage
*retval
, *fncall
;
1525 warn(expr
->pos
, "\tcall with no type!");
1530 FOR_EACH_PTR_REVERSE(expr
->args
, arg
) {
1531 struct storage
*new = x86_expression(arg
);
1532 int size
= arg
->ctype
->bit_size
;
1534 /* FIXME: pay attention to 'size' */
1535 insn("pushl", new, NULL
,
1536 !framesize
? "begin function call" : NULL
, 0);
1538 framesize
+= size
>> 3;
1539 } END_FOR_EACH_PTR_REVERSE
;
1543 /* Remove dereference, if any */
1545 if (fn
->type
== EXPR_PREOP
) {
1546 if (fn
->unop
->type
== EXPR_SYMBOL
) {
1547 struct symbol
*sym
= fn
->unop
->symbol
;
1548 if (sym
->ctype
.base_type
->type
== SYM_FN
)
1553 sprintf(s
, "\tcall\t%s\n", show_ident(direct
->ident
));
1554 push_text_atom(f
, s
);
1556 fncall
= x86_expression(fn
);
1557 emit_move(fncall
, REG_EAX
, fn
->ctype
, NULL
, 0);
1559 strcpy(s
, "\tcall\t*%eax\n");
1560 push_text_atom(f
, s
);
1563 /* FIXME: pay attention to BITS_IN_POINTER */
1565 struct storage
*val
= new_storage(STOR_VALUE
);
1566 val
->value
= (long long) framesize
;
1567 insn("addl", val
, REG_ESP
, NULL
, ATOM_FREE_OP1
);
1570 retval
= new_pseudo();
1571 emit_move(REG_EAX
, retval
, expr
->ctype
, "end function call", 0);
1576 static struct storage
*x86_address_gen(struct expression
*expr
)
1578 struct function
*f
= current_func
;
1579 struct storage
*addr
;
1580 struct storage
*new;
1583 if ((expr
->type
!= EXPR_PREOP
) || (expr
->op
!= '*'))
1584 return x86_expression(expr
->address
);
1586 addr
= x86_expression(expr
->unop
);
1587 if (expr
->unop
->type
== EXPR_SYMBOL
)
1590 emit_move(addr
, REG_EAX
, NULL
, "begin deref ..", 0);
1592 /* FIXME: operand size */
1593 strcpy(s
, "\tmovl\t(%eax), %ecx\n");
1594 push_text_atom(f
, s
);
1597 emit_move(REG_ECX
, new, NULL
, ".... end deref", 0);
1602 static struct storage
*x86_assignment(struct expression
*expr
)
1604 struct expression
*target
= expr
->left
;
1605 struct storage
*val
, *addr
;
1611 bits
= expr
->ctype
->bit_size
;
1612 val
= x86_expression(expr
->right
);
1613 addr
= x86_address_gen(target
);
1615 switch (val
->type
) {
1616 /* copy, where both operands are memory */
1619 emit_copy(val
, expr
->right
->ctype
, addr
, expr
->left
->ctype
);
1622 /* copy, one or zero operands are memory */
1627 emit_move(val
, addr
, expr
->left
->ctype
, NULL
, 0);
1633 static int x86_initialization(struct symbol
*sym
, struct expression
*expr
)
1635 struct storage
*val
, *addr
;
1641 bits
= expr
->ctype
->bit_size
;
1642 val
= x86_expression(expr
);
1643 addr
= x86_symbol_expr(sym
);
1644 // FIXME! The "target" expression is for bitfield store information.
1645 // Leave it NULL, which works fine.
1646 emit_store(NULL
, addr
, val
, bits
);
1650 static struct storage
*x86_access(struct expression
*expr
)
1652 return x86_address_gen(expr
);
1655 static struct storage
*x86_preop(struct expression
*expr
)
1658 * '*' is an lvalue access, and is fundamentally different
1659 * from an arithmetic operation. Maybe it should have an
1660 * expression type of its own..
1662 if (expr
->op
== '*')
1663 return x86_access(expr
);
1664 if (expr
->op
== SPECIAL_INCREMENT
|| expr
->op
== SPECIAL_DECREMENT
)
1665 return emit_inc_dec(expr
, 0);
1666 return emit_regular_preop(expr
);
1669 static struct storage
*x86_symbol_expr(struct symbol
*sym
)
1671 struct storage
*new = new_pseudo();
1673 if (sym
->ctype
.modifiers
& (MOD_TOPLEVEL
| MOD_EXTERN
| MOD_STATIC
)) {
1674 printf("\tmovi.%d\t\tv%d,$%s\n", BITS_IN_POINTER
, new->pseudo
, show_ident(sym
->ident
));
1677 if (sym
->ctype
.modifiers
& MOD_ADDRESSABLE
) {
1678 printf("\taddi.%d\t\tv%d,vFP,$%lld\n", BITS_IN_POINTER
, new->pseudo
, sym
->value
);
1681 printf("\taddi.%d\t\tv%d,vFP,$offsetof(%s:%p)\n", BITS_IN_POINTER
, new->pseudo
, show_ident(sym
->ident
), sym
);
1685 static void x86_symbol_init(struct symbol
*sym
)
1687 struct symbol_private
*priv
= sym
->aux
;
1688 struct expression
*expr
= sym
->initializer
;
1689 struct storage
*new;
1692 new = x86_expression(expr
);
1697 priv
= calloc(1, sizeof(*priv
));
1699 /* FIXME: leak! we don't free... */
1700 /* (well, we don't free symbols either) */
1706 static int type_is_signed(struct symbol
*sym
)
1708 if (sym
->type
== SYM_NODE
)
1709 sym
= sym
->ctype
.base_type
;
1710 if (sym
->type
== SYM_PTR
)
1712 return !(sym
->ctype
.modifiers
& MOD_UNSIGNED
);
1715 static struct storage
*x86_bitfield_expr(struct expression
*expr
)
1717 return x86_access(expr
);
1720 static struct storage
*x86_label_expr(struct expression
*expr
)
1722 struct storage
*new = new_pseudo();
1723 printf("\tmovi.%d\t\tv%d,.L%p\n",BITS_IN_POINTER
, new->pseudo
, expr
->label_symbol
);
1727 static struct storage
*x86_statement_expr(struct expression
*expr
)
1729 return x86_statement(expr
->statement
);
1732 static int x86_position_expr(struct expression
*expr
, struct symbol
*base
)
1734 struct storage
*new = x86_expression(expr
->init_expr
);
1735 struct symbol
*ctype
= expr
->init_sym
;
1737 printf("\tinsert v%d at [%d:%d] of %s\n", new->pseudo
,
1738 expr
->init_offset
, ctype
->bit_offset
,
1739 show_ident(base
->ident
));
1743 static void x86_initializer_expr(struct expression
*expr
, struct symbol
*ctype
)
1745 struct expression
*entry
;
1747 FOR_EACH_PTR(expr
->expr_list
, entry
) {
1748 // Nested initializers have their positions already
1749 // recursively calculated - just output them too
1750 if (entry
->type
== EXPR_INITIALIZER
) {
1751 x86_initializer_expr(entry
, ctype
);
1755 // Ignore initializer indexes and identifiers - the
1756 // evaluator has taken them into account
1757 if (entry
->type
== EXPR_IDENTIFIER
|| entry
->type
== EXPR_INDEX
)
1759 if (entry
->type
== EXPR_POS
) {
1760 x86_position_expr(entry
, ctype
);
1763 x86_initialization(ctype
, entry
);
1768 * Print out an expression. Return the pseudo that contains the
1771 static struct storage
*x86_expression(struct expression
*expr
)
1777 struct position
*pos
= &expr
->pos
;
1778 printf("\tno type at %s:%d:%d\n",
1779 input_streams
[pos
->stream
].name
,
1780 pos
->line
, pos
->pos
);
1784 switch (expr
->type
) {
1786 return x86_call_expression(expr
);
1788 case EXPR_ASSIGNMENT
:
1789 return x86_assignment(expr
);
1792 return emit_compare(expr
);
1796 return emit_binop(expr
);
1798 return x86_preop(expr
);
1800 return emit_postop(expr
);
1802 return emit_symbol_expr_init(expr
->symbol
);
1805 warn(expr
->pos
, "invalid expression after evaluation");
1808 return emit_cast_expr(expr
);
1810 return emit_value(expr
);
1812 return emit_string_expr(expr
);
1814 return x86_bitfield_expr(expr
);
1815 case EXPR_INITIALIZER
:
1816 x86_initializer_expr(expr
, expr
->ctype
);
1818 case EXPR_CONDITIONAL
:
1819 return emit_conditional_expr(expr
);
1820 case EXPR_STATEMENT
:
1821 return x86_statement_expr(expr
);
1823 return x86_label_expr(expr
);
1825 // None of these should exist as direct expressions: they are only
1826 // valid as sub-expressions of initializers.
1828 warn(expr
->pos
, "unable to show plain initializer position expression");
1830 case EXPR_IDENTIFIER
:
1831 warn(expr
->pos
, "unable to show identifier expression");
1834 warn(expr
->pos
, "unable to show index expression");