Let compile-i386 know about more registers.
[smatch.git] / compile-i386.c
blob3888a9db7ac25aa28883078ec431c278312d901b
1 /*
2 * sparse/compile-i386.c
4 * Copyright (C) 2003 Transmeta Corp.
5 * 2003 Linus Torvalds
6 * Copyright 2003 Jeff Garzik
8 * Licensed under the Open Software License version 1.1
10 * x86 backend
12 * TODO list:
13 * in general, any non-32bit SYM_BASETYPE is unlikely to work.
14 * complex initializers
15 * bitfields
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.
19 * labels / goto
20 * any function argument that isn't 32 bits (or promoted to such)
21 * inline asm
22 * floating point
25 #include <stdarg.h>
26 #include <stdlib.h>
27 #include <stdio.h>
28 #include <string.h>
29 #include <ctype.h>
30 #include <unistd.h>
31 #include <fcntl.h>
32 #include <assert.h>
34 #include "lib.h"
35 #include "token.h"
36 #include "parse.h"
37 #include "symbol.h"
38 #include "scope.h"
39 #include "expression.h"
40 #include "target.h"
41 #include "compile.h"
43 struct textbuf {
44 unsigned int len; /* does NOT include terminating null */
45 char *text;
46 struct textbuf *next;
47 struct textbuf *prev;
50 struct loop_stack {
51 int continue_lbl;
52 int loop_bottom_lbl;
53 struct loop_stack *next;
56 struct function {
57 int stack_size;
58 int pseudo_nr;
59 struct ptr_list *pseudo_list;
60 struct ptr_list *atom_list;
61 struct ptr_list *str_list;
62 struct loop_stack *loop_stack;
63 struct symbol **argv;
64 unsigned int argc;
65 int ret_target;
68 enum storage_type {
69 STOR_PSEUDO, /* variable stored on the stack */
70 STOR_ARG, /* function argument */
71 STOR_SYM, /* a symbol we can directly ref in the asm */
72 STOR_REG, /* scratch register */
73 STOR_VALUE, /* integer constant */
74 STOR_LABEL, /* label / jump target */
75 STOR_LABELSYM, /* label generated from symbol's pointer value */
78 struct reg_info {
79 const char *name;
82 struct storage {
83 enum storage_type type;
84 unsigned long flags;
86 /* STOR_REG */
87 struct reg_info *reg;
89 union {
90 /* STOR_PSEUDO */
91 struct {
92 int pseudo;
93 int offset;
94 int size;
96 /* STOR_ARG */
97 struct {
98 int idx;
100 /* STOR_SYM */
101 struct {
102 struct symbol *sym;
104 /* STOR_VALUE */
105 struct {
106 long long value;
108 /* STOR_LABEL */
109 struct {
110 int label;
112 /* STOR_LABELSYM */
113 struct {
114 struct symbol *labelsym;
119 enum {
120 STOR_LABEL_VAL = (1 << 0),
121 STOR_WANTS_FREE = (1 << 1),
124 struct symbol_private {
125 struct storage *addr;
128 enum atom_type {
129 ATOM_TEXT,
130 ATOM_INSN,
131 ATOM_CSTR,
134 struct atom {
135 enum atom_type type;
136 union {
137 /* stuff for text */
138 struct {
139 char *text;
140 unsigned int text_len; /* w/o terminating null */
143 /* stuff for insns */
144 struct {
145 char insn[32];
146 char comment[40];
147 struct storage *op1;
148 struct storage *op2;
151 /* stuff for C strings */
152 struct {
153 struct string *string;
154 int label;
160 struct function *current_func = NULL;
161 struct textbuf *unit_post_text = NULL;
162 static const char *current_section;
164 enum registers {
165 NOREG,
166 AL, DL, CL, BL, AH, DH, CH, BH, // 8-bit
167 AX, DX, CX, BX, SI, DI, BP, SP, // 16-bit
168 EAX, EDX, ECX, EBX, ESI, EDI, EBP, ESP, // 32-bit
169 EAX_EDX, ECX_EBX, ESI_EDI, // 64-bit
172 #define REGINFO(nr, str, aliases...) [nr] = { .name = str }
174 static struct reg_info reg_info_table[] = {
175 REGINFO( AL, "%al", AX, EAX, EAX_EDX),
176 REGINFO( DL, "%dl", DX, EDX, EAX_EDX),
177 REGINFO( CL, "%cl", CX, ECX, ECX_EBX),
178 REGINFO( BL, "%bl", BX, EBX, ECX_EBX),
179 REGINFO( AH, "%ah", AX, EAX, EAX_EDX),
180 REGINFO( DH, "%dh", DX, EDX, EAX_EDX),
181 REGINFO( CH, "%ch", CX, ECX, ECX_EBX),
182 REGINFO( BH, "%bh", BX, EBX, ECX_EBX),
183 REGINFO( AX, "%ax", AL, AH, EAX, EAX_EDX),
184 REGINFO( DX, "%dx", DL, DH, EDX, EAX_EDX),
185 REGINFO( CX, "%cx", CL, CH, ECX, ECX_EBX),
186 REGINFO( BX, "%bx", BL, BH, EBX, ECX_EBX),
187 REGINFO( SI, "%si", ESI, ESI_EDI),
188 REGINFO( DI, "%di", EDI, ESI_EDI),
189 REGINFO( BP, "%bp", EBP),
190 REGINFO( SP, "%sp", ESP),
191 REGINFO(EAX, "%eax", AL, AH, AX, EAX_EDX),
192 REGINFO(EDX, "%edx", DL, DH, DX, EAX_EDX),
193 REGINFO(ECX, "%ecx", CL, CH, CX, ECX_EBX),
194 REGINFO(EBX, "%ebx", BL, BH, BX, ECX_EBX),
195 REGINFO(ESI, "%esi", SI, ESI_EDI),
196 REGINFO(EDI, "%edi", DI, ESI_EDI),
197 REGINFO(EBP, "%ebp", BP),
198 REGINFO(ESP, "%esp", SP),
199 REGINFO(EAX_EDX, "%eax:%edx", AL, AH, AX, EAX, DL, DH, DX, EDX),
200 REGINFO(ECX_EBX, "%ecx:%ebx", CL, CH, CX, ECX, BL, BH, BX, EBX),
201 REGINFO(ESI_EDI, "%esi:%edi", SI, ESI, DI, EDI),
204 #define REGSTORAGE(nr) [nr] = { .type = STOR_REG, .reg = reg_info_table + (nr) }
206 static struct storage hardreg_storage_table[] = {
207 REGSTORAGE(AL), REGSTORAGE(DL), REGSTORAGE(CL), REGSTORAGE(BL),
208 REGSTORAGE(AH), REGSTORAGE(DH), REGSTORAGE(CH), REGSTORAGE(BH),
209 REGSTORAGE(AX), REGSTORAGE(DX), REGSTORAGE(CX), REGSTORAGE(BX),
210 REGSTORAGE(SI), REGSTORAGE(DI), REGSTORAGE(BP), REGSTORAGE(SP),
211 REGSTORAGE(EAX), REGSTORAGE(EDX), REGSTORAGE(ECX), REGSTORAGE(EBX),
212 REGSTORAGE(ESI), REGSTORAGE(EDI), REGSTORAGE(EBP), REGSTORAGE(ESP),
213 REGSTORAGE(EAX_EDX), REGSTORAGE(ECX_EBX), REGSTORAGE(ESI_EDI),
216 #define REG_EAX (&hardreg_storage_table[EAX])
217 #define REG_ECX (&hardreg_storage_table[ECX])
218 #define REG_EDX (&hardreg_storage_table[EDX])
219 #define REG_ESP (&hardreg_storage_table[ESP])
220 #define REG_DL (&hardreg_storage_table[DL])
221 #define REG_DX (&hardreg_storage_table[DX])
222 #define REG_AL (&hardreg_storage_table[AL])
223 #define REG_AX (&hardreg_storage_table[AX])
225 static void emit_move(struct storage *src, struct storage *dest,
226 struct symbol *ctype, const char *comment);
227 static int type_is_signed(struct symbol *sym);
228 static struct storage *x86_address_gen(struct expression *expr);
229 static struct storage *x86_symbol_expr(struct symbol *sym);
230 static void x86_symbol(struct symbol *sym);
231 static struct storage *x86_statement(struct statement *stmt);
232 static struct storage *x86_expression(struct expression *expr);
235 static struct storage *temp_from_bits(unsigned int bit_size)
237 switch(bit_size) {
238 case 8: return REG_AL;
239 case 16: return REG_AX;
240 case 32: return REG_EAX;
242 case 64: /* FIXME */
243 default:
244 assert(0);
245 break;
248 return NULL;
251 static inline unsigned int pseudo_offset(struct storage *s)
253 if (s->type != STOR_PSEUDO)
254 return 123456; /* intentionally bogus value */
256 return s->offset;
259 static inline unsigned int arg_offset(struct storage *s)
261 if (s->type != STOR_ARG)
262 return 123456; /* intentionally bogus value */
264 /* FIXME: this is wrong wrong wrong */
265 return current_func->stack_size + ((1 + s->idx) * 4);
268 static const char *pretty_offset(int ofs)
270 static char esp_buf[64];
272 if (ofs)
273 sprintf(esp_buf, "%d(%%esp)", ofs);
274 else
275 strcpy(esp_buf, "(%esp)");
277 return esp_buf;
280 static void stor_sym_init(struct symbol *sym)
282 struct storage *stor;
283 struct symbol_private *priv;
285 priv = calloc(1, sizeof(*priv) + sizeof(*stor));
286 if (!priv)
287 die("OOM in stor_sym_init");
289 stor = (struct storage *) (priv + 1);
291 priv->addr = stor;
292 stor->type = STOR_SYM;
293 stor->sym = sym;
296 static const char *stor_op_name(struct storage *s)
298 static char name[32];
300 switch (s->type) {
301 case STOR_PSEUDO:
302 strcpy(name, pretty_offset((int) pseudo_offset(s)));
303 break;
304 case STOR_ARG:
305 strcpy(name, pretty_offset((int) arg_offset(s)));
306 break;
307 case STOR_SYM:
308 strcpy(name, show_ident(s->sym->ident));
309 break;
310 case STOR_REG:
311 strcpy(name, s->reg->name);
312 break;
313 case STOR_VALUE:
314 sprintf(name, "$%Ld", s->value);
315 break;
316 case STOR_LABEL:
317 sprintf(name, "%s.L%d", s->flags & STOR_LABEL_VAL ? "$" : "",
318 s->label);
319 break;
320 case STOR_LABELSYM:
321 sprintf(name, "%s.LS%p", s->flags & STOR_LABEL_VAL ? "$" : "",
322 s->labelsym);
323 break;
326 return name;
329 static struct atom *new_atom(enum atom_type type)
331 struct atom *atom;
333 atom = calloc(1, sizeof(*atom)); /* TODO: chunked alloc */
334 if (!atom)
335 die("nuclear OOM");
337 atom->type = type;
339 return atom;
342 static inline void push_cstring(struct function *f, struct string *str,
343 int label)
345 struct atom *atom;
347 atom = new_atom(ATOM_CSTR);
348 atom->string = str;
349 atom->label = label;
351 add_ptr_list(&f->str_list, atom); /* note: _not_ atom_list */
354 static inline void push_atom(struct function *f, struct atom *atom)
356 add_ptr_list(&f->atom_list, atom);
359 static void push_text_atom(struct function *f, const char *text)
361 struct atom *atom = new_atom(ATOM_TEXT);
363 atom->text = strdup(text);
364 atom->text_len = strlen(text);
366 push_atom(f, atom);
369 static struct storage *new_storage(enum storage_type type)
371 struct storage *stor;
373 stor = calloc(1, sizeof(*stor));
374 if (!stor)
375 die("OOM in new_storage");
377 stor->type = type;
379 return stor;
382 static struct storage *stack_alloc(int n_bytes)
384 struct function *f = current_func;
385 struct storage *stor;
387 assert(f != NULL);
389 stor = new_storage(STOR_PSEUDO);
390 stor->type = STOR_PSEUDO;
391 stor->pseudo = f->pseudo_nr;
392 stor->offset = f->stack_size; /* FIXME: stack req. natural align */
393 stor->size = n_bytes;
394 f->stack_size += n_bytes;
395 f->pseudo_nr++;
397 add_ptr_list(&f->pseudo_list, stor);
399 return stor;
402 static struct storage *new_labelsym(struct symbol *sym)
404 struct storage *stor;
406 stor = new_storage(STOR_LABELSYM);
408 if (stor) {
409 stor->flags |= STOR_WANTS_FREE;
410 stor->labelsym = sym;
413 return stor;
416 static struct storage *new_val(long long value)
418 struct storage *stor;
420 stor = new_storage(STOR_VALUE);
422 if (stor) {
423 stor->flags |= STOR_WANTS_FREE;
424 stor->value = value;
427 return stor;
430 static int new_label(void)
432 static int label = 0;
433 return ++label;
436 static void textbuf_push(struct textbuf **buf_p, const char *text)
438 struct textbuf *tmp, *list = *buf_p;
439 unsigned int text_len = strlen(text);
440 unsigned int alloc_len = text_len + 1 + sizeof(*list);
442 tmp = calloc(1, alloc_len);
443 if (!tmp)
444 die("OOM on textbuf alloc");
446 tmp->text = ((void *) tmp) + sizeof(*tmp);
447 memcpy(tmp->text, text, text_len + 1);
448 tmp->len = text_len;
450 /* add to end of list */
451 if (!list) {
452 list = tmp;
453 tmp->prev = tmp;
454 } else {
455 tmp->prev = list->prev;
456 tmp->prev->next = tmp;
457 list->prev = tmp;
459 tmp->next = list;
461 *buf_p = list;
464 static void textbuf_emit(struct textbuf **buf_p)
466 struct textbuf *tmp, *list = *buf_p;
468 while (list) {
469 tmp = list;
470 if (tmp->next == tmp)
471 list = NULL;
472 else {
473 tmp->prev->next = tmp->next;
474 tmp->next->prev = tmp->prev;
475 list = tmp->next;
478 fputs(tmp->text, stdout);
480 free(tmp);
483 *buf_p = list;
486 static void insn(const char *insn, struct storage *op1, struct storage *op2,
487 const char *comment_in)
489 struct function *f = current_func;
490 struct atom *atom = new_atom(ATOM_INSN);
492 assert(insn != NULL);
494 strcpy(atom->insn, insn);
495 if (comment_in && (*comment_in))
496 strncpy(atom->comment, comment_in,
497 sizeof(atom->comment) - 1);
499 atom->op1 = op1;
500 atom->op2 = op2;
502 push_atom(f, atom);
505 static void emit_label (int label, const char *comment)
507 struct function *f = current_func;
508 char s[64];
510 if (!comment)
511 sprintf(s, ".L%d:\n", label);
512 else
513 sprintf(s, ".L%d:\t\t\t\t\t# %s\n", label, comment);
515 push_text_atom(f, s);
518 static void emit_labelsym (struct symbol *sym, const char *comment)
520 struct function *f = current_func;
521 char s[64];
523 if (!comment)
524 sprintf(s, ".LS%p:\n", sym);
525 else
526 sprintf(s, ".LS%p:\t\t\t\t# %s\n", sym, comment);
528 push_text_atom(f, s);
531 void emit_unit_begin(const char *basename)
533 printf("\t.file\t\"%s\"\n", basename);
536 void emit_unit_end(void)
538 textbuf_emit(&unit_post_text);
539 printf("\t.ident\t\"sparse silly x86 backend (built %s)\"\n", __DATE__);
542 /* conditionally switch sections */
543 static void emit_section(const char *s)
545 if (s == current_section)
546 return;
547 if (current_section && (!strcmp(s, current_section)))
548 return;
550 printf("\t%s\n", s);
551 current_section = s;
554 static void emit_insn_atom(struct function *f, struct atom *atom)
556 char s[128];
557 char comment[64];
558 struct storage *op1 = atom->op1;
559 struct storage *op2 = atom->op2;
561 if (atom->comment[0])
562 sprintf(comment, "\t\t# %s", atom->comment);
563 else
564 comment[0] = 0;
566 if (atom->op2) {
567 char tmp[16];
568 strcpy(tmp, stor_op_name(op1));
569 sprintf(s, "\t%s\t%s, %s%s\n",
570 atom->insn, tmp, stor_op_name(op2), comment);
571 } else if (atom->op1)
572 sprintf(s, "\t%s\t%s%s%s\n",
573 atom->insn, stor_op_name(op1),
574 comment[0] ? "\t" : "", comment);
575 else
576 sprintf(s, "\t%s\t%s%s\n",
577 atom->insn,
578 comment[0] ? "\t\t" : "", comment);
580 write(STDOUT_FILENO, s, strlen(s));
583 static void emit_atom_list(struct function *f)
585 struct atom *atom;
587 FOR_EACH_PTR(f->atom_list, atom) {
588 switch (atom->type) {
589 case ATOM_TEXT: {
590 ssize_t rc = write(STDOUT_FILENO, atom->text,
591 atom->text_len);
592 (void) rc; /* FIXME */
593 break;
595 case ATOM_INSN:
596 emit_insn_atom(f, atom);
597 break;
598 case ATOM_CSTR:
599 assert(0);
600 break;
602 } END_FOR_EACH_PTR;
605 static void emit_string_list(struct function *f)
607 struct atom *atom;
609 emit_section(".section\t.rodata");
611 FOR_EACH_PTR(f->str_list, atom) {
612 /* FIXME: escape " in string */
613 printf(".L%d:\n", atom->label);
614 printf("\t.string\t%s\n", show_string(atom->string));
616 free(atom);
617 } END_FOR_EACH_PTR;
620 static void func_cleanup(struct function *f)
622 struct storage *stor;
623 struct atom *atom;
625 FOR_EACH_PTR(f->pseudo_list, stor) {
626 free(stor);
627 } END_FOR_EACH_PTR;
629 FOR_EACH_PTR(f->atom_list, atom) {
630 if ((atom->type == ATOM_TEXT) && (atom->text))
631 free(atom->text);
632 if (atom->op1 && (atom->op1->flags & STOR_WANTS_FREE))
633 free(atom->op1);
634 if (atom->op2 && (atom->op2->flags & STOR_WANTS_FREE))
635 free(atom->op2);
636 free(atom);
637 } END_FOR_EACH_PTR;
639 free_ptr_list(&f->pseudo_list);
640 free(f);
643 /* function prologue */
644 static void emit_func_pre(struct symbol *sym)
646 struct function *f;
647 struct symbol *arg;
648 unsigned int i, argc = 0, alloc_len;
649 unsigned char *mem;
650 struct symbol_private *privbase;
651 struct storage *storage_base;
652 struct symbol *base_type = sym->ctype.base_type;
654 FOR_EACH_PTR(base_type->arguments, arg) {
655 argc++;
656 } END_FOR_EACH_PTR;
658 alloc_len =
659 sizeof(*f) +
660 (argc * sizeof(struct symbol *)) +
661 (argc * sizeof(struct symbol_private)) +
662 (argc * sizeof(struct storage));
663 mem = calloc(1, alloc_len);
664 if (!mem)
665 die("OOM on func info");
667 f = (struct function *) mem;
668 mem += sizeof(*f);
669 f->argv = (struct symbol **) mem;
670 mem += (argc * sizeof(struct symbol *));
671 privbase = (struct symbol_private *) mem;
672 mem += (argc * sizeof(struct symbol_private));
673 storage_base = (struct storage *) mem;
675 f->argc = argc;
676 f->ret_target = new_label();
678 i = 0;
679 FOR_EACH_PTR(base_type->arguments, arg) {
680 f->argv[i] = arg;
681 arg->aux = &privbase[i];
682 storage_base[i].type = STOR_ARG;
683 storage_base[i].idx = i;
684 privbase[i].addr = &storage_base[i];
685 i++;
686 } END_FOR_EACH_PTR;
688 assert(current_func == NULL);
689 current_func = f;
692 /* function epilogue */
693 static void emit_func_post(struct symbol *sym)
695 const char *name = show_ident(sym->ident);
696 struct function *f = current_func;
697 int stack_size = f->stack_size;
699 if (f->str_list)
700 emit_string_list(f);
702 /* function prologue */
703 emit_section(".text");
704 if ((sym->ctype.modifiers & MOD_STATIC) == 0)
705 printf(".globl %s\n", name);
706 printf("\t.type\t%s, @function\n", name);
707 printf("%s:\n", name);
709 if (stack_size) {
710 char pseudo_const[16];
712 sprintf(pseudo_const, "$%d", stack_size);
713 printf("\tsubl\t%s, %%esp\n", pseudo_const);
716 /* function epilogue */
718 /* jump target for 'return' statements */
719 emit_label(f->ret_target, NULL);
721 if (stack_size) {
722 struct storage *val;
724 val = new_storage(STOR_VALUE);
725 val->value = (long long) (stack_size);
726 val->flags = STOR_WANTS_FREE;
728 insn("addl", val, REG_ESP, NULL);
731 insn("ret", NULL, NULL, NULL);
733 /* output everything to stdout */
734 fflush(stdout); /* paranoia; needed? */
735 emit_atom_list(f);
737 /* function footer */
738 name = show_ident(sym->ident);
739 printf("\t.size\t%s, .-%s\n", name, name);
741 func_cleanup(f);
742 current_func = NULL;
745 /* emit object (a.k.a. variable, a.k.a. data) prologue */
746 static void emit_object_pre(const char *name, unsigned long modifiers,
747 unsigned long alignment, unsigned int byte_size)
749 if ((modifiers & MOD_STATIC) == 0)
750 printf(".globl %s\n", name);
751 emit_section(".data");
752 if (alignment)
753 printf("\t.align %lu\n", alignment);
754 printf("\t.type\t%s, @object\n", name);
755 printf("\t.size\t%s, %d\n", name, byte_size);
756 printf("%s:\n", name);
759 /* emit value (only) for an initializer scalar */
760 static void emit_scalar(struct expression *expr, unsigned int bit_size)
762 const char *type;
763 long long ll;
765 assert(expr->type == EXPR_VALUE);
767 if (expr->value == 0ULL) {
768 printf("\t.zero\t%d\n", bit_size / 8);
769 return;
772 ll = (long long) expr->value;
774 switch (bit_size) {
775 case 8: type = "byte"; ll = (char) ll; break;
776 case 16: type = "value"; ll = (short) ll; break;
777 case 32: type = "long"; ll = (int) ll; break;
778 case 64: type = "quad"; break;
779 default: type = NULL; break;
782 assert(type != NULL);
784 printf("\t.%s\t%Ld\n", type, ll);
787 static void emit_global_noinit(const char *name, unsigned long modifiers,
788 unsigned long alignment, unsigned int byte_size)
790 char s[64];
792 if (modifiers & MOD_STATIC) {
793 sprintf(s, "\t.local\t%s\n", name);
794 textbuf_push(&unit_post_text, s);
796 if (alignment)
797 sprintf(s, "\t.comm\t%s,%d,%lu\n", name, byte_size, alignment);
798 else
799 sprintf(s, "\t.comm\t%s,%d\n", name, byte_size);
800 textbuf_push(&unit_post_text, s);
803 static int ea_current, ea_last;
805 static void emit_initializer(struct symbol *sym,
806 struct expression *expr)
808 int distance = ea_current - ea_last - 1;
810 if (distance > 0)
811 printf("\t.zero\t%d\n", (sym->bit_size / 8) * distance);
813 if (expr->type == EXPR_VALUE) {
814 struct symbol *base_type = sym->ctype.base_type;
815 assert(base_type != NULL);
817 emit_scalar(expr, sym->bit_size / get_expression_value(base_type->array_size));
818 return;
820 if (expr->type != EXPR_INITIALIZER)
821 return;
823 assert(0); /* FIXME */
826 static int sort_array_cmp(const struct expression *a,
827 const struct expression *b)
829 int a_ofs = 0, b_ofs = 0;
831 if (a->type == EXPR_POS)
832 a_ofs = (int) a->init_offset;
833 if (b->type == EXPR_POS)
834 b_ofs = (int) b->init_offset;
836 return a_ofs - b_ofs;
839 /* move to front-end? */
840 static void sort_array(struct expression *expr)
842 struct expression *entry, **list;
843 unsigned int elem, sorted, i;
845 elem = 0;
846 FOR_EACH_PTR(expr->expr_list, entry) {
847 elem++;
848 } END_FOR_EACH_PTR;
850 if (!elem)
851 return;
853 list = malloc(sizeof(entry) * elem);
854 if (!list)
855 die("OOM in sort_array");
857 /* this code is no doubt evil and ignores EXPR_INDEX possibly
858 * to its detriment and other nasty things. improvements
859 * welcome.
861 i = 0;
862 sorted = 0;
863 FOR_EACH_PTR(expr->expr_list, entry) {
864 if ((entry->type == EXPR_POS) || (entry->type == EXPR_VALUE)) {
865 /* add entry to list[], in sorted order */
866 if (sorted == 0) {
867 list[0] = entry;
868 sorted = 1;
869 } else {
870 unsigned int i;
872 for (i = 0; i < sorted; i++)
873 if (sort_array_cmp(entry, list[i]) <= 0)
874 break;
876 /* If inserting into the middle of list[]
877 * instead of appending, we memmove.
878 * This is ugly, but thankfully
879 * uncommon. Input data with tons of
880 * entries very rarely have explicit
881 * offsets. convert to qsort eventually...
883 if (i != sorted)
884 memmove(&list[i + 1], &list[i],
885 (sorted - i) * sizeof(entry));
886 list[i] = entry;
887 sorted++;
890 } END_FOR_EACH_PTR;
892 i = 0;
893 FOR_EACH_PTR(expr->expr_list, entry) {
894 if ((entry->type == EXPR_POS) || (entry->type == EXPR_VALUE))
895 __list->list[__i] = list[i++];
896 } END_FOR_EACH_PTR;
900 static void emit_array(struct symbol *sym)
902 struct symbol *base_type = sym->ctype.base_type;
903 struct expression *expr = sym->initializer;
904 struct expression *entry;
906 assert(base_type != NULL);
908 stor_sym_init(sym);
910 ea_last = -1;
912 emit_object_pre(show_ident(sym->ident), sym->ctype.modifiers,
913 sym->ctype.alignment,
914 sym->bit_size / 8);
916 sort_array(expr);
918 FOR_EACH_PTR(expr->expr_list, entry) {
919 if (entry->type == EXPR_VALUE) {
920 ea_current = 0;
921 emit_initializer(sym, entry);
922 ea_last = ea_current;
923 } else if (entry->type == EXPR_POS) {
924 ea_current =
925 entry->init_offset / (base_type->bit_size / 8);
926 emit_initializer(sym, entry->init_expr);
927 ea_last = ea_current;
929 } END_FOR_EACH_PTR;
932 void emit_one_symbol(struct symbol *sym)
934 x86_symbol(sym);
937 static void emit_copy(struct storage *dest, struct storage *src,
938 struct symbol *ctype)
940 struct storage *reg = NULL;
941 unsigned int bit_size;
943 /* FIXME: Bitfield copy! */
945 bit_size = src->size * 8;
946 if (!bit_size)
947 bit_size = 32;
948 if ((src->type == STOR_ARG) && (bit_size < 32))
949 bit_size = 32;
951 reg = temp_from_bits(bit_size);
952 emit_move(src, reg, ctype, "begin copy ..");
954 bit_size = dest->size * 8;
955 if (!bit_size)
956 bit_size = 32;
957 if ((dest->type == STOR_ARG) && (bit_size < 32))
958 bit_size = 32;
960 reg = temp_from_bits(bit_size);
961 emit_move(reg, dest, ctype, ".... end copy");
964 static void emit_store(struct expression *dest_expr, struct storage *dest,
965 struct storage *src, int bits)
967 /* FIXME: Bitfield store! */
968 printf("\tst.%d\t\tv%d,[v%d]\n", bits, src->pseudo, dest->pseudo);
971 static void emit_scalar_noinit(struct symbol *sym)
973 emit_global_noinit(show_ident(sym->ident),
974 sym->ctype.modifiers, sym->ctype.alignment,
975 sym->bit_size / 8);
976 stor_sym_init(sym);
979 static void emit_array_noinit(struct symbol *sym)
981 emit_global_noinit(show_ident(sym->ident),
982 sym->ctype.modifiers, sym->ctype.alignment,
983 get_expression_value(sym->array_size) * (sym->bit_size / 8));
984 stor_sym_init(sym);
987 static const char *opbits(const char *insn, unsigned int bits)
989 static char opbits_str[32];
990 char c;
992 switch (bits) {
993 case 8: c = 'b'; break;
994 case 16: c = 'w'; break;
995 case 32: c = 'l'; break;
996 case 64: c = 'q'; break;
997 default: assert(0); break;
1000 sprintf(opbits_str, "%s%c", insn, c);
1002 return opbits_str;
1005 static void emit_move(struct storage *src, struct storage *dest,
1006 struct symbol *ctype, const char *comment)
1008 unsigned int bits;
1009 unsigned int is_signed;
1010 unsigned int is_dest = (src->type == STOR_REG);
1011 const char *opname;
1013 if (ctype) {
1014 bits = ctype->bit_size;
1015 is_signed = type_is_signed(ctype);
1016 } else {
1017 bits = 32;
1018 is_signed = 0;
1021 if ((dest->type == STOR_REG) && (src->type == STOR_REG)) {
1022 insn("mov", src, dest, NULL);
1023 return;
1026 if ((bits == 8) || (bits == 16)) {
1027 if (is_dest)
1028 opname = "mov";
1029 else
1030 opname = is_signed ? "movsx" : "movzx";
1031 } else
1032 opname = "mov";
1034 insn(opbits(opname, bits), src, dest, comment);
1037 static struct storage *emit_compare(struct expression *expr)
1039 struct storage *left = x86_expression(expr->left);
1040 struct storage *right = x86_expression(expr->right);
1041 struct storage *new, *val;
1042 const char *opname = NULL;
1043 unsigned int right_bits = expr->right->ctype->bit_size;
1045 switch(expr->op) {
1046 case '<': opname = "setl"; break;
1047 case '>': opname = "setg"; break;
1048 case SPECIAL_LTE:
1049 opname = "setle"; break;
1050 case SPECIAL_GTE:
1051 opname = "setge"; break;
1052 case SPECIAL_EQUAL: opname = "sete"; break;
1053 case SPECIAL_NOTEQUAL: opname = "setne"; break;
1054 case SPECIAL_UNSIGNED_LT:
1055 opname = "setb"; break;
1056 case SPECIAL_UNSIGNED_GT:
1057 opname = "seta"; break;
1058 case SPECIAL_UNSIGNED_LTE:
1059 opname = "setb"; break;
1060 case SPECIAL_UNSIGNED_GTE:
1061 opname = "setae"; break;
1062 default:
1063 assert(0);
1064 break;
1067 /* init EDX to 0 */
1068 val = new_storage(STOR_VALUE);
1069 val->flags = STOR_WANTS_FREE;
1070 emit_move(val, REG_EDX, NULL, NULL);
1072 /* move op1 into EAX */
1073 emit_move(left, REG_EAX, expr->left->ctype, NULL);
1075 /* perform comparison, RHS (op1, right) and LHS (op2, EAX) */
1076 insn(opbits("cmp", right_bits), right, REG_EAX, NULL);
1078 /* store result of operation, 0 or 1, in DL using SETcc */
1079 insn(opname, REG_DL, NULL, NULL);
1081 /* finally, store the result (DL) in a new pseudo / stack slot */
1082 new = stack_alloc(4);
1083 emit_move(REG_EDX, new, NULL, "end EXPR_COMPARE");
1085 return new;
1088 static struct storage *emit_value(struct expression *expr)
1090 #if 0 /* old and slow way */
1091 struct storage *new = stack_alloc(4);
1092 struct storage *val;
1094 val = new_storage(STOR_VALUE);
1095 val->value = (long long) expr->value;
1096 val->flags = STOR_WANTS_FREE;
1097 insn("movl", val, new, NULL);
1099 return new;
1100 #else
1101 struct storage *val;
1103 val = new_storage(STOR_VALUE);
1104 val->value = (long long) expr->value;
1106 return val; /* FIXME: memory leak */
1107 #endif
1110 static struct storage *emit_binop(struct expression *expr)
1112 struct storage *left = x86_expression(expr->left);
1113 struct storage *right = x86_expression(expr->right);
1114 struct storage *new;
1115 struct storage *accum_reg = NULL;
1116 struct storage *result_reg = NULL;
1117 const char *opname = NULL;
1118 const char *suffix;
1119 char movstr[16], opstr[16];
1120 int is_signed, doing_divide = 0;
1122 if ((expr->op == '/') || (expr->op == '%')) {
1123 struct storage *val;
1125 doing_divide = 1;
1126 /* init EDX to 0 */
1127 val = new_storage(STOR_VALUE);
1128 val->flags = STOR_WANTS_FREE;
1129 emit_move(val, REG_EDX, NULL, "begin EXPR_DIVIDE");
1132 is_signed = type_is_signed(expr->ctype);
1134 switch (expr->op) {
1135 case '+':
1136 opname = "add";
1137 break;
1138 case '-':
1139 opname = "sub";
1140 break;
1141 case '&':
1142 opname = "and";
1143 break;
1144 case '|':
1145 opname = "or";
1146 break;
1147 case '^':
1148 opname = "xor";
1149 break;
1150 case SPECIAL_LEFTSHIFT:
1151 opname = "shl";
1152 break;
1153 case SPECIAL_RIGHTSHIFT:
1154 if (is_signed)
1155 opname = "sar";
1156 else
1157 opname = "shr";
1158 break;
1159 case '*':
1160 if (is_signed)
1161 opname = "imul";
1162 else
1163 opname = "mul";
1164 break;
1165 case '/':
1166 case '%':
1167 if (is_signed)
1168 opname = "idiv";
1169 else
1170 opname = "div";
1171 break;
1172 case SPECIAL_LOGICAL_AND:
1173 warn(expr->pos, "bogus bitwise and for logical op (should use '2*setne + and' or something)");
1174 opname = "and";
1175 break;
1176 case SPECIAL_LOGICAL_OR:
1177 warn(expr->pos, "bogus bitwise or for logical op (should use 'or + setne' or something)");
1178 opname = "or";
1179 break;
1180 default:
1181 error(expr->pos, "unhandled binop '%s'\n", show_special(expr->op));
1182 break;
1185 switch (expr->ctype->bit_size) {
1186 case 8:
1187 suffix = "b";
1188 result_reg = accum_reg = REG_AL;
1189 if (expr->op == '%')
1190 result_reg = REG_DL;
1191 break;
1192 case 16:
1193 suffix = "w";
1194 result_reg = accum_reg = REG_AX;
1195 if (expr->op == '%')
1196 result_reg = REG_DX;
1197 break;
1198 case 32:
1199 suffix = "l";
1200 result_reg = accum_reg = REG_EAX;
1201 if (expr->op == '%')
1202 result_reg = REG_EDX;
1203 break;
1204 case 64:
1205 suffix = "q"; /* FIXME */
1206 result_reg = accum_reg = REG_EAX; /* FIXME */
1207 if (expr->op == '%')
1208 result_reg = REG_EDX;
1209 break;
1210 default:
1211 assert(0);
1212 break;
1215 sprintf(movstr, "mov%s", suffix);
1216 sprintf(opstr, "%s%s", opname, suffix);
1218 /* load op2 into EAX */
1219 insn(movstr, right, accum_reg,
1220 doing_divide ? NULL : "EXPR_BINOP/COMMA/LOGICAL");
1222 /* perform binop */
1223 insn(opstr, left, accum_reg, NULL);
1225 /* store result (EAX or EDX) in new pseudo / stack slot */
1226 new = stack_alloc(expr->ctype->bit_size / 8);
1227 insn(movstr, result_reg, new,
1228 doing_divide ? "end EXPR_DIVIDE" : "end EXPR_BINOP");
1230 return new;
1233 static int emit_conditional_test(struct storage *val)
1235 struct storage *target_val;
1236 int target_false;
1238 /* load result into EAX */
1239 insn("movl", val, REG_EAX, "begin if/conditional");
1241 /* compare result with zero */
1242 insn("test", REG_EAX, REG_EAX, NULL);
1244 /* create conditional-failed label to jump to */
1245 target_false = new_label();
1246 target_val = new_storage(STOR_LABEL);
1247 target_val->label = target_false;
1248 target_val->flags = STOR_WANTS_FREE;
1249 insn("jz", target_val, NULL, NULL);
1251 return target_false;
1254 static int emit_conditional_end(int target_false)
1256 struct storage *cond_end_st;
1257 int cond_end;
1259 /* finished generating code for if-true statement.
1260 * add a jump-to-end jump to avoid falling through
1261 * to the if-false statement code.
1263 cond_end = new_label();
1264 cond_end_st = new_storage(STOR_LABEL);
1265 cond_end_st->label = cond_end;
1266 cond_end_st->flags = STOR_WANTS_FREE;
1267 insn("jmp", cond_end_st, NULL, NULL);
1269 /* if we have both if-true and if-false statements,
1270 * the failed-conditional case will fall through to here
1272 emit_label(target_false, NULL);
1274 return cond_end;
1277 static void emit_if_conditional(struct statement *stmt)
1279 struct storage *val;
1280 int cond_end;
1282 /* emit test portion of conditional */
1283 val = x86_expression(stmt->if_conditional);
1284 cond_end = emit_conditional_test(val);
1286 /* emit if-true statement */
1287 x86_statement(stmt->if_true);
1289 /* emit if-false statement, if present */
1290 if (stmt->if_false) {
1291 cond_end = emit_conditional_end(cond_end);
1292 x86_statement(stmt->if_false);
1295 /* end of conditional; jump target for if-true branch */
1296 emit_label(cond_end, "end if");
1299 static struct storage *emit_inc_dec(struct expression *expr, int postop)
1301 struct storage *addr = x86_address_gen(expr->unop);
1302 struct storage *retval;
1303 char opname[16];
1305 strcpy(opname, opbits(expr->op == SPECIAL_INCREMENT ? "inc" : "dec",
1306 expr->ctype->bit_size));
1308 if (postop) {
1309 struct storage *new = stack_alloc(4);
1311 emit_copy(new, addr, expr->unop->ctype);
1313 retval = new;
1314 } else
1315 retval = addr;
1317 insn(opname, addr, NULL, NULL);
1319 return retval;
1322 static struct storage *emit_postop(struct expression *expr)
1324 return emit_inc_dec(expr, 1);
1327 static struct storage *emit_return_stmt(struct statement *stmt)
1329 struct function *f = current_func;
1330 struct expression *expr = stmt->ret_value;
1331 struct storage *val = NULL, *jmplbl;
1333 if (expr && expr->ctype) {
1334 val = x86_expression(expr);
1335 assert(val != NULL);
1336 emit_move(val, REG_EAX, expr->ctype, "return");
1339 jmplbl = new_storage(STOR_LABEL);
1340 jmplbl->flags |= STOR_WANTS_FREE;
1341 jmplbl->label = f->ret_target;
1342 insn("jmp", jmplbl, NULL, NULL);
1344 return val;
1347 static struct storage *emit_conditional_expr(struct expression *expr)
1349 struct storage *cond, *true = NULL, *false = NULL;
1350 struct storage *new = stack_alloc(expr->ctype->bit_size / 8);
1351 int target_false, cond_end;
1353 /* evaluate conditional */
1354 cond = x86_expression(expr->conditional);
1355 target_false = emit_conditional_test(cond);
1357 /* handle if-true part of the expression */
1358 if (!expr->cond_true)
1359 true = cond;
1360 else
1361 true = x86_expression(expr->cond_true);
1363 emit_copy(new, true, expr->ctype);
1365 cond_end = emit_conditional_end(target_false);
1367 /* handle if-false part of the expression */
1368 false = x86_expression(expr->cond_false);
1370 emit_copy(new, false, expr->ctype);
1372 /* end of conditional; jump target for if-true branch */
1373 emit_label(cond_end, "end conditional");
1375 return new;
1378 static struct storage *emit_select_expr(struct expression *expr)
1380 struct storage *cond = x86_expression(expr->conditional);
1381 struct storage *true = x86_expression(expr->cond_true);
1382 struct storage *false = x86_expression(expr->cond_false);
1383 struct storage *new = stack_alloc(4);
1384 struct storage *truereg;
1386 emit_move(cond, REG_EAX, expr->conditional->ctype, "begin SELECT");
1387 truereg = REG_EAX;
1388 if (true) {
1389 emit_move(true, REG_ECX, expr->cond_true->ctype, NULL);
1390 truereg = REG_ECX;
1392 emit_move(false, REG_EDX, expr->cond_false->ctype, NULL);
1395 * Do the actual select: check the conditional for zero,
1396 * move false over true if zero
1398 insn("test", REG_EAX, REG_EAX, NULL);
1399 insn("cmovz", REG_EDX, truereg, NULL);
1401 /* Store it back */
1402 emit_move(truereg, new, expr->ctype, "end SELECT");
1403 return new;
1406 static struct storage *emit_symbol_expr_init(struct symbol *sym)
1408 struct expression *expr = sym->initializer;
1409 struct symbol_private *priv = sym->aux;
1411 if (priv == NULL) {
1412 priv = calloc(1, sizeof(*priv));
1413 sym->aux = priv;
1415 if (expr == NULL) {
1416 struct storage *new = stack_alloc(4);
1417 fprintf(stderr, "FIXME! no value for symbol %s. creating pseudo %d (stack offset %d)\n",
1418 show_ident(sym->ident),
1419 new->pseudo, new->pseudo * 4);
1420 priv->addr = new;
1421 } else {
1422 priv->addr = x86_expression(expr);
1426 return priv->addr;
1429 static struct storage *emit_string_expr(struct expression *expr)
1431 struct function *f = current_func;
1432 int label = new_label();
1433 struct storage *new;
1435 push_cstring(f, expr->string, label);
1437 new = new_storage(STOR_LABEL);
1438 new->label = label;
1439 new->flags = STOR_LABEL_VAL | STOR_WANTS_FREE;
1440 return new;
1443 static struct storage *emit_cast_expr(struct expression *expr)
1445 struct symbol *old_type, *new_type;
1446 struct storage *op = x86_expression(expr->cast_expression);
1447 int oldbits, newbits;
1448 struct storage *new;
1450 old_type = expr->cast_expression->ctype;
1451 new_type = expr->cast_type;
1453 oldbits = old_type->bit_size;
1454 newbits = new_type->bit_size;
1455 if (oldbits >= newbits)
1456 return op;
1458 emit_move(op, REG_EAX, old_type, "begin cast ..");
1460 new = stack_alloc(newbits / 8);
1461 emit_move(REG_EAX, new, new_type, ".... end cast");
1463 return new;
1466 static struct storage *emit_regular_preop(struct expression *expr)
1468 struct storage *target = x86_expression(expr->unop);
1469 struct storage *val, *new = stack_alloc(4);
1470 const char *opname = NULL;
1472 switch (expr->op) {
1473 case '!':
1474 val = new_storage(STOR_VALUE);
1475 val->flags = STOR_WANTS_FREE;
1476 emit_move(val, REG_EDX, NULL, NULL);
1477 emit_move(target, REG_EAX, expr->unop->ctype, NULL);
1478 insn("test", REG_EAX, REG_EAX, NULL);
1479 insn("setz", REG_DL, NULL, NULL);
1480 emit_move(REG_EDX, new, expr->unop->ctype, NULL);
1482 break;
1483 case '~':
1484 opname = "not";
1485 case '-':
1486 if (!opname)
1487 opname = "neg";
1488 emit_move(target, REG_EAX, expr->unop->ctype, NULL);
1489 insn(opname, REG_EAX, NULL, NULL);
1490 emit_move(REG_EAX, new, expr->unop->ctype, NULL);
1491 break;
1492 default:
1493 assert(0);
1494 break;
1497 return new;
1500 static void emit_case_statement(struct statement *stmt)
1502 emit_labelsym(stmt->case_label, NULL);
1503 x86_statement(stmt->case_statement);
1506 static void emit_switch_statement(struct statement *stmt)
1508 struct storage *val = x86_expression(stmt->switch_expression);
1509 struct symbol *sym, *default_sym = NULL;
1510 struct storage *labelsym, *label;
1511 int switch_end = 0;
1513 emit_move(val, REG_EAX, stmt->switch_expression->ctype, "begin case");
1516 * This is where a _real_ back-end would go through the
1517 * cases to decide whether to use a lookup table or a
1518 * series of comparisons etc
1520 FOR_EACH_PTR(stmt->switch_case->symbol_list, sym) {
1521 struct statement *case_stmt = sym->stmt;
1522 struct expression *expr = case_stmt->case_expression;
1523 struct expression *to = case_stmt->case_to;
1525 /* default: */
1526 if (!expr)
1527 default_sym = sym;
1529 /* case NNN: */
1530 else {
1531 struct storage *case_val = new_val(expr->value);
1533 assert (expr->type == EXPR_VALUE);
1535 insn("cmpl", case_val, REG_EAX, NULL);
1537 if (!to) {
1538 labelsym = new_labelsym(sym);
1539 insn("je", labelsym, NULL, NULL);
1540 } else {
1541 int next_test;
1543 label = new_storage(STOR_LABEL);
1544 label->flags |= STOR_WANTS_FREE;
1545 label->label = next_test = new_label();
1547 /* FIXME: signed/unsigned */
1548 insn("jl", label, NULL, NULL);
1550 case_val = new_val(to->value);
1551 insn("cmpl", case_val, REG_EAX, NULL);
1553 /* TODO: implement and use refcounting... */
1554 label = new_storage(STOR_LABEL);
1555 label->flags |= STOR_WANTS_FREE;
1556 label->label = next_test;
1558 /* FIXME: signed/unsigned */
1559 insn("jg", label, NULL, NULL);
1561 labelsym = new_labelsym(sym);
1562 insn("jmp", labelsym, NULL, NULL);
1564 emit_label(next_test, NULL);
1567 } END_FOR_EACH_PTR;
1569 if (default_sym) {
1570 labelsym = new_labelsym(default_sym);
1571 insn("jmp", labelsym, NULL, "default");
1572 } else {
1573 label = new_storage(STOR_LABEL);
1574 label->flags |= STOR_WANTS_FREE;
1575 label->label = switch_end = new_label();
1576 insn("jmp", label, NULL, "goto end of switch");
1579 x86_statement(stmt->switch_statement);
1581 if (stmt->switch_break->used)
1582 emit_labelsym(stmt->switch_break, NULL);
1584 if (switch_end)
1585 emit_label(switch_end, NULL);
1588 static void x86_struct_member(struct symbol *sym, void *data, int flags)
1590 if (flags & ITERATE_FIRST)
1591 printf(" {\n\t");
1592 printf("%s:%d:%ld at offset %ld", show_ident(sym->ident), sym->bit_size, sym->ctype.alignment, sym->offset);
1593 if (sym->fieldwidth)
1594 printf("[%d..%d]", sym->bit_offset, sym->bit_offset+sym->fieldwidth-1);
1595 if (flags & ITERATE_LAST)
1596 printf("\n} ");
1597 else
1598 printf(", ");
1601 static void x86_symbol(struct symbol *sym)
1603 struct symbol *type;
1605 if (!sym)
1606 return;
1608 type = sym->ctype.base_type;
1609 if (!type)
1610 return;
1613 * Show actual implementation information
1615 switch (type->type) {
1617 case SYM_ARRAY:
1618 if (sym->initializer)
1619 emit_array(sym);
1620 else
1621 emit_array_noinit(sym);
1622 break;
1624 case SYM_BASETYPE:
1625 if (sym->initializer) {
1626 emit_object_pre(show_ident(sym->ident),
1627 sym->ctype.modifiers,
1628 sym->ctype.alignment,
1629 sym->bit_size / 8);
1630 emit_scalar(sym->initializer, sym->bit_size);
1631 stor_sym_init(sym);
1632 } else
1633 emit_scalar_noinit(sym);
1634 break;
1636 case SYM_STRUCT:
1637 symbol_iterate(type->symbol_list, x86_struct_member, NULL);
1638 break;
1640 case SYM_UNION:
1641 symbol_iterate(type->symbol_list, x86_struct_member, NULL);
1642 break;
1644 case SYM_FN: {
1645 struct statement *stmt = type->stmt;
1646 if (stmt) {
1647 emit_func_pre(sym);
1648 x86_statement(stmt);
1649 emit_func_post(sym);
1651 break;
1654 default:
1655 break;
1658 if (sym->initializer && (type->type != SYM_BASETYPE) &&
1659 (type->type != SYM_ARRAY)) {
1660 printf(" = \n");
1661 x86_expression(sym->initializer);
1665 static void x86_symbol_init(struct symbol *sym);
1667 static void x86_symbol_decl(struct symbol_list *syms)
1669 struct symbol *sym;
1670 FOR_EACH_PTR(syms, sym) {
1671 x86_symbol_init(sym);
1672 } END_FOR_EACH_PTR;
1675 static void loopstk_push(int cont_lbl, int loop_bottom_lbl)
1677 struct function *f = current_func;
1678 struct loop_stack *ls;
1680 ls = malloc(sizeof(*ls));
1681 ls->continue_lbl = cont_lbl;
1682 ls->loop_bottom_lbl = loop_bottom_lbl;
1683 ls->next = f->loop_stack;
1684 f->loop_stack = ls;
1687 static void loopstk_pop(void)
1689 struct function *f = current_func;
1690 struct loop_stack *ls;
1692 assert(f->loop_stack != NULL);
1693 ls = f->loop_stack;
1694 f->loop_stack = f->loop_stack->next;
1695 free(ls);
1698 static int loopstk_break(void)
1700 return current_func->loop_stack->loop_bottom_lbl;
1703 static int loopstk_continue(void)
1705 return current_func->loop_stack->continue_lbl;
1708 static void emit_loop(struct statement *stmt)
1710 struct statement *pre_statement = stmt->iterator_pre_statement;
1711 struct expression *pre_condition = stmt->iterator_pre_condition;
1712 struct statement *statement = stmt->iterator_statement;
1713 struct statement *post_statement = stmt->iterator_post_statement;
1714 struct expression *post_condition = stmt->iterator_post_condition;
1715 int loop_top = 0, loop_bottom, loop_continue;
1716 int have_bottom = 0;
1717 struct storage *val;
1719 loop_bottom = new_label();
1720 loop_continue = new_label();
1721 loopstk_push(loop_continue, loop_bottom);
1723 x86_symbol_decl(stmt->iterator_syms);
1724 x86_statement(pre_statement);
1725 if (pre_condition) {
1726 if (pre_condition->type == EXPR_VALUE) {
1727 if (!pre_condition->value) {
1728 struct storage *lbv;
1729 lbv = new_storage(STOR_LABEL);
1730 lbv->label = loop_bottom;
1731 lbv->flags = STOR_WANTS_FREE;
1732 insn("jmp", lbv, NULL, "go to loop bottom");
1733 have_bottom = 1;
1735 } else {
1736 struct storage *lbv = new_storage(STOR_LABEL);
1737 lbv->label = loop_bottom;
1738 lbv->flags = STOR_WANTS_FREE;
1739 have_bottom = 1;
1741 val = x86_expression(pre_condition);
1743 emit_move(val, REG_EAX, NULL, "loop pre condition");
1744 insn("test", REG_EAX, REG_EAX, NULL);
1745 insn("jz", lbv, NULL, NULL);
1748 if (!post_condition || post_condition->type != EXPR_VALUE || post_condition->value) {
1749 loop_top = new_label();
1750 emit_label(loop_top, "loop top");
1752 x86_statement(statement);
1753 if (stmt->iterator_continue->used)
1754 emit_label(loop_continue, "'continue' iterator");
1755 x86_statement(post_statement);
1756 if (!post_condition) {
1757 struct storage *lbv = new_storage(STOR_LABEL);
1758 lbv->label = loop_top;
1759 lbv->flags = STOR_WANTS_FREE;
1760 insn("jmp", lbv, NULL, "go to loop top");
1761 } else if (post_condition->type == EXPR_VALUE) {
1762 if (post_condition->value) {
1763 struct storage *lbv = new_storage(STOR_LABEL);
1764 lbv->label = loop_top;
1765 lbv->flags = STOR_WANTS_FREE;
1766 insn("jmp", lbv, NULL, "go to loop top");
1768 } else {
1769 struct storage *lbv = new_storage(STOR_LABEL);
1770 lbv->label = loop_top;
1771 lbv->flags = STOR_WANTS_FREE;
1773 val = x86_expression(post_condition);
1775 emit_move(val, REG_EAX, NULL, "loop post condition");
1776 insn("test", REG_EAX, REG_EAX, NULL);
1777 insn("jnz", lbv, NULL, NULL);
1779 if (have_bottom || stmt->iterator_break->used)
1780 emit_label(loop_bottom, "loop bottom");
1782 loopstk_pop();
1786 * Print out a statement
1788 static struct storage *x86_statement(struct statement *stmt)
1790 if (!stmt)
1791 return NULL;
1792 switch (stmt->type) {
1793 case STMT_RETURN:
1794 return emit_return_stmt(stmt);
1795 case STMT_COMPOUND: {
1796 struct statement *s;
1797 struct storage *last = NULL;
1799 x86_symbol_decl(stmt->syms);
1800 FOR_EACH_PTR(stmt->stmts, s) {
1801 last = x86_statement(s);
1802 } END_FOR_EACH_PTR;
1804 return last;
1807 case STMT_EXPRESSION:
1808 return x86_expression(stmt->expression);
1809 case STMT_IF:
1810 emit_if_conditional(stmt);
1811 return NULL;
1813 case STMT_CASE:
1814 emit_case_statement(stmt);
1815 break;
1816 case STMT_SWITCH:
1817 emit_switch_statement(stmt);
1818 break;
1820 case STMT_ITERATOR:
1821 emit_loop(stmt);
1822 break;
1824 case STMT_NONE:
1825 break;
1827 case STMT_LABEL:
1828 printf(".L%p:\n", stmt->label_identifier);
1829 x86_statement(stmt->label_statement);
1830 break;
1832 case STMT_GOTO:
1833 if (stmt->goto_expression) {
1834 struct storage *val = x86_expression(stmt->goto_expression);
1835 printf("\tgoto *v%d\n", val->pseudo);
1836 } else if (!strcmp("break", show_ident(stmt->goto_label->ident))) {
1837 struct storage *lbv = new_storage(STOR_LABEL);
1838 lbv->label = loopstk_break();
1839 lbv->flags = STOR_WANTS_FREE;
1840 insn("jmp", lbv, NULL, "'break'; go to loop bottom");
1841 } else if (!strcmp("continue", show_ident(stmt->goto_label->ident))) {
1842 struct storage *lbv = new_storage(STOR_LABEL);
1843 lbv->label = loopstk_continue();
1844 lbv->flags = STOR_WANTS_FREE;
1845 insn("jmp", lbv, NULL, "'continue'; go to loop top");
1846 } else {
1847 struct storage *labelsym = new_labelsym(stmt->goto_label);
1848 insn("jmp", labelsym, NULL, NULL);
1850 break;
1851 case STMT_ASM:
1852 printf("\tasm( .... )\n");
1853 break;
1855 return NULL;
1858 static struct storage *x86_call_expression(struct expression *expr)
1860 struct function *f = current_func;
1861 struct symbol *direct;
1862 struct expression *arg, *fn;
1863 struct storage *retval, *fncall;
1864 int framesize;
1865 char s[64];
1867 if (!expr->ctype) {
1868 warn(expr->pos, "\tcall with no type!");
1869 return NULL;
1872 framesize = 0;
1873 FOR_EACH_PTR_REVERSE(expr->args, arg) {
1874 struct storage *new = x86_expression(arg);
1875 int size = arg->ctype->bit_size;
1878 * FIXME: i386 SysV ABI dictates that values
1879 * smaller than 32 bits should be placed onto
1880 * the stack as 32-bit objects. We should not
1881 * blindly do a 32-bit push on objects smaller
1882 * than 32 bits.
1884 if (size < 32)
1885 size = 32;
1886 insn("pushl", new, NULL,
1887 !framesize ? "begin function call" : NULL);
1889 framesize += size >> 3;
1890 } END_FOR_EACH_PTR_REVERSE;
1892 fn = expr->fn;
1894 /* Remove dereference, if any */
1895 direct = NULL;
1896 if (fn->type == EXPR_PREOP) {
1897 if (fn->unop->type == EXPR_SYMBOL) {
1898 struct symbol *sym = fn->unop->symbol;
1899 if (sym->ctype.base_type->type == SYM_FN)
1900 direct = sym;
1903 if (direct) {
1904 struct storage *direct_stor = new_storage(STOR_SYM);
1905 direct_stor->flags |= STOR_WANTS_FREE;
1906 direct_stor->sym = direct;
1907 insn("call", direct_stor, NULL, NULL);
1908 } else {
1909 fncall = x86_expression(fn);
1910 emit_move(fncall, REG_EAX, fn->ctype, NULL);
1912 strcpy(s, "\tcall\t*%eax\n");
1913 push_text_atom(f, s);
1916 /* FIXME: pay attention to BITS_IN_POINTER */
1917 if (framesize) {
1918 struct storage *val = new_storage(STOR_VALUE);
1919 val->value = (long long) framesize;
1920 val->flags = STOR_WANTS_FREE;
1921 insn("addl", val, REG_ESP, NULL);
1924 retval = stack_alloc(4);
1925 emit_move(REG_EAX, retval, NULL, "end function call");
1927 return retval;
1930 static struct storage *x86_address_gen(struct expression *expr)
1932 struct function *f = current_func;
1933 struct storage *addr;
1934 struct storage *new;
1935 char s[32];
1937 if ((expr->type != EXPR_PREOP) || (expr->op != '*'))
1938 return x86_expression(expr->address);
1940 addr = x86_expression(expr->unop);
1941 if (expr->unop->type == EXPR_SYMBOL)
1942 return addr;
1944 emit_move(addr, REG_EAX, NULL, "begin deref ..");
1946 /* FIXME: operand size */
1947 strcpy(s, "\tmovl\t(%eax), %ecx\n");
1948 push_text_atom(f, s);
1950 new = stack_alloc(4);
1951 emit_move(REG_ECX, new, NULL, ".... end deref");
1953 return new;
1956 static struct storage *x86_assignment(struct expression *expr)
1958 struct expression *target = expr->left;
1959 struct storage *val, *addr;
1961 if (!expr->ctype)
1962 return NULL;
1964 val = x86_expression(expr->right);
1965 addr = x86_address_gen(target);
1967 switch (val->type) {
1968 /* copy, where both operands are memory */
1969 case STOR_PSEUDO:
1970 case STOR_ARG:
1971 emit_copy(addr, val, expr->ctype);
1972 break;
1974 /* copy, one or zero operands are memory */
1975 case STOR_REG:
1976 case STOR_SYM:
1977 case STOR_VALUE:
1978 case STOR_LABEL:
1979 emit_move(val, addr, expr->left->ctype, NULL);
1980 break;
1982 case STOR_LABELSYM:
1983 assert(0);
1984 break;
1986 return val;
1989 static int x86_initialization(struct symbol *sym, struct expression *expr)
1991 struct storage *val, *addr;
1992 int bits;
1994 if (!expr->ctype)
1995 return 0;
1997 bits = expr->ctype->bit_size;
1998 val = x86_expression(expr);
1999 addr = x86_symbol_expr(sym);
2000 // FIXME! The "target" expression is for bitfield store information.
2001 // Leave it NULL, which works fine.
2002 emit_store(NULL, addr, val, bits);
2003 return 0;
2006 static struct storage *x86_access(struct expression *expr)
2008 return x86_address_gen(expr);
2011 static struct storage *x86_preop(struct expression *expr)
2014 * '*' is an lvalue access, and is fundamentally different
2015 * from an arithmetic operation. Maybe it should have an
2016 * expression type of its own..
2018 if (expr->op == '*')
2019 return x86_access(expr);
2020 if (expr->op == SPECIAL_INCREMENT || expr->op == SPECIAL_DECREMENT)
2021 return emit_inc_dec(expr, 0);
2022 return emit_regular_preop(expr);
2025 static struct storage *x86_symbol_expr(struct symbol *sym)
2027 struct storage *new = stack_alloc(4);
2029 if (sym->ctype.modifiers & (MOD_TOPLEVEL | MOD_EXTERN | MOD_STATIC)) {
2030 printf("\tmovi.%d\t\tv%d,$%s\n", bits_in_pointer, new->pseudo, show_ident(sym->ident));
2031 return new;
2033 if (sym->ctype.modifiers & MOD_ADDRESSABLE) {
2034 printf("\taddi.%d\t\tv%d,vFP,$%lld\n", bits_in_pointer, new->pseudo, sym->value);
2035 return new;
2037 printf("\taddi.%d\t\tv%d,vFP,$offsetof(%s:%p)\n", bits_in_pointer, new->pseudo, show_ident(sym->ident), sym);
2038 return new;
2041 static void x86_symbol_init(struct symbol *sym)
2043 struct symbol_private *priv = sym->aux;
2044 struct expression *expr = sym->initializer;
2045 struct storage *new;
2047 if (expr)
2048 new = x86_expression(expr);
2049 else
2050 new = stack_alloc(sym->bit_size / 8);
2052 if (!priv) {
2053 priv = calloc(1, sizeof(*priv));
2054 sym->aux = priv;
2055 /* FIXME: leak! we don't free... */
2056 /* (well, we don't free symbols either) */
2059 priv->addr = new;
2062 static int type_is_signed(struct symbol *sym)
2064 if (sym->type == SYM_NODE)
2065 sym = sym->ctype.base_type;
2066 if (sym->type == SYM_PTR)
2067 return 0;
2068 return !(sym->ctype.modifiers & MOD_UNSIGNED);
2071 static struct storage *x86_bitfield_expr(struct expression *expr)
2073 return x86_access(expr);
2076 static struct storage *x86_label_expr(struct expression *expr)
2078 struct storage *new = stack_alloc(4);
2079 printf("\tmovi.%d\t\tv%d,.L%p\n", bits_in_pointer, new->pseudo, expr->label_symbol);
2080 return new;
2083 static struct storage *x86_statement_expr(struct expression *expr)
2085 return x86_statement(expr->statement);
2088 static int x86_position_expr(struct expression *expr, struct symbol *base)
2090 struct storage *new = x86_expression(expr->init_expr);
2091 struct symbol *ctype = expr->init_sym;
2093 printf("\tinsert v%d at [%d:%d] of %s\n", new->pseudo,
2094 expr->init_offset, ctype->bit_offset,
2095 show_ident(base->ident));
2096 return 0;
2099 static void x86_initializer_expr(struct expression *expr, struct symbol *ctype)
2101 struct expression *entry;
2103 FOR_EACH_PTR(expr->expr_list, entry) {
2104 // Nested initializers have their positions already
2105 // recursively calculated - just output them too
2106 if (entry->type == EXPR_INITIALIZER) {
2107 x86_initializer_expr(entry, ctype);
2108 continue;
2111 // Ignore initializer indexes and identifiers - the
2112 // evaluator has taken them into account
2113 if (entry->type == EXPR_IDENTIFIER || entry->type == EXPR_INDEX)
2114 continue;
2115 if (entry->type == EXPR_POS) {
2116 x86_position_expr(entry, ctype);
2117 continue;
2119 x86_initialization(ctype, entry);
2120 } END_FOR_EACH_PTR;
2124 * Print out an expression. Return the pseudo that contains the
2125 * variable.
2127 static struct storage *x86_expression(struct expression *expr)
2129 if (!expr)
2130 return NULL;
2132 if (!expr->ctype) {
2133 struct position *pos = &expr->pos;
2134 printf("\tno type at %s:%d:%d\n",
2135 input_streams[pos->stream].name,
2136 pos->line, pos->pos);
2137 return NULL;
2140 switch (expr->type) {
2141 case EXPR_CALL:
2142 return x86_call_expression(expr);
2144 case EXPR_ASSIGNMENT:
2145 return x86_assignment(expr);
2147 case EXPR_COMPARE:
2148 return emit_compare(expr);
2149 case EXPR_BINOP:
2150 case EXPR_COMMA:
2151 case EXPR_LOGICAL:
2152 return emit_binop(expr);
2153 case EXPR_PREOP:
2154 return x86_preop(expr);
2155 case EXPR_POSTOP:
2156 return emit_postop(expr);
2157 case EXPR_SYMBOL:
2158 return emit_symbol_expr_init(expr->symbol);
2159 case EXPR_DEREF:
2160 case EXPR_SIZEOF:
2161 case EXPR_ALIGNOF:
2162 warn(expr->pos, "invalid expression after evaluation");
2163 return NULL;
2164 case EXPR_CAST:
2165 return emit_cast_expr(expr);
2166 case EXPR_VALUE:
2167 return emit_value(expr);
2168 case EXPR_STRING:
2169 return emit_string_expr(expr);
2170 case EXPR_BITFIELD:
2171 return x86_bitfield_expr(expr);
2172 case EXPR_INITIALIZER:
2173 x86_initializer_expr(expr, expr->ctype);
2174 return NULL;
2175 case EXPR_SELECT:
2176 return emit_select_expr(expr);
2177 case EXPR_CONDITIONAL:
2178 return emit_conditional_expr(expr);
2179 case EXPR_STATEMENT:
2180 return x86_statement_expr(expr);
2181 case EXPR_LABEL:
2182 return x86_label_expr(expr);
2184 // None of these should exist as direct expressions: they are only
2185 // valid as sub-expressions of initializers.
2186 case EXPR_POS:
2187 warn(expr->pos, "unable to show plain initializer position expression");
2188 return NULL;
2189 case EXPR_IDENTIFIER:
2190 warn(expr->pos, "unable to show identifier expression");
2191 return NULL;
2192 case EXPR_INDEX:
2193 warn(expr->pos, "unable to show index expression");
2194 return NULL;
2195 case EXPR_TYPE:
2196 warn(expr->pos, "unable to show type expression");
2197 return NULL;
2198 case EXPR_FVALUE:
2199 warn(expr->pos, "floating point support is not implemented");
2200 return NULL;
2202 return NULL;