Merge kernel.bkbits.net:sparse.be into redhat.com:/garz/repo/sparse.be
[smatch.git] / compile-i386.c
blob1920ddcc6535f1a9a67ee3ec9a4be2aed8b9f3ae
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 int pseudo_nr;
55 struct ptr_list *pseudo_list;
56 struct ptr_list *atom_list;
57 struct ptr_list *str_list;
58 struct symbol **argv;
59 unsigned int argc;
60 int ret_target;
63 enum storage_type {
64 STOR_PSEUDO, /* variable stored on the stack */
65 STOR_ARG, /* function argument */
66 STOR_SYM, /* a symbol we can directly ref in the asm */
67 STOR_REG, /* scratch register */
68 STOR_VALUE, /* integer constant */
69 STOR_LABEL, /* label / jump target */
70 STOR_LABELSYM, /* label generated from symbol's pointer value */
73 struct reg_info {
74 const char *name;
77 struct storage {
78 enum storage_type type;
79 unsigned long flags;
81 /* STOR_REG */
82 struct reg_info *reg;
84 union {
85 /* STOR_PSEUDO */
86 struct {
87 int pseudo;
88 int offset;
89 int size;
91 /* STOR_ARG */
92 struct {
93 int idx;
95 /* STOR_SYM */
96 struct {
97 struct symbol *sym;
99 /* STOR_VALUE */
100 struct {
101 long long value;
103 /* STOR_LABEL */
104 struct {
105 int label;
107 /* STOR_LABELSYM */
108 struct {
109 struct symbol *labelsym;
114 enum {
115 STOR_LABEL_VAL = (1 << 0),
116 STOR_WANTS_FREE = (1 << 1),
119 struct symbol_private {
120 struct storage *addr;
123 enum atom_type {
124 ATOM_TEXT,
125 ATOM_INSN,
126 ATOM_CSTR,
129 struct atom {
130 enum atom_type type;
131 union {
132 /* stuff for text */
133 struct {
134 char *text;
135 unsigned int text_len; /* w/o terminating null */
138 /* stuff for insns */
139 struct {
140 char insn[32];
141 char comment[40];
142 struct storage *op1;
143 struct storage *op2;
146 /* stuff for C strings */
147 struct {
148 struct string *string;
149 int label;
155 struct function *current_func = NULL;
156 struct textbuf *unit_post_text = NULL;
157 static const char *current_section;
159 static struct reg_info reg_info_table[] = {
160 { "%eax" },
161 { "%ecx" },
162 { "%edx" },
163 { "%esp" },
164 { "%dl" },
167 static struct storage hardreg_storage_table[] = {
168 { /* eax */
169 .type = STOR_REG,
170 .reg = &reg_info_table[0],
173 { /* ecx */
174 .type = STOR_REG,
175 .reg = &reg_info_table[1],
178 { /* edx */
179 .type = STOR_REG,
180 .reg = &reg_info_table[2],
183 { /* esp */
184 .type = STOR_REG,
185 .reg = &reg_info_table[3],
188 { /* dl */
189 .type = STOR_REG,
190 .reg = &reg_info_table[4],
194 #define REG_EAX (&hardreg_storage_table[0])
195 #define REG_ECX (&hardreg_storage_table[1])
196 #define REG_EDX (&hardreg_storage_table[2])
197 #define REG_ESP (&hardreg_storage_table[3])
198 #define REG_DL (&hardreg_storage_table[4])
201 static void emit_move(struct storage *src, struct storage *dest,
202 struct symbol *ctype, const char *comment);
203 static int type_is_signed(struct symbol *sym);
204 static struct storage *x86_address_gen(struct expression *expr);
205 static struct storage *x86_symbol_expr(struct symbol *sym);
206 static void x86_symbol(struct symbol *sym);
207 static struct storage *x86_statement(struct statement *stmt);
208 static struct storage *x86_expression(struct expression *expr);
211 static inline unsigned int pseudo_offset(struct storage *s)
213 if (s->type != STOR_PSEUDO)
214 return 123456; /* intentionally bogus value */
216 return s->offset;
219 static inline unsigned int arg_offset(struct storage *s)
221 if (s->type != STOR_ARG)
222 return 123456; /* intentionally bogus value */
224 /* FIXME: this is wrong wrong wrong */
225 return current_func->stack_size + ((1 + s->idx) * 4);
228 static const char *pretty_offset(int ofs)
230 static char esp_buf[64];
232 if (ofs)
233 sprintf(esp_buf, "%d(%%esp)", ofs);
234 else
235 strcpy(esp_buf, "(%esp)");
237 return esp_buf;
240 static void stor_sym_init(struct symbol *sym)
242 struct storage *stor;
243 struct symbol_private *priv;
245 priv = calloc(1, sizeof(*priv) + sizeof(*stor));
246 if (!priv)
247 die("OOM in stor_sym_init");
249 stor = (struct storage *) (priv + 1);
251 priv->addr = stor;
252 stor->type = STOR_SYM;
253 stor->sym = sym;
256 static const char *stor_op_name(struct storage *s)
258 static char name[32];
260 switch (s->type) {
261 case STOR_PSEUDO:
262 strcpy(name, pretty_offset((int) pseudo_offset(s)));
263 break;
264 case STOR_ARG:
265 strcpy(name, pretty_offset((int) arg_offset(s)));
266 break;
267 case STOR_SYM:
268 strcpy(name, show_ident(s->sym->ident));
269 break;
270 case STOR_REG:
271 strcpy(name, s->reg->name);
272 break;
273 case STOR_VALUE:
274 sprintf(name, "$%Ld", s->value);
275 break;
276 case STOR_LABEL:
277 sprintf(name, "%s.L%d", s->flags & STOR_LABEL_VAL ? "$" : "",
278 s->label);
279 break;
280 case STOR_LABELSYM:
281 sprintf(name, "%s.LS%p", s->flags & STOR_LABEL_VAL ? "$" : "",
282 s->labelsym);
283 break;
286 return name;
289 static struct atom *new_atom(enum atom_type type)
291 struct atom *atom;
293 atom = calloc(1, sizeof(*atom)); /* TODO: chunked alloc */
294 if (!atom)
295 die("nuclear OOM");
297 atom->type = type;
299 return atom;
302 static inline void push_cstring(struct function *f, struct string *str,
303 int label)
305 struct atom *atom;
307 atom = new_atom(ATOM_CSTR);
308 atom->string = str;
309 atom->label = label;
311 add_ptr_list(&f->str_list, atom); /* note: _not_ atom_list */
314 static inline void push_atom(struct function *f, struct atom *atom)
316 add_ptr_list(&f->atom_list, atom);
319 static void push_text_atom(struct function *f, const char *text)
321 struct atom *atom = new_atom(ATOM_TEXT);
323 atom->text = strdup(text);
324 atom->text_len = strlen(text);
326 push_atom(f, atom);
329 static struct storage *new_storage(enum storage_type type)
331 struct storage *stor;
333 stor = calloc(1, sizeof(*stor));
334 if (!stor)
335 die("OOM in new_storage");
337 stor->type = type;
339 return stor;
342 static struct storage *stack_alloc(int n_bytes)
344 struct function *f = current_func;
345 struct storage *stor;
347 assert(f != NULL);
349 stor = new_storage(STOR_PSEUDO);
350 stor->type = STOR_PSEUDO;
351 stor->pseudo = f->pseudo_nr;
352 stor->offset = f->stack_size;
353 stor->size = n_bytes;
354 f->stack_size += n_bytes;
355 f->pseudo_nr++;
357 add_ptr_list(&f->pseudo_list, stor);
359 return stor;
362 static struct storage *new_labelsym(struct symbol *sym)
364 struct storage *stor;
366 stor = new_storage(STOR_LABELSYM);
368 if (stor) {
369 stor->flags |= STOR_WANTS_FREE;
370 stor->labelsym = sym;
373 return stor;
376 static struct storage *new_val(long long value)
378 struct storage *stor;
380 stor = new_storage(STOR_VALUE);
382 if (stor) {
383 stor->flags |= STOR_WANTS_FREE;
384 stor->value = value;
387 return stor;
390 static int new_label(void)
392 static int label = 0;
393 return ++label;
396 static void textbuf_push(struct textbuf **buf_p, const char *text)
398 struct textbuf *tmp, *list = *buf_p;
399 unsigned int text_len = strlen(text);
400 unsigned int alloc_len = text_len + 1 + sizeof(*list);
402 tmp = calloc(1, alloc_len);
403 if (!tmp)
404 die("OOM on textbuf alloc");
406 tmp->text = ((void *) tmp) + sizeof(*tmp);
407 memcpy(tmp->text, text, text_len + 1);
408 tmp->len = text_len;
410 /* add to end of list */
411 if (!list) {
412 list = tmp;
413 tmp->prev = tmp;
414 } else {
415 tmp->prev = list->prev;
416 tmp->prev->next = tmp;
417 list->prev = tmp;
419 tmp->next = list;
421 *buf_p = list;
424 static void textbuf_emit(struct textbuf **buf_p)
426 struct textbuf *tmp, *list = *buf_p;
428 while (list) {
429 tmp = list;
430 if (tmp->next == tmp)
431 list = NULL;
432 else {
433 tmp->prev->next = tmp->next;
434 tmp->next->prev = tmp->prev;
435 list = tmp->next;
438 fputs(tmp->text, stdout);
440 free(tmp);
443 *buf_p = list;
446 static void insn(const char *insn, struct storage *op1, struct storage *op2,
447 const char *comment_in)
449 struct function *f = current_func;
450 struct atom *atom = new_atom(ATOM_INSN);
452 assert(insn != NULL);
454 strcpy(atom->insn, insn);
455 if (comment_in && (*comment_in))
456 strncpy(atom->comment, comment_in,
457 sizeof(atom->comment) - 1);
459 atom->op1 = op1;
460 atom->op2 = op2;
462 push_atom(f, atom);
465 static void emit_label (int label, const char *comment)
467 struct function *f = current_func;
468 char s[64];
470 if (!comment)
471 sprintf(s, ".L%d:\n", label);
472 else
473 sprintf(s, ".L%d:\t\t\t\t\t# %s\n", label, comment);
475 push_text_atom(f, s);
478 static void emit_labelsym (struct symbol *sym, const char *comment)
480 struct function *f = current_func;
481 char s[64];
483 if (!comment)
484 sprintf(s, ".LS%p:\n", sym);
485 else
486 sprintf(s, ".LS%p:\t\t\t\t# %s\n", sym, comment);
488 push_text_atom(f, s);
491 static void emit_unit_pre(const char *basename)
493 printf("\t.file\t\"%s\"\n", basename);
496 static void emit_unit_post(void)
498 textbuf_emit(&unit_post_text);
499 printf("\t.ident\t\"sparse silly x86 backend (built %s)\"\n", __DATE__);
502 /* conditionally switch sections */
503 static void emit_section(const char *s)
505 if (s == current_section)
506 return;
507 if (current_section && (!strcmp(s, current_section)))
508 return;
510 printf("\t%s\n", s);
511 current_section = s;
514 static void emit_insn_atom(struct function *f, struct atom *atom)
516 char s[128];
517 char comment[64];
518 struct storage *op1 = atom->op1;
519 struct storage *op2 = atom->op2;
521 if (atom->comment[0])
522 sprintf(comment, "\t\t# %s", atom->comment);
523 else
524 comment[0] = 0;
526 if (atom->op2) {
527 char tmp[16];
528 strcpy(tmp, stor_op_name(op1));
529 sprintf(s, "\t%s\t%s, %s%s\n",
530 atom->insn, tmp, stor_op_name(op2), comment);
531 } else if (atom->op1)
532 sprintf(s, "\t%s\t%s%s%s\n",
533 atom->insn, stor_op_name(op1),
534 comment[0] ? "\t" : "", comment);
535 else
536 sprintf(s, "\t%s\t%s%s\n",
537 atom->insn,
538 comment[0] ? "\t\t" : "", comment);
540 write(STDOUT_FILENO, s, strlen(s));
543 static void emit_atom_list(struct function *f)
545 struct atom *atom;
547 FOR_EACH_PTR(f->atom_list, atom) {
548 switch (atom->type) {
549 case ATOM_TEXT: {
550 ssize_t rc = write(STDOUT_FILENO, atom->text,
551 atom->text_len);
552 (void) rc; /* FIXME */
553 break;
555 case ATOM_INSN:
556 emit_insn_atom(f, atom);
557 break;
558 case ATOM_CSTR:
559 assert(0);
560 break;
562 } END_FOR_EACH_PTR;
565 static void emit_string_list(struct function *f)
567 struct atom *atom;
569 emit_section(".section\t.rodata");
571 FOR_EACH_PTR(f->str_list, atom) {
572 /* FIXME: escape " in string */
573 printf(".L%d:\n", atom->label);
574 printf("\t.string\t%s\n", show_string(atom->string));
576 free(atom);
577 } END_FOR_EACH_PTR;
580 static void func_cleanup(struct function *f)
582 struct storage *stor;
583 struct atom *atom;
585 FOR_EACH_PTR(f->pseudo_list, stor) {
586 free(stor);
587 } END_FOR_EACH_PTR;
589 FOR_EACH_PTR(f->atom_list, atom) {
590 if ((atom->type == ATOM_TEXT) && (atom->text))
591 free(atom->text);
592 if (atom->op1 && (atom->op1->flags & STOR_WANTS_FREE))
593 free(atom->op1);
594 if (atom->op2 && (atom->op2->flags & STOR_WANTS_FREE))
595 free(atom->op2);
596 free(atom);
597 } END_FOR_EACH_PTR;
599 free_ptr_list(&f->pseudo_list);
600 free(f);
603 /* function prologue */
604 static void emit_func_pre(struct symbol *sym)
606 struct function *f;
607 struct symbol *arg;
608 unsigned int i, argc = 0, alloc_len;
609 unsigned char *mem;
610 struct symbol_private *privbase;
611 struct storage *storage_base;
612 struct symbol *base_type = sym->ctype.base_type;
614 FOR_EACH_PTR(base_type->arguments, arg) {
615 argc++;
616 } END_FOR_EACH_PTR;
618 alloc_len =
619 sizeof(*f) +
620 (argc * sizeof(struct symbol *)) +
621 (argc * sizeof(struct symbol_private)) +
622 (argc * sizeof(struct storage));
623 mem = calloc(1, alloc_len);
624 if (!mem)
625 die("OOM on func info");
627 f = (struct function *) mem;
628 mem += sizeof(*f);
629 f->argv = (struct symbol **) mem;
630 mem += (argc * sizeof(struct symbol *));
631 privbase = (struct symbol_private *) mem;
632 mem += (argc * sizeof(struct symbol_private));
633 storage_base = (struct storage *) mem;
635 f->argc = argc;
636 f->ret_target = new_label();
638 i = 0;
639 FOR_EACH_PTR(base_type->arguments, arg) {
640 f->argv[i] = arg;
641 arg->aux = &privbase[i];
642 storage_base[i].type = STOR_ARG;
643 storage_base[i].idx = i;
644 privbase[i].addr = &storage_base[i];
645 i++;
646 } END_FOR_EACH_PTR;
648 assert(current_func == NULL);
649 current_func = f;
652 /* function epilogue */
653 static void emit_func_post(struct symbol *sym)
655 const char *name = show_ident(sym->ident);
656 struct function *f = current_func;
657 int stack_size = f->stack_size;
659 if (f->str_list)
660 emit_string_list(f);
662 /* function prologue */
663 emit_section(".text");
664 if ((sym->ctype.modifiers & MOD_STATIC) == 0)
665 printf(".globl %s\n", name);
666 printf("\t.type\t%s, @function\n", name);
667 printf("%s:\n", name);
669 if (stack_size) {
670 char pseudo_const[16];
672 sprintf(pseudo_const, "$%d", stack_size);
673 printf("\tsubl\t%s, %%esp\n", pseudo_const);
676 /* function epilogue */
678 /* jump target for 'return' statements */
679 emit_label(f->ret_target, NULL);
681 if (stack_size) {
682 struct storage *val;
684 val = new_storage(STOR_VALUE);
685 val->value = (long long) (stack_size);
686 val->flags = STOR_WANTS_FREE;
688 insn("addl", val, REG_ESP, NULL);
691 insn("ret", NULL, NULL, NULL);
693 /* output everything to stdout */
694 fflush(stdout); /* paranoia; needed? */
695 emit_atom_list(f);
697 /* function footer */
698 printf("\t.size\t%s, .-%s\n", name, name);
700 func_cleanup(f);
701 current_func = NULL;
704 /* emit object (a.k.a. variable, a.k.a. data) prologue */
705 static void emit_object_pre(const char *name, unsigned long modifiers,
706 unsigned long alignment, unsigned int byte_size)
708 if ((modifiers & MOD_STATIC) == 0)
709 printf(".globl %s\n", name);
710 emit_section(".data");
711 if (alignment)
712 printf("\t.align %lu\n", alignment);
713 printf("\t.type\t%s, @object\n", name);
714 printf("\t.size\t%s, %d\n", name, byte_size);
715 printf("%s:\n", name);
718 /* emit value (only) for an initializer scalar */
719 static void emit_scalar(struct expression *expr, unsigned int bit_size)
721 const char *type;
722 long long ll;
724 assert(expr->type == EXPR_VALUE);
726 if (expr->value == 0ULL) {
727 printf("\t.zero\t%d\n", bit_size / 8);
728 return;
731 ll = (long long) expr->value;
733 switch (bit_size) {
734 case 8: type = "byte"; ll = (char) ll; break;
735 case 16: type = "value"; ll = (short) ll; break;
736 case 32: type = "long"; ll = (int) ll; break;
737 case 64: type = "quad"; break;
738 default: type = NULL; break;
741 assert(type != NULL);
743 printf("\t.%s\t%Ld\n", type, ll);
746 static void emit_global_noinit(const char *name, unsigned long modifiers,
747 unsigned long alignment, unsigned int byte_size)
749 char s[64];
751 if (modifiers & MOD_STATIC) {
752 sprintf(s, "\t.local\t%s\n", name);
753 textbuf_push(&unit_post_text, s);
755 if (alignment)
756 sprintf(s, "\t.comm\t%s,%d,%lu\n", name, byte_size, alignment);
757 else
758 sprintf(s, "\t.comm\t%s,%d\n", name, byte_size);
759 textbuf_push(&unit_post_text, s);
762 static int ea_current, ea_last;
764 static void emit_initializer(struct symbol *sym,
765 struct expression *expr)
767 int distance = ea_current - ea_last - 1;
769 if (distance > 0)
770 printf("\t.zero\t%d\n", (sym->bit_size / 8) * distance);
772 if (expr->type == EXPR_VALUE) {
773 struct symbol *base_type = sym->ctype.base_type;
774 assert(base_type != NULL);
776 emit_scalar(expr, sym->bit_size / get_expression_value(base_type->array_size));
777 return;
779 if (expr->type != EXPR_INITIALIZER)
780 return;
782 assert(0); /* FIXME */
785 static int sort_array_cmp(const struct expression *a,
786 const struct expression *b)
788 int a_ofs = 0, b_ofs = 0;
790 if (a->type == EXPR_POS)
791 a_ofs = (int) a->init_offset;
792 if (b->type == EXPR_POS)
793 b_ofs = (int) b->init_offset;
795 return a_ofs - b_ofs;
798 /* move to front-end? */
799 static void sort_array(struct expression *expr)
801 struct expression *entry, **list;
802 unsigned int elem, sorted, i;
804 elem = 0;
805 FOR_EACH_PTR(expr->expr_list, entry) {
806 elem++;
807 } END_FOR_EACH_PTR;
809 if (!elem)
810 return;
812 list = malloc(sizeof(entry) * elem);
813 if (!list)
814 die("OOM in sort_array");
816 /* this code is no doubt evil and ignores EXPR_INDEX possibly
817 * to its detriment and other nasty things. improvements
818 * welcome.
820 i = 0;
821 sorted = 0;
822 FOR_EACH_PTR(expr->expr_list, entry) {
823 if ((entry->type == EXPR_POS) || (entry->type == EXPR_VALUE)) {
824 /* add entry to list[], in sorted order */
825 if (sorted == 0) {
826 list[0] = entry;
827 sorted = 1;
828 } else {
829 unsigned int i;
831 for (i = 0; i < sorted; i++)
832 if (sort_array_cmp(entry, list[i]) <= 0)
833 break;
835 /* If inserting into the middle of list[]
836 * instead of appending, we memmove.
837 * This is ugly, but thankfully
838 * uncommon. Input data with tons of
839 * entries very rarely have explicit
840 * offsets. convert to qsort eventually...
842 if (i != sorted)
843 memmove(&list[i + 1], &list[i],
844 (sorted - i) * sizeof(entry));
845 list[i] = entry;
846 sorted++;
849 } END_FOR_EACH_PTR;
851 i = 0;
852 FOR_EACH_PTR(expr->expr_list, entry) {
853 if ((entry->type == EXPR_POS) || (entry->type == EXPR_VALUE))
854 __list->list[__i] = list[i++];
855 } END_FOR_EACH_PTR;
859 static void emit_array(struct symbol *sym)
861 struct symbol *base_type = sym->ctype.base_type;
862 struct expression *expr = sym->initializer;
863 struct expression *entry;
865 assert(base_type != NULL);
867 stor_sym_init(sym);
869 ea_last = -1;
871 emit_object_pre(show_ident(sym->ident), sym->ctype.modifiers,
872 sym->ctype.alignment,
873 sym->bit_size / 8);
875 sort_array(expr);
877 FOR_EACH_PTR(expr->expr_list, entry) {
878 if (entry->type == EXPR_VALUE) {
879 ea_current = 0;
880 emit_initializer(sym, entry);
881 ea_last = ea_current;
882 } else if (entry->type == EXPR_POS) {
883 ea_current =
884 entry->init_offset / (base_type->bit_size / 8);
885 emit_initializer(sym, entry->init_expr);
886 ea_last = ea_current;
888 } END_FOR_EACH_PTR;
891 static void emit_one_symbol(struct symbol *sym, void *dummy, int flags)
893 x86_symbol(sym);
896 void emit_unit(const char *basename, struct symbol_list *list)
898 emit_unit_pre(basename);
899 symbol_iterate(list, emit_one_symbol, NULL);
900 emit_unit_post();
903 static void emit_copy(struct storage *src, struct symbol *src_ctype,
904 struct storage *dest, struct symbol *dest_ctype)
906 /* FIXME: Bitfield move! */
908 emit_move(src, REG_EAX, src_ctype, "begin copy ..");
909 emit_move(REG_EAX, dest, dest_ctype, ".... end copy");
912 static void emit_store(struct expression *dest_expr, struct storage *dest,
913 struct storage *src, int bits)
915 /* FIXME: Bitfield store! */
916 printf("\tst.%d\t\tv%d,[v%d]\n", bits, src->pseudo, dest->pseudo);
919 static void emit_scalar_noinit(struct symbol *sym)
921 emit_global_noinit(show_ident(sym->ident),
922 sym->ctype.modifiers, sym->ctype.alignment,
923 sym->bit_size / 8);
924 stor_sym_init(sym);
927 static void emit_array_noinit(struct symbol *sym)
929 emit_global_noinit(show_ident(sym->ident),
930 sym->ctype.modifiers, sym->ctype.alignment,
931 get_expression_value(sym->array_size) * (sym->bit_size / 8));
932 stor_sym_init(sym);
935 static const char *opbits(const char *insn, unsigned int bits)
937 static char opbits_str[32];
938 char c;
940 switch (bits) {
941 case 8: c = 'b'; break;
942 case 16: c = 'w'; break;
943 case 32: c = 'l'; break;
944 case 64: c = 'q'; break;
945 default: assert(0); break;
948 sprintf(opbits_str, "%s%c", insn, bits);
950 return opbits_str;
953 static void emit_move(struct storage *src, struct storage *dest,
954 struct symbol *ctype, const char *comment)
956 unsigned int bits;
957 unsigned int is_signed;
958 unsigned int is_dest = (src->type == STOR_REG);
959 const char *opname;
961 if (ctype) {
962 bits = ctype->bit_size;
963 is_signed = type_is_signed(ctype);
964 } else {
965 bits = 32;
966 is_signed = 0;
969 if ((dest->type == STOR_REG) && (src->type == STOR_REG)) {
970 insn("mov", src, dest, NULL);
971 return;
974 switch (bits) {
975 case 8:
976 if (is_dest)
977 opname = "movb";
978 else {
979 if (is_signed) opname = "movsxb";
980 else opname = "movzxb";
982 break;
983 case 16:
984 if (is_dest)
985 opname = "movw";
986 else {
987 if (is_signed) opname = "movsxw";
988 else opname = "movzxw";
990 break;
992 case 32: opname = "movl"; break;
993 case 64: opname = "movq"; break;
995 default: assert(0); break;
998 insn(opname, src, dest, comment);
1001 static struct storage *emit_compare(struct expression *expr)
1003 struct storage *left = x86_expression(expr->left);
1004 struct storage *right = x86_expression(expr->right);
1005 struct storage *new, *val;
1006 const char *opname = NULL;
1007 unsigned int is_signed = type_is_signed(expr->left->ctype); /* FIXME */
1008 unsigned int right_bits = expr->right->ctype->bit_size;
1010 switch(expr->op) {
1011 case '<':
1012 if (is_signed) opname = "setl";
1013 else opname = "setb";
1014 break;
1015 case '>':
1016 if (is_signed) opname = "setg";
1017 else opname = "seta";
1018 break;
1019 case SPECIAL_LTE:
1020 if (is_signed) opname = "setle";
1021 else opname = "setbe";
1022 break;
1023 case SPECIAL_GTE:
1024 if (is_signed) opname = "setge";
1025 else opname = "setae";
1026 break;
1028 case SPECIAL_EQUAL: opname = "sete"; break;
1029 case SPECIAL_NOTEQUAL: opname = "setne"; break;
1031 default:
1032 assert(0);
1033 break;
1036 /* init EDX to 0 */
1037 val = new_storage(STOR_VALUE);
1038 val->flags = STOR_WANTS_FREE;
1039 emit_move(val, REG_EDX, NULL, NULL);
1041 /* move op1 into EAX */
1042 emit_move(left, REG_EAX, expr->left->ctype, NULL);
1044 /* perform comparison, RHS (op1, right) and LHS (op2, EAX) */
1045 insn(opbits("cmp", right_bits), right, REG_EAX, NULL);
1047 /* store result of operation, 0 or 1, in DL using SETcc */
1048 insn(opname, REG_DL, NULL, NULL);
1050 /* finally, store the result (DL) in a new pseudo / stack slot */
1051 new = stack_alloc(4);
1052 emit_move(REG_EDX, new, NULL, "end EXPR_COMPARE");
1054 return new;
1057 static struct storage *emit_value(struct expression *expr)
1059 #if 0 /* old and slow way */
1060 struct storage *new = stack_alloc(4);
1061 struct storage *val;
1063 val = new_storage(STOR_VALUE);
1064 val->value = (long long) expr->value;
1065 val->flags = STOR_WANTS_FREE;
1066 insn("movl", val, new, NULL);
1068 return new;
1069 #else
1070 struct storage *val;
1072 val = new_storage(STOR_VALUE);
1073 val->value = (long long) expr->value;
1075 return val; /* FIXME: memory leak */
1076 #endif
1079 static struct storage *emit_binop(struct expression *expr)
1081 struct storage *left = x86_expression(expr->left);
1082 struct storage *right = x86_expression(expr->right);
1083 struct storage *new;
1084 const char *opname = NULL;
1087 * FIXME FIXME this routine is so wrong it's not even funny.
1088 * On x86 both mod/div are handled with the same instruction.
1089 * We don't pay attention to signed/unsigned issues,
1090 * and like elsewhere we hardcode the operand size at 32 bits.
1093 switch (expr->op) {
1094 case '+': opname = "addl"; break;
1095 case '-': opname = "subl"; break;
1096 case '*': opname = "mull"; break;
1097 case '/': opname = "divl"; break;
1098 case '%': opname = "modl"; break;
1099 case '&': opname = "andl"; break;
1100 case '|': opname = "orl"; break;
1101 case '^': opname = "xorl"; break;
1102 case SPECIAL_LEFTSHIFT: opname = "shll"; break;
1103 case SPECIAL_RIGHTSHIFT: opname = "shrl"; break;
1104 default: assert(0); break;
1107 /* load op2 into EAX */
1108 insn("movl", right, REG_EAX, "EXPR_BINOP/COMMA/LOGICAL");
1110 /* perform binop */
1111 insn(opname, left, REG_EAX, NULL);
1113 /* store result (EAX) in new pseudo / stack slot */
1114 new = stack_alloc(4);
1115 insn("movl", REG_EAX, new, "end EXPR_BINOP");
1117 return new;
1120 static void emit_if_conditional(struct statement *stmt)
1122 struct storage *val, *target_val;
1123 int target;
1124 struct expression *cond = stmt->if_conditional;
1126 /* This is only valid if nobody can jump into the "dead" statement */
1127 #if 0
1128 if (cond->type == EXPR_VALUE) {
1129 struct statement *s = stmt->if_true;
1130 if (!cond->value)
1131 s = stmt->if_false;
1132 x86_statement(s);
1133 break;
1135 #endif
1136 val = x86_expression(cond);
1138 /* load 'if' test result into EAX */
1139 insn("movl", val, REG_EAX, "begin if conditional");
1141 /* compare 'if' test result */
1142 insn("test", REG_EAX, REG_EAX, NULL);
1144 /* create end-of-if label / if-failed labelto jump to,
1145 * and jump to it if the expression returned zero.
1147 target = new_label();
1148 target_val = new_storage(STOR_LABEL);
1149 target_val->label = target;
1150 target_val->flags = STOR_WANTS_FREE;
1151 insn("jz", target_val, NULL, NULL);
1153 x86_statement(stmt->if_true);
1154 if (stmt->if_false) {
1155 struct storage *last_val;
1156 int last;
1158 /* finished generating code for if-true statement.
1159 * add a jump-to-end jump to avoid falling through
1160 * to the if-false statement code.
1162 last = new_label();
1163 last_val = new_storage(STOR_LABEL);
1164 last_val->label = last;
1165 last_val->flags = STOR_WANTS_FREE;
1166 insn("jmp", last_val, NULL, NULL);
1168 /* if we have both if-true and if-false statements,
1169 * the failed-conditional case will fall through to here
1171 emit_label(target, NULL);
1173 target = last;
1174 x86_statement(stmt->if_false);
1177 emit_label(target, "end if");
1180 static struct storage *emit_inc_dec(struct expression *expr, int postop)
1182 struct storage *addr = x86_address_gen(expr->unop);
1183 struct storage *retval;
1184 char opname[16];
1186 strcpy(opname, opbits(expr->op == SPECIAL_INCREMENT ? "inc" : "dec",
1187 expr->ctype->bit_size));
1189 if (postop) {
1190 struct storage *new = stack_alloc(4);
1192 emit_copy(addr, expr->unop->ctype, new, NULL);
1194 retval = new;
1195 } else
1196 retval = addr;
1198 insn(opname, addr, NULL, NULL);
1200 return retval;
1203 static struct storage *emit_postop(struct expression *expr)
1205 return emit_inc_dec(expr, 1);
1208 static struct storage *emit_return_stmt(struct statement *stmt)
1210 struct function *f = current_func;
1211 struct expression *expr = stmt->ret_value;
1212 struct storage *val = NULL, *jmplbl;
1214 if (expr && expr->ctype) {
1215 val = x86_expression(expr);
1216 assert(val != NULL);
1217 emit_move(val, REG_EAX, expr->ctype, "return");
1220 jmplbl = new_storage(STOR_LABEL);
1221 jmplbl->flags |= STOR_WANTS_FREE;
1222 jmplbl->label = f->ret_target;
1223 insn("jmp", jmplbl, NULL, NULL);
1225 return val;
1228 static struct storage *emit_conditional_expr(struct expression *expr)
1230 struct storage *cond = x86_expression(expr->conditional);
1231 struct storage *true = x86_expression(expr->cond_true);
1232 struct storage *false = x86_expression(expr->cond_false);
1233 struct storage *new = stack_alloc(4);
1235 if (!true)
1236 true = cond;
1238 emit_move(cond, REG_EAX, expr->conditional->ctype,
1239 "begin EXPR_CONDITIONAL");
1240 emit_move(true, REG_ECX, expr->cond_true->ctype, NULL);
1241 emit_move(false, REG_EDX, expr->cond_false->ctype, NULL);
1243 /* test EAX (for zero/non-zero) */
1244 insn("test", REG_EAX, REG_EAX, NULL);
1246 /* if false, move EDX to ECX */
1247 insn("cmovz", REG_EDX, REG_ECX, NULL);
1249 /* finally, store the result (ECX) in a new pseudo / stack slot */
1250 new = stack_alloc(4);
1251 emit_move(REG_ECX, new, expr->ctype, "end EXPR_CONDITIONAL");
1252 /* FIXME: we lose type knowledge of expression result at this point */
1254 return new;
1257 static struct storage *emit_symbol_expr_init(struct symbol *sym)
1259 struct expression *expr = sym->initializer;
1260 struct symbol_private *priv = sym->aux;
1262 if (priv == NULL) {
1263 priv = calloc(1, sizeof(*priv));
1264 sym->aux = priv;
1266 if (expr == NULL) {
1267 struct storage *new = stack_alloc(4);
1268 fprintf(stderr, "FIXME! no value for symbol. creating pseudo %d (stack offset %d)\n",
1269 new->pseudo, new->pseudo * 4);
1270 priv->addr = new;
1271 } else {
1272 priv->addr = x86_expression(expr);
1276 return priv->addr;
1279 static struct storage *emit_string_expr(struct expression *expr)
1281 struct function *f = current_func;
1282 int label = new_label();
1283 struct storage *new;
1285 push_cstring(f, expr->string, label);
1287 new = new_storage(STOR_LABEL);
1288 new->label = label;
1289 new->flags = STOR_LABEL_VAL | STOR_WANTS_FREE;
1290 return new;
1293 static struct storage *emit_cast_expr(struct expression *expr)
1295 struct symbol *old_type, *new_type;
1296 struct storage *op = x86_expression(expr->cast_expression);
1297 int oldbits, newbits;
1298 struct storage *new;
1300 old_type = expr->cast_expression->ctype;
1301 new_type = expr->cast_type;
1303 oldbits = old_type->bit_size;
1304 newbits = new_type->bit_size;
1305 if (oldbits >= newbits)
1306 return op;
1308 emit_move(op, REG_EAX, old_type, "begin cast ..");
1310 new = stack_alloc(4);
1311 emit_move(REG_EAX, new, new_type, ".... end cast");
1313 return new;
1316 static struct storage *emit_regular_preop(struct expression *expr)
1318 struct storage *target = x86_expression(expr->unop);
1319 struct storage *val, *new = stack_alloc(4);
1320 const char *opname = NULL;
1322 switch (expr->op) {
1323 case '!':
1324 val = new_storage(STOR_VALUE);
1325 val->flags = STOR_WANTS_FREE;
1326 emit_move(val, REG_EDX, NULL, NULL);
1327 emit_move(target, REG_EAX, expr->unop->ctype, NULL);
1328 insn("test", REG_EAX, REG_EAX, NULL);
1329 insn("setz", REG_DL, NULL, NULL);
1330 emit_move(REG_EDX, new, expr->unop->ctype, NULL);
1332 break;
1333 case '~':
1334 opname = "not";
1335 case '-':
1336 if (!opname)
1337 opname = "neg";
1338 emit_move(target, REG_EAX, expr->unop->ctype, NULL);
1339 insn(opname, REG_EAX, NULL, NULL);
1340 emit_move(REG_EAX, new, expr->unop->ctype, NULL);
1341 break;
1342 default:
1343 assert(0);
1344 break;
1347 return new;
1350 static void emit_case_statement(struct statement *stmt)
1352 emit_labelsym(stmt->case_label, NULL);
1353 x86_statement(stmt->case_statement);
1356 static void emit_switch_statement(struct statement *stmt)
1358 struct storage *val = x86_expression(stmt->switch_expression);
1359 struct symbol *sym, *default_sym = NULL;
1360 struct storage *labelsym, *label;
1361 int switch_end = 0;
1363 emit_move(val, REG_EAX, stmt->switch_expression->ctype, "begin case");
1366 * This is where a _real_ back-end would go through the
1367 * cases to decide whether to use a lookup table or a
1368 * series of comparisons etc
1370 FOR_EACH_PTR(stmt->switch_case->symbol_list, sym) {
1371 struct statement *case_stmt = sym->stmt;
1372 struct expression *expr = case_stmt->case_expression;
1373 struct expression *to = case_stmt->case_to;
1375 /* default: */
1376 if (!expr)
1377 default_sym = sym;
1379 /* case NNN: */
1380 else {
1381 struct storage *case_val = new_val(expr->value);
1383 assert (expr->type == EXPR_VALUE);
1385 insn("cmpl", case_val, REG_EAX, NULL);
1387 if (!to) {
1388 labelsym = new_labelsym(sym);
1389 insn("je", labelsym, NULL, NULL);
1390 } else {
1391 int next_test;
1393 label = new_storage(STOR_LABEL);
1394 label->flags |= STOR_WANTS_FREE;
1395 label->label = next_test = new_label();
1397 /* FIXME: signed/unsigned */
1398 insn("jl", label, NULL, NULL);
1400 case_val = new_val(to->value);
1401 insn("cmpl", case_val, REG_EAX, NULL);
1403 /* TODO: implement and use refcounting... */
1404 label = new_storage(STOR_LABEL);
1405 label->flags |= STOR_WANTS_FREE;
1406 label->label = next_test;
1408 /* FIXME: signed/unsigned */
1409 insn("jg", label, NULL, NULL);
1411 labelsym = new_labelsym(sym);
1412 insn("jmp", labelsym, NULL, NULL);
1414 emit_label(next_test, NULL);
1417 } END_FOR_EACH_PTR;
1419 if (default_sym) {
1420 labelsym = new_labelsym(default_sym);
1421 insn("jmp", labelsym, NULL, "default");
1422 } else {
1423 label = new_storage(STOR_LABEL);
1424 label->flags |= STOR_WANTS_FREE;
1425 label->label = switch_end = new_label();
1426 insn("jmp", label, NULL, "goto end of switch");
1429 x86_statement(stmt->switch_statement);
1431 if (stmt->switch_break->used)
1432 emit_labelsym(stmt->switch_break, NULL);
1434 if (switch_end)
1435 emit_label(switch_end, NULL);
1438 static void x86_struct_member(struct symbol *sym, void *data, int flags)
1440 if (flags & ITERATE_FIRST)
1441 printf(" {\n\t");
1442 printf("%s:%d:%ld at offset %ld", show_ident(sym->ident), sym->bit_size, sym->ctype.alignment, sym->offset);
1443 if (sym->fieldwidth)
1444 printf("[%d..%d]", sym->bit_offset, sym->bit_offset+sym->fieldwidth-1);
1445 if (flags & ITERATE_LAST)
1446 printf("\n} ");
1447 else
1448 printf(", ");
1451 static void x86_symbol(struct symbol *sym)
1453 struct symbol *type;
1455 if (!sym)
1456 return;
1458 type = sym->ctype.base_type;
1459 if (!type)
1460 return;
1463 * Show actual implementation information
1465 switch (type->type) {
1467 case SYM_ARRAY:
1468 if (sym->initializer)
1469 emit_array(sym);
1470 else
1471 emit_array_noinit(sym);
1472 break;
1474 case SYM_BASETYPE:
1475 if (sym->initializer) {
1476 emit_object_pre(show_ident(sym->ident),
1477 sym->ctype.modifiers,
1478 sym->ctype.alignment,
1479 sym->bit_size / 8);
1480 emit_scalar(sym->initializer, sym->bit_size);
1481 stor_sym_init(sym);
1482 } else
1483 emit_scalar_noinit(sym);
1484 break;
1486 case SYM_STRUCT:
1487 symbol_iterate(type->symbol_list, x86_struct_member, NULL);
1488 break;
1490 case SYM_UNION:
1491 symbol_iterate(type->symbol_list, x86_struct_member, NULL);
1492 break;
1494 case SYM_FN: {
1495 struct statement *stmt = type->stmt;
1496 if (stmt) {
1497 emit_func_pre(sym);
1498 x86_statement(stmt);
1499 emit_func_post(sym);
1501 break;
1504 default:
1505 break;
1508 if (sym->initializer && (type->type != SYM_BASETYPE) &&
1509 (type->type != SYM_ARRAY)) {
1510 printf(" = \n");
1511 x86_expression(sym->initializer);
1515 static void x86_symbol_init(struct symbol *sym);
1517 static void x86_symbol_decl(struct symbol_list *syms)
1519 struct symbol *sym;
1520 FOR_EACH_PTR(syms, sym) {
1521 x86_symbol_init(sym);
1522 } END_FOR_EACH_PTR;
1525 static void x86_loop(struct statement *stmt)
1527 struct statement *pre_statement = stmt->iterator_pre_statement;
1528 struct expression *pre_condition = stmt->iterator_pre_condition;
1529 struct statement *statement = stmt->iterator_statement;
1530 struct statement *post_statement = stmt->iterator_post_statement;
1531 struct expression *post_condition = stmt->iterator_post_condition;
1532 int loop_top = 0, loop_bottom = 0;
1533 struct storage *val;
1535 x86_symbol_decl(stmt->iterator_syms);
1536 x86_statement(pre_statement);
1537 if (pre_condition) {
1538 if (pre_condition->type == EXPR_VALUE) {
1539 if (!pre_condition->value) {
1540 loop_bottom = new_label();
1541 printf("\tjmp\t\t.L%d\n", loop_bottom);
1543 } else {
1544 loop_bottom = new_label();
1545 val = x86_expression(pre_condition);
1546 printf("\tje\t\tv%d, .L%d\n", val->pseudo, loop_bottom);
1549 if (!post_condition || post_condition->type != EXPR_VALUE || post_condition->value) {
1550 loop_top = new_label();
1551 printf(".L%d:\n", loop_top);
1553 x86_statement(statement);
1554 if (stmt->iterator_continue->used)
1555 printf(".L%p:\n", stmt->iterator_continue);
1556 x86_statement(post_statement);
1557 if (!post_condition) {
1558 printf("\tjmp\t\t.L%d\n", loop_top);
1559 } else if (post_condition->type == EXPR_VALUE) {
1560 if (post_condition->value)
1561 printf("\tjmp\t\t.L%d\n", loop_top);
1562 } else {
1563 val = x86_expression(post_condition);
1564 printf("\tjne\t\tv%d, .L%d\n", val->pseudo, loop_top);
1566 if (stmt->iterator_break->used)
1567 printf(".L%p:\n", stmt->iterator_break);
1568 if (loop_bottom)
1569 printf(".L%d:\n", loop_bottom);
1573 * Print out a statement
1575 static struct storage *x86_statement(struct statement *stmt)
1577 if (!stmt)
1578 return 0;
1579 switch (stmt->type) {
1580 case STMT_RETURN:
1581 return emit_return_stmt(stmt);
1582 case STMT_COMPOUND: {
1583 struct statement *s;
1584 struct storage *last = NULL;
1586 x86_symbol_decl(stmt->syms);
1587 FOR_EACH_PTR(stmt->stmts, s) {
1588 last = x86_statement(s);
1589 } END_FOR_EACH_PTR;
1591 return last;
1594 case STMT_EXPRESSION:
1595 return x86_expression(stmt->expression);
1596 case STMT_IF:
1597 emit_if_conditional(stmt);
1598 return NULL;
1600 case STMT_CASE:
1601 emit_case_statement(stmt);
1602 break;
1603 case STMT_SWITCH:
1604 emit_switch_statement(stmt);
1605 break;
1607 case STMT_ITERATOR:
1608 x86_loop(stmt);
1609 break;
1611 case STMT_NONE:
1612 break;
1614 case STMT_LABEL:
1615 printf(".L%p:\n", stmt->label_identifier);
1616 x86_statement(stmt->label_statement);
1617 break;
1619 case STMT_GOTO:
1620 if (stmt->goto_expression) {
1621 struct storage *val = x86_expression(stmt->goto_expression);
1622 printf("\tgoto *v%d\n", val->pseudo);
1623 } else {
1624 struct storage *labelsym = new_labelsym(stmt->goto_label);
1625 insn("jmp", labelsym, NULL, NULL);
1627 break;
1628 case STMT_ASM:
1629 printf("\tasm( .... )\n");
1630 break;
1633 return NULL;
1636 static struct storage *x86_call_expression(struct expression *expr)
1638 struct function *f = current_func;
1639 struct symbol *direct;
1640 struct expression *arg, *fn;
1641 struct storage *retval, *fncall;
1642 int framesize;
1643 char s[64];
1645 if (!expr->ctype) {
1646 warn(expr->pos, "\tcall with no type!");
1647 return NULL;
1650 framesize = 0;
1651 FOR_EACH_PTR_REVERSE(expr->args, arg) {
1652 struct storage *new = x86_expression(arg);
1653 int size = arg->ctype->bit_size;
1655 /* FIXME: pay attention to 'size' */
1656 insn("pushl", new, NULL,
1657 !framesize ? "begin function call" : NULL);
1659 framesize += size >> 3;
1660 } END_FOR_EACH_PTR_REVERSE;
1662 fn = expr->fn;
1664 /* Remove dereference, if any */
1665 direct = NULL;
1666 if (fn->type == EXPR_PREOP) {
1667 if (fn->unop->type == EXPR_SYMBOL) {
1668 struct symbol *sym = fn->unop->symbol;
1669 if (sym->ctype.base_type->type == SYM_FN)
1670 direct = sym;
1673 if (direct) {
1674 struct storage *direct_stor = new_storage(STOR_SYM);
1675 direct_stor->flags |= STOR_WANTS_FREE;
1676 direct_stor->sym = direct;
1677 insn("call", direct_stor, NULL, NULL);
1678 } else {
1679 fncall = x86_expression(fn);
1680 emit_move(fncall, REG_EAX, fn->ctype, NULL);
1682 strcpy(s, "\tcall\t*%eax\n");
1683 push_text_atom(f, s);
1686 /* FIXME: pay attention to BITS_IN_POINTER */
1687 if (framesize) {
1688 struct storage *val = new_storage(STOR_VALUE);
1689 val->value = (long long) framesize;
1690 val->flags = STOR_WANTS_FREE;
1691 insn("addl", val, REG_ESP, NULL);
1694 retval = stack_alloc(4);
1695 emit_move(REG_EAX, retval, NULL, "end function call");
1697 return retval;
1700 static struct storage *x86_address_gen(struct expression *expr)
1702 struct function *f = current_func;
1703 struct storage *addr;
1704 struct storage *new;
1705 char s[32];
1707 if ((expr->type != EXPR_PREOP) || (expr->op != '*'))
1708 return x86_expression(expr->address);
1710 addr = x86_expression(expr->unop);
1711 if (expr->unop->type == EXPR_SYMBOL)
1712 return addr;
1714 emit_move(addr, REG_EAX, NULL, "begin deref ..");
1716 /* FIXME: operand size */
1717 strcpy(s, "\tmovl\t(%eax), %ecx\n");
1718 push_text_atom(f, s);
1720 new = stack_alloc(4);
1721 emit_move(REG_ECX, new, NULL, ".... end deref");
1723 return new;
1726 static struct storage *x86_assignment(struct expression *expr)
1728 struct expression *target = expr->left;
1729 struct storage *val, *addr;
1730 int bits;
1732 if (!expr->ctype)
1733 return NULL;
1735 bits = expr->ctype->bit_size;
1736 val = x86_expression(expr->right);
1737 addr = x86_address_gen(target);
1739 switch (val->type) {
1740 /* copy, where both operands are memory */
1741 case STOR_PSEUDO:
1742 case STOR_ARG:
1743 emit_copy(val, expr->right->ctype, addr, expr->left->ctype);
1744 break;
1746 /* copy, one or zero operands are memory */
1747 case STOR_REG:
1748 case STOR_SYM:
1749 case STOR_VALUE:
1750 case STOR_LABEL:
1751 emit_move(val, addr, expr->left->ctype, NULL);
1752 break;
1754 case STOR_LABELSYM:
1755 assert(0);
1756 break;
1758 return val;
1761 static int x86_initialization(struct symbol *sym, struct expression *expr)
1763 struct storage *val, *addr;
1764 int bits;
1766 if (!expr->ctype)
1767 return 0;
1769 bits = expr->ctype->bit_size;
1770 val = x86_expression(expr);
1771 addr = x86_symbol_expr(sym);
1772 // FIXME! The "target" expression is for bitfield store information.
1773 // Leave it NULL, which works fine.
1774 emit_store(NULL, addr, val, bits);
1775 return 0;
1778 static struct storage *x86_access(struct expression *expr)
1780 return x86_address_gen(expr);
1783 static struct storage *x86_preop(struct expression *expr)
1786 * '*' is an lvalue access, and is fundamentally different
1787 * from an arithmetic operation. Maybe it should have an
1788 * expression type of its own..
1790 if (expr->op == '*')
1791 return x86_access(expr);
1792 if (expr->op == SPECIAL_INCREMENT || expr->op == SPECIAL_DECREMENT)
1793 return emit_inc_dec(expr, 0);
1794 return emit_regular_preop(expr);
1797 static struct storage *x86_symbol_expr(struct symbol *sym)
1799 struct storage *new = stack_alloc(4);
1801 if (sym->ctype.modifiers & (MOD_TOPLEVEL | MOD_EXTERN | MOD_STATIC)) {
1802 printf("\tmovi.%d\t\tv%d,$%s\n", BITS_IN_POINTER, new->pseudo, show_ident(sym->ident));
1803 return new;
1805 if (sym->ctype.modifiers & MOD_ADDRESSABLE) {
1806 printf("\taddi.%d\t\tv%d,vFP,$%lld\n", BITS_IN_POINTER, new->pseudo, sym->value);
1807 return new;
1809 printf("\taddi.%d\t\tv%d,vFP,$offsetof(%s:%p)\n", BITS_IN_POINTER, new->pseudo, show_ident(sym->ident), sym);
1810 return new;
1813 static void x86_symbol_init(struct symbol *sym)
1815 struct symbol_private *priv = sym->aux;
1816 struct expression *expr = sym->initializer;
1817 struct storage *new;
1819 if (expr)
1820 new = x86_expression(expr);
1821 else
1822 new = stack_alloc(sym->bit_size / 8);
1824 if (!priv) {
1825 priv = calloc(1, sizeof(*priv));
1826 sym->aux = priv;
1827 /* FIXME: leak! we don't free... */
1828 /* (well, we don't free symbols either) */
1831 priv->addr = new;
1834 static int type_is_signed(struct symbol *sym)
1836 if (sym->type == SYM_NODE)
1837 sym = sym->ctype.base_type;
1838 if (sym->type == SYM_PTR)
1839 return 0;
1840 return !(sym->ctype.modifiers & MOD_UNSIGNED);
1843 static struct storage *x86_bitfield_expr(struct expression *expr)
1845 return x86_access(expr);
1848 static struct storage *x86_label_expr(struct expression *expr)
1850 struct storage *new = stack_alloc(4);
1851 printf("\tmovi.%d\t\tv%d,.L%p\n",BITS_IN_POINTER, new->pseudo, expr->label_symbol);
1852 return new;
1855 static struct storage *x86_statement_expr(struct expression *expr)
1857 return x86_statement(expr->statement);
1860 static int x86_position_expr(struct expression *expr, struct symbol *base)
1862 struct storage *new = x86_expression(expr->init_expr);
1863 struct symbol *ctype = expr->init_sym;
1865 printf("\tinsert v%d at [%d:%d] of %s\n", new->pseudo,
1866 expr->init_offset, ctype->bit_offset,
1867 show_ident(base->ident));
1868 return 0;
1871 static void x86_initializer_expr(struct expression *expr, struct symbol *ctype)
1873 struct expression *entry;
1875 FOR_EACH_PTR(expr->expr_list, entry) {
1876 // Nested initializers have their positions already
1877 // recursively calculated - just output them too
1878 if (entry->type == EXPR_INITIALIZER) {
1879 x86_initializer_expr(entry, ctype);
1880 continue;
1883 // Ignore initializer indexes and identifiers - the
1884 // evaluator has taken them into account
1885 if (entry->type == EXPR_IDENTIFIER || entry->type == EXPR_INDEX)
1886 continue;
1887 if (entry->type == EXPR_POS) {
1888 x86_position_expr(entry, ctype);
1889 continue;
1891 x86_initialization(ctype, entry);
1892 } END_FOR_EACH_PTR;
1896 * Print out an expression. Return the pseudo that contains the
1897 * variable.
1899 static struct storage *x86_expression(struct expression *expr)
1901 if (!expr)
1902 return 0;
1904 if (!expr->ctype) {
1905 struct position *pos = &expr->pos;
1906 printf("\tno type at %s:%d:%d\n",
1907 input_streams[pos->stream].name,
1908 pos->line, pos->pos);
1909 return 0;
1912 switch (expr->type) {
1913 case EXPR_CALL:
1914 return x86_call_expression(expr);
1916 case EXPR_ASSIGNMENT:
1917 return x86_assignment(expr);
1919 case EXPR_COMPARE:
1920 return emit_compare(expr);
1921 case EXPR_BINOP:
1922 case EXPR_COMMA:
1923 case EXPR_LOGICAL:
1924 return emit_binop(expr);
1925 case EXPR_PREOP:
1926 return x86_preop(expr);
1927 case EXPR_POSTOP:
1928 return emit_postop(expr);
1929 case EXPR_SYMBOL:
1930 return emit_symbol_expr_init(expr->symbol);
1931 case EXPR_DEREF:
1932 case EXPR_SIZEOF:
1933 warn(expr->pos, "invalid expression after evaluation");
1934 return 0;
1935 case EXPR_CAST:
1936 return emit_cast_expr(expr);
1937 case EXPR_VALUE:
1938 return emit_value(expr);
1939 case EXPR_STRING:
1940 return emit_string_expr(expr);
1941 case EXPR_BITFIELD:
1942 return x86_bitfield_expr(expr);
1943 case EXPR_INITIALIZER:
1944 x86_initializer_expr(expr, expr->ctype);
1945 return NULL;
1946 case EXPR_CONDITIONAL:
1947 return emit_conditional_expr(expr);
1948 case EXPR_STATEMENT:
1949 return x86_statement_expr(expr);
1950 case EXPR_LABEL:
1951 return x86_label_expr(expr);
1953 // None of these should exist as direct expressions: they are only
1954 // valid as sub-expressions of initializers.
1955 case EXPR_POS:
1956 warn(expr->pos, "unable to show plain initializer position expression");
1957 return 0;
1958 case EXPR_IDENTIFIER:
1959 warn(expr->pos, "unable to show identifier expression");
1960 return 0;
1961 case EXPR_INDEX:
1962 warn(expr->pos, "unable to show index expression");
1963 return 0;
1965 return 0;