[be] fix some of the brokenness related to non-32-bit variables
[smatch.git] / compile-i386.c
bloba5467e75e646adeb48948cf7343088ed1c6e5d66
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 struct storage *temp_from_bits(unsigned int bit_size)
239 switch(bit_size) {
240 case 8: return REG_AL;
241 case 16: return REG_AX;
242 case 32: return REG_EAX;
244 case 64: /* FIXME */
245 default:
246 assert(0);
247 break;
250 return NULL;
253 static inline unsigned int pseudo_offset(struct storage *s)
255 if (s->type != STOR_PSEUDO)
256 return 123456; /* intentionally bogus value */
258 return s->offset;
261 static inline unsigned int arg_offset(struct storage *s)
263 if (s->type != STOR_ARG)
264 return 123456; /* intentionally bogus value */
266 /* FIXME: this is wrong wrong wrong */
267 return current_func->stack_size + ((1 + s->idx) * 4);
270 static const char *pretty_offset(int ofs)
272 static char esp_buf[64];
274 if (ofs)
275 sprintf(esp_buf, "%d(%%esp)", ofs);
276 else
277 strcpy(esp_buf, "(%esp)");
279 return esp_buf;
282 static void stor_sym_init(struct symbol *sym)
284 struct storage *stor;
285 struct symbol_private *priv;
287 priv = calloc(1, sizeof(*priv) + sizeof(*stor));
288 if (!priv)
289 die("OOM in stor_sym_init");
291 stor = (struct storage *) (priv + 1);
293 priv->addr = stor;
294 stor->type = STOR_SYM;
295 stor->sym = sym;
298 static const char *stor_op_name(struct storage *s)
300 static char name[32];
302 switch (s->type) {
303 case STOR_PSEUDO:
304 strcpy(name, pretty_offset((int) pseudo_offset(s)));
305 break;
306 case STOR_ARG:
307 strcpy(name, pretty_offset((int) arg_offset(s)));
308 break;
309 case STOR_SYM:
310 strcpy(name, show_ident(s->sym->ident));
311 break;
312 case STOR_REG:
313 strcpy(name, s->reg->name);
314 break;
315 case STOR_VALUE:
316 sprintf(name, "$%Ld", s->value);
317 break;
318 case STOR_LABEL:
319 sprintf(name, "%s.L%d", s->flags & STOR_LABEL_VAL ? "$" : "",
320 s->label);
321 break;
322 case STOR_LABELSYM:
323 sprintf(name, "%s.LS%p", s->flags & STOR_LABEL_VAL ? "$" : "",
324 s->labelsym);
325 break;
328 return name;
331 static struct atom *new_atom(enum atom_type type)
333 struct atom *atom;
335 atom = calloc(1, sizeof(*atom)); /* TODO: chunked alloc */
336 if (!atom)
337 die("nuclear OOM");
339 atom->type = type;
341 return atom;
344 static inline void push_cstring(struct function *f, struct string *str,
345 int label)
347 struct atom *atom;
349 atom = new_atom(ATOM_CSTR);
350 atom->string = str;
351 atom->label = label;
353 add_ptr_list(&f->str_list, atom); /* note: _not_ atom_list */
356 static inline void push_atom(struct function *f, struct atom *atom)
358 add_ptr_list(&f->atom_list, atom);
361 static void push_text_atom(struct function *f, const char *text)
363 struct atom *atom = new_atom(ATOM_TEXT);
365 atom->text = strdup(text);
366 atom->text_len = strlen(text);
368 push_atom(f, atom);
371 static struct storage *new_storage(enum storage_type type)
373 struct storage *stor;
375 stor = calloc(1, sizeof(*stor));
376 if (!stor)
377 die("OOM in new_storage");
379 stor->type = type;
381 return stor;
384 static struct storage *stack_alloc(int n_bytes)
386 struct function *f = current_func;
387 struct storage *stor;
389 assert(f != NULL);
391 stor = new_storage(STOR_PSEUDO);
392 stor->type = STOR_PSEUDO;
393 stor->pseudo = f->pseudo_nr;
394 stor->offset = f->stack_size; /* FIXME: stack req. natural align */
395 stor->size = n_bytes;
396 f->stack_size += n_bytes;
397 f->pseudo_nr++;
399 add_ptr_list(&f->pseudo_list, stor);
401 return stor;
404 static struct storage *new_labelsym(struct symbol *sym)
406 struct storage *stor;
408 stor = new_storage(STOR_LABELSYM);
410 if (stor) {
411 stor->flags |= STOR_WANTS_FREE;
412 stor->labelsym = sym;
415 return stor;
418 static struct storage *new_val(long long value)
420 struct storage *stor;
422 stor = new_storage(STOR_VALUE);
424 if (stor) {
425 stor->flags |= STOR_WANTS_FREE;
426 stor->value = value;
429 return stor;
432 static int new_label(void)
434 static int label = 0;
435 return ++label;
438 static void textbuf_push(struct textbuf **buf_p, const char *text)
440 struct textbuf *tmp, *list = *buf_p;
441 unsigned int text_len = strlen(text);
442 unsigned int alloc_len = text_len + 1 + sizeof(*list);
444 tmp = calloc(1, alloc_len);
445 if (!tmp)
446 die("OOM on textbuf alloc");
448 tmp->text = ((void *) tmp) + sizeof(*tmp);
449 memcpy(tmp->text, text, text_len + 1);
450 tmp->len = text_len;
452 /* add to end of list */
453 if (!list) {
454 list = tmp;
455 tmp->prev = tmp;
456 } else {
457 tmp->prev = list->prev;
458 tmp->prev->next = tmp;
459 list->prev = tmp;
461 tmp->next = list;
463 *buf_p = list;
466 static void textbuf_emit(struct textbuf **buf_p)
468 struct textbuf *tmp, *list = *buf_p;
470 while (list) {
471 tmp = list;
472 if (tmp->next == tmp)
473 list = NULL;
474 else {
475 tmp->prev->next = tmp->next;
476 tmp->next->prev = tmp->prev;
477 list = tmp->next;
480 fputs(tmp->text, stdout);
482 free(tmp);
485 *buf_p = list;
488 static void insn(const char *insn, struct storage *op1, struct storage *op2,
489 const char *comment_in)
491 struct function *f = current_func;
492 struct atom *atom = new_atom(ATOM_INSN);
494 assert(insn != NULL);
496 strcpy(atom->insn, insn);
497 if (comment_in && (*comment_in))
498 strncpy(atom->comment, comment_in,
499 sizeof(atom->comment) - 1);
501 atom->op1 = op1;
502 atom->op2 = op2;
504 push_atom(f, atom);
507 static void emit_label (int label, const char *comment)
509 struct function *f = current_func;
510 char s[64];
512 if (!comment)
513 sprintf(s, ".L%d:\n", label);
514 else
515 sprintf(s, ".L%d:\t\t\t\t\t# %s\n", label, comment);
517 push_text_atom(f, s);
520 static void emit_labelsym (struct symbol *sym, const char *comment)
522 struct function *f = current_func;
523 char s[64];
525 if (!comment)
526 sprintf(s, ".LS%p:\n", sym);
527 else
528 sprintf(s, ".LS%p:\t\t\t\t# %s\n", sym, comment);
530 push_text_atom(f, s);
533 static void emit_unit_pre(const char *basename)
535 printf("\t.file\t\"%s\"\n", basename);
538 static void emit_unit_post(void)
540 textbuf_emit(&unit_post_text);
541 printf("\t.ident\t\"sparse silly x86 backend (built %s)\"\n", __DATE__);
544 /* conditionally switch sections */
545 static void emit_section(const char *s)
547 if (s == current_section)
548 return;
549 if (current_section && (!strcmp(s, current_section)))
550 return;
552 printf("\t%s\n", s);
553 current_section = s;
556 static void emit_insn_atom(struct function *f, struct atom *atom)
558 char s[128];
559 char comment[64];
560 struct storage *op1 = atom->op1;
561 struct storage *op2 = atom->op2;
563 if (atom->comment[0])
564 sprintf(comment, "\t\t# %s", atom->comment);
565 else
566 comment[0] = 0;
568 if (atom->op2) {
569 char tmp[16];
570 strcpy(tmp, stor_op_name(op1));
571 sprintf(s, "\t%s\t%s, %s%s\n",
572 atom->insn, tmp, stor_op_name(op2), comment);
573 } else if (atom->op1)
574 sprintf(s, "\t%s\t%s%s%s\n",
575 atom->insn, stor_op_name(op1),
576 comment[0] ? "\t" : "", comment);
577 else
578 sprintf(s, "\t%s\t%s%s\n",
579 atom->insn,
580 comment[0] ? "\t\t" : "", comment);
582 write(STDOUT_FILENO, s, strlen(s));
585 static void emit_atom_list(struct function *f)
587 struct atom *atom;
589 FOR_EACH_PTR(f->atom_list, atom) {
590 switch (atom->type) {
591 case ATOM_TEXT: {
592 ssize_t rc = write(STDOUT_FILENO, atom->text,
593 atom->text_len);
594 (void) rc; /* FIXME */
595 break;
597 case ATOM_INSN:
598 emit_insn_atom(f, atom);
599 break;
600 case ATOM_CSTR:
601 assert(0);
602 break;
604 } END_FOR_EACH_PTR;
607 static void emit_string_list(struct function *f)
609 struct atom *atom;
611 emit_section(".section\t.rodata");
613 FOR_EACH_PTR(f->str_list, atom) {
614 /* FIXME: escape " in string */
615 printf(".L%d:\n", atom->label);
616 printf("\t.string\t%s\n", show_string(atom->string));
618 free(atom);
619 } END_FOR_EACH_PTR;
622 static void func_cleanup(struct function *f)
624 struct storage *stor;
625 struct atom *atom;
627 FOR_EACH_PTR(f->pseudo_list, stor) {
628 free(stor);
629 } END_FOR_EACH_PTR;
631 FOR_EACH_PTR(f->atom_list, atom) {
632 if ((atom->type == ATOM_TEXT) && (atom->text))
633 free(atom->text);
634 if (atom->op1 && (atom->op1->flags & STOR_WANTS_FREE))
635 free(atom->op1);
636 if (atom->op2 && (atom->op2->flags & STOR_WANTS_FREE))
637 free(atom->op2);
638 free(atom);
639 } END_FOR_EACH_PTR;
641 free_ptr_list(&f->pseudo_list);
642 free(f);
645 /* function prologue */
646 static void emit_func_pre(struct symbol *sym)
648 struct function *f;
649 struct symbol *arg;
650 unsigned int i, argc = 0, alloc_len;
651 unsigned char *mem;
652 struct symbol_private *privbase;
653 struct storage *storage_base;
654 struct symbol *base_type = sym->ctype.base_type;
656 FOR_EACH_PTR(base_type->arguments, arg) {
657 argc++;
658 } END_FOR_EACH_PTR;
660 alloc_len =
661 sizeof(*f) +
662 (argc * sizeof(struct symbol *)) +
663 (argc * sizeof(struct symbol_private)) +
664 (argc * sizeof(struct storage));
665 mem = calloc(1, alloc_len);
666 if (!mem)
667 die("OOM on func info");
669 f = (struct function *) mem;
670 mem += sizeof(*f);
671 f->argv = (struct symbol **) mem;
672 mem += (argc * sizeof(struct symbol *));
673 privbase = (struct symbol_private *) mem;
674 mem += (argc * sizeof(struct symbol_private));
675 storage_base = (struct storage *) mem;
677 f->argc = argc;
678 f->ret_target = new_label();
680 i = 0;
681 FOR_EACH_PTR(base_type->arguments, arg) {
682 f->argv[i] = arg;
683 arg->aux = &privbase[i];
684 storage_base[i].type = STOR_ARG;
685 storage_base[i].idx = i;
686 privbase[i].addr = &storage_base[i];
687 i++;
688 } END_FOR_EACH_PTR;
690 assert(current_func == NULL);
691 current_func = f;
694 /* function epilogue */
695 static void emit_func_post(struct symbol *sym)
697 const char *name = show_ident(sym->ident);
698 struct function *f = current_func;
699 int stack_size = f->stack_size;
701 if (f->str_list)
702 emit_string_list(f);
704 /* function prologue */
705 emit_section(".text");
706 if ((sym->ctype.modifiers & MOD_STATIC) == 0)
707 printf(".globl %s\n", name);
708 printf("\t.type\t%s, @function\n", name);
709 printf("%s:\n", name);
711 if (stack_size) {
712 char pseudo_const[16];
714 sprintf(pseudo_const, "$%d", stack_size);
715 printf("\tsubl\t%s, %%esp\n", pseudo_const);
718 /* function epilogue */
720 /* jump target for 'return' statements */
721 emit_label(f->ret_target, NULL);
723 if (stack_size) {
724 struct storage *val;
726 val = new_storage(STOR_VALUE);
727 val->value = (long long) (stack_size);
728 val->flags = STOR_WANTS_FREE;
730 insn("addl", val, REG_ESP, NULL);
733 insn("ret", NULL, NULL, NULL);
735 /* output everything to stdout */
736 fflush(stdout); /* paranoia; needed? */
737 emit_atom_list(f);
739 /* function footer */
740 name = show_ident(sym->ident);
741 printf("\t.size\t%s, .-%s\n", name, name);
743 func_cleanup(f);
744 current_func = NULL;
747 /* emit object (a.k.a. variable, a.k.a. data) prologue */
748 static void emit_object_pre(const char *name, unsigned long modifiers,
749 unsigned long alignment, unsigned int byte_size)
751 if ((modifiers & MOD_STATIC) == 0)
752 printf(".globl %s\n", name);
753 emit_section(".data");
754 if (alignment)
755 printf("\t.align %lu\n", alignment);
756 printf("\t.type\t%s, @object\n", name);
757 printf("\t.size\t%s, %d\n", name, byte_size);
758 printf("%s:\n", name);
761 /* emit value (only) for an initializer scalar */
762 static void emit_scalar(struct expression *expr, unsigned int bit_size)
764 const char *type;
765 long long ll;
767 assert(expr->type == EXPR_VALUE);
769 if (expr->value == 0ULL) {
770 printf("\t.zero\t%d\n", bit_size / 8);
771 return;
774 ll = (long long) expr->value;
776 switch (bit_size) {
777 case 8: type = "byte"; ll = (char) ll; break;
778 case 16: type = "value"; ll = (short) ll; break;
779 case 32: type = "long"; ll = (int) ll; break;
780 case 64: type = "quad"; break;
781 default: type = NULL; break;
784 assert(type != NULL);
786 printf("\t.%s\t%Ld\n", type, ll);
789 static void emit_global_noinit(const char *name, unsigned long modifiers,
790 unsigned long alignment, unsigned int byte_size)
792 char s[64];
794 if (modifiers & MOD_STATIC) {
795 sprintf(s, "\t.local\t%s\n", name);
796 textbuf_push(&unit_post_text, s);
798 if (alignment)
799 sprintf(s, "\t.comm\t%s,%d,%lu\n", name, byte_size, alignment);
800 else
801 sprintf(s, "\t.comm\t%s,%d\n", name, byte_size);
802 textbuf_push(&unit_post_text, s);
805 static int ea_current, ea_last;
807 static void emit_initializer(struct symbol *sym,
808 struct expression *expr)
810 int distance = ea_current - ea_last - 1;
812 if (distance > 0)
813 printf("\t.zero\t%d\n", (sym->bit_size / 8) * distance);
815 if (expr->type == EXPR_VALUE) {
816 struct symbol *base_type = sym->ctype.base_type;
817 assert(base_type != NULL);
819 emit_scalar(expr, sym->bit_size / get_expression_value(base_type->array_size));
820 return;
822 if (expr->type != EXPR_INITIALIZER)
823 return;
825 assert(0); /* FIXME */
828 static int sort_array_cmp(const struct expression *a,
829 const struct expression *b)
831 int a_ofs = 0, b_ofs = 0;
833 if (a->type == EXPR_POS)
834 a_ofs = (int) a->init_offset;
835 if (b->type == EXPR_POS)
836 b_ofs = (int) b->init_offset;
838 return a_ofs - b_ofs;
841 /* move to front-end? */
842 static void sort_array(struct expression *expr)
844 struct expression *entry, **list;
845 unsigned int elem, sorted, i;
847 elem = 0;
848 FOR_EACH_PTR(expr->expr_list, entry) {
849 elem++;
850 } END_FOR_EACH_PTR;
852 if (!elem)
853 return;
855 list = malloc(sizeof(entry) * elem);
856 if (!list)
857 die("OOM in sort_array");
859 /* this code is no doubt evil and ignores EXPR_INDEX possibly
860 * to its detriment and other nasty things. improvements
861 * welcome.
863 i = 0;
864 sorted = 0;
865 FOR_EACH_PTR(expr->expr_list, entry) {
866 if ((entry->type == EXPR_POS) || (entry->type == EXPR_VALUE)) {
867 /* add entry to list[], in sorted order */
868 if (sorted == 0) {
869 list[0] = entry;
870 sorted = 1;
871 } else {
872 unsigned int i;
874 for (i = 0; i < sorted; i++)
875 if (sort_array_cmp(entry, list[i]) <= 0)
876 break;
878 /* If inserting into the middle of list[]
879 * instead of appending, we memmove.
880 * This is ugly, but thankfully
881 * uncommon. Input data with tons of
882 * entries very rarely have explicit
883 * offsets. convert to qsort eventually...
885 if (i != sorted)
886 memmove(&list[i + 1], &list[i],
887 (sorted - i) * sizeof(entry));
888 list[i] = entry;
889 sorted++;
892 } END_FOR_EACH_PTR;
894 i = 0;
895 FOR_EACH_PTR(expr->expr_list, entry) {
896 if ((entry->type == EXPR_POS) || (entry->type == EXPR_VALUE))
897 __list->list[__i] = list[i++];
898 } END_FOR_EACH_PTR;
902 static void emit_array(struct symbol *sym)
904 struct symbol *base_type = sym->ctype.base_type;
905 struct expression *expr = sym->initializer;
906 struct expression *entry;
908 assert(base_type != NULL);
910 stor_sym_init(sym);
912 ea_last = -1;
914 emit_object_pre(show_ident(sym->ident), sym->ctype.modifiers,
915 sym->ctype.alignment,
916 sym->bit_size / 8);
918 sort_array(expr);
920 FOR_EACH_PTR(expr->expr_list, entry) {
921 if (entry->type == EXPR_VALUE) {
922 ea_current = 0;
923 emit_initializer(sym, entry);
924 ea_last = ea_current;
925 } else if (entry->type == EXPR_POS) {
926 ea_current =
927 entry->init_offset / (base_type->bit_size / 8);
928 emit_initializer(sym, entry->init_expr);
929 ea_last = ea_current;
931 } END_FOR_EACH_PTR;
934 static void emit_one_symbol(struct symbol *sym, void *dummy, int flags)
936 x86_symbol(sym);
939 void emit_unit(const char *basename, struct symbol_list *list)
941 emit_unit_pre(basename);
942 symbol_iterate(list, emit_one_symbol, NULL);
943 emit_unit_post();
946 static void emit_copy(struct storage *dest, struct storage *src,
947 struct symbol *ctype)
949 struct storage *reg = NULL;
950 unsigned int bit_size;
952 /* FIXME: Bitfield copy! */
954 bit_size = src->size * 8;
955 if (!bit_size)
956 bit_size = 32;
957 if ((src->type == STOR_ARG) && (bit_size < 32))
958 bit_size = 32;
960 reg = temp_from_bits(bit_size);
961 emit_move(src, reg, ctype, "begin copy ..");
963 bit_size = dest->size * 8;
964 if (!bit_size)
965 bit_size = 32;
966 if ((dest->type == STOR_ARG) && (bit_size < 32))
967 bit_size = 32;
969 reg = temp_from_bits(bit_size);
970 emit_move(reg, dest, ctype, ".... end copy");
973 static void emit_store(struct expression *dest_expr, struct storage *dest,
974 struct storage *src, int bits)
976 /* FIXME: Bitfield store! */
977 printf("\tst.%d\t\tv%d,[v%d]\n", bits, src->pseudo, dest->pseudo);
980 static void emit_scalar_noinit(struct symbol *sym)
982 emit_global_noinit(show_ident(sym->ident),
983 sym->ctype.modifiers, sym->ctype.alignment,
984 sym->bit_size / 8);
985 stor_sym_init(sym);
988 static void emit_array_noinit(struct symbol *sym)
990 emit_global_noinit(show_ident(sym->ident),
991 sym->ctype.modifiers, sym->ctype.alignment,
992 get_expression_value(sym->array_size) * (sym->bit_size / 8));
993 stor_sym_init(sym);
996 static const char *opbits(const char *insn, unsigned int bits)
998 static char opbits_str[32];
999 char c;
1001 switch (bits) {
1002 case 8: c = 'b'; break;
1003 case 16: c = 'w'; break;
1004 case 32: c = 'l'; break;
1005 case 64: c = 'q'; break;
1006 default: assert(0); break;
1009 sprintf(opbits_str, "%s%c", insn, c);
1011 return opbits_str;
1014 static void emit_move(struct storage *src, struct storage *dest,
1015 struct symbol *ctype, const char *comment)
1017 unsigned int bits;
1018 unsigned int is_signed;
1019 unsigned int is_dest = (src->type == STOR_REG);
1020 const char *opname;
1022 if (ctype) {
1023 bits = ctype->bit_size;
1024 is_signed = type_is_signed(ctype);
1025 } else {
1026 bits = 32;
1027 is_signed = 0;
1030 if ((dest->type == STOR_REG) && (src->type == STOR_REG)) {
1031 insn("mov", src, dest, NULL);
1032 return;
1035 if ((bits == 8) || (bits == 16)) {
1036 if (is_dest)
1037 opname = "mov";
1038 else
1039 opname = is_signed ? "movsx" : "movzx";
1040 } else
1041 opname = "mov";
1043 insn(opbits(opname, bits), src, dest, comment);
1046 static struct storage *emit_compare(struct expression *expr)
1048 struct storage *left = x86_expression(expr->left);
1049 struct storage *right = x86_expression(expr->right);
1050 struct storage *new, *val;
1051 const char *opname = NULL;
1052 unsigned int right_bits = expr->right->ctype->bit_size;
1054 switch(expr->op) {
1055 case '<': opname = "setl"; break;
1056 case '>': opname = "setg"; break;
1057 case SPECIAL_LTE:
1058 opname = "setle"; break;
1059 case SPECIAL_GTE:
1060 opname = "setge"; break;
1061 case SPECIAL_EQUAL: opname = "sete"; break;
1062 case SPECIAL_NOTEQUAL: opname = "setne"; break;
1063 case SPECIAL_UNSIGNED_LT:
1064 opname = "setb"; break;
1065 case SPECIAL_UNSIGNED_GT:
1066 opname = "seta"; break;
1067 case SPECIAL_UNSIGNED_LTE:
1068 opname = "setb"; break;
1069 case SPECIAL_UNSIGNED_GTE:
1070 opname = "setae"; break;
1071 default:
1072 assert(0);
1073 break;
1076 /* init EDX to 0 */
1077 val = new_storage(STOR_VALUE);
1078 val->flags = STOR_WANTS_FREE;
1079 emit_move(val, REG_EDX, NULL, NULL);
1081 /* move op1 into EAX */
1082 emit_move(left, REG_EAX, expr->left->ctype, NULL);
1084 /* perform comparison, RHS (op1, right) and LHS (op2, EAX) */
1085 insn(opbits("cmp", right_bits), right, REG_EAX, NULL);
1087 /* store result of operation, 0 or 1, in DL using SETcc */
1088 insn(opname, REG_DL, NULL, NULL);
1090 /* finally, store the result (DL) in a new pseudo / stack slot */
1091 new = stack_alloc(4);
1092 emit_move(REG_EDX, new, NULL, "end EXPR_COMPARE");
1094 return new;
1097 static struct storage *emit_value(struct expression *expr)
1099 #if 0 /* old and slow way */
1100 struct storage *new = stack_alloc(4);
1101 struct storage *val;
1103 val = new_storage(STOR_VALUE);
1104 val->value = (long long) expr->value;
1105 val->flags = STOR_WANTS_FREE;
1106 insn("movl", val, new, NULL);
1108 return new;
1109 #else
1110 struct storage *val;
1112 val = new_storage(STOR_VALUE);
1113 val->value = (long long) expr->value;
1115 return val; /* FIXME: memory leak */
1116 #endif
1119 static struct storage *emit_binop(struct expression *expr)
1121 struct storage *left = x86_expression(expr->left);
1122 struct storage *right = x86_expression(expr->right);
1123 struct storage *new;
1124 struct storage *accum_reg = NULL;
1125 struct storage *result_reg = NULL;
1126 const char *opname = NULL;
1127 const char *suffix;
1128 char movstr[16], opstr[16];
1129 int is_signed, doing_divide = 0;
1131 if ((expr->op == '/') || (expr->op == '%')) {
1132 struct storage *val;
1134 doing_divide = 1;
1135 /* init EDX to 0 */
1136 val = new_storage(STOR_VALUE);
1137 val->flags = STOR_WANTS_FREE;
1138 emit_move(val, REG_EDX, NULL, "begin EXPR_DIVIDE");
1141 is_signed = type_is_signed(expr->ctype);
1143 switch (expr->op) {
1144 case '+':
1145 opname = "add";
1146 break;
1147 case '-':
1148 opname = "sub";
1149 break;
1150 case '&':
1151 opname = "and";
1152 break;
1153 case '|':
1154 opname = "or";
1155 break;
1156 case '^':
1157 opname = "xor";
1158 break;
1159 case SPECIAL_LEFTSHIFT:
1160 opname = "shl";
1161 break;
1162 case SPECIAL_RIGHTSHIFT:
1163 if (is_signed)
1164 opname = "sar";
1165 else
1166 opname = "shr";
1167 break;
1168 case '*':
1169 if (is_signed)
1170 opname = "imul";
1171 else
1172 opname = "mul";
1173 break;
1174 case '/':
1175 case '%':
1176 if (is_signed)
1177 opname = "idiv";
1178 else
1179 opname = "div";
1180 break;
1181 default:
1182 error(expr->pos, "unhandled binop '%s'\n", show_special(expr->op));
1183 break;
1186 switch (expr->ctype->bit_size) {
1187 case 8:
1188 suffix = "b";
1189 result_reg = accum_reg = REG_AL;
1190 if (expr->op == '%')
1191 result_reg = REG_DL;
1192 break;
1193 case 16:
1194 suffix = "w";
1195 result_reg = accum_reg = REG_AX;
1196 if (expr->op == '%')
1197 result_reg = REG_DX;
1198 break;
1199 case 32:
1200 suffix = "l";
1201 result_reg = accum_reg = REG_EAX;
1202 if (expr->op == '%')
1203 result_reg = REG_EDX;
1204 break;
1205 case 64:
1206 suffix = "q"; /* FIXME */
1207 result_reg = accum_reg = REG_EAX; /* FIXME */
1208 if (expr->op == '%')
1209 result_reg = REG_EDX;
1210 break;
1211 default:
1212 assert(0);
1213 break;
1216 sprintf(movstr, "mov%s", suffix);
1217 sprintf(opstr, "%s%s", opname, suffix);
1219 /* load op2 into EAX */
1220 insn(movstr, right, accum_reg,
1221 doing_divide ? NULL : "EXPR_BINOP/COMMA/LOGICAL");
1223 /* perform binop */
1224 insn(opstr, left, accum_reg, NULL);
1226 /* store result (EAX or EDX) in new pseudo / stack slot */
1227 new = stack_alloc(expr->ctype->bit_size / 8);
1228 insn(movstr, result_reg, new,
1229 doing_divide ? "end EXPR_DIVIDE" : "end EXPR_BINOP");
1231 return new;
1234 static void emit_if_conditional(struct statement *stmt)
1236 struct storage *val, *target_val;
1237 int target;
1238 struct expression *cond = stmt->if_conditional;
1240 /* This is only valid if nobody can jump into the "dead" statement */
1241 #if 0
1242 if (cond->type == EXPR_VALUE) {
1243 struct statement *s = stmt->if_true;
1244 if (!cond->value)
1245 s = stmt->if_false;
1246 x86_statement(s);
1247 break;
1249 #endif
1250 val = x86_expression(cond);
1252 /* load 'if' test result into EAX */
1253 insn("movl", val, REG_EAX, "begin if conditional");
1255 /* compare 'if' test result */
1256 insn("test", REG_EAX, REG_EAX, NULL);
1258 /* create end-of-if label / if-failed labelto jump to,
1259 * and jump to it if the expression returned zero.
1261 target = new_label();
1262 target_val = new_storage(STOR_LABEL);
1263 target_val->label = target;
1264 target_val->flags = STOR_WANTS_FREE;
1265 insn("jz", target_val, NULL, NULL);
1267 x86_statement(stmt->if_true);
1268 if (stmt->if_false) {
1269 struct storage *last_val;
1270 int last;
1272 /* finished generating code for if-true statement.
1273 * add a jump-to-end jump to avoid falling through
1274 * to the if-false statement code.
1276 last = new_label();
1277 last_val = new_storage(STOR_LABEL);
1278 last_val->label = last;
1279 last_val->flags = STOR_WANTS_FREE;
1280 insn("jmp", last_val, NULL, NULL);
1282 /* if we have both if-true and if-false statements,
1283 * the failed-conditional case will fall through to here
1285 emit_label(target, NULL);
1287 target = last;
1288 x86_statement(stmt->if_false);
1291 emit_label(target, "end if");
1294 static struct storage *emit_inc_dec(struct expression *expr, int postop)
1296 struct storage *addr = x86_address_gen(expr->unop);
1297 struct storage *retval;
1298 char opname[16];
1300 strcpy(opname, opbits(expr->op == SPECIAL_INCREMENT ? "inc" : "dec",
1301 expr->ctype->bit_size));
1303 if (postop) {
1304 struct storage *new = stack_alloc(4);
1306 emit_copy(new, addr, expr->unop->ctype);
1308 retval = new;
1309 } else
1310 retval = addr;
1312 insn(opname, addr, NULL, NULL);
1314 return retval;
1317 static struct storage *emit_postop(struct expression *expr)
1319 return emit_inc_dec(expr, 1);
1322 static struct storage *emit_return_stmt(struct statement *stmt)
1324 struct function *f = current_func;
1325 struct expression *expr = stmt->ret_value;
1326 struct storage *val = NULL, *jmplbl;
1328 if (expr && expr->ctype) {
1329 val = x86_expression(expr);
1330 assert(val != NULL);
1331 emit_move(val, REG_EAX, expr->ctype, "return");
1334 jmplbl = new_storage(STOR_LABEL);
1335 jmplbl->flags |= STOR_WANTS_FREE;
1336 jmplbl->label = f->ret_target;
1337 insn("jmp", jmplbl, NULL, NULL);
1339 return val;
1342 static struct storage *emit_conditional_expr(struct expression *expr)
1344 struct storage *cond = x86_expression(expr->conditional);
1345 struct storage *true = x86_expression(expr->cond_true);
1346 struct storage *false = x86_expression(expr->cond_false);
1347 struct storage *new = stack_alloc(4);
1349 if (!true)
1350 true = cond;
1352 emit_move(cond, REG_EAX, expr->conditional->ctype,
1353 "begin EXPR_CONDITIONAL");
1354 emit_move(true, REG_ECX, expr->cond_true->ctype, NULL);
1355 emit_move(false, REG_EDX, expr->cond_false->ctype, NULL);
1357 /* test EAX (for zero/non-zero) */
1358 insn("test", REG_EAX, REG_EAX, NULL);
1360 /* if false, move EDX to ECX */
1361 insn("cmovz", REG_EDX, REG_ECX, NULL);
1363 /* finally, store the result (ECX) in a new pseudo / stack slot */
1364 new = stack_alloc(4);
1365 emit_move(REG_ECX, new, expr->ctype, "end EXPR_CONDITIONAL");
1366 /* FIXME: we lose type knowledge of expression result at this point */
1368 return new;
1371 static struct storage *emit_symbol_expr_init(struct symbol *sym)
1373 struct expression *expr = sym->initializer;
1374 struct symbol_private *priv = sym->aux;
1376 if (priv == NULL) {
1377 priv = calloc(1, sizeof(*priv));
1378 sym->aux = priv;
1380 if (expr == NULL) {
1381 struct storage *new = stack_alloc(4);
1382 fprintf(stderr, "FIXME! no value for symbol. creating pseudo %d (stack offset %d)\n",
1383 new->pseudo, new->pseudo * 4);
1384 priv->addr = new;
1385 } else {
1386 priv->addr = x86_expression(expr);
1390 return priv->addr;
1393 static struct storage *emit_string_expr(struct expression *expr)
1395 struct function *f = current_func;
1396 int label = new_label();
1397 struct storage *new;
1399 push_cstring(f, expr->string, label);
1401 new = new_storage(STOR_LABEL);
1402 new->label = label;
1403 new->flags = STOR_LABEL_VAL | STOR_WANTS_FREE;
1404 return new;
1407 static struct storage *emit_cast_expr(struct expression *expr)
1409 struct symbol *old_type, *new_type;
1410 struct storage *op = x86_expression(expr->cast_expression);
1411 int oldbits, newbits;
1412 struct storage *new;
1414 old_type = expr->cast_expression->ctype;
1415 new_type = expr->cast_type;
1417 oldbits = old_type->bit_size;
1418 newbits = new_type->bit_size;
1419 if (oldbits >= newbits)
1420 return op;
1422 emit_move(op, REG_EAX, old_type, "begin cast ..");
1424 new = stack_alloc(newbits / 8);
1425 emit_move(REG_EAX, new, new_type, ".... end cast");
1427 return new;
1430 static struct storage *emit_regular_preop(struct expression *expr)
1432 struct storage *target = x86_expression(expr->unop);
1433 struct storage *val, *new = stack_alloc(4);
1434 const char *opname = NULL;
1436 switch (expr->op) {
1437 case '!':
1438 val = new_storage(STOR_VALUE);
1439 val->flags = STOR_WANTS_FREE;
1440 emit_move(val, REG_EDX, NULL, NULL);
1441 emit_move(target, REG_EAX, expr->unop->ctype, NULL);
1442 insn("test", REG_EAX, REG_EAX, NULL);
1443 insn("setz", REG_DL, NULL, NULL);
1444 emit_move(REG_EDX, new, expr->unop->ctype, NULL);
1446 break;
1447 case '~':
1448 opname = "not";
1449 case '-':
1450 if (!opname)
1451 opname = "neg";
1452 emit_move(target, REG_EAX, expr->unop->ctype, NULL);
1453 insn(opname, REG_EAX, NULL, NULL);
1454 emit_move(REG_EAX, new, expr->unop->ctype, NULL);
1455 break;
1456 default:
1457 assert(0);
1458 break;
1461 return new;
1464 static void emit_case_statement(struct statement *stmt)
1466 emit_labelsym(stmt->case_label, NULL);
1467 x86_statement(stmt->case_statement);
1470 static void emit_switch_statement(struct statement *stmt)
1472 struct storage *val = x86_expression(stmt->switch_expression);
1473 struct symbol *sym, *default_sym = NULL;
1474 struct storage *labelsym, *label;
1475 int switch_end = 0;
1477 emit_move(val, REG_EAX, stmt->switch_expression->ctype, "begin case");
1480 * This is where a _real_ back-end would go through the
1481 * cases to decide whether to use a lookup table or a
1482 * series of comparisons etc
1484 FOR_EACH_PTR(stmt->switch_case->symbol_list, sym) {
1485 struct statement *case_stmt = sym->stmt;
1486 struct expression *expr = case_stmt->case_expression;
1487 struct expression *to = case_stmt->case_to;
1489 /* default: */
1490 if (!expr)
1491 default_sym = sym;
1493 /* case NNN: */
1494 else {
1495 struct storage *case_val = new_val(expr->value);
1497 assert (expr->type == EXPR_VALUE);
1499 insn("cmpl", case_val, REG_EAX, NULL);
1501 if (!to) {
1502 labelsym = new_labelsym(sym);
1503 insn("je", labelsym, NULL, NULL);
1504 } else {
1505 int next_test;
1507 label = new_storage(STOR_LABEL);
1508 label->flags |= STOR_WANTS_FREE;
1509 label->label = next_test = new_label();
1511 /* FIXME: signed/unsigned */
1512 insn("jl", label, NULL, NULL);
1514 case_val = new_val(to->value);
1515 insn("cmpl", case_val, REG_EAX, NULL);
1517 /* TODO: implement and use refcounting... */
1518 label = new_storage(STOR_LABEL);
1519 label->flags |= STOR_WANTS_FREE;
1520 label->label = next_test;
1522 /* FIXME: signed/unsigned */
1523 insn("jg", label, NULL, NULL);
1525 labelsym = new_labelsym(sym);
1526 insn("jmp", labelsym, NULL, NULL);
1528 emit_label(next_test, NULL);
1531 } END_FOR_EACH_PTR;
1533 if (default_sym) {
1534 labelsym = new_labelsym(default_sym);
1535 insn("jmp", labelsym, NULL, "default");
1536 } else {
1537 label = new_storage(STOR_LABEL);
1538 label->flags |= STOR_WANTS_FREE;
1539 label->label = switch_end = new_label();
1540 insn("jmp", label, NULL, "goto end of switch");
1543 x86_statement(stmt->switch_statement);
1545 if (stmt->switch_break->used)
1546 emit_labelsym(stmt->switch_break, NULL);
1548 if (switch_end)
1549 emit_label(switch_end, NULL);
1552 static void x86_struct_member(struct symbol *sym, void *data, int flags)
1554 if (flags & ITERATE_FIRST)
1555 printf(" {\n\t");
1556 printf("%s:%d:%ld at offset %ld", show_ident(sym->ident), sym->bit_size, sym->ctype.alignment, sym->offset);
1557 if (sym->fieldwidth)
1558 printf("[%d..%d]", sym->bit_offset, sym->bit_offset+sym->fieldwidth-1);
1559 if (flags & ITERATE_LAST)
1560 printf("\n} ");
1561 else
1562 printf(", ");
1565 static void x86_symbol(struct symbol *sym)
1567 struct symbol *type;
1569 if (!sym)
1570 return;
1572 type = sym->ctype.base_type;
1573 if (!type)
1574 return;
1577 * Show actual implementation information
1579 switch (type->type) {
1581 case SYM_ARRAY:
1582 if (sym->initializer)
1583 emit_array(sym);
1584 else
1585 emit_array_noinit(sym);
1586 break;
1588 case SYM_BASETYPE:
1589 if (sym->initializer) {
1590 emit_object_pre(show_ident(sym->ident),
1591 sym->ctype.modifiers,
1592 sym->ctype.alignment,
1593 sym->bit_size / 8);
1594 emit_scalar(sym->initializer, sym->bit_size);
1595 stor_sym_init(sym);
1596 } else
1597 emit_scalar_noinit(sym);
1598 break;
1600 case SYM_STRUCT:
1601 symbol_iterate(type->symbol_list, x86_struct_member, NULL);
1602 break;
1604 case SYM_UNION:
1605 symbol_iterate(type->symbol_list, x86_struct_member, NULL);
1606 break;
1608 case SYM_FN: {
1609 struct statement *stmt = type->stmt;
1610 if (stmt) {
1611 emit_func_pre(sym);
1612 x86_statement(stmt);
1613 emit_func_post(sym);
1615 break;
1618 default:
1619 break;
1622 if (sym->initializer && (type->type != SYM_BASETYPE) &&
1623 (type->type != SYM_ARRAY)) {
1624 printf(" = \n");
1625 x86_expression(sym->initializer);
1629 static void x86_symbol_init(struct symbol *sym);
1631 static void x86_symbol_decl(struct symbol_list *syms)
1633 struct symbol *sym;
1634 FOR_EACH_PTR(syms, sym) {
1635 x86_symbol_init(sym);
1636 } END_FOR_EACH_PTR;
1639 static void loopstk_push(int cont_lbl, int loop_bottom_lbl)
1641 struct function *f = current_func;
1642 struct loop_stack *ls;
1644 ls = malloc(sizeof(*ls));
1645 ls->continue_lbl = cont_lbl;
1646 ls->loop_bottom_lbl = loop_bottom_lbl;
1647 ls->next = f->loop_stack;
1648 f->loop_stack = ls;
1651 static void loopstk_pop(void)
1653 struct function *f = current_func;
1654 struct loop_stack *ls;
1656 assert(f->loop_stack != NULL);
1657 ls = f->loop_stack;
1658 f->loop_stack = f->loop_stack->next;
1659 free(ls);
1662 static int loopstk_break(void)
1664 return current_func->loop_stack->loop_bottom_lbl;
1667 static int loopstk_continue(void)
1669 return current_func->loop_stack->continue_lbl;
1672 static void emit_loop(struct statement *stmt)
1674 struct statement *pre_statement = stmt->iterator_pre_statement;
1675 struct expression *pre_condition = stmt->iterator_pre_condition;
1676 struct statement *statement = stmt->iterator_statement;
1677 struct statement *post_statement = stmt->iterator_post_statement;
1678 struct expression *post_condition = stmt->iterator_post_condition;
1679 int loop_top = 0, loop_bottom, loop_continue;
1680 int have_bottom = 0;
1681 struct storage *val;
1683 loop_bottom = new_label();
1684 loop_continue = new_label();
1685 loopstk_push(loop_continue, loop_bottom);
1687 x86_symbol_decl(stmt->iterator_syms);
1688 x86_statement(pre_statement);
1689 if (pre_condition) {
1690 if (pre_condition->type == EXPR_VALUE) {
1691 if (!pre_condition->value) {
1692 struct storage *lbv;
1693 lbv = new_storage(STOR_LABEL);
1694 lbv->label = loop_bottom;
1695 lbv->flags = STOR_WANTS_FREE;
1696 insn("jmp", lbv, NULL, "go to loop bottom");
1697 have_bottom = 1;
1699 } else {
1700 struct storage *lbv = new_storage(STOR_LABEL);
1701 lbv->label = loop_bottom;
1702 lbv->flags = STOR_WANTS_FREE;
1703 have_bottom = 1;
1705 val = x86_expression(pre_condition);
1707 emit_move(val, REG_EAX, NULL, "loop pre condition");
1708 insn("test", REG_EAX, REG_EAX, NULL);
1709 insn("jz", lbv, NULL, NULL);
1712 if (!post_condition || post_condition->type != EXPR_VALUE || post_condition->value) {
1713 loop_top = new_label();
1714 emit_label(loop_top, "loop top");
1716 x86_statement(statement);
1717 if (stmt->iterator_continue->used)
1718 emit_label(loop_continue, "'continue' iterator");
1719 x86_statement(post_statement);
1720 if (!post_condition) {
1721 struct storage *lbv = new_storage(STOR_LABEL);
1722 lbv->label = loop_top;
1723 lbv->flags = STOR_WANTS_FREE;
1724 insn("jmp", lbv, NULL, "go to loop top");
1725 } else if (post_condition->type == EXPR_VALUE) {
1726 if (post_condition->value) {
1727 struct storage *lbv = new_storage(STOR_LABEL);
1728 lbv->label = loop_top;
1729 lbv->flags = STOR_WANTS_FREE;
1730 insn("jmp", lbv, NULL, "go to loop top");
1732 } else {
1733 struct storage *lbv = new_storage(STOR_LABEL);
1734 lbv->label = loop_top;
1735 lbv->flags = STOR_WANTS_FREE;
1737 val = x86_expression(post_condition);
1739 emit_move(val, REG_EAX, NULL, "loop post condition");
1740 insn("test", REG_EAX, REG_EAX, NULL);
1741 insn("jnz", lbv, NULL, NULL);
1743 if (have_bottom || stmt->iterator_break->used)
1744 emit_label(loop_bottom, "loop bottom");
1746 loopstk_pop();
1750 * Print out a statement
1752 static struct storage *x86_statement(struct statement *stmt)
1754 if (!stmt)
1755 return NULL;
1756 switch (stmt->type) {
1757 case STMT_RETURN:
1758 return emit_return_stmt(stmt);
1759 case STMT_COMPOUND: {
1760 struct statement *s;
1761 struct storage *last = NULL;
1763 x86_symbol_decl(stmt->syms);
1764 FOR_EACH_PTR(stmt->stmts, s) {
1765 last = x86_statement(s);
1766 } END_FOR_EACH_PTR;
1768 return last;
1771 case STMT_EXPRESSION:
1772 return x86_expression(stmt->expression);
1773 case STMT_IF:
1774 emit_if_conditional(stmt);
1775 return NULL;
1777 case STMT_CASE:
1778 emit_case_statement(stmt);
1779 break;
1780 case STMT_SWITCH:
1781 emit_switch_statement(stmt);
1782 break;
1784 case STMT_ITERATOR:
1785 emit_loop(stmt);
1786 break;
1788 case STMT_NONE:
1789 break;
1791 case STMT_LABEL:
1792 printf(".L%p:\n", stmt->label_identifier);
1793 x86_statement(stmt->label_statement);
1794 break;
1796 case STMT_GOTO:
1797 if (stmt->goto_expression) {
1798 struct storage *val = x86_expression(stmt->goto_expression);
1799 printf("\tgoto *v%d\n", val->pseudo);
1800 } else if (!strcmp("break", show_ident(stmt->goto_label->ident))) {
1801 struct storage *lbv = new_storage(STOR_LABEL);
1802 lbv->label = loopstk_break();
1803 lbv->flags = STOR_WANTS_FREE;
1804 insn("jmp", lbv, NULL, "'break'; go to loop bottom");
1805 } else if (!strcmp("continue", show_ident(stmt->goto_label->ident))) {
1806 struct storage *lbv = new_storage(STOR_LABEL);
1807 lbv->label = loopstk_continue();
1808 lbv->flags = STOR_WANTS_FREE;
1809 insn("jmp", lbv, NULL, "'continue'; go to loop top");
1810 } else {
1811 struct storage *labelsym = new_labelsym(stmt->goto_label);
1812 insn("jmp", labelsym, NULL, NULL);
1814 break;
1815 case STMT_ASM:
1816 printf("\tasm( .... )\n");
1817 break;
1819 return NULL;
1822 static struct storage *x86_call_expression(struct expression *expr)
1824 struct function *f = current_func;
1825 struct symbol *direct;
1826 struct expression *arg, *fn;
1827 struct storage *retval, *fncall;
1828 int framesize;
1829 char s[64];
1831 if (!expr->ctype) {
1832 warn(expr->pos, "\tcall with no type!");
1833 return NULL;
1836 framesize = 0;
1837 FOR_EACH_PTR_REVERSE(expr->args, arg) {
1838 struct storage *new = x86_expression(arg);
1839 int size = arg->ctype->bit_size;
1841 insn(opbits("push", size), new, NULL,
1842 !framesize ? "begin function call" : NULL);
1844 framesize += size >> 3;
1845 } END_FOR_EACH_PTR_REVERSE;
1847 fn = expr->fn;
1849 /* Remove dereference, if any */
1850 direct = NULL;
1851 if (fn->type == EXPR_PREOP) {
1852 if (fn->unop->type == EXPR_SYMBOL) {
1853 struct symbol *sym = fn->unop->symbol;
1854 if (sym->ctype.base_type->type == SYM_FN)
1855 direct = sym;
1858 if (direct) {
1859 struct storage *direct_stor = new_storage(STOR_SYM);
1860 direct_stor->flags |= STOR_WANTS_FREE;
1861 direct_stor->sym = direct;
1862 insn("call", direct_stor, NULL, NULL);
1863 } else {
1864 fncall = x86_expression(fn);
1865 emit_move(fncall, REG_EAX, fn->ctype, NULL);
1867 strcpy(s, "\tcall\t*%eax\n");
1868 push_text_atom(f, s);
1871 /* FIXME: pay attention to BITS_IN_POINTER */
1872 if (framesize) {
1873 struct storage *val = new_storage(STOR_VALUE);
1874 val->value = (long long) framesize;
1875 val->flags = STOR_WANTS_FREE;
1876 insn("addl", val, REG_ESP, NULL);
1879 retval = stack_alloc(4);
1880 emit_move(REG_EAX, retval, NULL, "end function call");
1882 return retval;
1885 static struct storage *x86_address_gen(struct expression *expr)
1887 struct function *f = current_func;
1888 struct storage *addr;
1889 struct storage *new;
1890 char s[32];
1892 if ((expr->type != EXPR_PREOP) || (expr->op != '*'))
1893 return x86_expression(expr->address);
1895 addr = x86_expression(expr->unop);
1896 if (expr->unop->type == EXPR_SYMBOL)
1897 return addr;
1899 emit_move(addr, REG_EAX, NULL, "begin deref ..");
1901 /* FIXME: operand size */
1902 strcpy(s, "\tmovl\t(%eax), %ecx\n");
1903 push_text_atom(f, s);
1905 new = stack_alloc(4);
1906 emit_move(REG_ECX, new, NULL, ".... end deref");
1908 return new;
1911 static struct storage *x86_assignment(struct expression *expr)
1913 struct expression *target = expr->left;
1914 struct storage *val, *addr;
1916 if (!expr->ctype)
1917 return NULL;
1919 val = x86_expression(expr->right);
1920 addr = x86_address_gen(target);
1922 switch (val->type) {
1923 /* copy, where both operands are memory */
1924 case STOR_PSEUDO:
1925 case STOR_ARG:
1926 emit_copy(addr, val, expr->ctype);
1927 break;
1929 /* copy, one or zero operands are memory */
1930 case STOR_REG:
1931 case STOR_SYM:
1932 case STOR_VALUE:
1933 case STOR_LABEL:
1934 emit_move(val, addr, expr->left->ctype, NULL);
1935 break;
1937 case STOR_LABELSYM:
1938 assert(0);
1939 break;
1941 return val;
1944 static int x86_initialization(struct symbol *sym, struct expression *expr)
1946 struct storage *val, *addr;
1947 int bits;
1949 if (!expr->ctype)
1950 return 0;
1952 bits = expr->ctype->bit_size;
1953 val = x86_expression(expr);
1954 addr = x86_symbol_expr(sym);
1955 // FIXME! The "target" expression is for bitfield store information.
1956 // Leave it NULL, which works fine.
1957 emit_store(NULL, addr, val, bits);
1958 return 0;
1961 static struct storage *x86_access(struct expression *expr)
1963 return x86_address_gen(expr);
1966 static struct storage *x86_preop(struct expression *expr)
1969 * '*' is an lvalue access, and is fundamentally different
1970 * from an arithmetic operation. Maybe it should have an
1971 * expression type of its own..
1973 if (expr->op == '*')
1974 return x86_access(expr);
1975 if (expr->op == SPECIAL_INCREMENT || expr->op == SPECIAL_DECREMENT)
1976 return emit_inc_dec(expr, 0);
1977 return emit_regular_preop(expr);
1980 static struct storage *x86_symbol_expr(struct symbol *sym)
1982 struct storage *new = stack_alloc(4);
1984 if (sym->ctype.modifiers & (MOD_TOPLEVEL | MOD_EXTERN | MOD_STATIC)) {
1985 printf("\tmovi.%d\t\tv%d,$%s\n", bits_in_pointer, new->pseudo, show_ident(sym->ident));
1986 return new;
1988 if (sym->ctype.modifiers & MOD_ADDRESSABLE) {
1989 printf("\taddi.%d\t\tv%d,vFP,$%lld\n", bits_in_pointer, new->pseudo, sym->value);
1990 return new;
1992 printf("\taddi.%d\t\tv%d,vFP,$offsetof(%s:%p)\n", bits_in_pointer, new->pseudo, show_ident(sym->ident), sym);
1993 return new;
1996 static void x86_symbol_init(struct symbol *sym)
1998 struct symbol_private *priv = sym->aux;
1999 struct expression *expr = sym->initializer;
2000 struct storage *new;
2002 if (expr)
2003 new = x86_expression(expr);
2004 else
2005 new = stack_alloc(sym->bit_size / 8);
2007 if (!priv) {
2008 priv = calloc(1, sizeof(*priv));
2009 sym->aux = priv;
2010 /* FIXME: leak! we don't free... */
2011 /* (well, we don't free symbols either) */
2014 priv->addr = new;
2017 static int type_is_signed(struct symbol *sym)
2019 if (sym->type == SYM_NODE)
2020 sym = sym->ctype.base_type;
2021 if (sym->type == SYM_PTR)
2022 return 0;
2023 return !(sym->ctype.modifiers & MOD_UNSIGNED);
2026 static struct storage *x86_bitfield_expr(struct expression *expr)
2028 return x86_access(expr);
2031 static struct storage *x86_label_expr(struct expression *expr)
2033 struct storage *new = stack_alloc(4);
2034 printf("\tmovi.%d\t\tv%d,.L%p\n", bits_in_pointer, new->pseudo, expr->label_symbol);
2035 return new;
2038 static struct storage *x86_statement_expr(struct expression *expr)
2040 return x86_statement(expr->statement);
2043 static int x86_position_expr(struct expression *expr, struct symbol *base)
2045 struct storage *new = x86_expression(expr->init_expr);
2046 struct symbol *ctype = expr->init_sym;
2048 printf("\tinsert v%d at [%d:%d] of %s\n", new->pseudo,
2049 expr->init_offset, ctype->bit_offset,
2050 show_ident(base->ident));
2051 return 0;
2054 static void x86_initializer_expr(struct expression *expr, struct symbol *ctype)
2056 struct expression *entry;
2058 FOR_EACH_PTR(expr->expr_list, entry) {
2059 // Nested initializers have their positions already
2060 // recursively calculated - just output them too
2061 if (entry->type == EXPR_INITIALIZER) {
2062 x86_initializer_expr(entry, ctype);
2063 continue;
2066 // Ignore initializer indexes and identifiers - the
2067 // evaluator has taken them into account
2068 if (entry->type == EXPR_IDENTIFIER || entry->type == EXPR_INDEX)
2069 continue;
2070 if (entry->type == EXPR_POS) {
2071 x86_position_expr(entry, ctype);
2072 continue;
2074 x86_initialization(ctype, entry);
2075 } END_FOR_EACH_PTR;
2079 * Print out an expression. Return the pseudo that contains the
2080 * variable.
2082 static struct storage *x86_expression(struct expression *expr)
2084 if (!expr)
2085 return NULL;
2087 if (!expr->ctype) {
2088 struct position *pos = &expr->pos;
2089 printf("\tno type at %s:%d:%d\n",
2090 input_streams[pos->stream].name,
2091 pos->line, pos->pos);
2092 return NULL;
2095 switch (expr->type) {
2096 case EXPR_CALL:
2097 return x86_call_expression(expr);
2099 case EXPR_ASSIGNMENT:
2100 return x86_assignment(expr);
2102 case EXPR_COMPARE:
2103 return emit_compare(expr);
2104 case EXPR_BINOP:
2105 case EXPR_COMMA:
2106 case EXPR_LOGICAL:
2107 return emit_binop(expr);
2108 case EXPR_PREOP:
2109 return x86_preop(expr);
2110 case EXPR_POSTOP:
2111 return emit_postop(expr);
2112 case EXPR_SYMBOL:
2113 return emit_symbol_expr_init(expr->symbol);
2114 case EXPR_DEREF:
2115 case EXPR_SIZEOF:
2116 case EXPR_ALIGNOF:
2117 warn(expr->pos, "invalid expression after evaluation");
2118 return NULL;
2119 case EXPR_CAST:
2120 return emit_cast_expr(expr);
2121 case EXPR_VALUE:
2122 return emit_value(expr);
2123 case EXPR_STRING:
2124 return emit_string_expr(expr);
2125 case EXPR_BITFIELD:
2126 return x86_bitfield_expr(expr);
2127 case EXPR_INITIALIZER:
2128 x86_initializer_expr(expr, expr->ctype);
2129 return NULL;
2130 case EXPR_CONDITIONAL:
2131 return emit_conditional_expr(expr);
2132 case EXPR_STATEMENT:
2133 return x86_statement_expr(expr);
2134 case EXPR_LABEL:
2135 return x86_label_expr(expr);
2137 // None of these should exist as direct expressions: they are only
2138 // valid as sub-expressions of initializers.
2139 case EXPR_POS:
2140 warn(expr->pos, "unable to show plain initializer position expression");
2141 return NULL;
2142 case EXPR_IDENTIFIER:
2143 warn(expr->pos, "unable to show identifier expression");
2144 return NULL;
2145 case EXPR_INDEX:
2146 warn(expr->pos, "unable to show index expression");
2147 return NULL;
2148 case EXPR_TYPE:
2149 warn(expr->pos, "unable to show type expression");
2150 return NULL;
2152 return NULL;