o split handle_switch, to make it more lib friendly
[smatch.git] / compile-i386.c
blob5ebaf6a42ced5c9c8b86a80562e69658230daf81
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
13 #include <stdarg.h>
14 #include <stdlib.h>
15 #include <stdio.h>
16 #include <string.h>
17 #include <ctype.h>
18 #include <unistd.h>
19 #include <fcntl.h>
20 #include <assert.h>
22 #include "lib.h"
23 #include "token.h"
24 #include "parse.h"
25 #include "symbol.h"
26 #include "scope.h"
27 #include "expression.h"
28 #include "target.h"
31 struct textbuf;
32 struct textbuf {
33 unsigned int len; /* does NOT include terminating null */
34 char *text;
35 struct textbuf *next;
36 struct textbuf *prev;
39 struct function {
40 int pseudo_nr;
41 struct ptr_list *pseudo_list;
42 struct ptr_list *atom_list;
43 struct ptr_list *str_list;
44 struct symbol **argv;
45 unsigned int argc;
46 int ret_target;
49 enum storage_type {
50 STOR_PSEUDO, /* variable stored on the stack */
51 STOR_ARG, /* function argument */
52 STOR_SYM, /* a symbol we can directly ref in the asm */
53 STOR_REG, /* scratch register */
54 STOR_VALUE, /* integer constant */
55 STOR_LABEL, /* label / jump target */
58 struct reg_info {
59 const char *name;
62 struct storage {
63 enum storage_type type;
65 /* STOR_REG */
66 struct reg_info *reg;
68 union {
69 /* STOR_PSEUDO */
70 struct {
71 int pseudo;
73 /* STOR_ARG */
74 struct {
75 int idx;
77 /* STOR_SYM */
78 struct {
79 struct symbol *sym;
81 /* STOR_VALUE */
82 struct {
83 long long value;
85 /* STOR_LABEL */
86 struct {
87 int label;
88 unsigned long flags;
93 enum {
94 STOR_LABEL_VAL = (1 << 0),
97 struct symbol_private {
98 struct storage *addr;
101 enum atom_type {
102 ATOM_TEXT,
103 ATOM_INSN,
104 ATOM_CSTR,
107 enum {
108 ATOM_FREE_OP1 = (1 << 0),
109 ATOM_FREE_OP2 = (1 << 1),
112 struct atom {
113 enum atom_type type;
114 union {
115 /* stuff for text */
116 struct {
117 char *text;
118 unsigned int text_len; /* w/o terminating null */
121 /* stuff for insns */
122 struct {
123 char insn[32];
124 char comment[40];
125 struct storage *op1;
126 struct storage *op2;
127 unsigned long flags;
130 /* stuff for C strings */
131 struct {
132 struct string *string;
133 int label;
139 struct function *current_func = NULL;
140 struct textbuf *unit_post_text = NULL;
141 static const char *current_section;
143 static struct reg_info reg_info_table[] = {
144 { "%eax" },
145 { "%ecx" },
146 { "%edx" },
147 { "%esp" },
148 { "%dl" },
151 static struct storage hardreg_storage_table[] = {
152 { /* eax */
153 .type = STOR_REG,
154 .reg = &reg_info_table[0],
157 { /* ecx */
158 .type = STOR_REG,
159 .reg = &reg_info_table[1],
162 { /* edx */
163 .type = STOR_REG,
164 .reg = &reg_info_table[2],
167 { /* esp */
168 .type = STOR_REG,
169 .reg = &reg_info_table[3],
172 { /* dl */
173 .type = STOR_REG,
174 .reg = &reg_info_table[4],
178 #define REG_EAX (&hardreg_storage_table[0])
179 #define REG_ECX (&hardreg_storage_table[1])
180 #define REG_EDX (&hardreg_storage_table[2])
181 #define REG_ESP (&hardreg_storage_table[3])
182 #define REG_DL (&hardreg_storage_table[4])
185 static void emit_move(struct storage *src, struct storage *dest,
186 struct symbol *ctype, const char *comment,
187 unsigned long flags);
188 static int type_is_signed(struct symbol *sym);
189 static struct storage *x86_address_gen(struct expression *expr);
190 static struct storage *x86_symbol_expr(struct symbol *sym);
191 static void x86_symbol(struct symbol *sym);
192 static struct storage *x86_statement(struct statement *stmt);
193 static struct storage *x86_expression(struct expression *expr);
196 static inline unsigned int pseudo_offset(struct storage *s)
198 if (s->type != STOR_PSEUDO)
199 return 123456; /* intentionally bogus value */
201 return ((s->pseudo - 1) * 4);
204 static inline unsigned int arg_offset(struct storage *s)
206 if (s->type != STOR_ARG)
207 return 123456; /* intentionally bogus value */
209 /* FIXME: this is wrong wrong wrong */
210 return (current_func->pseudo_nr + 1 + s->idx) * 4;
213 static const char *pretty_offset(int ofs)
215 static char esp_buf[64];
217 if (ofs)
218 sprintf(esp_buf, "%d(%%esp)", ofs);
219 else
220 strcpy(esp_buf, "(%esp)");
222 return esp_buf;
225 static void stor_sym_init(struct symbol *sym)
227 struct storage *stor;
228 struct symbol_private *priv;
230 priv = calloc(1, sizeof(*priv) + sizeof(*stor));
231 if (!priv)
232 die("OOM in stor_sym_init");
234 stor = (struct storage *) (priv + 1);
236 priv->addr = stor;
237 stor->type = STOR_SYM;
238 stor->sym = sym;
241 static const char *stor_op_name(struct storage *s, unsigned long flags)
243 static char name[32];
245 switch (s->type) {
246 case STOR_PSEUDO:
247 strcpy(name, pretty_offset((int) pseudo_offset(s)));
248 break;
249 case STOR_ARG:
250 strcpy(name, pretty_offset((int) arg_offset(s)));
251 break;
252 case STOR_SYM:
253 strcpy(name, show_ident(s->sym->ident));
254 break;
255 case STOR_REG:
256 strcpy(name, s->reg->name);
257 break;
258 case STOR_VALUE:
259 sprintf(name, "$%Ld", s->value);
260 break;
261 case STOR_LABEL:
262 sprintf(name, "%s.L%d", flags & STOR_LABEL_VAL ? "$" : "",
263 s->label);
264 break;
267 return name;
270 static struct atom *new_atom(enum atom_type type)
272 struct atom *atom;
274 atom = calloc(1, sizeof(*atom)); /* TODO: chunked alloc */
275 if (!atom)
276 die("nuclear OOM");
278 atom->type = type;
280 return atom;
283 static inline void push_cstring(struct function *f, struct string *str,
284 int label)
286 struct atom *atom;
288 atom = new_atom(ATOM_CSTR);
289 atom->string = str;
290 atom->label = label;
292 add_ptr_list(&f->str_list, atom); /* note: _not_ atom_list */
295 static inline void push_atom(struct function *f, struct atom *atom)
297 add_ptr_list(&f->atom_list, atom);
300 static void push_text_atom(struct function *f, const char *text)
302 struct atom *atom = new_atom(ATOM_TEXT);
304 atom->text = strdup(text);
305 atom->text_len = strlen(text);
307 push_atom(f, atom);
310 static struct storage *new_storage(enum storage_type type)
312 struct storage *stor;
314 stor = calloc(1, sizeof(*stor));
315 if (!stor)
316 die("OOM in new_storage");
318 stor->type = type;
320 return stor;
323 static struct storage *new_pseudo(void)
325 struct function *f = current_func;
326 struct storage *stor;
328 assert(f != NULL);
330 stor = new_storage(STOR_PSEUDO);
331 stor->type = STOR_PSEUDO;
332 stor->pseudo = ++f->pseudo_nr;
334 add_ptr_list(&f->pseudo_list, stor);
336 return stor;
339 static int new_label(void)
341 static int label = 0;
342 return ++label;
345 static void textbuf_push(struct textbuf **buf_p, const char *text)
347 struct textbuf *tmp, *list = *buf_p;
348 unsigned int text_len = strlen(text);
349 unsigned int alloc_len = text_len + 1 + sizeof(*list);
351 tmp = calloc(1, alloc_len);
352 if (!tmp)
353 die("OOM on textbuf alloc");
355 tmp->text = ((void *) tmp) + sizeof(*tmp);
356 memcpy(tmp->text, text, text_len + 1);
357 tmp->len = text_len;
359 /* add to end of list */
360 if (!list) {
361 list = tmp;
362 tmp->prev = tmp;
363 } else {
364 tmp->prev = list->prev;
365 tmp->prev->next = tmp;
366 list->prev = tmp;
368 tmp->next = list;
370 *buf_p = list;
373 static void textbuf_emit(struct textbuf **buf_p)
375 struct textbuf *tmp, *list = *buf_p;
377 while (list) {
378 tmp = list;
379 if (tmp->next == tmp)
380 list = NULL;
381 else {
382 tmp->prev->next = tmp->next;
383 tmp->next->prev = tmp->prev;
384 list = tmp->next;
387 fputs(tmp->text, stdout);
389 free(tmp);
392 *buf_p = list;
395 static void insn(const char *insn, struct storage *op1, struct storage *op2,
396 const char *comment_in, unsigned long flags)
398 struct function *f = current_func;
399 struct atom *atom = new_atom(ATOM_INSN);
401 assert(insn != NULL);
403 strcpy(atom->insn, insn);
404 if (comment_in && (*comment_in))
405 strncpy(atom->comment, comment_in,
406 sizeof(atom->comment) - 1);
408 atom->op1 = op1;
409 atom->op2 = op2;
410 atom->flags = flags;
412 push_atom(f, atom);
415 static void emit_unit_pre(const char *basename)
417 printf("\t.file\t\"%s\"\n", basename);
420 static void emit_unit_post(void)
422 textbuf_emit(&unit_post_text);
423 printf("\t.ident\t\"sparse silly x86 backend (built %s)\"\n", __DATE__);
426 /* conditionally switch sections */
427 static void emit_section(const char *s)
429 if (s == current_section)
430 return;
431 if (current_section && (!strcmp(s, current_section)))
432 return;
434 printf("\t%s\n", s);
435 current_section = s;
438 static void emit_insn_atom(struct function *f, struct atom *atom)
440 char s[128];
441 char comment[64];
442 struct storage *op1 = atom->op1;
443 struct storage *op2 = atom->op2;
445 if (atom->comment[0])
446 sprintf(comment, "\t\t# %s", atom->comment);
447 else
448 comment[0] = 0;
450 if (atom->op2) {
451 char tmp[16];
452 strcpy(tmp, stor_op_name(op1, op1->flags));
453 sprintf(s, "\t%s\t%s, %s%s\n",
454 atom->insn, tmp, stor_op_name(op2, op2->flags), comment);
455 } else if (atom->op1)
456 sprintf(s, "\t%s\t%s%s%s\n",
457 atom->insn, stor_op_name(op1, op1->flags),
458 comment[0] ? "\t" : "", comment);
459 else
460 sprintf(s, "\t%s\t%s%s\n",
461 atom->insn,
462 comment[0] ? "\t\t" : "", comment);
464 write(STDOUT_FILENO, s, strlen(s));
467 static void emit_atom_list(struct function *f)
469 struct atom *atom;
471 FOR_EACH_PTR(f->atom_list, atom) {
472 switch (atom->type) {
473 case ATOM_TEXT: {
474 ssize_t rc = write(STDOUT_FILENO, atom->text,
475 atom->text_len);
476 (void) rc; /* FIXME */
477 break;
479 case ATOM_INSN:
480 emit_insn_atom(f, atom);
481 break;
482 case ATOM_CSTR:
483 assert(0);
484 break;
486 } END_FOR_EACH_PTR;
489 static void emit_string_list(struct function *f)
491 struct atom *atom;
493 emit_section(".section\t.rodata");
495 FOR_EACH_PTR(f->str_list, atom) {
496 /* FIXME: escape " in string */
497 printf(".L%d:\n", atom->label);
498 printf("\t.string\t%s\n", show_string(atom->string));
500 free(atom);
501 } END_FOR_EACH_PTR;
504 static void func_cleanup(struct function *f)
506 struct storage *stor;
507 struct atom *atom;
509 FOR_EACH_PTR(f->pseudo_list, stor) {
510 free(stor);
511 } END_FOR_EACH_PTR;
513 FOR_EACH_PTR(f->atom_list, atom) {
514 if ((atom->type == ATOM_TEXT) && (atom->text))
515 free(atom->text);
516 if (atom->flags & ATOM_FREE_OP1)
517 free(atom->op1);
518 if (atom->flags & ATOM_FREE_OP2)
519 free(atom->op2);
520 free(atom);
521 } END_FOR_EACH_PTR;
523 free_ptr_list(&f->pseudo_list);
524 free(f);
527 /* function prologue */
528 static void emit_func_pre(struct symbol *sym)
530 struct function *f;
531 struct symbol *arg;
532 unsigned int i, argc = 0, alloc_len;
533 unsigned char *mem;
534 struct symbol_private *privbase;
535 struct storage *storage_base;
536 struct symbol *base_type = sym->ctype.base_type;
538 FOR_EACH_PTR(base_type->arguments, arg) {
539 argc++;
540 } END_FOR_EACH_PTR;
542 alloc_len =
543 sizeof(*f) +
544 (argc * sizeof(struct symbol *)) +
545 (argc * sizeof(struct symbol_private)) +
546 (argc * sizeof(struct storage));
547 mem = calloc(1, alloc_len);
548 if (!mem)
549 die("OOM on func info");
551 f = (struct function *) mem;
552 mem += sizeof(*f);
553 f->argv = (struct symbol **) mem;
554 mem += (argc * sizeof(struct symbol *));
555 privbase = (struct symbol_private *) mem;
556 mem += (argc * sizeof(struct symbol_private));
557 storage_base = (struct storage *) mem;
559 f->argc = argc;
560 f->ret_target = new_label();
562 i = 0;
563 FOR_EACH_PTR(base_type->arguments, arg) {
564 f->argv[i] = arg;
565 arg->aux = &privbase[i];
566 storage_base[i].type = STOR_ARG;
567 storage_base[i].idx = i;
568 privbase[i].addr = &storage_base[i];
569 i++;
570 } END_FOR_EACH_PTR;
572 assert(current_func == NULL);
573 current_func = f;
576 /* function epilogue */
577 static void emit_func_post(struct symbol *sym)
579 const char *name = show_ident(sym->ident);
580 struct function *f = current_func;
581 int pseudo_nr = f->pseudo_nr;
582 char jump_target[16];
584 if (f->str_list)
585 emit_string_list(f);
587 /* function prologue */
588 emit_section(".text");
589 if ((sym->ctype.modifiers & MOD_STATIC) == 0)
590 printf(".globl %s\n", name);
591 printf("\t.type\t%s, @function\n", name);
592 printf("%s:\n", name);
594 if (pseudo_nr) {
595 char pseudo_const[16];
597 sprintf(pseudo_const, "$%d", pseudo_nr * 4);
598 printf("\tsubl\t%s, %%esp\n", pseudo_const);
601 /* function epilogue */
603 /* jump target for 'return' statements */
604 sprintf(jump_target, ".L%d:\n", f->ret_target);
605 push_text_atom(f, jump_target);
607 if (pseudo_nr) {
608 struct storage *val;
610 val = new_storage(STOR_VALUE);
611 val->value = (long long) (pseudo_nr * 4);
613 insn("addl", val, REG_ESP, NULL, ATOM_FREE_OP1);
616 insn("ret", NULL, NULL, NULL, 0);
618 /* output everything to stdout */
619 fflush(stdout); /* paranoia; needed? */
620 emit_atom_list(f);
622 /* function footer */
623 printf("\t.size\t%s, .-%s\n", name, name);
625 func_cleanup(f);
626 current_func = NULL;
629 /* emit object (a.k.a. variable, a.k.a. data) prologue */
630 static void emit_object_pre(const char *name, unsigned long modifiers,
631 unsigned long alignment, unsigned int byte_size)
633 if ((modifiers & MOD_STATIC) == 0)
634 printf(".globl %s\n", name);
635 emit_section(".data");
636 if (alignment)
637 printf("\t.align %lu\n", alignment);
638 printf("\t.type\t%s, @object\n", name);
639 printf("\t.size\t%s, %d\n", name, byte_size);
640 printf("%s:\n", name);
643 /* emit value (only) for an initializer scalar */
644 static void emit_scalar(struct expression *expr, unsigned int bit_size)
646 const char *type;
647 long long ll;
649 assert(expr->type == EXPR_VALUE);
651 if (expr->value == 0ULL) {
652 printf("\t.zero\t%d\n", bit_size / 8);
653 return;
656 ll = (long long) expr->value;
658 switch (bit_size) {
659 case 8: type = "byte"; ll = (char) ll; break;
660 case 16: type = "value"; ll = (short) ll; break;
661 case 32: type = "long"; ll = (int) ll; break;
662 case 64: type = "quad"; break;
663 default: type = NULL; break;
666 assert(type != NULL);
668 printf("\t.%s\t%Ld\n", type, ll);
671 static void emit_global_noinit(const char *name, unsigned long modifiers,
672 unsigned long alignment, unsigned int byte_size)
674 char s[64];
676 if (modifiers & MOD_STATIC) {
677 sprintf(s, "\t.local\t%s\n", name);
678 textbuf_push(&unit_post_text, s);
680 if (alignment)
681 sprintf(s, "\t.comm\t%s,%d,%lu\n", name, byte_size, alignment);
682 else
683 sprintf(s, "\t.comm\t%s,%d\n", name, byte_size);
684 textbuf_push(&unit_post_text, s);
687 static int ea_current, ea_last;
689 static void emit_initializer(struct symbol *sym,
690 struct expression *expr)
692 int distance = ea_current - ea_last - 1;
694 if (distance > 0)
695 printf("\t.zero\t%d\n", (sym->bit_size / 8) * distance);
697 if (expr->type == EXPR_VALUE) {
698 struct symbol *base_type = sym->ctype.base_type;
699 assert(base_type != NULL);
701 emit_scalar(expr, sym->bit_size / base_type->array_size);
702 return;
704 if (expr->type != EXPR_INITIALIZER)
705 return;
707 assert(0); /* FIXME */
710 static int sort_array_cmp(const struct expression *a,
711 const struct expression *b)
713 int a_ofs = 0, b_ofs = 0;
715 if (a->type == EXPR_POS)
716 a_ofs = (int) a->init_offset;
717 if (b->type == EXPR_POS)
718 b_ofs = (int) b->init_offset;
720 return a_ofs - b_ofs;
723 /* move to front-end? */
724 static void sort_array(struct expression *expr)
726 struct expression *entry, **list;
727 unsigned int elem, sorted, i;
729 elem = 0;
730 FOR_EACH_PTR(expr->expr_list, entry) {
731 elem++;
732 } END_FOR_EACH_PTR;
734 if (!elem)
735 return;
737 list = malloc(sizeof(entry) * elem);
738 if (!list)
739 die("OOM in sort_array");
741 /* this code is no doubt evil and ignores EXPR_INDEX possibly
742 * to its detriment and other nasty things. improvements
743 * welcome.
745 i = 0;
746 sorted = 0;
747 FOR_EACH_PTR(expr->expr_list, entry) {
748 if ((entry->type == EXPR_POS) || (entry->type == EXPR_VALUE)) {
749 /* add entry to list[], in sorted order */
750 if (sorted == 0) {
751 list[0] = entry;
752 sorted = 1;
753 } else {
754 unsigned int i;
756 for (i = 0; i < sorted; i++)
757 if (sort_array_cmp(entry, list[i]) <= 0)
758 break;
760 /* If inserting into the middle of list[]
761 * instead of appending, we memmove.
762 * This is ugly, but thankfully
763 * uncommon. Input data with tons of
764 * entries very rarely have explicit
765 * offsets. convert to qsort eventually...
767 if (i != sorted)
768 memmove(&list[i + 1], &list[i],
769 (sorted - i) * sizeof(entry));
770 list[i] = entry;
771 sorted++;
774 } END_FOR_EACH_PTR;
776 i = 0;
777 FOR_EACH_PTR(expr->expr_list, entry) {
778 if ((entry->type == EXPR_POS) || (entry->type == EXPR_VALUE))
779 __list->list[__i] = list[i++];
780 } END_FOR_EACH_PTR;
784 static void emit_array(struct symbol *sym)
786 struct symbol *base_type = sym->ctype.base_type;
787 struct expression *expr = sym->initializer;
788 struct expression *entry;
790 assert(base_type != NULL);
792 stor_sym_init(sym);
794 ea_last = -1;
796 emit_object_pre(show_ident(sym->ident), sym->ctype.modifiers,
797 sym->ctype.alignment,
798 sym->bit_size / 8);
800 sort_array(expr);
802 FOR_EACH_PTR(expr->expr_list, entry) {
803 if (entry->type == EXPR_VALUE) {
804 ea_current = 0;
805 emit_initializer(sym, entry);
806 ea_last = ea_current;
807 } else if (entry->type == EXPR_POS) {
808 ea_current =
809 entry->init_offset / (base_type->bit_size / 8);
810 emit_initializer(sym, entry->init_expr);
811 ea_last = ea_current;
813 } END_FOR_EACH_PTR;
816 static void emit_one_symbol(struct symbol *sym, void *dummy, int flags)
818 x86_symbol(sym);
821 void emit_unit(const char *basename, struct symbol_list *list)
823 emit_unit_pre(basename);
824 symbol_iterate(list, emit_one_symbol, NULL);
825 emit_unit_post();
828 static void emit_copy(struct storage *src, struct symbol *src_ctype,
829 struct storage *dest, struct symbol *dest_ctype)
831 /* FIXME: Bitfield move! */
833 emit_move(src, REG_EAX, src_ctype, "begin copy ..", 0);
834 emit_move(REG_EAX, dest, dest_ctype, ".... end copy", 0);
837 static void emit_store(struct expression *dest_expr, struct storage *dest,
838 struct storage *src, int bits)
840 /* FIXME: Bitfield store! */
841 printf("\tst.%d\t\tv%d,[v%d]\n", bits, src->pseudo, dest->pseudo);
844 static void emit_scalar_noinit(struct symbol *sym)
846 emit_global_noinit(show_ident(sym->ident),
847 sym->ctype.modifiers, sym->ctype.alignment,
848 sym->bit_size / 8);
849 stor_sym_init(sym);
852 static void emit_array_noinit(struct symbol *sym)
854 emit_global_noinit(show_ident(sym->ident),
855 sym->ctype.modifiers, sym->ctype.alignment,
856 sym->array_size * (sym->bit_size / 8));
857 stor_sym_init(sym);
860 static const char *opbits(const char *insn, unsigned int bits)
862 static char opbits_str[32];
863 char c;
865 switch (bits) {
866 case 8: c = 'b'; break;
867 case 16: c = 'w'; break;
868 case 32: c = 'l'; break;
869 case 64: c = 'q'; break;
870 default: assert(0); break;
873 sprintf(opbits_str, "%s%c", insn, bits);
875 return opbits_str;
878 static void emit_move(struct storage *src, struct storage *dest,
879 struct symbol *ctype, const char *comment,
880 unsigned long flags)
882 unsigned int bits;
883 unsigned int is_signed;
884 unsigned int is_dest = (src->type == STOR_REG);
885 const char *opname;
887 if (ctype) {
888 bits = ctype->bit_size;
889 is_signed = type_is_signed(ctype);
890 } else {
891 bits = 32;
892 is_signed = 0;
895 if ((dest->type == STOR_REG) && (src->type == STOR_REG)) {
896 insn("mov", src, dest, NULL, 0);
897 return;
900 switch (bits) {
901 case 8:
902 if (is_dest)
903 opname = "movb";
904 else {
905 if (is_signed) opname = "movsxb";
906 else opname = "movzxb";
908 break;
909 case 16:
910 if (is_dest)
911 opname = "movw";
912 else {
913 if (is_signed) opname = "movsxw";
914 else opname = "movzxw";
916 break;
918 case 32: opname = "movl"; break;
919 case 64: opname = "movq"; break;
921 default: assert(0); break;
924 insn(opname, src, dest, comment, flags);
927 static struct storage *emit_compare(struct expression *expr)
929 struct storage *left = x86_expression(expr->left);
930 struct storage *right = x86_expression(expr->right);
931 struct storage *new;
932 const char *opname = NULL;
933 unsigned int is_signed = type_is_signed(expr->left->ctype); /* FIXME */
934 unsigned int right_bits = expr->right->ctype->bit_size;
936 switch(expr->op) {
937 case '<':
938 if (is_signed) opname = "setl";
939 else opname = "setb";
940 break;
941 case '>':
942 if (is_signed) opname = "setg";
943 else opname = "seta";
944 break;
945 case SPECIAL_LTE:
946 if (is_signed) opname = "setle";
947 else opname = "setbe";
948 break;
949 case SPECIAL_GTE:
950 if (is_signed) opname = "setge";
951 else opname = "setae";
952 break;
954 case SPECIAL_EQUAL: opname = "sete"; break;
955 case SPECIAL_NOTEQUAL: opname = "setne"; break;
957 default:
958 assert(0);
959 break;
962 /* init EDX to 0 */
963 insn("xor", REG_EDX, REG_EDX, "begin EXPR_COMPARE", 0);
965 /* move op1 into EAX */
966 emit_move(left, REG_EAX, expr->left->ctype, NULL, 0);
968 /* perform comparison, RHS (op1, right) and LHS (op2, EAX) */
969 insn(opbits("cmp", right_bits), right, REG_EAX, NULL, 0);
971 /* store result of operation, 0 or 1, in DL using SETcc */
972 insn(opname, REG_DL, NULL, NULL, 0);
974 /* finally, store the result (DL) in a new pseudo / stack slot */
975 new = new_pseudo();
976 emit_move(REG_EDX, new, NULL, "end EXPR_COMPARE", 0);
978 return new;
981 static struct storage *emit_value(struct expression *expr)
983 #if 0 /* old and slow way */
984 struct storage *new = new_pseudo();
985 struct storage *val;
987 val = new_storage(STOR_VALUE);
988 val->value = (long long) expr->value;
989 insn("movl", val, new, NULL, ATOM_FREE_OP1);
991 return new;
992 #else
993 struct storage *val;
995 val = new_storage(STOR_VALUE);
996 val->value = (long long) expr->value;
998 return val; /* FIXME: memory leak */
999 #endif
1002 static struct storage *emit_binop(struct expression *expr)
1004 struct storage *left = x86_expression(expr->left);
1005 struct storage *right = x86_expression(expr->right);
1006 struct storage *new;
1007 const char *opname;
1008 static const char *name[] = {
1009 ['+'] = "addl", ['-'] = "subl",
1010 ['*'] = "mull", ['/'] = "divl",
1011 ['%'] = "modl", ['&'] = "andl",
1012 ['|'] = "orl", ['^'] = "xorl"
1014 unsigned int op = expr->op;
1017 * FIXME FIXME this routine is so wrong it's not even funny.
1018 * On x86 both mod/div are handled with the same instruction.
1019 * We don't pay attention to signed/unsigned issues,
1020 * and like elsewhere we hardcode the operand size at 32 bits.
1023 opname = show_special(op);
1024 if (op < sizeof(name)/sizeof(*name)) {
1025 opname = name[op];
1026 assert(opname != NULL);
1027 } else
1028 assert(0); /* FIXME: no operations other than name[], ATM */
1030 /* load op2 into EAX */
1031 insn("movl", right, REG_EAX, "EXPR_BINOP/COMMA/LOGICAL", 0);
1033 /* perform binop */
1034 insn(opname, left, REG_EAX, NULL, 0);
1036 /* store result (EAX) in new pseudo / stack slot */
1037 new = new_pseudo();
1038 insn("movl", REG_EAX, new, "end EXPR_BINOP", 0);
1040 return new;
1043 static void emit_if_conditional(struct statement *stmt)
1045 struct function *f = current_func;
1046 struct storage *val, *target_val;
1047 int target;
1048 struct expression *cond = stmt->if_conditional;
1049 char s[16];
1051 /* This is only valid if nobody can jump into the "dead" statement */
1052 #if 0
1053 if (cond->type == EXPR_VALUE) {
1054 struct statement *s = stmt->if_true;
1055 if (!cond->value)
1056 s = stmt->if_false;
1057 x86_statement(s);
1058 break;
1060 #endif
1061 val = x86_expression(cond);
1063 /* load 'if' test result into EAX */
1064 insn("movl", val, REG_EAX, "begin if conditional", 0);
1066 /* compare 'if' test result */
1067 insn("test", REG_EAX, REG_EAX, NULL, 0);
1069 /* create end-of-if label / if-failed labelto jump to,
1070 * and jump to it if the expression returned zero.
1072 target = new_label();
1073 target_val = new_storage(STOR_LABEL);
1074 target_val->label = target;
1075 insn("jz", target_val, NULL, NULL, ATOM_FREE_OP1);
1077 x86_statement(stmt->if_true);
1078 if (stmt->if_false) {
1079 struct storage *last_val;
1080 int last;
1082 /* finished generating code for if-true statement.
1083 * add a jump-to-end jump to avoid falling through
1084 * to the if-false statement code.
1086 last = new_label();
1087 last_val = new_storage(STOR_LABEL);
1088 last_val->label = last;
1089 insn("jmp", last_val, NULL, NULL, ATOM_FREE_OP1);
1091 /* if we have both if-true and if-false statements,
1092 * the failed-conditional case will fall through to here
1094 sprintf(s, ".L%d:\n", target);
1095 push_text_atom(f, s);
1097 target = last;
1098 x86_statement(stmt->if_false);
1101 sprintf(s, ".L%d:\t\t\t\t\t# end if\n", target);
1102 push_text_atom(f, s);
1105 static struct storage *emit_inc_dec(struct expression *expr, int postop)
1107 struct storage *addr = x86_address_gen(expr->unop);
1108 struct storage *retval;
1109 char opname[16];
1111 strcpy(opname, opbits(expr->op == SPECIAL_INCREMENT ? "inc" : "dec",
1112 expr->ctype->bit_size));
1114 if (postop) {
1115 struct storage *new = new_pseudo();
1117 emit_copy(addr, expr->unop->ctype, new, NULL);
1119 retval = new;
1120 } else
1121 retval = addr;
1123 insn(opname, addr, NULL, NULL, 0);
1125 return retval;
1128 static struct storage *emit_postop(struct expression *expr)
1130 return emit_inc_dec(expr, 1);
1133 static struct storage *emit_return_stmt(struct statement *stmt)
1135 struct function *f = current_func;
1136 struct expression *expr = stmt->ret_value;
1137 struct storage *val = NULL;
1138 char s[32];
1140 if (expr && expr->ctype) {
1141 val = x86_expression(expr);
1142 assert(val != NULL);
1143 emit_move(val, REG_EAX, expr->ctype, "return", 0);
1146 sprintf(s, "\tjmp\t.L%d\n", f->ret_target);
1147 push_text_atom(f, s);
1149 return val;
1152 static struct storage *emit_conditional_expr(struct expression *expr)
1154 struct storage *cond = x86_expression(expr->conditional);
1155 struct storage *true = x86_expression(expr->cond_true);
1156 struct storage *false = x86_expression(expr->cond_false);
1157 struct storage *new = new_pseudo();
1159 if (!true)
1160 true = cond;
1162 emit_move(cond, REG_EAX, expr->conditional->ctype,
1163 "begin EXPR_CONDITIONAL", 0);
1164 emit_move(true, REG_ECX, expr->cond_true->ctype, NULL, 0);
1165 emit_move(false, REG_EDX, expr->cond_false->ctype, NULL, 0);
1167 /* test EAX (for zero/non-zero) */
1168 insn("test", REG_EAX, REG_EAX, NULL, 0);
1170 /* if false, move EDX to ECX */
1171 insn("cmovz", REG_EDX, REG_ECX, NULL, 0);
1173 /* finally, store the result (ECX) in a new pseudo / stack slot */
1174 new = new_pseudo();
1175 emit_move(REG_ECX, new, expr->ctype, "end EXPR_CONDITIONAL", 0);
1176 /* FIXME: we lose type knowledge of expression result at this point */
1178 return new;
1181 static struct storage *emit_symbol_expr_init(struct symbol *sym)
1183 struct expression *expr = sym->initializer;
1184 struct symbol_private *priv = sym->aux;
1186 if (priv == NULL) {
1187 priv = calloc(1, sizeof(*priv));
1188 sym->aux = priv;
1190 if (expr == NULL) {
1191 struct storage *new = new_pseudo();
1192 fprintf(stderr, "FIXME! no value for symbol. creating pseudo %d (stack offset %d)\n",
1193 new->pseudo, new->pseudo * 4);
1194 priv->addr = new;
1195 } else {
1196 priv->addr = x86_expression(expr);
1200 return priv->addr;
1203 static struct storage *emit_string_expr(struct expression *expr)
1205 struct function *f = current_func;
1206 int label = new_label();
1207 struct storage *new = new_pseudo();
1209 push_cstring(f, expr->string, label);
1211 new = new_storage(STOR_LABEL);
1212 new->label = label;
1213 new->flags = STOR_LABEL_VAL;
1214 return new;
1217 static struct storage *emit_cast_expr(struct expression *expr)
1219 struct symbol *old_type, *new_type;
1220 struct storage *op = x86_expression(expr->cast_expression);
1221 int oldbits, newbits;
1222 struct storage *new;
1224 old_type = expr->cast_expression->ctype;
1225 new_type = expr->cast_type;
1227 oldbits = old_type->bit_size;
1228 newbits = new_type->bit_size;
1229 if (oldbits >= newbits)
1230 return op;
1232 emit_move(op, REG_EAX, old_type, "begin cast ..", 0);
1234 new = new_pseudo();
1235 emit_move(REG_EAX, new, new_type, ".... end cast", 0);
1237 return new;
1240 static struct storage *emit_regular_preop(struct expression *expr)
1242 struct storage *target = x86_expression(expr->unop);
1243 struct storage *new = new_pseudo();
1244 const char *opname = NULL;
1246 switch (expr->op) {
1247 case '!':
1248 insn("xor", REG_EDX, REG_EDX, NULL, 0);
1249 emit_move(target, REG_EAX, expr->unop->ctype, NULL, 0);
1250 insn("test", REG_EAX, REG_EAX, NULL, 0);
1251 insn("setz", REG_DL, NULL, NULL, 0);
1252 emit_move(REG_EDX, new, expr->unop->ctype, NULL, 0);
1254 break;
1255 case '~':
1256 opname = "not";
1257 case '-':
1258 if (!opname)
1259 opname = "neg";
1260 emit_move(target, REG_EAX, expr->unop->ctype, NULL, 0);
1261 insn(opname, REG_EAX, NULL, NULL, 0);
1262 emit_move(REG_EAX, new, expr->unop->ctype, NULL, 0);
1263 break;
1264 default:
1265 assert(0);
1266 break;
1269 return new;
1272 static void x86_struct_member(struct symbol *sym, void *data, int flags)
1274 if (flags & ITERATE_FIRST)
1275 printf(" {\n\t");
1276 printf("%s:%d:%ld at offset %ld", show_ident(sym->ident), sym->bit_size, sym->ctype.alignment, sym->offset);
1277 if (sym->fieldwidth)
1278 printf("[%d..%d]", sym->bit_offset, sym->bit_offset+sym->fieldwidth-1);
1279 if (flags & ITERATE_LAST)
1280 printf("\n} ");
1281 else
1282 printf(", ");
1285 static void x86_symbol(struct symbol *sym)
1287 struct symbol *type;
1289 if (!sym)
1290 return;
1292 type = sym->ctype.base_type;
1293 if (!type)
1294 return;
1297 * Show actual implementation information
1299 switch (type->type) {
1301 case SYM_ARRAY:
1302 if (sym->initializer)
1303 emit_array(sym);
1304 else
1305 emit_array_noinit(sym);
1306 break;
1308 case SYM_BASETYPE:
1309 if (sym->initializer) {
1310 emit_object_pre(show_ident(sym->ident),
1311 sym->ctype.modifiers,
1312 sym->ctype.alignment,
1313 sym->bit_size / 8);
1314 emit_scalar(sym->initializer, sym->bit_size);
1315 stor_sym_init(sym);
1316 } else
1317 emit_scalar_noinit(sym);
1318 break;
1320 case SYM_STRUCT:
1321 symbol_iterate(type->symbol_list, x86_struct_member, NULL);
1322 break;
1324 case SYM_UNION:
1325 symbol_iterate(type->symbol_list, x86_struct_member, NULL);
1326 break;
1328 case SYM_FN: {
1329 struct statement *stmt = type->stmt;
1330 if (stmt) {
1331 emit_func_pre(sym);
1332 x86_statement(stmt);
1333 emit_func_post(sym);
1335 break;
1338 default:
1339 break;
1342 if (sym->initializer && (type->type != SYM_BASETYPE) &&
1343 (type->type != SYM_ARRAY)) {
1344 printf(" = \n");
1345 x86_expression(sym->initializer);
1349 static void x86_symbol_init(struct symbol *sym);
1351 static void x86_switch_statement(struct statement *stmt)
1353 struct storage *val = x86_expression(stmt->switch_expression);
1354 struct symbol *sym;
1355 printf("\tswitch v%d\n", val->pseudo);
1358 * Debugging only: Check that the case list is correct
1359 * by printing it out.
1361 * This is where a _real_ back-end would go through the
1362 * cases to decide whether to use a lookup table or a
1363 * series of comparisons etc
1365 printf("# case table:\n");
1366 FOR_EACH_PTR(stmt->switch_case->symbol_list, sym) {
1367 struct statement *case_stmt = sym->stmt;
1368 struct expression *expr = case_stmt->case_expression;
1369 struct expression *to = case_stmt->case_to;
1371 if (!expr) {
1372 printf(" default");
1373 } else {
1374 if (expr->type == EXPR_VALUE) {
1375 printf(" case %lld", expr->value);
1376 if (to) {
1377 if (to->type == EXPR_VALUE) {
1378 printf(" .. %lld", to->value);
1379 } else {
1380 printf(" .. what?");
1383 } else
1384 printf(" what?");
1386 printf(": .L%p\n", sym);
1387 } END_FOR_EACH_PTR;
1388 printf("# end case table\n");
1390 x86_statement(stmt->switch_statement);
1392 if (stmt->switch_break->used)
1393 printf(".L%p:\n", stmt->switch_break);
1396 static void x86_symbol_decl(struct symbol_list *syms)
1398 struct symbol *sym;
1399 FOR_EACH_PTR(syms, sym) {
1400 x86_symbol_init(sym);
1401 } END_FOR_EACH_PTR;
1404 static void x86_loop(struct statement *stmt)
1406 struct statement *pre_statement = stmt->iterator_pre_statement;
1407 struct expression *pre_condition = stmt->iterator_pre_condition;
1408 struct statement *statement = stmt->iterator_statement;
1409 struct statement *post_statement = stmt->iterator_post_statement;
1410 struct expression *post_condition = stmt->iterator_post_condition;
1411 int loop_top = 0, loop_bottom = 0;
1412 struct storage *val;
1414 x86_symbol_decl(stmt->iterator_syms);
1415 x86_statement(pre_statement);
1416 if (pre_condition) {
1417 if (pre_condition->type == EXPR_VALUE) {
1418 if (!pre_condition->value) {
1419 loop_bottom = new_label();
1420 printf("\tjmp\t\t.L%d\n", loop_bottom);
1422 } else {
1423 loop_bottom = new_label();
1424 val = x86_expression(pre_condition);
1425 printf("\tje\t\tv%d, .L%d\n", val->pseudo, loop_bottom);
1428 if (!post_condition || post_condition->type != EXPR_VALUE || post_condition->value) {
1429 loop_top = new_label();
1430 printf(".L%d:\n", loop_top);
1432 x86_statement(statement);
1433 if (stmt->iterator_continue->used)
1434 printf(".L%p:\n", stmt->iterator_continue);
1435 x86_statement(post_statement);
1436 if (!post_condition) {
1437 printf("\tjmp\t\t.L%d\n", loop_top);
1438 } else if (post_condition->type == EXPR_VALUE) {
1439 if (post_condition->value)
1440 printf("\tjmp\t\t.L%d\n", loop_top);
1441 } else {
1442 val = x86_expression(post_condition);
1443 printf("\tjne\t\tv%d, .L%d\n", val->pseudo, loop_top);
1445 if (stmt->iterator_break->used)
1446 printf(".L%p:\n", stmt->iterator_break);
1447 if (loop_bottom)
1448 printf(".L%d:\n", loop_bottom);
1452 * Print out a statement
1454 static struct storage *x86_statement(struct statement *stmt)
1456 if (!stmt)
1457 return 0;
1458 switch (stmt->type) {
1459 case STMT_RETURN:
1460 return emit_return_stmt(stmt);
1461 case STMT_COMPOUND: {
1462 struct statement *s;
1463 struct storage *last = NULL;
1465 x86_symbol_decl(stmt->syms);
1466 FOR_EACH_PTR(stmt->stmts, s) {
1467 last = x86_statement(s);
1468 } END_FOR_EACH_PTR;
1470 return last;
1473 case STMT_EXPRESSION:
1474 return x86_expression(stmt->expression);
1475 case STMT_IF:
1476 emit_if_conditional(stmt);
1477 return NULL;
1478 case STMT_SWITCH:
1479 x86_switch_statement(stmt);
1480 break;
1482 case STMT_CASE:
1483 printf(".L%p:\n", stmt->case_label);
1484 x86_statement(stmt->case_statement);
1485 break;
1487 case STMT_ITERATOR:
1488 x86_loop(stmt);
1489 break;
1491 case STMT_NONE:
1492 break;
1494 case STMT_LABEL:
1495 printf(".L%p:\n", stmt->label_identifier);
1496 x86_statement(stmt->label_statement);
1497 break;
1499 case STMT_GOTO:
1500 if (stmt->goto_expression) {
1501 struct storage *val = x86_expression(stmt->goto_expression);
1502 printf("\tgoto *v%d\n", val->pseudo);
1503 } else {
1504 printf("\tgoto .L%p\n", stmt->goto_label);
1506 break;
1507 case STMT_ASM:
1508 printf("\tasm( .... )\n");
1509 break;
1512 return NULL;
1515 static struct storage *x86_call_expression(struct expression *expr)
1517 struct function *f = current_func;
1518 struct symbol *direct;
1519 struct expression *arg, *fn;
1520 struct storage *retval, *fncall;
1521 int framesize;
1522 char s[64];
1524 if (!expr->ctype) {
1525 warn(expr->pos, "\tcall with no type!");
1526 return NULL;
1529 framesize = 0;
1530 FOR_EACH_PTR_REVERSE(expr->args, arg) {
1531 struct storage *new = x86_expression(arg);
1532 int size = arg->ctype->bit_size;
1534 /* FIXME: pay attention to 'size' */
1535 insn("pushl", new, NULL,
1536 !framesize ? "begin function call" : NULL, 0);
1538 framesize += size >> 3;
1539 } END_FOR_EACH_PTR_REVERSE;
1541 fn = expr->fn;
1543 /* Remove dereference, if any */
1544 direct = NULL;
1545 if (fn->type == EXPR_PREOP) {
1546 if (fn->unop->type == EXPR_SYMBOL) {
1547 struct symbol *sym = fn->unop->symbol;
1548 if (sym->ctype.base_type->type == SYM_FN)
1549 direct = sym;
1552 if (direct) {
1553 sprintf(s, "\tcall\t%s\n", show_ident(direct->ident));
1554 push_text_atom(f, s);
1555 } else {
1556 fncall = x86_expression(fn);
1557 emit_move(fncall, REG_EAX, fn->ctype, NULL, 0);
1559 strcpy(s, "\tcall\t*%eax\n");
1560 push_text_atom(f, s);
1563 /* FIXME: pay attention to BITS_IN_POINTER */
1564 if (framesize) {
1565 struct storage *val = new_storage(STOR_VALUE);
1566 val->value = (long long) framesize;
1567 insn("addl", val, REG_ESP, NULL, ATOM_FREE_OP1);
1570 retval = new_pseudo();
1571 emit_move(REG_EAX, retval, expr->ctype, "end function call", 0);
1573 return retval;
1576 static struct storage *x86_address_gen(struct expression *expr)
1578 struct function *f = current_func;
1579 struct storage *addr;
1580 struct storage *new;
1581 char s[32];
1583 if ((expr->type != EXPR_PREOP) || (expr->op != '*'))
1584 return x86_expression(expr->address);
1586 addr = x86_expression(expr->unop);
1587 if (expr->unop->type == EXPR_SYMBOL)
1588 return addr;
1590 emit_move(addr, REG_EAX, NULL, "begin deref ..", 0);
1592 /* FIXME: operand size */
1593 strcpy(s, "\tmovl\t(%eax), %ecx\n");
1594 push_text_atom(f, s);
1596 new = new_pseudo();
1597 emit_move(REG_ECX, new, NULL, ".... end deref", 0);
1599 return new;
1602 static struct storage *x86_assignment(struct expression *expr)
1604 struct expression *target = expr->left;
1605 struct storage *val, *addr;
1606 int bits;
1608 if (!expr->ctype)
1609 return NULL;
1611 bits = expr->ctype->bit_size;
1612 val = x86_expression(expr->right);
1613 addr = x86_address_gen(target);
1615 switch (val->type) {
1616 /* copy, where both operands are memory */
1617 case STOR_PSEUDO:
1618 case STOR_ARG:
1619 emit_copy(val, expr->right->ctype, addr, expr->left->ctype);
1620 break;
1622 /* copy, one or zero operands are memory */
1623 case STOR_REG:
1624 case STOR_SYM:
1625 case STOR_VALUE:
1626 case STOR_LABEL:
1627 emit_move(val, addr, expr->left->ctype, NULL, 0);
1628 break;
1630 return val;
1633 static int x86_initialization(struct symbol *sym, struct expression *expr)
1635 struct storage *val, *addr;
1636 int bits;
1638 if (!expr->ctype)
1639 return 0;
1641 bits = expr->ctype->bit_size;
1642 val = x86_expression(expr);
1643 addr = x86_symbol_expr(sym);
1644 // FIXME! The "target" expression is for bitfield store information.
1645 // Leave it NULL, which works fine.
1646 emit_store(NULL, addr, val, bits);
1647 return 0;
1650 static struct storage *x86_access(struct expression *expr)
1652 return x86_address_gen(expr);
1655 static struct storage *x86_preop(struct expression *expr)
1658 * '*' is an lvalue access, and is fundamentally different
1659 * from an arithmetic operation. Maybe it should have an
1660 * expression type of its own..
1662 if (expr->op == '*')
1663 return x86_access(expr);
1664 if (expr->op == SPECIAL_INCREMENT || expr->op == SPECIAL_DECREMENT)
1665 return emit_inc_dec(expr, 0);
1666 return emit_regular_preop(expr);
1669 static struct storage *x86_symbol_expr(struct symbol *sym)
1671 struct storage *new = new_pseudo();
1673 if (sym->ctype.modifiers & (MOD_TOPLEVEL | MOD_EXTERN | MOD_STATIC)) {
1674 printf("\tmovi.%d\t\tv%d,$%s\n", BITS_IN_POINTER, new->pseudo, show_ident(sym->ident));
1675 return new;
1677 if (sym->ctype.modifiers & MOD_ADDRESSABLE) {
1678 printf("\taddi.%d\t\tv%d,vFP,$%lld\n", BITS_IN_POINTER, new->pseudo, sym->value);
1679 return new;
1681 printf("\taddi.%d\t\tv%d,vFP,$offsetof(%s:%p)\n", BITS_IN_POINTER, new->pseudo, show_ident(sym->ident), sym);
1682 return new;
1685 static void x86_symbol_init(struct symbol *sym)
1687 struct symbol_private *priv = sym->aux;
1688 struct expression *expr = sym->initializer;
1689 struct storage *new;
1691 if (expr)
1692 new = x86_expression(expr);
1693 else
1694 new = new_pseudo();
1696 if (!priv) {
1697 priv = calloc(1, sizeof(*priv));
1698 sym->aux = priv;
1699 /* FIXME: leak! we don't free... */
1700 /* (well, we don't free symbols either) */
1703 priv->addr = new;
1706 static int type_is_signed(struct symbol *sym)
1708 if (sym->type == SYM_NODE)
1709 sym = sym->ctype.base_type;
1710 if (sym->type == SYM_PTR)
1711 return 0;
1712 return !(sym->ctype.modifiers & MOD_UNSIGNED);
1715 static struct storage *x86_bitfield_expr(struct expression *expr)
1717 return x86_access(expr);
1720 static struct storage *x86_label_expr(struct expression *expr)
1722 struct storage *new = new_pseudo();
1723 printf("\tmovi.%d\t\tv%d,.L%p\n",BITS_IN_POINTER, new->pseudo, expr->label_symbol);
1724 return new;
1727 static struct storage *x86_statement_expr(struct expression *expr)
1729 return x86_statement(expr->statement);
1732 static int x86_position_expr(struct expression *expr, struct symbol *base)
1734 struct storage *new = x86_expression(expr->init_expr);
1735 struct symbol *ctype = expr->init_sym;
1737 printf("\tinsert v%d at [%d:%d] of %s\n", new->pseudo,
1738 expr->init_offset, ctype->bit_offset,
1739 show_ident(base->ident));
1740 return 0;
1743 static void x86_initializer_expr(struct expression *expr, struct symbol *ctype)
1745 struct expression *entry;
1747 FOR_EACH_PTR(expr->expr_list, entry) {
1748 // Nested initializers have their positions already
1749 // recursively calculated - just output them too
1750 if (entry->type == EXPR_INITIALIZER) {
1751 x86_initializer_expr(entry, ctype);
1752 continue;
1755 // Ignore initializer indexes and identifiers - the
1756 // evaluator has taken them into account
1757 if (entry->type == EXPR_IDENTIFIER || entry->type == EXPR_INDEX)
1758 continue;
1759 if (entry->type == EXPR_POS) {
1760 x86_position_expr(entry, ctype);
1761 continue;
1763 x86_initialization(ctype, entry);
1764 } END_FOR_EACH_PTR;
1768 * Print out an expression. Return the pseudo that contains the
1769 * variable.
1771 static struct storage *x86_expression(struct expression *expr)
1773 if (!expr)
1774 return 0;
1776 if (!expr->ctype) {
1777 struct position *pos = &expr->pos;
1778 printf("\tno type at %s:%d:%d\n",
1779 input_streams[pos->stream].name,
1780 pos->line, pos->pos);
1781 return 0;
1784 switch (expr->type) {
1785 case EXPR_CALL:
1786 return x86_call_expression(expr);
1788 case EXPR_ASSIGNMENT:
1789 return x86_assignment(expr);
1791 case EXPR_COMPARE:
1792 return emit_compare(expr);
1793 case EXPR_BINOP:
1794 case EXPR_COMMA:
1795 case EXPR_LOGICAL:
1796 return emit_binop(expr);
1797 case EXPR_PREOP:
1798 return x86_preop(expr);
1799 case EXPR_POSTOP:
1800 return emit_postop(expr);
1801 case EXPR_SYMBOL:
1802 return emit_symbol_expr_init(expr->symbol);
1803 case EXPR_DEREF:
1804 case EXPR_SIZEOF:
1805 warn(expr->pos, "invalid expression after evaluation");
1806 return 0;
1807 case EXPR_CAST:
1808 return emit_cast_expr(expr);
1809 case EXPR_VALUE:
1810 return emit_value(expr);
1811 case EXPR_STRING:
1812 return emit_string_expr(expr);
1813 case EXPR_BITFIELD:
1814 return x86_bitfield_expr(expr);
1815 case EXPR_INITIALIZER:
1816 x86_initializer_expr(expr, expr->ctype);
1817 return NULL;
1818 case EXPR_CONDITIONAL:
1819 return emit_conditional_expr(expr);
1820 case EXPR_STATEMENT:
1821 return x86_statement_expr(expr);
1822 case EXPR_LABEL:
1823 return x86_label_expr(expr);
1825 // None of these should exist as direct expressions: they are only
1826 // valid as sub-expressions of initializers.
1827 case EXPR_POS:
1828 warn(expr->pos, "unable to show plain initializer position expression");
1829 return 0;
1830 case EXPR_IDENTIFIER:
1831 warn(expr->pos, "unable to show identifier expression");
1832 return 0;
1833 case EXPR_INDEX:
1834 warn(expr->pos, "unable to show index expression");
1835 return 0;
1837 return 0;