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)
40 #include "expression.h"
46 unsigned int len
; /* does NOT include terminating null */
55 struct loop_stack
*next
;
60 DECLARE_PTR_LIST(str_list
, struct atom
);
61 DECLARE_PTR_LIST(atom_list
, struct atom
);
62 DECLARE_PTR_LIST(storage_list
, struct storage
);
67 struct storage_list
*pseudo_list
;
68 struct atom_list
*atom_list
;
69 struct str_list
*str_list
;
70 struct loop_stack
*loop_stack
;
77 STOR_PSEUDO
, /* variable stored on the stack */
78 STOR_ARG
, /* function argument */
79 STOR_SYM
, /* a symbol we can directly ref in the asm */
80 STOR_REG
, /* scratch register */
81 STOR_VALUE
, /* integer constant */
82 STOR_LABEL
, /* label / jump target */
83 STOR_LABELSYM
, /* label generated from symbol's pointer value */
88 struct storage
*contains
;
89 const unsigned char aliases
[12];
90 #define own_regno aliases[0]
94 enum storage_type type
;
126 struct symbol
*labelsym
;
132 STOR_LABEL_VAL
= (1 << 0),
133 STOR_WANTS_FREE
= (1 << 1),
136 struct symbol_private
{
137 struct storage
*addr
;
152 unsigned int text_len
; /* w/o terminating null */
155 /* stuff for insns */
163 /* stuff for C strings */
165 struct string
*string
;
172 static struct function
*current_func
= NULL
;
173 static struct textbuf
*unit_post_text
= NULL
;
174 static const char *current_section
;
176 static void emit_comment(const char * fmt
, ...) FORMAT_ATTR(1);
177 static void emit_move(struct storage
*src
, struct storage
*dest
,
178 struct symbol
*ctype
, const char *comment
);
179 static int type_is_signed(struct symbol
*sym
);
180 static struct storage
*x86_address_gen(struct expression
*expr
);
181 static struct storage
*x86_symbol_expr(struct symbol
*sym
);
182 static void x86_symbol(struct symbol
*sym
);
183 static struct storage
*x86_statement(struct statement
*stmt
);
184 static struct storage
*x86_expression(struct expression
*expr
);
188 AL
, DL
, CL
, BL
, AH
, DH
, CH
, BH
, // 8-bit
189 AX
, DX
, CX
, BX
, SI
, DI
, BP
, SP
, // 16-bit
190 EAX
, EDX
, ECX
, EBX
, ESI
, EDI
, EBP
, ESP
, // 32-bit
191 EAX_EDX
, ECX_EBX
, ESI_EDI
, // 64-bit
194 /* This works on regno's, reg_info's and hardreg_storage's */
195 #define byte_reg(reg) ((reg) - 16)
196 #define highbyte_reg(reg) ((reg)-12)
197 #define word_reg(reg) ((reg)-8)
199 #define REGINFO(nr, str, conflicts...) [nr] = { .name = str, .aliases = { nr , conflicts } }
201 static struct reg_info reg_info_table
[] = {
202 REGINFO( AL
, "%al", AX
, EAX
, EAX_EDX
),
203 REGINFO( DL
, "%dl", DX
, EDX
, EAX_EDX
),
204 REGINFO( CL
, "%cl", CX
, ECX
, ECX_EBX
),
205 REGINFO( BL
, "%bl", BX
, EBX
, ECX_EBX
),
206 REGINFO( AH
, "%ah", AX
, EAX
, EAX_EDX
),
207 REGINFO( DH
, "%dh", DX
, EDX
, EAX_EDX
),
208 REGINFO( CH
, "%ch", CX
, ECX
, ECX_EBX
),
209 REGINFO( BH
, "%bh", BX
, EBX
, ECX_EBX
),
210 REGINFO( AX
, "%ax", AL
, AH
, EAX
, EAX_EDX
),
211 REGINFO( DX
, "%dx", DL
, DH
, EDX
, EAX_EDX
),
212 REGINFO( CX
, "%cx", CL
, CH
, ECX
, ECX_EBX
),
213 REGINFO( BX
, "%bx", BL
, BH
, EBX
, ECX_EBX
),
214 REGINFO( SI
, "%si", ESI
, ESI_EDI
),
215 REGINFO( DI
, "%di", EDI
, ESI_EDI
),
216 REGINFO( BP
, "%bp", EBP
),
217 REGINFO( SP
, "%sp", ESP
),
218 REGINFO(EAX
, "%eax", AL
, AH
, AX
, EAX_EDX
),
219 REGINFO(EDX
, "%edx", DL
, DH
, DX
, EAX_EDX
),
220 REGINFO(ECX
, "%ecx", CL
, CH
, CX
, ECX_EBX
),
221 REGINFO(EBX
, "%ebx", BL
, BH
, BX
, ECX_EBX
),
222 REGINFO(ESI
, "%esi", SI
, ESI_EDI
),
223 REGINFO(EDI
, "%edi", DI
, ESI_EDI
),
224 REGINFO(EBP
, "%ebp", BP
),
225 REGINFO(ESP
, "%esp", SP
),
226 REGINFO(EAX_EDX
, "%eax:%edx", AL
, AH
, AX
, EAX
, DL
, DH
, DX
, EDX
),
227 REGINFO(ECX_EBX
, "%ecx:%ebx", CL
, CH
, CX
, ECX
, BL
, BH
, BX
, EBX
),
228 REGINFO(ESI_EDI
, "%esi:%edi", SI
, ESI
, DI
, EDI
),
231 #define REGSTORAGE(nr) [nr] = { .type = STOR_REG, .reg = reg_info_table + (nr) }
233 static struct storage hardreg_storage_table
[] = {
234 REGSTORAGE(AL
), REGSTORAGE(DL
), REGSTORAGE(CL
), REGSTORAGE(BL
),
235 REGSTORAGE(AH
), REGSTORAGE(DH
), REGSTORAGE(CH
), REGSTORAGE(BH
),
236 REGSTORAGE(AX
), REGSTORAGE(DX
), REGSTORAGE(CX
), REGSTORAGE(BX
),
237 REGSTORAGE(SI
), REGSTORAGE(DI
), REGSTORAGE(BP
), REGSTORAGE(SP
),
238 REGSTORAGE(EAX
), REGSTORAGE(EDX
), REGSTORAGE(ECX
), REGSTORAGE(EBX
),
239 REGSTORAGE(ESI
), REGSTORAGE(EDI
), REGSTORAGE(EBP
), REGSTORAGE(ESP
),
240 REGSTORAGE(EAX_EDX
), REGSTORAGE(ECX_EBX
), REGSTORAGE(ESI_EDI
),
243 #define REG_EAX (&hardreg_storage_table[EAX])
244 #define REG_ECX (&hardreg_storage_table[ECX])
245 #define REG_EDX (&hardreg_storage_table[EDX])
246 #define REG_ESP (&hardreg_storage_table[ESP])
247 #define REG_DL (&hardreg_storage_table[DL])
248 #define REG_DX (&hardreg_storage_table[DX])
249 #define REG_AL (&hardreg_storage_table[AL])
250 #define REG_AX (&hardreg_storage_table[AX])
252 static DECLARE_BITMAP(regs_in_use
, 256);
254 static inline struct storage
* reginfo_reg(struct reg_info
*info
)
256 return hardreg_storage_table
+ info
->own_regno
;
259 static struct storage
* get_hardreg(struct storage
*reg
, int clear
)
261 struct reg_info
*info
= reg
->reg
;
262 const unsigned char *aliases
;
265 aliases
= info
->aliases
;
266 while ((regno
= *aliases
++) != NOREG
) {
267 if (test_bit(regno
, regs_in_use
))
270 reg_info_table
[regno
].contains
= NULL
;
272 set_bit(info
->own_regno
, regs_in_use
);
275 fprintf(stderr
, "register %s is busy\n", info
->name
);
276 if (regno
+ reg_info_table
!= info
)
277 fprintf(stderr
, " conflicts with %s\n", reg_info_table
[regno
].name
);
281 static void put_reg(struct storage
*reg
)
283 struct reg_info
*info
= reg
->reg
;
284 int regno
= info
->own_regno
;
286 if (test_and_clear_bit(regno
, regs_in_use
))
288 fprintf(stderr
, "freeing already free'd register %s\n", reg_info_table
[regno
].name
);
293 const unsigned char regs
[30];
296 static struct regclass regclass_8
= { "8-bit", { AL
, DL
, CL
, BL
, AH
, DH
, CH
, BH
}};
297 static struct regclass regclass_16
= { "16-bit", { AX
, DX
, CX
, BX
, SI
, DI
, BP
}};
298 static struct regclass regclass_32
= { "32-bit", { EAX
, EDX
, ECX
, EBX
, ESI
, EDI
, EBP
}};
299 static struct regclass regclass_64
= { "64-bit", { EAX_EDX
, ECX_EBX
, ESI_EDI
}};
301 static struct regclass regclass_32_8
= { "32-bit bytes", { EAX
, EDX
, ECX
, EBX
}};
303 static struct regclass
*get_regclass_bits(int bits
)
306 case 8: return ®class_8
;
307 case 16: return ®class_16
;
308 case 64: return ®class_64
;
309 default: return ®class_32
;
313 static struct regclass
*get_regclass(struct expression
*expr
)
315 return get_regclass_bits(expr
->ctype
->bit_size
);
318 static int register_busy(int regno
)
320 if (!test_bit(regno
, regs_in_use
)) {
321 struct reg_info
*info
= reg_info_table
+ regno
;
322 const unsigned char *regs
= info
->aliases
+1;
324 while ((regno
= *regs
) != NOREG
) {
326 if (test_bit(regno
, regs_in_use
))
335 static struct storage
*get_reg(struct regclass
*class)
337 const unsigned char *regs
= class->regs
;
340 while ((regno
= *regs
) != NOREG
) {
342 if (register_busy(regno
))
344 return get_hardreg(hardreg_storage_table
+ regno
, 1);
346 fprintf(stderr
, "Ran out of %s registers\n", class->name
);
350 static struct storage
*get_reg_value(struct storage
*value
, struct regclass
*class)
352 struct reg_info
*info
;
355 /* Do we already have it somewhere */
357 if (info
&& info
->contains
== value
) {
358 emit_comment("already have register %s", info
->name
);
359 return get_hardreg(hardreg_storage_table
+ info
->own_regno
, 0);
362 reg
= get_reg(class);
363 emit_move(value
, reg
, value
->ctype
, "reload register");
365 info
->contains
= value
;
370 static struct storage
*temp_from_bits(unsigned int bit_size
)
372 return get_reg(get_regclass_bits(bit_size
));
375 static inline unsigned int pseudo_offset(struct storage
*s
)
377 if (s
->type
!= STOR_PSEUDO
)
378 return 123456; /* intentionally bogus value */
383 static inline unsigned int arg_offset(struct storage
*s
)
385 if (s
->type
!= STOR_ARG
)
386 return 123456; /* intentionally bogus value */
388 /* FIXME: this is wrong wrong wrong */
389 return current_func
->stack_size
+ ((1 + s
->idx
) * 4);
392 static const char *pretty_offset(int ofs
)
394 static char esp_buf
[64];
397 sprintf(esp_buf
, "%d(%%esp)", ofs
);
399 strcpy(esp_buf
, "(%esp)");
404 static void stor_sym_init(struct symbol
*sym
)
406 struct storage
*stor
;
407 struct symbol_private
*priv
;
409 priv
= calloc(1, sizeof(*priv
) + sizeof(*stor
));
411 die("OOM in stor_sym_init");
413 stor
= (struct storage
*) (priv
+ 1);
416 stor
->type
= STOR_SYM
;
420 static const char *stor_op_name(struct storage
*s
)
422 static char name
[32];
426 strcpy(name
, pretty_offset((int) pseudo_offset(s
)));
429 strcpy(name
, pretty_offset((int) arg_offset(s
)));
432 strcpy(name
, show_ident(s
->sym
->ident
));
435 strcpy(name
, s
->reg
->name
);
438 sprintf(name
, "$%Ld", s
->value
);
441 sprintf(name
, "%s.L%d", s
->flags
& STOR_LABEL_VAL
? "$" : "",
445 sprintf(name
, "%s.LS%p", s
->flags
& STOR_LABEL_VAL
? "$" : "",
453 static struct atom
*new_atom(enum atom_type type
)
457 atom
= calloc(1, sizeof(*atom
)); /* TODO: chunked alloc */
466 static inline void push_cstring(struct function
*f
, struct string
*str
,
471 atom
= new_atom(ATOM_CSTR
);
475 add_ptr_list(&f
->str_list
, atom
); /* note: _not_ atom_list */
478 static inline void push_atom(struct function
*f
, struct atom
*atom
)
480 add_ptr_list(&f
->atom_list
, atom
);
483 static void push_text_atom(struct function
*f
, const char *text
)
485 struct atom
*atom
= new_atom(ATOM_TEXT
);
487 atom
->text
= strdup(text
);
488 atom
->text_len
= strlen(text
);
493 static struct storage
*new_storage(enum storage_type type
)
495 struct storage
*stor
;
497 stor
= calloc(1, sizeof(*stor
));
499 die("OOM in new_storage");
506 static struct storage
*stack_alloc(int n_bytes
)
508 struct function
*f
= current_func
;
509 struct storage
*stor
;
513 stor
= new_storage(STOR_PSEUDO
);
514 stor
->type
= STOR_PSEUDO
;
515 stor
->pseudo
= f
->pseudo_nr
;
516 stor
->offset
= f
->stack_size
; /* FIXME: stack req. natural align */
517 stor
->size
= n_bytes
;
518 f
->stack_size
+= n_bytes
;
521 add_ptr_list(&f
->pseudo_list
, stor
);
526 static struct storage
*new_labelsym(struct symbol
*sym
)
528 struct storage
*stor
;
530 stor
= new_storage(STOR_LABELSYM
);
533 stor
->flags
|= STOR_WANTS_FREE
;
534 stor
->labelsym
= sym
;
540 static struct storage
*new_val(long long value
)
542 struct storage
*stor
;
544 stor
= new_storage(STOR_VALUE
);
547 stor
->flags
|= STOR_WANTS_FREE
;
554 static int new_label(void)
556 static int label
= 0;
560 static void textbuf_push(struct textbuf
**buf_p
, const char *text
)
562 struct textbuf
*tmp
, *list
= *buf_p
;
563 unsigned int text_len
= strlen(text
);
564 unsigned int alloc_len
= text_len
+ 1 + sizeof(*list
);
566 tmp
= calloc(1, alloc_len
);
568 die("OOM on textbuf alloc");
570 tmp
->text
= ((void *) tmp
) + sizeof(*tmp
);
571 memcpy(tmp
->text
, text
, text_len
+ 1);
574 /* add to end of list */
579 tmp
->prev
= list
->prev
;
580 tmp
->prev
->next
= tmp
;
588 static void textbuf_emit(struct textbuf
**buf_p
)
590 struct textbuf
*tmp
, *list
= *buf_p
;
594 if (tmp
->next
== tmp
)
597 tmp
->prev
->next
= tmp
->next
;
598 tmp
->next
->prev
= tmp
->prev
;
602 fputs(tmp
->text
, stdout
);
610 static void insn(const char *insn
, struct storage
*op1
, struct storage
*op2
,
611 const char *comment_in
)
613 struct function
*f
= current_func
;
614 struct atom
*atom
= new_atom(ATOM_INSN
);
616 assert(insn
!= NULL
);
618 strcpy(atom
->insn
, insn
);
619 if (comment_in
&& (*comment_in
))
620 strncpy(atom
->comment
, comment_in
,
621 sizeof(atom
->comment
) - 1);
629 static void emit_comment(const char *fmt
, ...)
631 struct function
*f
= current_func
;
632 static char tmpbuf
[100] = "\t# ";
637 i
= vsnprintf(tmpbuf
+3, sizeof(tmpbuf
)-4, fmt
, args
);
641 push_text_atom(f
, tmpbuf
);
644 static void emit_label (int label
, const char *comment
)
646 struct function
*f
= current_func
;
650 sprintf(s
, ".L%d:\n", label
);
652 sprintf(s
, ".L%d:\t\t\t\t\t# %s\n", label
, comment
);
654 push_text_atom(f
, s
);
657 static void emit_labelsym (struct symbol
*sym
, const char *comment
)
659 struct function
*f
= current_func
;
663 sprintf(s
, ".LS%p:\n", sym
);
665 sprintf(s
, ".LS%p:\t\t\t\t# %s\n", sym
, comment
);
667 push_text_atom(f
, s
);
670 void emit_unit_begin(const char *basename
)
672 printf("\t.file\t\"%s\"\n", basename
);
675 void emit_unit_end(void)
677 textbuf_emit(&unit_post_text
);
678 printf("\t.ident\t\"sparse silly x86 backend (built %s)\"\n", __DATE__
);
681 /* conditionally switch sections */
682 static void emit_section(const char *s
)
684 if (s
== current_section
)
686 if (current_section
&& (!strcmp(s
, current_section
)))
693 static void emit_insn_atom(struct function
*f
, struct atom
*atom
)
697 struct storage
*op1
= atom
->op1
;
698 struct storage
*op2
= atom
->op2
;
700 if (atom
->comment
[0])
701 sprintf(comment
, "\t\t# %s", atom
->comment
);
707 strcpy(tmp
, stor_op_name(op1
));
708 sprintf(s
, "\t%s\t%s, %s%s\n",
709 atom
->insn
, tmp
, stor_op_name(op2
), comment
);
710 } else if (atom
->op1
)
711 sprintf(s
, "\t%s\t%s%s%s\n",
712 atom
->insn
, stor_op_name(op1
),
713 comment
[0] ? "\t" : "", comment
);
715 sprintf(s
, "\t%s\t%s%s\n",
717 comment
[0] ? "\t\t" : "", comment
);
719 write(STDOUT_FILENO
, s
, strlen(s
));
722 static void emit_atom_list(struct function
*f
)
726 FOR_EACH_PTR(f
->atom_list
, atom
) {
727 switch (atom
->type
) {
729 ssize_t rc
= write(STDOUT_FILENO
, atom
->text
,
731 (void) rc
; /* FIXME */
735 emit_insn_atom(f
, atom
);
741 } END_FOR_EACH_PTR(atom
);
744 static void emit_string_list(struct function
*f
)
748 emit_section(".section\t.rodata");
750 FOR_EACH_PTR(f
->str_list
, atom
) {
751 /* FIXME: escape " in string */
752 printf(".L%d:\n", atom
->label
);
753 printf("\t.string\t%s\n", show_string(atom
->string
));
756 } END_FOR_EACH_PTR(atom
);
759 static void func_cleanup(struct function
*f
)
761 struct storage
*stor
;
764 FOR_EACH_PTR(f
->atom_list
, atom
) {
765 if ((atom
->type
== ATOM_TEXT
) && (atom
->text
))
767 if (atom
->op1
&& (atom
->op1
->flags
& STOR_WANTS_FREE
))
769 if (atom
->op2
&& (atom
->op2
->flags
& STOR_WANTS_FREE
))
772 } END_FOR_EACH_PTR(atom
);
774 FOR_EACH_PTR(f
->pseudo_list
, stor
) {
776 } END_FOR_EACH_PTR(stor
);
778 free_ptr_list(&f
->pseudo_list
);
782 /* function prologue */
783 static void emit_func_pre(struct symbol
*sym
)
787 unsigned int i
, argc
= 0, alloc_len
;
789 struct symbol_private
*privbase
;
790 struct storage
*storage_base
;
791 struct symbol
*base_type
= sym
->ctype
.base_type
;
793 FOR_EACH_PTR(base_type
->arguments
, arg
) {
795 } END_FOR_EACH_PTR(arg
);
799 (argc
* sizeof(struct symbol
*)) +
800 (argc
* sizeof(struct symbol_private
)) +
801 (argc
* sizeof(struct storage
));
802 mem
= calloc(1, alloc_len
);
804 die("OOM on func info");
806 f
= (struct function
*) mem
;
808 f
->argv
= (struct symbol
**) mem
;
809 mem
+= (argc
* sizeof(struct symbol
*));
810 privbase
= (struct symbol_private
*) mem
;
811 mem
+= (argc
* sizeof(struct symbol_private
));
812 storage_base
= (struct storage
*) mem
;
815 f
->ret_target
= new_label();
818 FOR_EACH_PTR(base_type
->arguments
, arg
) {
820 arg
->aux
= &privbase
[i
];
821 storage_base
[i
].type
= STOR_ARG
;
822 storage_base
[i
].idx
= i
;
823 privbase
[i
].addr
= &storage_base
[i
];
825 } END_FOR_EACH_PTR(arg
);
827 assert(current_func
== NULL
);
831 /* function epilogue */
832 static void emit_func_post(struct symbol
*sym
)
834 const char *name
= show_ident(sym
->ident
);
835 struct function
*f
= current_func
;
836 int stack_size
= f
->stack_size
;
841 /* function prologue */
842 emit_section(".text");
843 if ((sym
->ctype
.modifiers
& MOD_STATIC
) == 0)
844 printf(".globl %s\n", name
);
845 printf("\t.type\t%s, @function\n", name
);
846 printf("%s:\n", name
);
849 char pseudo_const
[16];
851 sprintf(pseudo_const
, "$%d", stack_size
);
852 printf("\tsubl\t%s, %%esp\n", pseudo_const
);
855 /* function epilogue */
857 /* jump target for 'return' statements */
858 emit_label(f
->ret_target
, NULL
);
863 val
= new_storage(STOR_VALUE
);
864 val
->value
= (long long) (stack_size
);
865 val
->flags
= STOR_WANTS_FREE
;
867 insn("addl", val
, REG_ESP
, NULL
);
870 insn("ret", NULL
, NULL
, NULL
);
872 /* output everything to stdout */
873 fflush(stdout
); /* paranoia; needed? */
876 /* function footer */
877 name
= show_ident(sym
->ident
);
878 printf("\t.size\t%s, .-%s\n", name
, name
);
884 /* emit object (a.k.a. variable, a.k.a. data) prologue */
885 static void emit_object_pre(const char *name
, unsigned long modifiers
,
886 unsigned long alignment
, unsigned int byte_size
)
888 if ((modifiers
& MOD_STATIC
) == 0)
889 printf(".globl %s\n", name
);
890 emit_section(".data");
892 printf("\t.align %lu\n", alignment
);
893 printf("\t.type\t%s, @object\n", name
);
894 printf("\t.size\t%s, %d\n", name
, byte_size
);
895 printf("%s:\n", name
);
898 /* emit value (only) for an initializer scalar */
899 static void emit_scalar(struct expression
*expr
, unsigned int bit_size
)
904 assert(expr
->type
== EXPR_VALUE
);
906 if (expr
->value
== 0ULL) {
907 printf("\t.zero\t%d\n", bit_size
/ 8);
911 ll
= (long long) expr
->value
;
914 case 8: type
= "byte"; ll
= (char) ll
; break;
915 case 16: type
= "value"; ll
= (short) ll
; break;
916 case 32: type
= "long"; ll
= (int) ll
; break;
917 case 64: type
= "quad"; break;
918 default: type
= NULL
; break;
921 assert(type
!= NULL
);
923 printf("\t.%s\t%Ld\n", type
, ll
);
926 static void emit_global_noinit(const char *name
, unsigned long modifiers
,
927 unsigned long alignment
, unsigned int byte_size
)
931 if (modifiers
& MOD_STATIC
) {
932 sprintf(s
, "\t.local\t%s\n", name
);
933 textbuf_push(&unit_post_text
, s
);
936 sprintf(s
, "\t.comm\t%s,%d,%lu\n", name
, byte_size
, alignment
);
938 sprintf(s
, "\t.comm\t%s,%d\n", name
, byte_size
);
939 textbuf_push(&unit_post_text
, s
);
942 static int ea_current
, ea_last
;
944 static void emit_initializer(struct symbol
*sym
,
945 struct expression
*expr
)
947 int distance
= ea_current
- ea_last
- 1;
950 printf("\t.zero\t%d\n", (sym
->bit_size
/ 8) * distance
);
952 if (expr
->type
== EXPR_VALUE
) {
953 struct symbol
*base_type
= sym
->ctype
.base_type
;
954 assert(base_type
!= NULL
);
956 emit_scalar(expr
, sym
->bit_size
/ get_expression_value(base_type
->array_size
));
959 if (expr
->type
!= EXPR_INITIALIZER
)
962 assert(0); /* FIXME */
965 static int sort_array_cmp(const struct expression
*a
,
966 const struct expression
*b
)
968 int a_ofs
= 0, b_ofs
= 0;
970 if (a
->type
== EXPR_POS
)
971 a_ofs
= (int) a
->init_offset
;
972 if (b
->type
== EXPR_POS
)
973 b_ofs
= (int) b
->init_offset
;
975 return a_ofs
- b_ofs
;
978 /* move to front-end? */
979 static void sort_array(struct expression
*expr
)
981 struct expression
*entry
, **list
;
982 unsigned int elem
, sorted
, i
;
985 FOR_EACH_PTR(expr
->expr_list
, entry
) {
987 } END_FOR_EACH_PTR(entry
);
992 list
= malloc(sizeof(entry
) * elem
);
994 die("OOM in sort_array");
996 /* this code is no doubt evil and ignores EXPR_INDEX possibly
997 * to its detriment and other nasty things. improvements
1002 FOR_EACH_PTR(expr
->expr_list
, entry
) {
1003 if ((entry
->type
== EXPR_POS
) || (entry
->type
== EXPR_VALUE
)) {
1004 /* add entry to list[], in sorted order */
1009 for (i
= 0; i
< sorted
; i
++)
1010 if (sort_array_cmp(entry
, list
[i
]) <= 0)
1013 /* If inserting into the middle of list[]
1014 * instead of appending, we memmove.
1015 * This is ugly, but thankfully
1016 * uncommon. Input data with tons of
1017 * entries very rarely have explicit
1018 * offsets. convert to qsort eventually...
1021 memmove(&list
[i
+ 1], &list
[i
],
1022 (sorted
- i
) * sizeof(entry
));
1027 } END_FOR_EACH_PTR(entry
);
1030 FOR_EACH_PTR(expr
->expr_list
, entry
) {
1031 if ((entry
->type
== EXPR_POS
) || (entry
->type
== EXPR_VALUE
))
1032 *THIS_ADDRESS(entry
) = list
[i
++];
1033 } END_FOR_EACH_PTR(entry
);
1037 static void emit_array(struct symbol
*sym
)
1039 struct symbol
*base_type
= sym
->ctype
.base_type
;
1040 struct expression
*expr
= sym
->initializer
;
1041 struct expression
*entry
;
1043 assert(base_type
!= NULL
);
1049 emit_object_pre(show_ident(sym
->ident
), sym
->ctype
.modifiers
,
1050 sym
->ctype
.alignment
,
1055 FOR_EACH_PTR(expr
->expr_list
, entry
) {
1056 if (entry
->type
== EXPR_VALUE
) {
1058 emit_initializer(sym
, entry
);
1059 ea_last
= ea_current
;
1060 } else if (entry
->type
== EXPR_POS
) {
1062 entry
->init_offset
/ (base_type
->bit_size
/ 8);
1063 emit_initializer(sym
, entry
->init_expr
);
1064 ea_last
= ea_current
;
1066 } END_FOR_EACH_PTR(entry
);
1069 void emit_one_symbol(struct symbol
*sym
)
1074 static void emit_copy(struct storage
*dest
, struct storage
*src
,
1075 struct symbol
*ctype
)
1077 struct storage
*reg
= NULL
;
1078 unsigned int bit_size
;
1080 /* FIXME: Bitfield copy! */
1082 bit_size
= src
->size
* 8;
1085 if ((src
->type
== STOR_ARG
) && (bit_size
< 32))
1088 reg
= temp_from_bits(bit_size
);
1089 emit_move(src
, reg
, ctype
, "begin copy ..");
1091 bit_size
= dest
->size
* 8;
1094 if ((dest
->type
== STOR_ARG
) && (bit_size
< 32))
1097 emit_move(reg
, dest
, ctype
, ".... end copy");
1101 static void emit_store(struct expression
*dest_expr
, struct storage
*dest
,
1102 struct storage
*src
, int bits
)
1104 /* FIXME: Bitfield store! */
1105 printf("\tst.%d\t\tv%d,[v%d]\n", bits
, src
->pseudo
, dest
->pseudo
);
1108 static void emit_scalar_noinit(struct symbol
*sym
)
1110 emit_global_noinit(show_ident(sym
->ident
),
1111 sym
->ctype
.modifiers
, sym
->ctype
.alignment
,
1116 static void emit_array_noinit(struct symbol
*sym
)
1118 emit_global_noinit(show_ident(sym
->ident
),
1119 sym
->ctype
.modifiers
, sym
->ctype
.alignment
,
1120 get_expression_value(sym
->array_size
) * (sym
->bit_size
/ 8));
1124 static const char *opbits(const char *insn
, unsigned int bits
)
1126 static char opbits_str
[32];
1130 case 8: c
= 'b'; break;
1131 case 16: c
= 'w'; break;
1132 case 32: c
= 'l'; break;
1133 case 64: c
= 'q'; break;
1134 default: abort(); break;
1137 sprintf(opbits_str
, "%s%c", insn
, c
);
1142 static void emit_move(struct storage
*src
, struct storage
*dest
,
1143 struct symbol
*ctype
, const char *comment
)
1146 unsigned int is_signed
;
1147 unsigned int is_dest
= (src
->type
== STOR_REG
);
1151 bits
= ctype
->bit_size
;
1152 is_signed
= type_is_signed(ctype
);
1159 * Are we moving from a register to a register?
1160 * Make the new reg to be the "cache".
1162 if ((dest
->type
== STOR_REG
) && (src
->type
== STOR_REG
)) {
1163 struct storage
*backing
;
1169 backing
= src
->reg
->contains
;
1171 /* Is it still valid? */
1172 if (backing
->reg
!= src
->reg
)
1175 backing
->reg
= dest
->reg
;
1177 dest
->reg
->contains
= backing
;
1178 insn("mov", src
, dest
, NULL
);
1183 * Are we moving to a register from a non-reg?
1185 * See if we have the non-reg source already cached
1188 if (dest
->type
== STOR_REG
) {
1190 struct reg_info
*info
= src
->reg
;
1191 if (info
->contains
== src
) {
1192 src
= reginfo_reg(info
);
1196 dest
->reg
->contains
= src
;
1197 src
->reg
= dest
->reg
;
1200 if (src
->type
== STOR_REG
) {
1201 /* We could just mark the register dirty here and do lazy store.. */
1202 src
->reg
->contains
= dest
;
1203 dest
->reg
= src
->reg
;
1206 if ((bits
== 8) || (bits
== 16)) {
1210 opname
= is_signed
? "movsx" : "movzx";
1214 insn(opbits(opname
, bits
), src
, dest
, comment
);
1217 static struct storage
*emit_compare(struct expression
*expr
)
1219 struct storage
*left
= x86_expression(expr
->left
);
1220 struct storage
*right
= x86_expression(expr
->right
);
1221 struct storage
*reg1
, *reg2
;
1222 struct storage
*new, *val
;
1223 const char *opname
= NULL
;
1224 unsigned int right_bits
= expr
->right
->ctype
->bit_size
;
1227 case '<': opname
= "setl"; break;
1228 case '>': opname
= "setg"; break;
1230 opname
= "setle"; break;
1232 opname
= "setge"; break;
1233 case SPECIAL_EQUAL
: opname
= "sete"; break;
1234 case SPECIAL_NOTEQUAL
: opname
= "setne"; break;
1235 case SPECIAL_UNSIGNED_LT
:
1236 opname
= "setb"; break;
1237 case SPECIAL_UNSIGNED_GT
:
1238 opname
= "seta"; break;
1239 case SPECIAL_UNSIGNED_LTE
:
1240 opname
= "setb"; break;
1241 case SPECIAL_UNSIGNED_GTE
:
1242 opname
= "setae"; break;
1249 val
= new_storage(STOR_VALUE
);
1250 val
->flags
= STOR_WANTS_FREE
;
1252 reg1
= get_reg(®class_32_8
);
1253 emit_move(val
, reg1
, NULL
, NULL
);
1255 /* move op1 into EAX */
1256 reg2
= get_reg_value(left
, get_regclass(expr
->left
));
1258 /* perform comparison, RHS (op1, right) and LHS (op2, EAX) */
1259 insn(opbits("cmp", right_bits
), right
, reg2
, NULL
);
1262 /* store result of operation, 0 or 1, in DL using SETcc */
1263 insn(opname
, byte_reg(reg1
), NULL
, NULL
);
1265 /* finally, store the result (DL) in a new pseudo / stack slot */
1266 new = stack_alloc(4);
1267 emit_move(reg1
, new, NULL
, "end EXPR_COMPARE");
1273 static struct storage
*emit_value(struct expression
*expr
)
1275 #if 0 /* old and slow way */
1276 struct storage
*new = stack_alloc(4);
1277 struct storage
*val
;
1279 val
= new_storage(STOR_VALUE
);
1280 val
->value
= (long long) expr
->value
;
1281 val
->flags
= STOR_WANTS_FREE
;
1282 insn("movl", val
, new, NULL
);
1286 struct storage
*val
;
1288 val
= new_storage(STOR_VALUE
);
1289 val
->value
= (long long) expr
->value
;
1291 return val
; /* FIXME: memory leak */
1295 static struct storage
*emit_divide(struct expression
*expr
, struct storage
*left
, struct storage
*right
)
1297 struct storage
*eax_edx
;
1298 struct storage
*reg
, *new;
1299 struct storage
*val
= new_storage(STOR_VALUE
);
1301 emit_comment("begin DIVIDE");
1302 eax_edx
= get_hardreg(hardreg_storage_table
+ EAX_EDX
, 1);
1305 val
->flags
= STOR_WANTS_FREE
;
1306 emit_move(val
, REG_EDX
, NULL
, NULL
);
1308 new = stack_alloc(expr
->ctype
->bit_size
/ 8);
1310 /* EAX is dividend */
1311 emit_move(left
, REG_EAX
, NULL
, NULL
);
1313 reg
= get_reg_value(right
, ®class_32
);
1316 insn("div", reg
, REG_EAX
, NULL
);
1320 if (expr
->op
== '%')
1322 emit_move(reg
, new, NULL
, NULL
);
1325 emit_comment("end DIVIDE");
1329 static struct storage
*emit_binop(struct expression
*expr
)
1331 struct storage
*left
= x86_expression(expr
->left
);
1332 struct storage
*right
= x86_expression(expr
->right
);
1333 struct storage
*new;
1334 struct storage
*dest
, *src
;
1335 const char *opname
= NULL
;
1336 const char *suffix
= NULL
;
1340 /* Divides have special register constraints */
1341 if ((expr
->op
== '/') || (expr
->op
== '%'))
1342 return emit_divide(expr
, left
, right
);
1344 is_signed
= type_is_signed(expr
->ctype
);
1362 case SPECIAL_LEFTSHIFT
:
1365 case SPECIAL_RIGHTSHIFT
:
1377 case SPECIAL_LOGICAL_AND
:
1378 warning(expr
->pos
, "bogus bitwise and for logical op (should use '2*setne + and' or something)");
1381 case SPECIAL_LOGICAL_OR
:
1382 warning(expr
->pos
, "bogus bitwise or for logical op (should use 'or + setne' or something)");
1386 error_die(expr
->pos
, "unhandled binop '%s'\n", show_special(expr
->op
));
1390 dest
= get_reg_value(right
, ®class_32
);
1391 src
= get_reg_value(left
, ®class_32
);
1392 switch (expr
->ctype
->bit_size
) {
1403 suffix
= "q"; /* FIXME */
1410 snprintf(opstr
, sizeof(opstr
), "%s%s", opname
, suffix
);
1413 insn(opstr
, src
, dest
, NULL
);
1416 /* store result in new pseudo / stack slot */
1417 new = stack_alloc(expr
->ctype
->bit_size
/ 8);
1418 emit_move(dest
, new, NULL
, "end EXPR_BINOP");
1425 static int emit_conditional_test(struct storage
*val
)
1427 struct storage
*reg
;
1428 struct storage
*target_val
;
1431 /* load result into EAX */
1432 emit_comment("begin if/conditional");
1433 reg
= get_reg_value(val
, ®class_32
);
1435 /* compare result with zero */
1436 insn("test", reg
, reg
, NULL
);
1439 /* create conditional-failed label to jump to */
1440 target_false
= new_label();
1441 target_val
= new_storage(STOR_LABEL
);
1442 target_val
->label
= target_false
;
1443 target_val
->flags
= STOR_WANTS_FREE
;
1444 insn("jz", target_val
, NULL
, NULL
);
1446 return target_false
;
1449 static int emit_conditional_end(int target_false
)
1451 struct storage
*cond_end_st
;
1454 /* finished generating code for if-true statement.
1455 * add a jump-to-end jump to avoid falling through
1456 * to the if-false statement code.
1458 cond_end
= new_label();
1459 cond_end_st
= new_storage(STOR_LABEL
);
1460 cond_end_st
->label
= cond_end
;
1461 cond_end_st
->flags
= STOR_WANTS_FREE
;
1462 insn("jmp", cond_end_st
, NULL
, NULL
);
1464 /* if we have both if-true and if-false statements,
1465 * the failed-conditional case will fall through to here
1467 emit_label(target_false
, NULL
);
1472 static void emit_if_conditional(struct statement
*stmt
)
1474 struct storage
*val
;
1477 /* emit test portion of conditional */
1478 val
= x86_expression(stmt
->if_conditional
);
1479 cond_end
= emit_conditional_test(val
);
1481 /* emit if-true statement */
1482 x86_statement(stmt
->if_true
);
1484 /* emit if-false statement, if present */
1485 if (stmt
->if_false
) {
1486 cond_end
= emit_conditional_end(cond_end
);
1487 x86_statement(stmt
->if_false
);
1490 /* end of conditional; jump target for if-true branch */
1491 emit_label(cond_end
, "end if");
1494 static struct storage
*emit_inc_dec(struct expression
*expr
, int postop
)
1496 struct storage
*addr
= x86_address_gen(expr
->unop
);
1497 struct storage
*retval
;
1500 strcpy(opname
, opbits(expr
->op
== SPECIAL_INCREMENT
? "inc" : "dec",
1501 expr
->ctype
->bit_size
));
1504 struct storage
*new = stack_alloc(4);
1506 emit_copy(new, addr
, expr
->unop
->ctype
);
1512 insn(opname
, addr
, NULL
, NULL
);
1517 static struct storage
*emit_postop(struct expression
*expr
)
1519 return emit_inc_dec(expr
, 1);
1522 static struct storage
*emit_return_stmt(struct statement
*stmt
)
1524 struct function
*f
= current_func
;
1525 struct expression
*expr
= stmt
->ret_value
;
1526 struct storage
*val
= NULL
, *jmplbl
;
1528 if (expr
&& expr
->ctype
) {
1529 val
= x86_expression(expr
);
1530 assert(val
!= NULL
);
1531 emit_move(val
, REG_EAX
, expr
->ctype
, "return");
1534 jmplbl
= new_storage(STOR_LABEL
);
1535 jmplbl
->flags
|= STOR_WANTS_FREE
;
1536 jmplbl
->label
= f
->ret_target
;
1537 insn("jmp", jmplbl
, NULL
, NULL
);
1542 static struct storage
*emit_conditional_expr(struct expression
*expr
)
1544 struct storage
*cond
, *true = NULL
, *false = NULL
;
1545 struct storage
*new = stack_alloc(expr
->ctype
->bit_size
/ 8);
1546 int target_false
, cond_end
;
1548 /* evaluate conditional */
1549 cond
= x86_expression(expr
->conditional
);
1550 target_false
= emit_conditional_test(cond
);
1552 /* handle if-true part of the expression */
1553 true = x86_expression(expr
->cond_true
);
1555 emit_copy(new, true, expr
->ctype
);
1557 cond_end
= emit_conditional_end(target_false
);
1559 /* handle if-false part of the expression */
1560 false = x86_expression(expr
->cond_false
);
1562 emit_copy(new, false, expr
->ctype
);
1564 /* end of conditional; jump target for if-true branch */
1565 emit_label(cond_end
, "end conditional");
1570 static struct storage
*emit_select_expr(struct expression
*expr
)
1572 struct storage
*cond
= x86_expression(expr
->conditional
);
1573 struct storage
*true = x86_expression(expr
->cond_true
);
1574 struct storage
*false = x86_expression(expr
->cond_false
);
1575 struct storage
*reg_cond
, *reg_true
, *reg_false
;
1576 struct storage
*new = stack_alloc(4);
1578 emit_comment("begin SELECT");
1579 reg_cond
= get_reg_value(cond
, get_regclass(expr
->conditional
));
1580 reg_true
= get_reg_value(true, get_regclass(expr
));
1581 reg_false
= get_reg_value(false, get_regclass(expr
));
1584 * Do the actual select: check the conditional for zero,
1585 * move false over true if zero
1587 insn("test", reg_cond
, reg_cond
, NULL
);
1588 insn("cmovz", reg_false
, reg_true
, NULL
);
1591 emit_move(reg_true
, new, expr
->ctype
, NULL
);
1595 emit_comment("end SELECT");
1599 static struct storage
*emit_symbol_expr_init(struct symbol
*sym
)
1601 struct expression
*expr
= sym
->initializer
;
1602 struct symbol_private
*priv
= sym
->aux
;
1605 priv
= calloc(1, sizeof(*priv
));
1609 struct storage
*new = stack_alloc(4);
1610 fprintf(stderr
, "FIXME! no value for symbol %s. creating pseudo %d (stack offset %d)\n",
1611 show_ident(sym
->ident
),
1612 new->pseudo
, new->pseudo
* 4);
1615 priv
->addr
= x86_expression(expr
);
1622 static struct storage
*emit_string_expr(struct expression
*expr
)
1624 struct function
*f
= current_func
;
1625 int label
= new_label();
1626 struct storage
*new;
1628 push_cstring(f
, expr
->string
, label
);
1630 new = new_storage(STOR_LABEL
);
1632 new->flags
= STOR_LABEL_VAL
| STOR_WANTS_FREE
;
1636 static struct storage
*emit_cast_expr(struct expression
*expr
)
1638 struct symbol
*old_type
, *new_type
;
1639 struct storage
*op
= x86_expression(expr
->cast_expression
);
1640 int oldbits
, newbits
;
1641 struct storage
*new;
1643 old_type
= expr
->cast_expression
->ctype
;
1644 new_type
= expr
->cast_type
;
1646 oldbits
= old_type
->bit_size
;
1647 newbits
= new_type
->bit_size
;
1648 if (oldbits
>= newbits
)
1651 emit_move(op
, REG_EAX
, old_type
, "begin cast ..");
1653 new = stack_alloc(newbits
/ 8);
1654 emit_move(REG_EAX
, new, new_type
, ".... end cast");
1659 static struct storage
*emit_regular_preop(struct expression
*expr
)
1661 struct storage
*target
= x86_expression(expr
->unop
);
1662 struct storage
*val
, *new = stack_alloc(4);
1663 const char *opname
= NULL
;
1667 val
= new_storage(STOR_VALUE
);
1668 val
->flags
= STOR_WANTS_FREE
;
1669 emit_move(val
, REG_EDX
, NULL
, NULL
);
1670 emit_move(target
, REG_EAX
, expr
->unop
->ctype
, NULL
);
1671 insn("test", REG_EAX
, REG_EAX
, NULL
);
1672 insn("setz", REG_DL
, NULL
, NULL
);
1673 emit_move(REG_EDX
, new, expr
->unop
->ctype
, NULL
);
1681 emit_move(target
, REG_EAX
, expr
->unop
->ctype
, NULL
);
1682 insn(opname
, REG_EAX
, NULL
, NULL
);
1683 emit_move(REG_EAX
, new, expr
->unop
->ctype
, NULL
);
1693 static void emit_case_statement(struct statement
*stmt
)
1695 emit_labelsym(stmt
->case_label
, NULL
);
1696 x86_statement(stmt
->case_statement
);
1699 static void emit_switch_statement(struct statement
*stmt
)
1701 struct storage
*val
= x86_expression(stmt
->switch_expression
);
1702 struct symbol
*sym
, *default_sym
= NULL
;
1703 struct storage
*labelsym
, *label
;
1706 emit_move(val
, REG_EAX
, stmt
->switch_expression
->ctype
, "begin case");
1709 * This is where a _real_ back-end would go through the
1710 * cases to decide whether to use a lookup table or a
1711 * series of comparisons etc
1713 FOR_EACH_PTR(stmt
->switch_case
->symbol_list
, sym
) {
1714 struct statement
*case_stmt
= sym
->stmt
;
1715 struct expression
*expr
= case_stmt
->case_expression
;
1716 struct expression
*to
= case_stmt
->case_to
;
1724 struct storage
*case_val
= new_val(expr
->value
);
1726 assert (expr
->type
== EXPR_VALUE
);
1728 insn("cmpl", case_val
, REG_EAX
, NULL
);
1731 labelsym
= new_labelsym(sym
);
1732 insn("je", labelsym
, NULL
, NULL
);
1736 label
= new_storage(STOR_LABEL
);
1737 label
->flags
|= STOR_WANTS_FREE
;
1738 label
->label
= next_test
= new_label();
1740 /* FIXME: signed/unsigned */
1741 insn("jl", label
, NULL
, NULL
);
1743 case_val
= new_val(to
->value
);
1744 insn("cmpl", case_val
, REG_EAX
, NULL
);
1746 /* TODO: implement and use refcounting... */
1747 label
= new_storage(STOR_LABEL
);
1748 label
->flags
|= STOR_WANTS_FREE
;
1749 label
->label
= next_test
;
1751 /* FIXME: signed/unsigned */
1752 insn("jg", label
, NULL
, NULL
);
1754 labelsym
= new_labelsym(sym
);
1755 insn("jmp", labelsym
, NULL
, NULL
);
1757 emit_label(next_test
, NULL
);
1760 } END_FOR_EACH_PTR(sym
);
1763 labelsym
= new_labelsym(default_sym
);
1764 insn("jmp", labelsym
, NULL
, "default");
1766 label
= new_storage(STOR_LABEL
);
1767 label
->flags
|= STOR_WANTS_FREE
;
1768 label
->label
= switch_end
= new_label();
1769 insn("jmp", label
, NULL
, "goto end of switch");
1772 x86_statement(stmt
->switch_statement
);
1774 if (stmt
->switch_break
->used
)
1775 emit_labelsym(stmt
->switch_break
, NULL
);
1778 emit_label(switch_end
, NULL
);
1781 static void x86_struct_member(struct symbol
*sym
)
1783 printf("\t%s:%d:%ld at offset %ld.%d", show_ident(sym
->ident
), sym
->bit_size
, sym
->ctype
.alignment
, sym
->offset
, sym
->bit_offset
);
1787 static void x86_symbol(struct symbol
*sym
)
1789 struct symbol
*type
;
1794 type
= sym
->ctype
.base_type
;
1799 * Show actual implementation information
1801 switch (type
->type
) {
1804 if (sym
->initializer
)
1807 emit_array_noinit(sym
);
1811 if (sym
->initializer
) {
1812 emit_object_pre(show_ident(sym
->ident
),
1813 sym
->ctype
.modifiers
,
1814 sym
->ctype
.alignment
,
1816 emit_scalar(sym
->initializer
, sym
->bit_size
);
1819 emit_scalar_noinit(sym
);
1824 struct symbol
*member
;
1827 FOR_EACH_PTR(type
->symbol_list
, member
) {
1828 x86_struct_member(member
);
1829 } END_FOR_EACH_PTR(member
);
1835 struct statement
*stmt
= type
->stmt
;
1838 x86_statement(stmt
);
1839 emit_func_post(sym
);
1848 if (sym
->initializer
&& (type
->type
!= SYM_BASETYPE
) &&
1849 (type
->type
!= SYM_ARRAY
)) {
1851 x86_expression(sym
->initializer
);
1855 static void x86_symbol_init(struct symbol
*sym
);
1857 static void x86_symbol_decl(struct symbol_list
*syms
)
1860 FOR_EACH_PTR(syms
, sym
) {
1861 x86_symbol_init(sym
);
1862 } END_FOR_EACH_PTR(sym
);
1865 static void loopstk_push(int cont_lbl
, int loop_bottom_lbl
)
1867 struct function
*f
= current_func
;
1868 struct loop_stack
*ls
;
1870 ls
= malloc(sizeof(*ls
));
1871 ls
->continue_lbl
= cont_lbl
;
1872 ls
->loop_bottom_lbl
= loop_bottom_lbl
;
1873 ls
->next
= f
->loop_stack
;
1877 static void loopstk_pop(void)
1879 struct function
*f
= current_func
;
1880 struct loop_stack
*ls
;
1882 assert(f
->loop_stack
!= NULL
);
1884 f
->loop_stack
= f
->loop_stack
->next
;
1888 static int loopstk_break(void)
1890 return current_func
->loop_stack
->loop_bottom_lbl
;
1893 static int loopstk_continue(void)
1895 return current_func
->loop_stack
->continue_lbl
;
1898 static void emit_loop(struct statement
*stmt
)
1900 struct statement
*pre_statement
= stmt
->iterator_pre_statement
;
1901 struct expression
*pre_condition
= stmt
->iterator_pre_condition
;
1902 struct statement
*statement
= stmt
->iterator_statement
;
1903 struct statement
*post_statement
= stmt
->iterator_post_statement
;
1904 struct expression
*post_condition
= stmt
->iterator_post_condition
;
1905 int loop_top
= 0, loop_bottom
, loop_continue
;
1906 int have_bottom
= 0;
1907 struct storage
*val
;
1909 loop_bottom
= new_label();
1910 loop_continue
= new_label();
1911 loopstk_push(loop_continue
, loop_bottom
);
1913 x86_symbol_decl(stmt
->iterator_syms
);
1914 x86_statement(pre_statement
);
1915 if (!post_condition
|| post_condition
->type
!= EXPR_VALUE
|| post_condition
->value
) {
1916 loop_top
= new_label();
1917 emit_label(loop_top
, "loop top");
1919 if (pre_condition
) {
1920 if (pre_condition
->type
== EXPR_VALUE
) {
1921 if (!pre_condition
->value
) {
1922 struct storage
*lbv
;
1923 lbv
= new_storage(STOR_LABEL
);
1924 lbv
->label
= loop_bottom
;
1925 lbv
->flags
= STOR_WANTS_FREE
;
1926 insn("jmp", lbv
, NULL
, "go to loop bottom");
1930 struct storage
*lbv
= new_storage(STOR_LABEL
);
1931 lbv
->label
= loop_bottom
;
1932 lbv
->flags
= STOR_WANTS_FREE
;
1935 val
= x86_expression(pre_condition
);
1937 emit_move(val
, REG_EAX
, NULL
, "loop pre condition");
1938 insn("test", REG_EAX
, REG_EAX
, NULL
);
1939 insn("jz", lbv
, NULL
, NULL
);
1942 x86_statement(statement
);
1943 if (stmt
->iterator_continue
->used
)
1944 emit_label(loop_continue
, "'continue' iterator");
1945 x86_statement(post_statement
);
1946 if (!post_condition
) {
1947 struct storage
*lbv
= new_storage(STOR_LABEL
);
1948 lbv
->label
= loop_top
;
1949 lbv
->flags
= STOR_WANTS_FREE
;
1950 insn("jmp", lbv
, NULL
, "go to loop top");
1951 } else if (post_condition
->type
== EXPR_VALUE
) {
1952 if (post_condition
->value
) {
1953 struct storage
*lbv
= new_storage(STOR_LABEL
);
1954 lbv
->label
= loop_top
;
1955 lbv
->flags
= STOR_WANTS_FREE
;
1956 insn("jmp", lbv
, NULL
, "go to loop top");
1959 struct storage
*lbv
= new_storage(STOR_LABEL
);
1960 lbv
->label
= loop_top
;
1961 lbv
->flags
= STOR_WANTS_FREE
;
1963 val
= x86_expression(post_condition
);
1965 emit_move(val
, REG_EAX
, NULL
, "loop post condition");
1966 insn("test", REG_EAX
, REG_EAX
, NULL
);
1967 insn("jnz", lbv
, NULL
, NULL
);
1969 if (have_bottom
|| stmt
->iterator_break
->used
)
1970 emit_label(loop_bottom
, "loop bottom");
1976 * Print out a statement
1978 static struct storage
*x86_statement(struct statement
*stmt
)
1982 switch (stmt
->type
) {
1986 return emit_return_stmt(stmt
);
1987 case STMT_DECLARATION
:
1988 x86_symbol_decl(stmt
->declaration
);
1990 case STMT_COMPOUND
: {
1991 struct statement
*s
;
1992 struct storage
*last
= NULL
;
1994 FOR_EACH_PTR(stmt
->stmts
, s
) {
1995 last
= x86_statement(s
);
1996 } END_FOR_EACH_PTR(s
);
2001 case STMT_EXPRESSION
:
2002 return x86_expression(stmt
->expression
);
2004 emit_if_conditional(stmt
);
2008 emit_case_statement(stmt
);
2011 emit_switch_statement(stmt
);
2022 printf(".L%p:\n", stmt
->label_identifier
);
2023 x86_statement(stmt
->label_statement
);
2027 if (stmt
->goto_expression
) {
2028 struct storage
*val
= x86_expression(stmt
->goto_expression
);
2029 printf("\tgoto *v%d\n", val
->pseudo
);
2030 } else if (!strcmp("break", show_ident(stmt
->goto_label
->ident
))) {
2031 struct storage
*lbv
= new_storage(STOR_LABEL
);
2032 lbv
->label
= loopstk_break();
2033 lbv
->flags
= STOR_WANTS_FREE
;
2034 insn("jmp", lbv
, NULL
, "'break'; go to loop bottom");
2035 } else if (!strcmp("continue", show_ident(stmt
->goto_label
->ident
))) {
2036 struct storage
*lbv
= new_storage(STOR_LABEL
);
2037 lbv
->label
= loopstk_continue();
2038 lbv
->flags
= STOR_WANTS_FREE
;
2039 insn("jmp", lbv
, NULL
, "'continue'; go to loop top");
2041 struct storage
*labelsym
= new_labelsym(stmt
->goto_label
);
2042 insn("jmp", labelsym
, NULL
, NULL
);
2046 printf("\tasm( .... )\n");
2052 static struct storage
*x86_call_expression(struct expression
*expr
)
2054 struct function
*f
= current_func
;
2055 struct symbol
*direct
;
2056 struct expression
*arg
, *fn
;
2057 struct storage
*retval
, *fncall
;
2062 warning(expr
->pos
, "\tcall with no type!");
2067 FOR_EACH_PTR_REVERSE(expr
->args
, arg
) {
2068 struct storage
*new = x86_expression(arg
);
2069 int size
= arg
->ctype
->bit_size
;
2072 * FIXME: i386 SysV ABI dictates that values
2073 * smaller than 32 bits should be placed onto
2074 * the stack as 32-bit objects. We should not
2075 * blindly do a 32-bit push on objects smaller
2080 insn("pushl", new, NULL
,
2081 !framesize
? "begin function call" : NULL
);
2083 framesize
+= bits_to_bytes(size
);
2084 } END_FOR_EACH_PTR_REVERSE(arg
);
2088 /* Remove dereference, if any */
2090 if (fn
->type
== EXPR_PREOP
) {
2091 if (fn
->unop
->type
== EXPR_SYMBOL
) {
2092 struct symbol
*sym
= fn
->unop
->symbol
;
2093 if (sym
->ctype
.base_type
->type
== SYM_FN
)
2098 struct storage
*direct_stor
= new_storage(STOR_SYM
);
2099 direct_stor
->flags
|= STOR_WANTS_FREE
;
2100 direct_stor
->sym
= direct
;
2101 insn("call", direct_stor
, NULL
, NULL
);
2103 fncall
= x86_expression(fn
);
2104 emit_move(fncall
, REG_EAX
, fn
->ctype
, NULL
);
2106 strcpy(s
, "\tcall\t*%eax\n");
2107 push_text_atom(f
, s
);
2110 /* FIXME: pay attention to BITS_IN_POINTER */
2112 struct storage
*val
= new_storage(STOR_VALUE
);
2113 val
->value
= (long long) framesize
;
2114 val
->flags
= STOR_WANTS_FREE
;
2115 insn("addl", val
, REG_ESP
, NULL
);
2118 retval
= stack_alloc(4);
2119 emit_move(REG_EAX
, retval
, NULL
, "end function call");
2124 static struct storage
*x86_address_gen(struct expression
*expr
)
2126 struct function
*f
= current_func
;
2127 struct storage
*addr
;
2128 struct storage
*new;
2131 addr
= x86_expression(expr
->unop
);
2132 if (expr
->unop
->type
== EXPR_SYMBOL
)
2135 emit_move(addr
, REG_EAX
, NULL
, "begin deref ..");
2137 /* FIXME: operand size */
2138 strcpy(s
, "\tmovl\t(%eax), %ecx\n");
2139 push_text_atom(f
, s
);
2141 new = stack_alloc(4);
2142 emit_move(REG_ECX
, new, NULL
, ".... end deref");
2147 static struct storage
*x86_assignment(struct expression
*expr
)
2149 struct expression
*target
= expr
->left
;
2150 struct storage
*val
, *addr
;
2155 val
= x86_expression(expr
->right
);
2156 addr
= x86_address_gen(target
);
2158 switch (val
->type
) {
2159 /* copy, where both operands are memory */
2162 emit_copy(addr
, val
, expr
->ctype
);
2165 /* copy, one or zero operands are memory */
2170 emit_move(val
, addr
, expr
->left
->ctype
, NULL
);
2180 static int x86_initialization(struct symbol
*sym
, struct expression
*expr
)
2182 struct storage
*val
, *addr
;
2188 bits
= expr
->ctype
->bit_size
;
2189 val
= x86_expression(expr
);
2190 addr
= x86_symbol_expr(sym
);
2191 // FIXME! The "target" expression is for bitfield store information.
2192 // Leave it NULL, which works fine.
2193 emit_store(NULL
, addr
, val
, bits
);
2197 static struct storage
*x86_access(struct expression
*expr
)
2199 return x86_address_gen(expr
);
2202 static struct storage
*x86_preop(struct expression
*expr
)
2205 * '*' is an lvalue access, and is fundamentally different
2206 * from an arithmetic operation. Maybe it should have an
2207 * expression type of its own..
2209 if (expr
->op
== '*')
2210 return x86_access(expr
);
2211 if (expr
->op
== SPECIAL_INCREMENT
|| expr
->op
== SPECIAL_DECREMENT
)
2212 return emit_inc_dec(expr
, 0);
2213 return emit_regular_preop(expr
);
2216 static struct storage
*x86_symbol_expr(struct symbol
*sym
)
2218 struct storage
*new = stack_alloc(4);
2220 if (sym
->ctype
.modifiers
& (MOD_TOPLEVEL
| MOD_EXTERN
| MOD_STATIC
)) {
2221 printf("\tmovi.%d\t\tv%d,$%s\n", bits_in_pointer
, new->pseudo
, show_ident(sym
->ident
));
2224 if (sym
->ctype
.modifiers
& MOD_ADDRESSABLE
) {
2225 printf("\taddi.%d\t\tv%d,vFP,$%lld\n", bits_in_pointer
, new->pseudo
, sym
->value
);
2228 printf("\taddi.%d\t\tv%d,vFP,$offsetof(%s:%p)\n", bits_in_pointer
, new->pseudo
, show_ident(sym
->ident
), sym
);
2232 static void x86_symbol_init(struct symbol
*sym
)
2234 struct symbol_private
*priv
= sym
->aux
;
2235 struct expression
*expr
= sym
->initializer
;
2236 struct storage
*new;
2239 new = x86_expression(expr
);
2241 new = stack_alloc(sym
->bit_size
/ 8);
2244 priv
= calloc(1, sizeof(*priv
));
2246 /* FIXME: leak! we don't free... */
2247 /* (well, we don't free symbols either) */
2253 static int type_is_signed(struct symbol
*sym
)
2255 if (sym
->type
== SYM_NODE
)
2256 sym
= sym
->ctype
.base_type
;
2257 if (sym
->type
== SYM_PTR
)
2259 return !(sym
->ctype
.modifiers
& MOD_UNSIGNED
);
2262 static struct storage
*x86_label_expr(struct expression
*expr
)
2264 struct storage
*new = stack_alloc(4);
2265 printf("\tmovi.%d\t\tv%d,.L%p\n", bits_in_pointer
, new->pseudo
, expr
->label_symbol
);
2269 static struct storage
*x86_statement_expr(struct expression
*expr
)
2271 return x86_statement(expr
->statement
);
2274 static int x86_position_expr(struct expression
*expr
, struct symbol
*base
)
2276 struct storage
*new = x86_expression(expr
->init_expr
);
2277 struct symbol
*ctype
= expr
->init_expr
->ctype
;
2279 printf("\tinsert v%d at [%d:%d] of %s\n", new->pseudo
,
2280 expr
->init_offset
, ctype
->bit_offset
,
2281 show_ident(base
->ident
));
2285 static void x86_initializer_expr(struct expression
*expr
, struct symbol
*ctype
)
2287 struct expression
*entry
;
2289 FOR_EACH_PTR(expr
->expr_list
, entry
) {
2290 // Nested initializers have their positions already
2291 // recursively calculated - just output them too
2292 if (entry
->type
== EXPR_INITIALIZER
) {
2293 x86_initializer_expr(entry
, ctype
);
2297 // Ignore initializer indexes and identifiers - the
2298 // evaluator has taken them into account
2299 if (entry
->type
== EXPR_IDENTIFIER
|| entry
->type
== EXPR_INDEX
)
2301 if (entry
->type
== EXPR_POS
) {
2302 x86_position_expr(entry
, ctype
);
2305 x86_initialization(ctype
, entry
);
2306 } END_FOR_EACH_PTR(entry
);
2310 * Print out an expression. Return the pseudo that contains the
2313 static struct storage
*x86_expression(struct expression
*expr
)
2319 struct position
*pos
= &expr
->pos
;
2320 printf("\tno type at %s:%d:%d\n",
2321 stream_name(pos
->stream
),
2322 pos
->line
, pos
->pos
);
2326 switch (expr
->type
) {
2330 return x86_call_expression(expr
);
2332 case EXPR_ASSIGNMENT
:
2333 return x86_assignment(expr
);
2336 return emit_compare(expr
);
2340 return emit_binop(expr
);
2342 return x86_preop(expr
);
2344 return emit_postop(expr
);
2346 return emit_symbol_expr_init(expr
->symbol
);
2350 warning(expr
->pos
, "invalid expression after evaluation");
2353 case EXPR_FORCE_CAST
:
2354 case EXPR_IMPLIED_CAST
:
2355 return emit_cast_expr(expr
);
2357 return emit_value(expr
);
2359 return emit_string_expr(expr
);
2360 case EXPR_INITIALIZER
:
2361 x86_initializer_expr(expr
, expr
->ctype
);
2364 return emit_select_expr(expr
);
2365 case EXPR_CONDITIONAL
:
2366 return emit_conditional_expr(expr
);
2367 case EXPR_STATEMENT
:
2368 return x86_statement_expr(expr
);
2370 return x86_label_expr(expr
);
2372 // None of these should exist as direct expressions: they are only
2373 // valid as sub-expressions of initializers.
2375 warning(expr
->pos
, "unable to show plain initializer position expression");
2377 case EXPR_IDENTIFIER
:
2378 warning(expr
->pos
, "unable to show identifier expression");
2381 warning(expr
->pos
, "unable to show index expression");
2384 warning(expr
->pos
, "unable to show type expression");
2387 warning(expr
->pos
, "floating point support is not implemented");