Create a valid linearization of EXPR_SELECT.
[smatch.git] / compile-i386.c
bloba3174c6a3821bcc5b8f157eb9b719e98ea0c60dc
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 case SPECIAL_LOGICAL_AND:
1182 warn(expr->pos, "bogus bitwise and for logical op (should use '2*setne + and' or something)");
1183 opname = "and";
1184 break;
1185 case SPECIAL_LOGICAL_OR:
1186 warn(expr->pos, "bogus bitwise or for logical op (should use 'or + setne' or something)");
1187 opname = "or";
1188 break;
1189 default:
1190 error(expr->pos, "unhandled binop '%s'\n", show_special(expr->op));
1191 break;
1194 switch (expr->ctype->bit_size) {
1195 case 8:
1196 suffix = "b";
1197 result_reg = accum_reg = REG_AL;
1198 if (expr->op == '%')
1199 result_reg = REG_DL;
1200 break;
1201 case 16:
1202 suffix = "w";
1203 result_reg = accum_reg = REG_AX;
1204 if (expr->op == '%')
1205 result_reg = REG_DX;
1206 break;
1207 case 32:
1208 suffix = "l";
1209 result_reg = accum_reg = REG_EAX;
1210 if (expr->op == '%')
1211 result_reg = REG_EDX;
1212 break;
1213 case 64:
1214 suffix = "q"; /* FIXME */
1215 result_reg = accum_reg = REG_EAX; /* FIXME */
1216 if (expr->op == '%')
1217 result_reg = REG_EDX;
1218 break;
1219 default:
1220 assert(0);
1221 break;
1224 sprintf(movstr, "mov%s", suffix);
1225 sprintf(opstr, "%s%s", opname, suffix);
1227 /* load op2 into EAX */
1228 insn(movstr, right, accum_reg,
1229 doing_divide ? NULL : "EXPR_BINOP/COMMA/LOGICAL");
1231 /* perform binop */
1232 insn(opstr, left, accum_reg, NULL);
1234 /* store result (EAX or EDX) in new pseudo / stack slot */
1235 new = stack_alloc(expr->ctype->bit_size / 8);
1236 insn(movstr, result_reg, new,
1237 doing_divide ? "end EXPR_DIVIDE" : "end EXPR_BINOP");
1239 return new;
1242 static int emit_conditional_test(struct storage *val)
1244 struct storage *target_val;
1245 int target_false;
1247 /* load result into EAX */
1248 insn("movl", val, REG_EAX, "begin if/conditional");
1250 /* compare result with zero */
1251 insn("test", REG_EAX, REG_EAX, NULL);
1253 /* create conditional-failed label to jump to */
1254 target_false = new_label();
1255 target_val = new_storage(STOR_LABEL);
1256 target_val->label = target_false;
1257 target_val->flags = STOR_WANTS_FREE;
1258 insn("jz", target_val, NULL, NULL);
1260 return target_false;
1263 static int emit_conditional_end(int target_false)
1265 struct storage *cond_end_st;
1266 int cond_end;
1268 /* finished generating code for if-true statement.
1269 * add a jump-to-end jump to avoid falling through
1270 * to the if-false statement code.
1272 cond_end = new_label();
1273 cond_end_st = new_storage(STOR_LABEL);
1274 cond_end_st->label = cond_end;
1275 cond_end_st->flags = STOR_WANTS_FREE;
1276 insn("jmp", cond_end_st, NULL, NULL);
1278 /* if we have both if-true and if-false statements,
1279 * the failed-conditional case will fall through to here
1281 emit_label(target_false, NULL);
1283 return cond_end;
1286 static void emit_if_conditional(struct statement *stmt)
1288 struct storage *val;
1289 int cond_end;
1291 /* emit test portion of conditional */
1292 val = x86_expression(stmt->if_conditional);
1293 cond_end = emit_conditional_test(val);
1295 /* emit if-true statement */
1296 x86_statement(stmt->if_true);
1298 /* emit if-false statement, if present */
1299 if (stmt->if_false) {
1300 cond_end = emit_conditional_end(cond_end);
1301 x86_statement(stmt->if_false);
1304 /* end of conditional; jump target for if-true branch */
1305 emit_label(cond_end, "end if");
1308 static struct storage *emit_inc_dec(struct expression *expr, int postop)
1310 struct storage *addr = x86_address_gen(expr->unop);
1311 struct storage *retval;
1312 char opname[16];
1314 strcpy(opname, opbits(expr->op == SPECIAL_INCREMENT ? "inc" : "dec",
1315 expr->ctype->bit_size));
1317 if (postop) {
1318 struct storage *new = stack_alloc(4);
1320 emit_copy(new, addr, expr->unop->ctype);
1322 retval = new;
1323 } else
1324 retval = addr;
1326 insn(opname, addr, NULL, NULL);
1328 return retval;
1331 static struct storage *emit_postop(struct expression *expr)
1333 return emit_inc_dec(expr, 1);
1336 static struct storage *emit_return_stmt(struct statement *stmt)
1338 struct function *f = current_func;
1339 struct expression *expr = stmt->ret_value;
1340 struct storage *val = NULL, *jmplbl;
1342 if (expr && expr->ctype) {
1343 val = x86_expression(expr);
1344 assert(val != NULL);
1345 emit_move(val, REG_EAX, expr->ctype, "return");
1348 jmplbl = new_storage(STOR_LABEL);
1349 jmplbl->flags |= STOR_WANTS_FREE;
1350 jmplbl->label = f->ret_target;
1351 insn("jmp", jmplbl, NULL, NULL);
1353 return val;
1356 static struct storage *emit_conditional_expr(struct expression *expr)
1358 struct storage *cond, *true = NULL, *false = NULL;
1359 struct storage *new = stack_alloc(expr->ctype->bit_size / 8);
1360 int target_false, cond_end;
1362 /* evaluate conditional */
1363 cond = x86_expression(expr->conditional);
1364 target_false = emit_conditional_test(cond);
1366 /* handle if-true part of the expression */
1367 if (!expr->cond_true)
1368 true = cond;
1369 else
1370 true = x86_expression(expr->cond_true);
1372 emit_copy(new, true, expr->ctype);
1374 cond_end = emit_conditional_end(target_false);
1376 /* handle if-false part of the expression */
1377 false = x86_expression(expr->cond_false);
1379 emit_copy(new, false, expr->ctype);
1381 /* end of conditional; jump target for if-true branch */
1382 emit_label(cond_end, "end conditional");
1384 return new;
1387 static struct storage *emit_select_expr(struct expression *expr)
1389 struct storage *cond = x86_expression(expr->conditional);
1390 struct storage *true = x86_expression(expr->cond_true);
1391 struct storage *false = x86_expression(expr->cond_false);
1392 struct storage *new = stack_alloc(4);
1393 struct storage *truereg;
1395 emit_move(cond, REG_EAX, expr->conditional->ctype, "begin SELECT");
1396 truereg = REG_EAX;
1397 if (true) {
1398 emit_move(true, REG_ECX, expr->cond_true->ctype, NULL);
1399 truereg = REG_ECX;
1401 emit_move(false, REG_EDX, expr->cond_false->ctype, NULL);
1404 * Do the actual select: check the conditional for zero,
1405 * move false over true if zero
1407 insn("test", REG_EAX, REG_EAX, NULL);
1408 insn("cmovz", REG_EDX, truereg, NULL);
1410 /* Store it back */
1411 emit_move(truereg, new, expr->ctype, "end SELECT");
1412 return new;
1415 static struct storage *emit_symbol_expr_init(struct symbol *sym)
1417 struct expression *expr = sym->initializer;
1418 struct symbol_private *priv = sym->aux;
1420 if (priv == NULL) {
1421 priv = calloc(1, sizeof(*priv));
1422 sym->aux = priv;
1424 if (expr == NULL) {
1425 struct storage *new = stack_alloc(4);
1426 fprintf(stderr, "FIXME! no value for symbol %s. creating pseudo %d (stack offset %d)\n",
1427 show_ident(sym->ident),
1428 new->pseudo, new->pseudo * 4);
1429 priv->addr = new;
1430 } else {
1431 priv->addr = x86_expression(expr);
1435 return priv->addr;
1438 static struct storage *emit_string_expr(struct expression *expr)
1440 struct function *f = current_func;
1441 int label = new_label();
1442 struct storage *new;
1444 push_cstring(f, expr->string, label);
1446 new = new_storage(STOR_LABEL);
1447 new->label = label;
1448 new->flags = STOR_LABEL_VAL | STOR_WANTS_FREE;
1449 return new;
1452 static struct storage *emit_cast_expr(struct expression *expr)
1454 struct symbol *old_type, *new_type;
1455 struct storage *op = x86_expression(expr->cast_expression);
1456 int oldbits, newbits;
1457 struct storage *new;
1459 old_type = expr->cast_expression->ctype;
1460 new_type = expr->cast_type;
1462 oldbits = old_type->bit_size;
1463 newbits = new_type->bit_size;
1464 if (oldbits >= newbits)
1465 return op;
1467 emit_move(op, REG_EAX, old_type, "begin cast ..");
1469 new = stack_alloc(newbits / 8);
1470 emit_move(REG_EAX, new, new_type, ".... end cast");
1472 return new;
1475 static struct storage *emit_regular_preop(struct expression *expr)
1477 struct storage *target = x86_expression(expr->unop);
1478 struct storage *val, *new = stack_alloc(4);
1479 const char *opname = NULL;
1481 switch (expr->op) {
1482 case '!':
1483 val = new_storage(STOR_VALUE);
1484 val->flags = STOR_WANTS_FREE;
1485 emit_move(val, REG_EDX, NULL, NULL);
1486 emit_move(target, REG_EAX, expr->unop->ctype, NULL);
1487 insn("test", REG_EAX, REG_EAX, NULL);
1488 insn("setz", REG_DL, NULL, NULL);
1489 emit_move(REG_EDX, new, expr->unop->ctype, NULL);
1491 break;
1492 case '~':
1493 opname = "not";
1494 case '-':
1495 if (!opname)
1496 opname = "neg";
1497 emit_move(target, REG_EAX, expr->unop->ctype, NULL);
1498 insn(opname, REG_EAX, NULL, NULL);
1499 emit_move(REG_EAX, new, expr->unop->ctype, NULL);
1500 break;
1501 default:
1502 assert(0);
1503 break;
1506 return new;
1509 static void emit_case_statement(struct statement *stmt)
1511 emit_labelsym(stmt->case_label, NULL);
1512 x86_statement(stmt->case_statement);
1515 static void emit_switch_statement(struct statement *stmt)
1517 struct storage *val = x86_expression(stmt->switch_expression);
1518 struct symbol *sym, *default_sym = NULL;
1519 struct storage *labelsym, *label;
1520 int switch_end = 0;
1522 emit_move(val, REG_EAX, stmt->switch_expression->ctype, "begin case");
1525 * This is where a _real_ back-end would go through the
1526 * cases to decide whether to use a lookup table or a
1527 * series of comparisons etc
1529 FOR_EACH_PTR(stmt->switch_case->symbol_list, sym) {
1530 struct statement *case_stmt = sym->stmt;
1531 struct expression *expr = case_stmt->case_expression;
1532 struct expression *to = case_stmt->case_to;
1534 /* default: */
1535 if (!expr)
1536 default_sym = sym;
1538 /* case NNN: */
1539 else {
1540 struct storage *case_val = new_val(expr->value);
1542 assert (expr->type == EXPR_VALUE);
1544 insn("cmpl", case_val, REG_EAX, NULL);
1546 if (!to) {
1547 labelsym = new_labelsym(sym);
1548 insn("je", labelsym, NULL, NULL);
1549 } else {
1550 int next_test;
1552 label = new_storage(STOR_LABEL);
1553 label->flags |= STOR_WANTS_FREE;
1554 label->label = next_test = new_label();
1556 /* FIXME: signed/unsigned */
1557 insn("jl", label, NULL, NULL);
1559 case_val = new_val(to->value);
1560 insn("cmpl", case_val, REG_EAX, NULL);
1562 /* TODO: implement and use refcounting... */
1563 label = new_storage(STOR_LABEL);
1564 label->flags |= STOR_WANTS_FREE;
1565 label->label = next_test;
1567 /* FIXME: signed/unsigned */
1568 insn("jg", label, NULL, NULL);
1570 labelsym = new_labelsym(sym);
1571 insn("jmp", labelsym, NULL, NULL);
1573 emit_label(next_test, NULL);
1576 } END_FOR_EACH_PTR;
1578 if (default_sym) {
1579 labelsym = new_labelsym(default_sym);
1580 insn("jmp", labelsym, NULL, "default");
1581 } else {
1582 label = new_storage(STOR_LABEL);
1583 label->flags |= STOR_WANTS_FREE;
1584 label->label = switch_end = new_label();
1585 insn("jmp", label, NULL, "goto end of switch");
1588 x86_statement(stmt->switch_statement);
1590 if (stmt->switch_break->used)
1591 emit_labelsym(stmt->switch_break, NULL);
1593 if (switch_end)
1594 emit_label(switch_end, NULL);
1597 static void x86_struct_member(struct symbol *sym, void *data, int flags)
1599 if (flags & ITERATE_FIRST)
1600 printf(" {\n\t");
1601 printf("%s:%d:%ld at offset %ld", show_ident(sym->ident), sym->bit_size, sym->ctype.alignment, sym->offset);
1602 if (sym->fieldwidth)
1603 printf("[%d..%d]", sym->bit_offset, sym->bit_offset+sym->fieldwidth-1);
1604 if (flags & ITERATE_LAST)
1605 printf("\n} ");
1606 else
1607 printf(", ");
1610 static void x86_symbol(struct symbol *sym)
1612 struct symbol *type;
1614 if (!sym)
1615 return;
1617 type = sym->ctype.base_type;
1618 if (!type)
1619 return;
1622 * Show actual implementation information
1624 switch (type->type) {
1626 case SYM_ARRAY:
1627 if (sym->initializer)
1628 emit_array(sym);
1629 else
1630 emit_array_noinit(sym);
1631 break;
1633 case SYM_BASETYPE:
1634 if (sym->initializer) {
1635 emit_object_pre(show_ident(sym->ident),
1636 sym->ctype.modifiers,
1637 sym->ctype.alignment,
1638 sym->bit_size / 8);
1639 emit_scalar(sym->initializer, sym->bit_size);
1640 stor_sym_init(sym);
1641 } else
1642 emit_scalar_noinit(sym);
1643 break;
1645 case SYM_STRUCT:
1646 symbol_iterate(type->symbol_list, x86_struct_member, NULL);
1647 break;
1649 case SYM_UNION:
1650 symbol_iterate(type->symbol_list, x86_struct_member, NULL);
1651 break;
1653 case SYM_FN: {
1654 struct statement *stmt = type->stmt;
1655 if (stmt) {
1656 emit_func_pre(sym);
1657 x86_statement(stmt);
1658 emit_func_post(sym);
1660 break;
1663 default:
1664 break;
1667 if (sym->initializer && (type->type != SYM_BASETYPE) &&
1668 (type->type != SYM_ARRAY)) {
1669 printf(" = \n");
1670 x86_expression(sym->initializer);
1674 static void x86_symbol_init(struct symbol *sym);
1676 static void x86_symbol_decl(struct symbol_list *syms)
1678 struct symbol *sym;
1679 FOR_EACH_PTR(syms, sym) {
1680 x86_symbol_init(sym);
1681 } END_FOR_EACH_PTR;
1684 static void loopstk_push(int cont_lbl, int loop_bottom_lbl)
1686 struct function *f = current_func;
1687 struct loop_stack *ls;
1689 ls = malloc(sizeof(*ls));
1690 ls->continue_lbl = cont_lbl;
1691 ls->loop_bottom_lbl = loop_bottom_lbl;
1692 ls->next = f->loop_stack;
1693 f->loop_stack = ls;
1696 static void loopstk_pop(void)
1698 struct function *f = current_func;
1699 struct loop_stack *ls;
1701 assert(f->loop_stack != NULL);
1702 ls = f->loop_stack;
1703 f->loop_stack = f->loop_stack->next;
1704 free(ls);
1707 static int loopstk_break(void)
1709 return current_func->loop_stack->loop_bottom_lbl;
1712 static int loopstk_continue(void)
1714 return current_func->loop_stack->continue_lbl;
1717 static void emit_loop(struct statement *stmt)
1719 struct statement *pre_statement = stmt->iterator_pre_statement;
1720 struct expression *pre_condition = stmt->iterator_pre_condition;
1721 struct statement *statement = stmt->iterator_statement;
1722 struct statement *post_statement = stmt->iterator_post_statement;
1723 struct expression *post_condition = stmt->iterator_post_condition;
1724 int loop_top = 0, loop_bottom, loop_continue;
1725 int have_bottom = 0;
1726 struct storage *val;
1728 loop_bottom = new_label();
1729 loop_continue = new_label();
1730 loopstk_push(loop_continue, loop_bottom);
1732 x86_symbol_decl(stmt->iterator_syms);
1733 x86_statement(pre_statement);
1734 if (pre_condition) {
1735 if (pre_condition->type == EXPR_VALUE) {
1736 if (!pre_condition->value) {
1737 struct storage *lbv;
1738 lbv = new_storage(STOR_LABEL);
1739 lbv->label = loop_bottom;
1740 lbv->flags = STOR_WANTS_FREE;
1741 insn("jmp", lbv, NULL, "go to loop bottom");
1742 have_bottom = 1;
1744 } else {
1745 struct storage *lbv = new_storage(STOR_LABEL);
1746 lbv->label = loop_bottom;
1747 lbv->flags = STOR_WANTS_FREE;
1748 have_bottom = 1;
1750 val = x86_expression(pre_condition);
1752 emit_move(val, REG_EAX, NULL, "loop pre condition");
1753 insn("test", REG_EAX, REG_EAX, NULL);
1754 insn("jz", lbv, NULL, NULL);
1757 if (!post_condition || post_condition->type != EXPR_VALUE || post_condition->value) {
1758 loop_top = new_label();
1759 emit_label(loop_top, "loop top");
1761 x86_statement(statement);
1762 if (stmt->iterator_continue->used)
1763 emit_label(loop_continue, "'continue' iterator");
1764 x86_statement(post_statement);
1765 if (!post_condition) {
1766 struct storage *lbv = new_storage(STOR_LABEL);
1767 lbv->label = loop_top;
1768 lbv->flags = STOR_WANTS_FREE;
1769 insn("jmp", lbv, NULL, "go to loop top");
1770 } else if (post_condition->type == EXPR_VALUE) {
1771 if (post_condition->value) {
1772 struct storage *lbv = new_storage(STOR_LABEL);
1773 lbv->label = loop_top;
1774 lbv->flags = STOR_WANTS_FREE;
1775 insn("jmp", lbv, NULL, "go to loop top");
1777 } else {
1778 struct storage *lbv = new_storage(STOR_LABEL);
1779 lbv->label = loop_top;
1780 lbv->flags = STOR_WANTS_FREE;
1782 val = x86_expression(post_condition);
1784 emit_move(val, REG_EAX, NULL, "loop post condition");
1785 insn("test", REG_EAX, REG_EAX, NULL);
1786 insn("jnz", lbv, NULL, NULL);
1788 if (have_bottom || stmt->iterator_break->used)
1789 emit_label(loop_bottom, "loop bottom");
1791 loopstk_pop();
1795 * Print out a statement
1797 static struct storage *x86_statement(struct statement *stmt)
1799 if (!stmt)
1800 return NULL;
1801 switch (stmt->type) {
1802 case STMT_RETURN:
1803 return emit_return_stmt(stmt);
1804 case STMT_COMPOUND: {
1805 struct statement *s;
1806 struct storage *last = NULL;
1808 x86_symbol_decl(stmt->syms);
1809 FOR_EACH_PTR(stmt->stmts, s) {
1810 last = x86_statement(s);
1811 } END_FOR_EACH_PTR;
1813 return last;
1816 case STMT_EXPRESSION:
1817 return x86_expression(stmt->expression);
1818 case STMT_IF:
1819 emit_if_conditional(stmt);
1820 return NULL;
1822 case STMT_CASE:
1823 emit_case_statement(stmt);
1824 break;
1825 case STMT_SWITCH:
1826 emit_switch_statement(stmt);
1827 break;
1829 case STMT_ITERATOR:
1830 emit_loop(stmt);
1831 break;
1833 case STMT_NONE:
1834 break;
1836 case STMT_LABEL:
1837 printf(".L%p:\n", stmt->label_identifier);
1838 x86_statement(stmt->label_statement);
1839 break;
1841 case STMT_GOTO:
1842 if (stmt->goto_expression) {
1843 struct storage *val = x86_expression(stmt->goto_expression);
1844 printf("\tgoto *v%d\n", val->pseudo);
1845 } else if (!strcmp("break", show_ident(stmt->goto_label->ident))) {
1846 struct storage *lbv = new_storage(STOR_LABEL);
1847 lbv->label = loopstk_break();
1848 lbv->flags = STOR_WANTS_FREE;
1849 insn("jmp", lbv, NULL, "'break'; go to loop bottom");
1850 } else if (!strcmp("continue", show_ident(stmt->goto_label->ident))) {
1851 struct storage *lbv = new_storage(STOR_LABEL);
1852 lbv->label = loopstk_continue();
1853 lbv->flags = STOR_WANTS_FREE;
1854 insn("jmp", lbv, NULL, "'continue'; go to loop top");
1855 } else {
1856 struct storage *labelsym = new_labelsym(stmt->goto_label);
1857 insn("jmp", labelsym, NULL, NULL);
1859 break;
1860 case STMT_ASM:
1861 printf("\tasm( .... )\n");
1862 break;
1864 return NULL;
1867 static struct storage *x86_call_expression(struct expression *expr)
1869 struct function *f = current_func;
1870 struct symbol *direct;
1871 struct expression *arg, *fn;
1872 struct storage *retval, *fncall;
1873 int framesize;
1874 char s[64];
1876 if (!expr->ctype) {
1877 warn(expr->pos, "\tcall with no type!");
1878 return NULL;
1881 framesize = 0;
1882 FOR_EACH_PTR_REVERSE(expr->args, arg) {
1883 struct storage *new = x86_expression(arg);
1884 int size = arg->ctype->bit_size;
1887 * FIXME: i386 SysV ABI dictates that values
1888 * smaller than 32 bits should be placed onto
1889 * the stack as 32-bit objects. We should not
1890 * blindly do a 32-bit push on objects smaller
1891 * than 32 bits.
1893 if (size < 32)
1894 size = 32;
1895 insn("pushl", new, NULL,
1896 !framesize ? "begin function call" : NULL);
1898 framesize += size >> 3;
1899 } END_FOR_EACH_PTR_REVERSE;
1901 fn = expr->fn;
1903 /* Remove dereference, if any */
1904 direct = NULL;
1905 if (fn->type == EXPR_PREOP) {
1906 if (fn->unop->type == EXPR_SYMBOL) {
1907 struct symbol *sym = fn->unop->symbol;
1908 if (sym->ctype.base_type->type == SYM_FN)
1909 direct = sym;
1912 if (direct) {
1913 struct storage *direct_stor = new_storage(STOR_SYM);
1914 direct_stor->flags |= STOR_WANTS_FREE;
1915 direct_stor->sym = direct;
1916 insn("call", direct_stor, NULL, NULL);
1917 } else {
1918 fncall = x86_expression(fn);
1919 emit_move(fncall, REG_EAX, fn->ctype, NULL);
1921 strcpy(s, "\tcall\t*%eax\n");
1922 push_text_atom(f, s);
1925 /* FIXME: pay attention to BITS_IN_POINTER */
1926 if (framesize) {
1927 struct storage *val = new_storage(STOR_VALUE);
1928 val->value = (long long) framesize;
1929 val->flags = STOR_WANTS_FREE;
1930 insn("addl", val, REG_ESP, NULL);
1933 retval = stack_alloc(4);
1934 emit_move(REG_EAX, retval, NULL, "end function call");
1936 return retval;
1939 static struct storage *x86_address_gen(struct expression *expr)
1941 struct function *f = current_func;
1942 struct storage *addr;
1943 struct storage *new;
1944 char s[32];
1946 if ((expr->type != EXPR_PREOP) || (expr->op != '*'))
1947 return x86_expression(expr->address);
1949 addr = x86_expression(expr->unop);
1950 if (expr->unop->type == EXPR_SYMBOL)
1951 return addr;
1953 emit_move(addr, REG_EAX, NULL, "begin deref ..");
1955 /* FIXME: operand size */
1956 strcpy(s, "\tmovl\t(%eax), %ecx\n");
1957 push_text_atom(f, s);
1959 new = stack_alloc(4);
1960 emit_move(REG_ECX, new, NULL, ".... end deref");
1962 return new;
1965 static struct storage *x86_assignment(struct expression *expr)
1967 struct expression *target = expr->left;
1968 struct storage *val, *addr;
1970 if (!expr->ctype)
1971 return NULL;
1973 val = x86_expression(expr->right);
1974 addr = x86_address_gen(target);
1976 switch (val->type) {
1977 /* copy, where both operands are memory */
1978 case STOR_PSEUDO:
1979 case STOR_ARG:
1980 emit_copy(addr, val, expr->ctype);
1981 break;
1983 /* copy, one or zero operands are memory */
1984 case STOR_REG:
1985 case STOR_SYM:
1986 case STOR_VALUE:
1987 case STOR_LABEL:
1988 emit_move(val, addr, expr->left->ctype, NULL);
1989 break;
1991 case STOR_LABELSYM:
1992 assert(0);
1993 break;
1995 return val;
1998 static int x86_initialization(struct symbol *sym, struct expression *expr)
2000 struct storage *val, *addr;
2001 int bits;
2003 if (!expr->ctype)
2004 return 0;
2006 bits = expr->ctype->bit_size;
2007 val = x86_expression(expr);
2008 addr = x86_symbol_expr(sym);
2009 // FIXME! The "target" expression is for bitfield store information.
2010 // Leave it NULL, which works fine.
2011 emit_store(NULL, addr, val, bits);
2012 return 0;
2015 static struct storage *x86_access(struct expression *expr)
2017 return x86_address_gen(expr);
2020 static struct storage *x86_preop(struct expression *expr)
2023 * '*' is an lvalue access, and is fundamentally different
2024 * from an arithmetic operation. Maybe it should have an
2025 * expression type of its own..
2027 if (expr->op == '*')
2028 return x86_access(expr);
2029 if (expr->op == SPECIAL_INCREMENT || expr->op == SPECIAL_DECREMENT)
2030 return emit_inc_dec(expr, 0);
2031 return emit_regular_preop(expr);
2034 static struct storage *x86_symbol_expr(struct symbol *sym)
2036 struct storage *new = stack_alloc(4);
2038 if (sym->ctype.modifiers & (MOD_TOPLEVEL | MOD_EXTERN | MOD_STATIC)) {
2039 printf("\tmovi.%d\t\tv%d,$%s\n", bits_in_pointer, new->pseudo, show_ident(sym->ident));
2040 return new;
2042 if (sym->ctype.modifiers & MOD_ADDRESSABLE) {
2043 printf("\taddi.%d\t\tv%d,vFP,$%lld\n", bits_in_pointer, new->pseudo, sym->value);
2044 return new;
2046 printf("\taddi.%d\t\tv%d,vFP,$offsetof(%s:%p)\n", bits_in_pointer, new->pseudo, show_ident(sym->ident), sym);
2047 return new;
2050 static void x86_symbol_init(struct symbol *sym)
2052 struct symbol_private *priv = sym->aux;
2053 struct expression *expr = sym->initializer;
2054 struct storage *new;
2056 if (expr)
2057 new = x86_expression(expr);
2058 else
2059 new = stack_alloc(sym->bit_size / 8);
2061 if (!priv) {
2062 priv = calloc(1, sizeof(*priv));
2063 sym->aux = priv;
2064 /* FIXME: leak! we don't free... */
2065 /* (well, we don't free symbols either) */
2068 priv->addr = new;
2071 static int type_is_signed(struct symbol *sym)
2073 if (sym->type == SYM_NODE)
2074 sym = sym->ctype.base_type;
2075 if (sym->type == SYM_PTR)
2076 return 0;
2077 return !(sym->ctype.modifiers & MOD_UNSIGNED);
2080 static struct storage *x86_bitfield_expr(struct expression *expr)
2082 return x86_access(expr);
2085 static struct storage *x86_label_expr(struct expression *expr)
2087 struct storage *new = stack_alloc(4);
2088 printf("\tmovi.%d\t\tv%d,.L%p\n", bits_in_pointer, new->pseudo, expr->label_symbol);
2089 return new;
2092 static struct storage *x86_statement_expr(struct expression *expr)
2094 return x86_statement(expr->statement);
2097 static int x86_position_expr(struct expression *expr, struct symbol *base)
2099 struct storage *new = x86_expression(expr->init_expr);
2100 struct symbol *ctype = expr->init_sym;
2102 printf("\tinsert v%d at [%d:%d] of %s\n", new->pseudo,
2103 expr->init_offset, ctype->bit_offset,
2104 show_ident(base->ident));
2105 return 0;
2108 static void x86_initializer_expr(struct expression *expr, struct symbol *ctype)
2110 struct expression *entry;
2112 FOR_EACH_PTR(expr->expr_list, entry) {
2113 // Nested initializers have their positions already
2114 // recursively calculated - just output them too
2115 if (entry->type == EXPR_INITIALIZER) {
2116 x86_initializer_expr(entry, ctype);
2117 continue;
2120 // Ignore initializer indexes and identifiers - the
2121 // evaluator has taken them into account
2122 if (entry->type == EXPR_IDENTIFIER || entry->type == EXPR_INDEX)
2123 continue;
2124 if (entry->type == EXPR_POS) {
2125 x86_position_expr(entry, ctype);
2126 continue;
2128 x86_initialization(ctype, entry);
2129 } END_FOR_EACH_PTR;
2133 * Print out an expression. Return the pseudo that contains the
2134 * variable.
2136 static struct storage *x86_expression(struct expression *expr)
2138 if (!expr)
2139 return NULL;
2141 if (!expr->ctype) {
2142 struct position *pos = &expr->pos;
2143 printf("\tno type at %s:%d:%d\n",
2144 input_streams[pos->stream].name,
2145 pos->line, pos->pos);
2146 return NULL;
2149 switch (expr->type) {
2150 case EXPR_CALL:
2151 return x86_call_expression(expr);
2153 case EXPR_ASSIGNMENT:
2154 return x86_assignment(expr);
2156 case EXPR_COMPARE:
2157 return emit_compare(expr);
2158 case EXPR_BINOP:
2159 case EXPR_COMMA:
2160 case EXPR_LOGICAL:
2161 return emit_binop(expr);
2162 case EXPR_PREOP:
2163 return x86_preop(expr);
2164 case EXPR_POSTOP:
2165 return emit_postop(expr);
2166 case EXPR_SYMBOL:
2167 return emit_symbol_expr_init(expr->symbol);
2168 case EXPR_DEREF:
2169 case EXPR_SIZEOF:
2170 case EXPR_ALIGNOF:
2171 warn(expr->pos, "invalid expression after evaluation");
2172 return NULL;
2173 case EXPR_CAST:
2174 return emit_cast_expr(expr);
2175 case EXPR_VALUE:
2176 return emit_value(expr);
2177 case EXPR_STRING:
2178 return emit_string_expr(expr);
2179 case EXPR_BITFIELD:
2180 return x86_bitfield_expr(expr);
2181 case EXPR_INITIALIZER:
2182 x86_initializer_expr(expr, expr->ctype);
2183 return NULL;
2184 case EXPR_SELECT:
2185 return emit_select_expr(expr);
2186 case EXPR_CONDITIONAL:
2187 return emit_conditional_expr(expr);
2188 case EXPR_STATEMENT:
2189 return x86_statement_expr(expr);
2190 case EXPR_LABEL:
2191 return x86_label_expr(expr);
2193 // None of these should exist as direct expressions: they are only
2194 // valid as sub-expressions of initializers.
2195 case EXPR_POS:
2196 warn(expr->pos, "unable to show plain initializer position expression");
2197 return NULL;
2198 case EXPR_IDENTIFIER:
2199 warn(expr->pos, "unable to show identifier expression");
2200 return NULL;
2201 case EXPR_INDEX:
2202 warn(expr->pos, "unable to show index expression");
2203 return NULL;
2204 case EXPR_TYPE:
2205 warn(expr->pos, "unable to show type expression");
2206 return NULL;
2207 case EXPR_FVALUE:
2208 warn(expr->pos, "floating point support is not implemented");
2209 return NULL;
2211 return NULL;