Special evaluation rules for function argument types:
[smatch.git] / compile-i386.c
blob70253b708df529c068f8aafd63b3c27b16895685
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"
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 static struct reg_info reg_info_table[] = {
165 { "%eax" },
166 { "%ecx" },
167 { "%edx" },
168 { "%esp" },
169 { "%dl" },
170 { "%dx" },
171 { "%al" },
172 { "%ax" },
175 static struct storage hardreg_storage_table[] = {
176 { /* eax */
177 .type = STOR_REG,
178 .reg = &reg_info_table[0],
181 { /* ecx */
182 .type = STOR_REG,
183 .reg = &reg_info_table[1],
186 { /* edx */
187 .type = STOR_REG,
188 .reg = &reg_info_table[2],
191 { /* esp */
192 .type = STOR_REG,
193 .reg = &reg_info_table[3],
196 { /* dl */
197 .type = STOR_REG,
198 .reg = &reg_info_table[4],
201 { /* dx */
202 .type = STOR_REG,
203 .reg = &reg_info_table[5],
206 { /* al */
207 .type = STOR_REG,
208 .reg = &reg_info_table[6],
211 { /* ax */
212 .type = STOR_REG,
213 .reg = &reg_info_table[7],
217 #define REG_EAX (&hardreg_storage_table[0])
218 #define REG_ECX (&hardreg_storage_table[1])
219 #define REG_EDX (&hardreg_storage_table[2])
220 #define REG_ESP (&hardreg_storage_table[3])
221 #define REG_DL (&hardreg_storage_table[4])
222 #define REG_DX (&hardreg_storage_table[5])
223 #define REG_AL (&hardreg_storage_table[6])
224 #define REG_AX (&hardreg_storage_table[7])
227 static void emit_move(struct storage *src, struct storage *dest,
228 struct symbol *ctype, const char *comment);
229 static int type_is_signed(struct symbol *sym);
230 static struct storage *x86_address_gen(struct expression *expr);
231 static struct storage *x86_symbol_expr(struct symbol *sym);
232 static void x86_symbol(struct symbol *sym);
233 static struct storage *x86_statement(struct statement *stmt);
234 static struct storage *x86_expression(struct expression *expr);
237 static inline unsigned int pseudo_offset(struct storage *s)
239 if (s->type != STOR_PSEUDO)
240 return 123456; /* intentionally bogus value */
242 return s->offset;
245 static inline unsigned int arg_offset(struct storage *s)
247 if (s->type != STOR_ARG)
248 return 123456; /* intentionally bogus value */
250 /* FIXME: this is wrong wrong wrong */
251 return current_func->stack_size + ((1 + s->idx) * 4);
254 static const char *pretty_offset(int ofs)
256 static char esp_buf[64];
258 if (ofs)
259 sprintf(esp_buf, "%d(%%esp)", ofs);
260 else
261 strcpy(esp_buf, "(%esp)");
263 return esp_buf;
266 static void stor_sym_init(struct symbol *sym)
268 struct storage *stor;
269 struct symbol_private *priv;
271 priv = calloc(1, sizeof(*priv) + sizeof(*stor));
272 if (!priv)
273 die("OOM in stor_sym_init");
275 stor = (struct storage *) (priv + 1);
277 priv->addr = stor;
278 stor->type = STOR_SYM;
279 stor->sym = sym;
282 static const char *stor_op_name(struct storage *s)
284 static char name[32];
286 switch (s->type) {
287 case STOR_PSEUDO:
288 strcpy(name, pretty_offset((int) pseudo_offset(s)));
289 break;
290 case STOR_ARG:
291 strcpy(name, pretty_offset((int) arg_offset(s)));
292 break;
293 case STOR_SYM:
294 strcpy(name, show_ident(s->sym->ident));
295 break;
296 case STOR_REG:
297 strcpy(name, s->reg->name);
298 break;
299 case STOR_VALUE:
300 sprintf(name, "$%Ld", s->value);
301 break;
302 case STOR_LABEL:
303 sprintf(name, "%s.L%d", s->flags & STOR_LABEL_VAL ? "$" : "",
304 s->label);
305 break;
306 case STOR_LABELSYM:
307 sprintf(name, "%s.LS%p", s->flags & STOR_LABEL_VAL ? "$" : "",
308 s->labelsym);
309 break;
312 return name;
315 static struct atom *new_atom(enum atom_type type)
317 struct atom *atom;
319 atom = calloc(1, sizeof(*atom)); /* TODO: chunked alloc */
320 if (!atom)
321 die("nuclear OOM");
323 atom->type = type;
325 return atom;
328 static inline void push_cstring(struct function *f, struct string *str,
329 int label)
331 struct atom *atom;
333 atom = new_atom(ATOM_CSTR);
334 atom->string = str;
335 atom->label = label;
337 add_ptr_list(&f->str_list, atom); /* note: _not_ atom_list */
340 static inline void push_atom(struct function *f, struct atom *atom)
342 add_ptr_list(&f->atom_list, atom);
345 static void push_text_atom(struct function *f, const char *text)
347 struct atom *atom = new_atom(ATOM_TEXT);
349 atom->text = strdup(text);
350 atom->text_len = strlen(text);
352 push_atom(f, atom);
355 static struct storage *new_storage(enum storage_type type)
357 struct storage *stor;
359 stor = calloc(1, sizeof(*stor));
360 if (!stor)
361 die("OOM in new_storage");
363 stor->type = type;
365 return stor;
368 static struct storage *stack_alloc(int n_bytes)
370 struct function *f = current_func;
371 struct storage *stor;
373 assert(f != NULL);
375 stor = new_storage(STOR_PSEUDO);
376 stor->type = STOR_PSEUDO;
377 stor->pseudo = f->pseudo_nr;
378 stor->offset = f->stack_size;
379 stor->size = n_bytes;
380 f->stack_size += n_bytes;
381 f->pseudo_nr++;
383 add_ptr_list(&f->pseudo_list, stor);
385 return stor;
388 static struct storage *new_labelsym(struct symbol *sym)
390 struct storage *stor;
392 stor = new_storage(STOR_LABELSYM);
394 if (stor) {
395 stor->flags |= STOR_WANTS_FREE;
396 stor->labelsym = sym;
399 return stor;
402 static struct storage *new_val(long long value)
404 struct storage *stor;
406 stor = new_storage(STOR_VALUE);
408 if (stor) {
409 stor->flags |= STOR_WANTS_FREE;
410 stor->value = value;
413 return stor;
416 static int new_label(void)
418 static int label = 0;
419 return ++label;
422 static void textbuf_push(struct textbuf **buf_p, const char *text)
424 struct textbuf *tmp, *list = *buf_p;
425 unsigned int text_len = strlen(text);
426 unsigned int alloc_len = text_len + 1 + sizeof(*list);
428 tmp = calloc(1, alloc_len);
429 if (!tmp)
430 die("OOM on textbuf alloc");
432 tmp->text = ((void *) tmp) + sizeof(*tmp);
433 memcpy(tmp->text, text, text_len + 1);
434 tmp->len = text_len;
436 /* add to end of list */
437 if (!list) {
438 list = tmp;
439 tmp->prev = tmp;
440 } else {
441 tmp->prev = list->prev;
442 tmp->prev->next = tmp;
443 list->prev = tmp;
445 tmp->next = list;
447 *buf_p = list;
450 static void textbuf_emit(struct textbuf **buf_p)
452 struct textbuf *tmp, *list = *buf_p;
454 while (list) {
455 tmp = list;
456 if (tmp->next == tmp)
457 list = NULL;
458 else {
459 tmp->prev->next = tmp->next;
460 tmp->next->prev = tmp->prev;
461 list = tmp->next;
464 fputs(tmp->text, stdout);
466 free(tmp);
469 *buf_p = list;
472 static void insn(const char *insn, struct storage *op1, struct storage *op2,
473 const char *comment_in)
475 struct function *f = current_func;
476 struct atom *atom = new_atom(ATOM_INSN);
478 assert(insn != NULL);
480 strcpy(atom->insn, insn);
481 if (comment_in && (*comment_in))
482 strncpy(atom->comment, comment_in,
483 sizeof(atom->comment) - 1);
485 atom->op1 = op1;
486 atom->op2 = op2;
488 push_atom(f, atom);
491 static void emit_label (int label, const char *comment)
493 struct function *f = current_func;
494 char s[64];
496 if (!comment)
497 sprintf(s, ".L%d:\n", label);
498 else
499 sprintf(s, ".L%d:\t\t\t\t\t# %s\n", label, comment);
501 push_text_atom(f, s);
504 static void emit_labelsym (struct symbol *sym, const char *comment)
506 struct function *f = current_func;
507 char s[64];
509 if (!comment)
510 sprintf(s, ".LS%p:\n", sym);
511 else
512 sprintf(s, ".LS%p:\t\t\t\t# %s\n", sym, comment);
514 push_text_atom(f, s);
517 static void emit_unit_pre(const char *basename)
519 printf("\t.file\t\"%s\"\n", basename);
522 static void emit_unit_post(void)
524 textbuf_emit(&unit_post_text);
525 printf("\t.ident\t\"sparse silly x86 backend (built %s)\"\n", __DATE__);
528 /* conditionally switch sections */
529 static void emit_section(const char *s)
531 if (s == current_section)
532 return;
533 if (current_section && (!strcmp(s, current_section)))
534 return;
536 printf("\t%s\n", s);
537 current_section = s;
540 static void emit_insn_atom(struct function *f, struct atom *atom)
542 char s[128];
543 char comment[64];
544 struct storage *op1 = atom->op1;
545 struct storage *op2 = atom->op2;
547 if (atom->comment[0])
548 sprintf(comment, "\t\t# %s", atom->comment);
549 else
550 comment[0] = 0;
552 if (atom->op2) {
553 char tmp[16];
554 strcpy(tmp, stor_op_name(op1));
555 sprintf(s, "\t%s\t%s, %s%s\n",
556 atom->insn, tmp, stor_op_name(op2), comment);
557 } else if (atom->op1)
558 sprintf(s, "\t%s\t%s%s%s\n",
559 atom->insn, stor_op_name(op1),
560 comment[0] ? "\t" : "", comment);
561 else
562 sprintf(s, "\t%s\t%s%s\n",
563 atom->insn,
564 comment[0] ? "\t\t" : "", comment);
566 write(STDOUT_FILENO, s, strlen(s));
569 static void emit_atom_list(struct function *f)
571 struct atom *atom;
573 FOR_EACH_PTR(f->atom_list, atom) {
574 switch (atom->type) {
575 case ATOM_TEXT: {
576 ssize_t rc = write(STDOUT_FILENO, atom->text,
577 atom->text_len);
578 (void) rc; /* FIXME */
579 break;
581 case ATOM_INSN:
582 emit_insn_atom(f, atom);
583 break;
584 case ATOM_CSTR:
585 assert(0);
586 break;
588 } END_FOR_EACH_PTR;
591 static void emit_string_list(struct function *f)
593 struct atom *atom;
595 emit_section(".section\t.rodata");
597 FOR_EACH_PTR(f->str_list, atom) {
598 /* FIXME: escape " in string */
599 printf(".L%d:\n", atom->label);
600 printf("\t.string\t%s\n", show_string(atom->string));
602 free(atom);
603 } END_FOR_EACH_PTR;
606 static void func_cleanup(struct function *f)
608 struct storage *stor;
609 struct atom *atom;
611 FOR_EACH_PTR(f->pseudo_list, stor) {
612 free(stor);
613 } END_FOR_EACH_PTR;
615 FOR_EACH_PTR(f->atom_list, atom) {
616 if ((atom->type == ATOM_TEXT) && (atom->text))
617 free(atom->text);
618 if (atom->op1 && (atom->op1->flags & STOR_WANTS_FREE))
619 free(atom->op1);
620 if (atom->op2 && (atom->op2->flags & STOR_WANTS_FREE))
621 free(atom->op2);
622 free(atom);
623 } END_FOR_EACH_PTR;
625 free_ptr_list(&f->pseudo_list);
626 free(f);
629 /* function prologue */
630 static void emit_func_pre(struct symbol *sym)
632 struct function *f;
633 struct symbol *arg;
634 unsigned int i, argc = 0, alloc_len;
635 unsigned char *mem;
636 struct symbol_private *privbase;
637 struct storage *storage_base;
638 struct symbol *base_type = sym->ctype.base_type;
640 FOR_EACH_PTR(base_type->arguments, arg) {
641 argc++;
642 } END_FOR_EACH_PTR;
644 alloc_len =
645 sizeof(*f) +
646 (argc * sizeof(struct symbol *)) +
647 (argc * sizeof(struct symbol_private)) +
648 (argc * sizeof(struct storage));
649 mem = calloc(1, alloc_len);
650 if (!mem)
651 die("OOM on func info");
653 f = (struct function *) mem;
654 mem += sizeof(*f);
655 f->argv = (struct symbol **) mem;
656 mem += (argc * sizeof(struct symbol *));
657 privbase = (struct symbol_private *) mem;
658 mem += (argc * sizeof(struct symbol_private));
659 storage_base = (struct storage *) mem;
661 f->argc = argc;
662 f->ret_target = new_label();
664 i = 0;
665 FOR_EACH_PTR(base_type->arguments, arg) {
666 f->argv[i] = arg;
667 arg->aux = &privbase[i];
668 storage_base[i].type = STOR_ARG;
669 storage_base[i].idx = i;
670 privbase[i].addr = &storage_base[i];
671 i++;
672 } END_FOR_EACH_PTR;
674 assert(current_func == NULL);
675 current_func = f;
678 /* function epilogue */
679 static void emit_func_post(struct symbol *sym)
681 const char *name = show_ident(sym->ident);
682 struct function *f = current_func;
683 int stack_size = f->stack_size;
685 if (f->str_list)
686 emit_string_list(f);
688 /* function prologue */
689 emit_section(".text");
690 if ((sym->ctype.modifiers & MOD_STATIC) == 0)
691 printf(".globl %s\n", name);
692 printf("\t.type\t%s, @function\n", name);
693 printf("%s:\n", name);
695 if (stack_size) {
696 char pseudo_const[16];
698 sprintf(pseudo_const, "$%d", stack_size);
699 printf("\tsubl\t%s, %%esp\n", pseudo_const);
702 /* function epilogue */
704 /* jump target for 'return' statements */
705 emit_label(f->ret_target, NULL);
707 if (stack_size) {
708 struct storage *val;
710 val = new_storage(STOR_VALUE);
711 val->value = (long long) (stack_size);
712 val->flags = STOR_WANTS_FREE;
714 insn("addl", val, REG_ESP, NULL);
717 insn("ret", NULL, NULL, NULL);
719 /* output everything to stdout */
720 fflush(stdout); /* paranoia; needed? */
721 emit_atom_list(f);
723 /* function footer */
724 name = show_ident(sym->ident);
725 printf("\t.size\t%s, .-%s\n", name, name);
727 func_cleanup(f);
728 current_func = NULL;
731 /* emit object (a.k.a. variable, a.k.a. data) prologue */
732 static void emit_object_pre(const char *name, unsigned long modifiers,
733 unsigned long alignment, unsigned int byte_size)
735 if ((modifiers & MOD_STATIC) == 0)
736 printf(".globl %s\n", name);
737 emit_section(".data");
738 if (alignment)
739 printf("\t.align %lu\n", alignment);
740 printf("\t.type\t%s, @object\n", name);
741 printf("\t.size\t%s, %d\n", name, byte_size);
742 printf("%s:\n", name);
745 /* emit value (only) for an initializer scalar */
746 static void emit_scalar(struct expression *expr, unsigned int bit_size)
748 const char *type;
749 long long ll;
751 assert(expr->type == EXPR_VALUE);
753 if (expr->value == 0ULL) {
754 printf("\t.zero\t%d\n", bit_size / 8);
755 return;
758 ll = (long long) expr->value;
760 switch (bit_size) {
761 case 8: type = "byte"; ll = (char) ll; break;
762 case 16: type = "value"; ll = (short) ll; break;
763 case 32: type = "long"; ll = (int) ll; break;
764 case 64: type = "quad"; break;
765 default: type = NULL; break;
768 assert(type != NULL);
770 printf("\t.%s\t%Ld\n", type, ll);
773 static void emit_global_noinit(const char *name, unsigned long modifiers,
774 unsigned long alignment, unsigned int byte_size)
776 char s[64];
778 if (modifiers & MOD_STATIC) {
779 sprintf(s, "\t.local\t%s\n", name);
780 textbuf_push(&unit_post_text, s);
782 if (alignment)
783 sprintf(s, "\t.comm\t%s,%d,%lu\n", name, byte_size, alignment);
784 else
785 sprintf(s, "\t.comm\t%s,%d\n", name, byte_size);
786 textbuf_push(&unit_post_text, s);
789 static int ea_current, ea_last;
791 static void emit_initializer(struct symbol *sym,
792 struct expression *expr)
794 int distance = ea_current - ea_last - 1;
796 if (distance > 0)
797 printf("\t.zero\t%d\n", (sym->bit_size / 8) * distance);
799 if (expr->type == EXPR_VALUE) {
800 struct symbol *base_type = sym->ctype.base_type;
801 assert(base_type != NULL);
803 emit_scalar(expr, sym->bit_size / get_expression_value(base_type->array_size));
804 return;
806 if (expr->type != EXPR_INITIALIZER)
807 return;
809 assert(0); /* FIXME */
812 static int sort_array_cmp(const struct expression *a,
813 const struct expression *b)
815 int a_ofs = 0, b_ofs = 0;
817 if (a->type == EXPR_POS)
818 a_ofs = (int) a->init_offset;
819 if (b->type == EXPR_POS)
820 b_ofs = (int) b->init_offset;
822 return a_ofs - b_ofs;
825 /* move to front-end? */
826 static void sort_array(struct expression *expr)
828 struct expression *entry, **list;
829 unsigned int elem, sorted, i;
831 elem = 0;
832 FOR_EACH_PTR(expr->expr_list, entry) {
833 elem++;
834 } END_FOR_EACH_PTR;
836 if (!elem)
837 return;
839 list = malloc(sizeof(entry) * elem);
840 if (!list)
841 die("OOM in sort_array");
843 /* this code is no doubt evil and ignores EXPR_INDEX possibly
844 * to its detriment and other nasty things. improvements
845 * welcome.
847 i = 0;
848 sorted = 0;
849 FOR_EACH_PTR(expr->expr_list, entry) {
850 if ((entry->type == EXPR_POS) || (entry->type == EXPR_VALUE)) {
851 /* add entry to list[], in sorted order */
852 if (sorted == 0) {
853 list[0] = entry;
854 sorted = 1;
855 } else {
856 unsigned int i;
858 for (i = 0; i < sorted; i++)
859 if (sort_array_cmp(entry, list[i]) <= 0)
860 break;
862 /* If inserting into the middle of list[]
863 * instead of appending, we memmove.
864 * This is ugly, but thankfully
865 * uncommon. Input data with tons of
866 * entries very rarely have explicit
867 * offsets. convert to qsort eventually...
869 if (i != sorted)
870 memmove(&list[i + 1], &list[i],
871 (sorted - i) * sizeof(entry));
872 list[i] = entry;
873 sorted++;
876 } END_FOR_EACH_PTR;
878 i = 0;
879 FOR_EACH_PTR(expr->expr_list, entry) {
880 if ((entry->type == EXPR_POS) || (entry->type == EXPR_VALUE))
881 __list->list[__i] = list[i++];
882 } END_FOR_EACH_PTR;
886 static void emit_array(struct symbol *sym)
888 struct symbol *base_type = sym->ctype.base_type;
889 struct expression *expr = sym->initializer;
890 struct expression *entry;
892 assert(base_type != NULL);
894 stor_sym_init(sym);
896 ea_last = -1;
898 emit_object_pre(show_ident(sym->ident), sym->ctype.modifiers,
899 sym->ctype.alignment,
900 sym->bit_size / 8);
902 sort_array(expr);
904 FOR_EACH_PTR(expr->expr_list, entry) {
905 if (entry->type == EXPR_VALUE) {
906 ea_current = 0;
907 emit_initializer(sym, entry);
908 ea_last = ea_current;
909 } else if (entry->type == EXPR_POS) {
910 ea_current =
911 entry->init_offset / (base_type->bit_size / 8);
912 emit_initializer(sym, entry->init_expr);
913 ea_last = ea_current;
915 } END_FOR_EACH_PTR;
918 static void emit_one_symbol(struct symbol *sym, void *dummy, int flags)
920 x86_symbol(sym);
923 void emit_unit(const char *basename, struct symbol_list *list)
925 emit_unit_pre(basename);
926 symbol_iterate(list, emit_one_symbol, NULL);
927 emit_unit_post();
930 static void emit_copy(struct storage *dest, struct storage *src,
931 struct symbol *ctype)
933 struct storage *reg = NULL;
935 /* FIXME: Bitfield move! */
937 switch (ctype->bit_size) {
938 case 8:
939 reg = REG_AL;
940 break;
941 case 16:
942 reg = REG_AX;
943 break;
944 case 32:
945 reg = REG_EAX;
946 break;
947 case 64:
948 reg = REG_EAX; /* FIXME */
949 break;
950 default:
951 assert(0);
952 break;
955 emit_move(src, reg, ctype, "begin copy ..");
956 emit_move(reg, dest, ctype, ".... end copy");
959 static void emit_store(struct expression *dest_expr, struct storage *dest,
960 struct storage *src, int bits)
962 /* FIXME: Bitfield store! */
963 printf("\tst.%d\t\tv%d,[v%d]\n", bits, src->pseudo, dest->pseudo);
966 static void emit_scalar_noinit(struct symbol *sym)
968 emit_global_noinit(show_ident(sym->ident),
969 sym->ctype.modifiers, sym->ctype.alignment,
970 sym->bit_size / 8);
971 stor_sym_init(sym);
974 static void emit_array_noinit(struct symbol *sym)
976 emit_global_noinit(show_ident(sym->ident),
977 sym->ctype.modifiers, sym->ctype.alignment,
978 get_expression_value(sym->array_size) * (sym->bit_size / 8));
979 stor_sym_init(sym);
982 static const char *opbits(const char *insn, unsigned int bits)
984 static char opbits_str[32];
985 char c;
987 switch (bits) {
988 case 8: c = 'b'; break;
989 case 16: c = 'w'; break;
990 case 32: c = 'l'; break;
991 case 64: c = 'q'; break;
992 default: assert(0); break;
995 sprintf(opbits_str, "%s%c", insn, bits);
997 return opbits_str;
1000 static void emit_move(struct storage *src, struct storage *dest,
1001 struct symbol *ctype, const char *comment)
1003 unsigned int bits;
1004 unsigned int is_signed;
1005 unsigned int is_dest = (src->type == STOR_REG);
1006 const char *opname;
1008 if (ctype) {
1009 bits = ctype->bit_size;
1010 is_signed = type_is_signed(ctype);
1011 } else {
1012 bits = 32;
1013 is_signed = 0;
1016 if ((dest->type == STOR_REG) && (src->type == STOR_REG)) {
1017 insn("mov", src, dest, NULL);
1018 return;
1021 switch (bits) {
1022 case 8:
1023 if (is_dest)
1024 opname = "movb";
1025 else {
1026 if (is_signed) opname = "movsxb";
1027 else opname = "movzxb";
1029 break;
1030 case 16:
1031 if (is_dest)
1032 opname = "movw";
1033 else {
1034 if (is_signed) opname = "movsxw";
1035 else opname = "movzxw";
1037 break;
1039 case 32: opname = "movl"; break;
1040 case 64: opname = "movq"; break;
1042 default: assert(0); break;
1045 insn(opname, src, dest, comment);
1048 static struct storage *emit_compare(struct expression *expr)
1050 struct storage *left = x86_expression(expr->left);
1051 struct storage *right = x86_expression(expr->right);
1052 struct storage *new, *val;
1053 const char *opname = NULL;
1054 unsigned int is_signed = type_is_signed(expr->left->ctype); /* FIXME */
1055 unsigned int right_bits = expr->right->ctype->bit_size;
1057 switch(expr->op) {
1058 case '<':
1059 if (is_signed) opname = "setl";
1060 else opname = "setb";
1061 break;
1062 case '>':
1063 if (is_signed) opname = "setg";
1064 else opname = "seta";
1065 break;
1066 case SPECIAL_LTE:
1067 if (is_signed) opname = "setle";
1068 else opname = "setbe";
1069 break;
1070 case SPECIAL_GTE:
1071 if (is_signed) opname = "setge";
1072 else opname = "setae";
1073 break;
1075 case SPECIAL_EQUAL: opname = "sete"; break;
1076 case SPECIAL_NOTEQUAL: opname = "setne"; break;
1078 default:
1079 assert(0);
1080 break;
1083 /* init EDX to 0 */
1084 val = new_storage(STOR_VALUE);
1085 val->flags = STOR_WANTS_FREE;
1086 emit_move(val, REG_EDX, NULL, NULL);
1088 /* move op1 into EAX */
1089 emit_move(left, REG_EAX, expr->left->ctype, NULL);
1091 /* perform comparison, RHS (op1, right) and LHS (op2, EAX) */
1092 insn(opbits("cmp", right_bits), right, REG_EAX, NULL);
1094 /* store result of operation, 0 or 1, in DL using SETcc */
1095 insn(opname, REG_DL, NULL, NULL);
1097 /* finally, store the result (DL) in a new pseudo / stack slot */
1098 new = stack_alloc(4);
1099 emit_move(REG_EDX, new, NULL, "end EXPR_COMPARE");
1101 return new;
1104 static struct storage *emit_value(struct expression *expr)
1106 #if 0 /* old and slow way */
1107 struct storage *new = stack_alloc(4);
1108 struct storage *val;
1110 val = new_storage(STOR_VALUE);
1111 val->value = (long long) expr->value;
1112 val->flags = STOR_WANTS_FREE;
1113 insn("movl", val, new, NULL);
1115 return new;
1116 #else
1117 struct storage *val;
1119 val = new_storage(STOR_VALUE);
1120 val->value = (long long) expr->value;
1122 return val; /* FIXME: memory leak */
1123 #endif
1126 static struct storage *emit_binop(struct expression *expr)
1128 struct storage *left = x86_expression(expr->left);
1129 struct storage *right = x86_expression(expr->right);
1130 struct storage *new;
1131 struct storage *accum_reg = NULL;
1132 struct storage *result_reg = NULL;
1133 const char *opname = NULL;
1134 const char *suffix;
1135 char movstr[16], opstr[16];
1136 int is_signed, doing_divide = 0;
1138 if ((expr->op == '/') || (expr->op == '%')) {
1139 struct storage *val;
1141 doing_divide = 1;
1142 /* init EDX to 0 */
1143 val = new_storage(STOR_VALUE);
1144 val->flags = STOR_WANTS_FREE;
1145 emit_move(val, REG_EDX, NULL, "begin EXPR_DIVIDE");
1148 is_signed = type_is_signed(expr->ctype);
1150 switch (expr->op) {
1151 case '+':
1152 opname = "add";
1153 break;
1154 case '-':
1155 opname = "sub";
1156 break;
1157 case '&':
1158 opname = "and";
1159 break;
1160 case '|':
1161 opname = "or";
1162 break;
1163 case '^':
1164 opname = "xor";
1165 break;
1166 case SPECIAL_LEFTSHIFT:
1167 opname = "shl";
1168 break;
1169 case SPECIAL_RIGHTSHIFT:
1170 if (is_signed)
1171 opname = "sar";
1172 else
1173 opname = "shr";
1174 break;
1175 case '*':
1176 if (is_signed)
1177 opname = "imul";
1178 else
1179 opname = "mul";
1180 break;
1181 case '/':
1182 case '%':
1183 if (is_signed)
1184 opname = "idiv";
1185 else
1186 opname = "div";
1187 break;
1188 default:
1189 assert(0);
1190 break;
1193 switch (expr->ctype->bit_size) {
1194 case 8:
1195 suffix = "b";
1196 result_reg = accum_reg = REG_AL;
1197 if (expr->op == '%')
1198 result_reg = REG_DL;
1199 break;
1200 case 16:
1201 suffix = "w";
1202 result_reg = accum_reg = REG_AX;
1203 if (expr->op == '%')
1204 result_reg = REG_DX;
1205 break;
1206 case 32:
1207 suffix = "l";
1208 result_reg = accum_reg = REG_EAX;
1209 if (expr->op == '%')
1210 result_reg = REG_EDX;
1211 break;
1212 case 64:
1213 suffix = "q"; /* FIXME */
1214 result_reg = accum_reg = REG_EAX; /* FIXME */
1215 if (expr->op == '%')
1216 result_reg = REG_EDX;
1217 break;
1218 default:
1219 assert(0);
1220 break;
1223 sprintf(movstr, "mov%s", suffix);
1224 sprintf(opstr, "%s%s", opname, suffix);
1226 /* load op2 into EAX */
1227 insn(movstr, right, accum_reg,
1228 doing_divide ? NULL : "EXPR_BINOP/COMMA/LOGICAL");
1230 /* perform binop */
1231 insn(opstr, left, accum_reg, NULL);
1233 /* store result (EAX or EDX) in new pseudo / stack slot */
1234 new = stack_alloc(4);
1235 insn(movstr, result_reg, new,
1236 doing_divide ? "end EXPR_DIVIDE" : "end EXPR_BINOP");
1238 return new;
1241 static void emit_if_conditional(struct statement *stmt)
1243 struct storage *val, *target_val;
1244 int target;
1245 struct expression *cond = stmt->if_conditional;
1247 /* This is only valid if nobody can jump into the "dead" statement */
1248 #if 0
1249 if (cond->type == EXPR_VALUE) {
1250 struct statement *s = stmt->if_true;
1251 if (!cond->value)
1252 s = stmt->if_false;
1253 x86_statement(s);
1254 break;
1256 #endif
1257 val = x86_expression(cond);
1259 /* load 'if' test result into EAX */
1260 insn("movl", val, REG_EAX, "begin if conditional");
1262 /* compare 'if' test result */
1263 insn("test", REG_EAX, REG_EAX, NULL);
1265 /* create end-of-if label / if-failed labelto jump to,
1266 * and jump to it if the expression returned zero.
1268 target = new_label();
1269 target_val = new_storage(STOR_LABEL);
1270 target_val->label = target;
1271 target_val->flags = STOR_WANTS_FREE;
1272 insn("jz", target_val, NULL, NULL);
1274 x86_statement(stmt->if_true);
1275 if (stmt->if_false) {
1276 struct storage *last_val;
1277 int last;
1279 /* finished generating code for if-true statement.
1280 * add a jump-to-end jump to avoid falling through
1281 * to the if-false statement code.
1283 last = new_label();
1284 last_val = new_storage(STOR_LABEL);
1285 last_val->label = last;
1286 last_val->flags = STOR_WANTS_FREE;
1287 insn("jmp", last_val, NULL, NULL);
1289 /* if we have both if-true and if-false statements,
1290 * the failed-conditional case will fall through to here
1292 emit_label(target, NULL);
1294 target = last;
1295 x86_statement(stmt->if_false);
1298 emit_label(target, "end if");
1301 static struct storage *emit_inc_dec(struct expression *expr, int postop)
1303 struct storage *addr = x86_address_gen(expr->unop);
1304 struct storage *retval;
1305 char opname[16];
1307 strcpy(opname, opbits(expr->op == SPECIAL_INCREMENT ? "inc" : "dec",
1308 expr->ctype->bit_size));
1310 if (postop) {
1311 struct storage *new = stack_alloc(4);
1313 emit_copy(new, addr, expr->unop->ctype);
1315 retval = new;
1316 } else
1317 retval = addr;
1319 insn(opname, addr, NULL, NULL);
1321 return retval;
1324 static struct storage *emit_postop(struct expression *expr)
1326 return emit_inc_dec(expr, 1);
1329 static struct storage *emit_return_stmt(struct statement *stmt)
1331 struct function *f = current_func;
1332 struct expression *expr = stmt->ret_value;
1333 struct storage *val = NULL, *jmplbl;
1335 if (expr && expr->ctype) {
1336 val = x86_expression(expr);
1337 assert(val != NULL);
1338 emit_move(val, REG_EAX, expr->ctype, "return");
1341 jmplbl = new_storage(STOR_LABEL);
1342 jmplbl->flags |= STOR_WANTS_FREE;
1343 jmplbl->label = f->ret_target;
1344 insn("jmp", jmplbl, NULL, NULL);
1346 return val;
1349 static struct storage *emit_conditional_expr(struct expression *expr)
1351 struct storage *cond = x86_expression(expr->conditional);
1352 struct storage *true = x86_expression(expr->cond_true);
1353 struct storage *false = x86_expression(expr->cond_false);
1354 struct storage *new = stack_alloc(4);
1356 if (!true)
1357 true = cond;
1359 emit_move(cond, REG_EAX, expr->conditional->ctype,
1360 "begin EXPR_CONDITIONAL");
1361 emit_move(true, REG_ECX, expr->cond_true->ctype, NULL);
1362 emit_move(false, REG_EDX, expr->cond_false->ctype, NULL);
1364 /* test EAX (for zero/non-zero) */
1365 insn("test", REG_EAX, REG_EAX, NULL);
1367 /* if false, move EDX to ECX */
1368 insn("cmovz", REG_EDX, REG_ECX, NULL);
1370 /* finally, store the result (ECX) in a new pseudo / stack slot */
1371 new = stack_alloc(4);
1372 emit_move(REG_ECX, new, expr->ctype, "end EXPR_CONDITIONAL");
1373 /* FIXME: we lose type knowledge of expression result at this point */
1375 return new;
1378 static struct storage *emit_symbol_expr_init(struct symbol *sym)
1380 struct expression *expr = sym->initializer;
1381 struct symbol_private *priv = sym->aux;
1383 if (priv == NULL) {
1384 priv = calloc(1, sizeof(*priv));
1385 sym->aux = priv;
1387 if (expr == NULL) {
1388 struct storage *new = stack_alloc(4);
1389 fprintf(stderr, "FIXME! no value for symbol. creating pseudo %d (stack offset %d)\n",
1390 new->pseudo, new->pseudo * 4);
1391 priv->addr = new;
1392 } else {
1393 priv->addr = x86_expression(expr);
1397 return priv->addr;
1400 static struct storage *emit_string_expr(struct expression *expr)
1402 struct function *f = current_func;
1403 int label = new_label();
1404 struct storage *new;
1406 push_cstring(f, expr->string, label);
1408 new = new_storage(STOR_LABEL);
1409 new->label = label;
1410 new->flags = STOR_LABEL_VAL | STOR_WANTS_FREE;
1411 return new;
1414 static struct storage *emit_cast_expr(struct expression *expr)
1416 struct symbol *old_type, *new_type;
1417 struct storage *op = x86_expression(expr->cast_expression);
1418 int oldbits, newbits;
1419 struct storage *new;
1421 old_type = expr->cast_expression->ctype;
1422 new_type = expr->cast_type;
1424 oldbits = old_type->bit_size;
1425 newbits = new_type->bit_size;
1426 if (oldbits >= newbits)
1427 return op;
1429 emit_move(op, REG_EAX, old_type, "begin cast ..");
1431 new = stack_alloc(4);
1432 emit_move(REG_EAX, new, new_type, ".... end cast");
1434 return new;
1437 static struct storage *emit_regular_preop(struct expression *expr)
1439 struct storage *target = x86_expression(expr->unop);
1440 struct storage *val, *new = stack_alloc(4);
1441 const char *opname = NULL;
1443 switch (expr->op) {
1444 case '!':
1445 val = new_storage(STOR_VALUE);
1446 val->flags = STOR_WANTS_FREE;
1447 emit_move(val, REG_EDX, NULL, NULL);
1448 emit_move(target, REG_EAX, expr->unop->ctype, NULL);
1449 insn("test", REG_EAX, REG_EAX, NULL);
1450 insn("setz", REG_DL, NULL, NULL);
1451 emit_move(REG_EDX, new, expr->unop->ctype, NULL);
1453 break;
1454 case '~':
1455 opname = "not";
1456 case '-':
1457 if (!opname)
1458 opname = "neg";
1459 emit_move(target, REG_EAX, expr->unop->ctype, NULL);
1460 insn(opname, REG_EAX, NULL, NULL);
1461 emit_move(REG_EAX, new, expr->unop->ctype, NULL);
1462 break;
1463 default:
1464 assert(0);
1465 break;
1468 return new;
1471 static void emit_case_statement(struct statement *stmt)
1473 emit_labelsym(stmt->case_label, NULL);
1474 x86_statement(stmt->case_statement);
1477 static void emit_switch_statement(struct statement *stmt)
1479 struct storage *val = x86_expression(stmt->switch_expression);
1480 struct symbol *sym, *default_sym = NULL;
1481 struct storage *labelsym, *label;
1482 int switch_end = 0;
1484 emit_move(val, REG_EAX, stmt->switch_expression->ctype, "begin case");
1487 * This is where a _real_ back-end would go through the
1488 * cases to decide whether to use a lookup table or a
1489 * series of comparisons etc
1491 FOR_EACH_PTR(stmt->switch_case->symbol_list, sym) {
1492 struct statement *case_stmt = sym->stmt;
1493 struct expression *expr = case_stmt->case_expression;
1494 struct expression *to = case_stmt->case_to;
1496 /* default: */
1497 if (!expr)
1498 default_sym = sym;
1500 /* case NNN: */
1501 else {
1502 struct storage *case_val = new_val(expr->value);
1504 assert (expr->type == EXPR_VALUE);
1506 insn("cmpl", case_val, REG_EAX, NULL);
1508 if (!to) {
1509 labelsym = new_labelsym(sym);
1510 insn("je", labelsym, NULL, NULL);
1511 } else {
1512 int next_test;
1514 label = new_storage(STOR_LABEL);
1515 label->flags |= STOR_WANTS_FREE;
1516 label->label = next_test = new_label();
1518 /* FIXME: signed/unsigned */
1519 insn("jl", label, NULL, NULL);
1521 case_val = new_val(to->value);
1522 insn("cmpl", case_val, REG_EAX, NULL);
1524 /* TODO: implement and use refcounting... */
1525 label = new_storage(STOR_LABEL);
1526 label->flags |= STOR_WANTS_FREE;
1527 label->label = next_test;
1529 /* FIXME: signed/unsigned */
1530 insn("jg", label, NULL, NULL);
1532 labelsym = new_labelsym(sym);
1533 insn("jmp", labelsym, NULL, NULL);
1535 emit_label(next_test, NULL);
1538 } END_FOR_EACH_PTR;
1540 if (default_sym) {
1541 labelsym = new_labelsym(default_sym);
1542 insn("jmp", labelsym, NULL, "default");
1543 } else {
1544 label = new_storage(STOR_LABEL);
1545 label->flags |= STOR_WANTS_FREE;
1546 label->label = switch_end = new_label();
1547 insn("jmp", label, NULL, "goto end of switch");
1550 x86_statement(stmt->switch_statement);
1552 if (stmt->switch_break->used)
1553 emit_labelsym(stmt->switch_break, NULL);
1555 if (switch_end)
1556 emit_label(switch_end, NULL);
1559 static void x86_struct_member(struct symbol *sym, void *data, int flags)
1561 if (flags & ITERATE_FIRST)
1562 printf(" {\n\t");
1563 printf("%s:%d:%ld at offset %ld", show_ident(sym->ident), sym->bit_size, sym->ctype.alignment, sym->offset);
1564 if (sym->fieldwidth)
1565 printf("[%d..%d]", sym->bit_offset, sym->bit_offset+sym->fieldwidth-1);
1566 if (flags & ITERATE_LAST)
1567 printf("\n} ");
1568 else
1569 printf(", ");
1572 static void x86_symbol(struct symbol *sym)
1574 struct symbol *type;
1576 if (!sym)
1577 return;
1579 type = sym->ctype.base_type;
1580 if (!type)
1581 return;
1584 * Show actual implementation information
1586 switch (type->type) {
1588 case SYM_ARRAY:
1589 if (sym->initializer)
1590 emit_array(sym);
1591 else
1592 emit_array_noinit(sym);
1593 break;
1595 case SYM_BASETYPE:
1596 if (sym->initializer) {
1597 emit_object_pre(show_ident(sym->ident),
1598 sym->ctype.modifiers,
1599 sym->ctype.alignment,
1600 sym->bit_size / 8);
1601 emit_scalar(sym->initializer, sym->bit_size);
1602 stor_sym_init(sym);
1603 } else
1604 emit_scalar_noinit(sym);
1605 break;
1607 case SYM_STRUCT:
1608 symbol_iterate(type->symbol_list, x86_struct_member, NULL);
1609 break;
1611 case SYM_UNION:
1612 symbol_iterate(type->symbol_list, x86_struct_member, NULL);
1613 break;
1615 case SYM_FN: {
1616 struct statement *stmt = type->stmt;
1617 if (stmt) {
1618 emit_func_pre(sym);
1619 x86_statement(stmt);
1620 emit_func_post(sym);
1622 break;
1625 default:
1626 break;
1629 if (sym->initializer && (type->type != SYM_BASETYPE) &&
1630 (type->type != SYM_ARRAY)) {
1631 printf(" = \n");
1632 x86_expression(sym->initializer);
1636 static void x86_symbol_init(struct symbol *sym);
1638 static void x86_symbol_decl(struct symbol_list *syms)
1640 struct symbol *sym;
1641 FOR_EACH_PTR(syms, sym) {
1642 x86_symbol_init(sym);
1643 } END_FOR_EACH_PTR;
1646 static void loopstk_push(int cont_lbl, int loop_bottom_lbl)
1648 struct function *f = current_func;
1649 struct loop_stack *ls;
1651 ls = malloc(sizeof(*ls));
1652 ls->continue_lbl = cont_lbl;
1653 ls->loop_bottom_lbl = loop_bottom_lbl;
1654 ls->next = f->loop_stack;
1655 f->loop_stack = ls;
1658 static void loopstk_pop(void)
1660 struct function *f = current_func;
1661 struct loop_stack *ls;
1663 assert(f->loop_stack != NULL);
1664 ls = f->loop_stack;
1665 f->loop_stack = f->loop_stack->next;
1666 free(ls);
1669 static int loopstk_break(void)
1671 return current_func->loop_stack->loop_bottom_lbl;
1674 static int loopstk_continue(void)
1676 return current_func->loop_stack->continue_lbl;
1679 static void emit_loop(struct statement *stmt)
1681 struct statement *pre_statement = stmt->iterator_pre_statement;
1682 struct expression *pre_condition = stmt->iterator_pre_condition;
1683 struct statement *statement = stmt->iterator_statement;
1684 struct statement *post_statement = stmt->iterator_post_statement;
1685 struct expression *post_condition = stmt->iterator_post_condition;
1686 int loop_top = 0, loop_bottom, loop_continue;
1687 int have_bottom = 0;
1688 struct storage *val;
1690 loop_bottom = new_label();
1691 loop_continue = new_label();
1692 loopstk_push(loop_continue, loop_bottom);
1694 x86_symbol_decl(stmt->iterator_syms);
1695 x86_statement(pre_statement);
1696 if (pre_condition) {
1697 if (pre_condition->type == EXPR_VALUE) {
1698 if (!pre_condition->value) {
1699 struct storage *lbv;
1700 lbv = new_storage(STOR_LABEL);
1701 lbv->label = loop_bottom;
1702 lbv->flags = STOR_WANTS_FREE;
1703 insn("jmp", lbv, NULL, "go to loop bottom");
1704 have_bottom = 1;
1706 } else {
1707 struct storage *lbv = new_storage(STOR_LABEL);
1708 lbv->label = loop_bottom;
1709 lbv->flags = STOR_WANTS_FREE;
1710 have_bottom = 1;
1712 val = x86_expression(pre_condition);
1714 emit_move(val, REG_EAX, NULL, "loop pre condition");
1715 insn("test", REG_EAX, REG_EAX, NULL);
1716 insn("jz", lbv, NULL, NULL);
1719 if (!post_condition || post_condition->type != EXPR_VALUE || post_condition->value) {
1720 loop_top = new_label();
1721 emit_label(loop_top, "loop top");
1723 x86_statement(statement);
1724 if (stmt->iterator_continue->used)
1725 emit_label(loop_continue, "'continue' iterator");
1726 x86_statement(post_statement);
1727 if (!post_condition) {
1728 struct storage *lbv = new_storage(STOR_LABEL);
1729 lbv->label = loop_top;
1730 lbv->flags = STOR_WANTS_FREE;
1731 insn("jmp", lbv, NULL, "go to loop top");
1732 } else if (post_condition->type == EXPR_VALUE) {
1733 if (post_condition->value) {
1734 struct storage *lbv = new_storage(STOR_LABEL);
1735 lbv->label = loop_top;
1736 lbv->flags = STOR_WANTS_FREE;
1737 insn("jmp", lbv, NULL, "go to loop top");
1739 } else {
1740 struct storage *lbv = new_storage(STOR_LABEL);
1741 lbv->label = loop_top;
1742 lbv->flags = STOR_WANTS_FREE;
1744 val = x86_expression(post_condition);
1746 emit_move(val, REG_EAX, NULL, "loop post condition");
1747 insn("test", REG_EAX, REG_EAX, NULL);
1748 insn("jnz", lbv, NULL, NULL);
1750 if (have_bottom || stmt->iterator_break->used)
1751 emit_label(loop_bottom, "loop bottom");
1753 loopstk_pop();
1757 * Print out a statement
1759 static struct storage *x86_statement(struct statement *stmt)
1761 if (!stmt)
1762 return NULL;
1763 switch (stmt->type) {
1764 case STMT_RETURN:
1765 return emit_return_stmt(stmt);
1766 case STMT_COMPOUND: {
1767 struct statement *s;
1768 struct storage *last = NULL;
1770 x86_symbol_decl(stmt->syms);
1771 FOR_EACH_PTR(stmt->stmts, s) {
1772 last = x86_statement(s);
1773 } END_FOR_EACH_PTR;
1775 return last;
1778 case STMT_EXPRESSION:
1779 return x86_expression(stmt->expression);
1780 case STMT_IF:
1781 emit_if_conditional(stmt);
1782 return NULL;
1784 case STMT_CASE:
1785 emit_case_statement(stmt);
1786 break;
1787 case STMT_SWITCH:
1788 emit_switch_statement(stmt);
1789 break;
1791 case STMT_ITERATOR:
1792 emit_loop(stmt);
1793 break;
1795 case STMT_NONE:
1796 break;
1798 case STMT_LABEL:
1799 printf(".L%p:\n", stmt->label_identifier);
1800 x86_statement(stmt->label_statement);
1801 break;
1803 case STMT_GOTO:
1804 if (stmt->goto_expression) {
1805 struct storage *val = x86_expression(stmt->goto_expression);
1806 printf("\tgoto *v%d\n", val->pseudo);
1807 } else if (!strcmp("break", show_ident(stmt->goto_label->ident))) {
1808 struct storage *lbv = new_storage(STOR_LABEL);
1809 lbv->label = loopstk_break();
1810 lbv->flags = STOR_WANTS_FREE;
1811 insn("jmp", lbv, NULL, "'break'; go to loop bottom");
1812 } else if (!strcmp("continue", show_ident(stmt->goto_label->ident))) {
1813 struct storage *lbv = new_storage(STOR_LABEL);
1814 lbv->label = loopstk_continue();
1815 lbv->flags = STOR_WANTS_FREE;
1816 insn("jmp", lbv, NULL, "'continue'; go to loop top");
1817 } else {
1818 struct storage *labelsym = new_labelsym(stmt->goto_label);
1819 insn("jmp", labelsym, NULL, NULL);
1821 break;
1822 case STMT_ASM:
1823 printf("\tasm( .... )\n");
1824 break;
1826 return NULL;
1829 static struct storage *x86_call_expression(struct expression *expr)
1831 struct function *f = current_func;
1832 struct symbol *direct;
1833 struct expression *arg, *fn;
1834 struct storage *retval, *fncall;
1835 int framesize;
1836 char s[64];
1838 if (!expr->ctype) {
1839 warn(expr->pos, "\tcall with no type!");
1840 return NULL;
1843 framesize = 0;
1844 FOR_EACH_PTR_REVERSE(expr->args, arg) {
1845 struct storage *new = x86_expression(arg);
1846 int size = arg->ctype->bit_size;
1848 /* FIXME: pay attention to 'size' */
1849 insn("pushl", new, NULL,
1850 !framesize ? "begin function call" : NULL);
1852 framesize += size >> 3;
1853 } END_FOR_EACH_PTR_REVERSE;
1855 fn = expr->fn;
1857 /* Remove dereference, if any */
1858 direct = NULL;
1859 if (fn->type == EXPR_PREOP) {
1860 if (fn->unop->type == EXPR_SYMBOL) {
1861 struct symbol *sym = fn->unop->symbol;
1862 if (sym->ctype.base_type->type == SYM_FN)
1863 direct = sym;
1866 if (direct) {
1867 struct storage *direct_stor = new_storage(STOR_SYM);
1868 direct_stor->flags |= STOR_WANTS_FREE;
1869 direct_stor->sym = direct;
1870 insn("call", direct_stor, NULL, NULL);
1871 } else {
1872 fncall = x86_expression(fn);
1873 emit_move(fncall, REG_EAX, fn->ctype, NULL);
1875 strcpy(s, "\tcall\t*%eax\n");
1876 push_text_atom(f, s);
1879 /* FIXME: pay attention to BITS_IN_POINTER */
1880 if (framesize) {
1881 struct storage *val = new_storage(STOR_VALUE);
1882 val->value = (long long) framesize;
1883 val->flags = STOR_WANTS_FREE;
1884 insn("addl", val, REG_ESP, NULL);
1887 retval = stack_alloc(4);
1888 emit_move(REG_EAX, retval, NULL, "end function call");
1890 return retval;
1893 static struct storage *x86_address_gen(struct expression *expr)
1895 struct function *f = current_func;
1896 struct storage *addr;
1897 struct storage *new;
1898 char s[32];
1900 if ((expr->type != EXPR_PREOP) || (expr->op != '*'))
1901 return x86_expression(expr->address);
1903 addr = x86_expression(expr->unop);
1904 if (expr->unop->type == EXPR_SYMBOL)
1905 return addr;
1907 emit_move(addr, REG_EAX, NULL, "begin deref ..");
1909 /* FIXME: operand size */
1910 strcpy(s, "\tmovl\t(%eax), %ecx\n");
1911 push_text_atom(f, s);
1913 new = stack_alloc(4);
1914 emit_move(REG_ECX, new, NULL, ".... end deref");
1916 return new;
1919 static struct storage *x86_assignment(struct expression *expr)
1921 struct expression *target = expr->left;
1922 struct storage *val, *addr;
1924 if (!expr->ctype)
1925 return NULL;
1927 val = x86_expression(expr->right);
1928 addr = x86_address_gen(target);
1930 switch (val->type) {
1931 /* copy, where both operands are memory */
1932 case STOR_PSEUDO:
1933 case STOR_ARG:
1934 emit_copy(addr, val, expr->ctype);
1935 break;
1937 /* copy, one or zero operands are memory */
1938 case STOR_REG:
1939 case STOR_SYM:
1940 case STOR_VALUE:
1941 case STOR_LABEL:
1942 emit_move(val, addr, expr->left->ctype, NULL);
1943 break;
1945 case STOR_LABELSYM:
1946 assert(0);
1947 break;
1949 return val;
1952 static int x86_initialization(struct symbol *sym, struct expression *expr)
1954 struct storage *val, *addr;
1955 int bits;
1957 if (!expr->ctype)
1958 return 0;
1960 bits = expr->ctype->bit_size;
1961 val = x86_expression(expr);
1962 addr = x86_symbol_expr(sym);
1963 // FIXME! The "target" expression is for bitfield store information.
1964 // Leave it NULL, which works fine.
1965 emit_store(NULL, addr, val, bits);
1966 return 0;
1969 static struct storage *x86_access(struct expression *expr)
1971 return x86_address_gen(expr);
1974 static struct storage *x86_preop(struct expression *expr)
1977 * '*' is an lvalue access, and is fundamentally different
1978 * from an arithmetic operation. Maybe it should have an
1979 * expression type of its own..
1981 if (expr->op == '*')
1982 return x86_access(expr);
1983 if (expr->op == SPECIAL_INCREMENT || expr->op == SPECIAL_DECREMENT)
1984 return emit_inc_dec(expr, 0);
1985 return emit_regular_preop(expr);
1988 static struct storage *x86_symbol_expr(struct symbol *sym)
1990 struct storage *new = stack_alloc(4);
1992 if (sym->ctype.modifiers & (MOD_TOPLEVEL | MOD_EXTERN | MOD_STATIC)) {
1993 printf("\tmovi.%d\t\tv%d,$%s\n", bits_in_pointer, new->pseudo, show_ident(sym->ident));
1994 return new;
1996 if (sym->ctype.modifiers & MOD_ADDRESSABLE) {
1997 printf("\taddi.%d\t\tv%d,vFP,$%lld\n", bits_in_pointer, new->pseudo, sym->value);
1998 return new;
2000 printf("\taddi.%d\t\tv%d,vFP,$offsetof(%s:%p)\n", bits_in_pointer, new->pseudo, show_ident(sym->ident), sym);
2001 return new;
2004 static void x86_symbol_init(struct symbol *sym)
2006 struct symbol_private *priv = sym->aux;
2007 struct expression *expr = sym->initializer;
2008 struct storage *new;
2010 if (expr)
2011 new = x86_expression(expr);
2012 else
2013 new = stack_alloc(sym->bit_size / 8);
2015 if (!priv) {
2016 priv = calloc(1, sizeof(*priv));
2017 sym->aux = priv;
2018 /* FIXME: leak! we don't free... */
2019 /* (well, we don't free symbols either) */
2022 priv->addr = new;
2025 static int type_is_signed(struct symbol *sym)
2027 if (sym->type == SYM_NODE)
2028 sym = sym->ctype.base_type;
2029 if (sym->type == SYM_PTR)
2030 return 0;
2031 return !(sym->ctype.modifiers & MOD_UNSIGNED);
2034 static struct storage *x86_bitfield_expr(struct expression *expr)
2036 return x86_access(expr);
2039 static struct storage *x86_label_expr(struct expression *expr)
2041 struct storage *new = stack_alloc(4);
2042 printf("\tmovi.%d\t\tv%d,.L%p\n", bits_in_pointer, new->pseudo, expr->label_symbol);
2043 return new;
2046 static struct storage *x86_statement_expr(struct expression *expr)
2048 return x86_statement(expr->statement);
2051 static int x86_position_expr(struct expression *expr, struct symbol *base)
2053 struct storage *new = x86_expression(expr->init_expr);
2054 struct symbol *ctype = expr->init_sym;
2056 printf("\tinsert v%d at [%d:%d] of %s\n", new->pseudo,
2057 expr->init_offset, ctype->bit_offset,
2058 show_ident(base->ident));
2059 return 0;
2062 static void x86_initializer_expr(struct expression *expr, struct symbol *ctype)
2064 struct expression *entry;
2066 FOR_EACH_PTR(expr->expr_list, entry) {
2067 // Nested initializers have their positions already
2068 // recursively calculated - just output them too
2069 if (entry->type == EXPR_INITIALIZER) {
2070 x86_initializer_expr(entry, ctype);
2071 continue;
2074 // Ignore initializer indexes and identifiers - the
2075 // evaluator has taken them into account
2076 if (entry->type == EXPR_IDENTIFIER || entry->type == EXPR_INDEX)
2077 continue;
2078 if (entry->type == EXPR_POS) {
2079 x86_position_expr(entry, ctype);
2080 continue;
2082 x86_initialization(ctype, entry);
2083 } END_FOR_EACH_PTR;
2087 * Print out an expression. Return the pseudo that contains the
2088 * variable.
2090 static struct storage *x86_expression(struct expression *expr)
2092 if (!expr)
2093 return NULL;
2095 if (!expr->ctype) {
2096 struct position *pos = &expr->pos;
2097 printf("\tno type at %s:%d:%d\n",
2098 input_streams[pos->stream].name,
2099 pos->line, pos->pos);
2100 return NULL;
2103 switch (expr->type) {
2104 case EXPR_CALL:
2105 return x86_call_expression(expr);
2107 case EXPR_ASSIGNMENT:
2108 return x86_assignment(expr);
2110 case EXPR_COMPARE:
2111 return emit_compare(expr);
2112 case EXPR_BINOP:
2113 case EXPR_COMMA:
2114 case EXPR_LOGICAL:
2115 return emit_binop(expr);
2116 case EXPR_PREOP:
2117 return x86_preop(expr);
2118 case EXPR_POSTOP:
2119 return emit_postop(expr);
2120 case EXPR_SYMBOL:
2121 return emit_symbol_expr_init(expr->symbol);
2122 case EXPR_DEREF:
2123 case EXPR_SIZEOF:
2124 warn(expr->pos, "invalid expression after evaluation");
2125 return NULL;
2126 case EXPR_CAST:
2127 return emit_cast_expr(expr);
2128 case EXPR_VALUE:
2129 return emit_value(expr);
2130 case EXPR_STRING:
2131 return emit_string_expr(expr);
2132 case EXPR_BITFIELD:
2133 return x86_bitfield_expr(expr);
2134 case EXPR_INITIALIZER:
2135 x86_initializer_expr(expr, expr->ctype);
2136 return NULL;
2137 case EXPR_CONDITIONAL:
2138 return emit_conditional_expr(expr);
2139 case EXPR_STATEMENT:
2140 return x86_statement_expr(expr);
2141 case EXPR_LABEL:
2142 return x86_label_expr(expr);
2144 // None of these should exist as direct expressions: they are only
2145 // valid as sub-expressions of initializers.
2146 case EXPR_POS:
2147 warn(expr->pos, "unable to show plain initializer position expression");
2148 return NULL;
2149 case EXPR_IDENTIFIER:
2150 warn(expr->pos, "unable to show identifier expression");
2151 return NULL;
2152 case EXPR_INDEX:
2153 warn(expr->pos, "unable to show index expression");
2154 return NULL;
2155 case EXPR_TYPE:
2156 warn(expr->pos, "unable to show type expression");
2157 return NULL;
2159 return NULL;