[be] fix function name emitted for .size directive
[smatch.git] / compile-i386.c
blob55282905cd446e63380a8699302728b05a833a26
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 unsigned int len; /* does NOT include terminating null */
46 char *text;
47 struct textbuf *next;
48 struct textbuf *prev;
51 struct loop_stack {
52 int continue_lbl;
53 int loop_bottom_lbl;
54 struct loop_stack *next;
57 struct function {
58 int stack_size;
59 int pseudo_nr;
60 struct ptr_list *pseudo_list;
61 struct ptr_list *atom_list;
62 struct ptr_list *str_list;
63 struct loop_stack *loop_stack;
64 struct symbol **argv;
65 unsigned int argc;
66 int ret_target;
69 enum storage_type {
70 STOR_PSEUDO, /* variable stored on the stack */
71 STOR_ARG, /* function argument */
72 STOR_SYM, /* a symbol we can directly ref in the asm */
73 STOR_REG, /* scratch register */
74 STOR_VALUE, /* integer constant */
75 STOR_LABEL, /* label / jump target */
76 STOR_LABELSYM, /* label generated from symbol's pointer value */
79 struct reg_info {
80 const char *name;
83 struct storage {
84 enum storage_type type;
85 unsigned long flags;
87 /* STOR_REG */
88 struct reg_info *reg;
90 union {
91 /* STOR_PSEUDO */
92 struct {
93 int pseudo;
94 int offset;
95 int size;
97 /* STOR_ARG */
98 struct {
99 int idx;
101 /* STOR_SYM */
102 struct {
103 struct symbol *sym;
105 /* STOR_VALUE */
106 struct {
107 long long value;
109 /* STOR_LABEL */
110 struct {
111 int label;
113 /* STOR_LABELSYM */
114 struct {
115 struct symbol *labelsym;
120 enum {
121 STOR_LABEL_VAL = (1 << 0),
122 STOR_WANTS_FREE = (1 << 1),
125 struct symbol_private {
126 struct storage *addr;
129 enum atom_type {
130 ATOM_TEXT,
131 ATOM_INSN,
132 ATOM_CSTR,
135 struct atom {
136 enum atom_type type;
137 union {
138 /* stuff for text */
139 struct {
140 char *text;
141 unsigned int text_len; /* w/o terminating null */
144 /* stuff for insns */
145 struct {
146 char insn[32];
147 char comment[40];
148 struct storage *op1;
149 struct storage *op2;
152 /* stuff for C strings */
153 struct {
154 struct string *string;
155 int label;
161 struct function *current_func = NULL;
162 struct textbuf *unit_post_text = NULL;
163 static const char *current_section;
165 static struct reg_info reg_info_table[] = {
166 { "%eax" },
167 { "%ecx" },
168 { "%edx" },
169 { "%esp" },
170 { "%dl" },
173 static struct storage hardreg_storage_table[] = {
174 { /* eax */
175 .type = STOR_REG,
176 .reg = &reg_info_table[0],
179 { /* ecx */
180 .type = STOR_REG,
181 .reg = &reg_info_table[1],
184 { /* edx */
185 .type = STOR_REG,
186 .reg = &reg_info_table[2],
189 { /* esp */
190 .type = STOR_REG,
191 .reg = &reg_info_table[3],
194 { /* dl */
195 .type = STOR_REG,
196 .reg = &reg_info_table[4],
200 #define REG_EAX (&hardreg_storage_table[0])
201 #define REG_ECX (&hardreg_storage_table[1])
202 #define REG_EDX (&hardreg_storage_table[2])
203 #define REG_ESP (&hardreg_storage_table[3])
204 #define REG_DL (&hardreg_storage_table[4])
207 static void emit_move(struct storage *src, struct storage *dest,
208 struct symbol *ctype, const char *comment);
209 static int type_is_signed(struct symbol *sym);
210 static struct storage *x86_address_gen(struct expression *expr);
211 static struct storage *x86_symbol_expr(struct symbol *sym);
212 static void x86_symbol(struct symbol *sym);
213 static struct storage *x86_statement(struct statement *stmt);
214 static struct storage *x86_expression(struct expression *expr);
217 static inline unsigned int pseudo_offset(struct storage *s)
219 if (s->type != STOR_PSEUDO)
220 return 123456; /* intentionally bogus value */
222 return s->offset;
225 static inline unsigned int arg_offset(struct storage *s)
227 if (s->type != STOR_ARG)
228 return 123456; /* intentionally bogus value */
230 /* FIXME: this is wrong wrong wrong */
231 return current_func->stack_size + ((1 + s->idx) * 4);
234 static const char *pretty_offset(int ofs)
236 static char esp_buf[64];
238 if (ofs)
239 sprintf(esp_buf, "%d(%%esp)", ofs);
240 else
241 strcpy(esp_buf, "(%esp)");
243 return esp_buf;
246 static void stor_sym_init(struct symbol *sym)
248 struct storage *stor;
249 struct symbol_private *priv;
251 priv = calloc(1, sizeof(*priv) + sizeof(*stor));
252 if (!priv)
253 die("OOM in stor_sym_init");
255 stor = (struct storage *) (priv + 1);
257 priv->addr = stor;
258 stor->type = STOR_SYM;
259 stor->sym = sym;
262 static const char *stor_op_name(struct storage *s)
264 static char name[32];
266 switch (s->type) {
267 case STOR_PSEUDO:
268 strcpy(name, pretty_offset((int) pseudo_offset(s)));
269 break;
270 case STOR_ARG:
271 strcpy(name, pretty_offset((int) arg_offset(s)));
272 break;
273 case STOR_SYM:
274 strcpy(name, show_ident(s->sym->ident));
275 break;
276 case STOR_REG:
277 strcpy(name, s->reg->name);
278 break;
279 case STOR_VALUE:
280 sprintf(name, "$%Ld", s->value);
281 break;
282 case STOR_LABEL:
283 sprintf(name, "%s.L%d", s->flags & STOR_LABEL_VAL ? "$" : "",
284 s->label);
285 break;
286 case STOR_LABELSYM:
287 sprintf(name, "%s.LS%p", s->flags & STOR_LABEL_VAL ? "$" : "",
288 s->labelsym);
289 break;
292 return name;
295 static struct atom *new_atom(enum atom_type type)
297 struct atom *atom;
299 atom = calloc(1, sizeof(*atom)); /* TODO: chunked alloc */
300 if (!atom)
301 die("nuclear OOM");
303 atom->type = type;
305 return atom;
308 static inline void push_cstring(struct function *f, struct string *str,
309 int label)
311 struct atom *atom;
313 atom = new_atom(ATOM_CSTR);
314 atom->string = str;
315 atom->label = label;
317 add_ptr_list(&f->str_list, atom); /* note: _not_ atom_list */
320 static inline void push_atom(struct function *f, struct atom *atom)
322 add_ptr_list(&f->atom_list, atom);
325 static void push_text_atom(struct function *f, const char *text)
327 struct atom *atom = new_atom(ATOM_TEXT);
329 atom->text = strdup(text);
330 atom->text_len = strlen(text);
332 push_atom(f, atom);
335 static struct storage *new_storage(enum storage_type type)
337 struct storage *stor;
339 stor = calloc(1, sizeof(*stor));
340 if (!stor)
341 die("OOM in new_storage");
343 stor->type = type;
345 return stor;
348 static struct storage *stack_alloc(int n_bytes)
350 struct function *f = current_func;
351 struct storage *stor;
353 assert(f != NULL);
355 stor = new_storage(STOR_PSEUDO);
356 stor->type = STOR_PSEUDO;
357 stor->pseudo = f->pseudo_nr;
358 stor->offset = f->stack_size;
359 stor->size = n_bytes;
360 f->stack_size += n_bytes;
361 f->pseudo_nr++;
363 add_ptr_list(&f->pseudo_list, stor);
365 return stor;
368 static struct storage *new_labelsym(struct symbol *sym)
370 struct storage *stor;
372 stor = new_storage(STOR_LABELSYM);
374 if (stor) {
375 stor->flags |= STOR_WANTS_FREE;
376 stor->labelsym = sym;
379 return stor;
382 static struct storage *new_val(long long value)
384 struct storage *stor;
386 stor = new_storage(STOR_VALUE);
388 if (stor) {
389 stor->flags |= STOR_WANTS_FREE;
390 stor->value = value;
393 return stor;
396 static int new_label(void)
398 static int label = 0;
399 return ++label;
402 static void textbuf_push(struct textbuf **buf_p, const char *text)
404 struct textbuf *tmp, *list = *buf_p;
405 unsigned int text_len = strlen(text);
406 unsigned int alloc_len = text_len + 1 + sizeof(*list);
408 tmp = calloc(1, alloc_len);
409 if (!tmp)
410 die("OOM on textbuf alloc");
412 tmp->text = ((void *) tmp) + sizeof(*tmp);
413 memcpy(tmp->text, text, text_len + 1);
414 tmp->len = text_len;
416 /* add to end of list */
417 if (!list) {
418 list = tmp;
419 tmp->prev = tmp;
420 } else {
421 tmp->prev = list->prev;
422 tmp->prev->next = tmp;
423 list->prev = tmp;
425 tmp->next = list;
427 *buf_p = list;
430 static void textbuf_emit(struct textbuf **buf_p)
432 struct textbuf *tmp, *list = *buf_p;
434 while (list) {
435 tmp = list;
436 if (tmp->next == tmp)
437 list = NULL;
438 else {
439 tmp->prev->next = tmp->next;
440 tmp->next->prev = tmp->prev;
441 list = tmp->next;
444 fputs(tmp->text, stdout);
446 free(tmp);
449 *buf_p = list;
452 static void insn(const char *insn, struct storage *op1, struct storage *op2,
453 const char *comment_in)
455 struct function *f = current_func;
456 struct atom *atom = new_atom(ATOM_INSN);
458 assert(insn != NULL);
460 strcpy(atom->insn, insn);
461 if (comment_in && (*comment_in))
462 strncpy(atom->comment, comment_in,
463 sizeof(atom->comment) - 1);
465 atom->op1 = op1;
466 atom->op2 = op2;
468 push_atom(f, atom);
471 static void emit_label (int label, const char *comment)
473 struct function *f = current_func;
474 char s[64];
476 if (!comment)
477 sprintf(s, ".L%d:\n", label);
478 else
479 sprintf(s, ".L%d:\t\t\t\t\t# %s\n", label, comment);
481 push_text_atom(f, s);
484 static void emit_labelsym (struct symbol *sym, const char *comment)
486 struct function *f = current_func;
487 char s[64];
489 if (!comment)
490 sprintf(s, ".LS%p:\n", sym);
491 else
492 sprintf(s, ".LS%p:\t\t\t\t# %s\n", sym, comment);
494 push_text_atom(f, s);
497 static void emit_unit_pre(const char *basename)
499 printf("\t.file\t\"%s\"\n", basename);
502 static void emit_unit_post(void)
504 textbuf_emit(&unit_post_text);
505 printf("\t.ident\t\"sparse silly x86 backend (built %s)\"\n", __DATE__);
508 /* conditionally switch sections */
509 static void emit_section(const char *s)
511 if (s == current_section)
512 return;
513 if (current_section && (!strcmp(s, current_section)))
514 return;
516 printf("\t%s\n", s);
517 current_section = s;
520 static void emit_insn_atom(struct function *f, struct atom *atom)
522 char s[128];
523 char comment[64];
524 struct storage *op1 = atom->op1;
525 struct storage *op2 = atom->op2;
527 if (atom->comment[0])
528 sprintf(comment, "\t\t# %s", atom->comment);
529 else
530 comment[0] = 0;
532 if (atom->op2) {
533 char tmp[16];
534 strcpy(tmp, stor_op_name(op1));
535 sprintf(s, "\t%s\t%s, %s%s\n",
536 atom->insn, tmp, stor_op_name(op2), comment);
537 } else if (atom->op1)
538 sprintf(s, "\t%s\t%s%s%s\n",
539 atom->insn, stor_op_name(op1),
540 comment[0] ? "\t" : "", comment);
541 else
542 sprintf(s, "\t%s\t%s%s\n",
543 atom->insn,
544 comment[0] ? "\t\t" : "", comment);
546 write(STDOUT_FILENO, s, strlen(s));
549 static void emit_atom_list(struct function *f)
551 struct atom *atom;
553 FOR_EACH_PTR(f->atom_list, atom) {
554 switch (atom->type) {
555 case ATOM_TEXT: {
556 ssize_t rc = write(STDOUT_FILENO, atom->text,
557 atom->text_len);
558 (void) rc; /* FIXME */
559 break;
561 case ATOM_INSN:
562 emit_insn_atom(f, atom);
563 break;
564 case ATOM_CSTR:
565 assert(0);
566 break;
568 } END_FOR_EACH_PTR;
571 static void emit_string_list(struct function *f)
573 struct atom *atom;
575 emit_section(".section\t.rodata");
577 FOR_EACH_PTR(f->str_list, atom) {
578 /* FIXME: escape " in string */
579 printf(".L%d:\n", atom->label);
580 printf("\t.string\t%s\n", show_string(atom->string));
582 free(atom);
583 } END_FOR_EACH_PTR;
586 static void func_cleanup(struct function *f)
588 struct storage *stor;
589 struct atom *atom;
591 FOR_EACH_PTR(f->pseudo_list, stor) {
592 free(stor);
593 } END_FOR_EACH_PTR;
595 FOR_EACH_PTR(f->atom_list, atom) {
596 if ((atom->type == ATOM_TEXT) && (atom->text))
597 free(atom->text);
598 if (atom->op1 && (atom->op1->flags & STOR_WANTS_FREE))
599 free(atom->op1);
600 if (atom->op2 && (atom->op2->flags & STOR_WANTS_FREE))
601 free(atom->op2);
602 free(atom);
603 } END_FOR_EACH_PTR;
605 free_ptr_list(&f->pseudo_list);
606 free(f);
609 /* function prologue */
610 static void emit_func_pre(struct symbol *sym)
612 struct function *f;
613 struct symbol *arg;
614 unsigned int i, argc = 0, alloc_len;
615 unsigned char *mem;
616 struct symbol_private *privbase;
617 struct storage *storage_base;
618 struct symbol *base_type = sym->ctype.base_type;
620 FOR_EACH_PTR(base_type->arguments, arg) {
621 argc++;
622 } END_FOR_EACH_PTR;
624 alloc_len =
625 sizeof(*f) +
626 (argc * sizeof(struct symbol *)) +
627 (argc * sizeof(struct symbol_private)) +
628 (argc * sizeof(struct storage));
629 mem = calloc(1, alloc_len);
630 if (!mem)
631 die("OOM on func info");
633 f = (struct function *) mem;
634 mem += sizeof(*f);
635 f->argv = (struct symbol **) mem;
636 mem += (argc * sizeof(struct symbol *));
637 privbase = (struct symbol_private *) mem;
638 mem += (argc * sizeof(struct symbol_private));
639 storage_base = (struct storage *) mem;
641 f->argc = argc;
642 f->ret_target = new_label();
644 i = 0;
645 FOR_EACH_PTR(base_type->arguments, arg) {
646 f->argv[i] = arg;
647 arg->aux = &privbase[i];
648 storage_base[i].type = STOR_ARG;
649 storage_base[i].idx = i;
650 privbase[i].addr = &storage_base[i];
651 i++;
652 } END_FOR_EACH_PTR;
654 assert(current_func == NULL);
655 current_func = f;
658 /* function epilogue */
659 static void emit_func_post(struct symbol *sym)
661 const char *name = show_ident(sym->ident);
662 struct function *f = current_func;
663 int stack_size = f->stack_size;
665 if (f->str_list)
666 emit_string_list(f);
668 /* function prologue */
669 emit_section(".text");
670 if ((sym->ctype.modifiers & MOD_STATIC) == 0)
671 printf(".globl %s\n", name);
672 printf("\t.type\t%s, @function\n", name);
673 printf("%s:\n", name);
675 if (stack_size) {
676 char pseudo_const[16];
678 sprintf(pseudo_const, "$%d", stack_size);
679 printf("\tsubl\t%s, %%esp\n", pseudo_const);
682 /* function epilogue */
684 /* jump target for 'return' statements */
685 emit_label(f->ret_target, NULL);
687 if (stack_size) {
688 struct storage *val;
690 val = new_storage(STOR_VALUE);
691 val->value = (long long) (stack_size);
692 val->flags = STOR_WANTS_FREE;
694 insn("addl", val, REG_ESP, NULL);
697 insn("ret", NULL, NULL, NULL);
699 /* output everything to stdout */
700 fflush(stdout); /* paranoia; needed? */
701 emit_atom_list(f);
703 /* function footer */
704 name = show_ident(sym->ident);
705 printf("\t.size\t%s, .-%s\n", name, name);
707 func_cleanup(f);
708 current_func = NULL;
711 /* emit object (a.k.a. variable, a.k.a. data) prologue */
712 static void emit_object_pre(const char *name, unsigned long modifiers,
713 unsigned long alignment, unsigned int byte_size)
715 if ((modifiers & MOD_STATIC) == 0)
716 printf(".globl %s\n", name);
717 emit_section(".data");
718 if (alignment)
719 printf("\t.align %lu\n", alignment);
720 printf("\t.type\t%s, @object\n", name);
721 printf("\t.size\t%s, %d\n", name, byte_size);
722 printf("%s:\n", name);
725 /* emit value (only) for an initializer scalar */
726 static void emit_scalar(struct expression *expr, unsigned int bit_size)
728 const char *type;
729 long long ll;
731 assert(expr->type == EXPR_VALUE);
733 if (expr->value == 0ULL) {
734 printf("\t.zero\t%d\n", bit_size / 8);
735 return;
738 ll = (long long) expr->value;
740 switch (bit_size) {
741 case 8: type = "byte"; ll = (char) ll; break;
742 case 16: type = "value"; ll = (short) ll; break;
743 case 32: type = "long"; ll = (int) ll; break;
744 case 64: type = "quad"; break;
745 default: type = NULL; break;
748 assert(type != NULL);
750 printf("\t.%s\t%Ld\n", type, ll);
753 static void emit_global_noinit(const char *name, unsigned long modifiers,
754 unsigned long alignment, unsigned int byte_size)
756 char s[64];
758 if (modifiers & MOD_STATIC) {
759 sprintf(s, "\t.local\t%s\n", name);
760 textbuf_push(&unit_post_text, s);
762 if (alignment)
763 sprintf(s, "\t.comm\t%s,%d,%lu\n", name, byte_size, alignment);
764 else
765 sprintf(s, "\t.comm\t%s,%d\n", name, byte_size);
766 textbuf_push(&unit_post_text, s);
769 static int ea_current, ea_last;
771 static void emit_initializer(struct symbol *sym,
772 struct expression *expr)
774 int distance = ea_current - ea_last - 1;
776 if (distance > 0)
777 printf("\t.zero\t%d\n", (sym->bit_size / 8) * distance);
779 if (expr->type == EXPR_VALUE) {
780 struct symbol *base_type = sym->ctype.base_type;
781 assert(base_type != NULL);
783 emit_scalar(expr, sym->bit_size / get_expression_value(base_type->array_size));
784 return;
786 if (expr->type != EXPR_INITIALIZER)
787 return;
789 assert(0); /* FIXME */
792 static int sort_array_cmp(const struct expression *a,
793 const struct expression *b)
795 int a_ofs = 0, b_ofs = 0;
797 if (a->type == EXPR_POS)
798 a_ofs = (int) a->init_offset;
799 if (b->type == EXPR_POS)
800 b_ofs = (int) b->init_offset;
802 return a_ofs - b_ofs;
805 /* move to front-end? */
806 static void sort_array(struct expression *expr)
808 struct expression *entry, **list;
809 unsigned int elem, sorted, i;
811 elem = 0;
812 FOR_EACH_PTR(expr->expr_list, entry) {
813 elem++;
814 } END_FOR_EACH_PTR;
816 if (!elem)
817 return;
819 list = malloc(sizeof(entry) * elem);
820 if (!list)
821 die("OOM in sort_array");
823 /* this code is no doubt evil and ignores EXPR_INDEX possibly
824 * to its detriment and other nasty things. improvements
825 * welcome.
827 i = 0;
828 sorted = 0;
829 FOR_EACH_PTR(expr->expr_list, entry) {
830 if ((entry->type == EXPR_POS) || (entry->type == EXPR_VALUE)) {
831 /* add entry to list[], in sorted order */
832 if (sorted == 0) {
833 list[0] = entry;
834 sorted = 1;
835 } else {
836 unsigned int i;
838 for (i = 0; i < sorted; i++)
839 if (sort_array_cmp(entry, list[i]) <= 0)
840 break;
842 /* If inserting into the middle of list[]
843 * instead of appending, we memmove.
844 * This is ugly, but thankfully
845 * uncommon. Input data with tons of
846 * entries very rarely have explicit
847 * offsets. convert to qsort eventually...
849 if (i != sorted)
850 memmove(&list[i + 1], &list[i],
851 (sorted - i) * sizeof(entry));
852 list[i] = entry;
853 sorted++;
856 } END_FOR_EACH_PTR;
858 i = 0;
859 FOR_EACH_PTR(expr->expr_list, entry) {
860 if ((entry->type == EXPR_POS) || (entry->type == EXPR_VALUE))
861 __list->list[__i] = list[i++];
862 } END_FOR_EACH_PTR;
866 static void emit_array(struct symbol *sym)
868 struct symbol *base_type = sym->ctype.base_type;
869 struct expression *expr = sym->initializer;
870 struct expression *entry;
872 assert(base_type != NULL);
874 stor_sym_init(sym);
876 ea_last = -1;
878 emit_object_pre(show_ident(sym->ident), sym->ctype.modifiers,
879 sym->ctype.alignment,
880 sym->bit_size / 8);
882 sort_array(expr);
884 FOR_EACH_PTR(expr->expr_list, entry) {
885 if (entry->type == EXPR_VALUE) {
886 ea_current = 0;
887 emit_initializer(sym, entry);
888 ea_last = ea_current;
889 } else if (entry->type == EXPR_POS) {
890 ea_current =
891 entry->init_offset / (base_type->bit_size / 8);
892 emit_initializer(sym, entry->init_expr);
893 ea_last = ea_current;
895 } END_FOR_EACH_PTR;
898 static void emit_one_symbol(struct symbol *sym, void *dummy, int flags)
900 x86_symbol(sym);
903 void emit_unit(const char *basename, struct symbol_list *list)
905 emit_unit_pre(basename);
906 symbol_iterate(list, emit_one_symbol, NULL);
907 emit_unit_post();
910 static void emit_copy(struct storage *src, struct symbol *src_ctype,
911 struct storage *dest, struct symbol *dest_ctype)
913 /* FIXME: Bitfield move! */
915 emit_move(src, REG_EAX, src_ctype, "begin copy ..");
916 emit_move(REG_EAX, dest, dest_ctype, ".... end copy");
919 static void emit_store(struct expression *dest_expr, struct storage *dest,
920 struct storage *src, int bits)
922 /* FIXME: Bitfield store! */
923 printf("\tst.%d\t\tv%d,[v%d]\n", bits, src->pseudo, dest->pseudo);
926 static void emit_scalar_noinit(struct symbol *sym)
928 emit_global_noinit(show_ident(sym->ident),
929 sym->ctype.modifiers, sym->ctype.alignment,
930 sym->bit_size / 8);
931 stor_sym_init(sym);
934 static void emit_array_noinit(struct symbol *sym)
936 emit_global_noinit(show_ident(sym->ident),
937 sym->ctype.modifiers, sym->ctype.alignment,
938 get_expression_value(sym->array_size) * (sym->bit_size / 8));
939 stor_sym_init(sym);
942 static const char *opbits(const char *insn, unsigned int bits)
944 static char opbits_str[32];
945 char c;
947 switch (bits) {
948 case 8: c = 'b'; break;
949 case 16: c = 'w'; break;
950 case 32: c = 'l'; break;
951 case 64: c = 'q'; break;
952 default: assert(0); break;
955 sprintf(opbits_str, "%s%c", insn, bits);
957 return opbits_str;
960 static void emit_move(struct storage *src, struct storage *dest,
961 struct symbol *ctype, const char *comment)
963 unsigned int bits;
964 unsigned int is_signed;
965 unsigned int is_dest = (src->type == STOR_REG);
966 const char *opname;
968 if (ctype) {
969 bits = ctype->bit_size;
970 is_signed = type_is_signed(ctype);
971 } else {
972 bits = 32;
973 is_signed = 0;
976 if ((dest->type == STOR_REG) && (src->type == STOR_REG)) {
977 insn("mov", src, dest, NULL);
978 return;
981 switch (bits) {
982 case 8:
983 if (is_dest)
984 opname = "movb";
985 else {
986 if (is_signed) opname = "movsxb";
987 else opname = "movzxb";
989 break;
990 case 16:
991 if (is_dest)
992 opname = "movw";
993 else {
994 if (is_signed) opname = "movsxw";
995 else opname = "movzxw";
997 break;
999 case 32: opname = "movl"; break;
1000 case 64: opname = "movq"; break;
1002 default: assert(0); break;
1005 insn(opname, src, dest, comment);
1008 static struct storage *emit_compare(struct expression *expr)
1010 struct storage *left = x86_expression(expr->left);
1011 struct storage *right = x86_expression(expr->right);
1012 struct storage *new, *val;
1013 const char *opname = NULL;
1014 unsigned int is_signed = type_is_signed(expr->left->ctype); /* FIXME */
1015 unsigned int right_bits = expr->right->ctype->bit_size;
1017 switch(expr->op) {
1018 case '<':
1019 if (is_signed) opname = "setl";
1020 else opname = "setb";
1021 break;
1022 case '>':
1023 if (is_signed) opname = "setg";
1024 else opname = "seta";
1025 break;
1026 case SPECIAL_LTE:
1027 if (is_signed) opname = "setle";
1028 else opname = "setbe";
1029 break;
1030 case SPECIAL_GTE:
1031 if (is_signed) opname = "setge";
1032 else opname = "setae";
1033 break;
1035 case SPECIAL_EQUAL: opname = "sete"; break;
1036 case SPECIAL_NOTEQUAL: opname = "setne"; break;
1038 default:
1039 assert(0);
1040 break;
1043 /* init EDX to 0 */
1044 val = new_storage(STOR_VALUE);
1045 val->flags = STOR_WANTS_FREE;
1046 emit_move(val, REG_EDX, NULL, NULL);
1048 /* move op1 into EAX */
1049 emit_move(left, REG_EAX, expr->left->ctype, NULL);
1051 /* perform comparison, RHS (op1, right) and LHS (op2, EAX) */
1052 insn(opbits("cmp", right_bits), right, REG_EAX, NULL);
1054 /* store result of operation, 0 or 1, in DL using SETcc */
1055 insn(opname, REG_DL, NULL, NULL);
1057 /* finally, store the result (DL) in a new pseudo / stack slot */
1058 new = stack_alloc(4);
1059 emit_move(REG_EDX, new, NULL, "end EXPR_COMPARE");
1061 return new;
1064 static struct storage *emit_value(struct expression *expr)
1066 #if 0 /* old and slow way */
1067 struct storage *new = stack_alloc(4);
1068 struct storage *val;
1070 val = new_storage(STOR_VALUE);
1071 val->value = (long long) expr->value;
1072 val->flags = STOR_WANTS_FREE;
1073 insn("movl", val, new, NULL);
1075 return new;
1076 #else
1077 struct storage *val;
1079 val = new_storage(STOR_VALUE);
1080 val->value = (long long) expr->value;
1082 return val; /* FIXME: memory leak */
1083 #endif
1086 static struct storage *emit_binop(struct expression *expr)
1088 struct storage *left = x86_expression(expr->left);
1089 struct storage *right = x86_expression(expr->right);
1090 struct storage *new;
1091 const char *opname = NULL;
1094 * FIXME FIXME this routine is so wrong it's not even funny.
1095 * On x86 both mod/div are handled with the same instruction.
1096 * We don't pay attention to signed/unsigned issues,
1097 * and like elsewhere we hardcode the operand size at 32 bits.
1100 switch (expr->op) {
1101 case '+': opname = "addl"; break;
1102 case '-': opname = "subl"; break;
1103 case '*': opname = "mull"; break;
1104 case '/': opname = "divl"; break;
1105 case '%': opname = "modl"; break;
1106 case '&': opname = "andl"; break;
1107 case '|': opname = "orl"; break;
1108 case '^': opname = "xorl"; break;
1109 case SPECIAL_LEFTSHIFT: opname = "shll"; break;
1110 case SPECIAL_RIGHTSHIFT: opname = "shrl"; break;
1111 default: assert(0); break;
1114 /* load op2 into EAX */
1115 insn("movl", right, REG_EAX, "EXPR_BINOP/COMMA/LOGICAL");
1117 /* perform binop */
1118 insn(opname, left, REG_EAX, NULL);
1120 /* store result (EAX) in new pseudo / stack slot */
1121 new = stack_alloc(4);
1122 insn("movl", REG_EAX, new, "end EXPR_BINOP");
1124 return new;
1127 static void emit_if_conditional(struct statement *stmt)
1129 struct storage *val, *target_val;
1130 int target;
1131 struct expression *cond = stmt->if_conditional;
1133 /* This is only valid if nobody can jump into the "dead" statement */
1134 #if 0
1135 if (cond->type == EXPR_VALUE) {
1136 struct statement *s = stmt->if_true;
1137 if (!cond->value)
1138 s = stmt->if_false;
1139 x86_statement(s);
1140 break;
1142 #endif
1143 val = x86_expression(cond);
1145 /* load 'if' test result into EAX */
1146 insn("movl", val, REG_EAX, "begin if conditional");
1148 /* compare 'if' test result */
1149 insn("test", REG_EAX, REG_EAX, NULL);
1151 /* create end-of-if label / if-failed labelto jump to,
1152 * and jump to it if the expression returned zero.
1154 target = new_label();
1155 target_val = new_storage(STOR_LABEL);
1156 target_val->label = target;
1157 target_val->flags = STOR_WANTS_FREE;
1158 insn("jz", target_val, NULL, NULL);
1160 x86_statement(stmt->if_true);
1161 if (stmt->if_false) {
1162 struct storage *last_val;
1163 int last;
1165 /* finished generating code for if-true statement.
1166 * add a jump-to-end jump to avoid falling through
1167 * to the if-false statement code.
1169 last = new_label();
1170 last_val = new_storage(STOR_LABEL);
1171 last_val->label = last;
1172 last_val->flags = STOR_WANTS_FREE;
1173 insn("jmp", last_val, NULL, NULL);
1175 /* if we have both if-true and if-false statements,
1176 * the failed-conditional case will fall through to here
1178 emit_label(target, NULL);
1180 target = last;
1181 x86_statement(stmt->if_false);
1184 emit_label(target, "end if");
1187 static struct storage *emit_inc_dec(struct expression *expr, int postop)
1189 struct storage *addr = x86_address_gen(expr->unop);
1190 struct storage *retval;
1191 char opname[16];
1193 strcpy(opname, opbits(expr->op == SPECIAL_INCREMENT ? "inc" : "dec",
1194 expr->ctype->bit_size));
1196 if (postop) {
1197 struct storage *new = stack_alloc(4);
1199 emit_copy(addr, expr->unop->ctype, new, NULL);
1201 retval = new;
1202 } else
1203 retval = addr;
1205 insn(opname, addr, NULL, NULL);
1207 return retval;
1210 static struct storage *emit_postop(struct expression *expr)
1212 return emit_inc_dec(expr, 1);
1215 static struct storage *emit_return_stmt(struct statement *stmt)
1217 struct function *f = current_func;
1218 struct expression *expr = stmt->ret_value;
1219 struct storage *val = NULL, *jmplbl;
1221 if (expr && expr->ctype) {
1222 val = x86_expression(expr);
1223 assert(val != NULL);
1224 emit_move(val, REG_EAX, expr->ctype, "return");
1227 jmplbl = new_storage(STOR_LABEL);
1228 jmplbl->flags |= STOR_WANTS_FREE;
1229 jmplbl->label = f->ret_target;
1230 insn("jmp", jmplbl, NULL, NULL);
1232 return val;
1235 static struct storage *emit_conditional_expr(struct expression *expr)
1237 struct storage *cond = x86_expression(expr->conditional);
1238 struct storage *true = x86_expression(expr->cond_true);
1239 struct storage *false = x86_expression(expr->cond_false);
1240 struct storage *new = stack_alloc(4);
1242 if (!true)
1243 true = cond;
1245 emit_move(cond, REG_EAX, expr->conditional->ctype,
1246 "begin EXPR_CONDITIONAL");
1247 emit_move(true, REG_ECX, expr->cond_true->ctype, NULL);
1248 emit_move(false, REG_EDX, expr->cond_false->ctype, NULL);
1250 /* test EAX (for zero/non-zero) */
1251 insn("test", REG_EAX, REG_EAX, NULL);
1253 /* if false, move EDX to ECX */
1254 insn("cmovz", REG_EDX, REG_ECX, NULL);
1256 /* finally, store the result (ECX) in a new pseudo / stack slot */
1257 new = stack_alloc(4);
1258 emit_move(REG_ECX, new, expr->ctype, "end EXPR_CONDITIONAL");
1259 /* FIXME: we lose type knowledge of expression result at this point */
1261 return new;
1264 static struct storage *emit_symbol_expr_init(struct symbol *sym)
1266 struct expression *expr = sym->initializer;
1267 struct symbol_private *priv = sym->aux;
1269 if (priv == NULL) {
1270 priv = calloc(1, sizeof(*priv));
1271 sym->aux = priv;
1273 if (expr == NULL) {
1274 struct storage *new = stack_alloc(4);
1275 fprintf(stderr, "FIXME! no value for symbol. creating pseudo %d (stack offset %d)\n",
1276 new->pseudo, new->pseudo * 4);
1277 priv->addr = new;
1278 } else {
1279 priv->addr = x86_expression(expr);
1283 return priv->addr;
1286 static struct storage *emit_string_expr(struct expression *expr)
1288 struct function *f = current_func;
1289 int label = new_label();
1290 struct storage *new;
1292 push_cstring(f, expr->string, label);
1294 new = new_storage(STOR_LABEL);
1295 new->label = label;
1296 new->flags = STOR_LABEL_VAL | STOR_WANTS_FREE;
1297 return new;
1300 static struct storage *emit_cast_expr(struct expression *expr)
1302 struct symbol *old_type, *new_type;
1303 struct storage *op = x86_expression(expr->cast_expression);
1304 int oldbits, newbits;
1305 struct storage *new;
1307 old_type = expr->cast_expression->ctype;
1308 new_type = expr->cast_type;
1310 oldbits = old_type->bit_size;
1311 newbits = new_type->bit_size;
1312 if (oldbits >= newbits)
1313 return op;
1315 emit_move(op, REG_EAX, old_type, "begin cast ..");
1317 new = stack_alloc(4);
1318 emit_move(REG_EAX, new, new_type, ".... end cast");
1320 return new;
1323 static struct storage *emit_regular_preop(struct expression *expr)
1325 struct storage *target = x86_expression(expr->unop);
1326 struct storage *val, *new = stack_alloc(4);
1327 const char *opname = NULL;
1329 switch (expr->op) {
1330 case '!':
1331 val = new_storage(STOR_VALUE);
1332 val->flags = STOR_WANTS_FREE;
1333 emit_move(val, REG_EDX, NULL, NULL);
1334 emit_move(target, REG_EAX, expr->unop->ctype, NULL);
1335 insn("test", REG_EAX, REG_EAX, NULL);
1336 insn("setz", REG_DL, NULL, NULL);
1337 emit_move(REG_EDX, new, expr->unop->ctype, NULL);
1339 break;
1340 case '~':
1341 opname = "not";
1342 case '-':
1343 if (!opname)
1344 opname = "neg";
1345 emit_move(target, REG_EAX, expr->unop->ctype, NULL);
1346 insn(opname, REG_EAX, NULL, NULL);
1347 emit_move(REG_EAX, new, expr->unop->ctype, NULL);
1348 break;
1349 default:
1350 assert(0);
1351 break;
1354 return new;
1357 static void emit_case_statement(struct statement *stmt)
1359 emit_labelsym(stmt->case_label, NULL);
1360 x86_statement(stmt->case_statement);
1363 static void emit_switch_statement(struct statement *stmt)
1365 struct storage *val = x86_expression(stmt->switch_expression);
1366 struct symbol *sym, *default_sym = NULL;
1367 struct storage *labelsym, *label;
1368 int switch_end = 0;
1370 emit_move(val, REG_EAX, stmt->switch_expression->ctype, "begin case");
1373 * This is where a _real_ back-end would go through the
1374 * cases to decide whether to use a lookup table or a
1375 * series of comparisons etc
1377 FOR_EACH_PTR(stmt->switch_case->symbol_list, sym) {
1378 struct statement *case_stmt = sym->stmt;
1379 struct expression *expr = case_stmt->case_expression;
1380 struct expression *to = case_stmt->case_to;
1382 /* default: */
1383 if (!expr)
1384 default_sym = sym;
1386 /* case NNN: */
1387 else {
1388 struct storage *case_val = new_val(expr->value);
1390 assert (expr->type == EXPR_VALUE);
1392 insn("cmpl", case_val, REG_EAX, NULL);
1394 if (!to) {
1395 labelsym = new_labelsym(sym);
1396 insn("je", labelsym, NULL, NULL);
1397 } else {
1398 int next_test;
1400 label = new_storage(STOR_LABEL);
1401 label->flags |= STOR_WANTS_FREE;
1402 label->label = next_test = new_label();
1404 /* FIXME: signed/unsigned */
1405 insn("jl", label, NULL, NULL);
1407 case_val = new_val(to->value);
1408 insn("cmpl", case_val, REG_EAX, NULL);
1410 /* TODO: implement and use refcounting... */
1411 label = new_storage(STOR_LABEL);
1412 label->flags |= STOR_WANTS_FREE;
1413 label->label = next_test;
1415 /* FIXME: signed/unsigned */
1416 insn("jg", label, NULL, NULL);
1418 labelsym = new_labelsym(sym);
1419 insn("jmp", labelsym, NULL, NULL);
1421 emit_label(next_test, NULL);
1424 } END_FOR_EACH_PTR;
1426 if (default_sym) {
1427 labelsym = new_labelsym(default_sym);
1428 insn("jmp", labelsym, NULL, "default");
1429 } else {
1430 label = new_storage(STOR_LABEL);
1431 label->flags |= STOR_WANTS_FREE;
1432 label->label = switch_end = new_label();
1433 insn("jmp", label, NULL, "goto end of switch");
1436 x86_statement(stmt->switch_statement);
1438 if (stmt->switch_break->used)
1439 emit_labelsym(stmt->switch_break, NULL);
1441 if (switch_end)
1442 emit_label(switch_end, NULL);
1445 static void x86_struct_member(struct symbol *sym, void *data, int flags)
1447 if (flags & ITERATE_FIRST)
1448 printf(" {\n\t");
1449 printf("%s:%d:%ld at offset %ld", show_ident(sym->ident), sym->bit_size, sym->ctype.alignment, sym->offset);
1450 if (sym->fieldwidth)
1451 printf("[%d..%d]", sym->bit_offset, sym->bit_offset+sym->fieldwidth-1);
1452 if (flags & ITERATE_LAST)
1453 printf("\n} ");
1454 else
1455 printf(", ");
1458 static void x86_symbol(struct symbol *sym)
1460 struct symbol *type;
1462 if (!sym)
1463 return;
1465 type = sym->ctype.base_type;
1466 if (!type)
1467 return;
1470 * Show actual implementation information
1472 switch (type->type) {
1474 case SYM_ARRAY:
1475 if (sym->initializer)
1476 emit_array(sym);
1477 else
1478 emit_array_noinit(sym);
1479 break;
1481 case SYM_BASETYPE:
1482 if (sym->initializer) {
1483 emit_object_pre(show_ident(sym->ident),
1484 sym->ctype.modifiers,
1485 sym->ctype.alignment,
1486 sym->bit_size / 8);
1487 emit_scalar(sym->initializer, sym->bit_size);
1488 stor_sym_init(sym);
1489 } else
1490 emit_scalar_noinit(sym);
1491 break;
1493 case SYM_STRUCT:
1494 symbol_iterate(type->symbol_list, x86_struct_member, NULL);
1495 break;
1497 case SYM_UNION:
1498 symbol_iterate(type->symbol_list, x86_struct_member, NULL);
1499 break;
1501 case SYM_FN: {
1502 struct statement *stmt = type->stmt;
1503 if (stmt) {
1504 emit_func_pre(sym);
1505 x86_statement(stmt);
1506 emit_func_post(sym);
1508 break;
1511 default:
1512 break;
1515 if (sym->initializer && (type->type != SYM_BASETYPE) &&
1516 (type->type != SYM_ARRAY)) {
1517 printf(" = \n");
1518 x86_expression(sym->initializer);
1522 static void x86_symbol_init(struct symbol *sym);
1524 static void x86_symbol_decl(struct symbol_list *syms)
1526 struct symbol *sym;
1527 FOR_EACH_PTR(syms, sym) {
1528 x86_symbol_init(sym);
1529 } END_FOR_EACH_PTR;
1532 static void loopstk_push(int cont_lbl, int loop_bottom_lbl)
1534 struct function *f = current_func;
1535 struct loop_stack *ls;
1537 ls = malloc(sizeof(*ls));
1538 ls->continue_lbl = cont_lbl;
1539 ls->loop_bottom_lbl = loop_bottom_lbl;
1540 ls->next = f->loop_stack;
1541 f->loop_stack = ls;
1544 static void loopstk_pop(void)
1546 struct function *f = current_func;
1547 struct loop_stack *ls;
1549 assert(f->loop_stack != NULL);
1550 ls = f->loop_stack;
1551 f->loop_stack = f->loop_stack->next;
1552 free(ls);
1555 static int loopstk_break(void)
1557 return current_func->loop_stack->loop_bottom_lbl;
1560 static int loopstk_continue(void)
1562 return current_func->loop_stack->continue_lbl;
1565 static void emit_loop(struct statement *stmt)
1567 struct statement *pre_statement = stmt->iterator_pre_statement;
1568 struct expression *pre_condition = stmt->iterator_pre_condition;
1569 struct statement *statement = stmt->iterator_statement;
1570 struct statement *post_statement = stmt->iterator_post_statement;
1571 struct expression *post_condition = stmt->iterator_post_condition;
1572 int loop_top = 0, loop_bottom, loop_continue;
1573 int have_bottom = 0;
1574 struct storage *val;
1576 loop_bottom = new_label();
1577 loop_continue = new_label();
1578 loopstk_push(loop_continue, loop_bottom);
1580 x86_symbol_decl(stmt->iterator_syms);
1581 x86_statement(pre_statement);
1582 if (pre_condition) {
1583 if (pre_condition->type == EXPR_VALUE) {
1584 if (!pre_condition->value) {
1585 struct storage *lbv;
1586 lbv = new_storage(STOR_LABEL);
1587 lbv->label = loop_bottom;
1588 lbv->flags = STOR_WANTS_FREE;
1589 insn("jmp", lbv, NULL, "go to loop bottom");
1590 have_bottom = 1;
1592 } else {
1593 struct storage *lbv = new_storage(STOR_LABEL);
1594 lbv->label = loop_bottom;
1595 lbv->flags = STOR_WANTS_FREE;
1596 have_bottom = 1;
1598 val = x86_expression(pre_condition);
1600 emit_move(val, REG_EAX, NULL, "loop pre condition");
1601 insn("test", REG_EAX, REG_EAX, NULL);
1602 insn("jz", lbv, NULL, NULL);
1605 if (!post_condition || post_condition->type != EXPR_VALUE || post_condition->value) {
1606 loop_top = new_label();
1607 emit_label(loop_top, "loop top");
1609 x86_statement(statement);
1610 if (stmt->iterator_continue->used)
1611 emit_label(loop_continue, "'continue' iterator");
1612 x86_statement(post_statement);
1613 if (!post_condition) {
1614 struct storage *lbv = new_storage(STOR_LABEL);
1615 lbv->label = loop_top;
1616 lbv->flags = STOR_WANTS_FREE;
1617 insn("jmp", lbv, NULL, "go to loop top");
1618 } else if (post_condition->type == EXPR_VALUE) {
1619 if (post_condition->value) {
1620 struct storage *lbv = new_storage(STOR_LABEL);
1621 lbv->label = loop_top;
1622 lbv->flags = STOR_WANTS_FREE;
1623 insn("jmp", lbv, NULL, "go to loop top");
1625 } else {
1626 struct storage *lbv = new_storage(STOR_LABEL);
1627 lbv->label = loop_top;
1628 lbv->flags = STOR_WANTS_FREE;
1630 val = x86_expression(post_condition);
1632 emit_move(val, REG_EAX, NULL, "loop post condition");
1633 insn("test", REG_EAX, REG_EAX, NULL);
1634 insn("jnz", lbv, NULL, NULL);
1636 if (have_bottom || stmt->iterator_break->used)
1637 emit_label(loop_bottom, "loop bottom");
1639 loopstk_pop();
1643 * Print out a statement
1645 static struct storage *x86_statement(struct statement *stmt)
1647 if (!stmt)
1648 return 0;
1649 switch (stmt->type) {
1650 case STMT_RETURN:
1651 return emit_return_stmt(stmt);
1652 case STMT_COMPOUND: {
1653 struct statement *s;
1654 struct storage *last = NULL;
1656 x86_symbol_decl(stmt->syms);
1657 FOR_EACH_PTR(stmt->stmts, s) {
1658 last = x86_statement(s);
1659 } END_FOR_EACH_PTR;
1661 return last;
1664 case STMT_EXPRESSION:
1665 return x86_expression(stmt->expression);
1666 case STMT_IF:
1667 emit_if_conditional(stmt);
1668 return NULL;
1670 case STMT_CASE:
1671 emit_case_statement(stmt);
1672 break;
1673 case STMT_SWITCH:
1674 emit_switch_statement(stmt);
1675 break;
1677 case STMT_ITERATOR:
1678 emit_loop(stmt);
1679 break;
1681 case STMT_NONE:
1682 break;
1684 case STMT_LABEL:
1685 printf(".L%p:\n", stmt->label_identifier);
1686 x86_statement(stmt->label_statement);
1687 break;
1689 case STMT_GOTO:
1690 if (stmt->goto_expression) {
1691 struct storage *val = x86_expression(stmt->goto_expression);
1692 printf("\tgoto *v%d\n", val->pseudo);
1693 } else if (!strcmp("break", show_ident(stmt->goto_label->ident))) {
1694 struct storage *lbv = new_storage(STOR_LABEL);
1695 lbv->label = loopstk_break();
1696 lbv->flags = STOR_WANTS_FREE;
1697 insn("jmp", lbv, NULL, "'break'; go to loop bottom");
1698 } else if (!strcmp("continue", show_ident(stmt->goto_label->ident))) {
1699 struct storage *lbv = new_storage(STOR_LABEL);
1700 lbv->label = loopstk_continue();
1701 lbv->flags = STOR_WANTS_FREE;
1702 insn("jmp", lbv, NULL, "'continue'; go to loop top");
1703 } else {
1704 struct storage *labelsym = new_labelsym(stmt->goto_label);
1705 insn("jmp", labelsym, NULL, NULL);
1707 break;
1708 case STMT_ASM:
1709 printf("\tasm( .... )\n");
1710 break;
1713 return NULL;
1716 static struct storage *x86_call_expression(struct expression *expr)
1718 struct function *f = current_func;
1719 struct symbol *direct;
1720 struct expression *arg, *fn;
1721 struct storage *retval, *fncall;
1722 int framesize;
1723 char s[64];
1725 if (!expr->ctype) {
1726 warn(expr->pos, "\tcall with no type!");
1727 return NULL;
1730 framesize = 0;
1731 FOR_EACH_PTR_REVERSE(expr->args, arg) {
1732 struct storage *new = x86_expression(arg);
1733 int size = arg->ctype->bit_size;
1735 /* FIXME: pay attention to 'size' */
1736 insn("pushl", new, NULL,
1737 !framesize ? "begin function call" : NULL);
1739 framesize += size >> 3;
1740 } END_FOR_EACH_PTR_REVERSE;
1742 fn = expr->fn;
1744 /* Remove dereference, if any */
1745 direct = NULL;
1746 if (fn->type == EXPR_PREOP) {
1747 if (fn->unop->type == EXPR_SYMBOL) {
1748 struct symbol *sym = fn->unop->symbol;
1749 if (sym->ctype.base_type->type == SYM_FN)
1750 direct = sym;
1753 if (direct) {
1754 struct storage *direct_stor = new_storage(STOR_SYM);
1755 direct_stor->flags |= STOR_WANTS_FREE;
1756 direct_stor->sym = direct;
1757 insn("call", direct_stor, NULL, NULL);
1758 } else {
1759 fncall = x86_expression(fn);
1760 emit_move(fncall, REG_EAX, fn->ctype, NULL);
1762 strcpy(s, "\tcall\t*%eax\n");
1763 push_text_atom(f, s);
1766 /* FIXME: pay attention to BITS_IN_POINTER */
1767 if (framesize) {
1768 struct storage *val = new_storage(STOR_VALUE);
1769 val->value = (long long) framesize;
1770 val->flags = STOR_WANTS_FREE;
1771 insn("addl", val, REG_ESP, NULL);
1774 retval = stack_alloc(4);
1775 emit_move(REG_EAX, retval, NULL, "end function call");
1777 return retval;
1780 static struct storage *x86_address_gen(struct expression *expr)
1782 struct function *f = current_func;
1783 struct storage *addr;
1784 struct storage *new;
1785 char s[32];
1787 if ((expr->type != EXPR_PREOP) || (expr->op != '*'))
1788 return x86_expression(expr->address);
1790 addr = x86_expression(expr->unop);
1791 if (expr->unop->type == EXPR_SYMBOL)
1792 return addr;
1794 emit_move(addr, REG_EAX, NULL, "begin deref ..");
1796 /* FIXME: operand size */
1797 strcpy(s, "\tmovl\t(%eax), %ecx\n");
1798 push_text_atom(f, s);
1800 new = stack_alloc(4);
1801 emit_move(REG_ECX, new, NULL, ".... end deref");
1803 return new;
1806 static struct storage *x86_assignment(struct expression *expr)
1808 struct expression *target = expr->left;
1809 struct storage *val, *addr;
1810 int bits;
1812 if (!expr->ctype)
1813 return NULL;
1815 bits = expr->ctype->bit_size;
1816 val = x86_expression(expr->right);
1817 addr = x86_address_gen(target);
1819 switch (val->type) {
1820 /* copy, where both operands are memory */
1821 case STOR_PSEUDO:
1822 case STOR_ARG:
1823 emit_copy(val, expr->right->ctype, addr, expr->left->ctype);
1824 break;
1826 /* copy, one or zero operands are memory */
1827 case STOR_REG:
1828 case STOR_SYM:
1829 case STOR_VALUE:
1830 case STOR_LABEL:
1831 emit_move(val, addr, expr->left->ctype, NULL);
1832 break;
1834 case STOR_LABELSYM:
1835 assert(0);
1836 break;
1838 return val;
1841 static int x86_initialization(struct symbol *sym, struct expression *expr)
1843 struct storage *val, *addr;
1844 int bits;
1846 if (!expr->ctype)
1847 return 0;
1849 bits = expr->ctype->bit_size;
1850 val = x86_expression(expr);
1851 addr = x86_symbol_expr(sym);
1852 // FIXME! The "target" expression is for bitfield store information.
1853 // Leave it NULL, which works fine.
1854 emit_store(NULL, addr, val, bits);
1855 return 0;
1858 static struct storage *x86_access(struct expression *expr)
1860 return x86_address_gen(expr);
1863 static struct storage *x86_preop(struct expression *expr)
1866 * '*' is an lvalue access, and is fundamentally different
1867 * from an arithmetic operation. Maybe it should have an
1868 * expression type of its own..
1870 if (expr->op == '*')
1871 return x86_access(expr);
1872 if (expr->op == SPECIAL_INCREMENT || expr->op == SPECIAL_DECREMENT)
1873 return emit_inc_dec(expr, 0);
1874 return emit_regular_preop(expr);
1877 static struct storage *x86_symbol_expr(struct symbol *sym)
1879 struct storage *new = stack_alloc(4);
1881 if (sym->ctype.modifiers & (MOD_TOPLEVEL | MOD_EXTERN | MOD_STATIC)) {
1882 printf("\tmovi.%d\t\tv%d,$%s\n", BITS_IN_POINTER, new->pseudo, show_ident(sym->ident));
1883 return new;
1885 if (sym->ctype.modifiers & MOD_ADDRESSABLE) {
1886 printf("\taddi.%d\t\tv%d,vFP,$%lld\n", BITS_IN_POINTER, new->pseudo, sym->value);
1887 return new;
1889 printf("\taddi.%d\t\tv%d,vFP,$offsetof(%s:%p)\n", BITS_IN_POINTER, new->pseudo, show_ident(sym->ident), sym);
1890 return new;
1893 static void x86_symbol_init(struct symbol *sym)
1895 struct symbol_private *priv = sym->aux;
1896 struct expression *expr = sym->initializer;
1897 struct storage *new;
1899 if (expr)
1900 new = x86_expression(expr);
1901 else
1902 new = stack_alloc(sym->bit_size / 8);
1904 if (!priv) {
1905 priv = calloc(1, sizeof(*priv));
1906 sym->aux = priv;
1907 /* FIXME: leak! we don't free... */
1908 /* (well, we don't free symbols either) */
1911 priv->addr = new;
1914 static int type_is_signed(struct symbol *sym)
1916 if (sym->type == SYM_NODE)
1917 sym = sym->ctype.base_type;
1918 if (sym->type == SYM_PTR)
1919 return 0;
1920 return !(sym->ctype.modifiers & MOD_UNSIGNED);
1923 static struct storage *x86_bitfield_expr(struct expression *expr)
1925 return x86_access(expr);
1928 static struct storage *x86_label_expr(struct expression *expr)
1930 struct storage *new = stack_alloc(4);
1931 printf("\tmovi.%d\t\tv%d,.L%p\n",BITS_IN_POINTER, new->pseudo, expr->label_symbol);
1932 return new;
1935 static struct storage *x86_statement_expr(struct expression *expr)
1937 return x86_statement(expr->statement);
1940 static int x86_position_expr(struct expression *expr, struct symbol *base)
1942 struct storage *new = x86_expression(expr->init_expr);
1943 struct symbol *ctype = expr->init_sym;
1945 printf("\tinsert v%d at [%d:%d] of %s\n", new->pseudo,
1946 expr->init_offset, ctype->bit_offset,
1947 show_ident(base->ident));
1948 return 0;
1951 static void x86_initializer_expr(struct expression *expr, struct symbol *ctype)
1953 struct expression *entry;
1955 FOR_EACH_PTR(expr->expr_list, entry) {
1956 // Nested initializers have their positions already
1957 // recursively calculated - just output them too
1958 if (entry->type == EXPR_INITIALIZER) {
1959 x86_initializer_expr(entry, ctype);
1960 continue;
1963 // Ignore initializer indexes and identifiers - the
1964 // evaluator has taken them into account
1965 if (entry->type == EXPR_IDENTIFIER || entry->type == EXPR_INDEX)
1966 continue;
1967 if (entry->type == EXPR_POS) {
1968 x86_position_expr(entry, ctype);
1969 continue;
1971 x86_initialization(ctype, entry);
1972 } END_FOR_EACH_PTR;
1976 * Print out an expression. Return the pseudo that contains the
1977 * variable.
1979 static struct storage *x86_expression(struct expression *expr)
1981 if (!expr)
1982 return 0;
1984 if (!expr->ctype) {
1985 struct position *pos = &expr->pos;
1986 printf("\tno type at %s:%d:%d\n",
1987 input_streams[pos->stream].name,
1988 pos->line, pos->pos);
1989 return 0;
1992 switch (expr->type) {
1993 case EXPR_CALL:
1994 return x86_call_expression(expr);
1996 case EXPR_ASSIGNMENT:
1997 return x86_assignment(expr);
1999 case EXPR_COMPARE:
2000 return emit_compare(expr);
2001 case EXPR_BINOP:
2002 case EXPR_COMMA:
2003 case EXPR_LOGICAL:
2004 return emit_binop(expr);
2005 case EXPR_PREOP:
2006 return x86_preop(expr);
2007 case EXPR_POSTOP:
2008 return emit_postop(expr);
2009 case EXPR_SYMBOL:
2010 return emit_symbol_expr_init(expr->symbol);
2011 case EXPR_DEREF:
2012 case EXPR_SIZEOF:
2013 warn(expr->pos, "invalid expression after evaluation");
2014 return 0;
2015 case EXPR_CAST:
2016 return emit_cast_expr(expr);
2017 case EXPR_VALUE:
2018 return emit_value(expr);
2019 case EXPR_STRING:
2020 return emit_string_expr(expr);
2021 case EXPR_BITFIELD:
2022 return x86_bitfield_expr(expr);
2023 case EXPR_INITIALIZER:
2024 x86_initializer_expr(expr, expr->ctype);
2025 return NULL;
2026 case EXPR_CONDITIONAL:
2027 return emit_conditional_expr(expr);
2028 case EXPR_STATEMENT:
2029 return x86_statement_expr(expr);
2030 case EXPR_LABEL:
2031 return x86_label_expr(expr);
2033 // None of these should exist as direct expressions: they are only
2034 // valid as sub-expressions of initializers.
2035 case EXPR_POS:
2036 warn(expr->pos, "unable to show plain initializer position expression");
2037 return 0;
2038 case EXPR_IDENTIFIER:
2039 warn(expr->pos, "unable to show identifier expression");
2040 return 0;
2041 case EXPR_INDEX:
2042 warn(expr->pos, "unable to show index expression");
2043 return 0;
2045 return 0;