separate out the *_bh() lock handling.
[smatch.git] / compile-i386.c
blobabe93131aa6f7fb9a3d9fca945d2c609a6e0c441
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 = new_storage(STOR_VALUE);
1306 val->flags = STOR_WANTS_FREE;
1307 emit_move(val, REG_EDX, NULL, NULL);
1309 new = stack_alloc(expr->ctype->bit_size / 8);
1311 /* EAX is dividend */
1312 emit_move(left, REG_EAX, NULL, NULL);
1314 reg = get_reg_value(right, &regclass_32);
1316 /* perform binop */
1317 insn("div", reg, REG_EAX, NULL);
1318 put_reg(reg);
1320 reg = REG_EAX;
1321 if (expr->op == '%')
1322 reg = REG_EDX;
1323 emit_move(reg, new, NULL, NULL);
1325 put_reg(eax_edx);
1326 emit_comment("end DIVIDE");
1327 return new;
1330 static struct storage *emit_binop(struct expression *expr)
1332 struct storage *left = x86_expression(expr->left);
1333 struct storage *right = x86_expression(expr->right);
1334 struct storage *new;
1335 struct storage *dest, *src;
1336 const char *opname = NULL;
1337 const char *suffix = NULL;
1338 char opstr[16];
1339 int is_signed;
1341 /* Divides have special register constraints */
1342 if ((expr->op == '/') || (expr->op == '%'))
1343 return emit_divide(expr, left, right);
1345 is_signed = type_is_signed(expr->ctype);
1347 switch (expr->op) {
1348 case '+':
1349 opname = "add";
1350 break;
1351 case '-':
1352 opname = "sub";
1353 break;
1354 case '&':
1355 opname = "and";
1356 break;
1357 case '|':
1358 opname = "or";
1359 break;
1360 case '^':
1361 opname = "xor";
1362 break;
1363 case SPECIAL_LEFTSHIFT:
1364 opname = "shl";
1365 break;
1366 case SPECIAL_RIGHTSHIFT:
1367 if (is_signed)
1368 opname = "sar";
1369 else
1370 opname = "shr";
1371 break;
1372 case '*':
1373 if (is_signed)
1374 opname = "imul";
1375 else
1376 opname = "mul";
1377 break;
1378 case SPECIAL_LOGICAL_AND:
1379 warning(expr->pos, "bogus bitwise and for logical op (should use '2*setne + and' or something)");
1380 opname = "and";
1381 break;
1382 case SPECIAL_LOGICAL_OR:
1383 warning(expr->pos, "bogus bitwise or for logical op (should use 'or + setne' or something)");
1384 opname = "or";
1385 break;
1386 default:
1387 error_die(expr->pos, "unhandled binop '%s'\n", show_special(expr->op));
1388 break;
1391 dest = get_reg_value(right, &regclass_32);
1392 src = get_reg_value(left, &regclass_32);
1393 switch (expr->ctype->bit_size) {
1394 case 8:
1395 suffix = "b";
1396 break;
1397 case 16:
1398 suffix = "w";
1399 break;
1400 case 32:
1401 suffix = "l";
1402 break;
1403 case 64:
1404 suffix = "q"; /* FIXME */
1405 break;
1406 default:
1407 assert(0);
1408 break;
1411 snprintf(opstr, sizeof(opstr), "%s%s", opname, suffix);
1413 /* perform binop */
1414 insn(opstr, src, dest, NULL);
1415 put_reg(src);
1417 /* store result in new pseudo / stack slot */
1418 new = stack_alloc(expr->ctype->bit_size / 8);
1419 emit_move(dest, new, NULL, "end EXPR_BINOP");
1421 put_reg(dest);
1423 return new;
1426 static int emit_conditional_test(struct storage *val)
1428 struct storage *reg;
1429 struct storage *target_val;
1430 int target_false;
1432 /* load result into EAX */
1433 emit_comment("begin if/conditional");
1434 reg = get_reg_value(val, &regclass_32);
1436 /* compare result with zero */
1437 insn("test", reg, reg, NULL);
1438 put_reg(reg);
1440 /* create conditional-failed label to jump to */
1441 target_false = new_label();
1442 target_val = new_storage(STOR_LABEL);
1443 target_val->label = target_false;
1444 target_val->flags = STOR_WANTS_FREE;
1445 insn("jz", target_val, NULL, NULL);
1447 return target_false;
1450 static int emit_conditional_end(int target_false)
1452 struct storage *cond_end_st;
1453 int cond_end;
1455 /* finished generating code for if-true statement.
1456 * add a jump-to-end jump to avoid falling through
1457 * to the if-false statement code.
1459 cond_end = new_label();
1460 cond_end_st = new_storage(STOR_LABEL);
1461 cond_end_st->label = cond_end;
1462 cond_end_st->flags = STOR_WANTS_FREE;
1463 insn("jmp", cond_end_st, NULL, NULL);
1465 /* if we have both if-true and if-false statements,
1466 * the failed-conditional case will fall through to here
1468 emit_label(target_false, NULL);
1470 return cond_end;
1473 static void emit_if_conditional(struct statement *stmt)
1475 struct storage *val;
1476 int cond_end;
1478 /* emit test portion of conditional */
1479 val = x86_expression(stmt->if_conditional);
1480 cond_end = emit_conditional_test(val);
1482 /* emit if-true statement */
1483 x86_statement(stmt->if_true);
1485 /* emit if-false statement, if present */
1486 if (stmt->if_false) {
1487 cond_end = emit_conditional_end(cond_end);
1488 x86_statement(stmt->if_false);
1491 /* end of conditional; jump target for if-true branch */
1492 emit_label(cond_end, "end if");
1495 static struct storage *emit_inc_dec(struct expression *expr, int postop)
1497 struct storage *addr = x86_address_gen(expr->unop);
1498 struct storage *retval;
1499 char opname[16];
1501 strcpy(opname, opbits(expr->op == SPECIAL_INCREMENT ? "inc" : "dec",
1502 expr->ctype->bit_size));
1504 if (postop) {
1505 struct storage *new = stack_alloc(4);
1507 emit_copy(new, addr, expr->unop->ctype);
1509 retval = new;
1510 } else
1511 retval = addr;
1513 insn(opname, addr, NULL, NULL);
1515 return retval;
1518 static struct storage *emit_postop(struct expression *expr)
1520 return emit_inc_dec(expr, 1);
1523 static struct storage *emit_return_stmt(struct statement *stmt)
1525 struct function *f = current_func;
1526 struct expression *expr = stmt->ret_value;
1527 struct storage *val = NULL, *jmplbl;
1529 if (expr && expr->ctype) {
1530 val = x86_expression(expr);
1531 assert(val != NULL);
1532 emit_move(val, REG_EAX, expr->ctype, "return");
1535 jmplbl = new_storage(STOR_LABEL);
1536 jmplbl->flags |= STOR_WANTS_FREE;
1537 jmplbl->label = f->ret_target;
1538 insn("jmp", jmplbl, NULL, NULL);
1540 return val;
1543 static struct storage *emit_conditional_expr(struct expression *expr)
1545 struct storage *cond, *true = NULL, *false = NULL;
1546 struct storage *new = stack_alloc(expr->ctype->bit_size / 8);
1547 int target_false, cond_end;
1549 /* evaluate conditional */
1550 cond = x86_expression(expr->conditional);
1551 target_false = emit_conditional_test(cond);
1553 /* handle if-true part of the expression */
1554 true = x86_expression(expr->cond_true);
1556 emit_copy(new, true, expr->ctype);
1558 cond_end = emit_conditional_end(target_false);
1560 /* handle if-false part of the expression */
1561 false = x86_expression(expr->cond_false);
1563 emit_copy(new, false, expr->ctype);
1565 /* end of conditional; jump target for if-true branch */
1566 emit_label(cond_end, "end conditional");
1568 return new;
1571 static struct storage *emit_select_expr(struct expression *expr)
1573 struct storage *cond = x86_expression(expr->conditional);
1574 struct storage *true = x86_expression(expr->cond_true);
1575 struct storage *false = x86_expression(expr->cond_false);
1576 struct storage *reg_cond, *reg_true, *reg_false;
1577 struct storage *new = stack_alloc(4);
1579 emit_comment("begin SELECT");
1580 reg_cond = get_reg_value(cond, get_regclass(expr->conditional));
1581 reg_true = get_reg_value(true, get_regclass(expr));
1582 reg_false = get_reg_value(false, get_regclass(expr));
1585 * Do the actual select: check the conditional for zero,
1586 * move false over true if zero
1588 insn("test", reg_cond, reg_cond, NULL);
1589 insn("cmovz", reg_false, reg_true, NULL);
1591 /* Store it back */
1592 emit_move(reg_true, new, expr->ctype, NULL);
1593 put_reg(reg_cond);
1594 put_reg(reg_true);
1595 put_reg(reg_false);
1596 emit_comment("end SELECT");
1597 return new;
1600 static struct storage *emit_symbol_expr_init(struct symbol *sym)
1602 struct expression *expr = sym->initializer;
1603 struct symbol_private *priv = sym->aux;
1605 if (priv == NULL) {
1606 priv = calloc(1, sizeof(*priv));
1607 sym->aux = priv;
1609 if (expr == NULL) {
1610 struct storage *new = stack_alloc(4);
1611 fprintf(stderr, "FIXME! no value for symbol %s. creating pseudo %d (stack offset %d)\n",
1612 show_ident(sym->ident),
1613 new->pseudo, new->pseudo * 4);
1614 priv->addr = new;
1615 } else {
1616 priv->addr = x86_expression(expr);
1620 return priv->addr;
1623 static struct storage *emit_string_expr(struct expression *expr)
1625 struct function *f = current_func;
1626 int label = new_label();
1627 struct storage *new;
1629 push_cstring(f, expr->string, label);
1631 new = new_storage(STOR_LABEL);
1632 new->label = label;
1633 new->flags = STOR_LABEL_VAL | STOR_WANTS_FREE;
1634 return new;
1637 static struct storage *emit_cast_expr(struct expression *expr)
1639 struct symbol *old_type, *new_type;
1640 struct storage *op = x86_expression(expr->cast_expression);
1641 int oldbits, newbits;
1642 struct storage *new;
1644 old_type = expr->cast_expression->ctype;
1645 new_type = expr->cast_type;
1647 oldbits = old_type->bit_size;
1648 newbits = new_type->bit_size;
1649 if (oldbits >= newbits)
1650 return op;
1652 emit_move(op, REG_EAX, old_type, "begin cast ..");
1654 new = stack_alloc(newbits / 8);
1655 emit_move(REG_EAX, new, new_type, ".... end cast");
1657 return new;
1660 static struct storage *emit_regular_preop(struct expression *expr)
1662 struct storage *target = x86_expression(expr->unop);
1663 struct storage *val, *new = stack_alloc(4);
1664 const char *opname = NULL;
1666 switch (expr->op) {
1667 case '!':
1668 val = new_storage(STOR_VALUE);
1669 val->flags = STOR_WANTS_FREE;
1670 emit_move(val, REG_EDX, NULL, NULL);
1671 emit_move(target, REG_EAX, expr->unop->ctype, NULL);
1672 insn("test", REG_EAX, REG_EAX, NULL);
1673 insn("setz", REG_DL, NULL, NULL);
1674 emit_move(REG_EDX, new, expr->unop->ctype, NULL);
1676 break;
1677 case '~':
1678 opname = "not";
1679 case '-':
1680 if (!opname)
1681 opname = "neg";
1682 emit_move(target, REG_EAX, expr->unop->ctype, NULL);
1683 insn(opname, REG_EAX, NULL, NULL);
1684 emit_move(REG_EAX, new, expr->unop->ctype, NULL);
1685 break;
1686 default:
1687 assert(0);
1688 break;
1691 return new;
1694 static void emit_case_statement(struct statement *stmt)
1696 emit_labelsym(stmt->case_label, NULL);
1697 x86_statement(stmt->case_statement);
1700 static void emit_switch_statement(struct statement *stmt)
1702 struct storage *val = x86_expression(stmt->switch_expression);
1703 struct symbol *sym, *default_sym = NULL;
1704 struct storage *labelsym, *label;
1705 int switch_end = 0;
1707 emit_move(val, REG_EAX, stmt->switch_expression->ctype, "begin case");
1710 * This is where a _real_ back-end would go through the
1711 * cases to decide whether to use a lookup table or a
1712 * series of comparisons etc
1714 FOR_EACH_PTR(stmt->switch_case->symbol_list, sym) {
1715 struct statement *case_stmt = sym->stmt;
1716 struct expression *expr = case_stmt->case_expression;
1717 struct expression *to = case_stmt->case_to;
1719 /* default: */
1720 if (!expr)
1721 default_sym = sym;
1723 /* case NNN: */
1724 else {
1725 struct storage *case_val = new_val(expr->value);
1727 assert (expr->type == EXPR_VALUE);
1729 insn("cmpl", case_val, REG_EAX, NULL);
1731 if (!to) {
1732 labelsym = new_labelsym(sym);
1733 insn("je", labelsym, NULL, NULL);
1734 } else {
1735 int next_test;
1737 label = new_storage(STOR_LABEL);
1738 label->flags |= STOR_WANTS_FREE;
1739 label->label = next_test = new_label();
1741 /* FIXME: signed/unsigned */
1742 insn("jl", label, NULL, NULL);
1744 case_val = new_val(to->value);
1745 insn("cmpl", case_val, REG_EAX, NULL);
1747 /* TODO: implement and use refcounting... */
1748 label = new_storage(STOR_LABEL);
1749 label->flags |= STOR_WANTS_FREE;
1750 label->label = next_test;
1752 /* FIXME: signed/unsigned */
1753 insn("jg", label, NULL, NULL);
1755 labelsym = new_labelsym(sym);
1756 insn("jmp", labelsym, NULL, NULL);
1758 emit_label(next_test, NULL);
1761 } END_FOR_EACH_PTR(sym);
1763 if (default_sym) {
1764 labelsym = new_labelsym(default_sym);
1765 insn("jmp", labelsym, NULL, "default");
1766 } else {
1767 label = new_storage(STOR_LABEL);
1768 label->flags |= STOR_WANTS_FREE;
1769 label->label = switch_end = new_label();
1770 insn("jmp", label, NULL, "goto end of switch");
1773 x86_statement(stmt->switch_statement);
1775 if (stmt->switch_break->used)
1776 emit_labelsym(stmt->switch_break, NULL);
1778 if (switch_end)
1779 emit_label(switch_end, NULL);
1782 static void x86_struct_member(struct symbol *sym)
1784 printf("\t%s:%d:%ld at offset %ld.%d", show_ident(sym->ident), sym->bit_size, sym->ctype.alignment, sym->offset, sym->bit_offset);
1785 printf("\n");
1788 static void x86_symbol(struct symbol *sym)
1790 struct symbol *type;
1792 if (!sym)
1793 return;
1795 type = sym->ctype.base_type;
1796 if (!type)
1797 return;
1800 * Show actual implementation information
1802 switch (type->type) {
1804 case SYM_ARRAY:
1805 if (sym->initializer)
1806 emit_array(sym);
1807 else
1808 emit_array_noinit(sym);
1809 break;
1811 case SYM_BASETYPE:
1812 if (sym->initializer) {
1813 emit_object_pre(show_ident(sym->ident),
1814 sym->ctype.modifiers,
1815 sym->ctype.alignment,
1816 sym->bit_size / 8);
1817 emit_scalar(sym->initializer, sym->bit_size);
1818 stor_sym_init(sym);
1819 } else
1820 emit_scalar_noinit(sym);
1821 break;
1823 case SYM_STRUCT:
1824 case SYM_UNION: {
1825 struct symbol *member;
1827 printf(" {\n");
1828 FOR_EACH_PTR(type->symbol_list, member) {
1829 x86_struct_member(member);
1830 } END_FOR_EACH_PTR(member);
1831 printf("}\n");
1832 break;
1835 case SYM_FN: {
1836 struct statement *stmt = type->stmt;
1837 if (stmt) {
1838 emit_func_pre(sym);
1839 x86_statement(stmt);
1840 emit_func_post(sym);
1842 break;
1845 default:
1846 break;
1849 if (sym->initializer && (type->type != SYM_BASETYPE) &&
1850 (type->type != SYM_ARRAY)) {
1851 printf(" = \n");
1852 x86_expression(sym->initializer);
1856 static void x86_symbol_init(struct symbol *sym);
1858 static void x86_symbol_decl(struct symbol_list *syms)
1860 struct symbol *sym;
1861 FOR_EACH_PTR(syms, sym) {
1862 x86_symbol_init(sym);
1863 } END_FOR_EACH_PTR(sym);
1866 static void loopstk_push(int cont_lbl, int loop_bottom_lbl)
1868 struct function *f = current_func;
1869 struct loop_stack *ls;
1871 ls = malloc(sizeof(*ls));
1872 ls->continue_lbl = cont_lbl;
1873 ls->loop_bottom_lbl = loop_bottom_lbl;
1874 ls->next = f->loop_stack;
1875 f->loop_stack = ls;
1878 static void loopstk_pop(void)
1880 struct function *f = current_func;
1881 struct loop_stack *ls;
1883 assert(f->loop_stack != NULL);
1884 ls = f->loop_stack;
1885 f->loop_stack = f->loop_stack->next;
1886 free(ls);
1889 static int loopstk_break(void)
1891 return current_func->loop_stack->loop_bottom_lbl;
1894 static int loopstk_continue(void)
1896 return current_func->loop_stack->continue_lbl;
1899 static void emit_loop(struct statement *stmt)
1901 struct statement *pre_statement = stmt->iterator_pre_statement;
1902 struct expression *pre_condition = stmt->iterator_pre_condition;
1903 struct statement *statement = stmt->iterator_statement;
1904 struct statement *post_statement = stmt->iterator_post_statement;
1905 struct expression *post_condition = stmt->iterator_post_condition;
1906 int loop_top = 0, loop_bottom, loop_continue;
1907 int have_bottom = 0;
1908 struct storage *val;
1910 loop_bottom = new_label();
1911 loop_continue = new_label();
1912 loopstk_push(loop_continue, loop_bottom);
1914 x86_symbol_decl(stmt->iterator_syms);
1915 x86_statement(pre_statement);
1916 if (!post_condition || post_condition->type != EXPR_VALUE || post_condition->value) {
1917 loop_top = new_label();
1918 emit_label(loop_top, "loop top");
1920 if (pre_condition) {
1921 if (pre_condition->type == EXPR_VALUE) {
1922 if (!pre_condition->value) {
1923 struct storage *lbv;
1924 lbv = new_storage(STOR_LABEL);
1925 lbv->label = loop_bottom;
1926 lbv->flags = STOR_WANTS_FREE;
1927 insn("jmp", lbv, NULL, "go to loop bottom");
1928 have_bottom = 1;
1930 } else {
1931 struct storage *lbv = new_storage(STOR_LABEL);
1932 lbv->label = loop_bottom;
1933 lbv->flags = STOR_WANTS_FREE;
1934 have_bottom = 1;
1936 val = x86_expression(pre_condition);
1938 emit_move(val, REG_EAX, NULL, "loop pre condition");
1939 insn("test", REG_EAX, REG_EAX, NULL);
1940 insn("jz", lbv, NULL, NULL);
1943 x86_statement(statement);
1944 if (stmt->iterator_continue->used)
1945 emit_label(loop_continue, "'continue' iterator");
1946 x86_statement(post_statement);
1947 if (!post_condition) {
1948 struct storage *lbv = new_storage(STOR_LABEL);
1949 lbv->label = loop_top;
1950 lbv->flags = STOR_WANTS_FREE;
1951 insn("jmp", lbv, NULL, "go to loop top");
1952 } else if (post_condition->type == EXPR_VALUE) {
1953 if (post_condition->value) {
1954 struct storage *lbv = new_storage(STOR_LABEL);
1955 lbv->label = loop_top;
1956 lbv->flags = STOR_WANTS_FREE;
1957 insn("jmp", lbv, NULL, "go to loop top");
1959 } else {
1960 struct storage *lbv = new_storage(STOR_LABEL);
1961 lbv->label = loop_top;
1962 lbv->flags = STOR_WANTS_FREE;
1964 val = x86_expression(post_condition);
1966 emit_move(val, REG_EAX, NULL, "loop post condition");
1967 insn("test", REG_EAX, REG_EAX, NULL);
1968 insn("jnz", lbv, NULL, NULL);
1970 if (have_bottom || stmt->iterator_break->used)
1971 emit_label(loop_bottom, "loop bottom");
1973 loopstk_pop();
1977 * Print out a statement
1979 static struct storage *x86_statement(struct statement *stmt)
1981 if (!stmt)
1982 return NULL;
1983 switch (stmt->type) {
1984 default:
1985 return NULL;
1986 case STMT_RETURN:
1987 return emit_return_stmt(stmt);
1988 case STMT_DECLARATION:
1989 x86_symbol_decl(stmt->declaration);
1990 break;
1991 case STMT_COMPOUND: {
1992 struct statement *s;
1993 struct storage *last = NULL;
1995 FOR_EACH_PTR(stmt->stmts, s) {
1996 last = x86_statement(s);
1997 } END_FOR_EACH_PTR(s);
1999 return last;
2002 case STMT_EXPRESSION:
2003 return x86_expression(stmt->expression);
2004 case STMT_IF:
2005 emit_if_conditional(stmt);
2006 return NULL;
2008 case STMT_CASE:
2009 emit_case_statement(stmt);
2010 break;
2011 case STMT_SWITCH:
2012 emit_switch_statement(stmt);
2013 break;
2015 case STMT_ITERATOR:
2016 emit_loop(stmt);
2017 break;
2019 case STMT_NONE:
2020 break;
2022 case STMT_LABEL:
2023 printf(".L%p:\n", stmt->label_identifier);
2024 x86_statement(stmt->label_statement);
2025 break;
2027 case STMT_GOTO:
2028 if (stmt->goto_expression) {
2029 struct storage *val = x86_expression(stmt->goto_expression);
2030 printf("\tgoto *v%d\n", val->pseudo);
2031 } else if (!strcmp("break", show_ident(stmt->goto_label->ident))) {
2032 struct storage *lbv = new_storage(STOR_LABEL);
2033 lbv->label = loopstk_break();
2034 lbv->flags = STOR_WANTS_FREE;
2035 insn("jmp", lbv, NULL, "'break'; go to loop bottom");
2036 } else if (!strcmp("continue", show_ident(stmt->goto_label->ident))) {
2037 struct storage *lbv = new_storage(STOR_LABEL);
2038 lbv->label = loopstk_continue();
2039 lbv->flags = STOR_WANTS_FREE;
2040 insn("jmp", lbv, NULL, "'continue'; go to loop top");
2041 } else {
2042 struct storage *labelsym = new_labelsym(stmt->goto_label);
2043 insn("jmp", labelsym, NULL, NULL);
2045 break;
2046 case STMT_ASM:
2047 printf("\tasm( .... )\n");
2048 break;
2050 return NULL;
2053 static struct storage *x86_call_expression(struct expression *expr)
2055 struct function *f = current_func;
2056 struct symbol *direct;
2057 struct expression *arg, *fn;
2058 struct storage *retval, *fncall;
2059 int framesize;
2060 char s[64];
2062 if (!expr->ctype) {
2063 warning(expr->pos, "\tcall with no type!");
2064 return NULL;
2067 framesize = 0;
2068 FOR_EACH_PTR_REVERSE(expr->args, arg) {
2069 struct storage *new = x86_expression(arg);
2070 int size = arg->ctype->bit_size;
2073 * FIXME: i386 SysV ABI dictates that values
2074 * smaller than 32 bits should be placed onto
2075 * the stack as 32-bit objects. We should not
2076 * blindly do a 32-bit push on objects smaller
2077 * than 32 bits.
2079 if (size < 32)
2080 size = 32;
2081 insn("pushl", new, NULL,
2082 !framesize ? "begin function call" : NULL);
2084 framesize += bits_to_bytes(size);
2085 } END_FOR_EACH_PTR_REVERSE(arg);
2087 fn = expr->fn;
2089 /* Remove dereference, if any */
2090 direct = NULL;
2091 if (fn->type == EXPR_PREOP) {
2092 if (fn->unop->type == EXPR_SYMBOL) {
2093 struct symbol *sym = fn->unop->symbol;
2094 if (sym->ctype.base_type->type == SYM_FN)
2095 direct = sym;
2098 if (direct) {
2099 struct storage *direct_stor = new_storage(STOR_SYM);
2100 direct_stor->flags |= STOR_WANTS_FREE;
2101 direct_stor->sym = direct;
2102 insn("call", direct_stor, NULL, NULL);
2103 } else {
2104 fncall = x86_expression(fn);
2105 emit_move(fncall, REG_EAX, fn->ctype, NULL);
2107 strcpy(s, "\tcall\t*%eax\n");
2108 push_text_atom(f, s);
2111 /* FIXME: pay attention to BITS_IN_POINTER */
2112 if (framesize) {
2113 struct storage *val = new_storage(STOR_VALUE);
2114 val->value = (long long) framesize;
2115 val->flags = STOR_WANTS_FREE;
2116 insn("addl", val, REG_ESP, NULL);
2119 retval = stack_alloc(4);
2120 emit_move(REG_EAX, retval, NULL, "end function call");
2122 return retval;
2125 static struct storage *x86_address_gen(struct expression *expr)
2127 struct function *f = current_func;
2128 struct storage *addr;
2129 struct storage *new;
2130 char s[32];
2132 addr = x86_expression(expr->unop);
2133 if (expr->unop->type == EXPR_SYMBOL)
2134 return addr;
2136 emit_move(addr, REG_EAX, NULL, "begin deref ..");
2138 /* FIXME: operand size */
2139 strcpy(s, "\tmovl\t(%eax), %ecx\n");
2140 push_text_atom(f, s);
2142 new = stack_alloc(4);
2143 emit_move(REG_ECX, new, NULL, ".... end deref");
2145 return new;
2148 static struct storage *x86_assignment(struct expression *expr)
2150 struct expression *target = expr->left;
2151 struct storage *val, *addr;
2153 if (!expr->ctype)
2154 return NULL;
2156 val = x86_expression(expr->right);
2157 addr = x86_address_gen(target);
2159 switch (val->type) {
2160 /* copy, where both operands are memory */
2161 case STOR_PSEUDO:
2162 case STOR_ARG:
2163 emit_copy(addr, val, expr->ctype);
2164 break;
2166 /* copy, one or zero operands are memory */
2167 case STOR_REG:
2168 case STOR_SYM:
2169 case STOR_VALUE:
2170 case STOR_LABEL:
2171 emit_move(val, addr, expr->left->ctype, NULL);
2172 break;
2174 case STOR_LABELSYM:
2175 assert(0);
2176 break;
2178 return val;
2181 static int x86_initialization(struct symbol *sym, struct expression *expr)
2183 struct storage *val, *addr;
2184 int bits;
2186 if (!expr->ctype)
2187 return 0;
2189 bits = expr->ctype->bit_size;
2190 val = x86_expression(expr);
2191 addr = x86_symbol_expr(sym);
2192 // FIXME! The "target" expression is for bitfield store information.
2193 // Leave it NULL, which works fine.
2194 emit_store(NULL, addr, val, bits);
2195 return 0;
2198 static struct storage *x86_access(struct expression *expr)
2200 return x86_address_gen(expr);
2203 static struct storage *x86_preop(struct expression *expr)
2206 * '*' is an lvalue access, and is fundamentally different
2207 * from an arithmetic operation. Maybe it should have an
2208 * expression type of its own..
2210 if (expr->op == '*')
2211 return x86_access(expr);
2212 if (expr->op == SPECIAL_INCREMENT || expr->op == SPECIAL_DECREMENT)
2213 return emit_inc_dec(expr, 0);
2214 return emit_regular_preop(expr);
2217 static struct storage *x86_symbol_expr(struct symbol *sym)
2219 struct storage *new = stack_alloc(4);
2221 if (sym->ctype.modifiers & (MOD_TOPLEVEL | MOD_EXTERN | MOD_STATIC)) {
2222 printf("\tmovi.%d\t\tv%d,$%s\n", bits_in_pointer, new->pseudo, show_ident(sym->ident));
2223 return new;
2225 if (sym->ctype.modifiers & MOD_ADDRESSABLE) {
2226 printf("\taddi.%d\t\tv%d,vFP,$%lld\n", bits_in_pointer, new->pseudo, sym->value);
2227 return new;
2229 printf("\taddi.%d\t\tv%d,vFP,$offsetof(%s:%p)\n", bits_in_pointer, new->pseudo, show_ident(sym->ident), sym);
2230 return new;
2233 static void x86_symbol_init(struct symbol *sym)
2235 struct symbol_private *priv = sym->aux;
2236 struct expression *expr = sym->initializer;
2237 struct storage *new;
2239 if (expr)
2240 new = x86_expression(expr);
2241 else
2242 new = stack_alloc(sym->bit_size / 8);
2244 if (!priv) {
2245 priv = calloc(1, sizeof(*priv));
2246 sym->aux = priv;
2247 /* FIXME: leak! we don't free... */
2248 /* (well, we don't free symbols either) */
2251 priv->addr = new;
2254 static int type_is_signed(struct symbol *sym)
2256 if (sym->type == SYM_NODE)
2257 sym = sym->ctype.base_type;
2258 if (sym->type == SYM_PTR)
2259 return 0;
2260 return !(sym->ctype.modifiers & MOD_UNSIGNED);
2263 static struct storage *x86_label_expr(struct expression *expr)
2265 struct storage *new = stack_alloc(4);
2266 printf("\tmovi.%d\t\tv%d,.L%p\n", bits_in_pointer, new->pseudo, expr->label_symbol);
2267 return new;
2270 static struct storage *x86_statement_expr(struct expression *expr)
2272 return x86_statement(expr->statement);
2275 static int x86_position_expr(struct expression *expr, struct symbol *base)
2277 struct storage *new = x86_expression(expr->init_expr);
2278 struct symbol *ctype = expr->init_expr->ctype;
2280 printf("\tinsert v%d at [%d:%d] of %s\n", new->pseudo,
2281 expr->init_offset, ctype->bit_offset,
2282 show_ident(base->ident));
2283 return 0;
2286 static void x86_initializer_expr(struct expression *expr, struct symbol *ctype)
2288 struct expression *entry;
2290 FOR_EACH_PTR(expr->expr_list, entry) {
2291 // Nested initializers have their positions already
2292 // recursively calculated - just output them too
2293 if (entry->type == EXPR_INITIALIZER) {
2294 x86_initializer_expr(entry, ctype);
2295 continue;
2298 // Ignore initializer indexes and identifiers - the
2299 // evaluator has taken them into account
2300 if (entry->type == EXPR_IDENTIFIER || entry->type == EXPR_INDEX)
2301 continue;
2302 if (entry->type == EXPR_POS) {
2303 x86_position_expr(entry, ctype);
2304 continue;
2306 x86_initialization(ctype, entry);
2307 } END_FOR_EACH_PTR(entry);
2311 * Print out an expression. Return the pseudo that contains the
2312 * variable.
2314 static struct storage *x86_expression(struct expression *expr)
2316 if (!expr)
2317 return NULL;
2319 if (!expr->ctype) {
2320 struct position *pos = &expr->pos;
2321 printf("\tno type at %s:%d:%d\n",
2322 stream_name(pos->stream),
2323 pos->line, pos->pos);
2324 return NULL;
2327 switch (expr->type) {
2328 default:
2329 return NULL;
2330 case EXPR_CALL:
2331 return x86_call_expression(expr);
2333 case EXPR_ASSIGNMENT:
2334 return x86_assignment(expr);
2336 case EXPR_COMPARE:
2337 return emit_compare(expr);
2338 case EXPR_BINOP:
2339 case EXPR_COMMA:
2340 case EXPR_LOGICAL:
2341 return emit_binop(expr);
2342 case EXPR_PREOP:
2343 return x86_preop(expr);
2344 case EXPR_POSTOP:
2345 return emit_postop(expr);
2346 case EXPR_SYMBOL:
2347 return emit_symbol_expr_init(expr->symbol);
2348 case EXPR_DEREF:
2349 case EXPR_SIZEOF:
2350 case EXPR_ALIGNOF:
2351 warning(expr->pos, "invalid expression after evaluation");
2352 return NULL;
2353 case EXPR_CAST:
2354 case EXPR_FORCE_CAST:
2355 case EXPR_IMPLIED_CAST:
2356 return emit_cast_expr(expr);
2357 case EXPR_VALUE:
2358 return emit_value(expr);
2359 case EXPR_STRING:
2360 return emit_string_expr(expr);
2361 case EXPR_INITIALIZER:
2362 x86_initializer_expr(expr, expr->ctype);
2363 return NULL;
2364 case EXPR_SELECT:
2365 return emit_select_expr(expr);
2366 case EXPR_CONDITIONAL:
2367 return emit_conditional_expr(expr);
2368 case EXPR_STATEMENT:
2369 return x86_statement_expr(expr);
2370 case EXPR_LABEL:
2371 return x86_label_expr(expr);
2373 // None of these should exist as direct expressions: they are only
2374 // valid as sub-expressions of initializers.
2375 case EXPR_POS:
2376 warning(expr->pos, "unable to show plain initializer position expression");
2377 return NULL;
2378 case EXPR_IDENTIFIER:
2379 warning(expr->pos, "unable to show identifier expression");
2380 return NULL;
2381 case EXPR_INDEX:
2382 warning(expr->pos, "unable to show index expression");
2383 return NULL;
2384 case EXPR_TYPE:
2385 warning(expr->pos, "unable to show type expression");
2386 return NULL;
2387 case EXPR_FVALUE:
2388 warning(expr->pos, "floating point support is not implemented");
2389 return NULL;
2391 return NULL;