[PATCH] pack basic blocks
[smatch.git] / compile-i386.c
blob6290c3cbc35a950758e4b49e68d07fa083f2e145
1 /*
2 * sparse/compile-i386.c
4 * Copyright (C) 2003 Transmeta Corp.
5 * 2003 Linus Torvalds
6 * Copyright 2003 Jeff Garzik
8 * Licensed under the Open Software License version 1.1
10 * x86 backend
12 * TODO list:
13 * in general, any non-32bit SYM_BASETYPE is unlikely to work.
14 * complex initializers
15 * bitfields
16 * global struct/union variables
17 * addressing structures, and members of structures (as opposed to
18 * scalars) on the stack. Requires smarter stack frame allocation.
19 * labels / goto
20 * any function argument that isn't 32 bits (or promoted to such)
21 * inline asm
22 * floating point
25 #include <stdarg.h>
26 #include <stdlib.h>
27 #include <stdio.h>
28 #include <string.h>
29 #include <ctype.h>
30 #include <unistd.h>
31 #include <fcntl.h>
32 #include <assert.h>
34 #include "lib.h"
35 #include "token.h"
36 #include "parse.h"
37 #include "symbol.h"
38 #include "scope.h"
39 #include "expression.h"
40 #include "target.h"
43 struct textbuf {
44 unsigned int len; /* does NOT include terminating null */
45 char *text;
46 struct textbuf *next;
47 struct textbuf *prev;
50 struct loop_stack {
51 int continue_lbl;
52 int loop_bottom_lbl;
53 struct loop_stack *next;
56 struct function {
57 int stack_size;
58 int pseudo_nr;
59 struct ptr_list *pseudo_list;
60 struct ptr_list *atom_list;
61 struct ptr_list *str_list;
62 struct loop_stack *loop_stack;
63 struct symbol **argv;
64 unsigned int argc;
65 int ret_target;
68 enum storage_type {
69 STOR_PSEUDO, /* variable stored on the stack */
70 STOR_ARG, /* function argument */
71 STOR_SYM, /* a symbol we can directly ref in the asm */
72 STOR_REG, /* scratch register */
73 STOR_VALUE, /* integer constant */
74 STOR_LABEL, /* label / jump target */
75 STOR_LABELSYM, /* label generated from symbol's pointer value */
78 struct reg_info {
79 const char *name;
82 struct storage {
83 enum storage_type type;
84 unsigned long flags;
86 /* STOR_REG */
87 struct reg_info *reg;
89 union {
90 /* STOR_PSEUDO */
91 struct {
92 int pseudo;
93 int offset;
94 int size;
96 /* STOR_ARG */
97 struct {
98 int idx;
100 /* STOR_SYM */
101 struct {
102 struct symbol *sym;
104 /* STOR_VALUE */
105 struct {
106 long long value;
108 /* STOR_LABEL */
109 struct {
110 int label;
112 /* STOR_LABELSYM */
113 struct {
114 struct symbol *labelsym;
119 enum {
120 STOR_LABEL_VAL = (1 << 0),
121 STOR_WANTS_FREE = (1 << 1),
124 struct symbol_private {
125 struct storage *addr;
128 enum atom_type {
129 ATOM_TEXT,
130 ATOM_INSN,
131 ATOM_CSTR,
134 struct atom {
135 enum atom_type type;
136 union {
137 /* stuff for text */
138 struct {
139 char *text;
140 unsigned int text_len; /* w/o terminating null */
143 /* stuff for insns */
144 struct {
145 char insn[32];
146 char comment[40];
147 struct storage *op1;
148 struct storage *op2;
151 /* stuff for C strings */
152 struct {
153 struct string *string;
154 int label;
160 struct function *current_func = NULL;
161 struct textbuf *unit_post_text = NULL;
162 static const char *current_section;
164 static struct reg_info reg_info_table[] = {
165 { "%eax" },
166 { "%ecx" },
167 { "%edx" },
168 { "%esp" },
169 { "%dl" },
170 { "%dx" },
171 { "%al" },
172 { "%ax" },
175 static struct storage hardreg_storage_table[] = {
176 { /* eax */
177 .type = STOR_REG,
178 .reg = &reg_info_table[0],
181 { /* ecx */
182 .type = STOR_REG,
183 .reg = &reg_info_table[1],
186 { /* edx */
187 .type = STOR_REG,
188 .reg = &reg_info_table[2],
191 { /* esp */
192 .type = STOR_REG,
193 .reg = &reg_info_table[3],
196 { /* dl */
197 .type = STOR_REG,
198 .reg = &reg_info_table[4],
201 { /* dx */
202 .type = STOR_REG,
203 .reg = &reg_info_table[5],
206 { /* al */
207 .type = STOR_REG,
208 .reg = &reg_info_table[6],
211 { /* ax */
212 .type = STOR_REG,
213 .reg = &reg_info_table[7],
217 #define REG_EAX (&hardreg_storage_table[0])
218 #define REG_ECX (&hardreg_storage_table[1])
219 #define REG_EDX (&hardreg_storage_table[2])
220 #define REG_ESP (&hardreg_storage_table[3])
221 #define REG_DL (&hardreg_storage_table[4])
222 #define REG_DX (&hardreg_storage_table[5])
223 #define REG_AL (&hardreg_storage_table[6])
224 #define REG_AX (&hardreg_storage_table[7])
227 static void emit_move(struct storage *src, struct storage *dest,
228 struct symbol *ctype, const char *comment);
229 static int type_is_signed(struct symbol *sym);
230 static struct storage *x86_address_gen(struct expression *expr);
231 static struct storage *x86_symbol_expr(struct symbol *sym);
232 static void x86_symbol(struct symbol *sym);
233 static struct storage *x86_statement(struct statement *stmt);
234 static struct storage *x86_expression(struct expression *expr);
237 static inline unsigned int pseudo_offset(struct storage *s)
239 if (s->type != STOR_PSEUDO)
240 return 123456; /* intentionally bogus value */
242 return s->offset;
245 static inline unsigned int arg_offset(struct storage *s)
247 if (s->type != STOR_ARG)
248 return 123456; /* intentionally bogus value */
250 /* FIXME: this is wrong wrong wrong */
251 return current_func->stack_size + ((1 + s->idx) * 4);
254 static const char *pretty_offset(int ofs)
256 static char esp_buf[64];
258 if (ofs)
259 sprintf(esp_buf, "%d(%%esp)", ofs);
260 else
261 strcpy(esp_buf, "(%esp)");
263 return esp_buf;
266 static void stor_sym_init(struct symbol *sym)
268 struct storage *stor;
269 struct symbol_private *priv;
271 priv = calloc(1, sizeof(*priv) + sizeof(*stor));
272 if (!priv)
273 die("OOM in stor_sym_init");
275 stor = (struct storage *) (priv + 1);
277 priv->addr = stor;
278 stor->type = STOR_SYM;
279 stor->sym = sym;
282 static const char *stor_op_name(struct storage *s)
284 static char name[32];
286 switch (s->type) {
287 case STOR_PSEUDO:
288 strcpy(name, pretty_offset((int) pseudo_offset(s)));
289 break;
290 case STOR_ARG:
291 strcpy(name, pretty_offset((int) arg_offset(s)));
292 break;
293 case STOR_SYM:
294 strcpy(name, show_ident(s->sym->ident));
295 break;
296 case STOR_REG:
297 strcpy(name, s->reg->name);
298 break;
299 case STOR_VALUE:
300 sprintf(name, "$%Ld", s->value);
301 break;
302 case STOR_LABEL:
303 sprintf(name, "%s.L%d", s->flags & STOR_LABEL_VAL ? "$" : "",
304 s->label);
305 break;
306 case STOR_LABELSYM:
307 sprintf(name, "%s.LS%p", s->flags & STOR_LABEL_VAL ? "$" : "",
308 s->labelsym);
309 break;
312 return name;
315 static struct atom *new_atom(enum atom_type type)
317 struct atom *atom;
319 atom = calloc(1, sizeof(*atom)); /* TODO: chunked alloc */
320 if (!atom)
321 die("nuclear OOM");
323 atom->type = type;
325 return atom;
328 static inline void push_cstring(struct function *f, struct string *str,
329 int label)
331 struct atom *atom;
333 atom = new_atom(ATOM_CSTR);
334 atom->string = str;
335 atom->label = label;
337 add_ptr_list(&f->str_list, atom); /* note: _not_ atom_list */
340 static inline void push_atom(struct function *f, struct atom *atom)
342 add_ptr_list(&f->atom_list, atom);
345 static void push_text_atom(struct function *f, const char *text)
347 struct atom *atom = new_atom(ATOM_TEXT);
349 atom->text = strdup(text);
350 atom->text_len = strlen(text);
352 push_atom(f, atom);
355 static struct storage *new_storage(enum storage_type type)
357 struct storage *stor;
359 stor = calloc(1, sizeof(*stor));
360 if (!stor)
361 die("OOM in new_storage");
363 stor->type = type;
365 return stor;
368 static struct storage *stack_alloc(int n_bytes)
370 struct function *f = current_func;
371 struct storage *stor;
373 assert(f != NULL);
375 stor = new_storage(STOR_PSEUDO);
376 stor->type = STOR_PSEUDO;
377 stor->pseudo = f->pseudo_nr;
378 stor->offset = f->stack_size;
379 stor->size = n_bytes;
380 f->stack_size += n_bytes;
381 f->pseudo_nr++;
383 add_ptr_list(&f->pseudo_list, stor);
385 return stor;
388 static struct storage *new_labelsym(struct symbol *sym)
390 struct storage *stor;
392 stor = new_storage(STOR_LABELSYM);
394 if (stor) {
395 stor->flags |= STOR_WANTS_FREE;
396 stor->labelsym = sym;
399 return stor;
402 static struct storage *new_val(long long value)
404 struct storage *stor;
406 stor = new_storage(STOR_VALUE);
408 if (stor) {
409 stor->flags |= STOR_WANTS_FREE;
410 stor->value = value;
413 return stor;
416 static int new_label(void)
418 static int label = 0;
419 return ++label;
422 static void textbuf_push(struct textbuf **buf_p, const char *text)
424 struct textbuf *tmp, *list = *buf_p;
425 unsigned int text_len = strlen(text);
426 unsigned int alloc_len = text_len + 1 + sizeof(*list);
428 tmp = calloc(1, alloc_len);
429 if (!tmp)
430 die("OOM on textbuf alloc");
432 tmp->text = ((void *) tmp) + sizeof(*tmp);
433 memcpy(tmp->text, text, text_len + 1);
434 tmp->len = text_len;
436 /* add to end of list */
437 if (!list) {
438 list = tmp;
439 tmp->prev = tmp;
440 } else {
441 tmp->prev = list->prev;
442 tmp->prev->next = tmp;
443 list->prev = tmp;
445 tmp->next = list;
447 *buf_p = list;
450 static void textbuf_emit(struct textbuf **buf_p)
452 struct textbuf *tmp, *list = *buf_p;
454 while (list) {
455 tmp = list;
456 if (tmp->next == tmp)
457 list = NULL;
458 else {
459 tmp->prev->next = tmp->next;
460 tmp->next->prev = tmp->prev;
461 list = tmp->next;
464 fputs(tmp->text, stdout);
466 free(tmp);
469 *buf_p = list;
472 static void insn(const char *insn, struct storage *op1, struct storage *op2,
473 const char *comment_in)
475 struct function *f = current_func;
476 struct atom *atom = new_atom(ATOM_INSN);
478 assert(insn != NULL);
480 strcpy(atom->insn, insn);
481 if (comment_in && (*comment_in))
482 strncpy(atom->comment, comment_in,
483 sizeof(atom->comment) - 1);
485 atom->op1 = op1;
486 atom->op2 = op2;
488 push_atom(f, atom);
491 static void emit_label (int label, const char *comment)
493 struct function *f = current_func;
494 char s[64];
496 if (!comment)
497 sprintf(s, ".L%d:\n", label);
498 else
499 sprintf(s, ".L%d:\t\t\t\t\t# %s\n", label, comment);
501 push_text_atom(f, s);
504 static void emit_labelsym (struct symbol *sym, const char *comment)
506 struct function *f = current_func;
507 char s[64];
509 if (!comment)
510 sprintf(s, ".LS%p:\n", sym);
511 else
512 sprintf(s, ".LS%p:\t\t\t\t# %s\n", sym, comment);
514 push_text_atom(f, s);
517 static void emit_unit_pre(const char *basename)
519 printf("\t.file\t\"%s\"\n", basename);
522 static void emit_unit_post(void)
524 textbuf_emit(&unit_post_text);
525 printf("\t.ident\t\"sparse silly x86 backend (built %s)\"\n", __DATE__);
528 /* conditionally switch sections */
529 static void emit_section(const char *s)
531 if (s == current_section)
532 return;
533 if (current_section && (!strcmp(s, current_section)))
534 return;
536 printf("\t%s\n", s);
537 current_section = s;
540 static void emit_insn_atom(struct function *f, struct atom *atom)
542 char s[128];
543 char comment[64];
544 struct storage *op1 = atom->op1;
545 struct storage *op2 = atom->op2;
547 if (atom->comment[0])
548 sprintf(comment, "\t\t# %s", atom->comment);
549 else
550 comment[0] = 0;
552 if (atom->op2) {
553 char tmp[16];
554 strcpy(tmp, stor_op_name(op1));
555 sprintf(s, "\t%s\t%s, %s%s\n",
556 atom->insn, tmp, stor_op_name(op2), comment);
557 } else if (atom->op1)
558 sprintf(s, "\t%s\t%s%s%s\n",
559 atom->insn, stor_op_name(op1),
560 comment[0] ? "\t" : "", comment);
561 else
562 sprintf(s, "\t%s\t%s%s\n",
563 atom->insn,
564 comment[0] ? "\t\t" : "", comment);
566 write(STDOUT_FILENO, s, strlen(s));
569 static void emit_atom_list(struct function *f)
571 struct atom *atom;
573 FOR_EACH_PTR(f->atom_list, atom) {
574 switch (atom->type) {
575 case ATOM_TEXT: {
576 ssize_t rc = write(STDOUT_FILENO, atom->text,
577 atom->text_len);
578 (void) rc; /* FIXME */
579 break;
581 case ATOM_INSN:
582 emit_insn_atom(f, atom);
583 break;
584 case ATOM_CSTR:
585 assert(0);
586 break;
588 } END_FOR_EACH_PTR;
591 static void emit_string_list(struct function *f)
593 struct atom *atom;
595 emit_section(".section\t.rodata");
597 FOR_EACH_PTR(f->str_list, atom) {
598 /* FIXME: escape " in string */
599 printf(".L%d:\n", atom->label);
600 printf("\t.string\t%s\n", show_string(atom->string));
602 free(atom);
603 } END_FOR_EACH_PTR;
606 static void func_cleanup(struct function *f)
608 struct storage *stor;
609 struct atom *atom;
611 FOR_EACH_PTR(f->pseudo_list, stor) {
612 free(stor);
613 } END_FOR_EACH_PTR;
615 FOR_EACH_PTR(f->atom_list, atom) {
616 if ((atom->type == ATOM_TEXT) && (atom->text))
617 free(atom->text);
618 if (atom->op1 && (atom->op1->flags & STOR_WANTS_FREE))
619 free(atom->op1);
620 if (atom->op2 && (atom->op2->flags & STOR_WANTS_FREE))
621 free(atom->op2);
622 free(atom);
623 } END_FOR_EACH_PTR;
625 free_ptr_list(&f->pseudo_list);
626 free(f);
629 /* function prologue */
630 static void emit_func_pre(struct symbol *sym)
632 struct function *f;
633 struct symbol *arg;
634 unsigned int i, argc = 0, alloc_len;
635 unsigned char *mem;
636 struct symbol_private *privbase;
637 struct storage *storage_base;
638 struct symbol *base_type = sym->ctype.base_type;
640 FOR_EACH_PTR(base_type->arguments, arg) {
641 argc++;
642 } END_FOR_EACH_PTR;
644 alloc_len =
645 sizeof(*f) +
646 (argc * sizeof(struct symbol *)) +
647 (argc * sizeof(struct symbol_private)) +
648 (argc * sizeof(struct storage));
649 mem = calloc(1, alloc_len);
650 if (!mem)
651 die("OOM on func info");
653 f = (struct function *) mem;
654 mem += sizeof(*f);
655 f->argv = (struct symbol **) mem;
656 mem += (argc * sizeof(struct symbol *));
657 privbase = (struct symbol_private *) mem;
658 mem += (argc * sizeof(struct symbol_private));
659 storage_base = (struct storage *) mem;
661 f->argc = argc;
662 f->ret_target = new_label();
664 i = 0;
665 FOR_EACH_PTR(base_type->arguments, arg) {
666 f->argv[i] = arg;
667 arg->aux = &privbase[i];
668 storage_base[i].type = STOR_ARG;
669 storage_base[i].idx = i;
670 privbase[i].addr = &storage_base[i];
671 i++;
672 } END_FOR_EACH_PTR;
674 assert(current_func == NULL);
675 current_func = f;
678 /* function epilogue */
679 static void emit_func_post(struct symbol *sym)
681 const char *name = show_ident(sym->ident);
682 struct function *f = current_func;
683 int stack_size = f->stack_size;
685 if (f->str_list)
686 emit_string_list(f);
688 /* function prologue */
689 emit_section(".text");
690 if ((sym->ctype.modifiers & MOD_STATIC) == 0)
691 printf(".globl %s\n", name);
692 printf("\t.type\t%s, @function\n", name);
693 printf("%s:\n", name);
695 if (stack_size) {
696 char pseudo_const[16];
698 sprintf(pseudo_const, "$%d", stack_size);
699 printf("\tsubl\t%s, %%esp\n", pseudo_const);
702 /* function epilogue */
704 /* jump target for 'return' statements */
705 emit_label(f->ret_target, NULL);
707 if (stack_size) {
708 struct storage *val;
710 val = new_storage(STOR_VALUE);
711 val->value = (long long) (stack_size);
712 val->flags = STOR_WANTS_FREE;
714 insn("addl", val, REG_ESP, NULL);
717 insn("ret", NULL, NULL, NULL);
719 /* output everything to stdout */
720 fflush(stdout); /* paranoia; needed? */
721 emit_atom_list(f);
723 /* function footer */
724 name = show_ident(sym->ident);
725 printf("\t.size\t%s, .-%s\n", name, name);
727 func_cleanup(f);
728 current_func = NULL;
731 /* emit object (a.k.a. variable, a.k.a. data) prologue */
732 static void emit_object_pre(const char *name, unsigned long modifiers,
733 unsigned long alignment, unsigned int byte_size)
735 if ((modifiers & MOD_STATIC) == 0)
736 printf(".globl %s\n", name);
737 emit_section(".data");
738 if (alignment)
739 printf("\t.align %lu\n", alignment);
740 printf("\t.type\t%s, @object\n", name);
741 printf("\t.size\t%s, %d\n", name, byte_size);
742 printf("%s:\n", name);
745 /* emit value (only) for an initializer scalar */
746 static void emit_scalar(struct expression *expr, unsigned int bit_size)
748 const char *type;
749 long long ll;
751 assert(expr->type == EXPR_VALUE);
753 if (expr->value == 0ULL) {
754 printf("\t.zero\t%d\n", bit_size / 8);
755 return;
758 ll = (long long) expr->value;
760 switch (bit_size) {
761 case 8: type = "byte"; ll = (char) ll; break;
762 case 16: type = "value"; ll = (short) ll; break;
763 case 32: type = "long"; ll = (int) ll; break;
764 case 64: type = "quad"; break;
765 default: type = NULL; break;
768 assert(type != NULL);
770 printf("\t.%s\t%Ld\n", type, ll);
773 static void emit_global_noinit(const char *name, unsigned long modifiers,
774 unsigned long alignment, unsigned int byte_size)
776 char s[64];
778 if (modifiers & MOD_STATIC) {
779 sprintf(s, "\t.local\t%s\n", name);
780 textbuf_push(&unit_post_text, s);
782 if (alignment)
783 sprintf(s, "\t.comm\t%s,%d,%lu\n", name, byte_size, alignment);
784 else
785 sprintf(s, "\t.comm\t%s,%d\n", name, byte_size);
786 textbuf_push(&unit_post_text, s);
789 static int ea_current, ea_last;
791 static void emit_initializer(struct symbol *sym,
792 struct expression *expr)
794 int distance = ea_current - ea_last - 1;
796 if (distance > 0)
797 printf("\t.zero\t%d\n", (sym->bit_size / 8) * distance);
799 if (expr->type == EXPR_VALUE) {
800 struct symbol *base_type = sym->ctype.base_type;
801 assert(base_type != NULL);
803 emit_scalar(expr, sym->bit_size / get_expression_value(base_type->array_size));
804 return;
806 if (expr->type != EXPR_INITIALIZER)
807 return;
809 assert(0); /* FIXME */
812 static int sort_array_cmp(const struct expression *a,
813 const struct expression *b)
815 int a_ofs = 0, b_ofs = 0;
817 if (a->type == EXPR_POS)
818 a_ofs = (int) a->init_offset;
819 if (b->type == EXPR_POS)
820 b_ofs = (int) b->init_offset;
822 return a_ofs - b_ofs;
825 /* move to front-end? */
826 static void sort_array(struct expression *expr)
828 struct expression *entry, **list;
829 unsigned int elem, sorted, i;
831 elem = 0;
832 FOR_EACH_PTR(expr->expr_list, entry) {
833 elem++;
834 } END_FOR_EACH_PTR;
836 if (!elem)
837 return;
839 list = malloc(sizeof(entry) * elem);
840 if (!list)
841 die("OOM in sort_array");
843 /* this code is no doubt evil and ignores EXPR_INDEX possibly
844 * to its detriment and other nasty things. improvements
845 * welcome.
847 i = 0;
848 sorted = 0;
849 FOR_EACH_PTR(expr->expr_list, entry) {
850 if ((entry->type == EXPR_POS) || (entry->type == EXPR_VALUE)) {
851 /* add entry to list[], in sorted order */
852 if (sorted == 0) {
853 list[0] = entry;
854 sorted = 1;
855 } else {
856 unsigned int i;
858 for (i = 0; i < sorted; i++)
859 if (sort_array_cmp(entry, list[i]) <= 0)
860 break;
862 /* If inserting into the middle of list[]
863 * instead of appending, we memmove.
864 * This is ugly, but thankfully
865 * uncommon. Input data with tons of
866 * entries very rarely have explicit
867 * offsets. convert to qsort eventually...
869 if (i != sorted)
870 memmove(&list[i + 1], &list[i],
871 (sorted - i) * sizeof(entry));
872 list[i] = entry;
873 sorted++;
876 } END_FOR_EACH_PTR;
878 i = 0;
879 FOR_EACH_PTR(expr->expr_list, entry) {
880 if ((entry->type == EXPR_POS) || (entry->type == EXPR_VALUE))
881 __list->list[__i] = list[i++];
882 } END_FOR_EACH_PTR;
886 static void emit_array(struct symbol *sym)
888 struct symbol *base_type = sym->ctype.base_type;
889 struct expression *expr = sym->initializer;
890 struct expression *entry;
892 assert(base_type != NULL);
894 stor_sym_init(sym);
896 ea_last = -1;
898 emit_object_pre(show_ident(sym->ident), sym->ctype.modifiers,
899 sym->ctype.alignment,
900 sym->bit_size / 8);
902 sort_array(expr);
904 FOR_EACH_PTR(expr->expr_list, entry) {
905 if (entry->type == EXPR_VALUE) {
906 ea_current = 0;
907 emit_initializer(sym, entry);
908 ea_last = ea_current;
909 } else if (entry->type == EXPR_POS) {
910 ea_current =
911 entry->init_offset / (base_type->bit_size / 8);
912 emit_initializer(sym, entry->init_expr);
913 ea_last = ea_current;
915 } END_FOR_EACH_PTR;
918 static void emit_one_symbol(struct symbol *sym, void *dummy, int flags)
920 x86_symbol(sym);
923 void emit_unit(const char *basename, struct symbol_list *list)
925 emit_unit_pre(basename);
926 symbol_iterate(list, emit_one_symbol, NULL);
927 emit_unit_post();
930 static void emit_copy(struct storage *dest, struct storage *src,
931 struct symbol *ctype)
933 struct storage *reg = NULL;
935 /* FIXME: Bitfield move! */
937 switch (ctype->bit_size) {
938 case 8:
939 reg = REG_AL;
940 break;
941 case 16:
942 reg = REG_AX;
943 break;
944 case 32:
945 reg = REG_EAX;
946 break;
947 case 64:
948 reg = REG_EAX; /* FIXME */
949 break;
950 default:
951 assert(0);
952 break;
955 emit_move(src, reg, ctype, "begin copy ..");
956 emit_move(reg, dest, ctype, ".... end copy");
959 static void emit_store(struct expression *dest_expr, struct storage *dest,
960 struct storage *src, int bits)
962 /* FIXME: Bitfield store! */
963 printf("\tst.%d\t\tv%d,[v%d]\n", bits, src->pseudo, dest->pseudo);
966 static void emit_scalar_noinit(struct symbol *sym)
968 emit_global_noinit(show_ident(sym->ident),
969 sym->ctype.modifiers, sym->ctype.alignment,
970 sym->bit_size / 8);
971 stor_sym_init(sym);
974 static void emit_array_noinit(struct symbol *sym)
976 emit_global_noinit(show_ident(sym->ident),
977 sym->ctype.modifiers, sym->ctype.alignment,
978 get_expression_value(sym->array_size) * (sym->bit_size / 8));
979 stor_sym_init(sym);
982 static const char *opbits(const char *insn, unsigned int bits)
984 static char opbits_str[32];
985 char c;
987 switch (bits) {
988 case 8: c = 'b'; break;
989 case 16: c = 'w'; break;
990 case 32: c = 'l'; break;
991 case 64: c = 'q'; break;
992 default: assert(0); break;
995 sprintf(opbits_str, "%s%c", insn, bits);
997 return opbits_str;
1000 static void emit_move(struct storage *src, struct storage *dest,
1001 struct symbol *ctype, const char *comment)
1003 unsigned int bits;
1004 unsigned int is_signed;
1005 unsigned int is_dest = (src->type == STOR_REG);
1006 const char *opname;
1008 if (ctype) {
1009 bits = ctype->bit_size;
1010 is_signed = type_is_signed(ctype);
1011 } else {
1012 bits = 32;
1013 is_signed = 0;
1016 if ((dest->type == STOR_REG) && (src->type == STOR_REG)) {
1017 insn("mov", src, dest, NULL);
1018 return;
1021 switch (bits) {
1022 case 8:
1023 if (is_dest)
1024 opname = "movb";
1025 else {
1026 if (is_signed) opname = "movsxb";
1027 else opname = "movzxb";
1029 break;
1030 case 16:
1031 if (is_dest)
1032 opname = "movw";
1033 else {
1034 if (is_signed) opname = "movsxw";
1035 else opname = "movzxw";
1037 break;
1039 case 32: opname = "movl"; break;
1040 case 64: opname = "movq"; break;
1042 default: assert(0); break;
1045 insn(opname, src, dest, comment);
1048 static struct storage *emit_compare(struct expression *expr)
1050 struct storage *left = x86_expression(expr->left);
1051 struct storage *right = x86_expression(expr->right);
1052 struct storage *new, *val;
1053 const char *opname = NULL;
1054 unsigned int is_signed = type_is_signed(expr->left->ctype); /* FIXME */
1055 unsigned int right_bits = expr->right->ctype->bit_size;
1057 switch(expr->op) {
1058 case '<':
1059 if (is_signed) opname = "setl";
1060 else opname = "setb";
1061 break;
1062 case '>':
1063 if (is_signed) opname = "setg";
1064 else opname = "seta";
1065 break;
1066 case SPECIAL_LTE:
1067 if (is_signed) opname = "setle";
1068 else opname = "setbe";
1069 break;
1070 case SPECIAL_GTE:
1071 if (is_signed) opname = "setge";
1072 else opname = "setae";
1073 break;
1075 case SPECIAL_EQUAL: opname = "sete"; break;
1076 case SPECIAL_NOTEQUAL: opname = "setne"; break;
1078 default:
1079 assert(0);
1080 break;
1083 /* init EDX to 0 */
1084 val = new_storage(STOR_VALUE);
1085 val->flags = STOR_WANTS_FREE;
1086 emit_move(val, REG_EDX, NULL, NULL);
1088 /* move op1 into EAX */
1089 emit_move(left, REG_EAX, expr->left->ctype, NULL);
1091 /* perform comparison, RHS (op1, right) and LHS (op2, EAX) */
1092 insn(opbits("cmp", right_bits), right, REG_EAX, NULL);
1094 /* store result of operation, 0 or 1, in DL using SETcc */
1095 insn(opname, REG_DL, NULL, NULL);
1097 /* finally, store the result (DL) in a new pseudo / stack slot */
1098 new = stack_alloc(4);
1099 emit_move(REG_EDX, new, NULL, "end EXPR_COMPARE");
1101 return new;
1104 static struct storage *emit_value(struct expression *expr)
1106 #if 0 /* old and slow way */
1107 struct storage *new = stack_alloc(4);
1108 struct storage *val;
1110 val = new_storage(STOR_VALUE);
1111 val->value = (long long) expr->value;
1112 val->flags = STOR_WANTS_FREE;
1113 insn("movl", val, new, NULL);
1115 return new;
1116 #else
1117 struct storage *val;
1119 val = new_storage(STOR_VALUE);
1120 val->value = (long long) expr->value;
1122 return val; /* FIXME: memory leak */
1123 #endif
1126 static struct storage *emit_binop(struct expression *expr)
1128 struct storage *left = x86_expression(expr->left);
1129 struct storage *right = x86_expression(expr->right);
1130 struct storage *new;
1131 struct storage *accum_reg = NULL;
1132 struct storage *result_reg = NULL;
1133 const char *opname = NULL;
1134 const char *suffix;
1135 char movstr[16], opstr[16];
1136 int is_signed, doing_divide = 0;
1138 if ((expr->op == '/') || (expr->op == '%')) {
1139 doing_divide = 1;
1140 /* init EDX to 0 */
1141 struct storage *val = new_storage(STOR_VALUE);
1142 val->flags = STOR_WANTS_FREE;
1143 emit_move(val, REG_EDX, NULL, "begin EXPR_DIVIDE");
1146 is_signed = type_is_signed(expr->ctype);
1148 switch (expr->op) {
1149 case '+':
1150 opname = "add";
1151 break;
1152 case '-':
1153 opname = "sub";
1154 break;
1155 case '&':
1156 opname = "and";
1157 break;
1158 case '|':
1159 opname = "or";
1160 break;
1161 case '^':
1162 opname = "xor";
1163 break;
1164 case SPECIAL_LEFTSHIFT:
1165 opname = "shl";
1166 break;
1167 case SPECIAL_RIGHTSHIFT:
1168 if (is_signed)
1169 opname = "sar";
1170 else
1171 opname = "shr";
1172 break;
1173 case '*':
1174 if (is_signed)
1175 opname = "imul";
1176 else
1177 opname = "mul";
1178 break;
1179 case '/':
1180 case '%':
1181 if (is_signed)
1182 opname = "idiv";
1183 else
1184 opname = "div";
1185 break;
1186 default:
1187 assert(0);
1188 break;
1191 switch (expr->ctype->bit_size) {
1192 case 8:
1193 suffix = "b";
1194 result_reg = accum_reg = REG_AL;
1195 if (expr->op == '%')
1196 result_reg = REG_DL;
1197 break;
1198 case 16:
1199 suffix = "w";
1200 result_reg = accum_reg = REG_AX;
1201 if (expr->op == '%')
1202 result_reg = REG_DX;
1203 break;
1204 case 32:
1205 suffix = "l";
1206 result_reg = accum_reg = REG_EAX;
1207 if (expr->op == '%')
1208 result_reg = REG_EDX;
1209 break;
1210 case 64:
1211 suffix = "q"; /* FIXME */
1212 result_reg = accum_reg = REG_EAX; /* FIXME */
1213 if (expr->op == '%')
1214 result_reg = REG_EDX;
1215 break;
1216 default:
1217 assert(0);
1218 break;
1221 sprintf(movstr, "mov%s", suffix);
1222 sprintf(opstr, "%s%s", opname, suffix);
1224 /* load op2 into EAX */
1225 insn(movstr, right, accum_reg,
1226 doing_divide ? NULL : "EXPR_BINOP/COMMA/LOGICAL");
1228 /* perform binop */
1229 insn(opstr, left, accum_reg, NULL);
1231 /* store result (EAX or EDX) in new pseudo / stack slot */
1232 new = stack_alloc(4);
1233 insn(movstr, result_reg, new,
1234 doing_divide ? "end EXPR_DIVIDE" : "end EXPR_BINOP");
1236 return new;
1239 static void emit_if_conditional(struct statement *stmt)
1241 struct storage *val, *target_val;
1242 int target;
1243 struct expression *cond = stmt->if_conditional;
1245 /* This is only valid if nobody can jump into the "dead" statement */
1246 #if 0
1247 if (cond->type == EXPR_VALUE) {
1248 struct statement *s = stmt->if_true;
1249 if (!cond->value)
1250 s = stmt->if_false;
1251 x86_statement(s);
1252 break;
1254 #endif
1255 val = x86_expression(cond);
1257 /* load 'if' test result into EAX */
1258 insn("movl", val, REG_EAX, "begin if conditional");
1260 /* compare 'if' test result */
1261 insn("test", REG_EAX, REG_EAX, NULL);
1263 /* create end-of-if label / if-failed labelto jump to,
1264 * and jump to it if the expression returned zero.
1266 target = new_label();
1267 target_val = new_storage(STOR_LABEL);
1268 target_val->label = target;
1269 target_val->flags = STOR_WANTS_FREE;
1270 insn("jz", target_val, NULL, NULL);
1272 x86_statement(stmt->if_true);
1273 if (stmt->if_false) {
1274 struct storage *last_val;
1275 int last;
1277 /* finished generating code for if-true statement.
1278 * add a jump-to-end jump to avoid falling through
1279 * to the if-false statement code.
1281 last = new_label();
1282 last_val = new_storage(STOR_LABEL);
1283 last_val->label = last;
1284 last_val->flags = STOR_WANTS_FREE;
1285 insn("jmp", last_val, NULL, NULL);
1287 /* if we have both if-true and if-false statements,
1288 * the failed-conditional case will fall through to here
1290 emit_label(target, NULL);
1292 target = last;
1293 x86_statement(stmt->if_false);
1296 emit_label(target, "end if");
1299 static struct storage *emit_inc_dec(struct expression *expr, int postop)
1301 struct storage *addr = x86_address_gen(expr->unop);
1302 struct storage *retval;
1303 char opname[16];
1305 strcpy(opname, opbits(expr->op == SPECIAL_INCREMENT ? "inc" : "dec",
1306 expr->ctype->bit_size));
1308 if (postop) {
1309 struct storage *new = stack_alloc(4);
1311 emit_copy(new, addr, expr->unop->ctype);
1313 retval = new;
1314 } else
1315 retval = addr;
1317 insn(opname, addr, NULL, NULL);
1319 return retval;
1322 static struct storage *emit_postop(struct expression *expr)
1324 return emit_inc_dec(expr, 1);
1327 static struct storage *emit_return_stmt(struct statement *stmt)
1329 struct function *f = current_func;
1330 struct expression *expr = stmt->ret_value;
1331 struct storage *val = NULL, *jmplbl;
1333 if (expr && expr->ctype) {
1334 val = x86_expression(expr);
1335 assert(val != NULL);
1336 emit_move(val, REG_EAX, expr->ctype, "return");
1339 jmplbl = new_storage(STOR_LABEL);
1340 jmplbl->flags |= STOR_WANTS_FREE;
1341 jmplbl->label = f->ret_target;
1342 insn("jmp", jmplbl, NULL, NULL);
1344 return val;
1347 static struct storage *emit_conditional_expr(struct expression *expr)
1349 struct storage *cond = x86_expression(expr->conditional);
1350 struct storage *true = x86_expression(expr->cond_true);
1351 struct storage *false = x86_expression(expr->cond_false);
1352 struct storage *new = stack_alloc(4);
1354 if (!true)
1355 true = cond;
1357 emit_move(cond, REG_EAX, expr->conditional->ctype,
1358 "begin EXPR_CONDITIONAL");
1359 emit_move(true, REG_ECX, expr->cond_true->ctype, NULL);
1360 emit_move(false, REG_EDX, expr->cond_false->ctype, NULL);
1362 /* test EAX (for zero/non-zero) */
1363 insn("test", REG_EAX, REG_EAX, NULL);
1365 /* if false, move EDX to ECX */
1366 insn("cmovz", REG_EDX, REG_ECX, NULL);
1368 /* finally, store the result (ECX) in a new pseudo / stack slot */
1369 new = stack_alloc(4);
1370 emit_move(REG_ECX, new, expr->ctype, "end EXPR_CONDITIONAL");
1371 /* FIXME: we lose type knowledge of expression result at this point */
1373 return new;
1376 static struct storage *emit_symbol_expr_init(struct symbol *sym)
1378 struct expression *expr = sym->initializer;
1379 struct symbol_private *priv = sym->aux;
1381 if (priv == NULL) {
1382 priv = calloc(1, sizeof(*priv));
1383 sym->aux = priv;
1385 if (expr == NULL) {
1386 struct storage *new = stack_alloc(4);
1387 fprintf(stderr, "FIXME! no value for symbol. creating pseudo %d (stack offset %d)\n",
1388 new->pseudo, new->pseudo * 4);
1389 priv->addr = new;
1390 } else {
1391 priv->addr = x86_expression(expr);
1395 return priv->addr;
1398 static struct storage *emit_string_expr(struct expression *expr)
1400 struct function *f = current_func;
1401 int label = new_label();
1402 struct storage *new;
1404 push_cstring(f, expr->string, label);
1406 new = new_storage(STOR_LABEL);
1407 new->label = label;
1408 new->flags = STOR_LABEL_VAL | STOR_WANTS_FREE;
1409 return new;
1412 static struct storage *emit_cast_expr(struct expression *expr)
1414 struct symbol *old_type, *new_type;
1415 struct storage *op = x86_expression(expr->cast_expression);
1416 int oldbits, newbits;
1417 struct storage *new;
1419 old_type = expr->cast_expression->ctype;
1420 new_type = expr->cast_type;
1422 oldbits = old_type->bit_size;
1423 newbits = new_type->bit_size;
1424 if (oldbits >= newbits)
1425 return op;
1427 emit_move(op, REG_EAX, old_type, "begin cast ..");
1429 new = stack_alloc(4);
1430 emit_move(REG_EAX, new, new_type, ".... end cast");
1432 return new;
1435 static struct storage *emit_regular_preop(struct expression *expr)
1437 struct storage *target = x86_expression(expr->unop);
1438 struct storage *val, *new = stack_alloc(4);
1439 const char *opname = NULL;
1441 switch (expr->op) {
1442 case '!':
1443 val = new_storage(STOR_VALUE);
1444 val->flags = STOR_WANTS_FREE;
1445 emit_move(val, REG_EDX, NULL, NULL);
1446 emit_move(target, REG_EAX, expr->unop->ctype, NULL);
1447 insn("test", REG_EAX, REG_EAX, NULL);
1448 insn("setz", REG_DL, NULL, NULL);
1449 emit_move(REG_EDX, new, expr->unop->ctype, NULL);
1451 break;
1452 case '~':
1453 opname = "not";
1454 case '-':
1455 if (!opname)
1456 opname = "neg";
1457 emit_move(target, REG_EAX, expr->unop->ctype, NULL);
1458 insn(opname, REG_EAX, NULL, NULL);
1459 emit_move(REG_EAX, new, expr->unop->ctype, NULL);
1460 break;
1461 default:
1462 assert(0);
1463 break;
1466 return new;
1469 static void emit_case_statement(struct statement *stmt)
1471 emit_labelsym(stmt->case_label, NULL);
1472 x86_statement(stmt->case_statement);
1475 static void emit_switch_statement(struct statement *stmt)
1477 struct storage *val = x86_expression(stmt->switch_expression);
1478 struct symbol *sym, *default_sym = NULL;
1479 struct storage *labelsym, *label;
1480 int switch_end = 0;
1482 emit_move(val, REG_EAX, stmt->switch_expression->ctype, "begin case");
1485 * This is where a _real_ back-end would go through the
1486 * cases to decide whether to use a lookup table or a
1487 * series of comparisons etc
1489 FOR_EACH_PTR(stmt->switch_case->symbol_list, sym) {
1490 struct statement *case_stmt = sym->stmt;
1491 struct expression *expr = case_stmt->case_expression;
1492 struct expression *to = case_stmt->case_to;
1494 /* default: */
1495 if (!expr)
1496 default_sym = sym;
1498 /* case NNN: */
1499 else {
1500 struct storage *case_val = new_val(expr->value);
1502 assert (expr->type == EXPR_VALUE);
1504 insn("cmpl", case_val, REG_EAX, NULL);
1506 if (!to) {
1507 labelsym = new_labelsym(sym);
1508 insn("je", labelsym, NULL, NULL);
1509 } else {
1510 int next_test;
1512 label = new_storage(STOR_LABEL);
1513 label->flags |= STOR_WANTS_FREE;
1514 label->label = next_test = new_label();
1516 /* FIXME: signed/unsigned */
1517 insn("jl", label, NULL, NULL);
1519 case_val = new_val(to->value);
1520 insn("cmpl", case_val, REG_EAX, NULL);
1522 /* TODO: implement and use refcounting... */
1523 label = new_storage(STOR_LABEL);
1524 label->flags |= STOR_WANTS_FREE;
1525 label->label = next_test;
1527 /* FIXME: signed/unsigned */
1528 insn("jg", label, NULL, NULL);
1530 labelsym = new_labelsym(sym);
1531 insn("jmp", labelsym, NULL, NULL);
1533 emit_label(next_test, NULL);
1536 } END_FOR_EACH_PTR;
1538 if (default_sym) {
1539 labelsym = new_labelsym(default_sym);
1540 insn("jmp", labelsym, NULL, "default");
1541 } else {
1542 label = new_storage(STOR_LABEL);
1543 label->flags |= STOR_WANTS_FREE;
1544 label->label = switch_end = new_label();
1545 insn("jmp", label, NULL, "goto end of switch");
1548 x86_statement(stmt->switch_statement);
1550 if (stmt->switch_break->used)
1551 emit_labelsym(stmt->switch_break, NULL);
1553 if (switch_end)
1554 emit_label(switch_end, NULL);
1557 static void x86_struct_member(struct symbol *sym, void *data, int flags)
1559 if (flags & ITERATE_FIRST)
1560 printf(" {\n\t");
1561 printf("%s:%d:%ld at offset %ld", show_ident(sym->ident), sym->bit_size, sym->ctype.alignment, sym->offset);
1562 if (sym->fieldwidth)
1563 printf("[%d..%d]", sym->bit_offset, sym->bit_offset+sym->fieldwidth-1);
1564 if (flags & ITERATE_LAST)
1565 printf("\n} ");
1566 else
1567 printf(", ");
1570 static void x86_symbol(struct symbol *sym)
1572 struct symbol *type;
1574 if (!sym)
1575 return;
1577 type = sym->ctype.base_type;
1578 if (!type)
1579 return;
1582 * Show actual implementation information
1584 switch (type->type) {
1586 case SYM_ARRAY:
1587 if (sym->initializer)
1588 emit_array(sym);
1589 else
1590 emit_array_noinit(sym);
1591 break;
1593 case SYM_BASETYPE:
1594 if (sym->initializer) {
1595 emit_object_pre(show_ident(sym->ident),
1596 sym->ctype.modifiers,
1597 sym->ctype.alignment,
1598 sym->bit_size / 8);
1599 emit_scalar(sym->initializer, sym->bit_size);
1600 stor_sym_init(sym);
1601 } else
1602 emit_scalar_noinit(sym);
1603 break;
1605 case SYM_STRUCT:
1606 symbol_iterate(type->symbol_list, x86_struct_member, NULL);
1607 break;
1609 case SYM_UNION:
1610 symbol_iterate(type->symbol_list, x86_struct_member, NULL);
1611 break;
1613 case SYM_FN: {
1614 struct statement *stmt = type->stmt;
1615 if (stmt) {
1616 emit_func_pre(sym);
1617 x86_statement(stmt);
1618 emit_func_post(sym);
1620 break;
1623 default:
1624 break;
1627 if (sym->initializer && (type->type != SYM_BASETYPE) &&
1628 (type->type != SYM_ARRAY)) {
1629 printf(" = \n");
1630 x86_expression(sym->initializer);
1634 static void x86_symbol_init(struct symbol *sym);
1636 static void x86_symbol_decl(struct symbol_list *syms)
1638 struct symbol *sym;
1639 FOR_EACH_PTR(syms, sym) {
1640 x86_symbol_init(sym);
1641 } END_FOR_EACH_PTR;
1644 static void loopstk_push(int cont_lbl, int loop_bottom_lbl)
1646 struct function *f = current_func;
1647 struct loop_stack *ls;
1649 ls = malloc(sizeof(*ls));
1650 ls->continue_lbl = cont_lbl;
1651 ls->loop_bottom_lbl = loop_bottom_lbl;
1652 ls->next = f->loop_stack;
1653 f->loop_stack = ls;
1656 static void loopstk_pop(void)
1658 struct function *f = current_func;
1659 struct loop_stack *ls;
1661 assert(f->loop_stack != NULL);
1662 ls = f->loop_stack;
1663 f->loop_stack = f->loop_stack->next;
1664 free(ls);
1667 static int loopstk_break(void)
1669 return current_func->loop_stack->loop_bottom_lbl;
1672 static int loopstk_continue(void)
1674 return current_func->loop_stack->continue_lbl;
1677 static void emit_loop(struct statement *stmt)
1679 struct statement *pre_statement = stmt->iterator_pre_statement;
1680 struct expression *pre_condition = stmt->iterator_pre_condition;
1681 struct statement *statement = stmt->iterator_statement;
1682 struct statement *post_statement = stmt->iterator_post_statement;
1683 struct expression *post_condition = stmt->iterator_post_condition;
1684 int loop_top = 0, loop_bottom, loop_continue;
1685 int have_bottom = 0;
1686 struct storage *val;
1688 loop_bottom = new_label();
1689 loop_continue = new_label();
1690 loopstk_push(loop_continue, loop_bottom);
1692 x86_symbol_decl(stmt->iterator_syms);
1693 x86_statement(pre_statement);
1694 if (pre_condition) {
1695 if (pre_condition->type == EXPR_VALUE) {
1696 if (!pre_condition->value) {
1697 struct storage *lbv;
1698 lbv = new_storage(STOR_LABEL);
1699 lbv->label = loop_bottom;
1700 lbv->flags = STOR_WANTS_FREE;
1701 insn("jmp", lbv, NULL, "go to loop bottom");
1702 have_bottom = 1;
1704 } else {
1705 struct storage *lbv = new_storage(STOR_LABEL);
1706 lbv->label = loop_bottom;
1707 lbv->flags = STOR_WANTS_FREE;
1708 have_bottom = 1;
1710 val = x86_expression(pre_condition);
1712 emit_move(val, REG_EAX, NULL, "loop pre condition");
1713 insn("test", REG_EAX, REG_EAX, NULL);
1714 insn("jz", lbv, NULL, NULL);
1717 if (!post_condition || post_condition->type != EXPR_VALUE || post_condition->value) {
1718 loop_top = new_label();
1719 emit_label(loop_top, "loop top");
1721 x86_statement(statement);
1722 if (stmt->iterator_continue->used)
1723 emit_label(loop_continue, "'continue' iterator");
1724 x86_statement(post_statement);
1725 if (!post_condition) {
1726 struct storage *lbv = new_storage(STOR_LABEL);
1727 lbv->label = loop_top;
1728 lbv->flags = STOR_WANTS_FREE;
1729 insn("jmp", lbv, NULL, "go to loop top");
1730 } else if (post_condition->type == EXPR_VALUE) {
1731 if (post_condition->value) {
1732 struct storage *lbv = new_storage(STOR_LABEL);
1733 lbv->label = loop_top;
1734 lbv->flags = STOR_WANTS_FREE;
1735 insn("jmp", lbv, NULL, "go to loop top");
1737 } else {
1738 struct storage *lbv = new_storage(STOR_LABEL);
1739 lbv->label = loop_top;
1740 lbv->flags = STOR_WANTS_FREE;
1742 val = x86_expression(post_condition);
1744 emit_move(val, REG_EAX, NULL, "loop post condition");
1745 insn("test", REG_EAX, REG_EAX, NULL);
1746 insn("jnz", lbv, NULL, NULL);
1748 if (have_bottom || stmt->iterator_break->used)
1749 emit_label(loop_bottom, "loop bottom");
1751 loopstk_pop();
1755 * Print out a statement
1757 static struct storage *x86_statement(struct statement *stmt)
1759 if (!stmt)
1760 return 0;
1761 switch (stmt->type) {
1762 case STMT_RETURN:
1763 return emit_return_stmt(stmt);
1764 case STMT_COMPOUND: {
1765 struct statement *s;
1766 struct storage *last = NULL;
1768 x86_symbol_decl(stmt->syms);
1769 FOR_EACH_PTR(stmt->stmts, s) {
1770 last = x86_statement(s);
1771 } END_FOR_EACH_PTR;
1773 return last;
1776 case STMT_EXPRESSION:
1777 return x86_expression(stmt->expression);
1778 case STMT_IF:
1779 emit_if_conditional(stmt);
1780 return NULL;
1782 case STMT_CASE:
1783 emit_case_statement(stmt);
1784 break;
1785 case STMT_SWITCH:
1786 emit_switch_statement(stmt);
1787 break;
1789 case STMT_ITERATOR:
1790 emit_loop(stmt);
1791 break;
1793 case STMT_NONE:
1794 break;
1796 case STMT_LABEL:
1797 printf(".L%p:\n", stmt->label_identifier);
1798 x86_statement(stmt->label_statement);
1799 break;
1801 case STMT_GOTO:
1802 if (stmt->goto_expression) {
1803 struct storage *val = x86_expression(stmt->goto_expression);
1804 printf("\tgoto *v%d\n", val->pseudo);
1805 } else if (!strcmp("break", show_ident(stmt->goto_label->ident))) {
1806 struct storage *lbv = new_storage(STOR_LABEL);
1807 lbv->label = loopstk_break();
1808 lbv->flags = STOR_WANTS_FREE;
1809 insn("jmp", lbv, NULL, "'break'; go to loop bottom");
1810 } else if (!strcmp("continue", show_ident(stmt->goto_label->ident))) {
1811 struct storage *lbv = new_storage(STOR_LABEL);
1812 lbv->label = loopstk_continue();
1813 lbv->flags = STOR_WANTS_FREE;
1814 insn("jmp", lbv, NULL, "'continue'; go to loop top");
1815 } else {
1816 struct storage *labelsym = new_labelsym(stmt->goto_label);
1817 insn("jmp", labelsym, NULL, NULL);
1819 break;
1820 case STMT_ASM:
1821 printf("\tasm( .... )\n");
1822 break;
1824 return NULL;
1827 static struct storage *x86_call_expression(struct expression *expr)
1829 struct function *f = current_func;
1830 struct symbol *direct;
1831 struct expression *arg, *fn;
1832 struct storage *retval, *fncall;
1833 int framesize;
1834 char s[64];
1836 if (!expr->ctype) {
1837 warn(expr->pos, "\tcall with no type!");
1838 return NULL;
1841 framesize = 0;
1842 FOR_EACH_PTR_REVERSE(expr->args, arg) {
1843 struct storage *new = x86_expression(arg);
1844 int size = arg->ctype->bit_size;
1846 /* FIXME: pay attention to 'size' */
1847 insn("pushl", new, NULL,
1848 !framesize ? "begin function call" : NULL);
1850 framesize += size >> 3;
1851 } END_FOR_EACH_PTR_REVERSE;
1853 fn = expr->fn;
1855 /* Remove dereference, if any */
1856 direct = NULL;
1857 if (fn->type == EXPR_PREOP) {
1858 if (fn->unop->type == EXPR_SYMBOL) {
1859 struct symbol *sym = fn->unop->symbol;
1860 if (sym->ctype.base_type->type == SYM_FN)
1861 direct = sym;
1864 if (direct) {
1865 struct storage *direct_stor = new_storage(STOR_SYM);
1866 direct_stor->flags |= STOR_WANTS_FREE;
1867 direct_stor->sym = direct;
1868 insn("call", direct_stor, NULL, NULL);
1869 } else {
1870 fncall = x86_expression(fn);
1871 emit_move(fncall, REG_EAX, fn->ctype, NULL);
1873 strcpy(s, "\tcall\t*%eax\n");
1874 push_text_atom(f, s);
1877 /* FIXME: pay attention to BITS_IN_POINTER */
1878 if (framesize) {
1879 struct storage *val = new_storage(STOR_VALUE);
1880 val->value = (long long) framesize;
1881 val->flags = STOR_WANTS_FREE;
1882 insn("addl", val, REG_ESP, NULL);
1885 retval = stack_alloc(4);
1886 emit_move(REG_EAX, retval, NULL, "end function call");
1888 return retval;
1891 static struct storage *x86_address_gen(struct expression *expr)
1893 struct function *f = current_func;
1894 struct storage *addr;
1895 struct storage *new;
1896 char s[32];
1898 if ((expr->type != EXPR_PREOP) || (expr->op != '*'))
1899 return x86_expression(expr->address);
1901 addr = x86_expression(expr->unop);
1902 if (expr->unop->type == EXPR_SYMBOL)
1903 return addr;
1905 emit_move(addr, REG_EAX, NULL, "begin deref ..");
1907 /* FIXME: operand size */
1908 strcpy(s, "\tmovl\t(%eax), %ecx\n");
1909 push_text_atom(f, s);
1911 new = stack_alloc(4);
1912 emit_move(REG_ECX, new, NULL, ".... end deref");
1914 return new;
1917 static struct storage *x86_assignment(struct expression *expr)
1919 struct expression *target = expr->left;
1920 struct storage *val, *addr;
1922 if (!expr->ctype)
1923 return NULL;
1925 val = x86_expression(expr->right);
1926 addr = x86_address_gen(target);
1928 switch (val->type) {
1929 /* copy, where both operands are memory */
1930 case STOR_PSEUDO:
1931 case STOR_ARG:
1932 emit_copy(addr, val, expr->ctype);
1933 break;
1935 /* copy, one or zero operands are memory */
1936 case STOR_REG:
1937 case STOR_SYM:
1938 case STOR_VALUE:
1939 case STOR_LABEL:
1940 emit_move(val, addr, expr->left->ctype, NULL);
1941 break;
1943 case STOR_LABELSYM:
1944 assert(0);
1945 break;
1947 return val;
1950 static int x86_initialization(struct symbol *sym, struct expression *expr)
1952 struct storage *val, *addr;
1953 int bits;
1955 if (!expr->ctype)
1956 return 0;
1958 bits = expr->ctype->bit_size;
1959 val = x86_expression(expr);
1960 addr = x86_symbol_expr(sym);
1961 // FIXME! The "target" expression is for bitfield store information.
1962 // Leave it NULL, which works fine.
1963 emit_store(NULL, addr, val, bits);
1964 return 0;
1967 static struct storage *x86_access(struct expression *expr)
1969 return x86_address_gen(expr);
1972 static struct storage *x86_preop(struct expression *expr)
1975 * '*' is an lvalue access, and is fundamentally different
1976 * from an arithmetic operation. Maybe it should have an
1977 * expression type of its own..
1979 if (expr->op == '*')
1980 return x86_access(expr);
1981 if (expr->op == SPECIAL_INCREMENT || expr->op == SPECIAL_DECREMENT)
1982 return emit_inc_dec(expr, 0);
1983 return emit_regular_preop(expr);
1986 static struct storage *x86_symbol_expr(struct symbol *sym)
1988 struct storage *new = stack_alloc(4);
1990 if (sym->ctype.modifiers & (MOD_TOPLEVEL | MOD_EXTERN | MOD_STATIC)) {
1991 printf("\tmovi.%d\t\tv%d,$%s\n", BITS_IN_POINTER, new->pseudo, show_ident(sym->ident));
1992 return new;
1994 if (sym->ctype.modifiers & MOD_ADDRESSABLE) {
1995 printf("\taddi.%d\t\tv%d,vFP,$%lld\n", BITS_IN_POINTER, new->pseudo, sym->value);
1996 return new;
1998 printf("\taddi.%d\t\tv%d,vFP,$offsetof(%s:%p)\n", BITS_IN_POINTER, new->pseudo, show_ident(sym->ident), sym);
1999 return new;
2002 static void x86_symbol_init(struct symbol *sym)
2004 struct symbol_private *priv = sym->aux;
2005 struct expression *expr = sym->initializer;
2006 struct storage *new;
2008 if (expr)
2009 new = x86_expression(expr);
2010 else
2011 new = stack_alloc(sym->bit_size / 8);
2013 if (!priv) {
2014 priv = calloc(1, sizeof(*priv));
2015 sym->aux = priv;
2016 /* FIXME: leak! we don't free... */
2017 /* (well, we don't free symbols either) */
2020 priv->addr = new;
2023 static int type_is_signed(struct symbol *sym)
2025 if (sym->type == SYM_NODE)
2026 sym = sym->ctype.base_type;
2027 if (sym->type == SYM_PTR)
2028 return 0;
2029 return !(sym->ctype.modifiers & MOD_UNSIGNED);
2032 static struct storage *x86_bitfield_expr(struct expression *expr)
2034 return x86_access(expr);
2037 static struct storage *x86_label_expr(struct expression *expr)
2039 struct storage *new = stack_alloc(4);
2040 printf("\tmovi.%d\t\tv%d,.L%p\n",BITS_IN_POINTER, new->pseudo, expr->label_symbol);
2041 return new;
2044 static struct storage *x86_statement_expr(struct expression *expr)
2046 return x86_statement(expr->statement);
2049 static int x86_position_expr(struct expression *expr, struct symbol *base)
2051 struct storage *new = x86_expression(expr->init_expr);
2052 struct symbol *ctype = expr->init_sym;
2054 printf("\tinsert v%d at [%d:%d] of %s\n", new->pseudo,
2055 expr->init_offset, ctype->bit_offset,
2056 show_ident(base->ident));
2057 return 0;
2060 static void x86_initializer_expr(struct expression *expr, struct symbol *ctype)
2062 struct expression *entry;
2064 FOR_EACH_PTR(expr->expr_list, entry) {
2065 // Nested initializers have their positions already
2066 // recursively calculated - just output them too
2067 if (entry->type == EXPR_INITIALIZER) {
2068 x86_initializer_expr(entry, ctype);
2069 continue;
2072 // Ignore initializer indexes and identifiers - the
2073 // evaluator has taken them into account
2074 if (entry->type == EXPR_IDENTIFIER || entry->type == EXPR_INDEX)
2075 continue;
2076 if (entry->type == EXPR_POS) {
2077 x86_position_expr(entry, ctype);
2078 continue;
2080 x86_initialization(ctype, entry);
2081 } END_FOR_EACH_PTR;
2085 * Print out an expression. Return the pseudo that contains the
2086 * variable.
2088 static struct storage *x86_expression(struct expression *expr)
2090 if (!expr)
2091 return 0;
2093 if (!expr->ctype) {
2094 struct position *pos = &expr->pos;
2095 printf("\tno type at %s:%d:%d\n",
2096 input_streams[pos->stream].name,
2097 pos->line, pos->pos);
2098 return 0;
2101 switch (expr->type) {
2102 case EXPR_CALL:
2103 return x86_call_expression(expr);
2105 case EXPR_ASSIGNMENT:
2106 return x86_assignment(expr);
2108 case EXPR_COMPARE:
2109 return emit_compare(expr);
2110 case EXPR_BINOP:
2111 case EXPR_COMMA:
2112 case EXPR_LOGICAL:
2113 return emit_binop(expr);
2114 case EXPR_PREOP:
2115 return x86_preop(expr);
2116 case EXPR_POSTOP:
2117 return emit_postop(expr);
2118 case EXPR_SYMBOL:
2119 return emit_symbol_expr_init(expr->symbol);
2120 case EXPR_DEREF:
2121 case EXPR_SIZEOF:
2122 warn(expr->pos, "invalid expression after evaluation");
2123 return 0;
2124 case EXPR_CAST:
2125 return emit_cast_expr(expr);
2126 case EXPR_VALUE:
2127 return emit_value(expr);
2128 case EXPR_STRING:
2129 return emit_string_expr(expr);
2130 case EXPR_BITFIELD:
2131 return x86_bitfield_expr(expr);
2132 case EXPR_INITIALIZER:
2133 x86_initializer_expr(expr, expr->ctype);
2134 return NULL;
2135 case EXPR_CONDITIONAL:
2136 return emit_conditional_expr(expr);
2137 case EXPR_STATEMENT:
2138 return x86_statement_expr(expr);
2139 case EXPR_LABEL:
2140 return x86_label_expr(expr);
2142 // None of these should exist as direct expressions: they are only
2143 // valid as sub-expressions of initializers.
2144 case EXPR_POS:
2145 warn(expr->pos, "unable to show plain initializer position expression");
2146 return 0;
2147 case EXPR_IDENTIFIER:
2148 warn(expr->pos, "unable to show identifier expression");
2149 return 0;
2150 case EXPR_INDEX:
2151 warn(expr->pos, "unable to show index expression");
2152 return 0;
2153 case EXPR_TYPE:
2154 warn(expr->pos, "unable to show type expression");
2155 return 0;
2157 return 0;