[PATCH] evaluate_conditional() prepared for FP
[smatch.git] / compile-i386.c
blob596b47ae3e51a11c3ee72acf3dbdc9313ec6b335
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 right_bits = expr->right->ctype->bit_size;
1056 switch(expr->op) {
1057 case '<': opname = "setl"; break;
1058 case '>': opname = "setg"; break;
1059 case SPECIAL_LTE:
1060 opname = "setle"; break;
1061 case SPECIAL_GTE:
1062 opname = "setge"; break;
1063 case SPECIAL_EQUAL: opname = "sete"; break;
1064 case SPECIAL_NOTEQUAL: opname = "setne"; break;
1065 case SPECIAL_UNSIGNED_LT:
1066 opname = "setb"; break;
1067 case SPECIAL_UNSIGNED_GT:
1068 opname = "seta"; break;
1069 case SPECIAL_UNSIGNED_LTE:
1070 opname = "setb"; break;
1071 case SPECIAL_UNSIGNED_GTE:
1072 opname = "setae"; break;
1073 default:
1074 assert(0);
1075 break;
1078 /* init EDX to 0 */
1079 val = new_storage(STOR_VALUE);
1080 val->flags = STOR_WANTS_FREE;
1081 emit_move(val, REG_EDX, NULL, NULL);
1083 /* move op1 into EAX */
1084 emit_move(left, REG_EAX, expr->left->ctype, NULL);
1086 /* perform comparison, RHS (op1, right) and LHS (op2, EAX) */
1087 insn(opbits("cmp", right_bits), right, REG_EAX, NULL);
1089 /* store result of operation, 0 or 1, in DL using SETcc */
1090 insn(opname, REG_DL, NULL, NULL);
1092 /* finally, store the result (DL) in a new pseudo / stack slot */
1093 new = stack_alloc(4);
1094 emit_move(REG_EDX, new, NULL, "end EXPR_COMPARE");
1096 return new;
1099 static struct storage *emit_value(struct expression *expr)
1101 #if 0 /* old and slow way */
1102 struct storage *new = stack_alloc(4);
1103 struct storage *val;
1105 val = new_storage(STOR_VALUE);
1106 val->value = (long long) expr->value;
1107 val->flags = STOR_WANTS_FREE;
1108 insn("movl", val, new, NULL);
1110 return new;
1111 #else
1112 struct storage *val;
1114 val = new_storage(STOR_VALUE);
1115 val->value = (long long) expr->value;
1117 return val; /* FIXME: memory leak */
1118 #endif
1121 static struct storage *emit_binop(struct expression *expr)
1123 struct storage *left = x86_expression(expr->left);
1124 struct storage *right = x86_expression(expr->right);
1125 struct storage *new;
1126 struct storage *accum_reg = NULL;
1127 struct storage *result_reg = NULL;
1128 const char *opname = NULL;
1129 const char *suffix;
1130 char movstr[16], opstr[16];
1131 int is_signed, doing_divide = 0;
1133 if ((expr->op == '/') || (expr->op == '%')) {
1134 struct storage *val;
1136 doing_divide = 1;
1137 /* init EDX to 0 */
1138 val = new_storage(STOR_VALUE);
1139 val->flags = STOR_WANTS_FREE;
1140 emit_move(val, REG_EDX, NULL, "begin EXPR_DIVIDE");
1143 is_signed = type_is_signed(expr->ctype);
1145 switch (expr->op) {
1146 case '+':
1147 opname = "add";
1148 break;
1149 case '-':
1150 opname = "sub";
1151 break;
1152 case '&':
1153 opname = "and";
1154 break;
1155 case '|':
1156 opname = "or";
1157 break;
1158 case '^':
1159 opname = "xor";
1160 break;
1161 case SPECIAL_LEFTSHIFT:
1162 opname = "shl";
1163 break;
1164 case SPECIAL_RIGHTSHIFT:
1165 if (is_signed)
1166 opname = "sar";
1167 else
1168 opname = "shr";
1169 break;
1170 case '*':
1171 if (is_signed)
1172 opname = "imul";
1173 else
1174 opname = "mul";
1175 break;
1176 case '/':
1177 case '%':
1178 if (is_signed)
1179 opname = "idiv";
1180 else
1181 opname = "div";
1182 break;
1183 default:
1184 assert(0);
1185 break;
1188 switch (expr->ctype->bit_size) {
1189 case 8:
1190 suffix = "b";
1191 result_reg = accum_reg = REG_AL;
1192 if (expr->op == '%')
1193 result_reg = REG_DL;
1194 break;
1195 case 16:
1196 suffix = "w";
1197 result_reg = accum_reg = REG_AX;
1198 if (expr->op == '%')
1199 result_reg = REG_DX;
1200 break;
1201 case 32:
1202 suffix = "l";
1203 result_reg = accum_reg = REG_EAX;
1204 if (expr->op == '%')
1205 result_reg = REG_EDX;
1206 break;
1207 case 64:
1208 suffix = "q"; /* FIXME */
1209 result_reg = accum_reg = REG_EAX; /* FIXME */
1210 if (expr->op == '%')
1211 result_reg = REG_EDX;
1212 break;
1213 default:
1214 assert(0);
1215 break;
1218 sprintf(movstr, "mov%s", suffix);
1219 sprintf(opstr, "%s%s", opname, suffix);
1221 /* load op2 into EAX */
1222 insn(movstr, right, accum_reg,
1223 doing_divide ? NULL : "EXPR_BINOP/COMMA/LOGICAL");
1225 /* perform binop */
1226 insn(opstr, left, accum_reg, NULL);
1228 /* store result (EAX or EDX) in new pseudo / stack slot */
1229 new = stack_alloc(4);
1230 insn(movstr, result_reg, new,
1231 doing_divide ? "end EXPR_DIVIDE" : "end EXPR_BINOP");
1233 return new;
1236 static void emit_if_conditional(struct statement *stmt)
1238 struct storage *val, *target_val;
1239 int target;
1240 struct expression *cond = stmt->if_conditional;
1242 /* This is only valid if nobody can jump into the "dead" statement */
1243 #if 0
1244 if (cond->type == EXPR_VALUE) {
1245 struct statement *s = stmt->if_true;
1246 if (!cond->value)
1247 s = stmt->if_false;
1248 x86_statement(s);
1249 break;
1251 #endif
1252 val = x86_expression(cond);
1254 /* load 'if' test result into EAX */
1255 insn("movl", val, REG_EAX, "begin if conditional");
1257 /* compare 'if' test result */
1258 insn("test", REG_EAX, REG_EAX, NULL);
1260 /* create end-of-if label / if-failed labelto jump to,
1261 * and jump to it if the expression returned zero.
1263 target = new_label();
1264 target_val = new_storage(STOR_LABEL);
1265 target_val->label = target;
1266 target_val->flags = STOR_WANTS_FREE;
1267 insn("jz", target_val, NULL, NULL);
1269 x86_statement(stmt->if_true);
1270 if (stmt->if_false) {
1271 struct storage *last_val;
1272 int last;
1274 /* finished generating code for if-true statement.
1275 * add a jump-to-end jump to avoid falling through
1276 * to the if-false statement code.
1278 last = new_label();
1279 last_val = new_storage(STOR_LABEL);
1280 last_val->label = last;
1281 last_val->flags = STOR_WANTS_FREE;
1282 insn("jmp", last_val, NULL, NULL);
1284 /* if we have both if-true and if-false statements,
1285 * the failed-conditional case will fall through to here
1287 emit_label(target, NULL);
1289 target = last;
1290 x86_statement(stmt->if_false);
1293 emit_label(target, "end if");
1296 static struct storage *emit_inc_dec(struct expression *expr, int postop)
1298 struct storage *addr = x86_address_gen(expr->unop);
1299 struct storage *retval;
1300 char opname[16];
1302 strcpy(opname, opbits(expr->op == SPECIAL_INCREMENT ? "inc" : "dec",
1303 expr->ctype->bit_size));
1305 if (postop) {
1306 struct storage *new = stack_alloc(4);
1308 emit_copy(new, addr, expr->unop->ctype);
1310 retval = new;
1311 } else
1312 retval = addr;
1314 insn(opname, addr, NULL, NULL);
1316 return retval;
1319 static struct storage *emit_postop(struct expression *expr)
1321 return emit_inc_dec(expr, 1);
1324 static struct storage *emit_return_stmt(struct statement *stmt)
1326 struct function *f = current_func;
1327 struct expression *expr = stmt->ret_value;
1328 struct storage *val = NULL, *jmplbl;
1330 if (expr && expr->ctype) {
1331 val = x86_expression(expr);
1332 assert(val != NULL);
1333 emit_move(val, REG_EAX, expr->ctype, "return");
1336 jmplbl = new_storage(STOR_LABEL);
1337 jmplbl->flags |= STOR_WANTS_FREE;
1338 jmplbl->label = f->ret_target;
1339 insn("jmp", jmplbl, NULL, NULL);
1341 return val;
1344 static struct storage *emit_conditional_expr(struct expression *expr)
1346 struct storage *cond = x86_expression(expr->conditional);
1347 struct storage *true = x86_expression(expr->cond_true);
1348 struct storage *false = x86_expression(expr->cond_false);
1349 struct storage *new = stack_alloc(4);
1351 if (!true)
1352 true = cond;
1354 emit_move(cond, REG_EAX, expr->conditional->ctype,
1355 "begin EXPR_CONDITIONAL");
1356 emit_move(true, REG_ECX, expr->cond_true->ctype, NULL);
1357 emit_move(false, REG_EDX, expr->cond_false->ctype, NULL);
1359 /* test EAX (for zero/non-zero) */
1360 insn("test", REG_EAX, REG_EAX, NULL);
1362 /* if false, move EDX to ECX */
1363 insn("cmovz", REG_EDX, REG_ECX, NULL);
1365 /* finally, store the result (ECX) in a new pseudo / stack slot */
1366 new = stack_alloc(4);
1367 emit_move(REG_ECX, new, expr->ctype, "end EXPR_CONDITIONAL");
1368 /* FIXME: we lose type knowledge of expression result at this point */
1370 return new;
1373 static struct storage *emit_symbol_expr_init(struct symbol *sym)
1375 struct expression *expr = sym->initializer;
1376 struct symbol_private *priv = sym->aux;
1378 if (priv == NULL) {
1379 priv = calloc(1, sizeof(*priv));
1380 sym->aux = priv;
1382 if (expr == NULL) {
1383 struct storage *new = stack_alloc(4);
1384 fprintf(stderr, "FIXME! no value for symbol. creating pseudo %d (stack offset %d)\n",
1385 new->pseudo, new->pseudo * 4);
1386 priv->addr = new;
1387 } else {
1388 priv->addr = x86_expression(expr);
1392 return priv->addr;
1395 static struct storage *emit_string_expr(struct expression *expr)
1397 struct function *f = current_func;
1398 int label = new_label();
1399 struct storage *new;
1401 push_cstring(f, expr->string, label);
1403 new = new_storage(STOR_LABEL);
1404 new->label = label;
1405 new->flags = STOR_LABEL_VAL | STOR_WANTS_FREE;
1406 return new;
1409 static struct storage *emit_cast_expr(struct expression *expr)
1411 struct symbol *old_type, *new_type;
1412 struct storage *op = x86_expression(expr->cast_expression);
1413 int oldbits, newbits;
1414 struct storage *new;
1416 old_type = expr->cast_expression->ctype;
1417 new_type = expr->cast_type;
1419 oldbits = old_type->bit_size;
1420 newbits = new_type->bit_size;
1421 if (oldbits >= newbits)
1422 return op;
1424 emit_move(op, REG_EAX, old_type, "begin cast ..");
1426 new = stack_alloc(4);
1427 emit_move(REG_EAX, new, new_type, ".... end cast");
1429 return new;
1432 static struct storage *emit_regular_preop(struct expression *expr)
1434 struct storage *target = x86_expression(expr->unop);
1435 struct storage *val, *new = stack_alloc(4);
1436 const char *opname = NULL;
1438 switch (expr->op) {
1439 case '!':
1440 val = new_storage(STOR_VALUE);
1441 val->flags = STOR_WANTS_FREE;
1442 emit_move(val, REG_EDX, NULL, NULL);
1443 emit_move(target, REG_EAX, expr->unop->ctype, NULL);
1444 insn("test", REG_EAX, REG_EAX, NULL);
1445 insn("setz", REG_DL, NULL, NULL);
1446 emit_move(REG_EDX, new, expr->unop->ctype, NULL);
1448 break;
1449 case '~':
1450 opname = "not";
1451 case '-':
1452 if (!opname)
1453 opname = "neg";
1454 emit_move(target, REG_EAX, expr->unop->ctype, NULL);
1455 insn(opname, REG_EAX, NULL, NULL);
1456 emit_move(REG_EAX, new, expr->unop->ctype, NULL);
1457 break;
1458 default:
1459 assert(0);
1460 break;
1463 return new;
1466 static void emit_case_statement(struct statement *stmt)
1468 emit_labelsym(stmt->case_label, NULL);
1469 x86_statement(stmt->case_statement);
1472 static void emit_switch_statement(struct statement *stmt)
1474 struct storage *val = x86_expression(stmt->switch_expression);
1475 struct symbol *sym, *default_sym = NULL;
1476 struct storage *labelsym, *label;
1477 int switch_end = 0;
1479 emit_move(val, REG_EAX, stmt->switch_expression->ctype, "begin case");
1482 * This is where a _real_ back-end would go through the
1483 * cases to decide whether to use a lookup table or a
1484 * series of comparisons etc
1486 FOR_EACH_PTR(stmt->switch_case->symbol_list, sym) {
1487 struct statement *case_stmt = sym->stmt;
1488 struct expression *expr = case_stmt->case_expression;
1489 struct expression *to = case_stmt->case_to;
1491 /* default: */
1492 if (!expr)
1493 default_sym = sym;
1495 /* case NNN: */
1496 else {
1497 struct storage *case_val = new_val(expr->value);
1499 assert (expr->type == EXPR_VALUE);
1501 insn("cmpl", case_val, REG_EAX, NULL);
1503 if (!to) {
1504 labelsym = new_labelsym(sym);
1505 insn("je", labelsym, NULL, NULL);
1506 } else {
1507 int next_test;
1509 label = new_storage(STOR_LABEL);
1510 label->flags |= STOR_WANTS_FREE;
1511 label->label = next_test = new_label();
1513 /* FIXME: signed/unsigned */
1514 insn("jl", label, NULL, NULL);
1516 case_val = new_val(to->value);
1517 insn("cmpl", case_val, REG_EAX, NULL);
1519 /* TODO: implement and use refcounting... */
1520 label = new_storage(STOR_LABEL);
1521 label->flags |= STOR_WANTS_FREE;
1522 label->label = next_test;
1524 /* FIXME: signed/unsigned */
1525 insn("jg", label, NULL, NULL);
1527 labelsym = new_labelsym(sym);
1528 insn("jmp", labelsym, NULL, NULL);
1530 emit_label(next_test, NULL);
1533 } END_FOR_EACH_PTR;
1535 if (default_sym) {
1536 labelsym = new_labelsym(default_sym);
1537 insn("jmp", labelsym, NULL, "default");
1538 } else {
1539 label = new_storage(STOR_LABEL);
1540 label->flags |= STOR_WANTS_FREE;
1541 label->label = switch_end = new_label();
1542 insn("jmp", label, NULL, "goto end of switch");
1545 x86_statement(stmt->switch_statement);
1547 if (stmt->switch_break->used)
1548 emit_labelsym(stmt->switch_break, NULL);
1550 if (switch_end)
1551 emit_label(switch_end, NULL);
1554 static void x86_struct_member(struct symbol *sym, void *data, int flags)
1556 if (flags & ITERATE_FIRST)
1557 printf(" {\n\t");
1558 printf("%s:%d:%ld at offset %ld", show_ident(sym->ident), sym->bit_size, sym->ctype.alignment, sym->offset);
1559 if (sym->fieldwidth)
1560 printf("[%d..%d]", sym->bit_offset, sym->bit_offset+sym->fieldwidth-1);
1561 if (flags & ITERATE_LAST)
1562 printf("\n} ");
1563 else
1564 printf(", ");
1567 static void x86_symbol(struct symbol *sym)
1569 struct symbol *type;
1571 if (!sym)
1572 return;
1574 type = sym->ctype.base_type;
1575 if (!type)
1576 return;
1579 * Show actual implementation information
1581 switch (type->type) {
1583 case SYM_ARRAY:
1584 if (sym->initializer)
1585 emit_array(sym);
1586 else
1587 emit_array_noinit(sym);
1588 break;
1590 case SYM_BASETYPE:
1591 if (sym->initializer) {
1592 emit_object_pre(show_ident(sym->ident),
1593 sym->ctype.modifiers,
1594 sym->ctype.alignment,
1595 sym->bit_size / 8);
1596 emit_scalar(sym->initializer, sym->bit_size);
1597 stor_sym_init(sym);
1598 } else
1599 emit_scalar_noinit(sym);
1600 break;
1602 case SYM_STRUCT:
1603 symbol_iterate(type->symbol_list, x86_struct_member, NULL);
1604 break;
1606 case SYM_UNION:
1607 symbol_iterate(type->symbol_list, x86_struct_member, NULL);
1608 break;
1610 case SYM_FN: {
1611 struct statement *stmt = type->stmt;
1612 if (stmt) {
1613 emit_func_pre(sym);
1614 x86_statement(stmt);
1615 emit_func_post(sym);
1617 break;
1620 default:
1621 break;
1624 if (sym->initializer && (type->type != SYM_BASETYPE) &&
1625 (type->type != SYM_ARRAY)) {
1626 printf(" = \n");
1627 x86_expression(sym->initializer);
1631 static void x86_symbol_init(struct symbol *sym);
1633 static void x86_symbol_decl(struct symbol_list *syms)
1635 struct symbol *sym;
1636 FOR_EACH_PTR(syms, sym) {
1637 x86_symbol_init(sym);
1638 } END_FOR_EACH_PTR;
1641 static void loopstk_push(int cont_lbl, int loop_bottom_lbl)
1643 struct function *f = current_func;
1644 struct loop_stack *ls;
1646 ls = malloc(sizeof(*ls));
1647 ls->continue_lbl = cont_lbl;
1648 ls->loop_bottom_lbl = loop_bottom_lbl;
1649 ls->next = f->loop_stack;
1650 f->loop_stack = ls;
1653 static void loopstk_pop(void)
1655 struct function *f = current_func;
1656 struct loop_stack *ls;
1658 assert(f->loop_stack != NULL);
1659 ls = f->loop_stack;
1660 f->loop_stack = f->loop_stack->next;
1661 free(ls);
1664 static int loopstk_break(void)
1666 return current_func->loop_stack->loop_bottom_lbl;
1669 static int loopstk_continue(void)
1671 return current_func->loop_stack->continue_lbl;
1674 static void emit_loop(struct statement *stmt)
1676 struct statement *pre_statement = stmt->iterator_pre_statement;
1677 struct expression *pre_condition = stmt->iterator_pre_condition;
1678 struct statement *statement = stmt->iterator_statement;
1679 struct statement *post_statement = stmt->iterator_post_statement;
1680 struct expression *post_condition = stmt->iterator_post_condition;
1681 int loop_top = 0, loop_bottom, loop_continue;
1682 int have_bottom = 0;
1683 struct storage *val;
1685 loop_bottom = new_label();
1686 loop_continue = new_label();
1687 loopstk_push(loop_continue, loop_bottom);
1689 x86_symbol_decl(stmt->iterator_syms);
1690 x86_statement(pre_statement);
1691 if (pre_condition) {
1692 if (pre_condition->type == EXPR_VALUE) {
1693 if (!pre_condition->value) {
1694 struct storage *lbv;
1695 lbv = new_storage(STOR_LABEL);
1696 lbv->label = loop_bottom;
1697 lbv->flags = STOR_WANTS_FREE;
1698 insn("jmp", lbv, NULL, "go to loop bottom");
1699 have_bottom = 1;
1701 } else {
1702 struct storage *lbv = new_storage(STOR_LABEL);
1703 lbv->label = loop_bottom;
1704 lbv->flags = STOR_WANTS_FREE;
1705 have_bottom = 1;
1707 val = x86_expression(pre_condition);
1709 emit_move(val, REG_EAX, NULL, "loop pre condition");
1710 insn("test", REG_EAX, REG_EAX, NULL);
1711 insn("jz", lbv, NULL, NULL);
1714 if (!post_condition || post_condition->type != EXPR_VALUE || post_condition->value) {
1715 loop_top = new_label();
1716 emit_label(loop_top, "loop top");
1718 x86_statement(statement);
1719 if (stmt->iterator_continue->used)
1720 emit_label(loop_continue, "'continue' iterator");
1721 x86_statement(post_statement);
1722 if (!post_condition) {
1723 struct storage *lbv = new_storage(STOR_LABEL);
1724 lbv->label = loop_top;
1725 lbv->flags = STOR_WANTS_FREE;
1726 insn("jmp", lbv, NULL, "go to loop top");
1727 } else if (post_condition->type == EXPR_VALUE) {
1728 if (post_condition->value) {
1729 struct storage *lbv = new_storage(STOR_LABEL);
1730 lbv->label = loop_top;
1731 lbv->flags = STOR_WANTS_FREE;
1732 insn("jmp", lbv, NULL, "go to loop top");
1734 } else {
1735 struct storage *lbv = new_storage(STOR_LABEL);
1736 lbv->label = loop_top;
1737 lbv->flags = STOR_WANTS_FREE;
1739 val = x86_expression(post_condition);
1741 emit_move(val, REG_EAX, NULL, "loop post condition");
1742 insn("test", REG_EAX, REG_EAX, NULL);
1743 insn("jnz", lbv, NULL, NULL);
1745 if (have_bottom || stmt->iterator_break->used)
1746 emit_label(loop_bottom, "loop bottom");
1748 loopstk_pop();
1752 * Print out a statement
1754 static struct storage *x86_statement(struct statement *stmt)
1756 if (!stmt)
1757 return NULL;
1758 switch (stmt->type) {
1759 case STMT_RETURN:
1760 return emit_return_stmt(stmt);
1761 case STMT_COMPOUND: {
1762 struct statement *s;
1763 struct storage *last = NULL;
1765 x86_symbol_decl(stmt->syms);
1766 FOR_EACH_PTR(stmt->stmts, s) {
1767 last = x86_statement(s);
1768 } END_FOR_EACH_PTR;
1770 return last;
1773 case STMT_EXPRESSION:
1774 return x86_expression(stmt->expression);
1775 case STMT_IF:
1776 emit_if_conditional(stmt);
1777 return NULL;
1779 case STMT_CASE:
1780 emit_case_statement(stmt);
1781 break;
1782 case STMT_SWITCH:
1783 emit_switch_statement(stmt);
1784 break;
1786 case STMT_ITERATOR:
1787 emit_loop(stmt);
1788 break;
1790 case STMT_NONE:
1791 break;
1793 case STMT_LABEL:
1794 printf(".L%p:\n", stmt->label_identifier);
1795 x86_statement(stmt->label_statement);
1796 break;
1798 case STMT_GOTO:
1799 if (stmt->goto_expression) {
1800 struct storage *val = x86_expression(stmt->goto_expression);
1801 printf("\tgoto *v%d\n", val->pseudo);
1802 } else if (!strcmp("break", show_ident(stmt->goto_label->ident))) {
1803 struct storage *lbv = new_storage(STOR_LABEL);
1804 lbv->label = loopstk_break();
1805 lbv->flags = STOR_WANTS_FREE;
1806 insn("jmp", lbv, NULL, "'break'; go to loop bottom");
1807 } else if (!strcmp("continue", show_ident(stmt->goto_label->ident))) {
1808 struct storage *lbv = new_storage(STOR_LABEL);
1809 lbv->label = loopstk_continue();
1810 lbv->flags = STOR_WANTS_FREE;
1811 insn("jmp", lbv, NULL, "'continue'; go to loop top");
1812 } else {
1813 struct storage *labelsym = new_labelsym(stmt->goto_label);
1814 insn("jmp", labelsym, NULL, NULL);
1816 break;
1817 case STMT_ASM:
1818 printf("\tasm( .... )\n");
1819 break;
1821 return NULL;
1824 static struct storage *x86_call_expression(struct expression *expr)
1826 struct function *f = current_func;
1827 struct symbol *direct;
1828 struct expression *arg, *fn;
1829 struct storage *retval, *fncall;
1830 int framesize;
1831 char s[64];
1833 if (!expr->ctype) {
1834 warn(expr->pos, "\tcall with no type!");
1835 return NULL;
1838 framesize = 0;
1839 FOR_EACH_PTR_REVERSE(expr->args, arg) {
1840 struct storage *new = x86_expression(arg);
1841 int size = arg->ctype->bit_size;
1843 /* FIXME: pay attention to 'size' */
1844 insn("pushl", new, NULL,
1845 !framesize ? "begin function call" : NULL);
1847 framesize += size >> 3;
1848 } END_FOR_EACH_PTR_REVERSE;
1850 fn = expr->fn;
1852 /* Remove dereference, if any */
1853 direct = NULL;
1854 if (fn->type == EXPR_PREOP) {
1855 if (fn->unop->type == EXPR_SYMBOL) {
1856 struct symbol *sym = fn->unop->symbol;
1857 if (sym->ctype.base_type->type == SYM_FN)
1858 direct = sym;
1861 if (direct) {
1862 struct storage *direct_stor = new_storage(STOR_SYM);
1863 direct_stor->flags |= STOR_WANTS_FREE;
1864 direct_stor->sym = direct;
1865 insn("call", direct_stor, NULL, NULL);
1866 } else {
1867 fncall = x86_expression(fn);
1868 emit_move(fncall, REG_EAX, fn->ctype, NULL);
1870 strcpy(s, "\tcall\t*%eax\n");
1871 push_text_atom(f, s);
1874 /* FIXME: pay attention to BITS_IN_POINTER */
1875 if (framesize) {
1876 struct storage *val = new_storage(STOR_VALUE);
1877 val->value = (long long) framesize;
1878 val->flags = STOR_WANTS_FREE;
1879 insn("addl", val, REG_ESP, NULL);
1882 retval = stack_alloc(4);
1883 emit_move(REG_EAX, retval, NULL, "end function call");
1885 return retval;
1888 static struct storage *x86_address_gen(struct expression *expr)
1890 struct function *f = current_func;
1891 struct storage *addr;
1892 struct storage *new;
1893 char s[32];
1895 if ((expr->type != EXPR_PREOP) || (expr->op != '*'))
1896 return x86_expression(expr->address);
1898 addr = x86_expression(expr->unop);
1899 if (expr->unop->type == EXPR_SYMBOL)
1900 return addr;
1902 emit_move(addr, REG_EAX, NULL, "begin deref ..");
1904 /* FIXME: operand size */
1905 strcpy(s, "\tmovl\t(%eax), %ecx\n");
1906 push_text_atom(f, s);
1908 new = stack_alloc(4);
1909 emit_move(REG_ECX, new, NULL, ".... end deref");
1911 return new;
1914 static struct storage *x86_assignment(struct expression *expr)
1916 struct expression *target = expr->left;
1917 struct storage *val, *addr;
1919 if (!expr->ctype)
1920 return NULL;
1922 val = x86_expression(expr->right);
1923 addr = x86_address_gen(target);
1925 switch (val->type) {
1926 /* copy, where both operands are memory */
1927 case STOR_PSEUDO:
1928 case STOR_ARG:
1929 emit_copy(addr, val, expr->ctype);
1930 break;
1932 /* copy, one or zero operands are memory */
1933 case STOR_REG:
1934 case STOR_SYM:
1935 case STOR_VALUE:
1936 case STOR_LABEL:
1937 emit_move(val, addr, expr->left->ctype, NULL);
1938 break;
1940 case STOR_LABELSYM:
1941 assert(0);
1942 break;
1944 return val;
1947 static int x86_initialization(struct symbol *sym, struct expression *expr)
1949 struct storage *val, *addr;
1950 int bits;
1952 if (!expr->ctype)
1953 return 0;
1955 bits = expr->ctype->bit_size;
1956 val = x86_expression(expr);
1957 addr = x86_symbol_expr(sym);
1958 // FIXME! The "target" expression is for bitfield store information.
1959 // Leave it NULL, which works fine.
1960 emit_store(NULL, addr, val, bits);
1961 return 0;
1964 static struct storage *x86_access(struct expression *expr)
1966 return x86_address_gen(expr);
1969 static struct storage *x86_preop(struct expression *expr)
1972 * '*' is an lvalue access, and is fundamentally different
1973 * from an arithmetic operation. Maybe it should have an
1974 * expression type of its own..
1976 if (expr->op == '*')
1977 return x86_access(expr);
1978 if (expr->op == SPECIAL_INCREMENT || expr->op == SPECIAL_DECREMENT)
1979 return emit_inc_dec(expr, 0);
1980 return emit_regular_preop(expr);
1983 static struct storage *x86_symbol_expr(struct symbol *sym)
1985 struct storage *new = stack_alloc(4);
1987 if (sym->ctype.modifiers & (MOD_TOPLEVEL | MOD_EXTERN | MOD_STATIC)) {
1988 printf("\tmovi.%d\t\tv%d,$%s\n", bits_in_pointer, new->pseudo, show_ident(sym->ident));
1989 return new;
1991 if (sym->ctype.modifiers & MOD_ADDRESSABLE) {
1992 printf("\taddi.%d\t\tv%d,vFP,$%lld\n", bits_in_pointer, new->pseudo, sym->value);
1993 return new;
1995 printf("\taddi.%d\t\tv%d,vFP,$offsetof(%s:%p)\n", bits_in_pointer, new->pseudo, show_ident(sym->ident), sym);
1996 return new;
1999 static void x86_symbol_init(struct symbol *sym)
2001 struct symbol_private *priv = sym->aux;
2002 struct expression *expr = sym->initializer;
2003 struct storage *new;
2005 if (expr)
2006 new = x86_expression(expr);
2007 else
2008 new = stack_alloc(sym->bit_size / 8);
2010 if (!priv) {
2011 priv = calloc(1, sizeof(*priv));
2012 sym->aux = priv;
2013 /* FIXME: leak! we don't free... */
2014 /* (well, we don't free symbols either) */
2017 priv->addr = new;
2020 static int type_is_signed(struct symbol *sym)
2022 if (sym->type == SYM_NODE)
2023 sym = sym->ctype.base_type;
2024 if (sym->type == SYM_PTR)
2025 return 0;
2026 return !(sym->ctype.modifiers & MOD_UNSIGNED);
2029 static struct storage *x86_bitfield_expr(struct expression *expr)
2031 return x86_access(expr);
2034 static struct storage *x86_label_expr(struct expression *expr)
2036 struct storage *new = stack_alloc(4);
2037 printf("\tmovi.%d\t\tv%d,.L%p\n", bits_in_pointer, new->pseudo, expr->label_symbol);
2038 return new;
2041 static struct storage *x86_statement_expr(struct expression *expr)
2043 return x86_statement(expr->statement);
2046 static int x86_position_expr(struct expression *expr, struct symbol *base)
2048 struct storage *new = x86_expression(expr->init_expr);
2049 struct symbol *ctype = expr->init_sym;
2051 printf("\tinsert v%d at [%d:%d] of %s\n", new->pseudo,
2052 expr->init_offset, ctype->bit_offset,
2053 show_ident(base->ident));
2054 return 0;
2057 static void x86_initializer_expr(struct expression *expr, struct symbol *ctype)
2059 struct expression *entry;
2061 FOR_EACH_PTR(expr->expr_list, entry) {
2062 // Nested initializers have their positions already
2063 // recursively calculated - just output them too
2064 if (entry->type == EXPR_INITIALIZER) {
2065 x86_initializer_expr(entry, ctype);
2066 continue;
2069 // Ignore initializer indexes and identifiers - the
2070 // evaluator has taken them into account
2071 if (entry->type == EXPR_IDENTIFIER || entry->type == EXPR_INDEX)
2072 continue;
2073 if (entry->type == EXPR_POS) {
2074 x86_position_expr(entry, ctype);
2075 continue;
2077 x86_initialization(ctype, entry);
2078 } END_FOR_EACH_PTR;
2082 * Print out an expression. Return the pseudo that contains the
2083 * variable.
2085 static struct storage *x86_expression(struct expression *expr)
2087 if (!expr)
2088 return NULL;
2090 if (!expr->ctype) {
2091 struct position *pos = &expr->pos;
2092 printf("\tno type at %s:%d:%d\n",
2093 input_streams[pos->stream].name,
2094 pos->line, pos->pos);
2095 return NULL;
2098 switch (expr->type) {
2099 case EXPR_CALL:
2100 return x86_call_expression(expr);
2102 case EXPR_ASSIGNMENT:
2103 return x86_assignment(expr);
2105 case EXPR_COMPARE:
2106 return emit_compare(expr);
2107 case EXPR_BINOP:
2108 case EXPR_COMMA:
2109 case EXPR_LOGICAL:
2110 return emit_binop(expr);
2111 case EXPR_PREOP:
2112 return x86_preop(expr);
2113 case EXPR_POSTOP:
2114 return emit_postop(expr);
2115 case EXPR_SYMBOL:
2116 return emit_symbol_expr_init(expr->symbol);
2117 case EXPR_DEREF:
2118 case EXPR_SIZEOF:
2119 case EXPR_ALIGNOF:
2120 warn(expr->pos, "invalid expression after evaluation");
2121 return NULL;
2122 case EXPR_CAST:
2123 return emit_cast_expr(expr);
2124 case EXPR_VALUE:
2125 return emit_value(expr);
2126 case EXPR_STRING:
2127 return emit_string_expr(expr);
2128 case EXPR_BITFIELD:
2129 return x86_bitfield_expr(expr);
2130 case EXPR_INITIALIZER:
2131 x86_initializer_expr(expr, expr->ctype);
2132 return NULL;
2133 case EXPR_CONDITIONAL:
2134 return emit_conditional_expr(expr);
2135 case EXPR_STATEMENT:
2136 return x86_statement_expr(expr);
2137 case EXPR_LABEL:
2138 return x86_label_expr(expr);
2140 // None of these should exist as direct expressions: they are only
2141 // valid as sub-expressions of initializers.
2142 case EXPR_POS:
2143 warn(expr->pos, "unable to show plain initializer position expression");
2144 return NULL;
2145 case EXPR_IDENTIFIER:
2146 warn(expr->pos, "unable to show identifier expression");
2147 return NULL;
2148 case EXPR_INDEX:
2149 warn(expr->pos, "unable to show index expression");
2150 return NULL;
2151 case EXPR_TYPE:
2152 warn(expr->pos, "unable to show type expression");
2153 return NULL;
2155 return NULL;