Make binops use the new register tracking in compile-i386.c
[smatch.git] / compile-i386.c
blobab7a229deb7dbed7b2e878b4f8a645003916fdd7
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 * complex initializers
15 * bitfields
16 * global struct/union variables
17 * addressing structures, and members of structures (as opposed to
18 * scalars) on the stack. Requires smarter stack frame allocation.
19 * labels / goto
20 * any function argument that isn't 32 bits (or promoted to such)
21 * inline asm
22 * floating point
25 #include <stdarg.h>
26 #include <stdlib.h>
27 #include <stdio.h>
28 #include <string.h>
29 #include <ctype.h>
30 #include <unistd.h>
31 #include <fcntl.h>
32 #include <assert.h>
34 #include "lib.h"
35 #include "token.h"
36 #include "parse.h"
37 #include "symbol.h"
38 #include "scope.h"
39 #include "expression.h"
40 #include "target.h"
41 #include "compile.h"
42 #include "bitmap.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;
81 struct storage *contains;
82 const unsigned char aliases[12];
83 #define own_regno aliases[0]
86 struct storage {
87 enum storage_type type;
88 unsigned long flags;
90 /* STOR_REG */
91 struct reg_info *reg;
92 struct symbol *ctype;
94 union {
95 /* STOR_PSEUDO */
96 struct {
97 int pseudo;
98 int offset;
99 int size;
101 /* STOR_ARG */
102 struct {
103 int idx;
105 /* STOR_SYM */
106 struct {
107 struct symbol *sym;
109 /* STOR_VALUE */
110 struct {
111 long long value;
113 /* STOR_LABEL */
114 struct {
115 int label;
117 /* STOR_LABELSYM */
118 struct {
119 struct symbol *labelsym;
124 enum {
125 STOR_LABEL_VAL = (1 << 0),
126 STOR_WANTS_FREE = (1 << 1),
129 struct symbol_private {
130 struct storage *addr;
133 enum atom_type {
134 ATOM_TEXT,
135 ATOM_INSN,
136 ATOM_CSTR,
139 struct atom {
140 enum atom_type type;
141 union {
142 /* stuff for text */
143 struct {
144 char *text;
145 unsigned int text_len; /* w/o terminating null */
148 /* stuff for insns */
149 struct {
150 char insn[32];
151 char comment[40];
152 struct storage *op1;
153 struct storage *op2;
156 /* stuff for C strings */
157 struct {
158 struct string *string;
159 int label;
165 struct function *current_func = NULL;
166 struct textbuf *unit_post_text = NULL;
167 static const char *current_section;
169 static void emit_comment(const char * fmt, ...);
170 static void emit_move(struct storage *src, struct storage *dest,
171 struct symbol *ctype, const char *comment);
172 static int type_is_signed(struct symbol *sym);
173 static struct storage *x86_address_gen(struct expression *expr);
174 static struct storage *x86_symbol_expr(struct symbol *sym);
175 static void x86_symbol(struct symbol *sym);
176 static struct storage *x86_statement(struct statement *stmt);
177 static struct storage *x86_expression(struct expression *expr);
179 enum registers {
180 NOREG,
181 AL, DL, CL, BL, AH, DH, CH, BH, // 8-bit
182 AX, DX, CX, BX, SI, DI, BP, SP, // 16-bit
183 EAX, EDX, ECX, EBX, ESI, EDI, EBP, ESP, // 32-bit
184 EAX_EDX, ECX_EBX, ESI_EDI, // 64-bit
187 /* This works on regno's, reg_info's and hardreg_storage's */
188 #define byte_reg(reg) ((reg) - 16)
190 #define REGINFO(nr, str, conflicts...) [nr] = { .name = str, .aliases = { nr , conflicts } }
192 static struct reg_info reg_info_table[] = {
193 REGINFO( AL, "%al", AX, EAX, EAX_EDX),
194 REGINFO( DL, "%dl", DX, EDX, EAX_EDX),
195 REGINFO( CL, "%cl", CX, ECX, ECX_EBX),
196 REGINFO( BL, "%bl", BX, EBX, ECX_EBX),
197 REGINFO( AH, "%ah", AX, EAX, EAX_EDX),
198 REGINFO( DH, "%dh", DX, EDX, EAX_EDX),
199 REGINFO( CH, "%ch", CX, ECX, ECX_EBX),
200 REGINFO( BH, "%bh", BX, EBX, ECX_EBX),
201 REGINFO( AX, "%ax", AL, AH, EAX, EAX_EDX),
202 REGINFO( DX, "%dx", DL, DH, EDX, EAX_EDX),
203 REGINFO( CX, "%cx", CL, CH, ECX, ECX_EBX),
204 REGINFO( BX, "%bx", BL, BH, EBX, ECX_EBX),
205 REGINFO( SI, "%si", ESI, ESI_EDI),
206 REGINFO( DI, "%di", EDI, ESI_EDI),
207 REGINFO( BP, "%bp", EBP),
208 REGINFO( SP, "%sp", ESP),
209 REGINFO(EAX, "%eax", AL, AH, AX, EAX_EDX),
210 REGINFO(EDX, "%edx", DL, DH, DX, EAX_EDX),
211 REGINFO(ECX, "%ecx", CL, CH, CX, ECX_EBX),
212 REGINFO(EBX, "%ebx", BL, BH, BX, ECX_EBX),
213 REGINFO(ESI, "%esi", SI, ESI_EDI),
214 REGINFO(EDI, "%edi", DI, ESI_EDI),
215 REGINFO(EBP, "%ebp", BP),
216 REGINFO(ESP, "%esp", SP),
217 REGINFO(EAX_EDX, "%eax:%edx", AL, AH, AX, EAX, DL, DH, DX, EDX),
218 REGINFO(ECX_EBX, "%ecx:%ebx", CL, CH, CX, ECX, BL, BH, BX, EBX),
219 REGINFO(ESI_EDI, "%esi:%edi", SI, ESI, DI, EDI),
222 #define REGSTORAGE(nr) [nr] = { .type = STOR_REG, .reg = reg_info_table + (nr) }
224 static struct storage hardreg_storage_table[] = {
225 REGSTORAGE(AL), REGSTORAGE(DL), REGSTORAGE(CL), REGSTORAGE(BL),
226 REGSTORAGE(AH), REGSTORAGE(DH), REGSTORAGE(CH), REGSTORAGE(BH),
227 REGSTORAGE(AX), REGSTORAGE(DX), REGSTORAGE(CX), REGSTORAGE(BX),
228 REGSTORAGE(SI), REGSTORAGE(DI), REGSTORAGE(BP), REGSTORAGE(SP),
229 REGSTORAGE(EAX), REGSTORAGE(EDX), REGSTORAGE(ECX), REGSTORAGE(EBX),
230 REGSTORAGE(ESI), REGSTORAGE(EDI), REGSTORAGE(EBP), REGSTORAGE(ESP),
231 REGSTORAGE(EAX_EDX), REGSTORAGE(ECX_EBX), REGSTORAGE(ESI_EDI),
234 #define REG_EAX (&hardreg_storage_table[EAX])
235 #define REG_ECX (&hardreg_storage_table[ECX])
236 #define REG_EDX (&hardreg_storage_table[EDX])
237 #define REG_ESP (&hardreg_storage_table[ESP])
238 #define REG_DL (&hardreg_storage_table[DL])
239 #define REG_DX (&hardreg_storage_table[DX])
240 #define REG_AL (&hardreg_storage_table[AL])
241 #define REG_AX (&hardreg_storage_table[AX])
243 DECLARE_BITMAP(regs_in_use, 256);
245 struct storage * get_hardreg(struct storage *reg, int clear)
247 struct reg_info *info = reg->reg;
248 const unsigned char *aliases;
249 int regno;
251 aliases = info->aliases;
252 while ((regno = *aliases++) != NOREG) {
253 if (test_and_set_bit(regno, regs_in_use))
254 goto busy;
255 if (clear)
256 reg_info_table[regno].contains = NULL;
258 return reg;
259 busy:
260 fprintf(stderr, "register %s is busy\n", info->name);
261 if (regno + reg_info_table != info)
262 fprintf(stderr, " conflicts with %s\n", reg_info_table[regno].name);
263 exit(1);
266 void put_reg(struct storage *reg)
268 struct reg_info *info = reg->reg;
269 const unsigned char *aliases;
270 int regno;
272 aliases = info->aliases;
273 while ((regno = *aliases++) != NOREG) {
274 if (!test_and_clear_bit(regno, regs_in_use))
275 goto free;
277 return;
278 free:
279 fprintf(stderr, "freeing already free'd register %s\n", reg_info_table[regno].name);
282 struct regclass {
283 const char *name;
284 const unsigned char regs[30];
287 struct regclass regclass_8 = { "8-bit", { AL, DL, CL, BL, AH, DH, CH, BH }};
288 struct regclass regclass_16 = { "16-bit", { AX, DX, CX, BX, SI, DI, BP }};
289 struct regclass regclass_32 = { "32-bit", { EAX, EDX, ECX, EBX, ESI, EDI, EBP }};
290 struct regclass regclass_64 = { "64-bit", { EAX_EDX, ECX_EBX, ESI_EDI }};
292 struct regclass regclass_32_8 = { "32-bit bytes", { EAX, EDX, ECX, EBX }};
294 static int register_busy(int regno)
296 if (!test_bit(regno, regs_in_use)) {
297 struct reg_info *info = reg_info_table + regno;
298 const unsigned char *regs = info->aliases+1;
300 while ((regno = *regs) != NOREG) {
301 regs++;
302 if (test_bit(regno, regs_in_use))
303 goto busy;
305 return 0;
307 busy:
308 return 1;
311 struct storage *get_reg(struct regclass *class)
313 const unsigned char *regs = class->regs;
314 int regno;
316 while ((regno = *regs) != NOREG) {
317 regs++;
318 if (register_busy(regno))
319 continue;
320 return get_hardreg(hardreg_storage_table + regno, 1);
322 fprintf(stderr, "Ran out of %s registers\n", class->name);
323 exit(1);
326 struct storage *get_reg_value(struct storage *value)
328 struct reg_info *info;
329 struct storage *reg;
331 /* Do we already have it somewhere */
332 info = value->reg;
333 if (info && info->contains == value) {
334 emit_comment("already have register %s", info->name);
335 return get_hardreg(hardreg_storage_table + info->own_regno, 0);
338 reg = get_reg(&regclass_32);
339 emit_move(value, reg, value->ctype, "reload register");
340 info = reg->reg;
341 info->contains = value;
342 value->reg = info;
343 return reg;
346 static struct storage *temp_from_bits(unsigned int bit_size)
348 switch(bit_size) {
349 case 8: return get_reg(&regclass_8);
350 case 16: return get_reg(&regclass_16);
351 case 32: return get_reg(&regclass_32);
352 case 64: return get_reg(&regclass_64);
355 return NULL;
358 static inline unsigned int pseudo_offset(struct storage *s)
360 if (s->type != STOR_PSEUDO)
361 return 123456; /* intentionally bogus value */
363 return s->offset;
366 static inline unsigned int arg_offset(struct storage *s)
368 if (s->type != STOR_ARG)
369 return 123456; /* intentionally bogus value */
371 /* FIXME: this is wrong wrong wrong */
372 return current_func->stack_size + ((1 + s->idx) * 4);
375 static const char *pretty_offset(int ofs)
377 static char esp_buf[64];
379 if (ofs)
380 sprintf(esp_buf, "%d(%%esp)", ofs);
381 else
382 strcpy(esp_buf, "(%esp)");
384 return esp_buf;
387 static void stor_sym_init(struct symbol *sym)
389 struct storage *stor;
390 struct symbol_private *priv;
392 priv = calloc(1, sizeof(*priv) + sizeof(*stor));
393 if (!priv)
394 die("OOM in stor_sym_init");
396 stor = (struct storage *) (priv + 1);
398 priv->addr = stor;
399 stor->type = STOR_SYM;
400 stor->sym = sym;
403 static const char *stor_op_name(struct storage *s)
405 static char name[32];
407 switch (s->type) {
408 case STOR_PSEUDO:
409 strcpy(name, pretty_offset((int) pseudo_offset(s)));
410 break;
411 case STOR_ARG:
412 strcpy(name, pretty_offset((int) arg_offset(s)));
413 break;
414 case STOR_SYM:
415 strcpy(name, show_ident(s->sym->ident));
416 break;
417 case STOR_REG:
418 strcpy(name, s->reg->name);
419 break;
420 case STOR_VALUE:
421 sprintf(name, "$%Ld", s->value);
422 break;
423 case STOR_LABEL:
424 sprintf(name, "%s.L%d", s->flags & STOR_LABEL_VAL ? "$" : "",
425 s->label);
426 break;
427 case STOR_LABELSYM:
428 sprintf(name, "%s.LS%p", s->flags & STOR_LABEL_VAL ? "$" : "",
429 s->labelsym);
430 break;
433 return name;
436 static struct atom *new_atom(enum atom_type type)
438 struct atom *atom;
440 atom = calloc(1, sizeof(*atom)); /* TODO: chunked alloc */
441 if (!atom)
442 die("nuclear OOM");
444 atom->type = type;
446 return atom;
449 static inline void push_cstring(struct function *f, struct string *str,
450 int label)
452 struct atom *atom;
454 atom = new_atom(ATOM_CSTR);
455 atom->string = str;
456 atom->label = label;
458 add_ptr_list(&f->str_list, atom); /* note: _not_ atom_list */
461 static inline void push_atom(struct function *f, struct atom *atom)
463 add_ptr_list(&f->atom_list, atom);
466 static void push_text_atom(struct function *f, const char *text)
468 struct atom *atom = new_atom(ATOM_TEXT);
470 atom->text = strdup(text);
471 atom->text_len = strlen(text);
473 push_atom(f, atom);
476 static struct storage *new_storage(enum storage_type type)
478 struct storage *stor;
480 stor = calloc(1, sizeof(*stor));
481 if (!stor)
482 die("OOM in new_storage");
484 stor->type = type;
486 return stor;
489 static struct storage *stack_alloc(int n_bytes)
491 struct function *f = current_func;
492 struct storage *stor;
494 assert(f != NULL);
496 stor = new_storage(STOR_PSEUDO);
497 stor->type = STOR_PSEUDO;
498 stor->pseudo = f->pseudo_nr;
499 stor->offset = f->stack_size; /* FIXME: stack req. natural align */
500 stor->size = n_bytes;
501 f->stack_size += n_bytes;
502 f->pseudo_nr++;
504 add_ptr_list(&f->pseudo_list, stor);
506 return stor;
509 static struct storage *new_labelsym(struct symbol *sym)
511 struct storage *stor;
513 stor = new_storage(STOR_LABELSYM);
515 if (stor) {
516 stor->flags |= STOR_WANTS_FREE;
517 stor->labelsym = sym;
520 return stor;
523 static struct storage *new_val(long long value)
525 struct storage *stor;
527 stor = new_storage(STOR_VALUE);
529 if (stor) {
530 stor->flags |= STOR_WANTS_FREE;
531 stor->value = value;
534 return stor;
537 static int new_label(void)
539 static int label = 0;
540 return ++label;
543 static void textbuf_push(struct textbuf **buf_p, const char *text)
545 struct textbuf *tmp, *list = *buf_p;
546 unsigned int text_len = strlen(text);
547 unsigned int alloc_len = text_len + 1 + sizeof(*list);
549 tmp = calloc(1, alloc_len);
550 if (!tmp)
551 die("OOM on textbuf alloc");
553 tmp->text = ((void *) tmp) + sizeof(*tmp);
554 memcpy(tmp->text, text, text_len + 1);
555 tmp->len = text_len;
557 /* add to end of list */
558 if (!list) {
559 list = tmp;
560 tmp->prev = tmp;
561 } else {
562 tmp->prev = list->prev;
563 tmp->prev->next = tmp;
564 list->prev = tmp;
566 tmp->next = list;
568 *buf_p = list;
571 static void textbuf_emit(struct textbuf **buf_p)
573 struct textbuf *tmp, *list = *buf_p;
575 while (list) {
576 tmp = list;
577 if (tmp->next == tmp)
578 list = NULL;
579 else {
580 tmp->prev->next = tmp->next;
581 tmp->next->prev = tmp->prev;
582 list = tmp->next;
585 fputs(tmp->text, stdout);
587 free(tmp);
590 *buf_p = list;
593 static void insn(const char *insn, struct storage *op1, struct storage *op2,
594 const char *comment_in)
596 struct function *f = current_func;
597 struct atom *atom = new_atom(ATOM_INSN);
599 assert(insn != NULL);
601 strcpy(atom->insn, insn);
602 if (comment_in && (*comment_in))
603 strncpy(atom->comment, comment_in,
604 sizeof(atom->comment) - 1);
606 atom->op1 = op1;
607 atom->op2 = op2;
609 push_atom(f, atom);
612 static void emit_comment(const char *fmt, ...)
614 struct function *f = current_func;
615 static char tmpbuf[100] = "\t# ";
616 va_list args;
617 int i;
619 va_start(args, fmt);
620 i = vsnprintf(tmpbuf+3, sizeof(tmpbuf)-4, fmt, args);
621 va_end(args);
622 tmpbuf[i+3] = '\n';
623 tmpbuf[i+4] = '\0';
624 push_text_atom(f, tmpbuf);
627 static void emit_label (int label, const char *comment)
629 struct function *f = current_func;
630 char s[64];
632 if (!comment)
633 sprintf(s, ".L%d:\n", label);
634 else
635 sprintf(s, ".L%d:\t\t\t\t\t# %s\n", label, comment);
637 push_text_atom(f, s);
640 static void emit_labelsym (struct symbol *sym, const char *comment)
642 struct function *f = current_func;
643 char s[64];
645 if (!comment)
646 sprintf(s, ".LS%p:\n", sym);
647 else
648 sprintf(s, ".LS%p:\t\t\t\t# %s\n", sym, comment);
650 push_text_atom(f, s);
653 void emit_unit_begin(const char *basename)
655 printf("\t.file\t\"%s\"\n", basename);
658 void emit_unit_end(void)
660 textbuf_emit(&unit_post_text);
661 printf("\t.ident\t\"sparse silly x86 backend (built %s)\"\n", __DATE__);
664 /* conditionally switch sections */
665 static void emit_section(const char *s)
667 if (s == current_section)
668 return;
669 if (current_section && (!strcmp(s, current_section)))
670 return;
672 printf("\t%s\n", s);
673 current_section = s;
676 static void emit_insn_atom(struct function *f, struct atom *atom)
678 char s[128];
679 char comment[64];
680 struct storage *op1 = atom->op1;
681 struct storage *op2 = atom->op2;
683 if (atom->comment[0])
684 sprintf(comment, "\t\t# %s", atom->comment);
685 else
686 comment[0] = 0;
688 if (atom->op2) {
689 char tmp[16];
690 strcpy(tmp, stor_op_name(op1));
691 sprintf(s, "\t%s\t%s, %s%s\n",
692 atom->insn, tmp, stor_op_name(op2), comment);
693 } else if (atom->op1)
694 sprintf(s, "\t%s\t%s%s%s\n",
695 atom->insn, stor_op_name(op1),
696 comment[0] ? "\t" : "", comment);
697 else
698 sprintf(s, "\t%s\t%s%s\n",
699 atom->insn,
700 comment[0] ? "\t\t" : "", comment);
702 write(STDOUT_FILENO, s, strlen(s));
705 static void emit_atom_list(struct function *f)
707 struct atom *atom;
709 FOR_EACH_PTR(f->atom_list, atom) {
710 switch (atom->type) {
711 case ATOM_TEXT: {
712 ssize_t rc = write(STDOUT_FILENO, atom->text,
713 atom->text_len);
714 (void) rc; /* FIXME */
715 break;
717 case ATOM_INSN:
718 emit_insn_atom(f, atom);
719 break;
720 case ATOM_CSTR:
721 assert(0);
722 break;
724 } END_FOR_EACH_PTR;
727 static void emit_string_list(struct function *f)
729 struct atom *atom;
731 emit_section(".section\t.rodata");
733 FOR_EACH_PTR(f->str_list, atom) {
734 /* FIXME: escape " in string */
735 printf(".L%d:\n", atom->label);
736 printf("\t.string\t%s\n", show_string(atom->string));
738 free(atom);
739 } END_FOR_EACH_PTR;
742 static void func_cleanup(struct function *f)
744 struct storage *stor;
745 struct atom *atom;
747 FOR_EACH_PTR(f->pseudo_list, stor) {
748 free(stor);
749 } END_FOR_EACH_PTR;
751 FOR_EACH_PTR(f->atom_list, atom) {
752 if ((atom->type == ATOM_TEXT) && (atom->text))
753 free(atom->text);
754 if (atom->op1 && (atom->op1->flags & STOR_WANTS_FREE))
755 free(atom->op1);
756 if (atom->op2 && (atom->op2->flags & STOR_WANTS_FREE))
757 free(atom->op2);
758 free(atom);
759 } END_FOR_EACH_PTR;
761 free_ptr_list(&f->pseudo_list);
762 free(f);
765 /* function prologue */
766 static void emit_func_pre(struct symbol *sym)
768 struct function *f;
769 struct symbol *arg;
770 unsigned int i, argc = 0, alloc_len;
771 unsigned char *mem;
772 struct symbol_private *privbase;
773 struct storage *storage_base;
774 struct symbol *base_type = sym->ctype.base_type;
776 FOR_EACH_PTR(base_type->arguments, arg) {
777 argc++;
778 } END_FOR_EACH_PTR;
780 alloc_len =
781 sizeof(*f) +
782 (argc * sizeof(struct symbol *)) +
783 (argc * sizeof(struct symbol_private)) +
784 (argc * sizeof(struct storage));
785 mem = calloc(1, alloc_len);
786 if (!mem)
787 die("OOM on func info");
789 f = (struct function *) mem;
790 mem += sizeof(*f);
791 f->argv = (struct symbol **) mem;
792 mem += (argc * sizeof(struct symbol *));
793 privbase = (struct symbol_private *) mem;
794 mem += (argc * sizeof(struct symbol_private));
795 storage_base = (struct storage *) mem;
797 f->argc = argc;
798 f->ret_target = new_label();
800 i = 0;
801 FOR_EACH_PTR(base_type->arguments, arg) {
802 f->argv[i] = arg;
803 arg->aux = &privbase[i];
804 storage_base[i].type = STOR_ARG;
805 storage_base[i].idx = i;
806 privbase[i].addr = &storage_base[i];
807 i++;
808 } END_FOR_EACH_PTR;
810 assert(current_func == NULL);
811 current_func = f;
814 /* function epilogue */
815 static void emit_func_post(struct symbol *sym)
817 const char *name = show_ident(sym->ident);
818 struct function *f = current_func;
819 int stack_size = f->stack_size;
821 if (f->str_list)
822 emit_string_list(f);
824 /* function prologue */
825 emit_section(".text");
826 if ((sym->ctype.modifiers & MOD_STATIC) == 0)
827 printf(".globl %s\n", name);
828 printf("\t.type\t%s, @function\n", name);
829 printf("%s:\n", name);
831 if (stack_size) {
832 char pseudo_const[16];
834 sprintf(pseudo_const, "$%d", stack_size);
835 printf("\tsubl\t%s, %%esp\n", pseudo_const);
838 /* function epilogue */
840 /* jump target for 'return' statements */
841 emit_label(f->ret_target, NULL);
843 if (stack_size) {
844 struct storage *val;
846 val = new_storage(STOR_VALUE);
847 val->value = (long long) (stack_size);
848 val->flags = STOR_WANTS_FREE;
850 insn("addl", val, REG_ESP, NULL);
853 insn("ret", NULL, NULL, NULL);
855 /* output everything to stdout */
856 fflush(stdout); /* paranoia; needed? */
857 emit_atom_list(f);
859 /* function footer */
860 name = show_ident(sym->ident);
861 printf("\t.size\t%s, .-%s\n", name, name);
863 func_cleanup(f);
864 current_func = NULL;
867 /* emit object (a.k.a. variable, a.k.a. data) prologue */
868 static void emit_object_pre(const char *name, unsigned long modifiers,
869 unsigned long alignment, unsigned int byte_size)
871 if ((modifiers & MOD_STATIC) == 0)
872 printf(".globl %s\n", name);
873 emit_section(".data");
874 if (alignment)
875 printf("\t.align %lu\n", alignment);
876 printf("\t.type\t%s, @object\n", name);
877 printf("\t.size\t%s, %d\n", name, byte_size);
878 printf("%s:\n", name);
881 /* emit value (only) for an initializer scalar */
882 static void emit_scalar(struct expression *expr, unsigned int bit_size)
884 const char *type;
885 long long ll;
887 assert(expr->type == EXPR_VALUE);
889 if (expr->value == 0ULL) {
890 printf("\t.zero\t%d\n", bit_size / 8);
891 return;
894 ll = (long long) expr->value;
896 switch (bit_size) {
897 case 8: type = "byte"; ll = (char) ll; break;
898 case 16: type = "value"; ll = (short) ll; break;
899 case 32: type = "long"; ll = (int) ll; break;
900 case 64: type = "quad"; break;
901 default: type = NULL; break;
904 assert(type != NULL);
906 printf("\t.%s\t%Ld\n", type, ll);
909 static void emit_global_noinit(const char *name, unsigned long modifiers,
910 unsigned long alignment, unsigned int byte_size)
912 char s[64];
914 if (modifiers & MOD_STATIC) {
915 sprintf(s, "\t.local\t%s\n", name);
916 textbuf_push(&unit_post_text, s);
918 if (alignment)
919 sprintf(s, "\t.comm\t%s,%d,%lu\n", name, byte_size, alignment);
920 else
921 sprintf(s, "\t.comm\t%s,%d\n", name, byte_size);
922 textbuf_push(&unit_post_text, s);
925 static int ea_current, ea_last;
927 static void emit_initializer(struct symbol *sym,
928 struct expression *expr)
930 int distance = ea_current - ea_last - 1;
932 if (distance > 0)
933 printf("\t.zero\t%d\n", (sym->bit_size / 8) * distance);
935 if (expr->type == EXPR_VALUE) {
936 struct symbol *base_type = sym->ctype.base_type;
937 assert(base_type != NULL);
939 emit_scalar(expr, sym->bit_size / get_expression_value(base_type->array_size));
940 return;
942 if (expr->type != EXPR_INITIALIZER)
943 return;
945 assert(0); /* FIXME */
948 static int sort_array_cmp(const struct expression *a,
949 const struct expression *b)
951 int a_ofs = 0, b_ofs = 0;
953 if (a->type == EXPR_POS)
954 a_ofs = (int) a->init_offset;
955 if (b->type == EXPR_POS)
956 b_ofs = (int) b->init_offset;
958 return a_ofs - b_ofs;
961 /* move to front-end? */
962 static void sort_array(struct expression *expr)
964 struct expression *entry, **list;
965 unsigned int elem, sorted, i;
967 elem = 0;
968 FOR_EACH_PTR(expr->expr_list, entry) {
969 elem++;
970 } END_FOR_EACH_PTR;
972 if (!elem)
973 return;
975 list = malloc(sizeof(entry) * elem);
976 if (!list)
977 die("OOM in sort_array");
979 /* this code is no doubt evil and ignores EXPR_INDEX possibly
980 * to its detriment and other nasty things. improvements
981 * welcome.
983 i = 0;
984 sorted = 0;
985 FOR_EACH_PTR(expr->expr_list, entry) {
986 if ((entry->type == EXPR_POS) || (entry->type == EXPR_VALUE)) {
987 /* add entry to list[], in sorted order */
988 if (sorted == 0) {
989 list[0] = entry;
990 sorted = 1;
991 } else {
992 unsigned int i;
994 for (i = 0; i < sorted; i++)
995 if (sort_array_cmp(entry, list[i]) <= 0)
996 break;
998 /* If inserting into the middle of list[]
999 * instead of appending, we memmove.
1000 * This is ugly, but thankfully
1001 * uncommon. Input data with tons of
1002 * entries very rarely have explicit
1003 * offsets. convert to qsort eventually...
1005 if (i != sorted)
1006 memmove(&list[i + 1], &list[i],
1007 (sorted - i) * sizeof(entry));
1008 list[i] = entry;
1009 sorted++;
1012 } END_FOR_EACH_PTR;
1014 i = 0;
1015 FOR_EACH_PTR(expr->expr_list, entry) {
1016 if ((entry->type == EXPR_POS) || (entry->type == EXPR_VALUE))
1017 __list->list[__i] = list[i++];
1018 } END_FOR_EACH_PTR;
1022 static void emit_array(struct symbol *sym)
1024 struct symbol *base_type = sym->ctype.base_type;
1025 struct expression *expr = sym->initializer;
1026 struct expression *entry;
1028 assert(base_type != NULL);
1030 stor_sym_init(sym);
1032 ea_last = -1;
1034 emit_object_pre(show_ident(sym->ident), sym->ctype.modifiers,
1035 sym->ctype.alignment,
1036 sym->bit_size / 8);
1038 sort_array(expr);
1040 FOR_EACH_PTR(expr->expr_list, entry) {
1041 if (entry->type == EXPR_VALUE) {
1042 ea_current = 0;
1043 emit_initializer(sym, entry);
1044 ea_last = ea_current;
1045 } else if (entry->type == EXPR_POS) {
1046 ea_current =
1047 entry->init_offset / (base_type->bit_size / 8);
1048 emit_initializer(sym, entry->init_expr);
1049 ea_last = ea_current;
1051 } END_FOR_EACH_PTR;
1054 void emit_one_symbol(struct symbol *sym)
1056 x86_symbol(sym);
1059 static void emit_copy(struct storage *dest, struct storage *src,
1060 struct symbol *ctype)
1062 struct storage *reg = NULL;
1063 unsigned int bit_size;
1065 /* FIXME: Bitfield copy! */
1067 bit_size = src->size * 8;
1068 if (!bit_size)
1069 bit_size = 32;
1070 if ((src->type == STOR_ARG) && (bit_size < 32))
1071 bit_size = 32;
1073 reg = temp_from_bits(bit_size);
1074 emit_move(src, reg, ctype, "begin copy ..");
1076 bit_size = dest->size * 8;
1077 if (!bit_size)
1078 bit_size = 32;
1079 if ((dest->type == STOR_ARG) && (bit_size < 32))
1080 bit_size = 32;
1082 emit_move(reg, dest, ctype, ".... end copy");
1083 put_reg(reg);
1086 static void emit_store(struct expression *dest_expr, struct storage *dest,
1087 struct storage *src, int bits)
1089 /* FIXME: Bitfield store! */
1090 printf("\tst.%d\t\tv%d,[v%d]\n", bits, src->pseudo, dest->pseudo);
1093 static void emit_scalar_noinit(struct symbol *sym)
1095 emit_global_noinit(show_ident(sym->ident),
1096 sym->ctype.modifiers, sym->ctype.alignment,
1097 sym->bit_size / 8);
1098 stor_sym_init(sym);
1101 static void emit_array_noinit(struct symbol *sym)
1103 emit_global_noinit(show_ident(sym->ident),
1104 sym->ctype.modifiers, sym->ctype.alignment,
1105 get_expression_value(sym->array_size) * (sym->bit_size / 8));
1106 stor_sym_init(sym);
1109 static const char *opbits(const char *insn, unsigned int bits)
1111 static char opbits_str[32];
1112 char c;
1114 switch (bits) {
1115 case 8: c = 'b'; break;
1116 case 16: c = 'w'; break;
1117 case 32: c = 'l'; break;
1118 case 64: c = 'q'; break;
1119 default: assert(0); break;
1122 sprintf(opbits_str, "%s%c", insn, c);
1124 return opbits_str;
1127 static void emit_move(struct storage *src, struct storage *dest,
1128 struct symbol *ctype, const char *comment)
1130 unsigned int bits;
1131 unsigned int is_signed;
1132 unsigned int is_dest = (src->type == STOR_REG);
1133 const char *opname;
1135 if (ctype) {
1136 bits = ctype->bit_size;
1137 is_signed = type_is_signed(ctype);
1138 } else {
1139 bits = 32;
1140 is_signed = 0;
1143 if ((dest->type == STOR_REG) && (src->type == STOR_REG)) {
1144 struct storage *backing = src->reg->contains;
1145 if (backing) {
1146 /* Is it still valid? */
1147 if (backing->reg != src->reg)
1148 backing = NULL;
1149 else
1150 backing->reg = dest->reg;
1152 dest->reg->contains = backing;
1153 insn("mov", src, dest, NULL);
1154 return;
1157 if (src->type == STOR_REG) {
1158 /* We could just mark the register dirty here and do lazy store.. */
1159 src->reg->contains = dest;
1160 dest->reg = src->reg;
1163 if (dest->type == STOR_REG) {
1164 dest->reg->contains = src;
1165 src->reg = dest->reg;
1168 if ((bits == 8) || (bits == 16)) {
1169 if (is_dest)
1170 opname = "mov";
1171 else
1172 opname = is_signed ? "movsx" : "movzx";
1173 } else
1174 opname = "mov";
1176 insn(opbits(opname, bits), src, dest, comment);
1179 static struct storage *emit_compare(struct expression *expr)
1181 struct storage *left = x86_expression(expr->left);
1182 struct storage *right = x86_expression(expr->right);
1183 struct storage *reg1, *reg2;
1184 struct storage *new, *val;
1185 const char *opname = NULL;
1186 unsigned int right_bits = expr->right->ctype->bit_size;
1188 switch(expr->op) {
1189 case '<': opname = "setl"; break;
1190 case '>': opname = "setg"; break;
1191 case SPECIAL_LTE:
1192 opname = "setle"; break;
1193 case SPECIAL_GTE:
1194 opname = "setge"; break;
1195 case SPECIAL_EQUAL: opname = "sete"; break;
1196 case SPECIAL_NOTEQUAL: opname = "setne"; break;
1197 case SPECIAL_UNSIGNED_LT:
1198 opname = "setb"; break;
1199 case SPECIAL_UNSIGNED_GT:
1200 opname = "seta"; break;
1201 case SPECIAL_UNSIGNED_LTE:
1202 opname = "setb"; break;
1203 case SPECIAL_UNSIGNED_GTE:
1204 opname = "setae"; break;
1205 default:
1206 assert(0);
1207 break;
1210 /* init EDX to 0 */
1211 val = new_storage(STOR_VALUE);
1212 val->flags = STOR_WANTS_FREE;
1214 reg1 = get_reg(&regclass_32_8);
1215 emit_move(val, reg1, NULL, NULL);
1217 /* move op1 into EAX */
1218 reg2 = get_reg_value(left);
1220 /* perform comparison, RHS (op1, right) and LHS (op2, EAX) */
1221 insn(opbits("cmp", right_bits), right, reg2, NULL);
1222 put_reg(reg2);
1224 /* store result of operation, 0 or 1, in DL using SETcc */
1225 insn(opname, byte_reg(reg1), NULL, NULL);
1227 /* finally, store the result (DL) in a new pseudo / stack slot */
1228 new = stack_alloc(4);
1229 emit_move(reg1, new, NULL, "end EXPR_COMPARE");
1230 put_reg(reg1);
1232 return new;
1235 static struct storage *emit_value(struct expression *expr)
1237 #if 0 /* old and slow way */
1238 struct storage *new = stack_alloc(4);
1239 struct storage *val;
1241 val = new_storage(STOR_VALUE);
1242 val->value = (long long) expr->value;
1243 val->flags = STOR_WANTS_FREE;
1244 insn("movl", val, new, NULL);
1246 return new;
1247 #else
1248 struct storage *val;
1250 val = new_storage(STOR_VALUE);
1251 val->value = (long long) expr->value;
1253 return val; /* FIXME: memory leak */
1254 #endif
1257 static struct storage *emit_divide(struct expression *expr, struct storage *left, struct storage *right)
1259 struct storage *eax_edx;
1260 struct storage *reg, *new;
1261 struct storage *val = new_storage(STOR_VALUE);
1263 emit_comment("begin DIVIDE");
1264 eax_edx = get_hardreg(hardreg_storage_table + EAX_EDX, 1);
1266 /* init EDX to 0 */
1267 val = new_storage(STOR_VALUE);
1268 val->flags = STOR_WANTS_FREE;
1269 emit_move(val, REG_EDX, NULL, NULL);
1271 new = stack_alloc(expr->ctype->bit_size / 8);
1273 /* EAX is dividend */
1274 emit_move(left, REG_EAX, NULL, NULL);
1276 reg = get_reg_value(right);
1278 /* perform binop */
1279 insn("div", reg, REG_EAX, NULL);
1280 put_reg(reg);
1282 reg = REG_EAX;
1283 if (expr->op == '%')
1284 reg = REG_EDX;
1285 emit_move(reg, new, NULL, NULL);
1287 put_reg(eax_edx);
1288 emit_comment("end DIVIDE");
1289 return new;
1292 static struct storage *emit_binop(struct expression *expr)
1294 struct storage *left = x86_expression(expr->left);
1295 struct storage *right = x86_expression(expr->right);
1296 struct storage *new;
1297 struct storage *dest, *src;
1298 const char *opname = NULL;
1299 const char *suffix = NULL;
1300 char opstr[16];
1301 int is_signed;
1303 /* Divides have special register constraints */
1304 if ((expr->op == '/') || (expr->op == '%'))
1305 return emit_divide(expr, left, right);
1307 is_signed = type_is_signed(expr->ctype);
1309 switch (expr->op) {
1310 case '+':
1311 opname = "add";
1312 break;
1313 case '-':
1314 opname = "sub";
1315 break;
1316 case '&':
1317 opname = "and";
1318 break;
1319 case '|':
1320 opname = "or";
1321 break;
1322 case '^':
1323 opname = "xor";
1324 break;
1325 case SPECIAL_LEFTSHIFT:
1326 opname = "shl";
1327 break;
1328 case SPECIAL_RIGHTSHIFT:
1329 if (is_signed)
1330 opname = "sar";
1331 else
1332 opname = "shr";
1333 break;
1334 case '*':
1335 if (is_signed)
1336 opname = "imul";
1337 else
1338 opname = "mul";
1339 break;
1340 case SPECIAL_LOGICAL_AND:
1341 warn(expr->pos, "bogus bitwise and for logical op (should use '2*setne + and' or something)");
1342 opname = "and";
1343 break;
1344 case SPECIAL_LOGICAL_OR:
1345 warn(expr->pos, "bogus bitwise or for logical op (should use 'or + setne' or something)");
1346 opname = "or";
1347 break;
1348 default:
1349 error(expr->pos, "unhandled binop '%s'\n", show_special(expr->op));
1350 break;
1353 dest = get_reg_value(right);
1354 src = get_reg_value(left);
1355 switch (expr->ctype->bit_size) {
1356 case 8:
1357 suffix = "b";
1358 break;
1359 case 16:
1360 suffix = "w";
1361 break;
1362 case 32:
1363 suffix = "l";
1364 break;
1365 case 64:
1366 suffix = "q"; /* FIXME */
1367 break;
1368 default:
1369 assert(0);
1370 break;
1373 snprintf(opstr, sizeof(opstr), "%s%s", opname, suffix);
1375 /* perform binop */
1376 insn(opstr, src, dest, NULL);
1377 put_reg(src);
1379 /* store result in new pseudo / stack slot */
1380 new = stack_alloc(expr->ctype->bit_size / 8);
1381 emit_move(dest, new, NULL, "end EXPR_BINOP");
1383 put_reg(dest);
1385 return new;
1388 static int emit_conditional_test(struct storage *val)
1390 struct storage *target_val;
1391 int target_false;
1393 /* load result into EAX */
1394 insn("movl", val, REG_EAX, "begin if/conditional");
1396 /* compare result with zero */
1397 insn("test", REG_EAX, REG_EAX, NULL);
1399 /* create conditional-failed label to jump to */
1400 target_false = new_label();
1401 target_val = new_storage(STOR_LABEL);
1402 target_val->label = target_false;
1403 target_val->flags = STOR_WANTS_FREE;
1404 insn("jz", target_val, NULL, NULL);
1406 return target_false;
1409 static int emit_conditional_end(int target_false)
1411 struct storage *cond_end_st;
1412 int cond_end;
1414 /* finished generating code for if-true statement.
1415 * add a jump-to-end jump to avoid falling through
1416 * to the if-false statement code.
1418 cond_end = new_label();
1419 cond_end_st = new_storage(STOR_LABEL);
1420 cond_end_st->label = cond_end;
1421 cond_end_st->flags = STOR_WANTS_FREE;
1422 insn("jmp", cond_end_st, NULL, NULL);
1424 /* if we have both if-true and if-false statements,
1425 * the failed-conditional case will fall through to here
1427 emit_label(target_false, NULL);
1429 return cond_end;
1432 static void emit_if_conditional(struct statement *stmt)
1434 struct storage *val;
1435 int cond_end;
1437 /* emit test portion of conditional */
1438 val = x86_expression(stmt->if_conditional);
1439 cond_end = emit_conditional_test(val);
1441 /* emit if-true statement */
1442 x86_statement(stmt->if_true);
1444 /* emit if-false statement, if present */
1445 if (stmt->if_false) {
1446 cond_end = emit_conditional_end(cond_end);
1447 x86_statement(stmt->if_false);
1450 /* end of conditional; jump target for if-true branch */
1451 emit_label(cond_end, "end if");
1454 static struct storage *emit_inc_dec(struct expression *expr, int postop)
1456 struct storage *addr = x86_address_gen(expr->unop);
1457 struct storage *retval;
1458 char opname[16];
1460 strcpy(opname, opbits(expr->op == SPECIAL_INCREMENT ? "inc" : "dec",
1461 expr->ctype->bit_size));
1463 if (postop) {
1464 struct storage *new = stack_alloc(4);
1466 emit_copy(new, addr, expr->unop->ctype);
1468 retval = new;
1469 } else
1470 retval = addr;
1472 insn(opname, addr, NULL, NULL);
1474 return retval;
1477 static struct storage *emit_postop(struct expression *expr)
1479 return emit_inc_dec(expr, 1);
1482 static struct storage *emit_return_stmt(struct statement *stmt)
1484 struct function *f = current_func;
1485 struct expression *expr = stmt->ret_value;
1486 struct storage *val = NULL, *jmplbl;
1488 if (expr && expr->ctype) {
1489 val = x86_expression(expr);
1490 assert(val != NULL);
1491 emit_move(val, REG_EAX, expr->ctype, "return");
1494 jmplbl = new_storage(STOR_LABEL);
1495 jmplbl->flags |= STOR_WANTS_FREE;
1496 jmplbl->label = f->ret_target;
1497 insn("jmp", jmplbl, NULL, NULL);
1499 return val;
1502 static struct storage *emit_conditional_expr(struct expression *expr)
1504 struct storage *cond, *true = NULL, *false = NULL;
1505 struct storage *new = stack_alloc(expr->ctype->bit_size / 8);
1506 int target_false, cond_end;
1508 /* evaluate conditional */
1509 cond = x86_expression(expr->conditional);
1510 target_false = emit_conditional_test(cond);
1512 /* handle if-true part of the expression */
1513 if (!expr->cond_true)
1514 true = cond;
1515 else
1516 true = x86_expression(expr->cond_true);
1518 emit_copy(new, true, expr->ctype);
1520 cond_end = emit_conditional_end(target_false);
1522 /* handle if-false part of the expression */
1523 false = x86_expression(expr->cond_false);
1525 emit_copy(new, false, expr->ctype);
1527 /* end of conditional; jump target for if-true branch */
1528 emit_label(cond_end, "end conditional");
1530 return new;
1533 static struct storage *emit_select_expr(struct expression *expr)
1535 struct storage *cond = x86_expression(expr->conditional);
1536 struct storage *true = x86_expression(expr->cond_true);
1537 struct storage *false = x86_expression(expr->cond_false);
1538 struct storage *reg_cond, *reg_true, *reg_false;
1539 struct storage *new = stack_alloc(4);
1541 emit_comment("begin SELECT");
1542 reg_cond = get_reg_value(cond);
1543 reg_true = reg_cond;
1544 if (true) {
1545 reg_true = get_reg_value(true);
1547 reg_false = get_reg_value(false);
1550 * Do the actual select: check the conditional for zero,
1551 * move false over true if zero
1553 insn("test", reg_cond, reg_cond, NULL);
1554 insn("cmovz", reg_false, reg_true, NULL);
1556 /* Store it back */
1557 emit_move(reg_true, new, expr->ctype, NULL);
1558 put_reg(reg_cond);
1559 if (true)
1560 put_reg(reg_true);
1561 put_reg(reg_false);
1562 emit_comment("end SELECT");
1563 return new;
1566 static struct storage *emit_symbol_expr_init(struct symbol *sym)
1568 struct expression *expr = sym->initializer;
1569 struct symbol_private *priv = sym->aux;
1571 if (priv == NULL) {
1572 priv = calloc(1, sizeof(*priv));
1573 sym->aux = priv;
1575 if (expr == NULL) {
1576 struct storage *new = stack_alloc(4);
1577 fprintf(stderr, "FIXME! no value for symbol %s. creating pseudo %d (stack offset %d)\n",
1578 show_ident(sym->ident),
1579 new->pseudo, new->pseudo * 4);
1580 priv->addr = new;
1581 } else {
1582 priv->addr = x86_expression(expr);
1586 return priv->addr;
1589 static struct storage *emit_string_expr(struct expression *expr)
1591 struct function *f = current_func;
1592 int label = new_label();
1593 struct storage *new;
1595 push_cstring(f, expr->string, label);
1597 new = new_storage(STOR_LABEL);
1598 new->label = label;
1599 new->flags = STOR_LABEL_VAL | STOR_WANTS_FREE;
1600 return new;
1603 static struct storage *emit_cast_expr(struct expression *expr)
1605 struct symbol *old_type, *new_type;
1606 struct storage *op = x86_expression(expr->cast_expression);
1607 int oldbits, newbits;
1608 struct storage *new;
1610 old_type = expr->cast_expression->ctype;
1611 new_type = expr->cast_type;
1613 oldbits = old_type->bit_size;
1614 newbits = new_type->bit_size;
1615 if (oldbits >= newbits)
1616 return op;
1618 emit_move(op, REG_EAX, old_type, "begin cast ..");
1620 new = stack_alloc(newbits / 8);
1621 emit_move(REG_EAX, new, new_type, ".... end cast");
1623 return new;
1626 static struct storage *emit_regular_preop(struct expression *expr)
1628 struct storage *target = x86_expression(expr->unop);
1629 struct storage *val, *new = stack_alloc(4);
1630 const char *opname = NULL;
1632 switch (expr->op) {
1633 case '!':
1634 val = new_storage(STOR_VALUE);
1635 val->flags = STOR_WANTS_FREE;
1636 emit_move(val, REG_EDX, NULL, NULL);
1637 emit_move(target, REG_EAX, expr->unop->ctype, NULL);
1638 insn("test", REG_EAX, REG_EAX, NULL);
1639 insn("setz", REG_DL, NULL, NULL);
1640 emit_move(REG_EDX, new, expr->unop->ctype, NULL);
1642 break;
1643 case '~':
1644 opname = "not";
1645 case '-':
1646 if (!opname)
1647 opname = "neg";
1648 emit_move(target, REG_EAX, expr->unop->ctype, NULL);
1649 insn(opname, REG_EAX, NULL, NULL);
1650 emit_move(REG_EAX, new, expr->unop->ctype, NULL);
1651 break;
1652 default:
1653 assert(0);
1654 break;
1657 return new;
1660 static void emit_case_statement(struct statement *stmt)
1662 emit_labelsym(stmt->case_label, NULL);
1663 x86_statement(stmt->case_statement);
1666 static void emit_switch_statement(struct statement *stmt)
1668 struct storage *val = x86_expression(stmt->switch_expression);
1669 struct symbol *sym, *default_sym = NULL;
1670 struct storage *labelsym, *label;
1671 int switch_end = 0;
1673 emit_move(val, REG_EAX, stmt->switch_expression->ctype, "begin case");
1676 * This is where a _real_ back-end would go through the
1677 * cases to decide whether to use a lookup table or a
1678 * series of comparisons etc
1680 FOR_EACH_PTR(stmt->switch_case->symbol_list, sym) {
1681 struct statement *case_stmt = sym->stmt;
1682 struct expression *expr = case_stmt->case_expression;
1683 struct expression *to = case_stmt->case_to;
1685 /* default: */
1686 if (!expr)
1687 default_sym = sym;
1689 /* case NNN: */
1690 else {
1691 struct storage *case_val = new_val(expr->value);
1693 assert (expr->type == EXPR_VALUE);
1695 insn("cmpl", case_val, REG_EAX, NULL);
1697 if (!to) {
1698 labelsym = new_labelsym(sym);
1699 insn("je", labelsym, NULL, NULL);
1700 } else {
1701 int next_test;
1703 label = new_storage(STOR_LABEL);
1704 label->flags |= STOR_WANTS_FREE;
1705 label->label = next_test = new_label();
1707 /* FIXME: signed/unsigned */
1708 insn("jl", label, NULL, NULL);
1710 case_val = new_val(to->value);
1711 insn("cmpl", case_val, REG_EAX, NULL);
1713 /* TODO: implement and use refcounting... */
1714 label = new_storage(STOR_LABEL);
1715 label->flags |= STOR_WANTS_FREE;
1716 label->label = next_test;
1718 /* FIXME: signed/unsigned */
1719 insn("jg", label, NULL, NULL);
1721 labelsym = new_labelsym(sym);
1722 insn("jmp", labelsym, NULL, NULL);
1724 emit_label(next_test, NULL);
1727 } END_FOR_EACH_PTR;
1729 if (default_sym) {
1730 labelsym = new_labelsym(default_sym);
1731 insn("jmp", labelsym, NULL, "default");
1732 } else {
1733 label = new_storage(STOR_LABEL);
1734 label->flags |= STOR_WANTS_FREE;
1735 label->label = switch_end = new_label();
1736 insn("jmp", label, NULL, "goto end of switch");
1739 x86_statement(stmt->switch_statement);
1741 if (stmt->switch_break->used)
1742 emit_labelsym(stmt->switch_break, NULL);
1744 if (switch_end)
1745 emit_label(switch_end, NULL);
1748 static void x86_struct_member(struct symbol *sym, void *data, int flags)
1750 if (flags & ITERATE_FIRST)
1751 printf(" {\n\t");
1752 printf("%s:%d:%ld at offset %ld", show_ident(sym->ident), sym->bit_size, sym->ctype.alignment, sym->offset);
1753 if (sym->fieldwidth)
1754 printf("[%d..%d]", sym->bit_offset, sym->bit_offset+sym->fieldwidth-1);
1755 if (flags & ITERATE_LAST)
1756 printf("\n} ");
1757 else
1758 printf(", ");
1761 static void x86_symbol(struct symbol *sym)
1763 struct symbol *type;
1765 if (!sym)
1766 return;
1768 type = sym->ctype.base_type;
1769 if (!type)
1770 return;
1773 * Show actual implementation information
1775 switch (type->type) {
1777 case SYM_ARRAY:
1778 if (sym->initializer)
1779 emit_array(sym);
1780 else
1781 emit_array_noinit(sym);
1782 break;
1784 case SYM_BASETYPE:
1785 if (sym->initializer) {
1786 emit_object_pre(show_ident(sym->ident),
1787 sym->ctype.modifiers,
1788 sym->ctype.alignment,
1789 sym->bit_size / 8);
1790 emit_scalar(sym->initializer, sym->bit_size);
1791 stor_sym_init(sym);
1792 } else
1793 emit_scalar_noinit(sym);
1794 break;
1796 case SYM_STRUCT:
1797 symbol_iterate(type->symbol_list, x86_struct_member, NULL);
1798 break;
1800 case SYM_UNION:
1801 symbol_iterate(type->symbol_list, x86_struct_member, NULL);
1802 break;
1804 case SYM_FN: {
1805 struct statement *stmt = type->stmt;
1806 if (stmt) {
1807 emit_func_pre(sym);
1808 x86_statement(stmt);
1809 emit_func_post(sym);
1811 break;
1814 default:
1815 break;
1818 if (sym->initializer && (type->type != SYM_BASETYPE) &&
1819 (type->type != SYM_ARRAY)) {
1820 printf(" = \n");
1821 x86_expression(sym->initializer);
1825 static void x86_symbol_init(struct symbol *sym);
1827 static void x86_symbol_decl(struct symbol_list *syms)
1829 struct symbol *sym;
1830 FOR_EACH_PTR(syms, sym) {
1831 x86_symbol_init(sym);
1832 } END_FOR_EACH_PTR;
1835 static void loopstk_push(int cont_lbl, int loop_bottom_lbl)
1837 struct function *f = current_func;
1838 struct loop_stack *ls;
1840 ls = malloc(sizeof(*ls));
1841 ls->continue_lbl = cont_lbl;
1842 ls->loop_bottom_lbl = loop_bottom_lbl;
1843 ls->next = f->loop_stack;
1844 f->loop_stack = ls;
1847 static void loopstk_pop(void)
1849 struct function *f = current_func;
1850 struct loop_stack *ls;
1852 assert(f->loop_stack != NULL);
1853 ls = f->loop_stack;
1854 f->loop_stack = f->loop_stack->next;
1855 free(ls);
1858 static int loopstk_break(void)
1860 return current_func->loop_stack->loop_bottom_lbl;
1863 static int loopstk_continue(void)
1865 return current_func->loop_stack->continue_lbl;
1868 static void emit_loop(struct statement *stmt)
1870 struct statement *pre_statement = stmt->iterator_pre_statement;
1871 struct expression *pre_condition = stmt->iterator_pre_condition;
1872 struct statement *statement = stmt->iterator_statement;
1873 struct statement *post_statement = stmt->iterator_post_statement;
1874 struct expression *post_condition = stmt->iterator_post_condition;
1875 int loop_top = 0, loop_bottom, loop_continue;
1876 int have_bottom = 0;
1877 struct storage *val;
1879 loop_bottom = new_label();
1880 loop_continue = new_label();
1881 loopstk_push(loop_continue, loop_bottom);
1883 x86_symbol_decl(stmt->iterator_syms);
1884 x86_statement(pre_statement);
1885 if (pre_condition) {
1886 if (pre_condition->type == EXPR_VALUE) {
1887 if (!pre_condition->value) {
1888 struct storage *lbv;
1889 lbv = new_storage(STOR_LABEL);
1890 lbv->label = loop_bottom;
1891 lbv->flags = STOR_WANTS_FREE;
1892 insn("jmp", lbv, NULL, "go to loop bottom");
1893 have_bottom = 1;
1895 } else {
1896 struct storage *lbv = new_storage(STOR_LABEL);
1897 lbv->label = loop_bottom;
1898 lbv->flags = STOR_WANTS_FREE;
1899 have_bottom = 1;
1901 val = x86_expression(pre_condition);
1903 emit_move(val, REG_EAX, NULL, "loop pre condition");
1904 insn("test", REG_EAX, REG_EAX, NULL);
1905 insn("jz", lbv, NULL, NULL);
1908 if (!post_condition || post_condition->type != EXPR_VALUE || post_condition->value) {
1909 loop_top = new_label();
1910 emit_label(loop_top, "loop top");
1912 x86_statement(statement);
1913 if (stmt->iterator_continue->used)
1914 emit_label(loop_continue, "'continue' iterator");
1915 x86_statement(post_statement);
1916 if (!post_condition) {
1917 struct storage *lbv = new_storage(STOR_LABEL);
1918 lbv->label = loop_top;
1919 lbv->flags = STOR_WANTS_FREE;
1920 insn("jmp", lbv, NULL, "go to loop top");
1921 } else if (post_condition->type == EXPR_VALUE) {
1922 if (post_condition->value) {
1923 struct storage *lbv = new_storage(STOR_LABEL);
1924 lbv->label = loop_top;
1925 lbv->flags = STOR_WANTS_FREE;
1926 insn("jmp", lbv, NULL, "go to loop top");
1928 } else {
1929 struct storage *lbv = new_storage(STOR_LABEL);
1930 lbv->label = loop_top;
1931 lbv->flags = STOR_WANTS_FREE;
1933 val = x86_expression(post_condition);
1935 emit_move(val, REG_EAX, NULL, "loop post condition");
1936 insn("test", REG_EAX, REG_EAX, NULL);
1937 insn("jnz", lbv, NULL, NULL);
1939 if (have_bottom || stmt->iterator_break->used)
1940 emit_label(loop_bottom, "loop bottom");
1942 loopstk_pop();
1946 * Print out a statement
1948 static struct storage *x86_statement(struct statement *stmt)
1950 if (!stmt)
1951 return NULL;
1952 switch (stmt->type) {
1953 case STMT_RETURN:
1954 return emit_return_stmt(stmt);
1955 case STMT_COMPOUND: {
1956 struct statement *s;
1957 struct storage *last = NULL;
1959 x86_symbol_decl(stmt->syms);
1960 FOR_EACH_PTR(stmt->stmts, s) {
1961 last = x86_statement(s);
1962 } END_FOR_EACH_PTR;
1964 return last;
1967 case STMT_EXPRESSION:
1968 return x86_expression(stmt->expression);
1969 case STMT_IF:
1970 emit_if_conditional(stmt);
1971 return NULL;
1973 case STMT_CASE:
1974 emit_case_statement(stmt);
1975 break;
1976 case STMT_SWITCH:
1977 emit_switch_statement(stmt);
1978 break;
1980 case STMT_ITERATOR:
1981 emit_loop(stmt);
1982 break;
1984 case STMT_NONE:
1985 break;
1987 case STMT_LABEL:
1988 printf(".L%p:\n", stmt->label_identifier);
1989 x86_statement(stmt->label_statement);
1990 break;
1992 case STMT_GOTO:
1993 if (stmt->goto_expression) {
1994 struct storage *val = x86_expression(stmt->goto_expression);
1995 printf("\tgoto *v%d\n", val->pseudo);
1996 } else if (!strcmp("break", show_ident(stmt->goto_label->ident))) {
1997 struct storage *lbv = new_storage(STOR_LABEL);
1998 lbv->label = loopstk_break();
1999 lbv->flags = STOR_WANTS_FREE;
2000 insn("jmp", lbv, NULL, "'break'; go to loop bottom");
2001 } else if (!strcmp("continue", show_ident(stmt->goto_label->ident))) {
2002 struct storage *lbv = new_storage(STOR_LABEL);
2003 lbv->label = loopstk_continue();
2004 lbv->flags = STOR_WANTS_FREE;
2005 insn("jmp", lbv, NULL, "'continue'; go to loop top");
2006 } else {
2007 struct storage *labelsym = new_labelsym(stmt->goto_label);
2008 insn("jmp", labelsym, NULL, NULL);
2010 break;
2011 case STMT_ASM:
2012 printf("\tasm( .... )\n");
2013 break;
2015 return NULL;
2018 static struct storage *x86_call_expression(struct expression *expr)
2020 struct function *f = current_func;
2021 struct symbol *direct;
2022 struct expression *arg, *fn;
2023 struct storage *retval, *fncall;
2024 int framesize;
2025 char s[64];
2027 if (!expr->ctype) {
2028 warn(expr->pos, "\tcall with no type!");
2029 return NULL;
2032 framesize = 0;
2033 FOR_EACH_PTR_REVERSE(expr->args, arg) {
2034 struct storage *new = x86_expression(arg);
2035 int size = arg->ctype->bit_size;
2038 * FIXME: i386 SysV ABI dictates that values
2039 * smaller than 32 bits should be placed onto
2040 * the stack as 32-bit objects. We should not
2041 * blindly do a 32-bit push on objects smaller
2042 * than 32 bits.
2044 if (size < 32)
2045 size = 32;
2046 insn("pushl", new, NULL,
2047 !framesize ? "begin function call" : NULL);
2049 framesize += size >> 3;
2050 } END_FOR_EACH_PTR_REVERSE;
2052 fn = expr->fn;
2054 /* Remove dereference, if any */
2055 direct = NULL;
2056 if (fn->type == EXPR_PREOP) {
2057 if (fn->unop->type == EXPR_SYMBOL) {
2058 struct symbol *sym = fn->unop->symbol;
2059 if (sym->ctype.base_type->type == SYM_FN)
2060 direct = sym;
2063 if (direct) {
2064 struct storage *direct_stor = new_storage(STOR_SYM);
2065 direct_stor->flags |= STOR_WANTS_FREE;
2066 direct_stor->sym = direct;
2067 insn("call", direct_stor, NULL, NULL);
2068 } else {
2069 fncall = x86_expression(fn);
2070 emit_move(fncall, REG_EAX, fn->ctype, NULL);
2072 strcpy(s, "\tcall\t*%eax\n");
2073 push_text_atom(f, s);
2076 /* FIXME: pay attention to BITS_IN_POINTER */
2077 if (framesize) {
2078 struct storage *val = new_storage(STOR_VALUE);
2079 val->value = (long long) framesize;
2080 val->flags = STOR_WANTS_FREE;
2081 insn("addl", val, REG_ESP, NULL);
2084 retval = stack_alloc(4);
2085 emit_move(REG_EAX, retval, NULL, "end function call");
2087 return retval;
2090 static struct storage *x86_address_gen(struct expression *expr)
2092 struct function *f = current_func;
2093 struct storage *addr;
2094 struct storage *new;
2095 char s[32];
2097 if ((expr->type != EXPR_PREOP) || (expr->op != '*'))
2098 return x86_expression(expr->address);
2100 addr = x86_expression(expr->unop);
2101 if (expr->unop->type == EXPR_SYMBOL)
2102 return addr;
2104 emit_move(addr, REG_EAX, NULL, "begin deref ..");
2106 /* FIXME: operand size */
2107 strcpy(s, "\tmovl\t(%eax), %ecx\n");
2108 push_text_atom(f, s);
2110 new = stack_alloc(4);
2111 emit_move(REG_ECX, new, NULL, ".... end deref");
2113 return new;
2116 static struct storage *x86_assignment(struct expression *expr)
2118 struct expression *target = expr->left;
2119 struct storage *val, *addr;
2121 if (!expr->ctype)
2122 return NULL;
2124 val = x86_expression(expr->right);
2125 addr = x86_address_gen(target);
2127 switch (val->type) {
2128 /* copy, where both operands are memory */
2129 case STOR_PSEUDO:
2130 case STOR_ARG:
2131 emit_copy(addr, val, expr->ctype);
2132 break;
2134 /* copy, one or zero operands are memory */
2135 case STOR_REG:
2136 case STOR_SYM:
2137 case STOR_VALUE:
2138 case STOR_LABEL:
2139 emit_move(val, addr, expr->left->ctype, NULL);
2140 break;
2142 case STOR_LABELSYM:
2143 assert(0);
2144 break;
2146 return val;
2149 static int x86_initialization(struct symbol *sym, struct expression *expr)
2151 struct storage *val, *addr;
2152 int bits;
2154 if (!expr->ctype)
2155 return 0;
2157 bits = expr->ctype->bit_size;
2158 val = x86_expression(expr);
2159 addr = x86_symbol_expr(sym);
2160 // FIXME! The "target" expression is for bitfield store information.
2161 // Leave it NULL, which works fine.
2162 emit_store(NULL, addr, val, bits);
2163 return 0;
2166 static struct storage *x86_access(struct expression *expr)
2168 return x86_address_gen(expr);
2171 static struct storage *x86_preop(struct expression *expr)
2174 * '*' is an lvalue access, and is fundamentally different
2175 * from an arithmetic operation. Maybe it should have an
2176 * expression type of its own..
2178 if (expr->op == '*')
2179 return x86_access(expr);
2180 if (expr->op == SPECIAL_INCREMENT || expr->op == SPECIAL_DECREMENT)
2181 return emit_inc_dec(expr, 0);
2182 return emit_regular_preop(expr);
2185 static struct storage *x86_symbol_expr(struct symbol *sym)
2187 struct storage *new = stack_alloc(4);
2189 if (sym->ctype.modifiers & (MOD_TOPLEVEL | MOD_EXTERN | MOD_STATIC)) {
2190 printf("\tmovi.%d\t\tv%d,$%s\n", bits_in_pointer, new->pseudo, show_ident(sym->ident));
2191 return new;
2193 if (sym->ctype.modifiers & MOD_ADDRESSABLE) {
2194 printf("\taddi.%d\t\tv%d,vFP,$%lld\n", bits_in_pointer, new->pseudo, sym->value);
2195 return new;
2197 printf("\taddi.%d\t\tv%d,vFP,$offsetof(%s:%p)\n", bits_in_pointer, new->pseudo, show_ident(sym->ident), sym);
2198 return new;
2201 static void x86_symbol_init(struct symbol *sym)
2203 struct symbol_private *priv = sym->aux;
2204 struct expression *expr = sym->initializer;
2205 struct storage *new;
2207 if (expr)
2208 new = x86_expression(expr);
2209 else
2210 new = stack_alloc(sym->bit_size / 8);
2212 if (!priv) {
2213 priv = calloc(1, sizeof(*priv));
2214 sym->aux = priv;
2215 /* FIXME: leak! we don't free... */
2216 /* (well, we don't free symbols either) */
2219 priv->addr = new;
2222 static int type_is_signed(struct symbol *sym)
2224 if (sym->type == SYM_NODE)
2225 sym = sym->ctype.base_type;
2226 if (sym->type == SYM_PTR)
2227 return 0;
2228 return !(sym->ctype.modifiers & MOD_UNSIGNED);
2231 static struct storage *x86_bitfield_expr(struct expression *expr)
2233 return x86_access(expr);
2236 static struct storage *x86_label_expr(struct expression *expr)
2238 struct storage *new = stack_alloc(4);
2239 printf("\tmovi.%d\t\tv%d,.L%p\n", bits_in_pointer, new->pseudo, expr->label_symbol);
2240 return new;
2243 static struct storage *x86_statement_expr(struct expression *expr)
2245 return x86_statement(expr->statement);
2248 static int x86_position_expr(struct expression *expr, struct symbol *base)
2250 struct storage *new = x86_expression(expr->init_expr);
2251 struct symbol *ctype = expr->init_sym;
2253 printf("\tinsert v%d at [%d:%d] of %s\n", new->pseudo,
2254 expr->init_offset, ctype->bit_offset,
2255 show_ident(base->ident));
2256 return 0;
2259 static void x86_initializer_expr(struct expression *expr, struct symbol *ctype)
2261 struct expression *entry;
2263 FOR_EACH_PTR(expr->expr_list, entry) {
2264 // Nested initializers have their positions already
2265 // recursively calculated - just output them too
2266 if (entry->type == EXPR_INITIALIZER) {
2267 x86_initializer_expr(entry, ctype);
2268 continue;
2271 // Ignore initializer indexes and identifiers - the
2272 // evaluator has taken them into account
2273 if (entry->type == EXPR_IDENTIFIER || entry->type == EXPR_INDEX)
2274 continue;
2275 if (entry->type == EXPR_POS) {
2276 x86_position_expr(entry, ctype);
2277 continue;
2279 x86_initialization(ctype, entry);
2280 } END_FOR_EACH_PTR;
2284 * Print out an expression. Return the pseudo that contains the
2285 * variable.
2287 static struct storage *x86_expression(struct expression *expr)
2289 if (!expr)
2290 return NULL;
2292 if (!expr->ctype) {
2293 struct position *pos = &expr->pos;
2294 printf("\tno type at %s:%d:%d\n",
2295 input_streams[pos->stream].name,
2296 pos->line, pos->pos);
2297 return NULL;
2300 switch (expr->type) {
2301 case EXPR_CALL:
2302 return x86_call_expression(expr);
2304 case EXPR_ASSIGNMENT:
2305 return x86_assignment(expr);
2307 case EXPR_COMPARE:
2308 return emit_compare(expr);
2309 case EXPR_BINOP:
2310 case EXPR_COMMA:
2311 case EXPR_LOGICAL:
2312 return emit_binop(expr);
2313 case EXPR_PREOP:
2314 return x86_preop(expr);
2315 case EXPR_POSTOP:
2316 return emit_postop(expr);
2317 case EXPR_SYMBOL:
2318 return emit_symbol_expr_init(expr->symbol);
2319 case EXPR_DEREF:
2320 case EXPR_SIZEOF:
2321 case EXPR_ALIGNOF:
2322 warn(expr->pos, "invalid expression after evaluation");
2323 return NULL;
2324 case EXPR_CAST:
2325 return emit_cast_expr(expr);
2326 case EXPR_VALUE:
2327 return emit_value(expr);
2328 case EXPR_STRING:
2329 return emit_string_expr(expr);
2330 case EXPR_BITFIELD:
2331 return x86_bitfield_expr(expr);
2332 case EXPR_INITIALIZER:
2333 x86_initializer_expr(expr, expr->ctype);
2334 return NULL;
2335 case EXPR_SELECT:
2336 return emit_select_expr(expr);
2337 case EXPR_CONDITIONAL:
2338 return emit_conditional_expr(expr);
2339 case EXPR_STATEMENT:
2340 return x86_statement_expr(expr);
2341 case EXPR_LABEL:
2342 return x86_label_expr(expr);
2344 // None of these should exist as direct expressions: they are only
2345 // valid as sub-expressions of initializers.
2346 case EXPR_POS:
2347 warn(expr->pos, "unable to show plain initializer position expression");
2348 return NULL;
2349 case EXPR_IDENTIFIER:
2350 warn(expr->pos, "unable to show identifier expression");
2351 return NULL;
2352 case EXPR_INDEX:
2353 warn(expr->pos, "unable to show index expression");
2354 return NULL;
2355 case EXPR_TYPE:
2356 warn(expr->pos, "unable to show type expression");
2357 return NULL;
2358 case EXPR_FVALUE:
2359 warn(expr->pos, "floating point support is not implemented");
2360 return NULL;
2362 return NULL;