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
13 * in general, any non-32bit SYM_BASETYPE is unlikely to work.
15 * complex initializers
17 * global struct/union variables
18 * addressing structures, and members of structures (as opposed to
19 * scalars) on the stack. Requires smarter stack frame allocation.
21 * any function argument that isn't 32 bits (or promoted to such)
40 #include "expression.h"
46 unsigned int len
; /* does NOT include terminating null */
55 struct ptr_list
*pseudo_list
;
56 struct ptr_list
*atom_list
;
57 struct ptr_list
*str_list
;
64 STOR_PSEUDO
, /* variable stored on the stack */
65 STOR_ARG
, /* function argument */
66 STOR_SYM
, /* a symbol we can directly ref in the asm */
67 STOR_REG
, /* scratch register */
68 STOR_VALUE
, /* integer constant */
69 STOR_LABEL
, /* label / jump target */
70 STOR_LABELSYM
, /* label generated from symbol's pointer value */
78 enum storage_type type
;
109 struct symbol
*labelsym
;
115 STOR_LABEL_VAL
= (1 << 0),
116 STOR_WANTS_FREE
= (1 << 1),
119 struct symbol_private
{
120 struct storage
*addr
;
135 unsigned int text_len
; /* w/o terminating null */
138 /* stuff for insns */
146 /* stuff for C strings */
148 struct string
*string
;
155 struct function
*current_func
= NULL
;
156 struct textbuf
*unit_post_text
= NULL
;
157 static const char *current_section
;
159 static struct reg_info reg_info_table
[] = {
167 static struct storage hardreg_storage_table
[] = {
170 .reg
= ®_info_table
[0],
175 .reg
= ®_info_table
[1],
180 .reg
= ®_info_table
[2],
185 .reg
= ®_info_table
[3],
190 .reg
= ®_info_table
[4],
194 #define REG_EAX (&hardreg_storage_table[0])
195 #define REG_ECX (&hardreg_storage_table[1])
196 #define REG_EDX (&hardreg_storage_table[2])
197 #define REG_ESP (&hardreg_storage_table[3])
198 #define REG_DL (&hardreg_storage_table[4])
201 static void emit_move(struct storage
*src
, struct storage
*dest
,
202 struct symbol
*ctype
, const char *comment
);
203 static int type_is_signed(struct symbol
*sym
);
204 static struct storage
*x86_address_gen(struct expression
*expr
);
205 static struct storage
*x86_symbol_expr(struct symbol
*sym
);
206 static void x86_symbol(struct symbol
*sym
);
207 static struct storage
*x86_statement(struct statement
*stmt
);
208 static struct storage
*x86_expression(struct expression
*expr
);
211 static inline unsigned int pseudo_offset(struct storage
*s
)
213 if (s
->type
!= STOR_PSEUDO
)
214 return 123456; /* intentionally bogus value */
219 static inline unsigned int arg_offset(struct storage
*s
)
221 if (s
->type
!= STOR_ARG
)
222 return 123456; /* intentionally bogus value */
224 /* FIXME: this is wrong wrong wrong */
225 return current_func
->stack_size
+ ((1 + s
->idx
) * 4);
228 static const char *pretty_offset(int ofs
)
230 static char esp_buf
[64];
233 sprintf(esp_buf
, "%d(%%esp)", ofs
);
235 strcpy(esp_buf
, "(%esp)");
240 static void stor_sym_init(struct symbol
*sym
)
242 struct storage
*stor
;
243 struct symbol_private
*priv
;
245 priv
= calloc(1, sizeof(*priv
) + sizeof(*stor
));
247 die("OOM in stor_sym_init");
249 stor
= (struct storage
*) (priv
+ 1);
252 stor
->type
= STOR_SYM
;
256 static const char *stor_op_name(struct storage
*s
)
258 static char name
[32];
262 strcpy(name
, pretty_offset((int) pseudo_offset(s
)));
265 strcpy(name
, pretty_offset((int) arg_offset(s
)));
268 strcpy(name
, show_ident(s
->sym
->ident
));
271 strcpy(name
, s
->reg
->name
);
274 sprintf(name
, "$%Ld", s
->value
);
277 sprintf(name
, "%s.L%d", s
->flags
& STOR_LABEL_VAL
? "$" : "",
281 sprintf(name
, "%s.LS%p", s
->flags
& STOR_LABEL_VAL
? "$" : "",
289 static struct atom
*new_atom(enum atom_type type
)
293 atom
= calloc(1, sizeof(*atom
)); /* TODO: chunked alloc */
302 static inline void push_cstring(struct function
*f
, struct string
*str
,
307 atom
= new_atom(ATOM_CSTR
);
311 add_ptr_list(&f
->str_list
, atom
); /* note: _not_ atom_list */
314 static inline void push_atom(struct function
*f
, struct atom
*atom
)
316 add_ptr_list(&f
->atom_list
, atom
);
319 static void push_text_atom(struct function
*f
, const char *text
)
321 struct atom
*atom
= new_atom(ATOM_TEXT
);
323 atom
->text
= strdup(text
);
324 atom
->text_len
= strlen(text
);
329 static struct storage
*new_storage(enum storage_type type
)
331 struct storage
*stor
;
333 stor
= calloc(1, sizeof(*stor
));
335 die("OOM in new_storage");
342 static struct storage
*stack_alloc(int n_bytes
)
344 struct function
*f
= current_func
;
345 struct storage
*stor
;
349 stor
= new_storage(STOR_PSEUDO
);
350 stor
->type
= STOR_PSEUDO
;
351 stor
->pseudo
= f
->pseudo_nr
;
352 stor
->offset
= f
->stack_size
;
353 stor
->size
= n_bytes
;
354 f
->stack_size
+= n_bytes
;
357 add_ptr_list(&f
->pseudo_list
, stor
);
362 static struct storage
*new_labelsym(struct symbol
*sym
)
364 struct storage
*stor
;
366 stor
= new_storage(STOR_LABELSYM
);
369 stor
->flags
|= STOR_WANTS_FREE
;
370 stor
->labelsym
= sym
;
376 static struct storage
*new_val(long long value
)
378 struct storage
*stor
;
380 stor
= new_storage(STOR_VALUE
);
383 stor
->flags
|= STOR_WANTS_FREE
;
390 static int new_label(void)
392 static int label
= 0;
396 static void textbuf_push(struct textbuf
**buf_p
, const char *text
)
398 struct textbuf
*tmp
, *list
= *buf_p
;
399 unsigned int text_len
= strlen(text
);
400 unsigned int alloc_len
= text_len
+ 1 + sizeof(*list
);
402 tmp
= calloc(1, alloc_len
);
404 die("OOM on textbuf alloc");
406 tmp
->text
= ((void *) tmp
) + sizeof(*tmp
);
407 memcpy(tmp
->text
, text
, text_len
+ 1);
410 /* add to end of list */
415 tmp
->prev
= list
->prev
;
416 tmp
->prev
->next
= tmp
;
424 static void textbuf_emit(struct textbuf
**buf_p
)
426 struct textbuf
*tmp
, *list
= *buf_p
;
430 if (tmp
->next
== tmp
)
433 tmp
->prev
->next
= tmp
->next
;
434 tmp
->next
->prev
= tmp
->prev
;
438 fputs(tmp
->text
, stdout
);
446 static void insn(const char *insn
, struct storage
*op1
, struct storage
*op2
,
447 const char *comment_in
)
449 struct function
*f
= current_func
;
450 struct atom
*atom
= new_atom(ATOM_INSN
);
452 assert(insn
!= NULL
);
454 strcpy(atom
->insn
, insn
);
455 if (comment_in
&& (*comment_in
))
456 strncpy(atom
->comment
, comment_in
,
457 sizeof(atom
->comment
) - 1);
465 static void emit_label (int label
, const char *comment
)
467 struct function
*f
= current_func
;
471 sprintf(s
, ".L%d:\n", label
);
473 sprintf(s
, ".L%d:\t\t\t\t\t# %s\n", label
, comment
);
475 push_text_atom(f
, s
);
478 static void emit_labelsym (struct symbol
*sym
, const char *comment
)
480 struct function
*f
= current_func
;
484 sprintf(s
, ".LS%p:\n", sym
);
486 sprintf(s
, ".LS%p:\t\t\t\t# %s\n", sym
, comment
);
488 push_text_atom(f
, s
);
491 static void emit_unit_pre(const char *basename
)
493 printf("\t.file\t\"%s\"\n", basename
);
496 static void emit_unit_post(void)
498 textbuf_emit(&unit_post_text
);
499 printf("\t.ident\t\"sparse silly x86 backend (built %s)\"\n", __DATE__
);
502 /* conditionally switch sections */
503 static void emit_section(const char *s
)
505 if (s
== current_section
)
507 if (current_section
&& (!strcmp(s
, current_section
)))
514 static void emit_insn_atom(struct function
*f
, struct atom
*atom
)
518 struct storage
*op1
= atom
->op1
;
519 struct storage
*op2
= atom
->op2
;
521 if (atom
->comment
[0])
522 sprintf(comment
, "\t\t# %s", atom
->comment
);
528 strcpy(tmp
, stor_op_name(op1
));
529 sprintf(s
, "\t%s\t%s, %s%s\n",
530 atom
->insn
, tmp
, stor_op_name(op2
), comment
);
531 } else if (atom
->op1
)
532 sprintf(s
, "\t%s\t%s%s%s\n",
533 atom
->insn
, stor_op_name(op1
),
534 comment
[0] ? "\t" : "", comment
);
536 sprintf(s
, "\t%s\t%s%s\n",
538 comment
[0] ? "\t\t" : "", comment
);
540 write(STDOUT_FILENO
, s
, strlen(s
));
543 static void emit_atom_list(struct function
*f
)
547 FOR_EACH_PTR(f
->atom_list
, atom
) {
548 switch (atom
->type
) {
550 ssize_t rc
= write(STDOUT_FILENO
, atom
->text
,
552 (void) rc
; /* FIXME */
556 emit_insn_atom(f
, atom
);
565 static void emit_string_list(struct function
*f
)
569 emit_section(".section\t.rodata");
571 FOR_EACH_PTR(f
->str_list
, atom
) {
572 /* FIXME: escape " in string */
573 printf(".L%d:\n", atom
->label
);
574 printf("\t.string\t%s\n", show_string(atom
->string
));
580 static void func_cleanup(struct function
*f
)
582 struct storage
*stor
;
585 FOR_EACH_PTR(f
->pseudo_list
, stor
) {
589 FOR_EACH_PTR(f
->atom_list
, atom
) {
590 if ((atom
->type
== ATOM_TEXT
) && (atom
->text
))
592 if (atom
->op1
&& (atom
->op1
->flags
& STOR_WANTS_FREE
))
594 if (atom
->op2
&& (atom
->op2
->flags
& STOR_WANTS_FREE
))
599 free_ptr_list(&f
->pseudo_list
);
603 /* function prologue */
604 static void emit_func_pre(struct symbol
*sym
)
608 unsigned int i
, argc
= 0, alloc_len
;
610 struct symbol_private
*privbase
;
611 struct storage
*storage_base
;
612 struct symbol
*base_type
= sym
->ctype
.base_type
;
614 FOR_EACH_PTR(base_type
->arguments
, arg
) {
620 (argc
* sizeof(struct symbol
*)) +
621 (argc
* sizeof(struct symbol_private
)) +
622 (argc
* sizeof(struct storage
));
623 mem
= calloc(1, alloc_len
);
625 die("OOM on func info");
627 f
= (struct function
*) mem
;
629 f
->argv
= (struct symbol
**) mem
;
630 mem
+= (argc
* sizeof(struct symbol
*));
631 privbase
= (struct symbol_private
*) mem
;
632 mem
+= (argc
* sizeof(struct symbol_private
));
633 storage_base
= (struct storage
*) mem
;
636 f
->ret_target
= new_label();
639 FOR_EACH_PTR(base_type
->arguments
, arg
) {
641 arg
->aux
= &privbase
[i
];
642 storage_base
[i
].type
= STOR_ARG
;
643 storage_base
[i
].idx
= i
;
644 privbase
[i
].addr
= &storage_base
[i
];
648 assert(current_func
== NULL
);
652 /* function epilogue */
653 static void emit_func_post(struct symbol
*sym
)
655 const char *name
= show_ident(sym
->ident
);
656 struct function
*f
= current_func
;
657 int stack_size
= f
->stack_size
;
662 /* function prologue */
663 emit_section(".text");
664 if ((sym
->ctype
.modifiers
& MOD_STATIC
) == 0)
665 printf(".globl %s\n", name
);
666 printf("\t.type\t%s, @function\n", name
);
667 printf("%s:\n", name
);
670 char pseudo_const
[16];
672 sprintf(pseudo_const
, "$%d", stack_size
);
673 printf("\tsubl\t%s, %%esp\n", pseudo_const
);
676 /* function epilogue */
678 /* jump target for 'return' statements */
679 emit_label(f
->ret_target
, NULL
);
684 val
= new_storage(STOR_VALUE
);
685 val
->value
= (long long) (stack_size
);
686 val
->flags
= STOR_WANTS_FREE
;
688 insn("addl", val
, REG_ESP
, NULL
);
691 insn("ret", NULL
, NULL
, NULL
);
693 /* output everything to stdout */
694 fflush(stdout
); /* paranoia; needed? */
697 /* function footer */
698 printf("\t.size\t%s, .-%s\n", name
, name
);
704 /* emit object (a.k.a. variable, a.k.a. data) prologue */
705 static void emit_object_pre(const char *name
, unsigned long modifiers
,
706 unsigned long alignment
, unsigned int byte_size
)
708 if ((modifiers
& MOD_STATIC
) == 0)
709 printf(".globl %s\n", name
);
710 emit_section(".data");
712 printf("\t.align %lu\n", alignment
);
713 printf("\t.type\t%s, @object\n", name
);
714 printf("\t.size\t%s, %d\n", name
, byte_size
);
715 printf("%s:\n", name
);
718 /* emit value (only) for an initializer scalar */
719 static void emit_scalar(struct expression
*expr
, unsigned int bit_size
)
724 assert(expr
->type
== EXPR_VALUE
);
726 if (expr
->value
== 0ULL) {
727 printf("\t.zero\t%d\n", bit_size
/ 8);
731 ll
= (long long) expr
->value
;
734 case 8: type
= "byte"; ll
= (char) ll
; break;
735 case 16: type
= "value"; ll
= (short) ll
; break;
736 case 32: type
= "long"; ll
= (int) ll
; break;
737 case 64: type
= "quad"; break;
738 default: type
= NULL
; break;
741 assert(type
!= NULL
);
743 printf("\t.%s\t%Ld\n", type
, ll
);
746 static void emit_global_noinit(const char *name
, unsigned long modifiers
,
747 unsigned long alignment
, unsigned int byte_size
)
751 if (modifiers
& MOD_STATIC
) {
752 sprintf(s
, "\t.local\t%s\n", name
);
753 textbuf_push(&unit_post_text
, s
);
756 sprintf(s
, "\t.comm\t%s,%d,%lu\n", name
, byte_size
, alignment
);
758 sprintf(s
, "\t.comm\t%s,%d\n", name
, byte_size
);
759 textbuf_push(&unit_post_text
, s
);
762 static int ea_current
, ea_last
;
764 static void emit_initializer(struct symbol
*sym
,
765 struct expression
*expr
)
767 int distance
= ea_current
- ea_last
- 1;
770 printf("\t.zero\t%d\n", (sym
->bit_size
/ 8) * distance
);
772 if (expr
->type
== EXPR_VALUE
) {
773 struct symbol
*base_type
= sym
->ctype
.base_type
;
774 assert(base_type
!= NULL
);
776 emit_scalar(expr
, sym
->bit_size
/ get_expression_value(base_type
->array_size
));
779 if (expr
->type
!= EXPR_INITIALIZER
)
782 assert(0); /* FIXME */
785 static int sort_array_cmp(const struct expression
*a
,
786 const struct expression
*b
)
788 int a_ofs
= 0, b_ofs
= 0;
790 if (a
->type
== EXPR_POS
)
791 a_ofs
= (int) a
->init_offset
;
792 if (b
->type
== EXPR_POS
)
793 b_ofs
= (int) b
->init_offset
;
795 return a_ofs
- b_ofs
;
798 /* move to front-end? */
799 static void sort_array(struct expression
*expr
)
801 struct expression
*entry
, **list
;
802 unsigned int elem
, sorted
, i
;
805 FOR_EACH_PTR(expr
->expr_list
, entry
) {
812 list
= malloc(sizeof(entry
) * elem
);
814 die("OOM in sort_array");
816 /* this code is no doubt evil and ignores EXPR_INDEX possibly
817 * to its detriment and other nasty things. improvements
822 FOR_EACH_PTR(expr
->expr_list
, entry
) {
823 if ((entry
->type
== EXPR_POS
) || (entry
->type
== EXPR_VALUE
)) {
824 /* add entry to list[], in sorted order */
831 for (i
= 0; i
< sorted
; i
++)
832 if (sort_array_cmp(entry
, list
[i
]) <= 0)
835 /* If inserting into the middle of list[]
836 * instead of appending, we memmove.
837 * This is ugly, but thankfully
838 * uncommon. Input data with tons of
839 * entries very rarely have explicit
840 * offsets. convert to qsort eventually...
843 memmove(&list
[i
+ 1], &list
[i
],
844 (sorted
- i
) * sizeof(entry
));
852 FOR_EACH_PTR(expr
->expr_list
, entry
) {
853 if ((entry
->type
== EXPR_POS
) || (entry
->type
== EXPR_VALUE
))
854 __list
->list
[__i
] = list
[i
++];
859 static void emit_array(struct symbol
*sym
)
861 struct symbol
*base_type
= sym
->ctype
.base_type
;
862 struct expression
*expr
= sym
->initializer
;
863 struct expression
*entry
;
865 assert(base_type
!= NULL
);
871 emit_object_pre(show_ident(sym
->ident
), sym
->ctype
.modifiers
,
872 sym
->ctype
.alignment
,
877 FOR_EACH_PTR(expr
->expr_list
, entry
) {
878 if (entry
->type
== EXPR_VALUE
) {
880 emit_initializer(sym
, entry
);
881 ea_last
= ea_current
;
882 } else if (entry
->type
== EXPR_POS
) {
884 entry
->init_offset
/ (base_type
->bit_size
/ 8);
885 emit_initializer(sym
, entry
->init_expr
);
886 ea_last
= ea_current
;
891 static void emit_one_symbol(struct symbol
*sym
, void *dummy
, int flags
)
896 void emit_unit(const char *basename
, struct symbol_list
*list
)
898 emit_unit_pre(basename
);
899 symbol_iterate(list
, emit_one_symbol
, NULL
);
903 static void emit_copy(struct storage
*src
, struct symbol
*src_ctype
,
904 struct storage
*dest
, struct symbol
*dest_ctype
)
906 /* FIXME: Bitfield move! */
908 emit_move(src
, REG_EAX
, src_ctype
, "begin copy ..");
909 emit_move(REG_EAX
, dest
, dest_ctype
, ".... end copy");
912 static void emit_store(struct expression
*dest_expr
, struct storage
*dest
,
913 struct storage
*src
, int bits
)
915 /* FIXME: Bitfield store! */
916 printf("\tst.%d\t\tv%d,[v%d]\n", bits
, src
->pseudo
, dest
->pseudo
);
919 static void emit_scalar_noinit(struct symbol
*sym
)
921 emit_global_noinit(show_ident(sym
->ident
),
922 sym
->ctype
.modifiers
, sym
->ctype
.alignment
,
927 static void emit_array_noinit(struct symbol
*sym
)
929 emit_global_noinit(show_ident(sym
->ident
),
930 sym
->ctype
.modifiers
, sym
->ctype
.alignment
,
931 get_expression_value(sym
->array_size
) * (sym
->bit_size
/ 8));
935 static const char *opbits(const char *insn
, unsigned int bits
)
937 static char opbits_str
[32];
941 case 8: c
= 'b'; break;
942 case 16: c
= 'w'; break;
943 case 32: c
= 'l'; break;
944 case 64: c
= 'q'; break;
945 default: assert(0); break;
948 sprintf(opbits_str
, "%s%c", insn
, bits
);
953 static void emit_move(struct storage
*src
, struct storage
*dest
,
954 struct symbol
*ctype
, const char *comment
)
957 unsigned int is_signed
;
958 unsigned int is_dest
= (src
->type
== STOR_REG
);
962 bits
= ctype
->bit_size
;
963 is_signed
= type_is_signed(ctype
);
969 if ((dest
->type
== STOR_REG
) && (src
->type
== STOR_REG
)) {
970 insn("mov", src
, dest
, NULL
);
979 if (is_signed
) opname
= "movsxb";
980 else opname
= "movzxb";
987 if (is_signed
) opname
= "movsxw";
988 else opname
= "movzxw";
992 case 32: opname
= "movl"; break;
993 case 64: opname
= "movq"; break;
995 default: assert(0); break;
998 insn(opname
, src
, dest
, comment
);
1001 static struct storage
*emit_compare(struct expression
*expr
)
1003 struct storage
*left
= x86_expression(expr
->left
);
1004 struct storage
*right
= x86_expression(expr
->right
);
1005 struct storage
*new, *val
;
1006 const char *opname
= NULL
;
1007 unsigned int is_signed
= type_is_signed(expr
->left
->ctype
); /* FIXME */
1008 unsigned int right_bits
= expr
->right
->ctype
->bit_size
;
1012 if (is_signed
) opname
= "setl";
1013 else opname
= "setb";
1016 if (is_signed
) opname
= "setg";
1017 else opname
= "seta";
1020 if (is_signed
) opname
= "setle";
1021 else opname
= "setbe";
1024 if (is_signed
) opname
= "setge";
1025 else opname
= "setae";
1028 case SPECIAL_EQUAL
: opname
= "sete"; break;
1029 case SPECIAL_NOTEQUAL
: opname
= "setne"; break;
1037 val
= new_storage(STOR_VALUE
);
1038 val
->flags
= STOR_WANTS_FREE
;
1039 emit_move(val
, REG_EDX
, NULL
, NULL
);
1041 /* move op1 into EAX */
1042 emit_move(left
, REG_EAX
, expr
->left
->ctype
, NULL
);
1044 /* perform comparison, RHS (op1, right) and LHS (op2, EAX) */
1045 insn(opbits("cmp", right_bits
), right
, REG_EAX
, NULL
);
1047 /* store result of operation, 0 or 1, in DL using SETcc */
1048 insn(opname
, REG_DL
, NULL
, NULL
);
1050 /* finally, store the result (DL) in a new pseudo / stack slot */
1051 new = stack_alloc(4);
1052 emit_move(REG_EDX
, new, NULL
, "end EXPR_COMPARE");
1057 static struct storage
*emit_value(struct expression
*expr
)
1059 #if 0 /* old and slow way */
1060 struct storage
*new = stack_alloc(4);
1061 struct storage
*val
;
1063 val
= new_storage(STOR_VALUE
);
1064 val
->value
= (long long) expr
->value
;
1065 val
->flags
= STOR_WANTS_FREE
;
1066 insn("movl", val
, new, NULL
);
1070 struct storage
*val
;
1072 val
= new_storage(STOR_VALUE
);
1073 val
->value
= (long long) expr
->value
;
1075 return val
; /* FIXME: memory leak */
1079 static struct storage
*emit_binop(struct expression
*expr
)
1081 struct storage
*left
= x86_expression(expr
->left
);
1082 struct storage
*right
= x86_expression(expr
->right
);
1083 struct storage
*new;
1084 const char *opname
= NULL
;
1087 * FIXME FIXME this routine is so wrong it's not even funny.
1088 * On x86 both mod/div are handled with the same instruction.
1089 * We don't pay attention to signed/unsigned issues,
1090 * and like elsewhere we hardcode the operand size at 32 bits.
1094 case '+': opname
= "addl"; break;
1095 case '-': opname
= "subl"; break;
1096 case '*': opname
= "mull"; break;
1097 case '/': opname
= "divl"; break;
1098 case '%': opname
= "modl"; break;
1099 case '&': opname
= "andl"; break;
1100 case '|': opname
= "orl"; break;
1101 case '^': opname
= "xorl"; break;
1102 case SPECIAL_LEFTSHIFT
: opname
= "shll"; break;
1103 case SPECIAL_RIGHTSHIFT
: opname
= "shrl"; break;
1104 default: assert(0); break;
1107 /* load op2 into EAX */
1108 insn("movl", right
, REG_EAX
, "EXPR_BINOP/COMMA/LOGICAL");
1111 insn(opname
, left
, REG_EAX
, NULL
);
1113 /* store result (EAX) in new pseudo / stack slot */
1114 new = stack_alloc(4);
1115 insn("movl", REG_EAX
, new, "end EXPR_BINOP");
1120 static void emit_if_conditional(struct statement
*stmt
)
1122 struct storage
*val
, *target_val
;
1124 struct expression
*cond
= stmt
->if_conditional
;
1126 /* This is only valid if nobody can jump into the "dead" statement */
1128 if (cond
->type
== EXPR_VALUE
) {
1129 struct statement
*s
= stmt
->if_true
;
1136 val
= x86_expression(cond
);
1138 /* load 'if' test result into EAX */
1139 insn("movl", val
, REG_EAX
, "begin if conditional");
1141 /* compare 'if' test result */
1142 insn("test", REG_EAX
, REG_EAX
, NULL
);
1144 /* create end-of-if label / if-failed labelto jump to,
1145 * and jump to it if the expression returned zero.
1147 target
= new_label();
1148 target_val
= new_storage(STOR_LABEL
);
1149 target_val
->label
= target
;
1150 target_val
->flags
= STOR_WANTS_FREE
;
1151 insn("jz", target_val
, NULL
, NULL
);
1153 x86_statement(stmt
->if_true
);
1154 if (stmt
->if_false
) {
1155 struct storage
*last_val
;
1158 /* finished generating code for if-true statement.
1159 * add a jump-to-end jump to avoid falling through
1160 * to the if-false statement code.
1163 last_val
= new_storage(STOR_LABEL
);
1164 last_val
->label
= last
;
1165 last_val
->flags
= STOR_WANTS_FREE
;
1166 insn("jmp", last_val
, NULL
, NULL
);
1168 /* if we have both if-true and if-false statements,
1169 * the failed-conditional case will fall through to here
1171 emit_label(target
, NULL
);
1174 x86_statement(stmt
->if_false
);
1177 emit_label(target
, "end if");
1180 static struct storage
*emit_inc_dec(struct expression
*expr
, int postop
)
1182 struct storage
*addr
= x86_address_gen(expr
->unop
);
1183 struct storage
*retval
;
1186 strcpy(opname
, opbits(expr
->op
== SPECIAL_INCREMENT
? "inc" : "dec",
1187 expr
->ctype
->bit_size
));
1190 struct storage
*new = stack_alloc(4);
1192 emit_copy(addr
, expr
->unop
->ctype
, new, NULL
);
1198 insn(opname
, addr
, NULL
, NULL
);
1203 static struct storage
*emit_postop(struct expression
*expr
)
1205 return emit_inc_dec(expr
, 1);
1208 static struct storage
*emit_return_stmt(struct statement
*stmt
)
1210 struct function
*f
= current_func
;
1211 struct expression
*expr
= stmt
->ret_value
;
1212 struct storage
*val
= NULL
, *jmplbl
;
1214 if (expr
&& expr
->ctype
) {
1215 val
= x86_expression(expr
);
1216 assert(val
!= NULL
);
1217 emit_move(val
, REG_EAX
, expr
->ctype
, "return");
1220 jmplbl
= new_storage(STOR_LABEL
);
1221 jmplbl
->flags
|= STOR_WANTS_FREE
;
1222 jmplbl
->label
= f
->ret_target
;
1223 insn("jmp", jmplbl
, NULL
, NULL
);
1228 static struct storage
*emit_conditional_expr(struct expression
*expr
)
1230 struct storage
*cond
= x86_expression(expr
->conditional
);
1231 struct storage
*true = x86_expression(expr
->cond_true
);
1232 struct storage
*false = x86_expression(expr
->cond_false
);
1233 struct storage
*new = stack_alloc(4);
1238 emit_move(cond
, REG_EAX
, expr
->conditional
->ctype
,
1239 "begin EXPR_CONDITIONAL");
1240 emit_move(true, REG_ECX
, expr
->cond_true
->ctype
, NULL
);
1241 emit_move(false, REG_EDX
, expr
->cond_false
->ctype
, NULL
);
1243 /* test EAX (for zero/non-zero) */
1244 insn("test", REG_EAX
, REG_EAX
, NULL
);
1246 /* if false, move EDX to ECX */
1247 insn("cmovz", REG_EDX
, REG_ECX
, NULL
);
1249 /* finally, store the result (ECX) in a new pseudo / stack slot */
1250 new = stack_alloc(4);
1251 emit_move(REG_ECX
, new, expr
->ctype
, "end EXPR_CONDITIONAL");
1252 /* FIXME: we lose type knowledge of expression result at this point */
1257 static struct storage
*emit_symbol_expr_init(struct symbol
*sym
)
1259 struct expression
*expr
= sym
->initializer
;
1260 struct symbol_private
*priv
= sym
->aux
;
1263 priv
= calloc(1, sizeof(*priv
));
1267 struct storage
*new = stack_alloc(4);
1268 fprintf(stderr
, "FIXME! no value for symbol. creating pseudo %d (stack offset %d)\n",
1269 new->pseudo
, new->pseudo
* 4);
1272 priv
->addr
= x86_expression(expr
);
1279 static struct storage
*emit_string_expr(struct expression
*expr
)
1281 struct function
*f
= current_func
;
1282 int label
= new_label();
1283 struct storage
*new;
1285 push_cstring(f
, expr
->string
, label
);
1287 new = new_storage(STOR_LABEL
);
1289 new->flags
= STOR_LABEL_VAL
| STOR_WANTS_FREE
;
1293 static struct storage
*emit_cast_expr(struct expression
*expr
)
1295 struct symbol
*old_type
, *new_type
;
1296 struct storage
*op
= x86_expression(expr
->cast_expression
);
1297 int oldbits
, newbits
;
1298 struct storage
*new;
1300 old_type
= expr
->cast_expression
->ctype
;
1301 new_type
= expr
->cast_type
;
1303 oldbits
= old_type
->bit_size
;
1304 newbits
= new_type
->bit_size
;
1305 if (oldbits
>= newbits
)
1308 emit_move(op
, REG_EAX
, old_type
, "begin cast ..");
1310 new = stack_alloc(4);
1311 emit_move(REG_EAX
, new, new_type
, ".... end cast");
1316 static struct storage
*emit_regular_preop(struct expression
*expr
)
1318 struct storage
*target
= x86_expression(expr
->unop
);
1319 struct storage
*val
, *new = stack_alloc(4);
1320 const char *opname
= NULL
;
1324 val
= new_storage(STOR_VALUE
);
1325 val
->flags
= STOR_WANTS_FREE
;
1326 emit_move(val
, REG_EDX
, NULL
, NULL
);
1327 emit_move(target
, REG_EAX
, expr
->unop
->ctype
, NULL
);
1328 insn("test", REG_EAX
, REG_EAX
, NULL
);
1329 insn("setz", REG_DL
, NULL
, NULL
);
1330 emit_move(REG_EDX
, new, expr
->unop
->ctype
, NULL
);
1338 emit_move(target
, REG_EAX
, expr
->unop
->ctype
, NULL
);
1339 insn(opname
, REG_EAX
, NULL
, NULL
);
1340 emit_move(REG_EAX
, new, expr
->unop
->ctype
, NULL
);
1350 static void emit_case_statement(struct statement
*stmt
)
1352 emit_labelsym(stmt
->case_label
, NULL
);
1353 x86_statement(stmt
->case_statement
);
1356 static void emit_switch_statement(struct statement
*stmt
)
1358 struct storage
*val
= x86_expression(stmt
->switch_expression
);
1359 struct symbol
*sym
, *default_sym
= NULL
;
1360 struct storage
*labelsym
, *label
;
1363 emit_move(val
, REG_EAX
, stmt
->switch_expression
->ctype
, "begin case");
1366 * This is where a _real_ back-end would go through the
1367 * cases to decide whether to use a lookup table or a
1368 * series of comparisons etc
1370 FOR_EACH_PTR(stmt
->switch_case
->symbol_list
, sym
) {
1371 struct statement
*case_stmt
= sym
->stmt
;
1372 struct expression
*expr
= case_stmt
->case_expression
;
1373 struct expression
*to
= case_stmt
->case_to
;
1381 struct storage
*case_val
= new_val(expr
->value
);
1383 assert (expr
->type
== EXPR_VALUE
);
1385 insn("cmpl", case_val
, REG_EAX
, NULL
);
1388 labelsym
= new_labelsym(sym
);
1389 insn("je", labelsym
, NULL
, NULL
);
1393 label
= new_storage(STOR_LABEL
);
1394 label
->flags
|= STOR_WANTS_FREE
;
1395 label
->label
= next_test
= new_label();
1397 /* FIXME: signed/unsigned */
1398 insn("jl", label
, NULL
, NULL
);
1400 case_val
= new_val(to
->value
);
1401 insn("cmpl", case_val
, REG_EAX
, NULL
);
1403 /* TODO: implement and use refcounting... */
1404 label
= new_storage(STOR_LABEL
);
1405 label
->flags
|= STOR_WANTS_FREE
;
1406 label
->label
= next_test
;
1408 /* FIXME: signed/unsigned */
1409 insn("jg", label
, NULL
, NULL
);
1411 labelsym
= new_labelsym(sym
);
1412 insn("jmp", labelsym
, NULL
, NULL
);
1414 emit_label(next_test
, NULL
);
1420 labelsym
= new_labelsym(default_sym
);
1421 insn("jmp", labelsym
, NULL
, "default");
1423 label
= new_storage(STOR_LABEL
);
1424 label
->flags
|= STOR_WANTS_FREE
;
1425 label
->label
= switch_end
= new_label();
1426 insn("jmp", label
, NULL
, "goto end of switch");
1429 x86_statement(stmt
->switch_statement
);
1431 if (stmt
->switch_break
->used
)
1432 emit_labelsym(stmt
->switch_break
, NULL
);
1435 emit_label(switch_end
, NULL
);
1438 static void x86_struct_member(struct symbol
*sym
, void *data
, int flags
)
1440 if (flags
& ITERATE_FIRST
)
1442 printf("%s:%d:%ld at offset %ld", show_ident(sym
->ident
), sym
->bit_size
, sym
->ctype
.alignment
, sym
->offset
);
1443 if (sym
->fieldwidth
)
1444 printf("[%d..%d]", sym
->bit_offset
, sym
->bit_offset
+sym
->fieldwidth
-1);
1445 if (flags
& ITERATE_LAST
)
1451 static void x86_symbol(struct symbol
*sym
)
1453 struct symbol
*type
;
1458 type
= sym
->ctype
.base_type
;
1463 * Show actual implementation information
1465 switch (type
->type
) {
1468 if (sym
->initializer
)
1471 emit_array_noinit(sym
);
1475 if (sym
->initializer
) {
1476 emit_object_pre(show_ident(sym
->ident
),
1477 sym
->ctype
.modifiers
,
1478 sym
->ctype
.alignment
,
1480 emit_scalar(sym
->initializer
, sym
->bit_size
);
1483 emit_scalar_noinit(sym
);
1487 symbol_iterate(type
->symbol_list
, x86_struct_member
, NULL
);
1491 symbol_iterate(type
->symbol_list
, x86_struct_member
, NULL
);
1495 struct statement
*stmt
= type
->stmt
;
1498 x86_statement(stmt
);
1499 emit_func_post(sym
);
1508 if (sym
->initializer
&& (type
->type
!= SYM_BASETYPE
) &&
1509 (type
->type
!= SYM_ARRAY
)) {
1511 x86_expression(sym
->initializer
);
1515 static void x86_symbol_init(struct symbol
*sym
);
1517 static void x86_symbol_decl(struct symbol_list
*syms
)
1520 FOR_EACH_PTR(syms
, sym
) {
1521 x86_symbol_init(sym
);
1525 static void x86_loop(struct statement
*stmt
)
1527 struct statement
*pre_statement
= stmt
->iterator_pre_statement
;
1528 struct expression
*pre_condition
= stmt
->iterator_pre_condition
;
1529 struct statement
*statement
= stmt
->iterator_statement
;
1530 struct statement
*post_statement
= stmt
->iterator_post_statement
;
1531 struct expression
*post_condition
= stmt
->iterator_post_condition
;
1532 int loop_top
= 0, loop_bottom
= 0;
1533 struct storage
*val
;
1535 x86_symbol_decl(stmt
->iterator_syms
);
1536 x86_statement(pre_statement
);
1537 if (pre_condition
) {
1538 if (pre_condition
->type
== EXPR_VALUE
) {
1539 if (!pre_condition
->value
) {
1540 loop_bottom
= new_label();
1541 printf("\tjmp\t\t.L%d\n", loop_bottom
);
1544 loop_bottom
= new_label();
1545 val
= x86_expression(pre_condition
);
1546 printf("\tje\t\tv%d, .L%d\n", val
->pseudo
, loop_bottom
);
1549 if (!post_condition
|| post_condition
->type
!= EXPR_VALUE
|| post_condition
->value
) {
1550 loop_top
= new_label();
1551 printf(".L%d:\n", loop_top
);
1553 x86_statement(statement
);
1554 if (stmt
->iterator_continue
->used
)
1555 printf(".L%p:\n", stmt
->iterator_continue
);
1556 x86_statement(post_statement
);
1557 if (!post_condition
) {
1558 printf("\tjmp\t\t.L%d\n", loop_top
);
1559 } else if (post_condition
->type
== EXPR_VALUE
) {
1560 if (post_condition
->value
)
1561 printf("\tjmp\t\t.L%d\n", loop_top
);
1563 val
= x86_expression(post_condition
);
1564 printf("\tjne\t\tv%d, .L%d\n", val
->pseudo
, loop_top
);
1566 if (stmt
->iterator_break
->used
)
1567 printf(".L%p:\n", stmt
->iterator_break
);
1569 printf(".L%d:\n", loop_bottom
);
1573 * Print out a statement
1575 static struct storage
*x86_statement(struct statement
*stmt
)
1579 switch (stmt
->type
) {
1581 return emit_return_stmt(stmt
);
1582 case STMT_COMPOUND
: {
1583 struct statement
*s
;
1584 struct storage
*last
= NULL
;
1586 x86_symbol_decl(stmt
->syms
);
1587 FOR_EACH_PTR(stmt
->stmts
, s
) {
1588 last
= x86_statement(s
);
1594 case STMT_EXPRESSION
:
1595 return x86_expression(stmt
->expression
);
1597 emit_if_conditional(stmt
);
1601 emit_case_statement(stmt
);
1604 emit_switch_statement(stmt
);
1615 printf(".L%p:\n", stmt
->label_identifier
);
1616 x86_statement(stmt
->label_statement
);
1620 if (stmt
->goto_expression
) {
1621 struct storage
*val
= x86_expression(stmt
->goto_expression
);
1622 printf("\tgoto *v%d\n", val
->pseudo
);
1624 struct storage
*labelsym
= new_labelsym(stmt
->goto_label
);
1625 insn("jmp", labelsym
, NULL
, NULL
);
1629 printf("\tasm( .... )\n");
1636 static struct storage
*x86_call_expression(struct expression
*expr
)
1638 struct function
*f
= current_func
;
1639 struct symbol
*direct
;
1640 struct expression
*arg
, *fn
;
1641 struct storage
*retval
, *fncall
;
1646 warn(expr
->pos
, "\tcall with no type!");
1651 FOR_EACH_PTR_REVERSE(expr
->args
, arg
) {
1652 struct storage
*new = x86_expression(arg
);
1653 int size
= arg
->ctype
->bit_size
;
1655 /* FIXME: pay attention to 'size' */
1656 insn("pushl", new, NULL
,
1657 !framesize
? "begin function call" : NULL
);
1659 framesize
+= size
>> 3;
1660 } END_FOR_EACH_PTR_REVERSE
;
1664 /* Remove dereference, if any */
1666 if (fn
->type
== EXPR_PREOP
) {
1667 if (fn
->unop
->type
== EXPR_SYMBOL
) {
1668 struct symbol
*sym
= fn
->unop
->symbol
;
1669 if (sym
->ctype
.base_type
->type
== SYM_FN
)
1674 struct storage
*direct_stor
= new_storage(STOR_SYM
);
1675 direct_stor
->flags
|= STOR_WANTS_FREE
;
1676 direct_stor
->sym
= direct
;
1677 insn("call", direct_stor
, NULL
, NULL
);
1679 fncall
= x86_expression(fn
);
1680 emit_move(fncall
, REG_EAX
, fn
->ctype
, NULL
);
1682 strcpy(s
, "\tcall\t*%eax\n");
1683 push_text_atom(f
, s
);
1686 /* FIXME: pay attention to BITS_IN_POINTER */
1688 struct storage
*val
= new_storage(STOR_VALUE
);
1689 val
->value
= (long long) framesize
;
1690 val
->flags
= STOR_WANTS_FREE
;
1691 insn("addl", val
, REG_ESP
, NULL
);
1694 retval
= stack_alloc(4);
1695 emit_move(REG_EAX
, retval
, NULL
, "end function call");
1700 static struct storage
*x86_address_gen(struct expression
*expr
)
1702 struct function
*f
= current_func
;
1703 struct storage
*addr
;
1704 struct storage
*new;
1707 if ((expr
->type
!= EXPR_PREOP
) || (expr
->op
!= '*'))
1708 return x86_expression(expr
->address
);
1710 addr
= x86_expression(expr
->unop
);
1711 if (expr
->unop
->type
== EXPR_SYMBOL
)
1714 emit_move(addr
, REG_EAX
, NULL
, "begin deref ..");
1716 /* FIXME: operand size */
1717 strcpy(s
, "\tmovl\t(%eax), %ecx\n");
1718 push_text_atom(f
, s
);
1720 new = stack_alloc(4);
1721 emit_move(REG_ECX
, new, NULL
, ".... end deref");
1726 static struct storage
*x86_assignment(struct expression
*expr
)
1728 struct expression
*target
= expr
->left
;
1729 struct storage
*val
, *addr
;
1735 bits
= expr
->ctype
->bit_size
;
1736 val
= x86_expression(expr
->right
);
1737 addr
= x86_address_gen(target
);
1739 switch (val
->type
) {
1740 /* copy, where both operands are memory */
1743 emit_copy(val
, expr
->right
->ctype
, addr
, expr
->left
->ctype
);
1746 /* copy, one or zero operands are memory */
1751 emit_move(val
, addr
, expr
->left
->ctype
, NULL
);
1761 static int x86_initialization(struct symbol
*sym
, struct expression
*expr
)
1763 struct storage
*val
, *addr
;
1769 bits
= expr
->ctype
->bit_size
;
1770 val
= x86_expression(expr
);
1771 addr
= x86_symbol_expr(sym
);
1772 // FIXME! The "target" expression is for bitfield store information.
1773 // Leave it NULL, which works fine.
1774 emit_store(NULL
, addr
, val
, bits
);
1778 static struct storage
*x86_access(struct expression
*expr
)
1780 return x86_address_gen(expr
);
1783 static struct storage
*x86_preop(struct expression
*expr
)
1786 * '*' is an lvalue access, and is fundamentally different
1787 * from an arithmetic operation. Maybe it should have an
1788 * expression type of its own..
1790 if (expr
->op
== '*')
1791 return x86_access(expr
);
1792 if (expr
->op
== SPECIAL_INCREMENT
|| expr
->op
== SPECIAL_DECREMENT
)
1793 return emit_inc_dec(expr
, 0);
1794 return emit_regular_preop(expr
);
1797 static struct storage
*x86_symbol_expr(struct symbol
*sym
)
1799 struct storage
*new = stack_alloc(4);
1801 if (sym
->ctype
.modifiers
& (MOD_TOPLEVEL
| MOD_EXTERN
| MOD_STATIC
)) {
1802 printf("\tmovi.%d\t\tv%d,$%s\n", BITS_IN_POINTER
, new->pseudo
, show_ident(sym
->ident
));
1805 if (sym
->ctype
.modifiers
& MOD_ADDRESSABLE
) {
1806 printf("\taddi.%d\t\tv%d,vFP,$%lld\n", BITS_IN_POINTER
, new->pseudo
, sym
->value
);
1809 printf("\taddi.%d\t\tv%d,vFP,$offsetof(%s:%p)\n", BITS_IN_POINTER
, new->pseudo
, show_ident(sym
->ident
), sym
);
1813 static void x86_symbol_init(struct symbol
*sym
)
1815 struct symbol_private
*priv
= sym
->aux
;
1816 struct expression
*expr
= sym
->initializer
;
1817 struct storage
*new;
1820 new = x86_expression(expr
);
1822 new = stack_alloc(sym
->bit_size
/ 8);
1825 priv
= calloc(1, sizeof(*priv
));
1827 /* FIXME: leak! we don't free... */
1828 /* (well, we don't free symbols either) */
1834 static int type_is_signed(struct symbol
*sym
)
1836 if (sym
->type
== SYM_NODE
)
1837 sym
= sym
->ctype
.base_type
;
1838 if (sym
->type
== SYM_PTR
)
1840 return !(sym
->ctype
.modifiers
& MOD_UNSIGNED
);
1843 static struct storage
*x86_bitfield_expr(struct expression
*expr
)
1845 return x86_access(expr
);
1848 static struct storage
*x86_label_expr(struct expression
*expr
)
1850 struct storage
*new = stack_alloc(4);
1851 printf("\tmovi.%d\t\tv%d,.L%p\n",BITS_IN_POINTER
, new->pseudo
, expr
->label_symbol
);
1855 static struct storage
*x86_statement_expr(struct expression
*expr
)
1857 return x86_statement(expr
->statement
);
1860 static int x86_position_expr(struct expression
*expr
, struct symbol
*base
)
1862 struct storage
*new = x86_expression(expr
->init_expr
);
1863 struct symbol
*ctype
= expr
->init_sym
;
1865 printf("\tinsert v%d at [%d:%d] of %s\n", new->pseudo
,
1866 expr
->init_offset
, ctype
->bit_offset
,
1867 show_ident(base
->ident
));
1871 static void x86_initializer_expr(struct expression
*expr
, struct symbol
*ctype
)
1873 struct expression
*entry
;
1875 FOR_EACH_PTR(expr
->expr_list
, entry
) {
1876 // Nested initializers have their positions already
1877 // recursively calculated - just output them too
1878 if (entry
->type
== EXPR_INITIALIZER
) {
1879 x86_initializer_expr(entry
, ctype
);
1883 // Ignore initializer indexes and identifiers - the
1884 // evaluator has taken them into account
1885 if (entry
->type
== EXPR_IDENTIFIER
|| entry
->type
== EXPR_INDEX
)
1887 if (entry
->type
== EXPR_POS
) {
1888 x86_position_expr(entry
, ctype
);
1891 x86_initialization(ctype
, entry
);
1896 * Print out an expression. Return the pseudo that contains the
1899 static struct storage
*x86_expression(struct expression
*expr
)
1905 struct position
*pos
= &expr
->pos
;
1906 printf("\tno type at %s:%d:%d\n",
1907 input_streams
[pos
->stream
].name
,
1908 pos
->line
, pos
->pos
);
1912 switch (expr
->type
) {
1914 return x86_call_expression(expr
);
1916 case EXPR_ASSIGNMENT
:
1917 return x86_assignment(expr
);
1920 return emit_compare(expr
);
1924 return emit_binop(expr
);
1926 return x86_preop(expr
);
1928 return emit_postop(expr
);
1930 return emit_symbol_expr_init(expr
->symbol
);
1933 warn(expr
->pos
, "invalid expression after evaluation");
1936 return emit_cast_expr(expr
);
1938 return emit_value(expr
);
1940 return emit_string_expr(expr
);
1942 return x86_bitfield_expr(expr
);
1943 case EXPR_INITIALIZER
:
1944 x86_initializer_expr(expr
, expr
->ctype
);
1946 case EXPR_CONDITIONAL
:
1947 return emit_conditional_expr(expr
);
1948 case EXPR_STATEMENT
:
1949 return x86_statement_expr(expr
);
1951 return x86_label_expr(expr
);
1953 // None of these should exist as direct expressions: they are only
1954 // valid as sub-expressions of initializers.
1956 warn(expr
->pos
, "unable to show plain initializer position expression");
1958 case EXPR_IDENTIFIER
:
1959 warn(expr
->pos
, "unable to show identifier expression");
1962 warn(expr
->pos
, "unable to show index expression");