Merge redhat.com:/garz/repo/sparse into redhat.com:/garz/repo/sparse.be
[smatch.git] / compile-i386.c
blob8e9cdd07114309e34a04a7dd6a71f968c8c11048
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 pseudo_nr;
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->pseudo_nr + 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 stor->pseudo = ++f->pseudo_nr;
350 add_ptr_list(&f->pseudo_list, stor);
352 return stor;
355 static struct storage *new_labelsym(struct symbol *sym)
357 struct storage *stor;
359 stor = new_storage(STOR_LABELSYM);
361 if (stor) {
362 stor->flags |= STOR_WANTS_FREE;
363 stor->labelsym = sym;
366 return stor;
369 static struct storage *new_val(long long value)
371 struct storage *stor;
373 stor = new_storage(STOR_VALUE);
375 if (stor) {
376 stor->flags |= STOR_WANTS_FREE;
377 stor->value = value;
380 return stor;
383 static int new_label(void)
385 static int label = 0;
386 return ++label;
389 static void textbuf_push(struct textbuf **buf_p, const char *text)
391 struct textbuf *tmp, *list = *buf_p;
392 unsigned int text_len = strlen(text);
393 unsigned int alloc_len = text_len + 1 + sizeof(*list);
395 tmp = calloc(1, alloc_len);
396 if (!tmp)
397 die("OOM on textbuf alloc");
399 tmp->text = ((void *) tmp) + sizeof(*tmp);
400 memcpy(tmp->text, text, text_len + 1);
401 tmp->len = text_len;
403 /* add to end of list */
404 if (!list) {
405 list = tmp;
406 tmp->prev = tmp;
407 } else {
408 tmp->prev = list->prev;
409 tmp->prev->next = tmp;
410 list->prev = tmp;
412 tmp->next = list;
414 *buf_p = list;
417 static void textbuf_emit(struct textbuf **buf_p)
419 struct textbuf *tmp, *list = *buf_p;
421 while (list) {
422 tmp = list;
423 if (tmp->next == tmp)
424 list = NULL;
425 else {
426 tmp->prev->next = tmp->next;
427 tmp->next->prev = tmp->prev;
428 list = tmp->next;
431 fputs(tmp->text, stdout);
433 free(tmp);
436 *buf_p = list;
439 static void insn(const char *insn, struct storage *op1, struct storage *op2,
440 const char *comment_in)
442 struct function *f = current_func;
443 struct atom *atom = new_atom(ATOM_INSN);
445 assert(insn != NULL);
447 strcpy(atom->insn, insn);
448 if (comment_in && (*comment_in))
449 strncpy(atom->comment, comment_in,
450 sizeof(atom->comment) - 1);
452 atom->op1 = op1;
453 atom->op2 = op2;
455 push_atom(f, atom);
458 static void emit_label (int label, const char *comment)
460 struct function *f = current_func;
461 char s[64];
463 if (!comment)
464 sprintf(s, ".L%d:\n", label);
465 else
466 sprintf(s, ".L%d:\t\t\t\t\t# %s\n", label, comment);
468 push_text_atom(f, s);
471 static void emit_labelsym (struct symbol *sym, const char *comment)
473 struct function *f = current_func;
474 char s[64];
476 if (!comment)
477 sprintf(s, ".LS%p:\n", sym);
478 else
479 sprintf(s, ".LS%p:\t\t\t\t# %s\n", sym, comment);
481 push_text_atom(f, s);
484 static void emit_unit_pre(const char *basename)
486 printf("\t.file\t\"%s\"\n", basename);
489 static void emit_unit_post(void)
491 textbuf_emit(&unit_post_text);
492 printf("\t.ident\t\"sparse silly x86 backend (built %s)\"\n", __DATE__);
495 /* conditionally switch sections */
496 static void emit_section(const char *s)
498 if (s == current_section)
499 return;
500 if (current_section && (!strcmp(s, current_section)))
501 return;
503 printf("\t%s\n", s);
504 current_section = s;
507 static void emit_insn_atom(struct function *f, struct atom *atom)
509 char s[128];
510 char comment[64];
511 struct storage *op1 = atom->op1;
512 struct storage *op2 = atom->op2;
514 if (atom->comment[0])
515 sprintf(comment, "\t\t# %s", atom->comment);
516 else
517 comment[0] = 0;
519 if (atom->op2) {
520 char tmp[16];
521 strcpy(tmp, stor_op_name(op1));
522 sprintf(s, "\t%s\t%s, %s%s\n",
523 atom->insn, tmp, stor_op_name(op2), comment);
524 } else if (atom->op1)
525 sprintf(s, "\t%s\t%s%s%s\n",
526 atom->insn, stor_op_name(op1),
527 comment[0] ? "\t" : "", comment);
528 else
529 sprintf(s, "\t%s\t%s%s\n",
530 atom->insn,
531 comment[0] ? "\t\t" : "", comment);
533 write(STDOUT_FILENO, s, strlen(s));
536 static void emit_atom_list(struct function *f)
538 struct atom *atom;
540 FOR_EACH_PTR(f->atom_list, atom) {
541 switch (atom->type) {
542 case ATOM_TEXT: {
543 ssize_t rc = write(STDOUT_FILENO, atom->text,
544 atom->text_len);
545 (void) rc; /* FIXME */
546 break;
548 case ATOM_INSN:
549 emit_insn_atom(f, atom);
550 break;
551 case ATOM_CSTR:
552 assert(0);
553 break;
555 } END_FOR_EACH_PTR;
558 static void emit_string_list(struct function *f)
560 struct atom *atom;
562 emit_section(".section\t.rodata");
564 FOR_EACH_PTR(f->str_list, atom) {
565 /* FIXME: escape " in string */
566 printf(".L%d:\n", atom->label);
567 printf("\t.string\t%s\n", show_string(atom->string));
569 free(atom);
570 } END_FOR_EACH_PTR;
573 static void func_cleanup(struct function *f)
575 struct storage *stor;
576 struct atom *atom;
578 FOR_EACH_PTR(f->pseudo_list, stor) {
579 free(stor);
580 } END_FOR_EACH_PTR;
582 FOR_EACH_PTR(f->atom_list, atom) {
583 if ((atom->type == ATOM_TEXT) && (atom->text))
584 free(atom->text);
585 if (atom->op1 && (atom->op1->flags & STOR_WANTS_FREE))
586 free(atom->op1);
587 if (atom->op2 && (atom->op2->flags & STOR_WANTS_FREE))
588 free(atom->op2);
589 free(atom);
590 } END_FOR_EACH_PTR;
592 free_ptr_list(&f->pseudo_list);
593 free(f);
596 /* function prologue */
597 static void emit_func_pre(struct symbol *sym)
599 struct function *f;
600 struct symbol *arg;
601 unsigned int i, argc = 0, alloc_len;
602 unsigned char *mem;
603 struct symbol_private *privbase;
604 struct storage *storage_base;
605 struct symbol *base_type = sym->ctype.base_type;
607 FOR_EACH_PTR(base_type->arguments, arg) {
608 argc++;
609 } END_FOR_EACH_PTR;
611 alloc_len =
612 sizeof(*f) +
613 (argc * sizeof(struct symbol *)) +
614 (argc * sizeof(struct symbol_private)) +
615 (argc * sizeof(struct storage));
616 mem = calloc(1, alloc_len);
617 if (!mem)
618 die("OOM on func info");
620 f = (struct function *) mem;
621 mem += sizeof(*f);
622 f->argv = (struct symbol **) mem;
623 mem += (argc * sizeof(struct symbol *));
624 privbase = (struct symbol_private *) mem;
625 mem += (argc * sizeof(struct symbol_private));
626 storage_base = (struct storage *) mem;
628 f->argc = argc;
629 f->ret_target = new_label();
631 i = 0;
632 FOR_EACH_PTR(base_type->arguments, arg) {
633 f->argv[i] = arg;
634 arg->aux = &privbase[i];
635 storage_base[i].type = STOR_ARG;
636 storage_base[i].idx = i;
637 privbase[i].addr = &storage_base[i];
638 i++;
639 } END_FOR_EACH_PTR;
641 assert(current_func == NULL);
642 current_func = f;
645 /* function epilogue */
646 static void emit_func_post(struct symbol *sym)
648 const char *name = show_ident(sym->ident);
649 struct function *f = current_func;
650 int pseudo_nr = f->pseudo_nr;
652 if (f->str_list)
653 emit_string_list(f);
655 /* function prologue */
656 emit_section(".text");
657 if ((sym->ctype.modifiers & MOD_STATIC) == 0)
658 printf(".globl %s\n", name);
659 printf("\t.type\t%s, @function\n", name);
660 printf("%s:\n", name);
662 if (pseudo_nr) {
663 char pseudo_const[16];
665 sprintf(pseudo_const, "$%d", pseudo_nr * 4);
666 printf("\tsubl\t%s, %%esp\n", pseudo_const);
669 /* function epilogue */
671 /* jump target for 'return' statements */
672 emit_label(f->ret_target, NULL);
674 if (pseudo_nr) {
675 struct storage *val;
677 val = new_storage(STOR_VALUE);
678 val->value = (long long) (pseudo_nr * 4);
679 val->flags = STOR_WANTS_FREE;
681 insn("addl", val, REG_ESP, NULL);
684 insn("ret", NULL, NULL, NULL);
686 /* output everything to stdout */
687 fflush(stdout); /* paranoia; needed? */
688 emit_atom_list(f);
690 /* function footer */
691 printf("\t.size\t%s, .-%s\n", name, name);
693 func_cleanup(f);
694 current_func = NULL;
697 /* emit object (a.k.a. variable, a.k.a. data) prologue */
698 static void emit_object_pre(const char *name, unsigned long modifiers,
699 unsigned long alignment, unsigned int byte_size)
701 if ((modifiers & MOD_STATIC) == 0)
702 printf(".globl %s\n", name);
703 emit_section(".data");
704 if (alignment)
705 printf("\t.align %lu\n", alignment);
706 printf("\t.type\t%s, @object\n", name);
707 printf("\t.size\t%s, %d\n", name, byte_size);
708 printf("%s:\n", name);
711 /* emit value (only) for an initializer scalar */
712 static void emit_scalar(struct expression *expr, unsigned int bit_size)
714 const char *type;
715 long long ll;
717 assert(expr->type == EXPR_VALUE);
719 if (expr->value == 0ULL) {
720 printf("\t.zero\t%d\n", bit_size / 8);
721 return;
724 ll = (long long) expr->value;
726 switch (bit_size) {
727 case 8: type = "byte"; ll = (char) ll; break;
728 case 16: type = "value"; ll = (short) ll; break;
729 case 32: type = "long"; ll = (int) ll; break;
730 case 64: type = "quad"; break;
731 default: type = NULL; break;
734 assert(type != NULL);
736 printf("\t.%s\t%Ld\n", type, ll);
739 static void emit_global_noinit(const char *name, unsigned long modifiers,
740 unsigned long alignment, unsigned int byte_size)
742 char s[64];
744 if (modifiers & MOD_STATIC) {
745 sprintf(s, "\t.local\t%s\n", name);
746 textbuf_push(&unit_post_text, s);
748 if (alignment)
749 sprintf(s, "\t.comm\t%s,%d,%lu\n", name, byte_size, alignment);
750 else
751 sprintf(s, "\t.comm\t%s,%d\n", name, byte_size);
752 textbuf_push(&unit_post_text, s);
755 static int ea_current, ea_last;
757 static void emit_initializer(struct symbol *sym,
758 struct expression *expr)
760 int distance = ea_current - ea_last - 1;
762 if (distance > 0)
763 printf("\t.zero\t%d\n", (sym->bit_size / 8) * distance);
765 if (expr->type == EXPR_VALUE) {
766 struct symbol *base_type = sym->ctype.base_type;
767 assert(base_type != NULL);
769 emit_scalar(expr, sym->bit_size / base_type->array_size);
770 return;
772 if (expr->type != EXPR_INITIALIZER)
773 return;
775 assert(0); /* FIXME */
778 static int sort_array_cmp(const struct expression *a,
779 const struct expression *b)
781 int a_ofs = 0, b_ofs = 0;
783 if (a->type == EXPR_POS)
784 a_ofs = (int) a->init_offset;
785 if (b->type == EXPR_POS)
786 b_ofs = (int) b->init_offset;
788 return a_ofs - b_ofs;
791 /* move to front-end? */
792 static void sort_array(struct expression *expr)
794 struct expression *entry, **list;
795 unsigned int elem, sorted, i;
797 elem = 0;
798 FOR_EACH_PTR(expr->expr_list, entry) {
799 elem++;
800 } END_FOR_EACH_PTR;
802 if (!elem)
803 return;
805 list = malloc(sizeof(entry) * elem);
806 if (!list)
807 die("OOM in sort_array");
809 /* this code is no doubt evil and ignores EXPR_INDEX possibly
810 * to its detriment and other nasty things. improvements
811 * welcome.
813 i = 0;
814 sorted = 0;
815 FOR_EACH_PTR(expr->expr_list, entry) {
816 if ((entry->type == EXPR_POS) || (entry->type == EXPR_VALUE)) {
817 /* add entry to list[], in sorted order */
818 if (sorted == 0) {
819 list[0] = entry;
820 sorted = 1;
821 } else {
822 unsigned int i;
824 for (i = 0; i < sorted; i++)
825 if (sort_array_cmp(entry, list[i]) <= 0)
826 break;
828 /* If inserting into the middle of list[]
829 * instead of appending, we memmove.
830 * This is ugly, but thankfully
831 * uncommon. Input data with tons of
832 * entries very rarely have explicit
833 * offsets. convert to qsort eventually...
835 if (i != sorted)
836 memmove(&list[i + 1], &list[i],
837 (sorted - i) * sizeof(entry));
838 list[i] = entry;
839 sorted++;
842 } END_FOR_EACH_PTR;
844 i = 0;
845 FOR_EACH_PTR(expr->expr_list, entry) {
846 if ((entry->type == EXPR_POS) || (entry->type == EXPR_VALUE))
847 __list->list[__i] = list[i++];
848 } END_FOR_EACH_PTR;
852 static void emit_array(struct symbol *sym)
854 struct symbol *base_type = sym->ctype.base_type;
855 struct expression *expr = sym->initializer;
856 struct expression *entry;
858 assert(base_type != NULL);
860 stor_sym_init(sym);
862 ea_last = -1;
864 emit_object_pre(show_ident(sym->ident), sym->ctype.modifiers,
865 sym->ctype.alignment,
866 sym->bit_size / 8);
868 sort_array(expr);
870 FOR_EACH_PTR(expr->expr_list, entry) {
871 if (entry->type == EXPR_VALUE) {
872 ea_current = 0;
873 emit_initializer(sym, entry);
874 ea_last = ea_current;
875 } else if (entry->type == EXPR_POS) {
876 ea_current =
877 entry->init_offset / (base_type->bit_size / 8);
878 emit_initializer(sym, entry->init_expr);
879 ea_last = ea_current;
881 } END_FOR_EACH_PTR;
884 static void emit_one_symbol(struct symbol *sym, void *dummy, int flags)
886 x86_symbol(sym);
889 void emit_unit(const char *basename, struct symbol_list *list)
891 emit_unit_pre(basename);
892 symbol_iterate(list, emit_one_symbol, NULL);
893 emit_unit_post();
896 static void emit_copy(struct storage *src, struct symbol *src_ctype,
897 struct storage *dest, struct symbol *dest_ctype)
899 /* FIXME: Bitfield move! */
901 emit_move(src, REG_EAX, src_ctype, "begin copy ..");
902 emit_move(REG_EAX, dest, dest_ctype, ".... end copy");
905 static void emit_store(struct expression *dest_expr, struct storage *dest,
906 struct storage *src, int bits)
908 /* FIXME: Bitfield store! */
909 printf("\tst.%d\t\tv%d,[v%d]\n", bits, src->pseudo, dest->pseudo);
912 static void emit_scalar_noinit(struct symbol *sym)
914 emit_global_noinit(show_ident(sym->ident),
915 sym->ctype.modifiers, sym->ctype.alignment,
916 sym->bit_size / 8);
917 stor_sym_init(sym);
920 static void emit_array_noinit(struct symbol *sym)
922 emit_global_noinit(show_ident(sym->ident),
923 sym->ctype.modifiers, sym->ctype.alignment,
924 sym->array_size * (sym->bit_size / 8));
925 stor_sym_init(sym);
928 static const char *opbits(const char *insn, unsigned int bits)
930 static char opbits_str[32];
931 char c;
933 switch (bits) {
934 case 8: c = 'b'; break;
935 case 16: c = 'w'; break;
936 case 32: c = 'l'; break;
937 case 64: c = 'q'; break;
938 default: assert(0); break;
941 sprintf(opbits_str, "%s%c", insn, bits);
943 return opbits_str;
946 static void emit_move(struct storage *src, struct storage *dest,
947 struct symbol *ctype, const char *comment)
949 unsigned int bits;
950 unsigned int is_signed;
951 unsigned int is_dest = (src->type == STOR_REG);
952 const char *opname;
954 if (ctype) {
955 bits = ctype->bit_size;
956 is_signed = type_is_signed(ctype);
957 } else {
958 bits = 32;
959 is_signed = 0;
962 if ((dest->type == STOR_REG) && (src->type == STOR_REG)) {
963 insn("mov", src, dest, NULL);
964 return;
967 switch (bits) {
968 case 8:
969 if (is_dest)
970 opname = "movb";
971 else {
972 if (is_signed) opname = "movsxb";
973 else opname = "movzxb";
975 break;
976 case 16:
977 if (is_dest)
978 opname = "movw";
979 else {
980 if (is_signed) opname = "movsxw";
981 else opname = "movzxw";
983 break;
985 case 32: opname = "movl"; break;
986 case 64: opname = "movq"; break;
988 default: assert(0); break;
991 insn(opname, src, dest, comment);
994 static struct storage *emit_compare(struct expression *expr)
996 struct storage *left = x86_expression(expr->left);
997 struct storage *right = x86_expression(expr->right);
998 struct storage *new, *val;
999 const char *opname = NULL;
1000 unsigned int is_signed = type_is_signed(expr->left->ctype); /* FIXME */
1001 unsigned int right_bits = expr->right->ctype->bit_size;
1003 switch(expr->op) {
1004 case '<':
1005 if (is_signed) opname = "setl";
1006 else opname = "setb";
1007 break;
1008 case '>':
1009 if (is_signed) opname = "setg";
1010 else opname = "seta";
1011 break;
1012 case SPECIAL_LTE:
1013 if (is_signed) opname = "setle";
1014 else opname = "setbe";
1015 break;
1016 case SPECIAL_GTE:
1017 if (is_signed) opname = "setge";
1018 else opname = "setae";
1019 break;
1021 case SPECIAL_EQUAL: opname = "sete"; break;
1022 case SPECIAL_NOTEQUAL: opname = "setne"; break;
1024 default:
1025 assert(0);
1026 break;
1029 /* init EDX to 0 */
1030 val = new_storage(STOR_VALUE);
1031 val->flags = STOR_WANTS_FREE;
1032 emit_move(val, REG_EDX, NULL, NULL);
1034 /* move op1 into EAX */
1035 emit_move(left, REG_EAX, expr->left->ctype, NULL);
1037 /* perform comparison, RHS (op1, right) and LHS (op2, EAX) */
1038 insn(opbits("cmp", right_bits), right, REG_EAX, NULL);
1040 /* store result of operation, 0 or 1, in DL using SETcc */
1041 insn(opname, REG_DL, NULL, NULL);
1043 /* finally, store the result (DL) in a new pseudo / stack slot */
1044 new = new_pseudo();
1045 emit_move(REG_EDX, new, NULL, "end EXPR_COMPARE");
1047 return new;
1050 static struct storage *emit_value(struct expression *expr)
1052 #if 0 /* old and slow way */
1053 struct storage *new = new_pseudo();
1054 struct storage *val;
1056 val = new_storage(STOR_VALUE);
1057 val->value = (long long) expr->value;
1058 val->flags = STOR_WANTS_FREE;
1059 insn("movl", val, new, NULL);
1061 return new;
1062 #else
1063 struct storage *val;
1065 val = new_storage(STOR_VALUE);
1066 val->value = (long long) expr->value;
1068 return val; /* FIXME: memory leak */
1069 #endif
1072 static struct storage *emit_binop(struct expression *expr)
1074 struct storage *left = x86_expression(expr->left);
1075 struct storage *right = x86_expression(expr->right);
1076 struct storage *new;
1077 const char *opname = NULL;
1080 * FIXME FIXME this routine is so wrong it's not even funny.
1081 * On x86 both mod/div are handled with the same instruction.
1082 * We don't pay attention to signed/unsigned issues,
1083 * and like elsewhere we hardcode the operand size at 32 bits.
1086 switch (expr->op) {
1087 case '+': opname = "addl"; break;
1088 case '-': opname = "subl"; break;
1089 case '*': opname = "mull"; break;
1090 case '/': opname = "divl"; break;
1091 case '%': opname = "modl"; break;
1092 case '&': opname = "andl"; break;
1093 case '|': opname = "orl"; break;
1094 case '^': opname = "xorl"; break;
1095 case SPECIAL_LEFTSHIFT: opname = "shll"; break;
1096 case SPECIAL_RIGHTSHIFT: opname = "shrl"; break;
1097 default: assert(0); break;
1100 /* load op2 into EAX */
1101 insn("movl", right, REG_EAX, "EXPR_BINOP/COMMA/LOGICAL");
1103 /* perform binop */
1104 insn(opname, left, REG_EAX, NULL);
1106 /* store result (EAX) in new pseudo / stack slot */
1107 new = new_pseudo();
1108 insn("movl", REG_EAX, new, "end EXPR_BINOP");
1110 return new;
1113 static void emit_if_conditional(struct statement *stmt)
1115 struct storage *val, *target_val;
1116 int target;
1117 struct expression *cond = stmt->if_conditional;
1119 /* This is only valid if nobody can jump into the "dead" statement */
1120 #if 0
1121 if (cond->type == EXPR_VALUE) {
1122 struct statement *s = stmt->if_true;
1123 if (!cond->value)
1124 s = stmt->if_false;
1125 x86_statement(s);
1126 break;
1128 #endif
1129 val = x86_expression(cond);
1131 /* load 'if' test result into EAX */
1132 insn("movl", val, REG_EAX, "begin if conditional");
1134 /* compare 'if' test result */
1135 insn("test", REG_EAX, REG_EAX, NULL);
1137 /* create end-of-if label / if-failed labelto jump to,
1138 * and jump to it if the expression returned zero.
1140 target = new_label();
1141 target_val = new_storage(STOR_LABEL);
1142 target_val->label = target;
1143 target_val->flags = STOR_WANTS_FREE;
1144 insn("jz", target_val, NULL, NULL);
1146 x86_statement(stmt->if_true);
1147 if (stmt->if_false) {
1148 struct storage *last_val;
1149 int last;
1151 /* finished generating code for if-true statement.
1152 * add a jump-to-end jump to avoid falling through
1153 * to the if-false statement code.
1155 last = new_label();
1156 last_val = new_storage(STOR_LABEL);
1157 last_val->label = last;
1158 last_val->flags = STOR_WANTS_FREE;
1159 insn("jmp", last_val, NULL, NULL);
1161 /* if we have both if-true and if-false statements,
1162 * the failed-conditional case will fall through to here
1164 emit_label(target, NULL);
1166 target = last;
1167 x86_statement(stmt->if_false);
1170 emit_label(target, "end if");
1173 static struct storage *emit_inc_dec(struct expression *expr, int postop)
1175 struct storage *addr = x86_address_gen(expr->unop);
1176 struct storage *retval;
1177 char opname[16];
1179 strcpy(opname, opbits(expr->op == SPECIAL_INCREMENT ? "inc" : "dec",
1180 expr->ctype->bit_size));
1182 if (postop) {
1183 struct storage *new = new_pseudo();
1185 emit_copy(addr, expr->unop->ctype, new, NULL);
1187 retval = new;
1188 } else
1189 retval = addr;
1191 insn(opname, addr, NULL, NULL);
1193 return retval;
1196 static struct storage *emit_postop(struct expression *expr)
1198 return emit_inc_dec(expr, 1);
1201 static struct storage *emit_return_stmt(struct statement *stmt)
1203 struct function *f = current_func;
1204 struct expression *expr = stmt->ret_value;
1205 struct storage *val = NULL, *jmplbl;
1207 if (expr && expr->ctype) {
1208 val = x86_expression(expr);
1209 assert(val != NULL);
1210 emit_move(val, REG_EAX, expr->ctype, "return");
1213 jmplbl = new_storage(STOR_LABEL);
1214 jmplbl->flags |= STOR_WANTS_FREE;
1215 jmplbl->label = f->ret_target;
1216 insn("jmp", jmplbl, NULL, NULL);
1218 return val;
1221 static struct storage *emit_conditional_expr(struct expression *expr)
1223 struct storage *cond = x86_expression(expr->conditional);
1224 struct storage *true = x86_expression(expr->cond_true);
1225 struct storage *false = x86_expression(expr->cond_false);
1226 struct storage *new = new_pseudo();
1228 if (!true)
1229 true = cond;
1231 emit_move(cond, REG_EAX, expr->conditional->ctype,
1232 "begin EXPR_CONDITIONAL");
1233 emit_move(true, REG_ECX, expr->cond_true->ctype, NULL);
1234 emit_move(false, REG_EDX, expr->cond_false->ctype, NULL);
1236 /* test EAX (for zero/non-zero) */
1237 insn("test", REG_EAX, REG_EAX, NULL);
1239 /* if false, move EDX to ECX */
1240 insn("cmovz", REG_EDX, REG_ECX, NULL);
1242 /* finally, store the result (ECX) in a new pseudo / stack slot */
1243 new = new_pseudo();
1244 emit_move(REG_ECX, new, expr->ctype, "end EXPR_CONDITIONAL");
1245 /* FIXME: we lose type knowledge of expression result at this point */
1247 return new;
1250 static struct storage *emit_symbol_expr_init(struct symbol *sym)
1252 struct expression *expr = sym->initializer;
1253 struct symbol_private *priv = sym->aux;
1255 if (priv == NULL) {
1256 priv = calloc(1, sizeof(*priv));
1257 sym->aux = priv;
1259 if (expr == NULL) {
1260 struct storage *new = new_pseudo();
1261 fprintf(stderr, "FIXME! no value for symbol. creating pseudo %d (stack offset %d)\n",
1262 new->pseudo, new->pseudo * 4);
1263 priv->addr = new;
1264 } else {
1265 priv->addr = x86_expression(expr);
1269 return priv->addr;
1272 static struct storage *emit_string_expr(struct expression *expr)
1274 struct function *f = current_func;
1275 int label = new_label();
1276 struct storage *new;
1278 push_cstring(f, expr->string, label);
1280 new = new_storage(STOR_LABEL);
1281 new->label = label;
1282 new->flags = STOR_LABEL_VAL | STOR_WANTS_FREE;
1283 return new;
1286 static struct storage *emit_cast_expr(struct expression *expr)
1288 struct symbol *old_type, *new_type;
1289 struct storage *op = x86_expression(expr->cast_expression);
1290 int oldbits, newbits;
1291 struct storage *new;
1293 old_type = expr->cast_expression->ctype;
1294 new_type = expr->cast_type;
1296 oldbits = old_type->bit_size;
1297 newbits = new_type->bit_size;
1298 if (oldbits >= newbits)
1299 return op;
1301 emit_move(op, REG_EAX, old_type, "begin cast ..");
1303 new = new_pseudo();
1304 emit_move(REG_EAX, new, new_type, ".... end cast");
1306 return new;
1309 static struct storage *emit_regular_preop(struct expression *expr)
1311 struct storage *target = x86_expression(expr->unop);
1312 struct storage *val, *new = new_pseudo();
1313 const char *opname = NULL;
1315 switch (expr->op) {
1316 case '!':
1317 val = new_storage(STOR_VALUE);
1318 val->flags = STOR_WANTS_FREE;
1319 emit_move(val, REG_EDX, NULL, NULL);
1320 emit_move(target, REG_EAX, expr->unop->ctype, NULL);
1321 insn("test", REG_EAX, REG_EAX, NULL);
1322 insn("setz", REG_DL, NULL, NULL);
1323 emit_move(REG_EDX, new, expr->unop->ctype, NULL);
1325 break;
1326 case '~':
1327 opname = "not";
1328 case '-':
1329 if (!opname)
1330 opname = "neg";
1331 emit_move(target, REG_EAX, expr->unop->ctype, NULL);
1332 insn(opname, REG_EAX, NULL, NULL);
1333 emit_move(REG_EAX, new, expr->unop->ctype, NULL);
1334 break;
1335 default:
1336 assert(0);
1337 break;
1340 return new;
1343 static void emit_case_statement(struct statement *stmt)
1345 emit_labelsym(stmt->case_label, NULL);
1346 x86_statement(stmt->case_statement);
1349 static void emit_switch_statement(struct statement *stmt)
1351 struct storage *val = x86_expression(stmt->switch_expression);
1352 struct symbol *sym, *default_sym = NULL;
1353 struct storage *labelsym, *label;
1354 int switch_end = 0;
1356 emit_move(val, REG_EAX, stmt->switch_expression->ctype, "begin case");
1359 * This is where a _real_ back-end would go through the
1360 * cases to decide whether to use a lookup table or a
1361 * series of comparisons etc
1363 FOR_EACH_PTR(stmt->switch_case->symbol_list, sym) {
1364 struct statement *case_stmt = sym->stmt;
1365 struct expression *expr = case_stmt->case_expression;
1366 struct expression *to = case_stmt->case_to;
1368 /* default: */
1369 if (!expr)
1370 default_sym = sym;
1372 /* case NNN: */
1373 else {
1374 struct storage *case_val = new_val(expr->value);
1376 assert (expr->type == EXPR_VALUE);
1378 insn("cmpl", case_val, REG_EAX, NULL);
1380 if (!to) {
1381 labelsym = new_labelsym(sym);
1382 insn("je", labelsym, NULL, NULL);
1383 } else {
1384 int next_test;
1386 label = new_storage(STOR_LABEL);
1387 label->flags |= STOR_WANTS_FREE;
1388 label->label = next_test = new_label();
1390 /* FIXME: signed/unsigned */
1391 insn("jl", label, NULL, NULL);
1393 case_val = new_val(to->value);
1394 insn("cmpl", case_val, REG_EAX, NULL);
1396 /* TODO: implement and use refcounting... */
1397 label = new_storage(STOR_LABEL);
1398 label->flags |= STOR_WANTS_FREE;
1399 label->label = next_test;
1401 /* FIXME: signed/unsigned */
1402 insn("jg", label, NULL, NULL);
1404 labelsym = new_labelsym(sym);
1405 insn("jmp", labelsym, NULL, NULL);
1407 emit_label(next_test, NULL);
1410 } END_FOR_EACH_PTR;
1412 if (default_sym) {
1413 labelsym = new_labelsym(default_sym);
1414 insn("jmp", labelsym, NULL, "default");
1415 } else {
1416 label = new_storage(STOR_LABEL);
1417 label->flags |= STOR_WANTS_FREE;
1418 label->label = switch_end = new_label();
1419 insn("jmp", label, NULL, "goto end of switch");
1422 x86_statement(stmt->switch_statement);
1424 if (stmt->switch_break->used)
1425 emit_labelsym(stmt->switch_break, NULL);
1427 if (switch_end)
1428 emit_label(switch_end, NULL);
1431 static void x86_struct_member(struct symbol *sym, void *data, int flags)
1433 if (flags & ITERATE_FIRST)
1434 printf(" {\n\t");
1435 printf("%s:%d:%ld at offset %ld", show_ident(sym->ident), sym->bit_size, sym->ctype.alignment, sym->offset);
1436 if (sym->fieldwidth)
1437 printf("[%d..%d]", sym->bit_offset, sym->bit_offset+sym->fieldwidth-1);
1438 if (flags & ITERATE_LAST)
1439 printf("\n} ");
1440 else
1441 printf(", ");
1444 static void x86_symbol(struct symbol *sym)
1446 struct symbol *type;
1448 if (!sym)
1449 return;
1451 type = sym->ctype.base_type;
1452 if (!type)
1453 return;
1456 * Show actual implementation information
1458 switch (type->type) {
1460 case SYM_ARRAY:
1461 if (sym->initializer)
1462 emit_array(sym);
1463 else
1464 emit_array_noinit(sym);
1465 break;
1467 case SYM_BASETYPE:
1468 if (sym->initializer) {
1469 emit_object_pre(show_ident(sym->ident),
1470 sym->ctype.modifiers,
1471 sym->ctype.alignment,
1472 sym->bit_size / 8);
1473 emit_scalar(sym->initializer, sym->bit_size);
1474 stor_sym_init(sym);
1475 } else
1476 emit_scalar_noinit(sym);
1477 break;
1479 case SYM_STRUCT:
1480 symbol_iterate(type->symbol_list, x86_struct_member, NULL);
1481 break;
1483 case SYM_UNION:
1484 symbol_iterate(type->symbol_list, x86_struct_member, NULL);
1485 break;
1487 case SYM_FN: {
1488 struct statement *stmt = type->stmt;
1489 if (stmt) {
1490 emit_func_pre(sym);
1491 x86_statement(stmt);
1492 emit_func_post(sym);
1494 break;
1497 default:
1498 break;
1501 if (sym->initializer && (type->type != SYM_BASETYPE) &&
1502 (type->type != SYM_ARRAY)) {
1503 printf(" = \n");
1504 x86_expression(sym->initializer);
1508 static void x86_symbol_init(struct symbol *sym);
1510 static void x86_symbol_decl(struct symbol_list *syms)
1512 struct symbol *sym;
1513 FOR_EACH_PTR(syms, sym) {
1514 x86_symbol_init(sym);
1515 } END_FOR_EACH_PTR;
1518 static void x86_loop(struct statement *stmt)
1520 struct statement *pre_statement = stmt->iterator_pre_statement;
1521 struct expression *pre_condition = stmt->iterator_pre_condition;
1522 struct statement *statement = stmt->iterator_statement;
1523 struct statement *post_statement = stmt->iterator_post_statement;
1524 struct expression *post_condition = stmt->iterator_post_condition;
1525 int loop_top = 0, loop_bottom = 0;
1526 struct storage *val;
1528 x86_symbol_decl(stmt->iterator_syms);
1529 x86_statement(pre_statement);
1530 if (pre_condition) {
1531 if (pre_condition->type == EXPR_VALUE) {
1532 if (!pre_condition->value) {
1533 loop_bottom = new_label();
1534 printf("\tjmp\t\t.L%d\n", loop_bottom);
1536 } else {
1537 loop_bottom = new_label();
1538 val = x86_expression(pre_condition);
1539 printf("\tje\t\tv%d, .L%d\n", val->pseudo, loop_bottom);
1542 if (!post_condition || post_condition->type != EXPR_VALUE || post_condition->value) {
1543 loop_top = new_label();
1544 printf(".L%d:\n", loop_top);
1546 x86_statement(statement);
1547 if (stmt->iterator_continue->used)
1548 printf(".L%p:\n", stmt->iterator_continue);
1549 x86_statement(post_statement);
1550 if (!post_condition) {
1551 printf("\tjmp\t\t.L%d\n", loop_top);
1552 } else if (post_condition->type == EXPR_VALUE) {
1553 if (post_condition->value)
1554 printf("\tjmp\t\t.L%d\n", loop_top);
1555 } else {
1556 val = x86_expression(post_condition);
1557 printf("\tjne\t\tv%d, .L%d\n", val->pseudo, loop_top);
1559 if (stmt->iterator_break->used)
1560 printf(".L%p:\n", stmt->iterator_break);
1561 if (loop_bottom)
1562 printf(".L%d:\n", loop_bottom);
1566 * Print out a statement
1568 static struct storage *x86_statement(struct statement *stmt)
1570 if (!stmt)
1571 return 0;
1572 switch (stmt->type) {
1573 case STMT_RETURN:
1574 return emit_return_stmt(stmt);
1575 case STMT_COMPOUND: {
1576 struct statement *s;
1577 struct storage *last = NULL;
1579 x86_symbol_decl(stmt->syms);
1580 FOR_EACH_PTR(stmt->stmts, s) {
1581 last = x86_statement(s);
1582 } END_FOR_EACH_PTR;
1584 return last;
1587 case STMT_EXPRESSION:
1588 return x86_expression(stmt->expression);
1589 case STMT_IF:
1590 emit_if_conditional(stmt);
1591 return NULL;
1593 case STMT_CASE:
1594 emit_case_statement(stmt);
1595 break;
1596 case STMT_SWITCH:
1597 emit_switch_statement(stmt);
1598 break;
1600 case STMT_ITERATOR:
1601 x86_loop(stmt);
1602 break;
1604 case STMT_NONE:
1605 break;
1607 case STMT_LABEL:
1608 printf(".L%p:\n", stmt->label_identifier);
1609 x86_statement(stmt->label_statement);
1610 break;
1612 case STMT_GOTO:
1613 if (stmt->goto_expression) {
1614 struct storage *val = x86_expression(stmt->goto_expression);
1615 printf("\tgoto *v%d\n", val->pseudo);
1616 } else {
1617 struct storage *labelsym = new_labelsym(stmt->goto_label);
1618 insn("jmp", labelsym, NULL, NULL);
1620 break;
1621 case STMT_ASM:
1622 printf("\tasm( .... )\n");
1623 break;
1626 return NULL;
1629 static struct storage *x86_call_expression(struct expression *expr)
1631 struct function *f = current_func;
1632 struct symbol *direct;
1633 struct expression *arg, *fn;
1634 struct storage *retval, *fncall;
1635 int framesize;
1636 char s[64];
1638 if (!expr->ctype) {
1639 warn(expr->pos, "\tcall with no type!");
1640 return NULL;
1643 framesize = 0;
1644 FOR_EACH_PTR_REVERSE(expr->args, arg) {
1645 struct storage *new = x86_expression(arg);
1646 int size = arg->ctype->bit_size;
1648 /* FIXME: pay attention to 'size' */
1649 insn("pushl", new, NULL,
1650 !framesize ? "begin function call" : NULL);
1652 framesize += size >> 3;
1653 } END_FOR_EACH_PTR_REVERSE;
1655 fn = expr->fn;
1657 /* Remove dereference, if any */
1658 direct = NULL;
1659 if (fn->type == EXPR_PREOP) {
1660 if (fn->unop->type == EXPR_SYMBOL) {
1661 struct symbol *sym = fn->unop->symbol;
1662 if (sym->ctype.base_type->type == SYM_FN)
1663 direct = sym;
1666 if (direct) {
1667 struct storage *direct_stor = new_storage(STOR_SYM);
1668 direct_stor->flags |= STOR_WANTS_FREE;
1669 direct_stor->sym = direct;
1670 insn("call", direct_stor, NULL, NULL);
1671 } else {
1672 fncall = x86_expression(fn);
1673 emit_move(fncall, REG_EAX, fn->ctype, NULL);
1675 strcpy(s, "\tcall\t*%eax\n");
1676 push_text_atom(f, s);
1679 /* FIXME: pay attention to BITS_IN_POINTER */
1680 if (framesize) {
1681 struct storage *val = new_storage(STOR_VALUE);
1682 val->value = (long long) framesize;
1683 val->flags = STOR_WANTS_FREE;
1684 insn("addl", val, REG_ESP, NULL);
1687 retval = new_pseudo();
1688 emit_move(REG_EAX, retval, NULL, "end function call");
1690 return retval;
1693 static struct storage *x86_address_gen(struct expression *expr)
1695 struct function *f = current_func;
1696 struct storage *addr;
1697 struct storage *new;
1698 char s[32];
1700 if ((expr->type != EXPR_PREOP) || (expr->op != '*'))
1701 return x86_expression(expr->address);
1703 addr = x86_expression(expr->unop);
1704 if (expr->unop->type == EXPR_SYMBOL)
1705 return addr;
1707 emit_move(addr, REG_EAX, NULL, "begin deref ..");
1709 /* FIXME: operand size */
1710 strcpy(s, "\tmovl\t(%eax), %ecx\n");
1711 push_text_atom(f, s);
1713 new = new_pseudo();
1714 emit_move(REG_ECX, new, NULL, ".... end deref");
1716 return new;
1719 static struct storage *x86_assignment(struct expression *expr)
1721 struct expression *target = expr->left;
1722 struct storage *val, *addr;
1723 int bits;
1725 if (!expr->ctype)
1726 return NULL;
1728 bits = expr->ctype->bit_size;
1729 val = x86_expression(expr->right);
1730 addr = x86_address_gen(target);
1732 switch (val->type) {
1733 /* copy, where both operands are memory */
1734 case STOR_PSEUDO:
1735 case STOR_ARG:
1736 emit_copy(val, expr->right->ctype, addr, expr->left->ctype);
1737 break;
1739 /* copy, one or zero operands are memory */
1740 case STOR_REG:
1741 case STOR_SYM:
1742 case STOR_VALUE:
1743 case STOR_LABEL:
1744 emit_move(val, addr, expr->left->ctype, NULL);
1745 break;
1747 case STOR_LABELSYM:
1748 assert(0);
1749 break;
1751 return val;
1754 static int x86_initialization(struct symbol *sym, struct expression *expr)
1756 struct storage *val, *addr;
1757 int bits;
1759 if (!expr->ctype)
1760 return 0;
1762 bits = expr->ctype->bit_size;
1763 val = x86_expression(expr);
1764 addr = x86_symbol_expr(sym);
1765 // FIXME! The "target" expression is for bitfield store information.
1766 // Leave it NULL, which works fine.
1767 emit_store(NULL, addr, val, bits);
1768 return 0;
1771 static struct storage *x86_access(struct expression *expr)
1773 return x86_address_gen(expr);
1776 static struct storage *x86_preop(struct expression *expr)
1779 * '*' is an lvalue access, and is fundamentally different
1780 * from an arithmetic operation. Maybe it should have an
1781 * expression type of its own..
1783 if (expr->op == '*')
1784 return x86_access(expr);
1785 if (expr->op == SPECIAL_INCREMENT || expr->op == SPECIAL_DECREMENT)
1786 return emit_inc_dec(expr, 0);
1787 return emit_regular_preop(expr);
1790 static struct storage *x86_symbol_expr(struct symbol *sym)
1792 struct storage *new = new_pseudo();
1794 if (sym->ctype.modifiers & (MOD_TOPLEVEL | MOD_EXTERN | MOD_STATIC)) {
1795 printf("\tmovi.%d\t\tv%d,$%s\n", BITS_IN_POINTER, new->pseudo, show_ident(sym->ident));
1796 return new;
1798 if (sym->ctype.modifiers & MOD_ADDRESSABLE) {
1799 printf("\taddi.%d\t\tv%d,vFP,$%lld\n", BITS_IN_POINTER, new->pseudo, sym->value);
1800 return new;
1802 printf("\taddi.%d\t\tv%d,vFP,$offsetof(%s:%p)\n", BITS_IN_POINTER, new->pseudo, show_ident(sym->ident), sym);
1803 return new;
1806 static void x86_symbol_init(struct symbol *sym)
1808 struct symbol_private *priv = sym->aux;
1809 struct expression *expr = sym->initializer;
1810 struct storage *new;
1812 if (expr)
1813 new = x86_expression(expr);
1814 else
1815 new = new_pseudo();
1817 if (!priv) {
1818 priv = calloc(1, sizeof(*priv));
1819 sym->aux = priv;
1820 /* FIXME: leak! we don't free... */
1821 /* (well, we don't free symbols either) */
1824 priv->addr = new;
1827 static int type_is_signed(struct symbol *sym)
1829 if (sym->type == SYM_NODE)
1830 sym = sym->ctype.base_type;
1831 if (sym->type == SYM_PTR)
1832 return 0;
1833 return !(sym->ctype.modifiers & MOD_UNSIGNED);
1836 static struct storage *x86_bitfield_expr(struct expression *expr)
1838 return x86_access(expr);
1841 static struct storage *x86_label_expr(struct expression *expr)
1843 struct storage *new = new_pseudo();
1844 printf("\tmovi.%d\t\tv%d,.L%p\n",BITS_IN_POINTER, new->pseudo, expr->label_symbol);
1845 return new;
1848 static struct storage *x86_statement_expr(struct expression *expr)
1850 return x86_statement(expr->statement);
1853 static int x86_position_expr(struct expression *expr, struct symbol *base)
1855 struct storage *new = x86_expression(expr->init_expr);
1856 struct symbol *ctype = expr->init_sym;
1858 printf("\tinsert v%d at [%d:%d] of %s\n", new->pseudo,
1859 expr->init_offset, ctype->bit_offset,
1860 show_ident(base->ident));
1861 return 0;
1864 static void x86_initializer_expr(struct expression *expr, struct symbol *ctype)
1866 struct expression *entry;
1868 FOR_EACH_PTR(expr->expr_list, entry) {
1869 // Nested initializers have their positions already
1870 // recursively calculated - just output them too
1871 if (entry->type == EXPR_INITIALIZER) {
1872 x86_initializer_expr(entry, ctype);
1873 continue;
1876 // Ignore initializer indexes and identifiers - the
1877 // evaluator has taken them into account
1878 if (entry->type == EXPR_IDENTIFIER || entry->type == EXPR_INDEX)
1879 continue;
1880 if (entry->type == EXPR_POS) {
1881 x86_position_expr(entry, ctype);
1882 continue;
1884 x86_initialization(ctype, entry);
1885 } END_FOR_EACH_PTR;
1889 * Print out an expression. Return the pseudo that contains the
1890 * variable.
1892 static struct storage *x86_expression(struct expression *expr)
1894 if (!expr)
1895 return 0;
1897 if (!expr->ctype) {
1898 struct position *pos = &expr->pos;
1899 printf("\tno type at %s:%d:%d\n",
1900 input_streams[pos->stream].name,
1901 pos->line, pos->pos);
1902 return 0;
1905 switch (expr->type) {
1906 case EXPR_CALL:
1907 return x86_call_expression(expr);
1909 case EXPR_ASSIGNMENT:
1910 return x86_assignment(expr);
1912 case EXPR_COMPARE:
1913 return emit_compare(expr);
1914 case EXPR_BINOP:
1915 case EXPR_COMMA:
1916 case EXPR_LOGICAL:
1917 return emit_binop(expr);
1918 case EXPR_PREOP:
1919 return x86_preop(expr);
1920 case EXPR_POSTOP:
1921 return emit_postop(expr);
1922 case EXPR_SYMBOL:
1923 return emit_symbol_expr_init(expr->symbol);
1924 case EXPR_DEREF:
1925 case EXPR_SIZEOF:
1926 warn(expr->pos, "invalid expression after evaluation");
1927 return 0;
1928 case EXPR_CAST:
1929 return emit_cast_expr(expr);
1930 case EXPR_VALUE:
1931 return emit_value(expr);
1932 case EXPR_STRING:
1933 return emit_string_expr(expr);
1934 case EXPR_BITFIELD:
1935 return x86_bitfield_expr(expr);
1936 case EXPR_INITIALIZER:
1937 x86_initializer_expr(expr, expr->ctype);
1938 return NULL;
1939 case EXPR_CONDITIONAL:
1940 return emit_conditional_expr(expr);
1941 case EXPR_STATEMENT:
1942 return x86_statement_expr(expr);
1943 case EXPR_LABEL:
1944 return x86_label_expr(expr);
1946 // None of these should exist as direct expressions: they are only
1947 // valid as sub-expressions of initializers.
1948 case EXPR_POS:
1949 warn(expr->pos, "unable to show plain initializer position expression");
1950 return 0;
1951 case EXPR_IDENTIFIER:
1952 warn(expr->pos, "unable to show identifier expression");
1953 return 0;
1954 case EXPR_INDEX:
1955 warn(expr->pos, "unable to show index expression");
1956 return 0;
1958 return 0;