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.
14 * complex initializers
16 * global struct/union variables
17 * addressing structures, and members of structures (as opposed to
18 * scalars) on the stack. Requires smarter stack frame allocation.
20 * any function argument that isn't 32 bits (or promoted to such)
39 #include "expression.h"
45 unsigned int len
; /* does NOT include terminating null */
54 struct loop_stack
*next
;
60 struct ptr_list
*pseudo_list
;
61 struct ptr_list
*atom_list
;
62 struct ptr_list
*str_list
;
63 struct loop_stack
*loop_stack
;
70 STOR_PSEUDO
, /* variable stored on the stack */
71 STOR_ARG
, /* function argument */
72 STOR_SYM
, /* a symbol we can directly ref in the asm */
73 STOR_REG
, /* scratch register */
74 STOR_VALUE
, /* integer constant */
75 STOR_LABEL
, /* label / jump target */
76 STOR_LABELSYM
, /* label generated from symbol's pointer value */
81 struct storage
*contains
;
82 const unsigned char aliases
[12];
83 #define own_regno aliases[0]
87 enum storage_type type
;
119 struct symbol
*labelsym
;
125 STOR_LABEL_VAL
= (1 << 0),
126 STOR_WANTS_FREE
= (1 << 1),
129 struct symbol_private
{
130 struct storage
*addr
;
145 unsigned int text_len
; /* w/o terminating null */
148 /* stuff for insns */
156 /* stuff for C strings */
158 struct string
*string
;
165 struct function
*current_func
= NULL
;
166 struct textbuf
*unit_post_text
= NULL
;
167 static const char *current_section
;
169 static void emit_comment(const char * fmt
, ...);
170 static void emit_move(struct storage
*src
, struct storage
*dest
,
171 struct symbol
*ctype
, const char *comment
);
172 static int type_is_signed(struct symbol
*sym
);
173 static struct storage
*x86_address_gen(struct expression
*expr
);
174 static struct storage
*x86_symbol_expr(struct symbol
*sym
);
175 static void x86_symbol(struct symbol
*sym
);
176 static struct storage
*x86_statement(struct statement
*stmt
);
177 static struct storage
*x86_expression(struct expression
*expr
);
181 AL
, DL
, CL
, BL
, AH
, DH
, CH
, BH
, // 8-bit
182 AX
, DX
, CX
, BX
, SI
, DI
, BP
, SP
, // 16-bit
183 EAX
, EDX
, ECX
, EBX
, ESI
, EDI
, EBP
, ESP
, // 32-bit
184 EAX_EDX
, ECX_EBX
, ESI_EDI
, // 64-bit
187 /* This works on regno's, reg_info's and hardreg_storage's */
188 #define byte_reg(reg) ((reg) - 16)
189 #define highbyte_reg(reg) ((reg)-12)
190 #define word_reg(reg) ((reg)-8)
192 #define REGINFO(nr, str, conflicts...) [nr] = { .name = str, .aliases = { nr , conflicts } }
194 static struct reg_info reg_info_table
[] = {
195 REGINFO( AL
, "%al", AX
, EAX
, EAX_EDX
),
196 REGINFO( DL
, "%dl", DX
, EDX
, EAX_EDX
),
197 REGINFO( CL
, "%cl", CX
, ECX
, ECX_EBX
),
198 REGINFO( BL
, "%bl", BX
, EBX
, ECX_EBX
),
199 REGINFO( AH
, "%ah", AX
, EAX
, EAX_EDX
),
200 REGINFO( DH
, "%dh", DX
, EDX
, EAX_EDX
),
201 REGINFO( CH
, "%ch", CX
, ECX
, ECX_EBX
),
202 REGINFO( BH
, "%bh", BX
, EBX
, ECX_EBX
),
203 REGINFO( AX
, "%ax", AL
, AH
, EAX
, EAX_EDX
),
204 REGINFO( DX
, "%dx", DL
, DH
, EDX
, EAX_EDX
),
205 REGINFO( CX
, "%cx", CL
, CH
, ECX
, ECX_EBX
),
206 REGINFO( BX
, "%bx", BL
, BH
, EBX
, ECX_EBX
),
207 REGINFO( SI
, "%si", ESI
, ESI_EDI
),
208 REGINFO( DI
, "%di", EDI
, ESI_EDI
),
209 REGINFO( BP
, "%bp", EBP
),
210 REGINFO( SP
, "%sp", ESP
),
211 REGINFO(EAX
, "%eax", AL
, AH
, AX
, EAX_EDX
),
212 REGINFO(EDX
, "%edx", DL
, DH
, DX
, EAX_EDX
),
213 REGINFO(ECX
, "%ecx", CL
, CH
, CX
, ECX_EBX
),
214 REGINFO(EBX
, "%ebx", BL
, BH
, BX
, ECX_EBX
),
215 REGINFO(ESI
, "%esi", SI
, ESI_EDI
),
216 REGINFO(EDI
, "%edi", DI
, ESI_EDI
),
217 REGINFO(EBP
, "%ebp", BP
),
218 REGINFO(ESP
, "%esp", SP
),
219 REGINFO(EAX_EDX
, "%eax:%edx", AL
, AH
, AX
, EAX
, DL
, DH
, DX
, EDX
),
220 REGINFO(ECX_EBX
, "%ecx:%ebx", CL
, CH
, CX
, ECX
, BL
, BH
, BX
, EBX
),
221 REGINFO(ESI_EDI
, "%esi:%edi", SI
, ESI
, DI
, EDI
),
224 #define REGSTORAGE(nr) [nr] = { .type = STOR_REG, .reg = reg_info_table + (nr) }
226 static struct storage hardreg_storage_table
[] = {
227 REGSTORAGE(AL
), REGSTORAGE(DL
), REGSTORAGE(CL
), REGSTORAGE(BL
),
228 REGSTORAGE(AH
), REGSTORAGE(DH
), REGSTORAGE(CH
), REGSTORAGE(BH
),
229 REGSTORAGE(AX
), REGSTORAGE(DX
), REGSTORAGE(CX
), REGSTORAGE(BX
),
230 REGSTORAGE(SI
), REGSTORAGE(DI
), REGSTORAGE(BP
), REGSTORAGE(SP
),
231 REGSTORAGE(EAX
), REGSTORAGE(EDX
), REGSTORAGE(ECX
), REGSTORAGE(EBX
),
232 REGSTORAGE(ESI
), REGSTORAGE(EDI
), REGSTORAGE(EBP
), REGSTORAGE(ESP
),
233 REGSTORAGE(EAX_EDX
), REGSTORAGE(ECX_EBX
), REGSTORAGE(ESI_EDI
),
236 #define REG_EAX (&hardreg_storage_table[EAX])
237 #define REG_ECX (&hardreg_storage_table[ECX])
238 #define REG_EDX (&hardreg_storage_table[EDX])
239 #define REG_ESP (&hardreg_storage_table[ESP])
240 #define REG_DL (&hardreg_storage_table[DL])
241 #define REG_DX (&hardreg_storage_table[DX])
242 #define REG_AL (&hardreg_storage_table[AL])
243 #define REG_AX (&hardreg_storage_table[AX])
245 DECLARE_BITMAP(regs_in_use
, 256);
247 static inline struct storage
* reginfo_reg(struct reg_info
*info
)
249 return hardreg_storage_table
+ info
->own_regno
;
252 struct storage
* get_hardreg(struct storage
*reg
, int clear
)
254 struct reg_info
*info
= reg
->reg
;
255 const unsigned char *aliases
;
258 aliases
= info
->aliases
;
259 while ((regno
= *aliases
++) != NOREG
) {
260 if (test_bit(regno
, regs_in_use
))
263 reg_info_table
[regno
].contains
= NULL
;
265 set_bit(info
->own_regno
, regs_in_use
);
268 fprintf(stderr
, "register %s is busy\n", info
->name
);
269 if (regno
+ reg_info_table
!= info
)
270 fprintf(stderr
, " conflicts with %s\n", reg_info_table
[regno
].name
);
274 void put_reg(struct storage
*reg
)
276 struct reg_info
*info
= reg
->reg
;
277 int regno
= info
->own_regno
;
279 if (test_and_clear_bit(regno
, regs_in_use
))
281 fprintf(stderr
, "freeing already free'd register %s\n", reg_info_table
[regno
].name
);
286 const unsigned char regs
[30];
289 static struct regclass regclass_8
= { "8-bit", { AL
, DL
, CL
, BL
, AH
, DH
, CH
, BH
}};
290 static struct regclass regclass_16
= { "16-bit", { AX
, DX
, CX
, BX
, SI
, DI
, BP
}};
291 static struct regclass regclass_32
= { "32-bit", { EAX
, EDX
, ECX
, EBX
, ESI
, EDI
, EBP
}};
292 static struct regclass regclass_64
= { "64-bit", { EAX_EDX
, ECX_EBX
, ESI_EDI
}};
294 struct regclass regclass_32_8
= { "32-bit bytes", { EAX
, EDX
, ECX
, EBX
}};
296 static struct regclass
*get_regclass_bits(int bits
)
299 case 8: return ®class_8
;
300 case 16: return ®class_16
;
301 case 64: return ®class_64
;
302 default: return ®class_32
;
306 static struct regclass
*get_regclass(struct expression
*expr
)
308 return get_regclass_bits(expr
->ctype
->bit_size
);
311 static int register_busy(int regno
)
313 if (!test_bit(regno
, regs_in_use
)) {
314 struct reg_info
*info
= reg_info_table
+ regno
;
315 const unsigned char *regs
= info
->aliases
+1;
317 while ((regno
= *regs
) != NOREG
) {
319 if (test_bit(regno
, regs_in_use
))
328 struct storage
*get_reg(struct regclass
*class)
330 const unsigned char *regs
= class->regs
;
333 while ((regno
= *regs
) != NOREG
) {
335 if (register_busy(regno
))
337 return get_hardreg(hardreg_storage_table
+ regno
, 1);
339 fprintf(stderr
, "Ran out of %s registers\n", class->name
);
343 struct storage
*get_reg_value(struct storage
*value
, struct regclass
*class)
345 struct reg_info
*info
;
348 /* Do we already have it somewhere */
350 if (info
&& info
->contains
== value
) {
351 emit_comment("already have register %s", info
->name
);
352 return get_hardreg(hardreg_storage_table
+ info
->own_regno
, 0);
355 reg
= get_reg(class);
356 emit_move(value
, reg
, value
->ctype
, "reload register");
358 info
->contains
= value
;
363 static struct storage
*temp_from_bits(unsigned int bit_size
)
365 return get_reg(get_regclass_bits(bit_size
));
368 static inline unsigned int pseudo_offset(struct storage
*s
)
370 if (s
->type
!= STOR_PSEUDO
)
371 return 123456; /* intentionally bogus value */
376 static inline unsigned int arg_offset(struct storage
*s
)
378 if (s
->type
!= STOR_ARG
)
379 return 123456; /* intentionally bogus value */
381 /* FIXME: this is wrong wrong wrong */
382 return current_func
->stack_size
+ ((1 + s
->idx
) * 4);
385 static const char *pretty_offset(int ofs
)
387 static char esp_buf
[64];
390 sprintf(esp_buf
, "%d(%%esp)", ofs
);
392 strcpy(esp_buf
, "(%esp)");
397 static void stor_sym_init(struct symbol
*sym
)
399 struct storage
*stor
;
400 struct symbol_private
*priv
;
402 priv
= calloc(1, sizeof(*priv
) + sizeof(*stor
));
404 die("OOM in stor_sym_init");
406 stor
= (struct storage
*) (priv
+ 1);
409 stor
->type
= STOR_SYM
;
413 static const char *stor_op_name(struct storage
*s
)
415 static char name
[32];
419 strcpy(name
, pretty_offset((int) pseudo_offset(s
)));
422 strcpy(name
, pretty_offset((int) arg_offset(s
)));
425 strcpy(name
, show_ident(s
->sym
->ident
));
428 strcpy(name
, s
->reg
->name
);
431 sprintf(name
, "$%Ld", s
->value
);
434 sprintf(name
, "%s.L%d", s
->flags
& STOR_LABEL_VAL
? "$" : "",
438 sprintf(name
, "%s.LS%p", s
->flags
& STOR_LABEL_VAL
? "$" : "",
446 static struct atom
*new_atom(enum atom_type type
)
450 atom
= calloc(1, sizeof(*atom
)); /* TODO: chunked alloc */
459 static inline void push_cstring(struct function
*f
, struct string
*str
,
464 atom
= new_atom(ATOM_CSTR
);
468 add_ptr_list(&f
->str_list
, atom
); /* note: _not_ atom_list */
471 static inline void push_atom(struct function
*f
, struct atom
*atom
)
473 add_ptr_list(&f
->atom_list
, atom
);
476 static void push_text_atom(struct function
*f
, const char *text
)
478 struct atom
*atom
= new_atom(ATOM_TEXT
);
480 atom
->text
= strdup(text
);
481 atom
->text_len
= strlen(text
);
486 static struct storage
*new_storage(enum storage_type type
)
488 struct storage
*stor
;
490 stor
= calloc(1, sizeof(*stor
));
492 die("OOM in new_storage");
499 static struct storage
*stack_alloc(int n_bytes
)
501 struct function
*f
= current_func
;
502 struct storage
*stor
;
506 stor
= new_storage(STOR_PSEUDO
);
507 stor
->type
= STOR_PSEUDO
;
508 stor
->pseudo
= f
->pseudo_nr
;
509 stor
->offset
= f
->stack_size
; /* FIXME: stack req. natural align */
510 stor
->size
= n_bytes
;
511 f
->stack_size
+= n_bytes
;
514 add_ptr_list(&f
->pseudo_list
, stor
);
519 static struct storage
*new_labelsym(struct symbol
*sym
)
521 struct storage
*stor
;
523 stor
= new_storage(STOR_LABELSYM
);
526 stor
->flags
|= STOR_WANTS_FREE
;
527 stor
->labelsym
= sym
;
533 static struct storage
*new_val(long long value
)
535 struct storage
*stor
;
537 stor
= new_storage(STOR_VALUE
);
540 stor
->flags
|= STOR_WANTS_FREE
;
547 static int new_label(void)
549 static int label
= 0;
553 static void textbuf_push(struct textbuf
**buf_p
, const char *text
)
555 struct textbuf
*tmp
, *list
= *buf_p
;
556 unsigned int text_len
= strlen(text
);
557 unsigned int alloc_len
= text_len
+ 1 + sizeof(*list
);
559 tmp
= calloc(1, alloc_len
);
561 die("OOM on textbuf alloc");
563 tmp
->text
= ((void *) tmp
) + sizeof(*tmp
);
564 memcpy(tmp
->text
, text
, text_len
+ 1);
567 /* add to end of list */
572 tmp
->prev
= list
->prev
;
573 tmp
->prev
->next
= tmp
;
581 static void textbuf_emit(struct textbuf
**buf_p
)
583 struct textbuf
*tmp
, *list
= *buf_p
;
587 if (tmp
->next
== tmp
)
590 tmp
->prev
->next
= tmp
->next
;
591 tmp
->next
->prev
= tmp
->prev
;
595 fputs(tmp
->text
, stdout
);
603 static void insn(const char *insn
, struct storage
*op1
, struct storage
*op2
,
604 const char *comment_in
)
606 struct function
*f
= current_func
;
607 struct atom
*atom
= new_atom(ATOM_INSN
);
609 assert(insn
!= NULL
);
611 strcpy(atom
->insn
, insn
);
612 if (comment_in
&& (*comment_in
))
613 strncpy(atom
->comment
, comment_in
,
614 sizeof(atom
->comment
) - 1);
622 static void emit_comment(const char *fmt
, ...)
624 struct function
*f
= current_func
;
625 static char tmpbuf
[100] = "\t# ";
630 i
= vsnprintf(tmpbuf
+3, sizeof(tmpbuf
)-4, fmt
, args
);
634 push_text_atom(f
, tmpbuf
);
637 static void emit_label (int label
, const char *comment
)
639 struct function
*f
= current_func
;
643 sprintf(s
, ".L%d:\n", label
);
645 sprintf(s
, ".L%d:\t\t\t\t\t# %s\n", label
, comment
);
647 push_text_atom(f
, s
);
650 static void emit_labelsym (struct symbol
*sym
, const char *comment
)
652 struct function
*f
= current_func
;
656 sprintf(s
, ".LS%p:\n", sym
);
658 sprintf(s
, ".LS%p:\t\t\t\t# %s\n", sym
, comment
);
660 push_text_atom(f
, s
);
663 void emit_unit_begin(const char *basename
)
665 printf("\t.file\t\"%s\"\n", basename
);
668 void emit_unit_end(void)
670 textbuf_emit(&unit_post_text
);
671 printf("\t.ident\t\"sparse silly x86 backend (built %s)\"\n", __DATE__
);
674 /* conditionally switch sections */
675 static void emit_section(const char *s
)
677 if (s
== current_section
)
679 if (current_section
&& (!strcmp(s
, current_section
)))
686 static void emit_insn_atom(struct function
*f
, struct atom
*atom
)
690 struct storage
*op1
= atom
->op1
;
691 struct storage
*op2
= atom
->op2
;
693 if (atom
->comment
[0])
694 sprintf(comment
, "\t\t# %s", atom
->comment
);
700 strcpy(tmp
, stor_op_name(op1
));
701 sprintf(s
, "\t%s\t%s, %s%s\n",
702 atom
->insn
, tmp
, stor_op_name(op2
), comment
);
703 } else if (atom
->op1
)
704 sprintf(s
, "\t%s\t%s%s%s\n",
705 atom
->insn
, stor_op_name(op1
),
706 comment
[0] ? "\t" : "", comment
);
708 sprintf(s
, "\t%s\t%s%s\n",
710 comment
[0] ? "\t\t" : "", comment
);
712 write(STDOUT_FILENO
, s
, strlen(s
));
715 static void emit_atom_list(struct function
*f
)
719 FOR_EACH_PTR(f
->atom_list
, atom
) {
720 switch (atom
->type
) {
722 ssize_t rc
= write(STDOUT_FILENO
, atom
->text
,
724 (void) rc
; /* FIXME */
728 emit_insn_atom(f
, atom
);
734 } END_FOR_EACH_PTR(atom
);
737 static void emit_string_list(struct function
*f
)
741 emit_section(".section\t.rodata");
743 FOR_EACH_PTR(f
->str_list
, atom
) {
744 /* FIXME: escape " in string */
745 printf(".L%d:\n", atom
->label
);
746 printf("\t.string\t%s\n", show_string(atom
->string
));
749 } END_FOR_EACH_PTR(atom
);
752 static void func_cleanup(struct function
*f
)
754 struct storage
*stor
;
757 FOR_EACH_PTR(f
->pseudo_list
, stor
) {
759 } END_FOR_EACH_PTR(stor
);
761 FOR_EACH_PTR(f
->atom_list
, atom
) {
762 if ((atom
->type
== ATOM_TEXT
) && (atom
->text
))
764 if (atom
->op1
&& (atom
->op1
->flags
& STOR_WANTS_FREE
))
766 if (atom
->op2
&& (atom
->op2
->flags
& STOR_WANTS_FREE
))
769 } END_FOR_EACH_PTR(atom
);
771 free_ptr_list(&f
->pseudo_list
);
775 /* function prologue */
776 static void emit_func_pre(struct symbol
*sym
)
780 unsigned int i
, argc
= 0, alloc_len
;
782 struct symbol_private
*privbase
;
783 struct storage
*storage_base
;
784 struct symbol
*base_type
= sym
->ctype
.base_type
;
786 FOR_EACH_PTR(base_type
->arguments
, arg
) {
788 } END_FOR_EACH_PTR(arg
);
792 (argc
* sizeof(struct symbol
*)) +
793 (argc
* sizeof(struct symbol_private
)) +
794 (argc
* sizeof(struct storage
));
795 mem
= calloc(1, alloc_len
);
797 die("OOM on func info");
799 f
= (struct function
*) mem
;
801 f
->argv
= (struct symbol
**) mem
;
802 mem
+= (argc
* sizeof(struct symbol
*));
803 privbase
= (struct symbol_private
*) mem
;
804 mem
+= (argc
* sizeof(struct symbol_private
));
805 storage_base
= (struct storage
*) mem
;
808 f
->ret_target
= new_label();
811 FOR_EACH_PTR(base_type
->arguments
, arg
) {
813 arg
->aux
= &privbase
[i
];
814 storage_base
[i
].type
= STOR_ARG
;
815 storage_base
[i
].idx
= i
;
816 privbase
[i
].addr
= &storage_base
[i
];
818 } END_FOR_EACH_PTR(arg
);
820 assert(current_func
== NULL
);
824 /* function epilogue */
825 static void emit_func_post(struct symbol
*sym
)
827 const char *name
= show_ident(sym
->ident
);
828 struct function
*f
= current_func
;
829 int stack_size
= f
->stack_size
;
834 /* function prologue */
835 emit_section(".text");
836 if ((sym
->ctype
.modifiers
& MOD_STATIC
) == 0)
837 printf(".globl %s\n", name
);
838 printf("\t.type\t%s, @function\n", name
);
839 printf("%s:\n", name
);
842 char pseudo_const
[16];
844 sprintf(pseudo_const
, "$%d", stack_size
);
845 printf("\tsubl\t%s, %%esp\n", pseudo_const
);
848 /* function epilogue */
850 /* jump target for 'return' statements */
851 emit_label(f
->ret_target
, NULL
);
856 val
= new_storage(STOR_VALUE
);
857 val
->value
= (long long) (stack_size
);
858 val
->flags
= STOR_WANTS_FREE
;
860 insn("addl", val
, REG_ESP
, NULL
);
863 insn("ret", NULL
, NULL
, NULL
);
865 /* output everything to stdout */
866 fflush(stdout
); /* paranoia; needed? */
869 /* function footer */
870 name
= show_ident(sym
->ident
);
871 printf("\t.size\t%s, .-%s\n", name
, name
);
877 /* emit object (a.k.a. variable, a.k.a. data) prologue */
878 static void emit_object_pre(const char *name
, unsigned long modifiers
,
879 unsigned long alignment
, unsigned int byte_size
)
881 if ((modifiers
& MOD_STATIC
) == 0)
882 printf(".globl %s\n", name
);
883 emit_section(".data");
885 printf("\t.align %lu\n", alignment
);
886 printf("\t.type\t%s, @object\n", name
);
887 printf("\t.size\t%s, %d\n", name
, byte_size
);
888 printf("%s:\n", name
);
891 /* emit value (only) for an initializer scalar */
892 static void emit_scalar(struct expression
*expr
, unsigned int bit_size
)
897 assert(expr
->type
== EXPR_VALUE
);
899 if (expr
->value
== 0ULL) {
900 printf("\t.zero\t%d\n", bit_size
/ 8);
904 ll
= (long long) expr
->value
;
907 case 8: type
= "byte"; ll
= (char) ll
; break;
908 case 16: type
= "value"; ll
= (short) ll
; break;
909 case 32: type
= "long"; ll
= (int) ll
; break;
910 case 64: type
= "quad"; break;
911 default: type
= NULL
; break;
914 assert(type
!= NULL
);
916 printf("\t.%s\t%Ld\n", type
, ll
);
919 static void emit_global_noinit(const char *name
, unsigned long modifiers
,
920 unsigned long alignment
, unsigned int byte_size
)
924 if (modifiers
& MOD_STATIC
) {
925 sprintf(s
, "\t.local\t%s\n", name
);
926 textbuf_push(&unit_post_text
, s
);
929 sprintf(s
, "\t.comm\t%s,%d,%lu\n", name
, byte_size
, alignment
);
931 sprintf(s
, "\t.comm\t%s,%d\n", name
, byte_size
);
932 textbuf_push(&unit_post_text
, s
);
935 static int ea_current
, ea_last
;
937 static void emit_initializer(struct symbol
*sym
,
938 struct expression
*expr
)
940 int distance
= ea_current
- ea_last
- 1;
943 printf("\t.zero\t%d\n", (sym
->bit_size
/ 8) * distance
);
945 if (expr
->type
== EXPR_VALUE
) {
946 struct symbol
*base_type
= sym
->ctype
.base_type
;
947 assert(base_type
!= NULL
);
949 emit_scalar(expr
, sym
->bit_size
/ get_expression_value(base_type
->array_size
));
952 if (expr
->type
!= EXPR_INITIALIZER
)
955 assert(0); /* FIXME */
958 static int sort_array_cmp(const struct expression
*a
,
959 const struct expression
*b
)
961 int a_ofs
= 0, b_ofs
= 0;
963 if (a
->type
== EXPR_POS
)
964 a_ofs
= (int) a
->init_offset
;
965 if (b
->type
== EXPR_POS
)
966 b_ofs
= (int) b
->init_offset
;
968 return a_ofs
- b_ofs
;
971 /* move to front-end? */
972 static void sort_array(struct expression
*expr
)
974 struct expression
*entry
, **list
;
975 unsigned int elem
, sorted
, i
;
978 FOR_EACH_PTR(expr
->expr_list
, entry
) {
980 } END_FOR_EACH_PTR(entry
);
985 list
= malloc(sizeof(entry
) * elem
);
987 die("OOM in sort_array");
989 /* this code is no doubt evil and ignores EXPR_INDEX possibly
990 * to its detriment and other nasty things. improvements
995 FOR_EACH_PTR(expr
->expr_list
, entry
) {
996 if ((entry
->type
== EXPR_POS
) || (entry
->type
== EXPR_VALUE
)) {
997 /* add entry to list[], in sorted order */
1004 for (i
= 0; i
< sorted
; i
++)
1005 if (sort_array_cmp(entry
, list
[i
]) <= 0)
1008 /* If inserting into the middle of list[]
1009 * instead of appending, we memmove.
1010 * This is ugly, but thankfully
1011 * uncommon. Input data with tons of
1012 * entries very rarely have explicit
1013 * offsets. convert to qsort eventually...
1016 memmove(&list
[i
+ 1], &list
[i
],
1017 (sorted
- i
) * sizeof(entry
));
1022 } END_FOR_EACH_PTR(entry
);
1025 FOR_EACH_PTR(expr
->expr_list
, entry
) {
1026 if ((entry
->type
== EXPR_POS
) || (entry
->type
== EXPR_VALUE
))
1027 *THIS_ADDRESS(entry
) = list
[i
++];
1028 } END_FOR_EACH_PTR(entry
);
1032 static void emit_array(struct symbol
*sym
)
1034 struct symbol
*base_type
= sym
->ctype
.base_type
;
1035 struct expression
*expr
= sym
->initializer
;
1036 struct expression
*entry
;
1038 assert(base_type
!= NULL
);
1044 emit_object_pre(show_ident(sym
->ident
), sym
->ctype
.modifiers
,
1045 sym
->ctype
.alignment
,
1050 FOR_EACH_PTR(expr
->expr_list
, entry
) {
1051 if (entry
->type
== EXPR_VALUE
) {
1053 emit_initializer(sym
, entry
);
1054 ea_last
= ea_current
;
1055 } else if (entry
->type
== EXPR_POS
) {
1057 entry
->init_offset
/ (base_type
->bit_size
/ 8);
1058 emit_initializer(sym
, entry
->init_expr
);
1059 ea_last
= ea_current
;
1061 } END_FOR_EACH_PTR(entry
);
1064 void emit_one_symbol(struct symbol
*sym
)
1069 static void emit_copy(struct storage
*dest
, struct storage
*src
,
1070 struct symbol
*ctype
)
1072 struct storage
*reg
= NULL
;
1073 unsigned int bit_size
;
1075 /* FIXME: Bitfield copy! */
1077 bit_size
= src
->size
* 8;
1080 if ((src
->type
== STOR_ARG
) && (bit_size
< 32))
1083 reg
= temp_from_bits(bit_size
);
1084 emit_move(src
, reg
, ctype
, "begin copy ..");
1086 bit_size
= dest
->size
* 8;
1089 if ((dest
->type
== STOR_ARG
) && (bit_size
< 32))
1092 emit_move(reg
, dest
, ctype
, ".... end copy");
1096 static void emit_store(struct expression
*dest_expr
, struct storage
*dest
,
1097 struct storage
*src
, int bits
)
1099 /* FIXME: Bitfield store! */
1100 printf("\tst.%d\t\tv%d,[v%d]\n", bits
, src
->pseudo
, dest
->pseudo
);
1103 static void emit_scalar_noinit(struct symbol
*sym
)
1105 emit_global_noinit(show_ident(sym
->ident
),
1106 sym
->ctype
.modifiers
, sym
->ctype
.alignment
,
1111 static void emit_array_noinit(struct symbol
*sym
)
1113 emit_global_noinit(show_ident(sym
->ident
),
1114 sym
->ctype
.modifiers
, sym
->ctype
.alignment
,
1115 get_expression_value(sym
->array_size
) * (sym
->bit_size
/ 8));
1119 static const char *opbits(const char *insn
, unsigned int bits
)
1121 static char opbits_str
[32];
1125 case 8: c
= 'b'; break;
1126 case 16: c
= 'w'; break;
1127 case 32: c
= 'l'; break;
1128 case 64: c
= 'q'; break;
1129 default: abort(); break;
1132 sprintf(opbits_str
, "%s%c", insn
, c
);
1137 static void emit_move(struct storage
*src
, struct storage
*dest
,
1138 struct symbol
*ctype
, const char *comment
)
1141 unsigned int is_signed
;
1142 unsigned int is_dest
= (src
->type
== STOR_REG
);
1146 bits
= ctype
->bit_size
;
1147 is_signed
= type_is_signed(ctype
);
1154 * Are we moving from a register to a register?
1155 * Make the new reg to be the "cache".
1157 if ((dest
->type
== STOR_REG
) && (src
->type
== STOR_REG
)) {
1158 struct storage
*backing
;
1164 backing
= src
->reg
->contains
;
1166 /* Is it still valid? */
1167 if (backing
->reg
!= src
->reg
)
1170 backing
->reg
= dest
->reg
;
1172 dest
->reg
->contains
= backing
;
1173 insn("mov", src
, dest
, NULL
);
1178 * Are we moving to a register from a non-reg?
1180 * See if we have the non-reg source already cached
1183 if (dest
->type
== STOR_REG
) {
1185 struct reg_info
*info
= src
->reg
;
1186 if (info
->contains
== src
) {
1187 src
= reginfo_reg(info
);
1191 dest
->reg
->contains
= src
;
1192 src
->reg
= dest
->reg
;
1195 if (src
->type
== STOR_REG
) {
1196 /* We could just mark the register dirty here and do lazy store.. */
1197 src
->reg
->contains
= dest
;
1198 dest
->reg
= src
->reg
;
1201 if ((bits
== 8) || (bits
== 16)) {
1205 opname
= is_signed
? "movsx" : "movzx";
1209 insn(opbits(opname
, bits
), src
, dest
, comment
);
1212 static struct storage
*emit_compare(struct expression
*expr
)
1214 struct storage
*left
= x86_expression(expr
->left
);
1215 struct storage
*right
= x86_expression(expr
->right
);
1216 struct storage
*reg1
, *reg2
;
1217 struct storage
*new, *val
;
1218 const char *opname
= NULL
;
1219 unsigned int right_bits
= expr
->right
->ctype
->bit_size
;
1222 case '<': opname
= "setl"; break;
1223 case '>': opname
= "setg"; break;
1225 opname
= "setle"; break;
1227 opname
= "setge"; break;
1228 case SPECIAL_EQUAL
: opname
= "sete"; break;
1229 case SPECIAL_NOTEQUAL
: opname
= "setne"; break;
1230 case SPECIAL_UNSIGNED_LT
:
1231 opname
= "setb"; break;
1232 case SPECIAL_UNSIGNED_GT
:
1233 opname
= "seta"; break;
1234 case SPECIAL_UNSIGNED_LTE
:
1235 opname
= "setb"; break;
1236 case SPECIAL_UNSIGNED_GTE
:
1237 opname
= "setae"; break;
1244 val
= new_storage(STOR_VALUE
);
1245 val
->flags
= STOR_WANTS_FREE
;
1247 reg1
= get_reg(®class_32_8
);
1248 emit_move(val
, reg1
, NULL
, NULL
);
1250 /* move op1 into EAX */
1251 reg2
= get_reg_value(left
, get_regclass(expr
->left
));
1253 /* perform comparison, RHS (op1, right) and LHS (op2, EAX) */
1254 insn(opbits("cmp", right_bits
), right
, reg2
, NULL
);
1257 /* store result of operation, 0 or 1, in DL using SETcc */
1258 insn(opname
, byte_reg(reg1
), NULL
, NULL
);
1260 /* finally, store the result (DL) in a new pseudo / stack slot */
1261 new = stack_alloc(4);
1262 emit_move(reg1
, new, NULL
, "end EXPR_COMPARE");
1268 static struct storage
*emit_value(struct expression
*expr
)
1270 #if 0 /* old and slow way */
1271 struct storage
*new = stack_alloc(4);
1272 struct storage
*val
;
1274 val
= new_storage(STOR_VALUE
);
1275 val
->value
= (long long) expr
->value
;
1276 val
->flags
= STOR_WANTS_FREE
;
1277 insn("movl", val
, new, NULL
);
1281 struct storage
*val
;
1283 val
= new_storage(STOR_VALUE
);
1284 val
->value
= (long long) expr
->value
;
1286 return val
; /* FIXME: memory leak */
1290 static struct storage
*emit_divide(struct expression
*expr
, struct storage
*left
, struct storage
*right
)
1292 struct storage
*eax_edx
;
1293 struct storage
*reg
, *new;
1294 struct storage
*val
= new_storage(STOR_VALUE
);
1296 emit_comment("begin DIVIDE");
1297 eax_edx
= get_hardreg(hardreg_storage_table
+ EAX_EDX
, 1);
1300 val
= new_storage(STOR_VALUE
);
1301 val
->flags
= STOR_WANTS_FREE
;
1302 emit_move(val
, REG_EDX
, NULL
, NULL
);
1304 new = stack_alloc(expr
->ctype
->bit_size
/ 8);
1306 /* EAX is dividend */
1307 emit_move(left
, REG_EAX
, NULL
, NULL
);
1309 reg
= get_reg_value(right
, ®class_32
);
1312 insn("div", reg
, REG_EAX
, NULL
);
1316 if (expr
->op
== '%')
1318 emit_move(reg
, new, NULL
, NULL
);
1321 emit_comment("end DIVIDE");
1325 static struct storage
*emit_binop(struct expression
*expr
)
1327 struct storage
*left
= x86_expression(expr
->left
);
1328 struct storage
*right
= x86_expression(expr
->right
);
1329 struct storage
*new;
1330 struct storage
*dest
, *src
;
1331 const char *opname
= NULL
;
1332 const char *suffix
= NULL
;
1336 /* Divides have special register constraints */
1337 if ((expr
->op
== '/') || (expr
->op
== '%'))
1338 return emit_divide(expr
, left
, right
);
1340 is_signed
= type_is_signed(expr
->ctype
);
1358 case SPECIAL_LEFTSHIFT
:
1361 case SPECIAL_RIGHTSHIFT
:
1373 case SPECIAL_LOGICAL_AND
:
1374 warning(expr
->pos
, "bogus bitwise and for logical op (should use '2*setne + and' or something)");
1377 case SPECIAL_LOGICAL_OR
:
1378 warning(expr
->pos
, "bogus bitwise or for logical op (should use 'or + setne' or something)");
1382 error_die(expr
->pos
, "unhandled binop '%s'\n", show_special(expr
->op
));
1386 dest
= get_reg_value(right
, ®class_32
);
1387 src
= get_reg_value(left
, ®class_32
);
1388 switch (expr
->ctype
->bit_size
) {
1399 suffix
= "q"; /* FIXME */
1406 snprintf(opstr
, sizeof(opstr
), "%s%s", opname
, suffix
);
1409 insn(opstr
, src
, dest
, NULL
);
1412 /* store result in new pseudo / stack slot */
1413 new = stack_alloc(expr
->ctype
->bit_size
/ 8);
1414 emit_move(dest
, new, NULL
, "end EXPR_BINOP");
1421 static int emit_conditional_test(struct storage
*val
)
1423 struct storage
*reg
;
1424 struct storage
*target_val
;
1427 /* load result into EAX */
1428 emit_comment("begin if/conditional");
1429 reg
= get_reg_value(val
, ®class_32
);
1431 /* compare result with zero */
1432 insn("test", reg
, reg
, NULL
);
1435 /* create conditional-failed label to jump to */
1436 target_false
= new_label();
1437 target_val
= new_storage(STOR_LABEL
);
1438 target_val
->label
= target_false
;
1439 target_val
->flags
= STOR_WANTS_FREE
;
1440 insn("jz", target_val
, NULL
, NULL
);
1442 return target_false
;
1445 static int emit_conditional_end(int target_false
)
1447 struct storage
*cond_end_st
;
1450 /* finished generating code for if-true statement.
1451 * add a jump-to-end jump to avoid falling through
1452 * to the if-false statement code.
1454 cond_end
= new_label();
1455 cond_end_st
= new_storage(STOR_LABEL
);
1456 cond_end_st
->label
= cond_end
;
1457 cond_end_st
->flags
= STOR_WANTS_FREE
;
1458 insn("jmp", cond_end_st
, NULL
, NULL
);
1460 /* if we have both if-true and if-false statements,
1461 * the failed-conditional case will fall through to here
1463 emit_label(target_false
, NULL
);
1468 static void emit_if_conditional(struct statement
*stmt
)
1470 struct storage
*val
;
1473 /* emit test portion of conditional */
1474 val
= x86_expression(stmt
->if_conditional
);
1475 cond_end
= emit_conditional_test(val
);
1477 /* emit if-true statement */
1478 x86_statement(stmt
->if_true
);
1480 /* emit if-false statement, if present */
1481 if (stmt
->if_false
) {
1482 cond_end
= emit_conditional_end(cond_end
);
1483 x86_statement(stmt
->if_false
);
1486 /* end of conditional; jump target for if-true branch */
1487 emit_label(cond_end
, "end if");
1490 static struct storage
*emit_inc_dec(struct expression
*expr
, int postop
)
1492 struct storage
*addr
= x86_address_gen(expr
->unop
);
1493 struct storage
*retval
;
1496 strcpy(opname
, opbits(expr
->op
== SPECIAL_INCREMENT
? "inc" : "dec",
1497 expr
->ctype
->bit_size
));
1500 struct storage
*new = stack_alloc(4);
1502 emit_copy(new, addr
, expr
->unop
->ctype
);
1508 insn(opname
, addr
, NULL
, NULL
);
1513 static struct storage
*emit_postop(struct expression
*expr
)
1515 return emit_inc_dec(expr
, 1);
1518 static struct storage
*emit_return_stmt(struct statement
*stmt
)
1520 struct function
*f
= current_func
;
1521 struct expression
*expr
= stmt
->ret_value
;
1522 struct storage
*val
= NULL
, *jmplbl
;
1524 if (expr
&& expr
->ctype
) {
1525 val
= x86_expression(expr
);
1526 assert(val
!= NULL
);
1527 emit_move(val
, REG_EAX
, expr
->ctype
, "return");
1530 jmplbl
= new_storage(STOR_LABEL
);
1531 jmplbl
->flags
|= STOR_WANTS_FREE
;
1532 jmplbl
->label
= f
->ret_target
;
1533 insn("jmp", jmplbl
, NULL
, NULL
);
1538 static struct storage
*emit_conditional_expr(struct expression
*expr
)
1540 struct storage
*cond
, *true = NULL
, *false = NULL
;
1541 struct storage
*new = stack_alloc(expr
->ctype
->bit_size
/ 8);
1542 int target_false
, cond_end
;
1544 /* evaluate conditional */
1545 cond
= x86_expression(expr
->conditional
);
1546 target_false
= emit_conditional_test(cond
);
1548 /* handle if-true part of the expression */
1549 true = x86_expression(expr
->cond_true
);
1551 emit_copy(new, true, expr
->ctype
);
1553 cond_end
= emit_conditional_end(target_false
);
1555 /* handle if-false part of the expression */
1556 false = x86_expression(expr
->cond_false
);
1558 emit_copy(new, false, expr
->ctype
);
1560 /* end of conditional; jump target for if-true branch */
1561 emit_label(cond_end
, "end conditional");
1566 static struct storage
*emit_select_expr(struct expression
*expr
)
1568 struct storage
*cond
= x86_expression(expr
->conditional
);
1569 struct storage
*true = x86_expression(expr
->cond_true
);
1570 struct storage
*false = x86_expression(expr
->cond_false
);
1571 struct storage
*reg_cond
, *reg_true
, *reg_false
;
1572 struct storage
*new = stack_alloc(4);
1574 emit_comment("begin SELECT");
1575 reg_cond
= get_reg_value(cond
, get_regclass(expr
->conditional
));
1576 reg_true
= get_reg_value(true, get_regclass(expr
));
1577 reg_false
= get_reg_value(false, get_regclass(expr
));
1580 * Do the actual select: check the conditional for zero,
1581 * move false over true if zero
1583 insn("test", reg_cond
, reg_cond
, NULL
);
1584 insn("cmovz", reg_false
, reg_true
, NULL
);
1587 emit_move(reg_true
, new, expr
->ctype
, NULL
);
1591 emit_comment("end SELECT");
1595 static struct storage
*emit_symbol_expr_init(struct symbol
*sym
)
1597 struct expression
*expr
= sym
->initializer
;
1598 struct symbol_private
*priv
= sym
->aux
;
1601 priv
= calloc(1, sizeof(*priv
));
1605 struct storage
*new = stack_alloc(4);
1606 fprintf(stderr
, "FIXME! no value for symbol %s. creating pseudo %d (stack offset %d)\n",
1607 show_ident(sym
->ident
),
1608 new->pseudo
, new->pseudo
* 4);
1611 priv
->addr
= x86_expression(expr
);
1618 static struct storage
*emit_string_expr(struct expression
*expr
)
1620 struct function
*f
= current_func
;
1621 int label
= new_label();
1622 struct storage
*new;
1624 push_cstring(f
, expr
->string
, label
);
1626 new = new_storage(STOR_LABEL
);
1628 new->flags
= STOR_LABEL_VAL
| STOR_WANTS_FREE
;
1632 static struct storage
*emit_cast_expr(struct expression
*expr
)
1634 struct symbol
*old_type
, *new_type
;
1635 struct storage
*op
= x86_expression(expr
->cast_expression
);
1636 int oldbits
, newbits
;
1637 struct storage
*new;
1639 old_type
= expr
->cast_expression
->ctype
;
1640 new_type
= expr
->cast_type
;
1642 oldbits
= old_type
->bit_size
;
1643 newbits
= new_type
->bit_size
;
1644 if (oldbits
>= newbits
)
1647 emit_move(op
, REG_EAX
, old_type
, "begin cast ..");
1649 new = stack_alloc(newbits
/ 8);
1650 emit_move(REG_EAX
, new, new_type
, ".... end cast");
1655 static struct storage
*emit_regular_preop(struct expression
*expr
)
1657 struct storage
*target
= x86_expression(expr
->unop
);
1658 struct storage
*val
, *new = stack_alloc(4);
1659 const char *opname
= NULL
;
1663 val
= new_storage(STOR_VALUE
);
1664 val
->flags
= STOR_WANTS_FREE
;
1665 emit_move(val
, REG_EDX
, NULL
, NULL
);
1666 emit_move(target
, REG_EAX
, expr
->unop
->ctype
, NULL
);
1667 insn("test", REG_EAX
, REG_EAX
, NULL
);
1668 insn("setz", REG_DL
, NULL
, NULL
);
1669 emit_move(REG_EDX
, new, expr
->unop
->ctype
, NULL
);
1677 emit_move(target
, REG_EAX
, expr
->unop
->ctype
, NULL
);
1678 insn(opname
, REG_EAX
, NULL
, NULL
);
1679 emit_move(REG_EAX
, new, expr
->unop
->ctype
, NULL
);
1689 static void emit_case_statement(struct statement
*stmt
)
1691 emit_labelsym(stmt
->case_label
, NULL
);
1692 x86_statement(stmt
->case_statement
);
1695 static void emit_switch_statement(struct statement
*stmt
)
1697 struct storage
*val
= x86_expression(stmt
->switch_expression
);
1698 struct symbol
*sym
, *default_sym
= NULL
;
1699 struct storage
*labelsym
, *label
;
1702 emit_move(val
, REG_EAX
, stmt
->switch_expression
->ctype
, "begin case");
1705 * This is where a _real_ back-end would go through the
1706 * cases to decide whether to use a lookup table or a
1707 * series of comparisons etc
1709 FOR_EACH_PTR(stmt
->switch_case
->symbol_list
, sym
) {
1710 struct statement
*case_stmt
= sym
->stmt
;
1711 struct expression
*expr
= case_stmt
->case_expression
;
1712 struct expression
*to
= case_stmt
->case_to
;
1720 struct storage
*case_val
= new_val(expr
->value
);
1722 assert (expr
->type
== EXPR_VALUE
);
1724 insn("cmpl", case_val
, REG_EAX
, NULL
);
1727 labelsym
= new_labelsym(sym
);
1728 insn("je", labelsym
, NULL
, NULL
);
1732 label
= new_storage(STOR_LABEL
);
1733 label
->flags
|= STOR_WANTS_FREE
;
1734 label
->label
= next_test
= new_label();
1736 /* FIXME: signed/unsigned */
1737 insn("jl", label
, NULL
, NULL
);
1739 case_val
= new_val(to
->value
);
1740 insn("cmpl", case_val
, REG_EAX
, NULL
);
1742 /* TODO: implement and use refcounting... */
1743 label
= new_storage(STOR_LABEL
);
1744 label
->flags
|= STOR_WANTS_FREE
;
1745 label
->label
= next_test
;
1747 /* FIXME: signed/unsigned */
1748 insn("jg", label
, NULL
, NULL
);
1750 labelsym
= new_labelsym(sym
);
1751 insn("jmp", labelsym
, NULL
, NULL
);
1753 emit_label(next_test
, NULL
);
1756 } END_FOR_EACH_PTR(sym
);
1759 labelsym
= new_labelsym(default_sym
);
1760 insn("jmp", labelsym
, NULL
, "default");
1762 label
= new_storage(STOR_LABEL
);
1763 label
->flags
|= STOR_WANTS_FREE
;
1764 label
->label
= switch_end
= new_label();
1765 insn("jmp", label
, NULL
, "goto end of switch");
1768 x86_statement(stmt
->switch_statement
);
1770 if (stmt
->switch_break
->used
)
1771 emit_labelsym(stmt
->switch_break
, NULL
);
1774 emit_label(switch_end
, NULL
);
1777 static void x86_struct_member(struct symbol
*sym
)
1779 printf("\t%s:%d:%ld at offset %ld.%d", show_ident(sym
->ident
), sym
->bit_size
, sym
->ctype
.alignment
, sym
->offset
, sym
->bit_offset
);
1783 static void x86_symbol(struct symbol
*sym
)
1785 struct symbol
*type
;
1790 type
= sym
->ctype
.base_type
;
1795 * Show actual implementation information
1797 switch (type
->type
) {
1800 if (sym
->initializer
)
1803 emit_array_noinit(sym
);
1807 if (sym
->initializer
) {
1808 emit_object_pre(show_ident(sym
->ident
),
1809 sym
->ctype
.modifiers
,
1810 sym
->ctype
.alignment
,
1812 emit_scalar(sym
->initializer
, sym
->bit_size
);
1815 emit_scalar_noinit(sym
);
1820 struct symbol
*member
;
1823 FOR_EACH_PTR(type
->symbol_list
, member
) {
1824 x86_struct_member(member
);
1825 } END_FOR_EACH_PTR(member
);
1831 struct statement
*stmt
= type
->stmt
;
1834 x86_statement(stmt
);
1835 emit_func_post(sym
);
1844 if (sym
->initializer
&& (type
->type
!= SYM_BASETYPE
) &&
1845 (type
->type
!= SYM_ARRAY
)) {
1847 x86_expression(sym
->initializer
);
1851 static void x86_symbol_init(struct symbol
*sym
);
1853 static void x86_symbol_decl(struct symbol_list
*syms
)
1856 FOR_EACH_PTR(syms
, sym
) {
1857 x86_symbol_init(sym
);
1858 } END_FOR_EACH_PTR(sym
);
1861 static void loopstk_push(int cont_lbl
, int loop_bottom_lbl
)
1863 struct function
*f
= current_func
;
1864 struct loop_stack
*ls
;
1866 ls
= malloc(sizeof(*ls
));
1867 ls
->continue_lbl
= cont_lbl
;
1868 ls
->loop_bottom_lbl
= loop_bottom_lbl
;
1869 ls
->next
= f
->loop_stack
;
1873 static void loopstk_pop(void)
1875 struct function
*f
= current_func
;
1876 struct loop_stack
*ls
;
1878 assert(f
->loop_stack
!= NULL
);
1880 f
->loop_stack
= f
->loop_stack
->next
;
1884 static int loopstk_break(void)
1886 return current_func
->loop_stack
->loop_bottom_lbl
;
1889 static int loopstk_continue(void)
1891 return current_func
->loop_stack
->continue_lbl
;
1894 static void emit_loop(struct statement
*stmt
)
1896 struct statement
*pre_statement
= stmt
->iterator_pre_statement
;
1897 struct expression
*pre_condition
= stmt
->iterator_pre_condition
;
1898 struct statement
*statement
= stmt
->iterator_statement
;
1899 struct statement
*post_statement
= stmt
->iterator_post_statement
;
1900 struct expression
*post_condition
= stmt
->iterator_post_condition
;
1901 int loop_top
= 0, loop_bottom
, loop_continue
;
1902 int have_bottom
= 0;
1903 struct storage
*val
;
1905 loop_bottom
= new_label();
1906 loop_continue
= new_label();
1907 loopstk_push(loop_continue
, loop_bottom
);
1909 x86_symbol_decl(stmt
->iterator_syms
);
1910 x86_statement(pre_statement
);
1911 if (pre_condition
) {
1912 if (pre_condition
->type
== EXPR_VALUE
) {
1913 if (!pre_condition
->value
) {
1914 struct storage
*lbv
;
1915 lbv
= new_storage(STOR_LABEL
);
1916 lbv
->label
= loop_bottom
;
1917 lbv
->flags
= STOR_WANTS_FREE
;
1918 insn("jmp", lbv
, NULL
, "go to loop bottom");
1922 struct storage
*lbv
= new_storage(STOR_LABEL
);
1923 lbv
->label
= loop_bottom
;
1924 lbv
->flags
= STOR_WANTS_FREE
;
1927 val
= x86_expression(pre_condition
);
1929 emit_move(val
, REG_EAX
, NULL
, "loop pre condition");
1930 insn("test", REG_EAX
, REG_EAX
, NULL
);
1931 insn("jz", lbv
, NULL
, NULL
);
1934 if (!post_condition
|| post_condition
->type
!= EXPR_VALUE
|| post_condition
->value
) {
1935 loop_top
= new_label();
1936 emit_label(loop_top
, "loop top");
1938 x86_statement(statement
);
1939 if (stmt
->iterator_continue
->used
)
1940 emit_label(loop_continue
, "'continue' iterator");
1941 x86_statement(post_statement
);
1942 if (!post_condition
) {
1943 struct storage
*lbv
= new_storage(STOR_LABEL
);
1944 lbv
->label
= loop_top
;
1945 lbv
->flags
= STOR_WANTS_FREE
;
1946 insn("jmp", lbv
, NULL
, "go to loop top");
1947 } else if (post_condition
->type
== EXPR_VALUE
) {
1948 if (post_condition
->value
) {
1949 struct storage
*lbv
= new_storage(STOR_LABEL
);
1950 lbv
->label
= loop_top
;
1951 lbv
->flags
= STOR_WANTS_FREE
;
1952 insn("jmp", lbv
, NULL
, "go to loop top");
1955 struct storage
*lbv
= new_storage(STOR_LABEL
);
1956 lbv
->label
= loop_top
;
1957 lbv
->flags
= STOR_WANTS_FREE
;
1959 val
= x86_expression(post_condition
);
1961 emit_move(val
, REG_EAX
, NULL
, "loop post condition");
1962 insn("test", REG_EAX
, REG_EAX
, NULL
);
1963 insn("jnz", lbv
, NULL
, NULL
);
1965 if (have_bottom
|| stmt
->iterator_break
->used
)
1966 emit_label(loop_bottom
, "loop bottom");
1972 * Print out a statement
1974 static struct storage
*x86_statement(struct statement
*stmt
)
1978 switch (stmt
->type
) {
1980 return emit_return_stmt(stmt
);
1981 case STMT_COMPOUND
: {
1982 struct statement
*s
;
1983 struct storage
*last
= NULL
;
1985 x86_symbol_decl(stmt
->syms
);
1986 FOR_EACH_PTR(stmt
->stmts
, s
) {
1987 last
= x86_statement(s
);
1988 } END_FOR_EACH_PTR(s
);
1993 case STMT_EXPRESSION
:
1994 return x86_expression(stmt
->expression
);
1996 emit_if_conditional(stmt
);
2000 emit_case_statement(stmt
);
2003 emit_switch_statement(stmt
);
2014 printf(".L%p:\n", stmt
->label_identifier
);
2015 x86_statement(stmt
->label_statement
);
2019 if (stmt
->goto_expression
) {
2020 struct storage
*val
= x86_expression(stmt
->goto_expression
);
2021 printf("\tgoto *v%d\n", val
->pseudo
);
2022 } else if (!strcmp("break", show_ident(stmt
->goto_label
->ident
))) {
2023 struct storage
*lbv
= new_storage(STOR_LABEL
);
2024 lbv
->label
= loopstk_break();
2025 lbv
->flags
= STOR_WANTS_FREE
;
2026 insn("jmp", lbv
, NULL
, "'break'; go to loop bottom");
2027 } else if (!strcmp("continue", show_ident(stmt
->goto_label
->ident
))) {
2028 struct storage
*lbv
= new_storage(STOR_LABEL
);
2029 lbv
->label
= loopstk_continue();
2030 lbv
->flags
= STOR_WANTS_FREE
;
2031 insn("jmp", lbv
, NULL
, "'continue'; go to loop top");
2033 struct storage
*labelsym
= new_labelsym(stmt
->goto_label
);
2034 insn("jmp", labelsym
, NULL
, NULL
);
2038 printf("\tasm( .... )\n");
2044 static struct storage
*x86_call_expression(struct expression
*expr
)
2046 struct function
*f
= current_func
;
2047 struct symbol
*direct
;
2048 struct expression
*arg
, *fn
;
2049 struct storage
*retval
, *fncall
;
2054 warning(expr
->pos
, "\tcall with no type!");
2059 FOR_EACH_PTR_REVERSE(expr
->args
, arg
) {
2060 struct storage
*new = x86_expression(arg
);
2061 int size
= arg
->ctype
->bit_size
;
2064 * FIXME: i386 SysV ABI dictates that values
2065 * smaller than 32 bits should be placed onto
2066 * the stack as 32-bit objects. We should not
2067 * blindly do a 32-bit push on objects smaller
2072 insn("pushl", new, NULL
,
2073 !framesize
? "begin function call" : NULL
);
2075 framesize
+= size
>> 3;
2076 } END_FOR_EACH_PTR_REVERSE(arg
);
2080 /* Remove dereference, if any */
2082 if (fn
->type
== EXPR_PREOP
) {
2083 if (fn
->unop
->type
== EXPR_SYMBOL
) {
2084 struct symbol
*sym
= fn
->unop
->symbol
;
2085 if (sym
->ctype
.base_type
->type
== SYM_FN
)
2090 struct storage
*direct_stor
= new_storage(STOR_SYM
);
2091 direct_stor
->flags
|= STOR_WANTS_FREE
;
2092 direct_stor
->sym
= direct
;
2093 insn("call", direct_stor
, NULL
, NULL
);
2095 fncall
= x86_expression(fn
);
2096 emit_move(fncall
, REG_EAX
, fn
->ctype
, NULL
);
2098 strcpy(s
, "\tcall\t*%eax\n");
2099 push_text_atom(f
, s
);
2102 /* FIXME: pay attention to BITS_IN_POINTER */
2104 struct storage
*val
= new_storage(STOR_VALUE
);
2105 val
->value
= (long long) framesize
;
2106 val
->flags
= STOR_WANTS_FREE
;
2107 insn("addl", val
, REG_ESP
, NULL
);
2110 retval
= stack_alloc(4);
2111 emit_move(REG_EAX
, retval
, NULL
, "end function call");
2116 static struct storage
*x86_address_gen(struct expression
*expr
)
2118 struct function
*f
= current_func
;
2119 struct storage
*addr
;
2120 struct storage
*new;
2123 addr
= x86_expression(expr
->unop
);
2124 if (expr
->unop
->type
== EXPR_SYMBOL
)
2127 emit_move(addr
, REG_EAX
, NULL
, "begin deref ..");
2129 /* FIXME: operand size */
2130 strcpy(s
, "\tmovl\t(%eax), %ecx\n");
2131 push_text_atom(f
, s
);
2133 new = stack_alloc(4);
2134 emit_move(REG_ECX
, new, NULL
, ".... end deref");
2139 static struct storage
*x86_assignment(struct expression
*expr
)
2141 struct expression
*target
= expr
->left
;
2142 struct storage
*val
, *addr
;
2147 val
= x86_expression(expr
->right
);
2148 addr
= x86_address_gen(target
);
2150 switch (val
->type
) {
2151 /* copy, where both operands are memory */
2154 emit_copy(addr
, val
, expr
->ctype
);
2157 /* copy, one or zero operands are memory */
2162 emit_move(val
, addr
, expr
->left
->ctype
, NULL
);
2172 static int x86_initialization(struct symbol
*sym
, struct expression
*expr
)
2174 struct storage
*val
, *addr
;
2180 bits
= expr
->ctype
->bit_size
;
2181 val
= x86_expression(expr
);
2182 addr
= x86_symbol_expr(sym
);
2183 // FIXME! The "target" expression is for bitfield store information.
2184 // Leave it NULL, which works fine.
2185 emit_store(NULL
, addr
, val
, bits
);
2189 static struct storage
*x86_access(struct expression
*expr
)
2191 return x86_address_gen(expr
);
2194 static struct storage
*x86_preop(struct expression
*expr
)
2197 * '*' is an lvalue access, and is fundamentally different
2198 * from an arithmetic operation. Maybe it should have an
2199 * expression type of its own..
2201 if (expr
->op
== '*')
2202 return x86_access(expr
);
2203 if (expr
->op
== SPECIAL_INCREMENT
|| expr
->op
== SPECIAL_DECREMENT
)
2204 return emit_inc_dec(expr
, 0);
2205 return emit_regular_preop(expr
);
2208 static struct storage
*x86_symbol_expr(struct symbol
*sym
)
2210 struct storage
*new = stack_alloc(4);
2212 if (sym
->ctype
.modifiers
& (MOD_TOPLEVEL
| MOD_EXTERN
| MOD_STATIC
)) {
2213 printf("\tmovi.%d\t\tv%d,$%s\n", bits_in_pointer
, new->pseudo
, show_ident(sym
->ident
));
2216 if (sym
->ctype
.modifiers
& MOD_ADDRESSABLE
) {
2217 printf("\taddi.%d\t\tv%d,vFP,$%lld\n", bits_in_pointer
, new->pseudo
, sym
->value
);
2220 printf("\taddi.%d\t\tv%d,vFP,$offsetof(%s:%p)\n", bits_in_pointer
, new->pseudo
, show_ident(sym
->ident
), sym
);
2224 static void x86_symbol_init(struct symbol
*sym
)
2226 struct symbol_private
*priv
= sym
->aux
;
2227 struct expression
*expr
= sym
->initializer
;
2228 struct storage
*new;
2231 new = x86_expression(expr
);
2233 new = stack_alloc(sym
->bit_size
/ 8);
2236 priv
= calloc(1, sizeof(*priv
));
2238 /* FIXME: leak! we don't free... */
2239 /* (well, we don't free symbols either) */
2245 static int type_is_signed(struct symbol
*sym
)
2247 if (sym
->type
== SYM_NODE
)
2248 sym
= sym
->ctype
.base_type
;
2249 if (sym
->type
== SYM_PTR
)
2251 return !(sym
->ctype
.modifiers
& MOD_UNSIGNED
);
2254 static struct storage
*x86_label_expr(struct expression
*expr
)
2256 struct storage
*new = stack_alloc(4);
2257 printf("\tmovi.%d\t\tv%d,.L%p\n", bits_in_pointer
, new->pseudo
, expr
->label_symbol
);
2261 static struct storage
*x86_statement_expr(struct expression
*expr
)
2263 return x86_statement(expr
->statement
);
2266 static int x86_position_expr(struct expression
*expr
, struct symbol
*base
)
2268 struct storage
*new = x86_expression(expr
->init_expr
);
2269 struct symbol
*ctype
= expr
->init_expr
->ctype
;
2271 printf("\tinsert v%d at [%d:%d] of %s\n", new->pseudo
,
2272 expr
->init_offset
, ctype
->bit_offset
,
2273 show_ident(base
->ident
));
2277 static void x86_initializer_expr(struct expression
*expr
, struct symbol
*ctype
)
2279 struct expression
*entry
;
2281 FOR_EACH_PTR(expr
->expr_list
, entry
) {
2282 // Nested initializers have their positions already
2283 // recursively calculated - just output them too
2284 if (entry
->type
== EXPR_INITIALIZER
) {
2285 x86_initializer_expr(entry
, ctype
);
2289 // Ignore initializer indexes and identifiers - the
2290 // evaluator has taken them into account
2291 if (entry
->type
== EXPR_IDENTIFIER
|| entry
->type
== EXPR_INDEX
)
2293 if (entry
->type
== EXPR_POS
) {
2294 x86_position_expr(entry
, ctype
);
2297 x86_initialization(ctype
, entry
);
2298 } END_FOR_EACH_PTR(entry
);
2302 * Print out an expression. Return the pseudo that contains the
2305 static struct storage
*x86_expression(struct expression
*expr
)
2311 struct position
*pos
= &expr
->pos
;
2312 printf("\tno type at %s:%d:%d\n",
2313 input_streams
[pos
->stream
].name
,
2314 pos
->line
, pos
->pos
);
2318 switch (expr
->type
) {
2320 return x86_call_expression(expr
);
2322 case EXPR_ASSIGNMENT
:
2323 return x86_assignment(expr
);
2326 return emit_compare(expr
);
2330 return emit_binop(expr
);
2332 return x86_preop(expr
);
2334 return emit_postop(expr
);
2336 return emit_symbol_expr_init(expr
->symbol
);
2340 warning(expr
->pos
, "invalid expression after evaluation");
2343 case EXPR_IMPLIED_CAST
:
2344 return emit_cast_expr(expr
);
2346 return emit_value(expr
);
2348 return emit_string_expr(expr
);
2349 case EXPR_INITIALIZER
:
2350 x86_initializer_expr(expr
, expr
->ctype
);
2353 return emit_select_expr(expr
);
2354 case EXPR_CONDITIONAL
:
2355 return emit_conditional_expr(expr
);
2356 case EXPR_STATEMENT
:
2357 return x86_statement_expr(expr
);
2359 return x86_label_expr(expr
);
2361 // None of these should exist as direct expressions: they are only
2362 // valid as sub-expressions of initializers.
2364 warning(expr
->pos
, "unable to show plain initializer position expression");
2366 case EXPR_IDENTIFIER
:
2367 warning(expr
->pos
, "unable to show identifier expression");
2370 warning(expr
->pos
, "unable to show index expression");
2373 warning(expr
->pos
, "unable to show type expression");
2376 warning(expr
->pos
, "floating point support is not implemented");