[be] rename pseudo_nr to stack_size
[smatch.git] / compile-i386.c
blob133ddc33b9941db0dfe7a447cd2af83cb5519885
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 * loops
15 * complex initializers
16 * bitfields
17 * global struct/union variables
18 * addressing structures, and members of structures (as opposed to
19 * scalars) on the stack. Requires smarter stack frame allocation.
20 * labels / goto
21 * any function argument that isn't 32 bits (or promoted to such)
22 * inline asm
23 * floating point
26 #include <stdarg.h>
27 #include <stdlib.h>
28 #include <stdio.h>
29 #include <string.h>
30 #include <ctype.h>
31 #include <unistd.h>
32 #include <fcntl.h>
33 #include <assert.h>
35 #include "lib.h"
36 #include "token.h"
37 #include "parse.h"
38 #include "symbol.h"
39 #include "scope.h"
40 #include "expression.h"
41 #include "target.h"
44 struct textbuf;
45 struct textbuf {
46 unsigned int len; /* does NOT include terminating null */
47 char *text;
48 struct textbuf *next;
49 struct textbuf *prev;
52 struct function {
53 int stack_size;
54 struct ptr_list *pseudo_list;
55 struct ptr_list *atom_list;
56 struct ptr_list *str_list;
57 struct symbol **argv;
58 unsigned int argc;
59 int ret_target;
62 enum storage_type {
63 STOR_PSEUDO, /* variable stored on the stack */
64 STOR_ARG, /* function argument */
65 STOR_SYM, /* a symbol we can directly ref in the asm */
66 STOR_REG, /* scratch register */
67 STOR_VALUE, /* integer constant */
68 STOR_LABEL, /* label / jump target */
69 STOR_LABELSYM, /* label generated from symbol's pointer value */
72 struct reg_info {
73 const char *name;
76 struct storage {
77 enum storage_type type;
78 unsigned long flags;
80 /* STOR_REG */
81 struct reg_info *reg;
83 union {
84 /* STOR_PSEUDO */
85 struct {
86 int pseudo;
88 /* STOR_ARG */
89 struct {
90 int idx;
92 /* STOR_SYM */
93 struct {
94 struct symbol *sym;
96 /* STOR_VALUE */
97 struct {
98 long long value;
100 /* STOR_LABEL */
101 struct {
102 int label;
104 /* STOR_LABELSYM */
105 struct {
106 struct symbol *labelsym;
111 enum {
112 STOR_LABEL_VAL = (1 << 0),
113 STOR_WANTS_FREE = (1 << 1),
116 struct symbol_private {
117 struct storage *addr;
120 enum atom_type {
121 ATOM_TEXT,
122 ATOM_INSN,
123 ATOM_CSTR,
126 struct atom {
127 enum atom_type type;
128 union {
129 /* stuff for text */
130 struct {
131 char *text;
132 unsigned int text_len; /* w/o terminating null */
135 /* stuff for insns */
136 struct {
137 char insn[32];
138 char comment[40];
139 struct storage *op1;
140 struct storage *op2;
143 /* stuff for C strings */
144 struct {
145 struct string *string;
146 int label;
152 struct function *current_func = NULL;
153 struct textbuf *unit_post_text = NULL;
154 static const char *current_section;
156 static struct reg_info reg_info_table[] = {
157 { "%eax" },
158 { "%ecx" },
159 { "%edx" },
160 { "%esp" },
161 { "%dl" },
164 static struct storage hardreg_storage_table[] = {
165 { /* eax */
166 .type = STOR_REG,
167 .reg = &reg_info_table[0],
170 { /* ecx */
171 .type = STOR_REG,
172 .reg = &reg_info_table[1],
175 { /* edx */
176 .type = STOR_REG,
177 .reg = &reg_info_table[2],
180 { /* esp */
181 .type = STOR_REG,
182 .reg = &reg_info_table[3],
185 { /* dl */
186 .type = STOR_REG,
187 .reg = &reg_info_table[4],
191 #define REG_EAX (&hardreg_storage_table[0])
192 #define REG_ECX (&hardreg_storage_table[1])
193 #define REG_EDX (&hardreg_storage_table[2])
194 #define REG_ESP (&hardreg_storage_table[3])
195 #define REG_DL (&hardreg_storage_table[4])
198 static void emit_move(struct storage *src, struct storage *dest,
199 struct symbol *ctype, const char *comment);
200 static int type_is_signed(struct symbol *sym);
201 static struct storage *x86_address_gen(struct expression *expr);
202 static struct storage *x86_symbol_expr(struct symbol *sym);
203 static void x86_symbol(struct symbol *sym);
204 static struct storage *x86_statement(struct statement *stmt);
205 static struct storage *x86_expression(struct expression *expr);
208 static inline unsigned int pseudo_offset(struct storage *s)
210 if (s->type != STOR_PSEUDO)
211 return 123456; /* intentionally bogus value */
213 return ((s->pseudo - 1) * 4);
216 static inline unsigned int arg_offset(struct storage *s)
218 if (s->type != STOR_ARG)
219 return 123456; /* intentionally bogus value */
221 /* FIXME: this is wrong wrong wrong */
222 return ((current_func->stack_size / 4) + 1 + s->idx) * 4;
225 static const char *pretty_offset(int ofs)
227 static char esp_buf[64];
229 if (ofs)
230 sprintf(esp_buf, "%d(%%esp)", ofs);
231 else
232 strcpy(esp_buf, "(%esp)");
234 return esp_buf;
237 static void stor_sym_init(struct symbol *sym)
239 struct storage *stor;
240 struct symbol_private *priv;
242 priv = calloc(1, sizeof(*priv) + sizeof(*stor));
243 if (!priv)
244 die("OOM in stor_sym_init");
246 stor = (struct storage *) (priv + 1);
248 priv->addr = stor;
249 stor->type = STOR_SYM;
250 stor->sym = sym;
253 static const char *stor_op_name(struct storage *s)
255 static char name[32];
257 switch (s->type) {
258 case STOR_PSEUDO:
259 strcpy(name, pretty_offset((int) pseudo_offset(s)));
260 break;
261 case STOR_ARG:
262 strcpy(name, pretty_offset((int) arg_offset(s)));
263 break;
264 case STOR_SYM:
265 strcpy(name, show_ident(s->sym->ident));
266 break;
267 case STOR_REG:
268 strcpy(name, s->reg->name);
269 break;
270 case STOR_VALUE:
271 sprintf(name, "$%Ld", s->value);
272 break;
273 case STOR_LABEL:
274 sprintf(name, "%s.L%d", s->flags & STOR_LABEL_VAL ? "$" : "",
275 s->label);
276 break;
277 case STOR_LABELSYM:
278 sprintf(name, "%s.LS%p", s->flags & STOR_LABEL_VAL ? "$" : "",
279 s->labelsym);
280 break;
283 return name;
286 static struct atom *new_atom(enum atom_type type)
288 struct atom *atom;
290 atom = calloc(1, sizeof(*atom)); /* TODO: chunked alloc */
291 if (!atom)
292 die("nuclear OOM");
294 atom->type = type;
296 return atom;
299 static inline void push_cstring(struct function *f, struct string *str,
300 int label)
302 struct atom *atom;
304 atom = new_atom(ATOM_CSTR);
305 atom->string = str;
306 atom->label = label;
308 add_ptr_list(&f->str_list, atom); /* note: _not_ atom_list */
311 static inline void push_atom(struct function *f, struct atom *atom)
313 add_ptr_list(&f->atom_list, atom);
316 static void push_text_atom(struct function *f, const char *text)
318 struct atom *atom = new_atom(ATOM_TEXT);
320 atom->text = strdup(text);
321 atom->text_len = strlen(text);
323 push_atom(f, atom);
326 static struct storage *new_storage(enum storage_type type)
328 struct storage *stor;
330 stor = calloc(1, sizeof(*stor));
331 if (!stor)
332 die("OOM in new_storage");
334 stor->type = type;
336 return stor;
339 static struct storage *new_pseudo(void)
341 struct function *f = current_func;
342 struct storage *stor;
344 assert(f != NULL);
346 stor = new_storage(STOR_PSEUDO);
347 stor->type = STOR_PSEUDO;
348 f->stack_size += 4;
349 stor->pseudo = f->stack_size / 4;
351 add_ptr_list(&f->pseudo_list, stor);
353 return stor;
356 static struct storage *new_labelsym(struct symbol *sym)
358 struct storage *stor;
360 stor = new_storage(STOR_LABELSYM);
362 if (stor) {
363 stor->flags |= STOR_WANTS_FREE;
364 stor->labelsym = sym;
367 return stor;
370 static struct storage *new_val(long long value)
372 struct storage *stor;
374 stor = new_storage(STOR_VALUE);
376 if (stor) {
377 stor->flags |= STOR_WANTS_FREE;
378 stor->value = value;
381 return stor;
384 static int new_label(void)
386 static int label = 0;
387 return ++label;
390 static void textbuf_push(struct textbuf **buf_p, const char *text)
392 struct textbuf *tmp, *list = *buf_p;
393 unsigned int text_len = strlen(text);
394 unsigned int alloc_len = text_len + 1 + sizeof(*list);
396 tmp = calloc(1, alloc_len);
397 if (!tmp)
398 die("OOM on textbuf alloc");
400 tmp->text = ((void *) tmp) + sizeof(*tmp);
401 memcpy(tmp->text, text, text_len + 1);
402 tmp->len = text_len;
404 /* add to end of list */
405 if (!list) {
406 list = tmp;
407 tmp->prev = tmp;
408 } else {
409 tmp->prev = list->prev;
410 tmp->prev->next = tmp;
411 list->prev = tmp;
413 tmp->next = list;
415 *buf_p = list;
418 static void textbuf_emit(struct textbuf **buf_p)
420 struct textbuf *tmp, *list = *buf_p;
422 while (list) {
423 tmp = list;
424 if (tmp->next == tmp)
425 list = NULL;
426 else {
427 tmp->prev->next = tmp->next;
428 tmp->next->prev = tmp->prev;
429 list = tmp->next;
432 fputs(tmp->text, stdout);
434 free(tmp);
437 *buf_p = list;
440 static void insn(const char *insn, struct storage *op1, struct storage *op2,
441 const char *comment_in)
443 struct function *f = current_func;
444 struct atom *atom = new_atom(ATOM_INSN);
446 assert(insn != NULL);
448 strcpy(atom->insn, insn);
449 if (comment_in && (*comment_in))
450 strncpy(atom->comment, comment_in,
451 sizeof(atom->comment) - 1);
453 atom->op1 = op1;
454 atom->op2 = op2;
456 push_atom(f, atom);
459 static void emit_label (int label, const char *comment)
461 struct function *f = current_func;
462 char s[64];
464 if (!comment)
465 sprintf(s, ".L%d:\n", label);
466 else
467 sprintf(s, ".L%d:\t\t\t\t\t# %s\n", label, comment);
469 push_text_atom(f, s);
472 static void emit_labelsym (struct symbol *sym, const char *comment)
474 struct function *f = current_func;
475 char s[64];
477 if (!comment)
478 sprintf(s, ".LS%p:\n", sym);
479 else
480 sprintf(s, ".LS%p:\t\t\t\t# %s\n", sym, comment);
482 push_text_atom(f, s);
485 static void emit_unit_pre(const char *basename)
487 printf("\t.file\t\"%s\"\n", basename);
490 static void emit_unit_post(void)
492 textbuf_emit(&unit_post_text);
493 printf("\t.ident\t\"sparse silly x86 backend (built %s)\"\n", __DATE__);
496 /* conditionally switch sections */
497 static void emit_section(const char *s)
499 if (s == current_section)
500 return;
501 if (current_section && (!strcmp(s, current_section)))
502 return;
504 printf("\t%s\n", s);
505 current_section = s;
508 static void emit_insn_atom(struct function *f, struct atom *atom)
510 char s[128];
511 char comment[64];
512 struct storage *op1 = atom->op1;
513 struct storage *op2 = atom->op2;
515 if (atom->comment[0])
516 sprintf(comment, "\t\t# %s", atom->comment);
517 else
518 comment[0] = 0;
520 if (atom->op2) {
521 char tmp[16];
522 strcpy(tmp, stor_op_name(op1));
523 sprintf(s, "\t%s\t%s, %s%s\n",
524 atom->insn, tmp, stor_op_name(op2), comment);
525 } else if (atom->op1)
526 sprintf(s, "\t%s\t%s%s%s\n",
527 atom->insn, stor_op_name(op1),
528 comment[0] ? "\t" : "", comment);
529 else
530 sprintf(s, "\t%s\t%s%s\n",
531 atom->insn,
532 comment[0] ? "\t\t" : "", comment);
534 write(STDOUT_FILENO, s, strlen(s));
537 static void emit_atom_list(struct function *f)
539 struct atom *atom;
541 FOR_EACH_PTR(f->atom_list, atom) {
542 switch (atom->type) {
543 case ATOM_TEXT: {
544 ssize_t rc = write(STDOUT_FILENO, atom->text,
545 atom->text_len);
546 (void) rc; /* FIXME */
547 break;
549 case ATOM_INSN:
550 emit_insn_atom(f, atom);
551 break;
552 case ATOM_CSTR:
553 assert(0);
554 break;
556 } END_FOR_EACH_PTR;
559 static void emit_string_list(struct function *f)
561 struct atom *atom;
563 emit_section(".section\t.rodata");
565 FOR_EACH_PTR(f->str_list, atom) {
566 /* FIXME: escape " in string */
567 printf(".L%d:\n", atom->label);
568 printf("\t.string\t%s\n", show_string(atom->string));
570 free(atom);
571 } END_FOR_EACH_PTR;
574 static void func_cleanup(struct function *f)
576 struct storage *stor;
577 struct atom *atom;
579 FOR_EACH_PTR(f->pseudo_list, stor) {
580 free(stor);
581 } END_FOR_EACH_PTR;
583 FOR_EACH_PTR(f->atom_list, atom) {
584 if ((atom->type == ATOM_TEXT) && (atom->text))
585 free(atom->text);
586 if (atom->op1 && (atom->op1->flags & STOR_WANTS_FREE))
587 free(atom->op1);
588 if (atom->op2 && (atom->op2->flags & STOR_WANTS_FREE))
589 free(atom->op2);
590 free(atom);
591 } END_FOR_EACH_PTR;
593 free_ptr_list(&f->pseudo_list);
594 free(f);
597 /* function prologue */
598 static void emit_func_pre(struct symbol *sym)
600 struct function *f;
601 struct symbol *arg;
602 unsigned int i, argc = 0, alloc_len;
603 unsigned char *mem;
604 struct symbol_private *privbase;
605 struct storage *storage_base;
606 struct symbol *base_type = sym->ctype.base_type;
608 FOR_EACH_PTR(base_type->arguments, arg) {
609 argc++;
610 } END_FOR_EACH_PTR;
612 alloc_len =
613 sizeof(*f) +
614 (argc * sizeof(struct symbol *)) +
615 (argc * sizeof(struct symbol_private)) +
616 (argc * sizeof(struct storage));
617 mem = calloc(1, alloc_len);
618 if (!mem)
619 die("OOM on func info");
621 f = (struct function *) mem;
622 mem += sizeof(*f);
623 f->argv = (struct symbol **) mem;
624 mem += (argc * sizeof(struct symbol *));
625 privbase = (struct symbol_private *) mem;
626 mem += (argc * sizeof(struct symbol_private));
627 storage_base = (struct storage *) mem;
629 f->argc = argc;
630 f->ret_target = new_label();
632 i = 0;
633 FOR_EACH_PTR(base_type->arguments, arg) {
634 f->argv[i] = arg;
635 arg->aux = &privbase[i];
636 storage_base[i].type = STOR_ARG;
637 storage_base[i].idx = i;
638 privbase[i].addr = &storage_base[i];
639 i++;
640 } END_FOR_EACH_PTR;
642 assert(current_func == NULL);
643 current_func = f;
646 /* function epilogue */
647 static void emit_func_post(struct symbol *sym)
649 const char *name = show_ident(sym->ident);
650 struct function *f = current_func;
651 int stack_size = f->stack_size;
653 if (f->str_list)
654 emit_string_list(f);
656 /* function prologue */
657 emit_section(".text");
658 if ((sym->ctype.modifiers & MOD_STATIC) == 0)
659 printf(".globl %s\n", name);
660 printf("\t.type\t%s, @function\n", name);
661 printf("%s:\n", name);
663 if (stack_size) {
664 char pseudo_const[16];
666 sprintf(pseudo_const, "$%d", stack_size);
667 printf("\tsubl\t%s, %%esp\n", pseudo_const);
670 /* function epilogue */
672 /* jump target for 'return' statements */
673 emit_label(f->ret_target, NULL);
675 if (stack_size) {
676 struct storage *val;
678 val = new_storage(STOR_VALUE);
679 val->value = (long long) (stack_size);
680 val->flags = STOR_WANTS_FREE;
682 insn("addl", val, REG_ESP, NULL);
685 insn("ret", NULL, NULL, NULL);
687 /* output everything to stdout */
688 fflush(stdout); /* paranoia; needed? */
689 emit_atom_list(f);
691 /* function footer */
692 printf("\t.size\t%s, .-%s\n", name, name);
694 func_cleanup(f);
695 current_func = NULL;
698 /* emit object (a.k.a. variable, a.k.a. data) prologue */
699 static void emit_object_pre(const char *name, unsigned long modifiers,
700 unsigned long alignment, unsigned int byte_size)
702 if ((modifiers & MOD_STATIC) == 0)
703 printf(".globl %s\n", name);
704 emit_section(".data");
705 if (alignment)
706 printf("\t.align %lu\n", alignment);
707 printf("\t.type\t%s, @object\n", name);
708 printf("\t.size\t%s, %d\n", name, byte_size);
709 printf("%s:\n", name);
712 /* emit value (only) for an initializer scalar */
713 static void emit_scalar(struct expression *expr, unsigned int bit_size)
715 const char *type;
716 long long ll;
718 assert(expr->type == EXPR_VALUE);
720 if (expr->value == 0ULL) {
721 printf("\t.zero\t%d\n", bit_size / 8);
722 return;
725 ll = (long long) expr->value;
727 switch (bit_size) {
728 case 8: type = "byte"; ll = (char) ll; break;
729 case 16: type = "value"; ll = (short) ll; break;
730 case 32: type = "long"; ll = (int) ll; break;
731 case 64: type = "quad"; break;
732 default: type = NULL; break;
735 assert(type != NULL);
737 printf("\t.%s\t%Ld\n", type, ll);
740 static void emit_global_noinit(const char *name, unsigned long modifiers,
741 unsigned long alignment, unsigned int byte_size)
743 char s[64];
745 if (modifiers & MOD_STATIC) {
746 sprintf(s, "\t.local\t%s\n", name);
747 textbuf_push(&unit_post_text, s);
749 if (alignment)
750 sprintf(s, "\t.comm\t%s,%d,%lu\n", name, byte_size, alignment);
751 else
752 sprintf(s, "\t.comm\t%s,%d\n", name, byte_size);
753 textbuf_push(&unit_post_text, s);
756 static int ea_current, ea_last;
758 static void emit_initializer(struct symbol *sym,
759 struct expression *expr)
761 int distance = ea_current - ea_last - 1;
763 if (distance > 0)
764 printf("\t.zero\t%d\n", (sym->bit_size / 8) * distance);
766 if (expr->type == EXPR_VALUE) {
767 struct symbol *base_type = sym->ctype.base_type;
768 assert(base_type != NULL);
770 emit_scalar(expr, sym->bit_size / base_type->array_size);
771 return;
773 if (expr->type != EXPR_INITIALIZER)
774 return;
776 assert(0); /* FIXME */
779 static int sort_array_cmp(const struct expression *a,
780 const struct expression *b)
782 int a_ofs = 0, b_ofs = 0;
784 if (a->type == EXPR_POS)
785 a_ofs = (int) a->init_offset;
786 if (b->type == EXPR_POS)
787 b_ofs = (int) b->init_offset;
789 return a_ofs - b_ofs;
792 /* move to front-end? */
793 static void sort_array(struct expression *expr)
795 struct expression *entry, **list;
796 unsigned int elem, sorted, i;
798 elem = 0;
799 FOR_EACH_PTR(expr->expr_list, entry) {
800 elem++;
801 } END_FOR_EACH_PTR;
803 if (!elem)
804 return;
806 list = malloc(sizeof(entry) * elem);
807 if (!list)
808 die("OOM in sort_array");
810 /* this code is no doubt evil and ignores EXPR_INDEX possibly
811 * to its detriment and other nasty things. improvements
812 * welcome.
814 i = 0;
815 sorted = 0;
816 FOR_EACH_PTR(expr->expr_list, entry) {
817 if ((entry->type == EXPR_POS) || (entry->type == EXPR_VALUE)) {
818 /* add entry to list[], in sorted order */
819 if (sorted == 0) {
820 list[0] = entry;
821 sorted = 1;
822 } else {
823 unsigned int i;
825 for (i = 0; i < sorted; i++)
826 if (sort_array_cmp(entry, list[i]) <= 0)
827 break;
829 /* If inserting into the middle of list[]
830 * instead of appending, we memmove.
831 * This is ugly, but thankfully
832 * uncommon. Input data with tons of
833 * entries very rarely have explicit
834 * offsets. convert to qsort eventually...
836 if (i != sorted)
837 memmove(&list[i + 1], &list[i],
838 (sorted - i) * sizeof(entry));
839 list[i] = entry;
840 sorted++;
843 } END_FOR_EACH_PTR;
845 i = 0;
846 FOR_EACH_PTR(expr->expr_list, entry) {
847 if ((entry->type == EXPR_POS) || (entry->type == EXPR_VALUE))
848 __list->list[__i] = list[i++];
849 } END_FOR_EACH_PTR;
853 static void emit_array(struct symbol *sym)
855 struct symbol *base_type = sym->ctype.base_type;
856 struct expression *expr = sym->initializer;
857 struct expression *entry;
859 assert(base_type != NULL);
861 stor_sym_init(sym);
863 ea_last = -1;
865 emit_object_pre(show_ident(sym->ident), sym->ctype.modifiers,
866 sym->ctype.alignment,
867 sym->bit_size / 8);
869 sort_array(expr);
871 FOR_EACH_PTR(expr->expr_list, entry) {
872 if (entry->type == EXPR_VALUE) {
873 ea_current = 0;
874 emit_initializer(sym, entry);
875 ea_last = ea_current;
876 } else if (entry->type == EXPR_POS) {
877 ea_current =
878 entry->init_offset / (base_type->bit_size / 8);
879 emit_initializer(sym, entry->init_expr);
880 ea_last = ea_current;
882 } END_FOR_EACH_PTR;
885 static void emit_one_symbol(struct symbol *sym, void *dummy, int flags)
887 x86_symbol(sym);
890 void emit_unit(const char *basename, struct symbol_list *list)
892 emit_unit_pre(basename);
893 symbol_iterate(list, emit_one_symbol, NULL);
894 emit_unit_post();
897 static void emit_copy(struct storage *src, struct symbol *src_ctype,
898 struct storage *dest, struct symbol *dest_ctype)
900 /* FIXME: Bitfield move! */
902 emit_move(src, REG_EAX, src_ctype, "begin copy ..");
903 emit_move(REG_EAX, dest, dest_ctype, ".... end copy");
906 static void emit_store(struct expression *dest_expr, struct storage *dest,
907 struct storage *src, int bits)
909 /* FIXME: Bitfield store! */
910 printf("\tst.%d\t\tv%d,[v%d]\n", bits, src->pseudo, dest->pseudo);
913 static void emit_scalar_noinit(struct symbol *sym)
915 emit_global_noinit(show_ident(sym->ident),
916 sym->ctype.modifiers, sym->ctype.alignment,
917 sym->bit_size / 8);
918 stor_sym_init(sym);
921 static void emit_array_noinit(struct symbol *sym)
923 emit_global_noinit(show_ident(sym->ident),
924 sym->ctype.modifiers, sym->ctype.alignment,
925 sym->array_size * (sym->bit_size / 8));
926 stor_sym_init(sym);
929 static const char *opbits(const char *insn, unsigned int bits)
931 static char opbits_str[32];
932 char c;
934 switch (bits) {
935 case 8: c = 'b'; break;
936 case 16: c = 'w'; break;
937 case 32: c = 'l'; break;
938 case 64: c = 'q'; break;
939 default: assert(0); break;
942 sprintf(opbits_str, "%s%c", insn, bits);
944 return opbits_str;
947 static void emit_move(struct storage *src, struct storage *dest,
948 struct symbol *ctype, const char *comment)
950 unsigned int bits;
951 unsigned int is_signed;
952 unsigned int is_dest = (src->type == STOR_REG);
953 const char *opname;
955 if (ctype) {
956 bits = ctype->bit_size;
957 is_signed = type_is_signed(ctype);
958 } else {
959 bits = 32;
960 is_signed = 0;
963 if ((dest->type == STOR_REG) && (src->type == STOR_REG)) {
964 insn("mov", src, dest, NULL);
965 return;
968 switch (bits) {
969 case 8:
970 if (is_dest)
971 opname = "movb";
972 else {
973 if (is_signed) opname = "movsxb";
974 else opname = "movzxb";
976 break;
977 case 16:
978 if (is_dest)
979 opname = "movw";
980 else {
981 if (is_signed) opname = "movsxw";
982 else opname = "movzxw";
984 break;
986 case 32: opname = "movl"; break;
987 case 64: opname = "movq"; break;
989 default: assert(0); break;
992 insn(opname, src, dest, comment);
995 static struct storage *emit_compare(struct expression *expr)
997 struct storage *left = x86_expression(expr->left);
998 struct storage *right = x86_expression(expr->right);
999 struct storage *new, *val;
1000 const char *opname = NULL;
1001 unsigned int is_signed = type_is_signed(expr->left->ctype); /* FIXME */
1002 unsigned int right_bits = expr->right->ctype->bit_size;
1004 switch(expr->op) {
1005 case '<':
1006 if (is_signed) opname = "setl";
1007 else opname = "setb";
1008 break;
1009 case '>':
1010 if (is_signed) opname = "setg";
1011 else opname = "seta";
1012 break;
1013 case SPECIAL_LTE:
1014 if (is_signed) opname = "setle";
1015 else opname = "setbe";
1016 break;
1017 case SPECIAL_GTE:
1018 if (is_signed) opname = "setge";
1019 else opname = "setae";
1020 break;
1022 case SPECIAL_EQUAL: opname = "sete"; break;
1023 case SPECIAL_NOTEQUAL: opname = "setne"; break;
1025 default:
1026 assert(0);
1027 break;
1030 /* init EDX to 0 */
1031 val = new_storage(STOR_VALUE);
1032 val->flags = STOR_WANTS_FREE;
1033 emit_move(val, REG_EDX, NULL, NULL);
1035 /* move op1 into EAX */
1036 emit_move(left, REG_EAX, expr->left->ctype, NULL);
1038 /* perform comparison, RHS (op1, right) and LHS (op2, EAX) */
1039 insn(opbits("cmp", right_bits), right, REG_EAX, NULL);
1041 /* store result of operation, 0 or 1, in DL using SETcc */
1042 insn(opname, REG_DL, NULL, NULL);
1044 /* finally, store the result (DL) in a new pseudo / stack slot */
1045 new = new_pseudo();
1046 emit_move(REG_EDX, new, NULL, "end EXPR_COMPARE");
1048 return new;
1051 static struct storage *emit_value(struct expression *expr)
1053 #if 0 /* old and slow way */
1054 struct storage *new = new_pseudo();
1055 struct storage *val;
1057 val = new_storage(STOR_VALUE);
1058 val->value = (long long) expr->value;
1059 val->flags = STOR_WANTS_FREE;
1060 insn("movl", val, new, NULL);
1062 return new;
1063 #else
1064 struct storage *val;
1066 val = new_storage(STOR_VALUE);
1067 val->value = (long long) expr->value;
1069 return val; /* FIXME: memory leak */
1070 #endif
1073 static struct storage *emit_binop(struct expression *expr)
1075 struct storage *left = x86_expression(expr->left);
1076 struct storage *right = x86_expression(expr->right);
1077 struct storage *new;
1078 const char *opname = NULL;
1081 * FIXME FIXME this routine is so wrong it's not even funny.
1082 * On x86 both mod/div are handled with the same instruction.
1083 * We don't pay attention to signed/unsigned issues,
1084 * and like elsewhere we hardcode the operand size at 32 bits.
1087 switch (expr->op) {
1088 case '+': opname = "addl"; break;
1089 case '-': opname = "subl"; break;
1090 case '*': opname = "mull"; break;
1091 case '/': opname = "divl"; break;
1092 case '%': opname = "modl"; break;
1093 case '&': opname = "andl"; break;
1094 case '|': opname = "orl"; break;
1095 case '^': opname = "xorl"; break;
1096 case SPECIAL_LEFTSHIFT: opname = "shll"; break;
1097 case SPECIAL_RIGHTSHIFT: opname = "shrl"; break;
1098 default: assert(0); break;
1101 /* load op2 into EAX */
1102 insn("movl", right, REG_EAX, "EXPR_BINOP/COMMA/LOGICAL");
1104 /* perform binop */
1105 insn(opname, left, REG_EAX, NULL);
1107 /* store result (EAX) in new pseudo / stack slot */
1108 new = new_pseudo();
1109 insn("movl", REG_EAX, new, "end EXPR_BINOP");
1111 return new;
1114 static void emit_if_conditional(struct statement *stmt)
1116 struct storage *val, *target_val;
1117 int target;
1118 struct expression *cond = stmt->if_conditional;
1120 /* This is only valid if nobody can jump into the "dead" statement */
1121 #if 0
1122 if (cond->type == EXPR_VALUE) {
1123 struct statement *s = stmt->if_true;
1124 if (!cond->value)
1125 s = stmt->if_false;
1126 x86_statement(s);
1127 break;
1129 #endif
1130 val = x86_expression(cond);
1132 /* load 'if' test result into EAX */
1133 insn("movl", val, REG_EAX, "begin if conditional");
1135 /* compare 'if' test result */
1136 insn("test", REG_EAX, REG_EAX, NULL);
1138 /* create end-of-if label / if-failed labelto jump to,
1139 * and jump to it if the expression returned zero.
1141 target = new_label();
1142 target_val = new_storage(STOR_LABEL);
1143 target_val->label = target;
1144 target_val->flags = STOR_WANTS_FREE;
1145 insn("jz", target_val, NULL, NULL);
1147 x86_statement(stmt->if_true);
1148 if (stmt->if_false) {
1149 struct storage *last_val;
1150 int last;
1152 /* finished generating code for if-true statement.
1153 * add a jump-to-end jump to avoid falling through
1154 * to the if-false statement code.
1156 last = new_label();
1157 last_val = new_storage(STOR_LABEL);
1158 last_val->label = last;
1159 last_val->flags = STOR_WANTS_FREE;
1160 insn("jmp", last_val, NULL, NULL);
1162 /* if we have both if-true and if-false statements,
1163 * the failed-conditional case will fall through to here
1165 emit_label(target, NULL);
1167 target = last;
1168 x86_statement(stmt->if_false);
1171 emit_label(target, "end if");
1174 static struct storage *emit_inc_dec(struct expression *expr, int postop)
1176 struct storage *addr = x86_address_gen(expr->unop);
1177 struct storage *retval;
1178 char opname[16];
1180 strcpy(opname, opbits(expr->op == SPECIAL_INCREMENT ? "inc" : "dec",
1181 expr->ctype->bit_size));
1183 if (postop) {
1184 struct storage *new = new_pseudo();
1186 emit_copy(addr, expr->unop->ctype, new, NULL);
1188 retval = new;
1189 } else
1190 retval = addr;
1192 insn(opname, addr, NULL, NULL);
1194 return retval;
1197 static struct storage *emit_postop(struct expression *expr)
1199 return emit_inc_dec(expr, 1);
1202 static struct storage *emit_return_stmt(struct statement *stmt)
1204 struct function *f = current_func;
1205 struct expression *expr = stmt->ret_value;
1206 struct storage *val = NULL, *jmplbl;
1208 if (expr && expr->ctype) {
1209 val = x86_expression(expr);
1210 assert(val != NULL);
1211 emit_move(val, REG_EAX, expr->ctype, "return");
1214 jmplbl = new_storage(STOR_LABEL);
1215 jmplbl->flags |= STOR_WANTS_FREE;
1216 jmplbl->label = f->ret_target;
1217 insn("jmp", jmplbl, NULL, NULL);
1219 return val;
1222 static struct storage *emit_conditional_expr(struct expression *expr)
1224 struct storage *cond = x86_expression(expr->conditional);
1225 struct storage *true = x86_expression(expr->cond_true);
1226 struct storage *false = x86_expression(expr->cond_false);
1227 struct storage *new = new_pseudo();
1229 if (!true)
1230 true = cond;
1232 emit_move(cond, REG_EAX, expr->conditional->ctype,
1233 "begin EXPR_CONDITIONAL");
1234 emit_move(true, REG_ECX, expr->cond_true->ctype, NULL);
1235 emit_move(false, REG_EDX, expr->cond_false->ctype, NULL);
1237 /* test EAX (for zero/non-zero) */
1238 insn("test", REG_EAX, REG_EAX, NULL);
1240 /* if false, move EDX to ECX */
1241 insn("cmovz", REG_EDX, REG_ECX, NULL);
1243 /* finally, store the result (ECX) in a new pseudo / stack slot */
1244 new = new_pseudo();
1245 emit_move(REG_ECX, new, expr->ctype, "end EXPR_CONDITIONAL");
1246 /* FIXME: we lose type knowledge of expression result at this point */
1248 return new;
1251 static struct storage *emit_symbol_expr_init(struct symbol *sym)
1253 struct expression *expr = sym->initializer;
1254 struct symbol_private *priv = sym->aux;
1256 if (priv == NULL) {
1257 priv = calloc(1, sizeof(*priv));
1258 sym->aux = priv;
1260 if (expr == NULL) {
1261 struct storage *new = new_pseudo();
1262 fprintf(stderr, "FIXME! no value for symbol. creating pseudo %d (stack offset %d)\n",
1263 new->pseudo, new->pseudo * 4);
1264 priv->addr = new;
1265 } else {
1266 priv->addr = x86_expression(expr);
1270 return priv->addr;
1273 static struct storage *emit_string_expr(struct expression *expr)
1275 struct function *f = current_func;
1276 int label = new_label();
1277 struct storage *new;
1279 push_cstring(f, expr->string, label);
1281 new = new_storage(STOR_LABEL);
1282 new->label = label;
1283 new->flags = STOR_LABEL_VAL | STOR_WANTS_FREE;
1284 return new;
1287 static struct storage *emit_cast_expr(struct expression *expr)
1289 struct symbol *old_type, *new_type;
1290 struct storage *op = x86_expression(expr->cast_expression);
1291 int oldbits, newbits;
1292 struct storage *new;
1294 old_type = expr->cast_expression->ctype;
1295 new_type = expr->cast_type;
1297 oldbits = old_type->bit_size;
1298 newbits = new_type->bit_size;
1299 if (oldbits >= newbits)
1300 return op;
1302 emit_move(op, REG_EAX, old_type, "begin cast ..");
1304 new = new_pseudo();
1305 emit_move(REG_EAX, new, new_type, ".... end cast");
1307 return new;
1310 static struct storage *emit_regular_preop(struct expression *expr)
1312 struct storage *target = x86_expression(expr->unop);
1313 struct storage *val, *new = new_pseudo();
1314 const char *opname = NULL;
1316 switch (expr->op) {
1317 case '!':
1318 val = new_storage(STOR_VALUE);
1319 val->flags = STOR_WANTS_FREE;
1320 emit_move(val, REG_EDX, NULL, NULL);
1321 emit_move(target, REG_EAX, expr->unop->ctype, NULL);
1322 insn("test", REG_EAX, REG_EAX, NULL);
1323 insn("setz", REG_DL, NULL, NULL);
1324 emit_move(REG_EDX, new, expr->unop->ctype, NULL);
1326 break;
1327 case '~':
1328 opname = "not";
1329 case '-':
1330 if (!opname)
1331 opname = "neg";
1332 emit_move(target, REG_EAX, expr->unop->ctype, NULL);
1333 insn(opname, REG_EAX, NULL, NULL);
1334 emit_move(REG_EAX, new, expr->unop->ctype, NULL);
1335 break;
1336 default:
1337 assert(0);
1338 break;
1341 return new;
1344 static void emit_case_statement(struct statement *stmt)
1346 emit_labelsym(stmt->case_label, NULL);
1347 x86_statement(stmt->case_statement);
1350 static void emit_switch_statement(struct statement *stmt)
1352 struct storage *val = x86_expression(stmt->switch_expression);
1353 struct symbol *sym, *default_sym = NULL;
1354 struct storage *labelsym, *label;
1355 int switch_end = 0;
1357 emit_move(val, REG_EAX, stmt->switch_expression->ctype, "begin case");
1360 * This is where a _real_ back-end would go through the
1361 * cases to decide whether to use a lookup table or a
1362 * series of comparisons etc
1364 FOR_EACH_PTR(stmt->switch_case->symbol_list, sym) {
1365 struct statement *case_stmt = sym->stmt;
1366 struct expression *expr = case_stmt->case_expression;
1367 struct expression *to = case_stmt->case_to;
1369 /* default: */
1370 if (!expr)
1371 default_sym = sym;
1373 /* case NNN: */
1374 else {
1375 struct storage *case_val = new_val(expr->value);
1377 assert (expr->type == EXPR_VALUE);
1379 insn("cmpl", case_val, REG_EAX, NULL);
1381 if (!to) {
1382 labelsym = new_labelsym(sym);
1383 insn("je", labelsym, NULL, NULL);
1384 } else {
1385 int next_test;
1387 label = new_storage(STOR_LABEL);
1388 label->flags |= STOR_WANTS_FREE;
1389 label->label = next_test = new_label();
1391 /* FIXME: signed/unsigned */
1392 insn("jl", label, NULL, NULL);
1394 case_val = new_val(to->value);
1395 insn("cmpl", case_val, REG_EAX, NULL);
1397 /* TODO: implement and use refcounting... */
1398 label = new_storage(STOR_LABEL);
1399 label->flags |= STOR_WANTS_FREE;
1400 label->label = next_test;
1402 /* FIXME: signed/unsigned */
1403 insn("jg", label, NULL, NULL);
1405 labelsym = new_labelsym(sym);
1406 insn("jmp", labelsym, NULL, NULL);
1408 emit_label(next_test, NULL);
1411 } END_FOR_EACH_PTR;
1413 if (default_sym) {
1414 labelsym = new_labelsym(default_sym);
1415 insn("jmp", labelsym, NULL, "default");
1416 } else {
1417 label = new_storage(STOR_LABEL);
1418 label->flags |= STOR_WANTS_FREE;
1419 label->label = switch_end = new_label();
1420 insn("jmp", label, NULL, "goto end of switch");
1423 x86_statement(stmt->switch_statement);
1425 if (stmt->switch_break->used)
1426 emit_labelsym(stmt->switch_break, NULL);
1428 if (switch_end)
1429 emit_label(switch_end, NULL);
1432 static void x86_struct_member(struct symbol *sym, void *data, int flags)
1434 if (flags & ITERATE_FIRST)
1435 printf(" {\n\t");
1436 printf("%s:%d:%ld at offset %ld", show_ident(sym->ident), sym->bit_size, sym->ctype.alignment, sym->offset);
1437 if (sym->fieldwidth)
1438 printf("[%d..%d]", sym->bit_offset, sym->bit_offset+sym->fieldwidth-1);
1439 if (flags & ITERATE_LAST)
1440 printf("\n} ");
1441 else
1442 printf(", ");
1445 static void x86_symbol(struct symbol *sym)
1447 struct symbol *type;
1449 if (!sym)
1450 return;
1452 type = sym->ctype.base_type;
1453 if (!type)
1454 return;
1457 * Show actual implementation information
1459 switch (type->type) {
1461 case SYM_ARRAY:
1462 if (sym->initializer)
1463 emit_array(sym);
1464 else
1465 emit_array_noinit(sym);
1466 break;
1468 case SYM_BASETYPE:
1469 if (sym->initializer) {
1470 emit_object_pre(show_ident(sym->ident),
1471 sym->ctype.modifiers,
1472 sym->ctype.alignment,
1473 sym->bit_size / 8);
1474 emit_scalar(sym->initializer, sym->bit_size);
1475 stor_sym_init(sym);
1476 } else
1477 emit_scalar_noinit(sym);
1478 break;
1480 case SYM_STRUCT:
1481 symbol_iterate(type->symbol_list, x86_struct_member, NULL);
1482 break;
1484 case SYM_UNION:
1485 symbol_iterate(type->symbol_list, x86_struct_member, NULL);
1486 break;
1488 case SYM_FN: {
1489 struct statement *stmt = type->stmt;
1490 if (stmt) {
1491 emit_func_pre(sym);
1492 x86_statement(stmt);
1493 emit_func_post(sym);
1495 break;
1498 default:
1499 break;
1502 if (sym->initializer && (type->type != SYM_BASETYPE) &&
1503 (type->type != SYM_ARRAY)) {
1504 printf(" = \n");
1505 x86_expression(sym->initializer);
1509 static void x86_symbol_init(struct symbol *sym);
1511 static void x86_symbol_decl(struct symbol_list *syms)
1513 struct symbol *sym;
1514 FOR_EACH_PTR(syms, sym) {
1515 x86_symbol_init(sym);
1516 } END_FOR_EACH_PTR;
1519 static void x86_loop(struct statement *stmt)
1521 struct statement *pre_statement = stmt->iterator_pre_statement;
1522 struct expression *pre_condition = stmt->iterator_pre_condition;
1523 struct statement *statement = stmt->iterator_statement;
1524 struct statement *post_statement = stmt->iterator_post_statement;
1525 struct expression *post_condition = stmt->iterator_post_condition;
1526 int loop_top = 0, loop_bottom = 0;
1527 struct storage *val;
1529 x86_symbol_decl(stmt->iterator_syms);
1530 x86_statement(pre_statement);
1531 if (pre_condition) {
1532 if (pre_condition->type == EXPR_VALUE) {
1533 if (!pre_condition->value) {
1534 loop_bottom = new_label();
1535 printf("\tjmp\t\t.L%d\n", loop_bottom);
1537 } else {
1538 loop_bottom = new_label();
1539 val = x86_expression(pre_condition);
1540 printf("\tje\t\tv%d, .L%d\n", val->pseudo, loop_bottom);
1543 if (!post_condition || post_condition->type != EXPR_VALUE || post_condition->value) {
1544 loop_top = new_label();
1545 printf(".L%d:\n", loop_top);
1547 x86_statement(statement);
1548 if (stmt->iterator_continue->used)
1549 printf(".L%p:\n", stmt->iterator_continue);
1550 x86_statement(post_statement);
1551 if (!post_condition) {
1552 printf("\tjmp\t\t.L%d\n", loop_top);
1553 } else if (post_condition->type == EXPR_VALUE) {
1554 if (post_condition->value)
1555 printf("\tjmp\t\t.L%d\n", loop_top);
1556 } else {
1557 val = x86_expression(post_condition);
1558 printf("\tjne\t\tv%d, .L%d\n", val->pseudo, loop_top);
1560 if (stmt->iterator_break->used)
1561 printf(".L%p:\n", stmt->iterator_break);
1562 if (loop_bottom)
1563 printf(".L%d:\n", loop_bottom);
1567 * Print out a statement
1569 static struct storage *x86_statement(struct statement *stmt)
1571 if (!stmt)
1572 return 0;
1573 switch (stmt->type) {
1574 case STMT_RETURN:
1575 return emit_return_stmt(stmt);
1576 case STMT_COMPOUND: {
1577 struct statement *s;
1578 struct storage *last = NULL;
1580 x86_symbol_decl(stmt->syms);
1581 FOR_EACH_PTR(stmt->stmts, s) {
1582 last = x86_statement(s);
1583 } END_FOR_EACH_PTR;
1585 return last;
1588 case STMT_EXPRESSION:
1589 return x86_expression(stmt->expression);
1590 case STMT_IF:
1591 emit_if_conditional(stmt);
1592 return NULL;
1594 case STMT_CASE:
1595 emit_case_statement(stmt);
1596 break;
1597 case STMT_SWITCH:
1598 emit_switch_statement(stmt);
1599 break;
1601 case STMT_ITERATOR:
1602 x86_loop(stmt);
1603 break;
1605 case STMT_NONE:
1606 break;
1608 case STMT_LABEL:
1609 printf(".L%p:\n", stmt->label_identifier);
1610 x86_statement(stmt->label_statement);
1611 break;
1613 case STMT_GOTO:
1614 if (stmt->goto_expression) {
1615 struct storage *val = x86_expression(stmt->goto_expression);
1616 printf("\tgoto *v%d\n", val->pseudo);
1617 } else {
1618 struct storage *labelsym = new_labelsym(stmt->goto_label);
1619 insn("jmp", labelsym, NULL, NULL);
1621 break;
1622 case STMT_ASM:
1623 printf("\tasm( .... )\n");
1624 break;
1627 return NULL;
1630 static struct storage *x86_call_expression(struct expression *expr)
1632 struct function *f = current_func;
1633 struct symbol *direct;
1634 struct expression *arg, *fn;
1635 struct storage *retval, *fncall;
1636 int framesize;
1637 char s[64];
1639 if (!expr->ctype) {
1640 warn(expr->pos, "\tcall with no type!");
1641 return NULL;
1644 framesize = 0;
1645 FOR_EACH_PTR_REVERSE(expr->args, arg) {
1646 struct storage *new = x86_expression(arg);
1647 int size = arg->ctype->bit_size;
1649 /* FIXME: pay attention to 'size' */
1650 insn("pushl", new, NULL,
1651 !framesize ? "begin function call" : NULL);
1653 framesize += size >> 3;
1654 } END_FOR_EACH_PTR_REVERSE;
1656 fn = expr->fn;
1658 /* Remove dereference, if any */
1659 direct = NULL;
1660 if (fn->type == EXPR_PREOP) {
1661 if (fn->unop->type == EXPR_SYMBOL) {
1662 struct symbol *sym = fn->unop->symbol;
1663 if (sym->ctype.base_type->type == SYM_FN)
1664 direct = sym;
1667 if (direct) {
1668 struct storage *direct_stor = new_storage(STOR_SYM);
1669 direct_stor->flags |= STOR_WANTS_FREE;
1670 direct_stor->sym = direct;
1671 insn("call", direct_stor, NULL, NULL);
1672 } else {
1673 fncall = x86_expression(fn);
1674 emit_move(fncall, REG_EAX, fn->ctype, NULL);
1676 strcpy(s, "\tcall\t*%eax\n");
1677 push_text_atom(f, s);
1680 /* FIXME: pay attention to BITS_IN_POINTER */
1681 if (framesize) {
1682 struct storage *val = new_storage(STOR_VALUE);
1683 val->value = (long long) framesize;
1684 val->flags = STOR_WANTS_FREE;
1685 insn("addl", val, REG_ESP, NULL);
1688 retval = new_pseudo();
1689 emit_move(REG_EAX, retval, NULL, "end function call");
1691 return retval;
1694 static struct storage *x86_address_gen(struct expression *expr)
1696 struct function *f = current_func;
1697 struct storage *addr;
1698 struct storage *new;
1699 char s[32];
1701 if ((expr->type != EXPR_PREOP) || (expr->op != '*'))
1702 return x86_expression(expr->address);
1704 addr = x86_expression(expr->unop);
1705 if (expr->unop->type == EXPR_SYMBOL)
1706 return addr;
1708 emit_move(addr, REG_EAX, NULL, "begin deref ..");
1710 /* FIXME: operand size */
1711 strcpy(s, "\tmovl\t(%eax), %ecx\n");
1712 push_text_atom(f, s);
1714 new = new_pseudo();
1715 emit_move(REG_ECX, new, NULL, ".... end deref");
1717 return new;
1720 static struct storage *x86_assignment(struct expression *expr)
1722 struct expression *target = expr->left;
1723 struct storage *val, *addr;
1724 int bits;
1726 if (!expr->ctype)
1727 return NULL;
1729 bits = expr->ctype->bit_size;
1730 val = x86_expression(expr->right);
1731 addr = x86_address_gen(target);
1733 switch (val->type) {
1734 /* copy, where both operands are memory */
1735 case STOR_PSEUDO:
1736 case STOR_ARG:
1737 emit_copy(val, expr->right->ctype, addr, expr->left->ctype);
1738 break;
1740 /* copy, one or zero operands are memory */
1741 case STOR_REG:
1742 case STOR_SYM:
1743 case STOR_VALUE:
1744 case STOR_LABEL:
1745 emit_move(val, addr, expr->left->ctype, NULL);
1746 break;
1748 case STOR_LABELSYM:
1749 assert(0);
1750 break;
1752 return val;
1755 static int x86_initialization(struct symbol *sym, struct expression *expr)
1757 struct storage *val, *addr;
1758 int bits;
1760 if (!expr->ctype)
1761 return 0;
1763 bits = expr->ctype->bit_size;
1764 val = x86_expression(expr);
1765 addr = x86_symbol_expr(sym);
1766 // FIXME! The "target" expression is for bitfield store information.
1767 // Leave it NULL, which works fine.
1768 emit_store(NULL, addr, val, bits);
1769 return 0;
1772 static struct storage *x86_access(struct expression *expr)
1774 return x86_address_gen(expr);
1777 static struct storage *x86_preop(struct expression *expr)
1780 * '*' is an lvalue access, and is fundamentally different
1781 * from an arithmetic operation. Maybe it should have an
1782 * expression type of its own..
1784 if (expr->op == '*')
1785 return x86_access(expr);
1786 if (expr->op == SPECIAL_INCREMENT || expr->op == SPECIAL_DECREMENT)
1787 return emit_inc_dec(expr, 0);
1788 return emit_regular_preop(expr);
1791 static struct storage *x86_symbol_expr(struct symbol *sym)
1793 struct storage *new = new_pseudo();
1795 if (sym->ctype.modifiers & (MOD_TOPLEVEL | MOD_EXTERN | MOD_STATIC)) {
1796 printf("\tmovi.%d\t\tv%d,$%s\n", BITS_IN_POINTER, new->pseudo, show_ident(sym->ident));
1797 return new;
1799 if (sym->ctype.modifiers & MOD_ADDRESSABLE) {
1800 printf("\taddi.%d\t\tv%d,vFP,$%lld\n", BITS_IN_POINTER, new->pseudo, sym->value);
1801 return new;
1803 printf("\taddi.%d\t\tv%d,vFP,$offsetof(%s:%p)\n", BITS_IN_POINTER, new->pseudo, show_ident(sym->ident), sym);
1804 return new;
1807 static void x86_symbol_init(struct symbol *sym)
1809 struct symbol_private *priv = sym->aux;
1810 struct expression *expr = sym->initializer;
1811 struct storage *new;
1813 if (expr)
1814 new = x86_expression(expr);
1815 else
1816 new = new_pseudo();
1818 if (!priv) {
1819 priv = calloc(1, sizeof(*priv));
1820 sym->aux = priv;
1821 /* FIXME: leak! we don't free... */
1822 /* (well, we don't free symbols either) */
1825 priv->addr = new;
1828 static int type_is_signed(struct symbol *sym)
1830 if (sym->type == SYM_NODE)
1831 sym = sym->ctype.base_type;
1832 if (sym->type == SYM_PTR)
1833 return 0;
1834 return !(sym->ctype.modifiers & MOD_UNSIGNED);
1837 static struct storage *x86_bitfield_expr(struct expression *expr)
1839 return x86_access(expr);
1842 static struct storage *x86_label_expr(struct expression *expr)
1844 struct storage *new = new_pseudo();
1845 printf("\tmovi.%d\t\tv%d,.L%p\n",BITS_IN_POINTER, new->pseudo, expr->label_symbol);
1846 return new;
1849 static struct storage *x86_statement_expr(struct expression *expr)
1851 return x86_statement(expr->statement);
1854 static int x86_position_expr(struct expression *expr, struct symbol *base)
1856 struct storage *new = x86_expression(expr->init_expr);
1857 struct symbol *ctype = expr->init_sym;
1859 printf("\tinsert v%d at [%d:%d] of %s\n", new->pseudo,
1860 expr->init_offset, ctype->bit_offset,
1861 show_ident(base->ident));
1862 return 0;
1865 static void x86_initializer_expr(struct expression *expr, struct symbol *ctype)
1867 struct expression *entry;
1869 FOR_EACH_PTR(expr->expr_list, entry) {
1870 // Nested initializers have their positions already
1871 // recursively calculated - just output them too
1872 if (entry->type == EXPR_INITIALIZER) {
1873 x86_initializer_expr(entry, ctype);
1874 continue;
1877 // Ignore initializer indexes and identifiers - the
1878 // evaluator has taken them into account
1879 if (entry->type == EXPR_IDENTIFIER || entry->type == EXPR_INDEX)
1880 continue;
1881 if (entry->type == EXPR_POS) {
1882 x86_position_expr(entry, ctype);
1883 continue;
1885 x86_initialization(ctype, entry);
1886 } END_FOR_EACH_PTR;
1890 * Print out an expression. Return the pseudo that contains the
1891 * variable.
1893 static struct storage *x86_expression(struct expression *expr)
1895 if (!expr)
1896 return 0;
1898 if (!expr->ctype) {
1899 struct position *pos = &expr->pos;
1900 printf("\tno type at %s:%d:%d\n",
1901 input_streams[pos->stream].name,
1902 pos->line, pos->pos);
1903 return 0;
1906 switch (expr->type) {
1907 case EXPR_CALL:
1908 return x86_call_expression(expr);
1910 case EXPR_ASSIGNMENT:
1911 return x86_assignment(expr);
1913 case EXPR_COMPARE:
1914 return emit_compare(expr);
1915 case EXPR_BINOP:
1916 case EXPR_COMMA:
1917 case EXPR_LOGICAL:
1918 return emit_binop(expr);
1919 case EXPR_PREOP:
1920 return x86_preop(expr);
1921 case EXPR_POSTOP:
1922 return emit_postop(expr);
1923 case EXPR_SYMBOL:
1924 return emit_symbol_expr_init(expr->symbol);
1925 case EXPR_DEREF:
1926 case EXPR_SIZEOF:
1927 warn(expr->pos, "invalid expression after evaluation");
1928 return 0;
1929 case EXPR_CAST:
1930 return emit_cast_expr(expr);
1931 case EXPR_VALUE:
1932 return emit_value(expr);
1933 case EXPR_STRING:
1934 return emit_string_expr(expr);
1935 case EXPR_BITFIELD:
1936 return x86_bitfield_expr(expr);
1937 case EXPR_INITIALIZER:
1938 x86_initializer_expr(expr, expr->ctype);
1939 return NULL;
1940 case EXPR_CONDITIONAL:
1941 return emit_conditional_expr(expr);
1942 case EXPR_STATEMENT:
1943 return x86_statement_expr(expr);
1944 case EXPR_LABEL:
1945 return x86_label_expr(expr);
1947 // None of these should exist as direct expressions: they are only
1948 // valid as sub-expressions of initializers.
1949 case EXPR_POS:
1950 warn(expr->pos, "unable to show plain initializer position expression");
1951 return 0;
1952 case EXPR_IDENTIFIER:
1953 warn(expr->pos, "unable to show identifier expression");
1954 return 0;
1955 case EXPR_INDEX:
1956 warn(expr->pos, "unable to show index expression");
1957 return 0;
1959 return 0;