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
;
1109 const char *opname
= expr
->op
== SPECIAL_INCREMENT
? "incl" : "decl";
1111 /* FIXME: don't hardware operand size */
1112 int bits
= expr
->ctype
->bit_size
;
1116 struct storage
*new = new_pseudo();
1118 emit_copy(addr
, expr
->unop
->ctype
, new, NULL
);
1124 insn(opname
, addr
, NULL
, NULL
, 0);
1129 static struct storage
*emit_postop(struct expression
*expr
)
1131 return emit_inc_dec(expr
, 1);
1134 static struct storage
*emit_return_stmt(struct statement
*stmt
)
1136 struct function
*f
= current_func
;
1137 struct expression
*expr
= stmt
->ret_value
;
1138 struct storage
*val
= NULL
;
1141 if (expr
&& expr
->ctype
) {
1142 val
= x86_expression(expr
);
1143 assert(val
!= NULL
);
1144 emit_move(val
, REG_EAX
, expr
->ctype
, "return", 0);
1147 sprintf(s
, "\tjmp\t.L%d\n", f
->ret_target
);
1148 push_text_atom(f
, s
);
1153 static struct storage
*emit_conditional_expr(struct expression
*expr
)
1155 struct storage
*cond
= x86_expression(expr
->conditional
);
1156 struct storage
*true = x86_expression(expr
->cond_true
);
1157 struct storage
*false = x86_expression(expr
->cond_false
);
1158 struct storage
*new = new_pseudo();
1163 emit_move(cond
, REG_EAX
, expr
->conditional
->ctype
,
1164 "begin EXPR_CONDITIONAL", 0);
1165 emit_move(true, REG_ECX
, expr
->cond_true
->ctype
, NULL
, 0);
1166 emit_move(false, REG_EDX
, expr
->cond_false
->ctype
, NULL
, 0);
1168 /* test EAX (for zero/non-zero) */
1169 insn("test", REG_EAX
, REG_EAX
, NULL
, 0);
1171 /* if false, move EDX to ECX */
1172 insn("cmovz", REG_EDX
, REG_ECX
, NULL
, 0);
1174 /* finally, store the result (ECX) in a new pseudo / stack slot */
1176 emit_move(REG_ECX
, new, expr
->ctype
, "end EXPR_CONDITIONAL", 0);
1177 /* FIXME: we lose type knowledge of expression result at this point */
1182 static struct storage
*emit_symbol_expr_init(struct symbol
*sym
)
1184 struct expression
*expr
= sym
->initializer
;
1185 struct symbol_private
*priv
= sym
->aux
;
1188 priv
= calloc(1, sizeof(*priv
));
1192 struct storage
*new = new_pseudo();
1193 fprintf(stderr
, "FIXME! no value for symbol. creating pseudo %d (stack offset %d)\n",
1194 new->pseudo
, new->pseudo
* 4);
1197 priv
->addr
= x86_expression(expr
);
1204 static struct storage
*emit_string_expr(struct expression
*expr
)
1206 struct function
*f
= current_func
;
1207 int label
= new_label();
1208 struct storage
*new = new_pseudo();
1210 push_cstring(f
, expr
->string
, label
);
1212 new = new_storage(STOR_LABEL
);
1214 new->flags
= STOR_LABEL_VAL
;
1218 static struct storage
*emit_cast_expr(struct expression
*expr
)
1220 struct symbol
*old_type
, *new_type
;
1221 struct storage
*op
= x86_expression(expr
->cast_expression
);
1222 int oldbits
, newbits
;
1223 struct storage
*new;
1225 old_type
= expr
->cast_expression
->ctype
;
1226 new_type
= expr
->cast_type
;
1228 oldbits
= old_type
->bit_size
;
1229 newbits
= new_type
->bit_size
;
1230 if (oldbits
>= newbits
)
1233 emit_move(op
, REG_EAX
, old_type
, "begin cast ..", 0);
1236 emit_move(REG_EAX
, new, new_type
, ".... end cast", 0);
1241 static void x86_struct_member(struct symbol
*sym
, void *data
, int flags
)
1243 if (flags
& ITERATE_FIRST
)
1245 printf("%s:%d:%ld at offset %ld", show_ident(sym
->ident
), sym
->bit_size
, sym
->ctype
.alignment
, sym
->offset
);
1246 if (sym
->fieldwidth
)
1247 printf("[%d..%d]", sym
->bit_offset
, sym
->bit_offset
+sym
->fieldwidth
-1);
1248 if (flags
& ITERATE_LAST
)
1254 static void x86_symbol(struct symbol
*sym
)
1256 struct symbol
*type
;
1261 type
= sym
->ctype
.base_type
;
1266 * Show actual implementation information
1268 switch (type
->type
) {
1271 if (sym
->initializer
)
1274 emit_array_noinit(sym
);
1278 if (sym
->initializer
) {
1279 emit_object_pre(show_ident(sym
->ident
),
1280 sym
->ctype
.modifiers
,
1281 sym
->ctype
.alignment
,
1283 emit_scalar(sym
->initializer
, sym
->bit_size
);
1286 emit_scalar_noinit(sym
);
1290 symbol_iterate(type
->symbol_list
, x86_struct_member
, NULL
);
1294 symbol_iterate(type
->symbol_list
, x86_struct_member
, NULL
);
1298 struct statement
*stmt
= type
->stmt
;
1301 x86_statement(stmt
);
1302 emit_func_post(sym
);
1311 if (sym
->initializer
&& (type
->type
!= SYM_BASETYPE
) &&
1312 (type
->type
!= SYM_ARRAY
)) {
1314 x86_expression(sym
->initializer
);
1318 static void x86_symbol_init(struct symbol
*sym
);
1320 static void x86_switch_statement(struct statement
*stmt
)
1322 struct storage
*val
= x86_expression(stmt
->switch_expression
);
1324 printf("\tswitch v%d\n", val
->pseudo
);
1327 * Debugging only: Check that the case list is correct
1328 * by printing it out.
1330 * This is where a _real_ back-end would go through the
1331 * cases to decide whether to use a lookup table or a
1332 * series of comparisons etc
1334 printf("# case table:\n");
1335 FOR_EACH_PTR(stmt
->switch_case
->symbol_list
, sym
) {
1336 struct statement
*case_stmt
= sym
->stmt
;
1337 struct expression
*expr
= case_stmt
->case_expression
;
1338 struct expression
*to
= case_stmt
->case_to
;
1343 if (expr
->type
== EXPR_VALUE
) {
1344 printf(" case %lld", expr
->value
);
1346 if (to
->type
== EXPR_VALUE
) {
1347 printf(" .. %lld", to
->value
);
1349 printf(" .. what?");
1355 printf(": .L%p\n", sym
);
1357 printf("# end case table\n");
1359 x86_statement(stmt
->switch_statement
);
1361 if (stmt
->switch_break
->used
)
1362 printf(".L%p:\n", stmt
->switch_break
);
1365 static void x86_symbol_decl(struct symbol_list
*syms
)
1368 FOR_EACH_PTR(syms
, sym
) {
1369 x86_symbol_init(sym
);
1373 static void x86_loop(struct statement
*stmt
)
1375 struct statement
*pre_statement
= stmt
->iterator_pre_statement
;
1376 struct expression
*pre_condition
= stmt
->iterator_pre_condition
;
1377 struct statement
*statement
= stmt
->iterator_statement
;
1378 struct statement
*post_statement
= stmt
->iterator_post_statement
;
1379 struct expression
*post_condition
= stmt
->iterator_post_condition
;
1380 int loop_top
= 0, loop_bottom
= 0;
1381 struct storage
*val
;
1383 x86_symbol_decl(stmt
->iterator_syms
);
1384 x86_statement(pre_statement
);
1385 if (pre_condition
) {
1386 if (pre_condition
->type
== EXPR_VALUE
) {
1387 if (!pre_condition
->value
) {
1388 loop_bottom
= new_label();
1389 printf("\tjmp\t\t.L%d\n", loop_bottom
);
1392 loop_bottom
= new_label();
1393 val
= x86_expression(pre_condition
);
1394 printf("\tje\t\tv%d, .L%d\n", val
->pseudo
, loop_bottom
);
1397 if (!post_condition
|| post_condition
->type
!= EXPR_VALUE
|| post_condition
->value
) {
1398 loop_top
= new_label();
1399 printf(".L%d:\n", loop_top
);
1401 x86_statement(statement
);
1402 if (stmt
->iterator_continue
->used
)
1403 printf(".L%p:\n", stmt
->iterator_continue
);
1404 x86_statement(post_statement
);
1405 if (!post_condition
) {
1406 printf("\tjmp\t\t.L%d\n", loop_top
);
1407 } else if (post_condition
->type
== EXPR_VALUE
) {
1408 if (post_condition
->value
)
1409 printf("\tjmp\t\t.L%d\n", loop_top
);
1411 val
= x86_expression(post_condition
);
1412 printf("\tjne\t\tv%d, .L%d\n", val
->pseudo
, loop_top
);
1414 if (stmt
->iterator_break
->used
)
1415 printf(".L%p:\n", stmt
->iterator_break
);
1417 printf(".L%d:\n", loop_bottom
);
1421 * Print out a statement
1423 static struct storage
*x86_statement(struct statement
*stmt
)
1427 switch (stmt
->type
) {
1429 return emit_return_stmt(stmt
);
1430 case STMT_COMPOUND
: {
1431 struct statement
*s
;
1432 struct storage
*last
= NULL
;
1434 x86_symbol_decl(stmt
->syms
);
1435 FOR_EACH_PTR(stmt
->stmts
, s
) {
1436 last
= x86_statement(s
);
1442 case STMT_EXPRESSION
:
1443 return x86_expression(stmt
->expression
);
1445 emit_if_conditional(stmt
);
1448 x86_switch_statement(stmt
);
1452 printf(".L%p:\n", stmt
->case_label
);
1453 x86_statement(stmt
->case_statement
);
1464 printf(".L%p:\n", stmt
->label_identifier
);
1465 x86_statement(stmt
->label_statement
);
1469 if (stmt
->goto_expression
) {
1470 struct storage
*val
= x86_expression(stmt
->goto_expression
);
1471 printf("\tgoto *v%d\n", val
->pseudo
);
1473 printf("\tgoto .L%p\n", stmt
->goto_label
);
1477 printf("\tasm( .... )\n");
1484 static struct storage
*x86_call_expression(struct expression
*expr
)
1486 struct function
*f
= current_func
;
1487 struct symbol
*direct
;
1488 struct expression
*arg
, *fn
;
1489 struct storage
*retval
, *fncall
;
1494 warn(expr
->pos
, "\tcall with no type!");
1499 FOR_EACH_PTR_REVERSE(expr
->args
, arg
) {
1500 struct storage
*new = x86_expression(arg
);
1501 int size
= arg
->ctype
->bit_size
;
1503 /* FIXME: pay attention to 'size' */
1504 insn("pushl", new, NULL
,
1505 !framesize
? "begin function call" : NULL
, 0);
1507 framesize
+= size
>> 3;
1508 } END_FOR_EACH_PTR_REVERSE
;
1512 /* Remove dereference, if any */
1514 if (fn
->type
== EXPR_PREOP
) {
1515 if (fn
->unop
->type
== EXPR_SYMBOL
) {
1516 struct symbol
*sym
= fn
->unop
->symbol
;
1517 if (sym
->ctype
.base_type
->type
== SYM_FN
)
1522 sprintf(s
, "\tcall\t%s\n", show_ident(direct
->ident
));
1523 push_text_atom(f
, s
);
1525 fncall
= x86_expression(fn
);
1526 emit_move(fncall
, REG_EAX
, fn
->ctype
, NULL
, 0);
1528 strcpy(s
, "\tcall\t*%eax\n");
1529 push_text_atom(f
, s
);
1532 /* FIXME: pay attention to BITS_IN_POINTER */
1534 struct storage
*val
= new_storage(STOR_VALUE
);
1535 val
->value
= (long long) framesize
;
1536 insn("addl", val
, REG_ESP
, NULL
, ATOM_FREE_OP1
);
1539 retval
= new_pseudo();
1540 emit_move(REG_EAX
, retval
, expr
->ctype
, "end function call", 0);
1545 static struct storage
*x86_regular_preop(struct expression
*expr
)
1547 struct storage
*target
= x86_expression(expr
->unop
);
1548 struct storage
*new = new_pseudo();
1549 static const char *name
[] = {
1550 ['!'] = "nonzero", ['-'] = "neg",
1553 unsigned int op
= expr
->op
;
1556 opname
= show_special(op
);
1557 if (op
< sizeof(name
)/sizeof(*name
))
1559 printf("\t%s.%d\t\tv%d,v%d\n", opname
, expr
->ctype
->bit_size
, new->pseudo
, target
->pseudo
);
1563 static struct storage
*x86_address_gen(struct expression
*expr
)
1565 struct function
*f
= current_func
;
1566 struct storage
*addr
;
1567 struct storage
*new;
1570 if ((expr
->type
!= EXPR_PREOP
) ||
1571 ((expr
->type
== EXPR_PREOP
) && (expr
->op
!= '*')))
1572 return x86_expression(expr
->address
);
1574 addr
= x86_expression(expr
->unop
);
1575 if (expr
->unop
->type
== EXPR_SYMBOL
)
1578 emit_move(addr
, REG_EAX
, NULL
, "begin deref ..", 0);
1580 /* FIXME: operand size */
1581 strcpy(s
, "\tmovl\t(%eax), %ecx\n");
1582 push_text_atom(f
, s
);
1585 emit_move(REG_ECX
, new, NULL
, ".... end deref", 0);
1590 static struct storage
*x86_assignment(struct expression
*expr
)
1592 struct expression
*target
= expr
->left
;
1593 struct storage
*val
, *addr
;
1599 bits
= expr
->ctype
->bit_size
;
1600 val
= x86_expression(expr
->right
);
1601 addr
= x86_address_gen(target
);
1603 switch (val
->type
) {
1604 /* copy, where both operands are memory */
1607 emit_copy(val
, expr
->right
->ctype
, addr
, expr
->left
->ctype
);
1610 /* copy, one or zero operands are memory */
1615 emit_move(val
, addr
, expr
->left
->ctype
, NULL
, 0);
1621 static int x86_initialization(struct symbol
*sym
, struct expression
*expr
)
1623 struct storage
*val
, *addr
;
1629 bits
= expr
->ctype
->bit_size
;
1630 val
= x86_expression(expr
);
1631 addr
= x86_symbol_expr(sym
);
1632 // FIXME! The "target" expression is for bitfield store information.
1633 // Leave it NULL, which works fine.
1634 emit_store(NULL
, addr
, val
, bits
);
1638 static struct storage
*x86_access(struct expression
*expr
)
1640 return x86_address_gen(expr
);
1643 static struct storage
*x86_preop(struct expression
*expr
)
1646 * '*' is an lvalue access, and is fundamentally different
1647 * from an arithmetic operation. Maybe it should have an
1648 * expression type of its own..
1650 if (expr
->op
== '*')
1651 return x86_access(expr
);
1652 if (expr
->op
== SPECIAL_INCREMENT
|| expr
->op
== SPECIAL_DECREMENT
)
1653 return emit_inc_dec(expr
, 0);
1654 return x86_regular_preop(expr
);
1657 static struct storage
*x86_symbol_expr(struct symbol
*sym
)
1659 struct storage
*new = new_pseudo();
1661 if (sym
->ctype
.modifiers
& (MOD_TOPLEVEL
| MOD_EXTERN
| MOD_STATIC
)) {
1662 printf("\tmovi.%d\t\tv%d,$%s\n", BITS_IN_POINTER
, new->pseudo
, show_ident(sym
->ident
));
1665 if (sym
->ctype
.modifiers
& MOD_ADDRESSABLE
) {
1666 printf("\taddi.%d\t\tv%d,vFP,$%lld\n", BITS_IN_POINTER
, new->pseudo
, sym
->value
);
1669 printf("\taddi.%d\t\tv%d,vFP,$offsetof(%s:%p)\n", BITS_IN_POINTER
, new->pseudo
, show_ident(sym
->ident
), sym
);
1673 static void x86_symbol_init(struct symbol
*sym
)
1675 struct symbol_private
*priv
= sym
->aux
;
1676 struct expression
*expr
= sym
->initializer
;
1677 struct storage
*new;
1680 new = x86_expression(expr
);
1685 priv
= calloc(1, sizeof(*priv
));
1687 /* FIXME: leak! we don't free... */
1688 /* (well, we don't free symbols either) */
1694 static int type_is_signed(struct symbol
*sym
)
1696 if (sym
->type
== SYM_NODE
)
1697 sym
= sym
->ctype
.base_type
;
1698 if (sym
->type
== SYM_PTR
)
1700 return !(sym
->ctype
.modifiers
& MOD_UNSIGNED
);
1703 static struct storage
*x86_bitfield_expr(struct expression
*expr
)
1705 return x86_access(expr
);
1708 static struct storage
*x86_label_expr(struct expression
*expr
)
1710 struct storage
*new = new_pseudo();
1711 printf("\tmovi.%d\t\tv%d,.L%p\n",BITS_IN_POINTER
, new->pseudo
, expr
->label_symbol
);
1715 static struct storage
*x86_statement_expr(struct expression
*expr
)
1717 return x86_statement(expr
->statement
);
1720 static int x86_position_expr(struct expression
*expr
, struct symbol
*base
)
1722 struct storage
*new = x86_expression(expr
->init_expr
);
1723 struct symbol
*ctype
= expr
->init_sym
;
1725 printf("\tinsert v%d at [%d:%d] of %s\n", new->pseudo
,
1726 expr
->init_offset
, ctype
->bit_offset
,
1727 show_ident(base
->ident
));
1731 static void x86_initializer_expr(struct expression
*expr
, struct symbol
*ctype
)
1733 struct expression
*entry
;
1735 FOR_EACH_PTR(expr
->expr_list
, entry
) {
1736 // Nested initializers have their positions already
1737 // recursively calculated - just output them too
1738 if (entry
->type
== EXPR_INITIALIZER
) {
1739 x86_initializer_expr(entry
, ctype
);
1743 // Ignore initializer indexes and identifiers - the
1744 // evaluator has taken them into account
1745 if (entry
->type
== EXPR_IDENTIFIER
|| entry
->type
== EXPR_INDEX
)
1747 if (entry
->type
== EXPR_POS
) {
1748 x86_position_expr(entry
, ctype
);
1751 x86_initialization(ctype
, entry
);
1756 * Print out an expression. Return the pseudo that contains the
1759 static struct storage
*x86_expression(struct expression
*expr
)
1765 struct position
*pos
= &expr
->pos
;
1766 printf("\tno type at %s:%d:%d\n",
1767 input_streams
[pos
->stream
].name
,
1768 pos
->line
, pos
->pos
);
1772 switch (expr
->type
) {
1774 return x86_call_expression(expr
);
1776 case EXPR_ASSIGNMENT
:
1777 return x86_assignment(expr
);
1780 return emit_compare(expr
);
1784 return emit_binop(expr
);
1786 return x86_preop(expr
);
1788 return emit_postop(expr
);
1790 return emit_symbol_expr_init(expr
->symbol
);
1793 warn(expr
->pos
, "invalid expression after evaluation");
1796 return emit_cast_expr(expr
);
1798 return emit_value(expr
);
1800 return emit_string_expr(expr
);
1802 return x86_bitfield_expr(expr
);
1803 case EXPR_INITIALIZER
:
1804 x86_initializer_expr(expr
, expr
->ctype
);
1806 case EXPR_CONDITIONAL
:
1807 return emit_conditional_expr(expr
);
1808 case EXPR_STATEMENT
:
1809 return x86_statement_expr(expr
);
1811 return x86_label_expr(expr
);
1813 // None of these should exist as direct expressions: they are only
1814 // valid as sub-expressions of initializers.
1816 warn(expr
->pos
, "unable to show plain initializer position expression");
1818 case EXPR_IDENTIFIER
:
1819 warn(expr
->pos
, "unable to show identifier expression");
1822 warn(expr
->pos
, "unable to show index expression");