db: look up all the function pointers
[smatch.git] / compile-i386.c
blobda3ee4978f728056c2a5f0621cc910c065d258d1
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 "allocate.h"
36 #include "token.h"
37 #include "parse.h"
38 #include "symbol.h"
39 #include "scope.h"
40 #include "expression.h"
41 #include "target.h"
42 #include "compile.h"
43 #include "bitmap.h"
45 struct textbuf {
46 unsigned int len; /* does NOT include terminating null */
47 char *text;
48 struct textbuf *next;
49 struct textbuf *prev;
52 struct loop_stack {
53 int continue_lbl;
54 int loop_bottom_lbl;
55 struct loop_stack *next;
58 struct atom;
59 struct storage;
60 DECLARE_PTR_LIST(str_list, struct atom);
61 DECLARE_PTR_LIST(atom_list, struct atom);
62 DECLARE_PTR_LIST(storage_list, struct storage);
64 struct function {
65 int stack_size;
66 int pseudo_nr;
67 struct storage_list *pseudo_list;
68 struct atom_list *atom_list;
69 struct str_list *str_list;
70 struct loop_stack *loop_stack;
71 struct symbol **argv;
72 unsigned int argc;
73 int ret_target;
76 enum storage_type {
77 STOR_PSEUDO, /* variable stored on the stack */
78 STOR_ARG, /* function argument */
79 STOR_SYM, /* a symbol we can directly ref in the asm */
80 STOR_REG, /* scratch register */
81 STOR_VALUE, /* integer constant */
82 STOR_LABEL, /* label / jump target */
83 STOR_LABELSYM, /* label generated from symbol's pointer value */
86 struct reg_info {
87 const char *name;
88 struct storage *contains;
89 const unsigned char aliases[12];
90 #define own_regno aliases[0]
93 struct storage {
94 enum storage_type type;
95 unsigned long flags;
97 /* STOR_REG */
98 struct reg_info *reg;
99 struct symbol *ctype;
101 union {
102 /* STOR_PSEUDO */
103 struct {
104 int pseudo;
105 int offset;
106 int size;
108 /* STOR_ARG */
109 struct {
110 int idx;
112 /* STOR_SYM */
113 struct {
114 struct symbol *sym;
116 /* STOR_VALUE */
117 struct {
118 long long value;
120 /* STOR_LABEL */
121 struct {
122 int label;
124 /* STOR_LABELSYM */
125 struct {
126 struct symbol *labelsym;
131 enum {
132 STOR_LABEL_VAL = (1 << 0),
133 STOR_WANTS_FREE = (1 << 1),
136 struct symbol_private {
137 struct storage *addr;
140 enum atom_type {
141 ATOM_TEXT,
142 ATOM_INSN,
143 ATOM_CSTR,
146 struct atom {
147 enum atom_type type;
148 union {
149 /* stuff for text */
150 struct {
151 char *text;
152 unsigned int text_len; /* w/o terminating null */
155 /* stuff for insns */
156 struct {
157 char insn[32];
158 char comment[40];
159 struct storage *op1;
160 struct storage *op2;
163 /* stuff for C strings */
164 struct {
165 struct string *string;
166 int label;
172 static struct function *current_func = NULL;
173 static struct textbuf *unit_post_text = NULL;
174 static const char *current_section;
176 static void emit_comment(const char * fmt, ...) FORMAT_ATTR(1);
177 static void emit_move(struct storage *src, struct storage *dest,
178 struct symbol *ctype, const char *comment);
179 static int type_is_signed(struct symbol *sym);
180 static struct storage *x86_address_gen(struct expression *expr);
181 static struct storage *x86_symbol_expr(struct symbol *sym);
182 static void x86_symbol(struct symbol *sym);
183 static struct storage *x86_statement(struct statement *stmt);
184 static struct storage *x86_expression(struct expression *expr);
186 enum registers {
187 NOREG,
188 AL, DL, CL, BL, AH, DH, CH, BH, // 8-bit
189 AX, DX, CX, BX, SI, DI, BP, SP, // 16-bit
190 EAX, EDX, ECX, EBX, ESI, EDI, EBP, ESP, // 32-bit
191 EAX_EDX, ECX_EBX, ESI_EDI, // 64-bit
194 /* This works on regno's, reg_info's and hardreg_storage's */
195 #define byte_reg(reg) ((reg) - 16)
196 #define highbyte_reg(reg) ((reg)-12)
197 #define word_reg(reg) ((reg)-8)
199 #define REGINFO(nr, str, conflicts...) [nr] = { .name = str, .aliases = { nr , conflicts } }
201 static struct reg_info reg_info_table[] = {
202 REGINFO( AL, "%al", AX, EAX, EAX_EDX),
203 REGINFO( DL, "%dl", DX, EDX, EAX_EDX),
204 REGINFO( CL, "%cl", CX, ECX, ECX_EBX),
205 REGINFO( BL, "%bl", BX, EBX, ECX_EBX),
206 REGINFO( AH, "%ah", AX, EAX, EAX_EDX),
207 REGINFO( DH, "%dh", DX, EDX, EAX_EDX),
208 REGINFO( CH, "%ch", CX, ECX, ECX_EBX),
209 REGINFO( BH, "%bh", BX, EBX, ECX_EBX),
210 REGINFO( AX, "%ax", AL, AH, EAX, EAX_EDX),
211 REGINFO( DX, "%dx", DL, DH, EDX, EAX_EDX),
212 REGINFO( CX, "%cx", CL, CH, ECX, ECX_EBX),
213 REGINFO( BX, "%bx", BL, BH, EBX, ECX_EBX),
214 REGINFO( SI, "%si", ESI, ESI_EDI),
215 REGINFO( DI, "%di", EDI, ESI_EDI),
216 REGINFO( BP, "%bp", EBP),
217 REGINFO( SP, "%sp", ESP),
218 REGINFO(EAX, "%eax", AL, AH, AX, EAX_EDX),
219 REGINFO(EDX, "%edx", DL, DH, DX, EAX_EDX),
220 REGINFO(ECX, "%ecx", CL, CH, CX, ECX_EBX),
221 REGINFO(EBX, "%ebx", BL, BH, BX, ECX_EBX),
222 REGINFO(ESI, "%esi", SI, ESI_EDI),
223 REGINFO(EDI, "%edi", DI, ESI_EDI),
224 REGINFO(EBP, "%ebp", BP),
225 REGINFO(ESP, "%esp", SP),
226 REGINFO(EAX_EDX, "%eax:%edx", AL, AH, AX, EAX, DL, DH, DX, EDX),
227 REGINFO(ECX_EBX, "%ecx:%ebx", CL, CH, CX, ECX, BL, BH, BX, EBX),
228 REGINFO(ESI_EDI, "%esi:%edi", SI, ESI, DI, EDI),
231 #define REGSTORAGE(nr) [nr] = { .type = STOR_REG, .reg = reg_info_table + (nr) }
233 static struct storage hardreg_storage_table[] = {
234 REGSTORAGE(AL), REGSTORAGE(DL), REGSTORAGE(CL), REGSTORAGE(BL),
235 REGSTORAGE(AH), REGSTORAGE(DH), REGSTORAGE(CH), REGSTORAGE(BH),
236 REGSTORAGE(AX), REGSTORAGE(DX), REGSTORAGE(CX), REGSTORAGE(BX),
237 REGSTORAGE(SI), REGSTORAGE(DI), REGSTORAGE(BP), REGSTORAGE(SP),
238 REGSTORAGE(EAX), REGSTORAGE(EDX), REGSTORAGE(ECX), REGSTORAGE(EBX),
239 REGSTORAGE(ESI), REGSTORAGE(EDI), REGSTORAGE(EBP), REGSTORAGE(ESP),
240 REGSTORAGE(EAX_EDX), REGSTORAGE(ECX_EBX), REGSTORAGE(ESI_EDI),
243 #define REG_EAX (&hardreg_storage_table[EAX])
244 #define REG_ECX (&hardreg_storage_table[ECX])
245 #define REG_EDX (&hardreg_storage_table[EDX])
246 #define REG_ESP (&hardreg_storage_table[ESP])
247 #define REG_DL (&hardreg_storage_table[DL])
248 #define REG_DX (&hardreg_storage_table[DX])
249 #define REG_AL (&hardreg_storage_table[AL])
250 #define REG_AX (&hardreg_storage_table[AX])
252 static DECLARE_BITMAP(regs_in_use, 256);
254 static inline struct storage * reginfo_reg(struct reg_info *info)
256 return hardreg_storage_table + info->own_regno;
259 static struct storage * get_hardreg(struct storage *reg, int clear)
261 struct reg_info *info = reg->reg;
262 const unsigned char *aliases;
263 int regno;
265 aliases = info->aliases;
266 while ((regno = *aliases++) != NOREG) {
267 if (test_bit(regno, regs_in_use))
268 goto busy;
269 if (clear)
270 reg_info_table[regno].contains = NULL;
272 set_bit(info->own_regno, regs_in_use);
273 return reg;
274 busy:
275 fprintf(stderr, "register %s is busy\n", info->name);
276 if (regno + reg_info_table != info)
277 fprintf(stderr, " conflicts with %s\n", reg_info_table[regno].name);
278 exit(1);
281 static void put_reg(struct storage *reg)
283 struct reg_info *info = reg->reg;
284 int regno = info->own_regno;
286 if (test_and_clear_bit(regno, regs_in_use))
287 return;
288 fprintf(stderr, "freeing already free'd register %s\n", reg_info_table[regno].name);
291 struct regclass {
292 const char *name;
293 const unsigned char regs[30];
296 static struct regclass regclass_8 = { "8-bit", { AL, DL, CL, BL, AH, DH, CH, BH }};
297 static struct regclass regclass_16 = { "16-bit", { AX, DX, CX, BX, SI, DI, BP }};
298 static struct regclass regclass_32 = { "32-bit", { EAX, EDX, ECX, EBX, ESI, EDI, EBP }};
299 static struct regclass regclass_64 = { "64-bit", { EAX_EDX, ECX_EBX, ESI_EDI }};
301 static struct regclass regclass_32_8 = { "32-bit bytes", { EAX, EDX, ECX, EBX }};
303 static struct regclass *get_regclass_bits(int bits)
305 switch (bits) {
306 case 8: return &regclass_8;
307 case 16: return &regclass_16;
308 case 64: return &regclass_64;
309 default: return &regclass_32;
313 static struct regclass *get_regclass(struct expression *expr)
315 return get_regclass_bits(expr->ctype->bit_size);
318 static int register_busy(int regno)
320 if (!test_bit(regno, regs_in_use)) {
321 struct reg_info *info = reg_info_table + regno;
322 const unsigned char *regs = info->aliases+1;
324 while ((regno = *regs) != NOREG) {
325 regs++;
326 if (test_bit(regno, regs_in_use))
327 goto busy;
329 return 0;
331 busy:
332 return 1;
335 static struct storage *get_reg(struct regclass *class)
337 const unsigned char *regs = class->regs;
338 int regno;
340 while ((regno = *regs) != NOREG) {
341 regs++;
342 if (register_busy(regno))
343 continue;
344 return get_hardreg(hardreg_storage_table + regno, 1);
346 fprintf(stderr, "Ran out of %s registers\n", class->name);
347 exit(1);
350 static struct storage *get_reg_value(struct storage *value, struct regclass *class)
352 struct reg_info *info;
353 struct storage *reg;
355 /* Do we already have it somewhere */
356 info = value->reg;
357 if (info && info->contains == value) {
358 emit_comment("already have register %s", info->name);
359 return get_hardreg(hardreg_storage_table + info->own_regno, 0);
362 reg = get_reg(class);
363 emit_move(value, reg, value->ctype, "reload register");
364 info = reg->reg;
365 info->contains = value;
366 value->reg = info;
367 return reg;
370 static struct storage *temp_from_bits(unsigned int bit_size)
372 return get_reg(get_regclass_bits(bit_size));
375 static inline unsigned int pseudo_offset(struct storage *s)
377 if (s->type != STOR_PSEUDO)
378 return 123456; /* intentionally bogus value */
380 return s->offset;
383 static inline unsigned int arg_offset(struct storage *s)
385 if (s->type != STOR_ARG)
386 return 123456; /* intentionally bogus value */
388 /* FIXME: this is wrong wrong wrong */
389 return current_func->stack_size + ((1 + s->idx) * 4);
392 static const char *pretty_offset(int ofs)
394 static char esp_buf[64];
396 if (ofs)
397 sprintf(esp_buf, "%d(%%esp)", ofs);
398 else
399 strcpy(esp_buf, "(%esp)");
401 return esp_buf;
404 static void stor_sym_init(struct symbol *sym)
406 struct storage *stor;
407 struct symbol_private *priv;
409 priv = calloc(1, sizeof(*priv) + sizeof(*stor));
410 if (!priv)
411 die("OOM in stor_sym_init");
413 stor = (struct storage *) (priv + 1);
415 priv->addr = stor;
416 stor->type = STOR_SYM;
417 stor->sym = sym;
420 static const char *stor_op_name(struct storage *s)
422 static char name[32];
424 switch (s->type) {
425 case STOR_PSEUDO:
426 strcpy(name, pretty_offset((int) pseudo_offset(s)));
427 break;
428 case STOR_ARG:
429 strcpy(name, pretty_offset((int) arg_offset(s)));
430 break;
431 case STOR_SYM:
432 strcpy(name, show_ident(s->sym->ident));
433 break;
434 case STOR_REG:
435 strcpy(name, s->reg->name);
436 break;
437 case STOR_VALUE:
438 sprintf(name, "$%Ld", s->value);
439 break;
440 case STOR_LABEL:
441 sprintf(name, "%s.L%d", s->flags & STOR_LABEL_VAL ? "$" : "",
442 s->label);
443 break;
444 case STOR_LABELSYM:
445 sprintf(name, "%s.LS%p", s->flags & STOR_LABEL_VAL ? "$" : "",
446 s->labelsym);
447 break;
450 return name;
453 static struct atom *new_atom(enum atom_type type)
455 struct atom *atom;
457 atom = calloc(1, sizeof(*atom)); /* TODO: chunked alloc */
458 if (!atom)
459 die("nuclear OOM");
461 atom->type = type;
463 return atom;
466 static inline void push_cstring(struct function *f, struct string *str,
467 int label)
469 struct atom *atom;
471 atom = new_atom(ATOM_CSTR);
472 atom->string = str;
473 atom->label = label;
475 add_ptr_list(&f->str_list, atom); /* note: _not_ atom_list */
478 static inline void push_atom(struct function *f, struct atom *atom)
480 add_ptr_list(&f->atom_list, atom);
483 static void push_text_atom(struct function *f, const char *text)
485 struct atom *atom = new_atom(ATOM_TEXT);
487 atom->text = strdup(text);
488 atom->text_len = strlen(text);
490 push_atom(f, atom);
493 static struct storage *new_storage(enum storage_type type)
495 struct storage *stor;
497 stor = calloc(1, sizeof(*stor));
498 if (!stor)
499 die("OOM in new_storage");
501 stor->type = type;
503 return stor;
506 static struct storage *stack_alloc(int n_bytes)
508 struct function *f = current_func;
509 struct storage *stor;
511 assert(f != NULL);
513 stor = new_storage(STOR_PSEUDO);
514 stor->type = STOR_PSEUDO;
515 stor->pseudo = f->pseudo_nr;
516 stor->offset = f->stack_size; /* FIXME: stack req. natural align */
517 stor->size = n_bytes;
518 f->stack_size += n_bytes;
519 f->pseudo_nr++;
521 add_ptr_list(&f->pseudo_list, stor);
523 return stor;
526 static struct storage *new_labelsym(struct symbol *sym)
528 struct storage *stor;
530 stor = new_storage(STOR_LABELSYM);
532 if (stor) {
533 stor->flags |= STOR_WANTS_FREE;
534 stor->labelsym = sym;
537 return stor;
540 static struct storage *new_val(long long value)
542 struct storage *stor;
544 stor = new_storage(STOR_VALUE);
546 if (stor) {
547 stor->flags |= STOR_WANTS_FREE;
548 stor->value = value;
551 return stor;
554 static int new_label(void)
556 static int label = 0;
557 return ++label;
560 static void textbuf_push(struct textbuf **buf_p, const char *text)
562 struct textbuf *tmp, *list = *buf_p;
563 unsigned int text_len = strlen(text);
564 unsigned int alloc_len = text_len + 1 + sizeof(*list);
566 tmp = calloc(1, alloc_len);
567 if (!tmp)
568 die("OOM on textbuf alloc");
570 tmp->text = ((void *) tmp) + sizeof(*tmp);
571 memcpy(tmp->text, text, text_len + 1);
572 tmp->len = text_len;
574 /* add to end of list */
575 if (!list) {
576 list = tmp;
577 tmp->prev = tmp;
578 } else {
579 tmp->prev = list->prev;
580 tmp->prev->next = tmp;
581 list->prev = tmp;
583 tmp->next = list;
585 *buf_p = list;
588 static void textbuf_emit(struct textbuf **buf_p)
590 struct textbuf *tmp, *list = *buf_p;
592 while (list) {
593 tmp = list;
594 if (tmp->next == tmp)
595 list = NULL;
596 else {
597 tmp->prev->next = tmp->next;
598 tmp->next->prev = tmp->prev;
599 list = tmp->next;
602 fputs(tmp->text, stdout);
604 free(tmp);
607 *buf_p = list;
610 static void insn(const char *insn, struct storage *op1, struct storage *op2,
611 const char *comment_in)
613 struct function *f = current_func;
614 struct atom *atom = new_atom(ATOM_INSN);
616 assert(insn != NULL);
618 strcpy(atom->insn, insn);
619 if (comment_in && (*comment_in))
620 strncpy(atom->comment, comment_in,
621 sizeof(atom->comment) - 1);
623 atom->op1 = op1;
624 atom->op2 = op2;
626 push_atom(f, atom);
629 static void emit_comment(const char *fmt, ...)
631 struct function *f = current_func;
632 static char tmpbuf[100] = "\t# ";
633 va_list args;
634 int i;
636 va_start(args, fmt);
637 i = vsnprintf(tmpbuf+3, sizeof(tmpbuf)-4, fmt, args);
638 va_end(args);
639 tmpbuf[i+3] = '\n';
640 tmpbuf[i+4] = '\0';
641 push_text_atom(f, tmpbuf);
644 static void emit_label (int label, const char *comment)
646 struct function *f = current_func;
647 char s[64];
649 if (!comment)
650 sprintf(s, ".L%d:\n", label);
651 else
652 sprintf(s, ".L%d:\t\t\t\t\t# %s\n", label, comment);
654 push_text_atom(f, s);
657 static void emit_labelsym (struct symbol *sym, const char *comment)
659 struct function *f = current_func;
660 char s[64];
662 if (!comment)
663 sprintf(s, ".LS%p:\n", sym);
664 else
665 sprintf(s, ".LS%p:\t\t\t\t# %s\n", sym, comment);
667 push_text_atom(f, s);
670 void emit_unit_begin(const char *basename)
672 printf("\t.file\t\"%s\"\n", basename);
675 void emit_unit_end(void)
677 textbuf_emit(&unit_post_text);
678 printf("\t.ident\t\"sparse silly x86 backend (built %s)\"\n", __DATE__);
681 /* conditionally switch sections */
682 static void emit_section(const char *s)
684 if (s == current_section)
685 return;
686 if (current_section && (!strcmp(s, current_section)))
687 return;
689 printf("\t%s\n", s);
690 current_section = s;
693 static void emit_insn_atom(struct function *f, struct atom *atom)
695 char s[128];
696 char comment[64];
697 struct storage *op1 = atom->op1;
698 struct storage *op2 = atom->op2;
700 if (atom->comment[0])
701 sprintf(comment, "\t\t# %s", atom->comment);
702 else
703 comment[0] = 0;
705 if (atom->op2) {
706 char tmp[16];
707 strcpy(tmp, stor_op_name(op1));
708 sprintf(s, "\t%s\t%s, %s%s\n",
709 atom->insn, tmp, stor_op_name(op2), comment);
710 } else if (atom->op1)
711 sprintf(s, "\t%s\t%s%s%s\n",
712 atom->insn, stor_op_name(op1),
713 comment[0] ? "\t" : "", comment);
714 else
715 sprintf(s, "\t%s\t%s%s\n",
716 atom->insn,
717 comment[0] ? "\t\t" : "", comment);
719 write(STDOUT_FILENO, s, strlen(s));
722 static void emit_atom_list(struct function *f)
724 struct atom *atom;
726 FOR_EACH_PTR(f->atom_list, atom) {
727 switch (atom->type) {
728 case ATOM_TEXT: {
729 ssize_t rc = write(STDOUT_FILENO, atom->text,
730 atom->text_len);
731 (void) rc; /* FIXME */
732 break;
734 case ATOM_INSN:
735 emit_insn_atom(f, atom);
736 break;
737 case ATOM_CSTR:
738 assert(0);
739 break;
741 } END_FOR_EACH_PTR(atom);
744 static void emit_string_list(struct function *f)
746 struct atom *atom;
748 emit_section(".section\t.rodata");
750 FOR_EACH_PTR(f->str_list, atom) {
751 /* FIXME: escape " in string */
752 printf(".L%d:\n", atom->label);
753 printf("\t.string\t%s\n", show_string(atom->string));
755 free(atom);
756 } END_FOR_EACH_PTR(atom);
759 static void func_cleanup(struct function *f)
761 struct storage *stor;
762 struct atom *atom;
764 FOR_EACH_PTR(f->pseudo_list, stor) {
765 free(stor);
766 } END_FOR_EACH_PTR(stor);
768 FOR_EACH_PTR(f->atom_list, atom) {
769 if ((atom->type == ATOM_TEXT) && (atom->text))
770 free(atom->text);
771 if (atom->op1 && (atom->op1->flags & STOR_WANTS_FREE))
772 free(atom->op1);
773 if (atom->op2 && (atom->op2->flags & STOR_WANTS_FREE))
774 free(atom->op2);
775 free(atom);
776 } END_FOR_EACH_PTR(atom);
778 free_ptr_list(&f->pseudo_list);
779 free(f);
782 /* function prologue */
783 static void emit_func_pre(struct symbol *sym)
785 struct function *f;
786 struct symbol *arg;
787 unsigned int i, argc = 0, alloc_len;
788 unsigned char *mem;
789 struct symbol_private *privbase;
790 struct storage *storage_base;
791 struct symbol *base_type = sym->ctype.base_type;
793 FOR_EACH_PTR(base_type->arguments, arg) {
794 argc++;
795 } END_FOR_EACH_PTR(arg);
797 alloc_len =
798 sizeof(*f) +
799 (argc * sizeof(struct symbol *)) +
800 (argc * sizeof(struct symbol_private)) +
801 (argc * sizeof(struct storage));
802 mem = calloc(1, alloc_len);
803 if (!mem)
804 die("OOM on func info");
806 f = (struct function *) mem;
807 mem += sizeof(*f);
808 f->argv = (struct symbol **) mem;
809 mem += (argc * sizeof(struct symbol *));
810 privbase = (struct symbol_private *) mem;
811 mem += (argc * sizeof(struct symbol_private));
812 storage_base = (struct storage *) mem;
814 f->argc = argc;
815 f->ret_target = new_label();
817 i = 0;
818 FOR_EACH_PTR(base_type->arguments, arg) {
819 f->argv[i] = arg;
820 arg->aux = &privbase[i];
821 storage_base[i].type = STOR_ARG;
822 storage_base[i].idx = i;
823 privbase[i].addr = &storage_base[i];
824 i++;
825 } END_FOR_EACH_PTR(arg);
827 assert(current_func == NULL);
828 current_func = f;
831 /* function epilogue */
832 static void emit_func_post(struct symbol *sym)
834 const char *name = show_ident(sym->ident);
835 struct function *f = current_func;
836 int stack_size = f->stack_size;
838 if (f->str_list)
839 emit_string_list(f);
841 /* function prologue */
842 emit_section(".text");
843 if ((sym->ctype.modifiers & MOD_STATIC) == 0)
844 printf(".globl %s\n", name);
845 printf("\t.type\t%s, @function\n", name);
846 printf("%s:\n", name);
848 if (stack_size) {
849 char pseudo_const[16];
851 sprintf(pseudo_const, "$%d", stack_size);
852 printf("\tsubl\t%s, %%esp\n", pseudo_const);
855 /* function epilogue */
857 /* jump target for 'return' statements */
858 emit_label(f->ret_target, NULL);
860 if (stack_size) {
861 struct storage *val;
863 val = new_storage(STOR_VALUE);
864 val->value = (long long) (stack_size);
865 val->flags = STOR_WANTS_FREE;
867 insn("addl", val, REG_ESP, NULL);
870 insn("ret", NULL, NULL, NULL);
872 /* output everything to stdout */
873 fflush(stdout); /* paranoia; needed? */
874 emit_atom_list(f);
876 /* function footer */
877 name = show_ident(sym->ident);
878 printf("\t.size\t%s, .-%s\n", name, name);
880 func_cleanup(f);
881 current_func = NULL;
884 /* emit object (a.k.a. variable, a.k.a. data) prologue */
885 static void emit_object_pre(const char *name, unsigned long modifiers,
886 unsigned long alignment, unsigned int byte_size)
888 if ((modifiers & MOD_STATIC) == 0)
889 printf(".globl %s\n", name);
890 emit_section(".data");
891 if (alignment)
892 printf("\t.align %lu\n", alignment);
893 printf("\t.type\t%s, @object\n", name);
894 printf("\t.size\t%s, %d\n", name, byte_size);
895 printf("%s:\n", name);
898 /* emit value (only) for an initializer scalar */
899 static void emit_scalar(struct expression *expr, unsigned int bit_size)
901 const char *type;
902 long long ll;
904 assert(expr->type == EXPR_VALUE);
906 if (expr->value == 0ULL) {
907 printf("\t.zero\t%d\n", bit_size / 8);
908 return;
911 ll = (long long) expr->value;
913 switch (bit_size) {
914 case 8: type = "byte"; ll = (char) ll; break;
915 case 16: type = "value"; ll = (short) ll; break;
916 case 32: type = "long"; ll = (int) ll; break;
917 case 64: type = "quad"; break;
918 default: type = NULL; break;
921 assert(type != NULL);
923 printf("\t.%s\t%Ld\n", type, ll);
926 static void emit_global_noinit(const char *name, unsigned long modifiers,
927 unsigned long alignment, unsigned int byte_size)
929 char s[64];
931 if (modifiers & MOD_STATIC) {
932 sprintf(s, "\t.local\t%s\n", name);
933 textbuf_push(&unit_post_text, s);
935 if (alignment)
936 sprintf(s, "\t.comm\t%s,%d,%lu\n", name, byte_size, alignment);
937 else
938 sprintf(s, "\t.comm\t%s,%d\n", name, byte_size);
939 textbuf_push(&unit_post_text, s);
942 static int ea_current, ea_last;
944 static void emit_initializer(struct symbol *sym,
945 struct expression *expr)
947 int distance = ea_current - ea_last - 1;
949 if (distance > 0)
950 printf("\t.zero\t%d\n", (sym->bit_size / 8) * distance);
952 if (expr->type == EXPR_VALUE) {
953 struct symbol *base_type = sym->ctype.base_type;
954 assert(base_type != NULL);
956 emit_scalar(expr, sym->bit_size / get_expression_value(base_type->array_size));
957 return;
959 if (expr->type != EXPR_INITIALIZER)
960 return;
962 assert(0); /* FIXME */
965 static int sort_array_cmp(const struct expression *a,
966 const struct expression *b)
968 int a_ofs = 0, b_ofs = 0;
970 if (a->type == EXPR_POS)
971 a_ofs = (int) a->init_offset;
972 if (b->type == EXPR_POS)
973 b_ofs = (int) b->init_offset;
975 return a_ofs - b_ofs;
978 /* move to front-end? */
979 static void sort_array(struct expression *expr)
981 struct expression *entry, **list;
982 unsigned int elem, sorted, i;
984 elem = 0;
985 FOR_EACH_PTR(expr->expr_list, entry) {
986 elem++;
987 } END_FOR_EACH_PTR(entry);
989 if (!elem)
990 return;
992 list = malloc(sizeof(entry) * elem);
993 if (!list)
994 die("OOM in sort_array");
996 /* this code is no doubt evil and ignores EXPR_INDEX possibly
997 * to its detriment and other nasty things. improvements
998 * welcome.
1000 i = 0;
1001 sorted = 0;
1002 FOR_EACH_PTR(expr->expr_list, entry) {
1003 if ((entry->type == EXPR_POS) || (entry->type == EXPR_VALUE)) {
1004 /* add entry to list[], in sorted order */
1005 if (sorted == 0) {
1006 list[0] = entry;
1007 sorted = 1;
1008 } else {
1009 for (i = 0; i < sorted; i++)
1010 if (sort_array_cmp(entry, list[i]) <= 0)
1011 break;
1013 /* If inserting into the middle of list[]
1014 * instead of appending, we memmove.
1015 * This is ugly, but thankfully
1016 * uncommon. Input data with tons of
1017 * entries very rarely have explicit
1018 * offsets. convert to qsort eventually...
1020 if (i != sorted)
1021 memmove(&list[i + 1], &list[i],
1022 (sorted - i) * sizeof(entry));
1023 list[i] = entry;
1024 sorted++;
1027 } END_FOR_EACH_PTR(entry);
1029 i = 0;
1030 FOR_EACH_PTR(expr->expr_list, entry) {
1031 if ((entry->type == EXPR_POS) || (entry->type == EXPR_VALUE))
1032 *THIS_ADDRESS(entry) = list[i++];
1033 } END_FOR_EACH_PTR(entry);
1037 static void emit_array(struct symbol *sym)
1039 struct symbol *base_type = sym->ctype.base_type;
1040 struct expression *expr = sym->initializer;
1041 struct expression *entry;
1043 assert(base_type != NULL);
1045 stor_sym_init(sym);
1047 ea_last = -1;
1049 emit_object_pre(show_ident(sym->ident), sym->ctype.modifiers,
1050 sym->ctype.alignment,
1051 sym->bit_size / 8);
1053 sort_array(expr);
1055 FOR_EACH_PTR(expr->expr_list, entry) {
1056 if (entry->type == EXPR_VALUE) {
1057 ea_current = 0;
1058 emit_initializer(sym, entry);
1059 ea_last = ea_current;
1060 } else if (entry->type == EXPR_POS) {
1061 ea_current =
1062 entry->init_offset / (base_type->bit_size / 8);
1063 emit_initializer(sym, entry->init_expr);
1064 ea_last = ea_current;
1066 } END_FOR_EACH_PTR(entry);
1069 void emit_one_symbol(struct symbol *sym)
1071 x86_symbol(sym);
1074 static void emit_copy(struct storage *dest, struct storage *src,
1075 struct symbol *ctype)
1077 struct storage *reg = NULL;
1078 unsigned int bit_size;
1080 /* FIXME: Bitfield copy! */
1082 bit_size = src->size * 8;
1083 if (!bit_size)
1084 bit_size = 32;
1085 if ((src->type == STOR_ARG) && (bit_size < 32))
1086 bit_size = 32;
1088 reg = temp_from_bits(bit_size);
1089 emit_move(src, reg, ctype, "begin copy ..");
1091 bit_size = dest->size * 8;
1092 if (!bit_size)
1093 bit_size = 32;
1094 if ((dest->type == STOR_ARG) && (bit_size < 32))
1095 bit_size = 32;
1097 emit_move(reg, dest, ctype, ".... end copy");
1098 put_reg(reg);
1101 static void emit_store(struct expression *dest_expr, struct storage *dest,
1102 struct storage *src, int bits)
1104 /* FIXME: Bitfield store! */
1105 printf("\tst.%d\t\tv%d,[v%d]\n", bits, src->pseudo, dest->pseudo);
1108 static void emit_scalar_noinit(struct symbol *sym)
1110 emit_global_noinit(show_ident(sym->ident),
1111 sym->ctype.modifiers, sym->ctype.alignment,
1112 sym->bit_size / 8);
1113 stor_sym_init(sym);
1116 static void emit_array_noinit(struct symbol *sym)
1118 emit_global_noinit(show_ident(sym->ident),
1119 sym->ctype.modifiers, sym->ctype.alignment,
1120 get_expression_value(sym->array_size) * (sym->bit_size / 8));
1121 stor_sym_init(sym);
1124 static const char *opbits(const char *insn, unsigned int bits)
1126 static char opbits_str[32];
1127 char c;
1129 switch (bits) {
1130 case 8: c = 'b'; break;
1131 case 16: c = 'w'; break;
1132 case 32: c = 'l'; break;
1133 case 64: c = 'q'; break;
1134 default: abort(); break;
1137 sprintf(opbits_str, "%s%c", insn, c);
1139 return opbits_str;
1142 static void emit_move(struct storage *src, struct storage *dest,
1143 struct symbol *ctype, const char *comment)
1145 unsigned int bits;
1146 unsigned int is_signed;
1147 unsigned int is_dest = (src->type == STOR_REG);
1148 const char *opname;
1150 if (ctype) {
1151 bits = ctype->bit_size;
1152 is_signed = type_is_signed(ctype);
1153 } else {
1154 bits = 32;
1155 is_signed = 0;
1159 * Are we moving from a register to a register?
1160 * Make the new reg to be the "cache".
1162 if ((dest->type == STOR_REG) && (src->type == STOR_REG)) {
1163 struct storage *backing;
1165 reg_reg_move:
1166 if (dest == src)
1167 return;
1169 backing = src->reg->contains;
1170 if (backing) {
1171 /* Is it still valid? */
1172 if (backing->reg != src->reg)
1173 backing = NULL;
1174 else
1175 backing->reg = dest->reg;
1177 dest->reg->contains = backing;
1178 insn("mov", src, dest, NULL);
1179 return;
1183 * Are we moving to a register from a non-reg?
1185 * See if we have the non-reg source already cached
1186 * in a register..
1188 if (dest->type == STOR_REG) {
1189 if (src->reg) {
1190 struct reg_info *info = src->reg;
1191 if (info->contains == src) {
1192 src = reginfo_reg(info);
1193 goto reg_reg_move;
1196 dest->reg->contains = src;
1197 src->reg = dest->reg;
1200 if (src->type == STOR_REG) {
1201 /* We could just mark the register dirty here and do lazy store.. */
1202 src->reg->contains = dest;
1203 dest->reg = src->reg;
1206 if ((bits == 8) || (bits == 16)) {
1207 if (is_dest)
1208 opname = "mov";
1209 else
1210 opname = is_signed ? "movsx" : "movzx";
1211 } else
1212 opname = "mov";
1214 insn(opbits(opname, bits), src, dest, comment);
1217 static struct storage *emit_compare(struct expression *expr)
1219 struct storage *left = x86_expression(expr->left);
1220 struct storage *right = x86_expression(expr->right);
1221 struct storage *reg1, *reg2;
1222 struct storage *new, *val;
1223 const char *opname = NULL;
1224 unsigned int right_bits = expr->right->ctype->bit_size;
1226 switch(expr->op) {
1227 case '<': opname = "setl"; break;
1228 case '>': opname = "setg"; break;
1229 case SPECIAL_LTE:
1230 opname = "setle"; break;
1231 case SPECIAL_GTE:
1232 opname = "setge"; break;
1233 case SPECIAL_EQUAL: opname = "sete"; break;
1234 case SPECIAL_NOTEQUAL: opname = "setne"; break;
1235 case SPECIAL_UNSIGNED_LT:
1236 opname = "setb"; break;
1237 case SPECIAL_UNSIGNED_GT:
1238 opname = "seta"; break;
1239 case SPECIAL_UNSIGNED_LTE:
1240 opname = "setb"; break;
1241 case SPECIAL_UNSIGNED_GTE:
1242 opname = "setae"; break;
1243 default:
1244 assert(0);
1245 break;
1248 /* init EDX to 0 */
1249 val = new_storage(STOR_VALUE);
1250 val->flags = STOR_WANTS_FREE;
1252 reg1 = get_reg(&regclass_32_8);
1253 emit_move(val, reg1, NULL, NULL);
1255 /* move op1 into EAX */
1256 reg2 = get_reg_value(left, get_regclass(expr->left));
1258 /* perform comparison, RHS (op1, right) and LHS (op2, EAX) */
1259 insn(opbits("cmp", right_bits), right, reg2, NULL);
1260 put_reg(reg2);
1262 /* store result of operation, 0 or 1, in DL using SETcc */
1263 insn(opname, byte_reg(reg1), NULL, NULL);
1265 /* finally, store the result (DL) in a new pseudo / stack slot */
1266 new = stack_alloc(4);
1267 emit_move(reg1, new, NULL, "end EXPR_COMPARE");
1268 put_reg(reg1);
1270 return new;
1273 static struct storage *emit_value(struct expression *expr)
1275 #if 0 /* old and slow way */
1276 struct storage *new = stack_alloc(4);
1277 struct storage *val;
1279 val = new_storage(STOR_VALUE);
1280 val->value = (long long) expr->value;
1281 val->flags = STOR_WANTS_FREE;
1282 insn("movl", val, new, NULL);
1284 return new;
1285 #else
1286 struct storage *val;
1288 val = new_storage(STOR_VALUE);
1289 val->value = (long long) expr->value;
1291 return val; /* FIXME: memory leak */
1292 #endif
1295 static struct storage *emit_divide(struct expression *expr, struct storage *left, struct storage *right)
1297 struct storage *eax_edx;
1298 struct storage *reg, *new;
1299 struct storage *val = new_storage(STOR_VALUE);
1301 emit_comment("begin DIVIDE");
1302 eax_edx = get_hardreg(hardreg_storage_table + EAX_EDX, 1);
1304 /* init EDX to 0 */
1305 val->flags = STOR_WANTS_FREE;
1306 emit_move(val, REG_EDX, NULL, NULL);
1308 new = stack_alloc(expr->ctype->bit_size / 8);
1310 /* EAX is dividend */
1311 emit_move(left, REG_EAX, NULL, NULL);
1313 reg = get_reg_value(right, &regclass_32);
1315 /* perform binop */
1316 insn("div", reg, REG_EAX, NULL);
1317 put_reg(reg);
1319 reg = REG_EAX;
1320 if (expr->op == '%')
1321 reg = REG_EDX;
1322 emit_move(reg, new, NULL, NULL);
1324 put_reg(eax_edx);
1325 emit_comment("end DIVIDE");
1326 return new;
1329 static struct storage *emit_binop(struct expression *expr)
1331 struct storage *left = x86_expression(expr->left);
1332 struct storage *right = x86_expression(expr->right);
1333 struct storage *new;
1334 struct storage *dest, *src;
1335 const char *opname = NULL;
1336 const char *suffix = NULL;
1337 char opstr[16];
1338 int is_signed;
1340 /* Divides have special register constraints */
1341 if ((expr->op == '/') || (expr->op == '%'))
1342 return emit_divide(expr, left, right);
1344 is_signed = type_is_signed(expr->ctype);
1346 switch (expr->op) {
1347 case '+':
1348 opname = "add";
1349 break;
1350 case '-':
1351 opname = "sub";
1352 break;
1353 case '&':
1354 opname = "and";
1355 break;
1356 case '|':
1357 opname = "or";
1358 break;
1359 case '^':
1360 opname = "xor";
1361 break;
1362 case SPECIAL_LEFTSHIFT:
1363 opname = "shl";
1364 break;
1365 case SPECIAL_RIGHTSHIFT:
1366 if (is_signed)
1367 opname = "sar";
1368 else
1369 opname = "shr";
1370 break;
1371 case '*':
1372 if (is_signed)
1373 opname = "imul";
1374 else
1375 opname = "mul";
1376 break;
1377 case SPECIAL_LOGICAL_AND:
1378 warning(expr->pos, "bogus bitwise and for logical op (should use '2*setne + and' or something)");
1379 opname = "and";
1380 break;
1381 case SPECIAL_LOGICAL_OR:
1382 warning(expr->pos, "bogus bitwise or for logical op (should use 'or + setne' or something)");
1383 opname = "or";
1384 break;
1385 default:
1386 error_die(expr->pos, "unhandled binop '%s'\n", show_special(expr->op));
1387 break;
1390 dest = get_reg_value(right, &regclass_32);
1391 src = get_reg_value(left, &regclass_32);
1392 switch (expr->ctype->bit_size) {
1393 case 8:
1394 suffix = "b";
1395 break;
1396 case 16:
1397 suffix = "w";
1398 break;
1399 case 32:
1400 suffix = "l";
1401 break;
1402 case 64:
1403 suffix = "q"; /* FIXME */
1404 break;
1405 default:
1406 assert(0);
1407 break;
1410 snprintf(opstr, sizeof(opstr), "%s%s", opname, suffix);
1412 /* perform binop */
1413 insn(opstr, src, dest, NULL);
1414 put_reg(src);
1416 /* store result in new pseudo / stack slot */
1417 new = stack_alloc(expr->ctype->bit_size / 8);
1418 emit_move(dest, new, NULL, "end EXPR_BINOP");
1420 put_reg(dest);
1422 return new;
1425 static int emit_conditional_test(struct storage *val)
1427 struct storage *reg;
1428 struct storage *target_val;
1429 int target_false;
1431 /* load result into EAX */
1432 emit_comment("begin if/conditional");
1433 reg = get_reg_value(val, &regclass_32);
1435 /* compare result with zero */
1436 insn("test", reg, reg, NULL);
1437 put_reg(reg);
1439 /* create conditional-failed label to jump to */
1440 target_false = new_label();
1441 target_val = new_storage(STOR_LABEL);
1442 target_val->label = target_false;
1443 target_val->flags = STOR_WANTS_FREE;
1444 insn("jz", target_val, NULL, NULL);
1446 return target_false;
1449 static int emit_conditional_end(int target_false)
1451 struct storage *cond_end_st;
1452 int cond_end;
1454 /* finished generating code for if-true statement.
1455 * add a jump-to-end jump to avoid falling through
1456 * to the if-false statement code.
1458 cond_end = new_label();
1459 cond_end_st = new_storage(STOR_LABEL);
1460 cond_end_st->label = cond_end;
1461 cond_end_st->flags = STOR_WANTS_FREE;
1462 insn("jmp", cond_end_st, NULL, NULL);
1464 /* if we have both if-true and if-false statements,
1465 * the failed-conditional case will fall through to here
1467 emit_label(target_false, NULL);
1469 return cond_end;
1472 static void emit_if_conditional(struct statement *stmt)
1474 struct storage *val;
1475 int cond_end;
1477 /* emit test portion of conditional */
1478 val = x86_expression(stmt->if_conditional);
1479 cond_end = emit_conditional_test(val);
1481 /* emit if-true statement */
1482 x86_statement(stmt->if_true);
1484 /* emit if-false statement, if present */
1485 if (stmt->if_false) {
1486 cond_end = emit_conditional_end(cond_end);
1487 x86_statement(stmt->if_false);
1490 /* end of conditional; jump target for if-true branch */
1491 emit_label(cond_end, "end if");
1494 static struct storage *emit_inc_dec(struct expression *expr, int postop)
1496 struct storage *addr = x86_address_gen(expr->unop);
1497 struct storage *retval;
1498 char opname[16];
1500 strcpy(opname, opbits(expr->op == SPECIAL_INCREMENT ? "inc" : "dec",
1501 expr->ctype->bit_size));
1503 if (postop) {
1504 struct storage *new = stack_alloc(4);
1506 emit_copy(new, addr, expr->unop->ctype);
1508 retval = new;
1509 } else
1510 retval = addr;
1512 insn(opname, addr, NULL, NULL);
1514 return retval;
1517 static struct storage *emit_postop(struct expression *expr)
1519 return emit_inc_dec(expr, 1);
1522 static struct storage *emit_return_stmt(struct statement *stmt)
1524 struct function *f = current_func;
1525 struct expression *expr = stmt->ret_value;
1526 struct storage *val = NULL, *jmplbl;
1528 if (expr && expr->ctype) {
1529 val = x86_expression(expr);
1530 assert(val != NULL);
1531 emit_move(val, REG_EAX, expr->ctype, "return");
1534 jmplbl = new_storage(STOR_LABEL);
1535 jmplbl->flags |= STOR_WANTS_FREE;
1536 jmplbl->label = f->ret_target;
1537 insn("jmp", jmplbl, NULL, NULL);
1539 return val;
1542 static struct storage *emit_conditional_expr(struct expression *expr)
1544 struct storage *cond, *true = NULL, *false = NULL;
1545 struct storage *new = stack_alloc(expr->ctype->bit_size / 8);
1546 int target_false, cond_end;
1548 /* evaluate conditional */
1549 cond = x86_expression(expr->conditional);
1550 target_false = emit_conditional_test(cond);
1552 /* handle if-true part of the expression */
1553 true = x86_expression(expr->cond_true);
1555 emit_copy(new, true, expr->ctype);
1557 cond_end = emit_conditional_end(target_false);
1559 /* handle if-false part of the expression */
1560 false = x86_expression(expr->cond_false);
1562 emit_copy(new, false, expr->ctype);
1564 /* end of conditional; jump target for if-true branch */
1565 emit_label(cond_end, "end conditional");
1567 return new;
1570 static struct storage *emit_select_expr(struct expression *expr)
1572 struct storage *cond = x86_expression(expr->conditional);
1573 struct storage *true = x86_expression(expr->cond_true);
1574 struct storage *false = x86_expression(expr->cond_false);
1575 struct storage *reg_cond, *reg_true, *reg_false;
1576 struct storage *new = stack_alloc(4);
1578 emit_comment("begin SELECT");
1579 reg_cond = get_reg_value(cond, get_regclass(expr->conditional));
1580 reg_true = get_reg_value(true, get_regclass(expr));
1581 reg_false = get_reg_value(false, get_regclass(expr));
1584 * Do the actual select: check the conditional for zero,
1585 * move false over true if zero
1587 insn("test", reg_cond, reg_cond, NULL);
1588 insn("cmovz", reg_false, reg_true, NULL);
1590 /* Store it back */
1591 emit_move(reg_true, new, expr->ctype, NULL);
1592 put_reg(reg_cond);
1593 put_reg(reg_true);
1594 put_reg(reg_false);
1595 emit_comment("end SELECT");
1596 return new;
1599 static struct storage *emit_symbol_expr_init(struct symbol *sym)
1601 struct expression *expr = sym->initializer;
1602 struct symbol_private *priv = sym->aux;
1604 if (priv == NULL) {
1605 priv = calloc(1, sizeof(*priv));
1606 sym->aux = priv;
1608 if (expr == NULL) {
1609 struct storage *new = stack_alloc(4);
1610 fprintf(stderr, "FIXME! no value for symbol %s. creating pseudo %d (stack offset %d)\n",
1611 show_ident(sym->ident),
1612 new->pseudo, new->pseudo * 4);
1613 priv->addr = new;
1614 } else {
1615 priv->addr = x86_expression(expr);
1619 return priv->addr;
1622 static struct storage *emit_string_expr(struct expression *expr)
1624 struct function *f = current_func;
1625 int label = new_label();
1626 struct storage *new;
1628 push_cstring(f, expr->string, label);
1630 new = new_storage(STOR_LABEL);
1631 new->label = label;
1632 new->flags = STOR_LABEL_VAL | STOR_WANTS_FREE;
1633 return new;
1636 static struct storage *emit_cast_expr(struct expression *expr)
1638 struct symbol *old_type, *new_type;
1639 struct storage *op = x86_expression(expr->cast_expression);
1640 int oldbits, newbits;
1641 struct storage *new;
1643 old_type = expr->cast_expression->ctype;
1644 new_type = expr->cast_type;
1646 oldbits = old_type->bit_size;
1647 newbits = new_type->bit_size;
1648 if (oldbits >= newbits)
1649 return op;
1651 emit_move(op, REG_EAX, old_type, "begin cast ..");
1653 new = stack_alloc(newbits / 8);
1654 emit_move(REG_EAX, new, new_type, ".... end cast");
1656 return new;
1659 static struct storage *emit_regular_preop(struct expression *expr)
1661 struct storage *target = x86_expression(expr->unop);
1662 struct storage *val, *new = stack_alloc(4);
1663 const char *opname = NULL;
1665 switch (expr->op) {
1666 case '!':
1667 val = new_storage(STOR_VALUE);
1668 val->flags = STOR_WANTS_FREE;
1669 emit_move(val, REG_EDX, NULL, NULL);
1670 emit_move(target, REG_EAX, expr->unop->ctype, NULL);
1671 insn("test", REG_EAX, REG_EAX, NULL);
1672 insn("setz", REG_DL, NULL, NULL);
1673 emit_move(REG_EDX, new, expr->unop->ctype, NULL);
1675 break;
1676 case '~':
1677 opname = "not";
1678 case '-':
1679 if (!opname)
1680 opname = "neg";
1681 emit_move(target, REG_EAX, expr->unop->ctype, NULL);
1682 insn(opname, REG_EAX, NULL, NULL);
1683 emit_move(REG_EAX, new, expr->unop->ctype, NULL);
1684 break;
1685 default:
1686 assert(0);
1687 break;
1690 return new;
1693 static void emit_case_statement(struct statement *stmt)
1695 emit_labelsym(stmt->case_label, NULL);
1696 x86_statement(stmt->case_statement);
1699 static void emit_switch_statement(struct statement *stmt)
1701 struct storage *val = x86_expression(stmt->switch_expression);
1702 struct symbol *sym, *default_sym = NULL;
1703 struct storage *labelsym, *label;
1704 int switch_end = 0;
1706 emit_move(val, REG_EAX, stmt->switch_expression->ctype, "begin case");
1709 * This is where a _real_ back-end would go through the
1710 * cases to decide whether to use a lookup table or a
1711 * series of comparisons etc
1713 FOR_EACH_PTR(stmt->switch_case->symbol_list, sym) {
1714 struct statement *case_stmt = sym->stmt;
1715 struct expression *expr = case_stmt->case_expression;
1716 struct expression *to = case_stmt->case_to;
1718 /* default: */
1719 if (!expr)
1720 default_sym = sym;
1722 /* case NNN: */
1723 else {
1724 struct storage *case_val = new_val(expr->value);
1726 assert (expr->type == EXPR_VALUE);
1728 insn("cmpl", case_val, REG_EAX, NULL);
1730 if (!to) {
1731 labelsym = new_labelsym(sym);
1732 insn("je", labelsym, NULL, NULL);
1733 } else {
1734 int next_test;
1736 label = new_storage(STOR_LABEL);
1737 label->flags |= STOR_WANTS_FREE;
1738 label->label = next_test = new_label();
1740 /* FIXME: signed/unsigned */
1741 insn("jl", label, NULL, NULL);
1743 case_val = new_val(to->value);
1744 insn("cmpl", case_val, REG_EAX, NULL);
1746 /* TODO: implement and use refcounting... */
1747 label = new_storage(STOR_LABEL);
1748 label->flags |= STOR_WANTS_FREE;
1749 label->label = next_test;
1751 /* FIXME: signed/unsigned */
1752 insn("jg", label, NULL, NULL);
1754 labelsym = new_labelsym(sym);
1755 insn("jmp", labelsym, NULL, NULL);
1757 emit_label(next_test, NULL);
1760 } END_FOR_EACH_PTR(sym);
1762 if (default_sym) {
1763 labelsym = new_labelsym(default_sym);
1764 insn("jmp", labelsym, NULL, "default");
1765 } else {
1766 label = new_storage(STOR_LABEL);
1767 label->flags |= STOR_WANTS_FREE;
1768 label->label = switch_end = new_label();
1769 insn("jmp", label, NULL, "goto end of switch");
1772 x86_statement(stmt->switch_statement);
1774 if (stmt->switch_break->used)
1775 emit_labelsym(stmt->switch_break, NULL);
1777 if (switch_end)
1778 emit_label(switch_end, NULL);
1781 static void x86_struct_member(struct symbol *sym)
1783 printf("\t%s:%d:%ld at offset %ld.%d", show_ident(sym->ident), sym->bit_size, sym->ctype.alignment, sym->offset, sym->bit_offset);
1784 printf("\n");
1787 static void x86_symbol(struct symbol *sym)
1789 struct symbol *type;
1791 if (!sym)
1792 return;
1794 type = sym->ctype.base_type;
1795 if (!type)
1796 return;
1799 * Show actual implementation information
1801 switch (type->type) {
1803 case SYM_ARRAY:
1804 if (sym->initializer)
1805 emit_array(sym);
1806 else
1807 emit_array_noinit(sym);
1808 break;
1810 case SYM_BASETYPE:
1811 if (sym->initializer) {
1812 emit_object_pre(show_ident(sym->ident),
1813 sym->ctype.modifiers,
1814 sym->ctype.alignment,
1815 sym->bit_size / 8);
1816 emit_scalar(sym->initializer, sym->bit_size);
1817 stor_sym_init(sym);
1818 } else
1819 emit_scalar_noinit(sym);
1820 break;
1822 case SYM_STRUCT:
1823 case SYM_UNION: {
1824 struct symbol *member;
1826 printf(" {\n");
1827 FOR_EACH_PTR(type->symbol_list, member) {
1828 x86_struct_member(member);
1829 } END_FOR_EACH_PTR(member);
1830 printf("}\n");
1831 break;
1834 case SYM_FN: {
1835 struct statement *stmt = type->stmt;
1836 if (stmt) {
1837 emit_func_pre(sym);
1838 x86_statement(stmt);
1839 emit_func_post(sym);
1841 break;
1844 default:
1845 break;
1848 if (sym->initializer && (type->type != SYM_BASETYPE) &&
1849 (type->type != SYM_ARRAY)) {
1850 printf(" = \n");
1851 x86_expression(sym->initializer);
1855 static void x86_symbol_init(struct symbol *sym);
1857 static void x86_symbol_decl(struct symbol_list *syms)
1859 struct symbol *sym;
1860 FOR_EACH_PTR(syms, sym) {
1861 x86_symbol_init(sym);
1862 } END_FOR_EACH_PTR(sym);
1865 static void loopstk_push(int cont_lbl, int loop_bottom_lbl)
1867 struct function *f = current_func;
1868 struct loop_stack *ls;
1870 ls = malloc(sizeof(*ls));
1871 ls->continue_lbl = cont_lbl;
1872 ls->loop_bottom_lbl = loop_bottom_lbl;
1873 ls->next = f->loop_stack;
1874 f->loop_stack = ls;
1877 static void loopstk_pop(void)
1879 struct function *f = current_func;
1880 struct loop_stack *ls;
1882 assert(f->loop_stack != NULL);
1883 ls = f->loop_stack;
1884 f->loop_stack = f->loop_stack->next;
1885 free(ls);
1888 static int loopstk_break(void)
1890 return current_func->loop_stack->loop_bottom_lbl;
1893 static int loopstk_continue(void)
1895 return current_func->loop_stack->continue_lbl;
1898 static void emit_loop(struct statement *stmt)
1900 struct statement *pre_statement = stmt->iterator_pre_statement;
1901 struct expression *pre_condition = stmt->iterator_pre_condition;
1902 struct statement *statement = stmt->iterator_statement;
1903 struct statement *post_statement = stmt->iterator_post_statement;
1904 struct expression *post_condition = stmt->iterator_post_condition;
1905 int loop_top = 0, loop_bottom, loop_continue;
1906 int have_bottom = 0;
1907 struct storage *val;
1909 loop_bottom = new_label();
1910 loop_continue = new_label();
1911 loopstk_push(loop_continue, loop_bottom);
1913 x86_symbol_decl(stmt->iterator_syms);
1914 x86_statement(pre_statement);
1915 if (!post_condition || post_condition->type != EXPR_VALUE || post_condition->value) {
1916 loop_top = new_label();
1917 emit_label(loop_top, "loop top");
1919 if (pre_condition) {
1920 if (pre_condition->type == EXPR_VALUE) {
1921 if (!pre_condition->value) {
1922 struct storage *lbv;
1923 lbv = new_storage(STOR_LABEL);
1924 lbv->label = loop_bottom;
1925 lbv->flags = STOR_WANTS_FREE;
1926 insn("jmp", lbv, NULL, "go to loop bottom");
1927 have_bottom = 1;
1929 } else {
1930 struct storage *lbv = new_storage(STOR_LABEL);
1931 lbv->label = loop_bottom;
1932 lbv->flags = STOR_WANTS_FREE;
1933 have_bottom = 1;
1935 val = x86_expression(pre_condition);
1937 emit_move(val, REG_EAX, NULL, "loop pre condition");
1938 insn("test", REG_EAX, REG_EAX, NULL);
1939 insn("jz", lbv, NULL, NULL);
1942 x86_statement(statement);
1943 if (stmt->iterator_continue->used)
1944 emit_label(loop_continue, "'continue' iterator");
1945 x86_statement(post_statement);
1946 if (!post_condition) {
1947 struct storage *lbv = new_storage(STOR_LABEL);
1948 lbv->label = loop_top;
1949 lbv->flags = STOR_WANTS_FREE;
1950 insn("jmp", lbv, NULL, "go to loop top");
1951 } else if (post_condition->type == EXPR_VALUE) {
1952 if (post_condition->value) {
1953 struct storage *lbv = new_storage(STOR_LABEL);
1954 lbv->label = loop_top;
1955 lbv->flags = STOR_WANTS_FREE;
1956 insn("jmp", lbv, NULL, "go to loop top");
1958 } else {
1959 struct storage *lbv = new_storage(STOR_LABEL);
1960 lbv->label = loop_top;
1961 lbv->flags = STOR_WANTS_FREE;
1963 val = x86_expression(post_condition);
1965 emit_move(val, REG_EAX, NULL, "loop post condition");
1966 insn("test", REG_EAX, REG_EAX, NULL);
1967 insn("jnz", lbv, NULL, NULL);
1969 if (have_bottom || stmt->iterator_break->used)
1970 emit_label(loop_bottom, "loop bottom");
1972 loopstk_pop();
1976 * Print out a statement
1978 static struct storage *x86_statement(struct statement *stmt)
1980 if (!stmt)
1981 return NULL;
1982 switch (stmt->type) {
1983 default:
1984 return NULL;
1985 case STMT_RETURN:
1986 return emit_return_stmt(stmt);
1987 case STMT_DECLARATION:
1988 x86_symbol_decl(stmt->declaration);
1989 break;
1990 case STMT_COMPOUND: {
1991 struct statement *s;
1992 struct storage *last = NULL;
1994 FOR_EACH_PTR(stmt->stmts, s) {
1995 last = x86_statement(s);
1996 } END_FOR_EACH_PTR(s);
1998 return last;
2001 case STMT_EXPRESSION:
2002 return x86_expression(stmt->expression);
2003 case STMT_IF:
2004 emit_if_conditional(stmt);
2005 return NULL;
2007 case STMT_CASE:
2008 emit_case_statement(stmt);
2009 break;
2010 case STMT_SWITCH:
2011 emit_switch_statement(stmt);
2012 break;
2014 case STMT_ITERATOR:
2015 emit_loop(stmt);
2016 break;
2018 case STMT_NONE:
2019 break;
2021 case STMT_LABEL:
2022 printf(".L%p:\n", stmt->label_identifier);
2023 x86_statement(stmt->label_statement);
2024 break;
2026 case STMT_GOTO:
2027 if (stmt->goto_expression) {
2028 struct storage *val = x86_expression(stmt->goto_expression);
2029 printf("\tgoto *v%d\n", val->pseudo);
2030 } else if (!strcmp("break", show_ident(stmt->goto_label->ident))) {
2031 struct storage *lbv = new_storage(STOR_LABEL);
2032 lbv->label = loopstk_break();
2033 lbv->flags = STOR_WANTS_FREE;
2034 insn("jmp", lbv, NULL, "'break'; go to loop bottom");
2035 } else if (!strcmp("continue", show_ident(stmt->goto_label->ident))) {
2036 struct storage *lbv = new_storage(STOR_LABEL);
2037 lbv->label = loopstk_continue();
2038 lbv->flags = STOR_WANTS_FREE;
2039 insn("jmp", lbv, NULL, "'continue'; go to loop top");
2040 } else {
2041 struct storage *labelsym = new_labelsym(stmt->goto_label);
2042 insn("jmp", labelsym, NULL, NULL);
2044 break;
2045 case STMT_ASM:
2046 printf("\tasm( .... )\n");
2047 break;
2049 return NULL;
2052 static struct storage *x86_call_expression(struct expression *expr)
2054 struct function *f = current_func;
2055 struct symbol *direct;
2056 struct expression *arg, *fn;
2057 struct storage *retval, *fncall;
2058 int framesize;
2059 char s[64];
2061 if (!expr->ctype) {
2062 warning(expr->pos, "\tcall with no type!");
2063 return NULL;
2066 framesize = 0;
2067 FOR_EACH_PTR_REVERSE(expr->args, arg) {
2068 struct storage *new = x86_expression(arg);
2069 int size = arg->ctype->bit_size;
2072 * FIXME: i386 SysV ABI dictates that values
2073 * smaller than 32 bits should be placed onto
2074 * the stack as 32-bit objects. We should not
2075 * blindly do a 32-bit push on objects smaller
2076 * than 32 bits.
2078 if (size < 32)
2079 size = 32;
2080 insn("pushl", new, NULL,
2081 !framesize ? "begin function call" : NULL);
2083 framesize += bits_to_bytes(size);
2084 } END_FOR_EACH_PTR_REVERSE(arg);
2086 fn = expr->fn;
2088 /* Remove dereference, if any */
2089 direct = NULL;
2090 if (fn->type == EXPR_PREOP) {
2091 if (fn->unop->type == EXPR_SYMBOL) {
2092 struct symbol *sym = fn->unop->symbol;
2093 if (sym->ctype.base_type->type == SYM_FN)
2094 direct = sym;
2097 if (direct) {
2098 struct storage *direct_stor = new_storage(STOR_SYM);
2099 direct_stor->flags |= STOR_WANTS_FREE;
2100 direct_stor->sym = direct;
2101 insn("call", direct_stor, NULL, NULL);
2102 } else {
2103 fncall = x86_expression(fn);
2104 emit_move(fncall, REG_EAX, fn->ctype, NULL);
2106 strcpy(s, "\tcall\t*%eax\n");
2107 push_text_atom(f, s);
2110 /* FIXME: pay attention to BITS_IN_POINTER */
2111 if (framesize) {
2112 struct storage *val = new_storage(STOR_VALUE);
2113 val->value = (long long) framesize;
2114 val->flags = STOR_WANTS_FREE;
2115 insn("addl", val, REG_ESP, NULL);
2118 retval = stack_alloc(4);
2119 emit_move(REG_EAX, retval, NULL, "end function call");
2121 return retval;
2124 static struct storage *x86_address_gen(struct expression *expr)
2126 struct function *f = current_func;
2127 struct storage *addr;
2128 struct storage *new;
2129 char s[32];
2131 addr = x86_expression(expr->unop);
2132 if (expr->unop->type == EXPR_SYMBOL)
2133 return addr;
2135 emit_move(addr, REG_EAX, NULL, "begin deref ..");
2137 /* FIXME: operand size */
2138 strcpy(s, "\tmovl\t(%eax), %ecx\n");
2139 push_text_atom(f, s);
2141 new = stack_alloc(4);
2142 emit_move(REG_ECX, new, NULL, ".... end deref");
2144 return new;
2147 static struct storage *x86_assignment(struct expression *expr)
2149 struct expression *target = expr->left;
2150 struct storage *val, *addr;
2152 if (!expr->ctype)
2153 return NULL;
2155 val = x86_expression(expr->right);
2156 addr = x86_address_gen(target);
2158 switch (val->type) {
2159 /* copy, where both operands are memory */
2160 case STOR_PSEUDO:
2161 case STOR_ARG:
2162 emit_copy(addr, val, expr->ctype);
2163 break;
2165 /* copy, one or zero operands are memory */
2166 case STOR_REG:
2167 case STOR_SYM:
2168 case STOR_VALUE:
2169 case STOR_LABEL:
2170 emit_move(val, addr, expr->left->ctype, NULL);
2171 break;
2173 case STOR_LABELSYM:
2174 assert(0);
2175 break;
2177 return val;
2180 static int x86_initialization(struct symbol *sym, struct expression *expr)
2182 struct storage *val, *addr;
2183 int bits;
2185 if (!expr->ctype)
2186 return 0;
2188 bits = expr->ctype->bit_size;
2189 val = x86_expression(expr);
2190 addr = x86_symbol_expr(sym);
2191 // FIXME! The "target" expression is for bitfield store information.
2192 // Leave it NULL, which works fine.
2193 emit_store(NULL, addr, val, bits);
2194 return 0;
2197 static struct storage *x86_access(struct expression *expr)
2199 return x86_address_gen(expr);
2202 static struct storage *x86_preop(struct expression *expr)
2205 * '*' is an lvalue access, and is fundamentally different
2206 * from an arithmetic operation. Maybe it should have an
2207 * expression type of its own..
2209 if (expr->op == '*')
2210 return x86_access(expr);
2211 if (expr->op == SPECIAL_INCREMENT || expr->op == SPECIAL_DECREMENT)
2212 return emit_inc_dec(expr, 0);
2213 return emit_regular_preop(expr);
2216 static struct storage *x86_symbol_expr(struct symbol *sym)
2218 struct storage *new = stack_alloc(4);
2220 if (sym->ctype.modifiers & (MOD_TOPLEVEL | MOD_EXTERN | MOD_STATIC)) {
2221 printf("\tmovi.%d\t\tv%d,$%s\n", bits_in_pointer, new->pseudo, show_ident(sym->ident));
2222 return new;
2224 if (sym->ctype.modifiers & MOD_ADDRESSABLE) {
2225 printf("\taddi.%d\t\tv%d,vFP,$%lld\n", bits_in_pointer, new->pseudo, sym->value);
2226 return new;
2228 printf("\taddi.%d\t\tv%d,vFP,$offsetof(%s:%p)\n", bits_in_pointer, new->pseudo, show_ident(sym->ident), sym);
2229 return new;
2232 static void x86_symbol_init(struct symbol *sym)
2234 struct symbol_private *priv = sym->aux;
2235 struct expression *expr = sym->initializer;
2236 struct storage *new;
2238 if (expr)
2239 new = x86_expression(expr);
2240 else
2241 new = stack_alloc(sym->bit_size / 8);
2243 if (!priv) {
2244 priv = calloc(1, sizeof(*priv));
2245 sym->aux = priv;
2246 /* FIXME: leak! we don't free... */
2247 /* (well, we don't free symbols either) */
2250 priv->addr = new;
2253 static int type_is_signed(struct symbol *sym)
2255 if (sym->type == SYM_NODE)
2256 sym = sym->ctype.base_type;
2257 if (sym->type == SYM_PTR)
2258 return 0;
2259 return !(sym->ctype.modifiers & MOD_UNSIGNED);
2262 static struct storage *x86_label_expr(struct expression *expr)
2264 struct storage *new = stack_alloc(4);
2265 printf("\tmovi.%d\t\tv%d,.L%p\n", bits_in_pointer, new->pseudo, expr->label_symbol);
2266 return new;
2269 static struct storage *x86_statement_expr(struct expression *expr)
2271 return x86_statement(expr->statement);
2274 static int x86_position_expr(struct expression *expr, struct symbol *base)
2276 struct storage *new = x86_expression(expr->init_expr);
2277 struct symbol *ctype = expr->init_expr->ctype;
2279 printf("\tinsert v%d at [%d:%d] of %s\n", new->pseudo,
2280 expr->init_offset, ctype->bit_offset,
2281 show_ident(base->ident));
2282 return 0;
2285 static void x86_initializer_expr(struct expression *expr, struct symbol *ctype)
2287 struct expression *entry;
2289 FOR_EACH_PTR(expr->expr_list, entry) {
2290 // Nested initializers have their positions already
2291 // recursively calculated - just output them too
2292 if (entry->type == EXPR_INITIALIZER) {
2293 x86_initializer_expr(entry, ctype);
2294 continue;
2297 // Ignore initializer indexes and identifiers - the
2298 // evaluator has taken them into account
2299 if (entry->type == EXPR_IDENTIFIER || entry->type == EXPR_INDEX)
2300 continue;
2301 if (entry->type == EXPR_POS) {
2302 x86_position_expr(entry, ctype);
2303 continue;
2305 x86_initialization(ctype, entry);
2306 } END_FOR_EACH_PTR(entry);
2310 * Print out an expression. Return the pseudo that contains the
2311 * variable.
2313 static struct storage *x86_expression(struct expression *expr)
2315 if (!expr)
2316 return NULL;
2318 if (!expr->ctype) {
2319 struct position *pos = &expr->pos;
2320 printf("\tno type at %s:%d:%d\n",
2321 stream_name(pos->stream),
2322 pos->line, pos->pos);
2323 return NULL;
2326 switch (expr->type) {
2327 default:
2328 return NULL;
2329 case EXPR_CALL:
2330 return x86_call_expression(expr);
2332 case EXPR_ASSIGNMENT:
2333 return x86_assignment(expr);
2335 case EXPR_COMPARE:
2336 return emit_compare(expr);
2337 case EXPR_BINOP:
2338 case EXPR_COMMA:
2339 case EXPR_LOGICAL:
2340 return emit_binop(expr);
2341 case EXPR_PREOP:
2342 return x86_preop(expr);
2343 case EXPR_POSTOP:
2344 return emit_postop(expr);
2345 case EXPR_SYMBOL:
2346 return emit_symbol_expr_init(expr->symbol);
2347 case EXPR_DEREF:
2348 case EXPR_SIZEOF:
2349 case EXPR_ALIGNOF:
2350 warning(expr->pos, "invalid expression after evaluation");
2351 return NULL;
2352 case EXPR_CAST:
2353 case EXPR_FORCE_CAST:
2354 case EXPR_IMPLIED_CAST:
2355 return emit_cast_expr(expr);
2356 case EXPR_VALUE:
2357 return emit_value(expr);
2358 case EXPR_STRING:
2359 return emit_string_expr(expr);
2360 case EXPR_INITIALIZER:
2361 x86_initializer_expr(expr, expr->ctype);
2362 return NULL;
2363 case EXPR_SELECT:
2364 return emit_select_expr(expr);
2365 case EXPR_CONDITIONAL:
2366 return emit_conditional_expr(expr);
2367 case EXPR_STATEMENT:
2368 return x86_statement_expr(expr);
2369 case EXPR_LABEL:
2370 return x86_label_expr(expr);
2372 // None of these should exist as direct expressions: they are only
2373 // valid as sub-expressions of initializers.
2374 case EXPR_POS:
2375 warning(expr->pos, "unable to show plain initializer position expression");
2376 return NULL;
2377 case EXPR_IDENTIFIER:
2378 warning(expr->pos, "unable to show identifier expression");
2379 return NULL;
2380 case EXPR_INDEX:
2381 warning(expr->pos, "unable to show index expression");
2382 return NULL;
2383 case EXPR_TYPE:
2384 warning(expr->pos, "unable to show type expression");
2385 return NULL;
2386 case EXPR_FVALUE:
2387 warning(expr->pos, "floating point support is not implemented");
2388 return NULL;
2390 return NULL;