added a bunch of gcc builtins
[smatch.git] / compile-i386.c
blobd61652e6e3097a3336caea098041d69e2809951d
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, ...);
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 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 unsigned int i;
1011 for (i = 0; i < sorted; i++)
1012 if (sort_array_cmp(entry, list[i]) <= 0)
1013 break;
1015 /* If inserting into the middle of list[]
1016 * instead of appending, we memmove.
1017 * This is ugly, but thankfully
1018 * uncommon. Input data with tons of
1019 * entries very rarely have explicit
1020 * offsets. convert to qsort eventually...
1022 if (i != sorted)
1023 memmove(&list[i + 1], &list[i],
1024 (sorted - i) * sizeof(entry));
1025 list[i] = entry;
1026 sorted++;
1029 } END_FOR_EACH_PTR(entry);
1031 i = 0;
1032 FOR_EACH_PTR(expr->expr_list, entry) {
1033 if ((entry->type == EXPR_POS) || (entry->type == EXPR_VALUE))
1034 *THIS_ADDRESS(entry) = list[i++];
1035 } END_FOR_EACH_PTR(entry);
1039 static void emit_array(struct symbol *sym)
1041 struct symbol *base_type = sym->ctype.base_type;
1042 struct expression *expr = sym->initializer;
1043 struct expression *entry;
1045 assert(base_type != NULL);
1047 stor_sym_init(sym);
1049 ea_last = -1;
1051 emit_object_pre(show_ident(sym->ident), sym->ctype.modifiers,
1052 sym->ctype.alignment,
1053 sym->bit_size / 8);
1055 sort_array(expr);
1057 FOR_EACH_PTR(expr->expr_list, entry) {
1058 if (entry->type == EXPR_VALUE) {
1059 ea_current = 0;
1060 emit_initializer(sym, entry);
1061 ea_last = ea_current;
1062 } else if (entry->type == EXPR_POS) {
1063 ea_current =
1064 entry->init_offset / (base_type->bit_size / 8);
1065 emit_initializer(sym, entry->init_expr);
1066 ea_last = ea_current;
1068 } END_FOR_EACH_PTR(entry);
1071 void emit_one_symbol(struct symbol *sym)
1073 x86_symbol(sym);
1076 static void emit_copy(struct storage *dest, struct storage *src,
1077 struct symbol *ctype)
1079 struct storage *reg = NULL;
1080 unsigned int bit_size;
1082 /* FIXME: Bitfield copy! */
1084 bit_size = src->size * 8;
1085 if (!bit_size)
1086 bit_size = 32;
1087 if ((src->type == STOR_ARG) && (bit_size < 32))
1088 bit_size = 32;
1090 reg = temp_from_bits(bit_size);
1091 emit_move(src, reg, ctype, "begin copy ..");
1093 bit_size = dest->size * 8;
1094 if (!bit_size)
1095 bit_size = 32;
1096 if ((dest->type == STOR_ARG) && (bit_size < 32))
1097 bit_size = 32;
1099 emit_move(reg, dest, ctype, ".... end copy");
1100 put_reg(reg);
1103 static void emit_store(struct expression *dest_expr, struct storage *dest,
1104 struct storage *src, int bits)
1106 /* FIXME: Bitfield store! */
1107 printf("\tst.%d\t\tv%d,[v%d]\n", bits, src->pseudo, dest->pseudo);
1110 static void emit_scalar_noinit(struct symbol *sym)
1112 emit_global_noinit(show_ident(sym->ident),
1113 sym->ctype.modifiers, sym->ctype.alignment,
1114 sym->bit_size / 8);
1115 stor_sym_init(sym);
1118 static void emit_array_noinit(struct symbol *sym)
1120 emit_global_noinit(show_ident(sym->ident),
1121 sym->ctype.modifiers, sym->ctype.alignment,
1122 get_expression_value(sym->array_size) * (sym->bit_size / 8));
1123 stor_sym_init(sym);
1126 static const char *opbits(const char *insn, unsigned int bits)
1128 static char opbits_str[32];
1129 char c;
1131 switch (bits) {
1132 case 8: c = 'b'; break;
1133 case 16: c = 'w'; break;
1134 case 32: c = 'l'; break;
1135 case 64: c = 'q'; break;
1136 default: abort(); break;
1139 sprintf(opbits_str, "%s%c", insn, c);
1141 return opbits_str;
1144 static void emit_move(struct storage *src, struct storage *dest,
1145 struct symbol *ctype, const char *comment)
1147 unsigned int bits;
1148 unsigned int is_signed;
1149 unsigned int is_dest = (src->type == STOR_REG);
1150 const char *opname;
1152 if (ctype) {
1153 bits = ctype->bit_size;
1154 is_signed = type_is_signed(ctype);
1155 } else {
1156 bits = 32;
1157 is_signed = 0;
1161 * Are we moving from a register to a register?
1162 * Make the new reg to be the "cache".
1164 if ((dest->type == STOR_REG) && (src->type == STOR_REG)) {
1165 struct storage *backing;
1167 reg_reg_move:
1168 if (dest == src)
1169 return;
1171 backing = src->reg->contains;
1172 if (backing) {
1173 /* Is it still valid? */
1174 if (backing->reg != src->reg)
1175 backing = NULL;
1176 else
1177 backing->reg = dest->reg;
1179 dest->reg->contains = backing;
1180 insn("mov", src, dest, NULL);
1181 return;
1185 * Are we moving to a register from a non-reg?
1187 * See if we have the non-reg source already cached
1188 * in a register..
1190 if (dest->type == STOR_REG) {
1191 if (src->reg) {
1192 struct reg_info *info = src->reg;
1193 if (info->contains == src) {
1194 src = reginfo_reg(info);
1195 goto reg_reg_move;
1198 dest->reg->contains = src;
1199 src->reg = dest->reg;
1202 if (src->type == STOR_REG) {
1203 /* We could just mark the register dirty here and do lazy store.. */
1204 src->reg->contains = dest;
1205 dest->reg = src->reg;
1208 if ((bits == 8) || (bits == 16)) {
1209 if (is_dest)
1210 opname = "mov";
1211 else
1212 opname = is_signed ? "movsx" : "movzx";
1213 } else
1214 opname = "mov";
1216 insn(opbits(opname, bits), src, dest, comment);
1219 static struct storage *emit_compare(struct expression *expr)
1221 struct storage *left = x86_expression(expr->left);
1222 struct storage *right = x86_expression(expr->right);
1223 struct storage *reg1, *reg2;
1224 struct storage *new, *val;
1225 const char *opname = NULL;
1226 unsigned int right_bits = expr->right->ctype->bit_size;
1228 switch(expr->op) {
1229 case '<': opname = "setl"; break;
1230 case '>': opname = "setg"; break;
1231 case SPECIAL_LTE:
1232 opname = "setle"; break;
1233 case SPECIAL_GTE:
1234 opname = "setge"; break;
1235 case SPECIAL_EQUAL: opname = "sete"; break;
1236 case SPECIAL_NOTEQUAL: opname = "setne"; break;
1237 case SPECIAL_UNSIGNED_LT:
1238 opname = "setb"; break;
1239 case SPECIAL_UNSIGNED_GT:
1240 opname = "seta"; break;
1241 case SPECIAL_UNSIGNED_LTE:
1242 opname = "setb"; break;
1243 case SPECIAL_UNSIGNED_GTE:
1244 opname = "setae"; break;
1245 default:
1246 assert(0);
1247 break;
1250 /* init EDX to 0 */
1251 val = new_storage(STOR_VALUE);
1252 val->flags = STOR_WANTS_FREE;
1254 reg1 = get_reg(&regclass_32_8);
1255 emit_move(val, reg1, NULL, NULL);
1257 /* move op1 into EAX */
1258 reg2 = get_reg_value(left, get_regclass(expr->left));
1260 /* perform comparison, RHS (op1, right) and LHS (op2, EAX) */
1261 insn(opbits("cmp", right_bits), right, reg2, NULL);
1262 put_reg(reg2);
1264 /* store result of operation, 0 or 1, in DL using SETcc */
1265 insn(opname, byte_reg(reg1), NULL, NULL);
1267 /* finally, store the result (DL) in a new pseudo / stack slot */
1268 new = stack_alloc(4);
1269 emit_move(reg1, new, NULL, "end EXPR_COMPARE");
1270 put_reg(reg1);
1272 return new;
1275 static struct storage *emit_value(struct expression *expr)
1277 #if 0 /* old and slow way */
1278 struct storage *new = stack_alloc(4);
1279 struct storage *val;
1281 val = new_storage(STOR_VALUE);
1282 val->value = (long long) expr->value;
1283 val->flags = STOR_WANTS_FREE;
1284 insn("movl", val, new, NULL);
1286 return new;
1287 #else
1288 struct storage *val;
1290 val = new_storage(STOR_VALUE);
1291 val->value = (long long) expr->value;
1293 return val; /* FIXME: memory leak */
1294 #endif
1297 static struct storage *emit_divide(struct expression *expr, struct storage *left, struct storage *right)
1299 struct storage *eax_edx;
1300 struct storage *reg, *new;
1301 struct storage *val = new_storage(STOR_VALUE);
1303 emit_comment("begin DIVIDE");
1304 eax_edx = get_hardreg(hardreg_storage_table + EAX_EDX, 1);
1306 /* init EDX to 0 */
1307 val = new_storage(STOR_VALUE);
1308 val->flags = STOR_WANTS_FREE;
1309 emit_move(val, REG_EDX, NULL, NULL);
1311 new = stack_alloc(expr->ctype->bit_size / 8);
1313 /* EAX is dividend */
1314 emit_move(left, REG_EAX, NULL, NULL);
1316 reg = get_reg_value(right, &regclass_32);
1318 /* perform binop */
1319 insn("div", reg, REG_EAX, NULL);
1320 put_reg(reg);
1322 reg = REG_EAX;
1323 if (expr->op == '%')
1324 reg = REG_EDX;
1325 emit_move(reg, new, NULL, NULL);
1327 put_reg(eax_edx);
1328 emit_comment("end DIVIDE");
1329 return new;
1332 static struct storage *emit_binop(struct expression *expr)
1334 struct storage *left = x86_expression(expr->left);
1335 struct storage *right = x86_expression(expr->right);
1336 struct storage *new;
1337 struct storage *dest, *src;
1338 const char *opname = NULL;
1339 const char *suffix = NULL;
1340 char opstr[16];
1341 int is_signed;
1343 /* Divides have special register constraints */
1344 if ((expr->op == '/') || (expr->op == '%'))
1345 return emit_divide(expr, left, right);
1347 is_signed = type_is_signed(expr->ctype);
1349 switch (expr->op) {
1350 case '+':
1351 opname = "add";
1352 break;
1353 case '-':
1354 opname = "sub";
1355 break;
1356 case '&':
1357 opname = "and";
1358 break;
1359 case '|':
1360 opname = "or";
1361 break;
1362 case '^':
1363 opname = "xor";
1364 break;
1365 case SPECIAL_LEFTSHIFT:
1366 opname = "shl";
1367 break;
1368 case SPECIAL_RIGHTSHIFT:
1369 if (is_signed)
1370 opname = "sar";
1371 else
1372 opname = "shr";
1373 break;
1374 case '*':
1375 if (is_signed)
1376 opname = "imul";
1377 else
1378 opname = "mul";
1379 break;
1380 case SPECIAL_LOGICAL_AND:
1381 warning(expr->pos, "bogus bitwise and for logical op (should use '2*setne + and' or something)");
1382 opname = "and";
1383 break;
1384 case SPECIAL_LOGICAL_OR:
1385 warning(expr->pos, "bogus bitwise or for logical op (should use 'or + setne' or something)");
1386 opname = "or";
1387 break;
1388 default:
1389 error_die(expr->pos, "unhandled binop '%s'\n", show_special(expr->op));
1390 break;
1393 dest = get_reg_value(right, &regclass_32);
1394 src = get_reg_value(left, &regclass_32);
1395 switch (expr->ctype->bit_size) {
1396 case 8:
1397 suffix = "b";
1398 break;
1399 case 16:
1400 suffix = "w";
1401 break;
1402 case 32:
1403 suffix = "l";
1404 break;
1405 case 64:
1406 suffix = "q"; /* FIXME */
1407 break;
1408 default:
1409 assert(0);
1410 break;
1413 snprintf(opstr, sizeof(opstr), "%s%s", opname, suffix);
1415 /* perform binop */
1416 insn(opstr, src, dest, NULL);
1417 put_reg(src);
1419 /* store result in new pseudo / stack slot */
1420 new = stack_alloc(expr->ctype->bit_size / 8);
1421 emit_move(dest, new, NULL, "end EXPR_BINOP");
1423 put_reg(dest);
1425 return new;
1428 static int emit_conditional_test(struct storage *val)
1430 struct storage *reg;
1431 struct storage *target_val;
1432 int target_false;
1434 /* load result into EAX */
1435 emit_comment("begin if/conditional");
1436 reg = get_reg_value(val, &regclass_32);
1438 /* compare result with zero */
1439 insn("test", reg, reg, NULL);
1440 put_reg(reg);
1442 /* create conditional-failed label to jump to */
1443 target_false = new_label();
1444 target_val = new_storage(STOR_LABEL);
1445 target_val->label = target_false;
1446 target_val->flags = STOR_WANTS_FREE;
1447 insn("jz", target_val, NULL, NULL);
1449 return target_false;
1452 static int emit_conditional_end(int target_false)
1454 struct storage *cond_end_st;
1455 int cond_end;
1457 /* finished generating code for if-true statement.
1458 * add a jump-to-end jump to avoid falling through
1459 * to the if-false statement code.
1461 cond_end = new_label();
1462 cond_end_st = new_storage(STOR_LABEL);
1463 cond_end_st->label = cond_end;
1464 cond_end_st->flags = STOR_WANTS_FREE;
1465 insn("jmp", cond_end_st, NULL, NULL);
1467 /* if we have both if-true and if-false statements,
1468 * the failed-conditional case will fall through to here
1470 emit_label(target_false, NULL);
1472 return cond_end;
1475 static void emit_if_conditional(struct statement *stmt)
1477 struct storage *val;
1478 int cond_end;
1480 /* emit test portion of conditional */
1481 val = x86_expression(stmt->if_conditional);
1482 cond_end = emit_conditional_test(val);
1484 /* emit if-true statement */
1485 x86_statement(stmt->if_true);
1487 /* emit if-false statement, if present */
1488 if (stmt->if_false) {
1489 cond_end = emit_conditional_end(cond_end);
1490 x86_statement(stmt->if_false);
1493 /* end of conditional; jump target for if-true branch */
1494 emit_label(cond_end, "end if");
1497 static struct storage *emit_inc_dec(struct expression *expr, int postop)
1499 struct storage *addr = x86_address_gen(expr->unop);
1500 struct storage *retval;
1501 char opname[16];
1503 strcpy(opname, opbits(expr->op == SPECIAL_INCREMENT ? "inc" : "dec",
1504 expr->ctype->bit_size));
1506 if (postop) {
1507 struct storage *new = stack_alloc(4);
1509 emit_copy(new, addr, expr->unop->ctype);
1511 retval = new;
1512 } else
1513 retval = addr;
1515 insn(opname, addr, NULL, NULL);
1517 return retval;
1520 static struct storage *emit_postop(struct expression *expr)
1522 return emit_inc_dec(expr, 1);
1525 static struct storage *emit_return_stmt(struct statement *stmt)
1527 struct function *f = current_func;
1528 struct expression *expr = stmt->ret_value;
1529 struct storage *val = NULL, *jmplbl;
1531 if (expr && expr->ctype) {
1532 val = x86_expression(expr);
1533 assert(val != NULL);
1534 emit_move(val, REG_EAX, expr->ctype, "return");
1537 jmplbl = new_storage(STOR_LABEL);
1538 jmplbl->flags |= STOR_WANTS_FREE;
1539 jmplbl->label = f->ret_target;
1540 insn("jmp", jmplbl, NULL, NULL);
1542 return val;
1545 static struct storage *emit_conditional_expr(struct expression *expr)
1547 struct storage *cond, *true = NULL, *false = NULL;
1548 struct storage *new = stack_alloc(expr->ctype->bit_size / 8);
1549 int target_false, cond_end;
1551 /* evaluate conditional */
1552 cond = x86_expression(expr->conditional);
1553 target_false = emit_conditional_test(cond);
1555 /* handle if-true part of the expression */
1556 true = x86_expression(expr->cond_true);
1558 emit_copy(new, true, expr->ctype);
1560 cond_end = emit_conditional_end(target_false);
1562 /* handle if-false part of the expression */
1563 false = x86_expression(expr->cond_false);
1565 emit_copy(new, false, expr->ctype);
1567 /* end of conditional; jump target for if-true branch */
1568 emit_label(cond_end, "end conditional");
1570 return new;
1573 static struct storage *emit_select_expr(struct expression *expr)
1575 struct storage *cond = x86_expression(expr->conditional);
1576 struct storage *true = x86_expression(expr->cond_true);
1577 struct storage *false = x86_expression(expr->cond_false);
1578 struct storage *reg_cond, *reg_true, *reg_false;
1579 struct storage *new = stack_alloc(4);
1581 emit_comment("begin SELECT");
1582 reg_cond = get_reg_value(cond, get_regclass(expr->conditional));
1583 reg_true = get_reg_value(true, get_regclass(expr));
1584 reg_false = get_reg_value(false, get_regclass(expr));
1587 * Do the actual select: check the conditional for zero,
1588 * move false over true if zero
1590 insn("test", reg_cond, reg_cond, NULL);
1591 insn("cmovz", reg_false, reg_true, NULL);
1593 /* Store it back */
1594 emit_move(reg_true, new, expr->ctype, NULL);
1595 put_reg(reg_cond);
1596 put_reg(reg_true);
1597 put_reg(reg_false);
1598 emit_comment("end SELECT");
1599 return new;
1602 static struct storage *emit_symbol_expr_init(struct symbol *sym)
1604 struct expression *expr = sym->initializer;
1605 struct symbol_private *priv = sym->aux;
1607 if (priv == NULL) {
1608 priv = calloc(1, sizeof(*priv));
1609 sym->aux = priv;
1611 if (expr == NULL) {
1612 struct storage *new = stack_alloc(4);
1613 fprintf(stderr, "FIXME! no value for symbol %s. creating pseudo %d (stack offset %d)\n",
1614 show_ident(sym->ident),
1615 new->pseudo, new->pseudo * 4);
1616 priv->addr = new;
1617 } else {
1618 priv->addr = x86_expression(expr);
1622 return priv->addr;
1625 static struct storage *emit_string_expr(struct expression *expr)
1627 struct function *f = current_func;
1628 int label = new_label();
1629 struct storage *new;
1631 push_cstring(f, expr->string, label);
1633 new = new_storage(STOR_LABEL);
1634 new->label = label;
1635 new->flags = STOR_LABEL_VAL | STOR_WANTS_FREE;
1636 return new;
1639 static struct storage *emit_cast_expr(struct expression *expr)
1641 struct symbol *old_type, *new_type;
1642 struct storage *op = x86_expression(expr->cast_expression);
1643 int oldbits, newbits;
1644 struct storage *new;
1646 old_type = expr->cast_expression->ctype;
1647 new_type = expr->cast_type;
1649 oldbits = old_type->bit_size;
1650 newbits = new_type->bit_size;
1651 if (oldbits >= newbits)
1652 return op;
1654 emit_move(op, REG_EAX, old_type, "begin cast ..");
1656 new = stack_alloc(newbits / 8);
1657 emit_move(REG_EAX, new, new_type, ".... end cast");
1659 return new;
1662 static struct storage *emit_regular_preop(struct expression *expr)
1664 struct storage *target = x86_expression(expr->unop);
1665 struct storage *val, *new = stack_alloc(4);
1666 const char *opname = NULL;
1668 switch (expr->op) {
1669 case '!':
1670 val = new_storage(STOR_VALUE);
1671 val->flags = STOR_WANTS_FREE;
1672 emit_move(val, REG_EDX, NULL, NULL);
1673 emit_move(target, REG_EAX, expr->unop->ctype, NULL);
1674 insn("test", REG_EAX, REG_EAX, NULL);
1675 insn("setz", REG_DL, NULL, NULL);
1676 emit_move(REG_EDX, new, expr->unop->ctype, NULL);
1678 break;
1679 case '~':
1680 opname = "not";
1681 case '-':
1682 if (!opname)
1683 opname = "neg";
1684 emit_move(target, REG_EAX, expr->unop->ctype, NULL);
1685 insn(opname, REG_EAX, NULL, NULL);
1686 emit_move(REG_EAX, new, expr->unop->ctype, NULL);
1687 break;
1688 default:
1689 assert(0);
1690 break;
1693 return new;
1696 static void emit_case_statement(struct statement *stmt)
1698 emit_labelsym(stmt->case_label, NULL);
1699 x86_statement(stmt->case_statement);
1702 static void emit_switch_statement(struct statement *stmt)
1704 struct storage *val = x86_expression(stmt->switch_expression);
1705 struct symbol *sym, *default_sym = NULL;
1706 struct storage *labelsym, *label;
1707 int switch_end = 0;
1709 emit_move(val, REG_EAX, stmt->switch_expression->ctype, "begin case");
1712 * This is where a _real_ back-end would go through the
1713 * cases to decide whether to use a lookup table or a
1714 * series of comparisons etc
1716 FOR_EACH_PTR(stmt->switch_case->symbol_list, sym) {
1717 struct statement *case_stmt = sym->stmt;
1718 struct expression *expr = case_stmt->case_expression;
1719 struct expression *to = case_stmt->case_to;
1721 /* default: */
1722 if (!expr)
1723 default_sym = sym;
1725 /* case NNN: */
1726 else {
1727 struct storage *case_val = new_val(expr->value);
1729 assert (expr->type == EXPR_VALUE);
1731 insn("cmpl", case_val, REG_EAX, NULL);
1733 if (!to) {
1734 labelsym = new_labelsym(sym);
1735 insn("je", labelsym, NULL, NULL);
1736 } else {
1737 int next_test;
1739 label = new_storage(STOR_LABEL);
1740 label->flags |= STOR_WANTS_FREE;
1741 label->label = next_test = new_label();
1743 /* FIXME: signed/unsigned */
1744 insn("jl", label, NULL, NULL);
1746 case_val = new_val(to->value);
1747 insn("cmpl", case_val, REG_EAX, NULL);
1749 /* TODO: implement and use refcounting... */
1750 label = new_storage(STOR_LABEL);
1751 label->flags |= STOR_WANTS_FREE;
1752 label->label = next_test;
1754 /* FIXME: signed/unsigned */
1755 insn("jg", label, NULL, NULL);
1757 labelsym = new_labelsym(sym);
1758 insn("jmp", labelsym, NULL, NULL);
1760 emit_label(next_test, NULL);
1763 } END_FOR_EACH_PTR(sym);
1765 if (default_sym) {
1766 labelsym = new_labelsym(default_sym);
1767 insn("jmp", labelsym, NULL, "default");
1768 } else {
1769 label = new_storage(STOR_LABEL);
1770 label->flags |= STOR_WANTS_FREE;
1771 label->label = switch_end = new_label();
1772 insn("jmp", label, NULL, "goto end of switch");
1775 x86_statement(stmt->switch_statement);
1777 if (stmt->switch_break->used)
1778 emit_labelsym(stmt->switch_break, NULL);
1780 if (switch_end)
1781 emit_label(switch_end, NULL);
1784 static void x86_struct_member(struct symbol *sym)
1786 printf("\t%s:%d:%ld at offset %ld.%d", show_ident(sym->ident), sym->bit_size, sym->ctype.alignment, sym->offset, sym->bit_offset);
1787 printf("\n");
1790 static void x86_symbol(struct symbol *sym)
1792 struct symbol *type;
1794 if (!sym)
1795 return;
1797 type = sym->ctype.base_type;
1798 if (!type)
1799 return;
1802 * Show actual implementation information
1804 switch (type->type) {
1806 case SYM_ARRAY:
1807 if (sym->initializer)
1808 emit_array(sym);
1809 else
1810 emit_array_noinit(sym);
1811 break;
1813 case SYM_BASETYPE:
1814 if (sym->initializer) {
1815 emit_object_pre(show_ident(sym->ident),
1816 sym->ctype.modifiers,
1817 sym->ctype.alignment,
1818 sym->bit_size / 8);
1819 emit_scalar(sym->initializer, sym->bit_size);
1820 stor_sym_init(sym);
1821 } else
1822 emit_scalar_noinit(sym);
1823 break;
1825 case SYM_STRUCT:
1826 case SYM_UNION: {
1827 struct symbol *member;
1829 printf(" {\n");
1830 FOR_EACH_PTR(type->symbol_list, member) {
1831 x86_struct_member(member);
1832 } END_FOR_EACH_PTR(member);
1833 printf("}\n");
1834 break;
1837 case SYM_FN: {
1838 struct statement *stmt = type->stmt;
1839 if (stmt) {
1840 emit_func_pre(sym);
1841 x86_statement(stmt);
1842 emit_func_post(sym);
1844 break;
1847 default:
1848 break;
1851 if (sym->initializer && (type->type != SYM_BASETYPE) &&
1852 (type->type != SYM_ARRAY)) {
1853 printf(" = \n");
1854 x86_expression(sym->initializer);
1858 static void x86_symbol_init(struct symbol *sym);
1860 static void x86_symbol_decl(struct symbol_list *syms)
1862 struct symbol *sym;
1863 FOR_EACH_PTR(syms, sym) {
1864 x86_symbol_init(sym);
1865 } END_FOR_EACH_PTR(sym);
1868 static void loopstk_push(int cont_lbl, int loop_bottom_lbl)
1870 struct function *f = current_func;
1871 struct loop_stack *ls;
1873 ls = malloc(sizeof(*ls));
1874 ls->continue_lbl = cont_lbl;
1875 ls->loop_bottom_lbl = loop_bottom_lbl;
1876 ls->next = f->loop_stack;
1877 f->loop_stack = ls;
1880 static void loopstk_pop(void)
1882 struct function *f = current_func;
1883 struct loop_stack *ls;
1885 assert(f->loop_stack != NULL);
1886 ls = f->loop_stack;
1887 f->loop_stack = f->loop_stack->next;
1888 free(ls);
1891 static int loopstk_break(void)
1893 return current_func->loop_stack->loop_bottom_lbl;
1896 static int loopstk_continue(void)
1898 return current_func->loop_stack->continue_lbl;
1901 static void emit_loop(struct statement *stmt)
1903 struct statement *pre_statement = stmt->iterator_pre_statement;
1904 struct expression *pre_condition = stmt->iterator_pre_condition;
1905 struct statement *statement = stmt->iterator_statement;
1906 struct statement *post_statement = stmt->iterator_post_statement;
1907 struct expression *post_condition = stmt->iterator_post_condition;
1908 int loop_top = 0, loop_bottom, loop_continue;
1909 int have_bottom = 0;
1910 struct storage *val;
1912 loop_bottom = new_label();
1913 loop_continue = new_label();
1914 loopstk_push(loop_continue, loop_bottom);
1916 x86_symbol_decl(stmt->iterator_syms);
1917 x86_statement(pre_statement);
1918 if (pre_condition) {
1919 if (pre_condition->type == EXPR_VALUE) {
1920 if (!pre_condition->value) {
1921 struct storage *lbv;
1922 lbv = new_storage(STOR_LABEL);
1923 lbv->label = loop_bottom;
1924 lbv->flags = STOR_WANTS_FREE;
1925 insn("jmp", lbv, NULL, "go to loop bottom");
1926 have_bottom = 1;
1928 } else {
1929 struct storage *lbv = new_storage(STOR_LABEL);
1930 lbv->label = loop_bottom;
1931 lbv->flags = STOR_WANTS_FREE;
1932 have_bottom = 1;
1934 val = x86_expression(pre_condition);
1936 emit_move(val, REG_EAX, NULL, "loop pre condition");
1937 insn("test", REG_EAX, REG_EAX, NULL);
1938 insn("jz", lbv, NULL, NULL);
1941 if (!post_condition || post_condition->type != EXPR_VALUE || post_condition->value) {
1942 loop_top = new_label();
1943 emit_label(loop_top, "loop top");
1945 x86_statement(statement);
1946 if (stmt->iterator_continue->used)
1947 emit_label(loop_continue, "'continue' iterator");
1948 x86_statement(post_statement);
1949 if (!post_condition) {
1950 struct storage *lbv = new_storage(STOR_LABEL);
1951 lbv->label = loop_top;
1952 lbv->flags = STOR_WANTS_FREE;
1953 insn("jmp", lbv, NULL, "go to loop top");
1954 } else if (post_condition->type == EXPR_VALUE) {
1955 if (post_condition->value) {
1956 struct storage *lbv = new_storage(STOR_LABEL);
1957 lbv->label = loop_top;
1958 lbv->flags = STOR_WANTS_FREE;
1959 insn("jmp", lbv, NULL, "go to loop top");
1961 } else {
1962 struct storage *lbv = new_storage(STOR_LABEL);
1963 lbv->label = loop_top;
1964 lbv->flags = STOR_WANTS_FREE;
1966 val = x86_expression(post_condition);
1968 emit_move(val, REG_EAX, NULL, "loop post condition");
1969 insn("test", REG_EAX, REG_EAX, NULL);
1970 insn("jnz", lbv, NULL, NULL);
1972 if (have_bottom || stmt->iterator_break->used)
1973 emit_label(loop_bottom, "loop bottom");
1975 loopstk_pop();
1979 * Print out a statement
1981 static struct storage *x86_statement(struct statement *stmt)
1983 if (!stmt)
1984 return NULL;
1985 switch (stmt->type) {
1986 default:
1987 return NULL;
1988 case STMT_RETURN:
1989 return emit_return_stmt(stmt);
1990 case STMT_DECLARATION:
1991 x86_symbol_decl(stmt->declaration);
1992 break;
1993 case STMT_COMPOUND: {
1994 struct statement *s;
1995 struct storage *last = NULL;
1997 FOR_EACH_PTR(stmt->stmts, s) {
1998 last = x86_statement(s);
1999 } END_FOR_EACH_PTR(s);
2001 return last;
2004 case STMT_EXPRESSION:
2005 return x86_expression(stmt->expression);
2006 case STMT_IF:
2007 emit_if_conditional(stmt);
2008 return NULL;
2010 case STMT_CASE:
2011 emit_case_statement(stmt);
2012 break;
2013 case STMT_SWITCH:
2014 emit_switch_statement(stmt);
2015 break;
2017 case STMT_ITERATOR:
2018 emit_loop(stmt);
2019 break;
2021 case STMT_NONE:
2022 break;
2024 case STMT_LABEL:
2025 printf(".L%p:\n", stmt->label_identifier);
2026 x86_statement(stmt->label_statement);
2027 break;
2029 case STMT_GOTO:
2030 if (stmt->goto_expression) {
2031 struct storage *val = x86_expression(stmt->goto_expression);
2032 printf("\tgoto *v%d\n", val->pseudo);
2033 } else if (!strcmp("break", show_ident(stmt->goto_label->ident))) {
2034 struct storage *lbv = new_storage(STOR_LABEL);
2035 lbv->label = loopstk_break();
2036 lbv->flags = STOR_WANTS_FREE;
2037 insn("jmp", lbv, NULL, "'break'; go to loop bottom");
2038 } else if (!strcmp("continue", show_ident(stmt->goto_label->ident))) {
2039 struct storage *lbv = new_storage(STOR_LABEL);
2040 lbv->label = loopstk_continue();
2041 lbv->flags = STOR_WANTS_FREE;
2042 insn("jmp", lbv, NULL, "'continue'; go to loop top");
2043 } else {
2044 struct storage *labelsym = new_labelsym(stmt->goto_label);
2045 insn("jmp", labelsym, NULL, NULL);
2047 break;
2048 case STMT_ASM:
2049 printf("\tasm( .... )\n");
2050 break;
2052 return NULL;
2055 static struct storage *x86_call_expression(struct expression *expr)
2057 struct function *f = current_func;
2058 struct symbol *direct;
2059 struct expression *arg, *fn;
2060 struct storage *retval, *fncall;
2061 int framesize;
2062 char s[64];
2064 if (!expr->ctype) {
2065 warning(expr->pos, "\tcall with no type!");
2066 return NULL;
2069 framesize = 0;
2070 FOR_EACH_PTR_REVERSE(expr->args, arg) {
2071 struct storage *new = x86_expression(arg);
2072 int size = arg->ctype->bit_size;
2075 * FIXME: i386 SysV ABI dictates that values
2076 * smaller than 32 bits should be placed onto
2077 * the stack as 32-bit objects. We should not
2078 * blindly do a 32-bit push on objects smaller
2079 * than 32 bits.
2081 if (size < 32)
2082 size = 32;
2083 insn("pushl", new, NULL,
2084 !framesize ? "begin function call" : NULL);
2086 framesize += size >> 3;
2087 } END_FOR_EACH_PTR_REVERSE(arg);
2089 fn = expr->fn;
2091 /* Remove dereference, if any */
2092 direct = NULL;
2093 if (fn->type == EXPR_PREOP) {
2094 if (fn->unop->type == EXPR_SYMBOL) {
2095 struct symbol *sym = fn->unop->symbol;
2096 if (sym->ctype.base_type->type == SYM_FN)
2097 direct = sym;
2100 if (direct) {
2101 struct storage *direct_stor = new_storage(STOR_SYM);
2102 direct_stor->flags |= STOR_WANTS_FREE;
2103 direct_stor->sym = direct;
2104 insn("call", direct_stor, NULL, NULL);
2105 } else {
2106 fncall = x86_expression(fn);
2107 emit_move(fncall, REG_EAX, fn->ctype, NULL);
2109 strcpy(s, "\tcall\t*%eax\n");
2110 push_text_atom(f, s);
2113 /* FIXME: pay attention to BITS_IN_POINTER */
2114 if (framesize) {
2115 struct storage *val = new_storage(STOR_VALUE);
2116 val->value = (long long) framesize;
2117 val->flags = STOR_WANTS_FREE;
2118 insn("addl", val, REG_ESP, NULL);
2121 retval = stack_alloc(4);
2122 emit_move(REG_EAX, retval, NULL, "end function call");
2124 return retval;
2127 static struct storage *x86_address_gen(struct expression *expr)
2129 struct function *f = current_func;
2130 struct storage *addr;
2131 struct storage *new;
2132 char s[32];
2134 addr = x86_expression(expr->unop);
2135 if (expr->unop->type == EXPR_SYMBOL)
2136 return addr;
2138 emit_move(addr, REG_EAX, NULL, "begin deref ..");
2140 /* FIXME: operand size */
2141 strcpy(s, "\tmovl\t(%eax), %ecx\n");
2142 push_text_atom(f, s);
2144 new = stack_alloc(4);
2145 emit_move(REG_ECX, new, NULL, ".... end deref");
2147 return new;
2150 static struct storage *x86_assignment(struct expression *expr)
2152 struct expression *target = expr->left;
2153 struct storage *val, *addr;
2155 if (!expr->ctype)
2156 return NULL;
2158 val = x86_expression(expr->right);
2159 addr = x86_address_gen(target);
2161 switch (val->type) {
2162 /* copy, where both operands are memory */
2163 case STOR_PSEUDO:
2164 case STOR_ARG:
2165 emit_copy(addr, val, expr->ctype);
2166 break;
2168 /* copy, one or zero operands are memory */
2169 case STOR_REG:
2170 case STOR_SYM:
2171 case STOR_VALUE:
2172 case STOR_LABEL:
2173 emit_move(val, addr, expr->left->ctype, NULL);
2174 break;
2176 case STOR_LABELSYM:
2177 assert(0);
2178 break;
2180 return val;
2183 static int x86_initialization(struct symbol *sym, struct expression *expr)
2185 struct storage *val, *addr;
2186 int bits;
2188 if (!expr->ctype)
2189 return 0;
2191 bits = expr->ctype->bit_size;
2192 val = x86_expression(expr);
2193 addr = x86_symbol_expr(sym);
2194 // FIXME! The "target" expression is for bitfield store information.
2195 // Leave it NULL, which works fine.
2196 emit_store(NULL, addr, val, bits);
2197 return 0;
2200 static struct storage *x86_access(struct expression *expr)
2202 return x86_address_gen(expr);
2205 static struct storage *x86_preop(struct expression *expr)
2208 * '*' is an lvalue access, and is fundamentally different
2209 * from an arithmetic operation. Maybe it should have an
2210 * expression type of its own..
2212 if (expr->op == '*')
2213 return x86_access(expr);
2214 if (expr->op == SPECIAL_INCREMENT || expr->op == SPECIAL_DECREMENT)
2215 return emit_inc_dec(expr, 0);
2216 return emit_regular_preop(expr);
2219 static struct storage *x86_symbol_expr(struct symbol *sym)
2221 struct storage *new = stack_alloc(4);
2223 if (sym->ctype.modifiers & (MOD_TOPLEVEL | MOD_EXTERN | MOD_STATIC)) {
2224 printf("\tmovi.%d\t\tv%d,$%s\n", bits_in_pointer, new->pseudo, show_ident(sym->ident));
2225 return new;
2227 if (sym->ctype.modifiers & MOD_ADDRESSABLE) {
2228 printf("\taddi.%d\t\tv%d,vFP,$%lld\n", bits_in_pointer, new->pseudo, sym->value);
2229 return new;
2231 printf("\taddi.%d\t\tv%d,vFP,$offsetof(%s:%p)\n", bits_in_pointer, new->pseudo, show_ident(sym->ident), sym);
2232 return new;
2235 static void x86_symbol_init(struct symbol *sym)
2237 struct symbol_private *priv = sym->aux;
2238 struct expression *expr = sym->initializer;
2239 struct storage *new;
2241 if (expr)
2242 new = x86_expression(expr);
2243 else
2244 new = stack_alloc(sym->bit_size / 8);
2246 if (!priv) {
2247 priv = calloc(1, sizeof(*priv));
2248 sym->aux = priv;
2249 /* FIXME: leak! we don't free... */
2250 /* (well, we don't free symbols either) */
2253 priv->addr = new;
2256 static int type_is_signed(struct symbol *sym)
2258 if (sym->type == SYM_NODE)
2259 sym = sym->ctype.base_type;
2260 if (sym->type == SYM_PTR)
2261 return 0;
2262 return !(sym->ctype.modifiers & MOD_UNSIGNED);
2265 static struct storage *x86_label_expr(struct expression *expr)
2267 struct storage *new = stack_alloc(4);
2268 printf("\tmovi.%d\t\tv%d,.L%p\n", bits_in_pointer, new->pseudo, expr->label_symbol);
2269 return new;
2272 static struct storage *x86_statement_expr(struct expression *expr)
2274 return x86_statement(expr->statement);
2277 static int x86_position_expr(struct expression *expr, struct symbol *base)
2279 struct storage *new = x86_expression(expr->init_expr);
2280 struct symbol *ctype = expr->init_expr->ctype;
2282 printf("\tinsert v%d at [%d:%d] of %s\n", new->pseudo,
2283 expr->init_offset, ctype->bit_offset,
2284 show_ident(base->ident));
2285 return 0;
2288 static void x86_initializer_expr(struct expression *expr, struct symbol *ctype)
2290 struct expression *entry;
2292 FOR_EACH_PTR(expr->expr_list, entry) {
2293 // Nested initializers have their positions already
2294 // recursively calculated - just output them too
2295 if (entry->type == EXPR_INITIALIZER) {
2296 x86_initializer_expr(entry, ctype);
2297 continue;
2300 // Ignore initializer indexes and identifiers - the
2301 // evaluator has taken them into account
2302 if (entry->type == EXPR_IDENTIFIER || entry->type == EXPR_INDEX)
2303 continue;
2304 if (entry->type == EXPR_POS) {
2305 x86_position_expr(entry, ctype);
2306 continue;
2308 x86_initialization(ctype, entry);
2309 } END_FOR_EACH_PTR(entry);
2313 * Print out an expression. Return the pseudo that contains the
2314 * variable.
2316 static struct storage *x86_expression(struct expression *expr)
2318 if (!expr)
2319 return NULL;
2321 if (!expr->ctype) {
2322 struct position *pos = &expr->pos;
2323 printf("\tno type at %s:%d:%d\n",
2324 stream_name(pos->stream),
2325 pos->line, pos->pos);
2326 return NULL;
2329 switch (expr->type) {
2330 default:
2331 return NULL;
2332 case EXPR_CALL:
2333 return x86_call_expression(expr);
2335 case EXPR_ASSIGNMENT:
2336 return x86_assignment(expr);
2338 case EXPR_COMPARE:
2339 return emit_compare(expr);
2340 case EXPR_BINOP:
2341 case EXPR_COMMA:
2342 case EXPR_LOGICAL:
2343 return emit_binop(expr);
2344 case EXPR_PREOP:
2345 return x86_preop(expr);
2346 case EXPR_POSTOP:
2347 return emit_postop(expr);
2348 case EXPR_SYMBOL:
2349 return emit_symbol_expr_init(expr->symbol);
2350 case EXPR_DEREF:
2351 case EXPR_SIZEOF:
2352 case EXPR_ALIGNOF:
2353 warning(expr->pos, "invalid expression after evaluation");
2354 return NULL;
2355 case EXPR_CAST:
2356 case EXPR_IMPLIED_CAST:
2357 return emit_cast_expr(expr);
2358 case EXPR_VALUE:
2359 return emit_value(expr);
2360 case EXPR_STRING:
2361 return emit_string_expr(expr);
2362 case EXPR_INITIALIZER:
2363 x86_initializer_expr(expr, expr->ctype);
2364 return NULL;
2365 case EXPR_SELECT:
2366 return emit_select_expr(expr);
2367 case EXPR_CONDITIONAL:
2368 return emit_conditional_expr(expr);
2369 case EXPR_STATEMENT:
2370 return x86_statement_expr(expr);
2371 case EXPR_LABEL:
2372 return x86_label_expr(expr);
2374 // None of these should exist as direct expressions: they are only
2375 // valid as sub-expressions of initializers.
2376 case EXPR_POS:
2377 warning(expr->pos, "unable to show plain initializer position expression");
2378 return NULL;
2379 case EXPR_IDENTIFIER:
2380 warning(expr->pos, "unable to show identifier expression");
2381 return NULL;
2382 case EXPR_INDEX:
2383 warning(expr->pos, "unable to show index expression");
2384 return NULL;
2385 case EXPR_TYPE:
2386 warning(expr->pos, "unable to show type expression");
2387 return NULL;
2388 case EXPR_FVALUE:
2389 warning(expr->pos, "floating point support is not implemented");
2390 return NULL;
2392 return NULL;