[PATCH] evaluate_sign() typo
[smatch.git] / compile-i386.c
blob741718151c1e89c781e05eea1bb2830140b177e8
1 /*
2 * sparse/compile-i386.c
4 * Copyright (C) 2003 Transmeta Corp.
5 * 2003 Linus Torvalds
6 * Copyright 2003 Jeff Garzik
8 * Licensed under the Open Software License version 1.1
10 * x86 backend
12 * TODO list:
13 * in general, any non-32bit SYM_BASETYPE is unlikely to work.
14 * complex initializers
15 * bitfields
16 * global struct/union variables
17 * addressing structures, and members of structures (as opposed to
18 * scalars) on the stack. Requires smarter stack frame allocation.
19 * labels / goto
20 * any function argument that isn't 32 bits (or promoted to such)
21 * inline asm
22 * floating point
25 #include <stdarg.h>
26 #include <stdlib.h>
27 #include <stdio.h>
28 #include <string.h>
29 #include <ctype.h>
30 #include <unistd.h>
31 #include <fcntl.h>
32 #include <assert.h>
34 #include "lib.h"
35 #include "token.h"
36 #include "parse.h"
37 #include "symbol.h"
38 #include "scope.h"
39 #include "expression.h"
40 #include "target.h"
41 #include "compile.h"
42 #include "bitmap.h"
44 struct textbuf {
45 unsigned int len; /* does NOT include terminating null */
46 char *text;
47 struct textbuf *next;
48 struct textbuf *prev;
51 struct loop_stack {
52 int continue_lbl;
53 int loop_bottom_lbl;
54 struct loop_stack *next;
57 struct function {
58 int stack_size;
59 int pseudo_nr;
60 struct ptr_list *pseudo_list;
61 struct ptr_list *atom_list;
62 struct ptr_list *str_list;
63 struct loop_stack *loop_stack;
64 struct symbol **argv;
65 unsigned int argc;
66 int ret_target;
69 enum storage_type {
70 STOR_PSEUDO, /* variable stored on the stack */
71 STOR_ARG, /* function argument */
72 STOR_SYM, /* a symbol we can directly ref in the asm */
73 STOR_REG, /* scratch register */
74 STOR_VALUE, /* integer constant */
75 STOR_LABEL, /* label / jump target */
76 STOR_LABELSYM, /* label generated from symbol's pointer value */
79 struct reg_info {
80 const char *name;
81 struct storage *contains;
82 const unsigned char aliases[12];
83 #define own_regno aliases[0]
86 struct storage {
87 enum storage_type type;
88 unsigned long flags;
90 /* STOR_REG */
91 struct reg_info *reg;
92 struct symbol *ctype;
94 union {
95 /* STOR_PSEUDO */
96 struct {
97 int pseudo;
98 int offset;
99 int size;
101 /* STOR_ARG */
102 struct {
103 int idx;
105 /* STOR_SYM */
106 struct {
107 struct symbol *sym;
109 /* STOR_VALUE */
110 struct {
111 long long value;
113 /* STOR_LABEL */
114 struct {
115 int label;
117 /* STOR_LABELSYM */
118 struct {
119 struct symbol *labelsym;
124 enum {
125 STOR_LABEL_VAL = (1 << 0),
126 STOR_WANTS_FREE = (1 << 1),
129 struct symbol_private {
130 struct storage *addr;
133 enum atom_type {
134 ATOM_TEXT,
135 ATOM_INSN,
136 ATOM_CSTR,
139 struct atom {
140 enum atom_type type;
141 union {
142 /* stuff for text */
143 struct {
144 char *text;
145 unsigned int text_len; /* w/o terminating null */
148 /* stuff for insns */
149 struct {
150 char insn[32];
151 char comment[40];
152 struct storage *op1;
153 struct storage *op2;
156 /* stuff for C strings */
157 struct {
158 struct string *string;
159 int label;
165 struct function *current_func = NULL;
166 struct textbuf *unit_post_text = NULL;
167 static const char *current_section;
169 static void emit_comment(const char * fmt, ...);
170 static void emit_move(struct storage *src, struct storage *dest,
171 struct symbol *ctype, const char *comment);
172 static int type_is_signed(struct symbol *sym);
173 static struct storage *x86_address_gen(struct expression *expr);
174 static struct storage *x86_symbol_expr(struct symbol *sym);
175 static void x86_symbol(struct symbol *sym);
176 static struct storage *x86_statement(struct statement *stmt);
177 static struct storage *x86_expression(struct expression *expr);
179 enum registers {
180 NOREG,
181 AL, DL, CL, BL, AH, DH, CH, BH, // 8-bit
182 AX, DX, CX, BX, SI, DI, BP, SP, // 16-bit
183 EAX, EDX, ECX, EBX, ESI, EDI, EBP, ESP, // 32-bit
184 EAX_EDX, ECX_EBX, ESI_EDI, // 64-bit
187 /* This works on regno's, reg_info's and hardreg_storage's */
188 #define byte_reg(reg) ((reg) - 16)
189 #define highbyte_reg(reg) ((reg)-12)
190 #define word_reg(reg) ((reg)-8)
192 #define REGINFO(nr, str, conflicts...) [nr] = { .name = str, .aliases = { nr , conflicts } }
194 static struct reg_info reg_info_table[] = {
195 REGINFO( AL, "%al", AX, EAX, EAX_EDX),
196 REGINFO( DL, "%dl", DX, EDX, EAX_EDX),
197 REGINFO( CL, "%cl", CX, ECX, ECX_EBX),
198 REGINFO( BL, "%bl", BX, EBX, ECX_EBX),
199 REGINFO( AH, "%ah", AX, EAX, EAX_EDX),
200 REGINFO( DH, "%dh", DX, EDX, EAX_EDX),
201 REGINFO( CH, "%ch", CX, ECX, ECX_EBX),
202 REGINFO( BH, "%bh", BX, EBX, ECX_EBX),
203 REGINFO( AX, "%ax", AL, AH, EAX, EAX_EDX),
204 REGINFO( DX, "%dx", DL, DH, EDX, EAX_EDX),
205 REGINFO( CX, "%cx", CL, CH, ECX, ECX_EBX),
206 REGINFO( BX, "%bx", BL, BH, EBX, ECX_EBX),
207 REGINFO( SI, "%si", ESI, ESI_EDI),
208 REGINFO( DI, "%di", EDI, ESI_EDI),
209 REGINFO( BP, "%bp", EBP),
210 REGINFO( SP, "%sp", ESP),
211 REGINFO(EAX, "%eax", AL, AH, AX, EAX_EDX),
212 REGINFO(EDX, "%edx", DL, DH, DX, EAX_EDX),
213 REGINFO(ECX, "%ecx", CL, CH, CX, ECX_EBX),
214 REGINFO(EBX, "%ebx", BL, BH, BX, ECX_EBX),
215 REGINFO(ESI, "%esi", SI, ESI_EDI),
216 REGINFO(EDI, "%edi", DI, ESI_EDI),
217 REGINFO(EBP, "%ebp", BP),
218 REGINFO(ESP, "%esp", SP),
219 REGINFO(EAX_EDX, "%eax:%edx", AL, AH, AX, EAX, DL, DH, DX, EDX),
220 REGINFO(ECX_EBX, "%ecx:%ebx", CL, CH, CX, ECX, BL, BH, BX, EBX),
221 REGINFO(ESI_EDI, "%esi:%edi", SI, ESI, DI, EDI),
224 #define REGSTORAGE(nr) [nr] = { .type = STOR_REG, .reg = reg_info_table + (nr) }
226 static struct storage hardreg_storage_table[] = {
227 REGSTORAGE(AL), REGSTORAGE(DL), REGSTORAGE(CL), REGSTORAGE(BL),
228 REGSTORAGE(AH), REGSTORAGE(DH), REGSTORAGE(CH), REGSTORAGE(BH),
229 REGSTORAGE(AX), REGSTORAGE(DX), REGSTORAGE(CX), REGSTORAGE(BX),
230 REGSTORAGE(SI), REGSTORAGE(DI), REGSTORAGE(BP), REGSTORAGE(SP),
231 REGSTORAGE(EAX), REGSTORAGE(EDX), REGSTORAGE(ECX), REGSTORAGE(EBX),
232 REGSTORAGE(ESI), REGSTORAGE(EDI), REGSTORAGE(EBP), REGSTORAGE(ESP),
233 REGSTORAGE(EAX_EDX), REGSTORAGE(ECX_EBX), REGSTORAGE(ESI_EDI),
236 #define REG_EAX (&hardreg_storage_table[EAX])
237 #define REG_ECX (&hardreg_storage_table[ECX])
238 #define REG_EDX (&hardreg_storage_table[EDX])
239 #define REG_ESP (&hardreg_storage_table[ESP])
240 #define REG_DL (&hardreg_storage_table[DL])
241 #define REG_DX (&hardreg_storage_table[DX])
242 #define REG_AL (&hardreg_storage_table[AL])
243 #define REG_AX (&hardreg_storage_table[AX])
245 DECLARE_BITMAP(regs_in_use, 256);
247 static inline struct storage * reginfo_reg(struct reg_info *info)
249 return hardreg_storage_table + info->own_regno;
252 struct storage * get_hardreg(struct storage *reg, int clear)
254 struct reg_info *info = reg->reg;
255 const unsigned char *aliases;
256 int regno;
258 aliases = info->aliases;
259 while ((regno = *aliases++) != NOREG) {
260 if (test_bit(regno, regs_in_use))
261 goto busy;
262 if (clear)
263 reg_info_table[regno].contains = NULL;
265 set_bit(info->own_regno, regs_in_use);
266 return reg;
267 busy:
268 fprintf(stderr, "register %s is busy\n", info->name);
269 if (regno + reg_info_table != info)
270 fprintf(stderr, " conflicts with %s\n", reg_info_table[regno].name);
271 exit(1);
274 void put_reg(struct storage *reg)
276 struct reg_info *info = reg->reg;
277 int regno = info->own_regno;
279 if (test_and_clear_bit(regno, regs_in_use))
280 return;
281 fprintf(stderr, "freeing already free'd register %s\n", reg_info_table[regno].name);
284 struct regclass {
285 const char *name;
286 const unsigned char regs[30];
289 struct regclass regclass_8 = { "8-bit", { AL, DL, CL, BL, AH, DH, CH, BH }};
290 struct regclass regclass_16 = { "16-bit", { AX, DX, CX, BX, SI, DI, BP }};
291 struct regclass regclass_32 = { "32-bit", { EAX, EDX, ECX, EBX, ESI, EDI, EBP }};
292 struct regclass regclass_64 = { "64-bit", { EAX_EDX, ECX_EBX, ESI_EDI }};
294 struct regclass regclass_32_8 = { "32-bit bytes", { EAX, EDX, ECX, EBX }};
296 static struct regclass *get_regclass_bits(int bits)
298 switch (bits) {
299 case 8: return &regclass_8;
300 case 16: return &regclass_16;
301 case 64: return &regclass_64;
302 default: return &regclass_32;
306 static struct regclass *get_regclass(struct expression *expr)
308 return get_regclass_bits(expr->ctype->bit_size);
311 static int register_busy(int regno)
313 if (!test_bit(regno, regs_in_use)) {
314 struct reg_info *info = reg_info_table + regno;
315 const unsigned char *regs = info->aliases+1;
317 while ((regno = *regs) != NOREG) {
318 regs++;
319 if (test_bit(regno, regs_in_use))
320 goto busy;
322 return 0;
324 busy:
325 return 1;
328 struct storage *get_reg(struct regclass *class)
330 const unsigned char *regs = class->regs;
331 int regno;
333 while ((regno = *regs) != NOREG) {
334 regs++;
335 if (register_busy(regno))
336 continue;
337 return get_hardreg(hardreg_storage_table + regno, 1);
339 fprintf(stderr, "Ran out of %s registers\n", class->name);
340 exit(1);
343 struct storage *get_reg_value(struct storage *value, struct regclass *class)
345 struct reg_info *info;
346 struct storage *reg;
348 /* Do we already have it somewhere */
349 info = value->reg;
350 if (info && info->contains == value) {
351 emit_comment("already have register %s", info->name);
352 return get_hardreg(hardreg_storage_table + info->own_regno, 0);
355 reg = get_reg(class);
356 emit_move(value, reg, value->ctype, "reload register");
357 info = reg->reg;
358 info->contains = value;
359 value->reg = info;
360 return reg;
363 static struct storage *temp_from_bits(unsigned int bit_size)
365 return get_reg(get_regclass_bits(bit_size));
368 static inline unsigned int pseudo_offset(struct storage *s)
370 if (s->type != STOR_PSEUDO)
371 return 123456; /* intentionally bogus value */
373 return s->offset;
376 static inline unsigned int arg_offset(struct storage *s)
378 if (s->type != STOR_ARG)
379 return 123456; /* intentionally bogus value */
381 /* FIXME: this is wrong wrong wrong */
382 return current_func->stack_size + ((1 + s->idx) * 4);
385 static const char *pretty_offset(int ofs)
387 static char esp_buf[64];
389 if (ofs)
390 sprintf(esp_buf, "%d(%%esp)", ofs);
391 else
392 strcpy(esp_buf, "(%esp)");
394 return esp_buf;
397 static void stor_sym_init(struct symbol *sym)
399 struct storage *stor;
400 struct symbol_private *priv;
402 priv = calloc(1, sizeof(*priv) + sizeof(*stor));
403 if (!priv)
404 die("OOM in stor_sym_init");
406 stor = (struct storage *) (priv + 1);
408 priv->addr = stor;
409 stor->type = STOR_SYM;
410 stor->sym = sym;
413 static const char *stor_op_name(struct storage *s)
415 static char name[32];
417 switch (s->type) {
418 case STOR_PSEUDO:
419 strcpy(name, pretty_offset((int) pseudo_offset(s)));
420 break;
421 case STOR_ARG:
422 strcpy(name, pretty_offset((int) arg_offset(s)));
423 break;
424 case STOR_SYM:
425 strcpy(name, show_ident(s->sym->ident));
426 break;
427 case STOR_REG:
428 strcpy(name, s->reg->name);
429 break;
430 case STOR_VALUE:
431 sprintf(name, "$%Ld", s->value);
432 break;
433 case STOR_LABEL:
434 sprintf(name, "%s.L%d", s->flags & STOR_LABEL_VAL ? "$" : "",
435 s->label);
436 break;
437 case STOR_LABELSYM:
438 sprintf(name, "%s.LS%p", s->flags & STOR_LABEL_VAL ? "$" : "",
439 s->labelsym);
440 break;
443 return name;
446 static struct atom *new_atom(enum atom_type type)
448 struct atom *atom;
450 atom = calloc(1, sizeof(*atom)); /* TODO: chunked alloc */
451 if (!atom)
452 die("nuclear OOM");
454 atom->type = type;
456 return atom;
459 static inline void push_cstring(struct function *f, struct string *str,
460 int label)
462 struct atom *atom;
464 atom = new_atom(ATOM_CSTR);
465 atom->string = str;
466 atom->label = label;
468 add_ptr_list(&f->str_list, atom); /* note: _not_ atom_list */
471 static inline void push_atom(struct function *f, struct atom *atom)
473 add_ptr_list(&f->atom_list, atom);
476 static void push_text_atom(struct function *f, const char *text)
478 struct atom *atom = new_atom(ATOM_TEXT);
480 atom->text = strdup(text);
481 atom->text_len = strlen(text);
483 push_atom(f, atom);
486 static struct storage *new_storage(enum storage_type type)
488 struct storage *stor;
490 stor = calloc(1, sizeof(*stor));
491 if (!stor)
492 die("OOM in new_storage");
494 stor->type = type;
496 return stor;
499 static struct storage *stack_alloc(int n_bytes)
501 struct function *f = current_func;
502 struct storage *stor;
504 assert(f != NULL);
506 stor = new_storage(STOR_PSEUDO);
507 stor->type = STOR_PSEUDO;
508 stor->pseudo = f->pseudo_nr;
509 stor->offset = f->stack_size; /* FIXME: stack req. natural align */
510 stor->size = n_bytes;
511 f->stack_size += n_bytes;
512 f->pseudo_nr++;
514 add_ptr_list(&f->pseudo_list, stor);
516 return stor;
519 static struct storage *new_labelsym(struct symbol *sym)
521 struct storage *stor;
523 stor = new_storage(STOR_LABELSYM);
525 if (stor) {
526 stor->flags |= STOR_WANTS_FREE;
527 stor->labelsym = sym;
530 return stor;
533 static struct storage *new_val(long long value)
535 struct storage *stor;
537 stor = new_storage(STOR_VALUE);
539 if (stor) {
540 stor->flags |= STOR_WANTS_FREE;
541 stor->value = value;
544 return stor;
547 static int new_label(void)
549 static int label = 0;
550 return ++label;
553 static void textbuf_push(struct textbuf **buf_p, const char *text)
555 struct textbuf *tmp, *list = *buf_p;
556 unsigned int text_len = strlen(text);
557 unsigned int alloc_len = text_len + 1 + sizeof(*list);
559 tmp = calloc(1, alloc_len);
560 if (!tmp)
561 die("OOM on textbuf alloc");
563 tmp->text = ((void *) tmp) + sizeof(*tmp);
564 memcpy(tmp->text, text, text_len + 1);
565 tmp->len = text_len;
567 /* add to end of list */
568 if (!list) {
569 list = tmp;
570 tmp->prev = tmp;
571 } else {
572 tmp->prev = list->prev;
573 tmp->prev->next = tmp;
574 list->prev = tmp;
576 tmp->next = list;
578 *buf_p = list;
581 static void textbuf_emit(struct textbuf **buf_p)
583 struct textbuf *tmp, *list = *buf_p;
585 while (list) {
586 tmp = list;
587 if (tmp->next == tmp)
588 list = NULL;
589 else {
590 tmp->prev->next = tmp->next;
591 tmp->next->prev = tmp->prev;
592 list = tmp->next;
595 fputs(tmp->text, stdout);
597 free(tmp);
600 *buf_p = list;
603 static void insn(const char *insn, struct storage *op1, struct storage *op2,
604 const char *comment_in)
606 struct function *f = current_func;
607 struct atom *atom = new_atom(ATOM_INSN);
609 assert(insn != NULL);
611 strcpy(atom->insn, insn);
612 if (comment_in && (*comment_in))
613 strncpy(atom->comment, comment_in,
614 sizeof(atom->comment) - 1);
616 atom->op1 = op1;
617 atom->op2 = op2;
619 push_atom(f, atom);
622 static void emit_comment(const char *fmt, ...)
624 struct function *f = current_func;
625 static char tmpbuf[100] = "\t# ";
626 va_list args;
627 int i;
629 va_start(args, fmt);
630 i = vsnprintf(tmpbuf+3, sizeof(tmpbuf)-4, fmt, args);
631 va_end(args);
632 tmpbuf[i+3] = '\n';
633 tmpbuf[i+4] = '\0';
634 push_text_atom(f, tmpbuf);
637 static void emit_label (int label, const char *comment)
639 struct function *f = current_func;
640 char s[64];
642 if (!comment)
643 sprintf(s, ".L%d:\n", label);
644 else
645 sprintf(s, ".L%d:\t\t\t\t\t# %s\n", label, comment);
647 push_text_atom(f, s);
650 static void emit_labelsym (struct symbol *sym, const char *comment)
652 struct function *f = current_func;
653 char s[64];
655 if (!comment)
656 sprintf(s, ".LS%p:\n", sym);
657 else
658 sprintf(s, ".LS%p:\t\t\t\t# %s\n", sym, comment);
660 push_text_atom(f, s);
663 void emit_unit_begin(const char *basename)
665 printf("\t.file\t\"%s\"\n", basename);
668 void emit_unit_end(void)
670 textbuf_emit(&unit_post_text);
671 printf("\t.ident\t\"sparse silly x86 backend (built %s)\"\n", __DATE__);
674 /* conditionally switch sections */
675 static void emit_section(const char *s)
677 if (s == current_section)
678 return;
679 if (current_section && (!strcmp(s, current_section)))
680 return;
682 printf("\t%s\n", s);
683 current_section = s;
686 static void emit_insn_atom(struct function *f, struct atom *atom)
688 char s[128];
689 char comment[64];
690 struct storage *op1 = atom->op1;
691 struct storage *op2 = atom->op2;
693 if (atom->comment[0])
694 sprintf(comment, "\t\t# %s", atom->comment);
695 else
696 comment[0] = 0;
698 if (atom->op2) {
699 char tmp[16];
700 strcpy(tmp, stor_op_name(op1));
701 sprintf(s, "\t%s\t%s, %s%s\n",
702 atom->insn, tmp, stor_op_name(op2), comment);
703 } else if (atom->op1)
704 sprintf(s, "\t%s\t%s%s%s\n",
705 atom->insn, stor_op_name(op1),
706 comment[0] ? "\t" : "", comment);
707 else
708 sprintf(s, "\t%s\t%s%s\n",
709 atom->insn,
710 comment[0] ? "\t\t" : "", comment);
712 write(STDOUT_FILENO, s, strlen(s));
715 static void emit_atom_list(struct function *f)
717 struct atom *atom;
719 FOR_EACH_PTR(f->atom_list, atom) {
720 switch (atom->type) {
721 case ATOM_TEXT: {
722 ssize_t rc = write(STDOUT_FILENO, atom->text,
723 atom->text_len);
724 (void) rc; /* FIXME */
725 break;
727 case ATOM_INSN:
728 emit_insn_atom(f, atom);
729 break;
730 case ATOM_CSTR:
731 assert(0);
732 break;
734 } END_FOR_EACH_PTR;
737 static void emit_string_list(struct function *f)
739 struct atom *atom;
741 emit_section(".section\t.rodata");
743 FOR_EACH_PTR(f->str_list, atom) {
744 /* FIXME: escape " in string */
745 printf(".L%d:\n", atom->label);
746 printf("\t.string\t%s\n", show_string(atom->string));
748 free(atom);
749 } END_FOR_EACH_PTR;
752 static void func_cleanup(struct function *f)
754 struct storage *stor;
755 struct atom *atom;
757 FOR_EACH_PTR(f->pseudo_list, stor) {
758 free(stor);
759 } END_FOR_EACH_PTR;
761 FOR_EACH_PTR(f->atom_list, atom) {
762 if ((atom->type == ATOM_TEXT) && (atom->text))
763 free(atom->text);
764 if (atom->op1 && (atom->op1->flags & STOR_WANTS_FREE))
765 free(atom->op1);
766 if (atom->op2 && (atom->op2->flags & STOR_WANTS_FREE))
767 free(atom->op2);
768 free(atom);
769 } END_FOR_EACH_PTR;
771 free_ptr_list(&f->pseudo_list);
772 free(f);
775 /* function prologue */
776 static void emit_func_pre(struct symbol *sym)
778 struct function *f;
779 struct symbol *arg;
780 unsigned int i, argc = 0, alloc_len;
781 unsigned char *mem;
782 struct symbol_private *privbase;
783 struct storage *storage_base;
784 struct symbol *base_type = sym->ctype.base_type;
786 FOR_EACH_PTR(base_type->arguments, arg) {
787 argc++;
788 } END_FOR_EACH_PTR;
790 alloc_len =
791 sizeof(*f) +
792 (argc * sizeof(struct symbol *)) +
793 (argc * sizeof(struct symbol_private)) +
794 (argc * sizeof(struct storage));
795 mem = calloc(1, alloc_len);
796 if (!mem)
797 die("OOM on func info");
799 f = (struct function *) mem;
800 mem += sizeof(*f);
801 f->argv = (struct symbol **) mem;
802 mem += (argc * sizeof(struct symbol *));
803 privbase = (struct symbol_private *) mem;
804 mem += (argc * sizeof(struct symbol_private));
805 storage_base = (struct storage *) mem;
807 f->argc = argc;
808 f->ret_target = new_label();
810 i = 0;
811 FOR_EACH_PTR(base_type->arguments, arg) {
812 f->argv[i] = arg;
813 arg->aux = &privbase[i];
814 storage_base[i].type = STOR_ARG;
815 storage_base[i].idx = i;
816 privbase[i].addr = &storage_base[i];
817 i++;
818 } END_FOR_EACH_PTR;
820 assert(current_func == NULL);
821 current_func = f;
824 /* function epilogue */
825 static void emit_func_post(struct symbol *sym)
827 const char *name = show_ident(sym->ident);
828 struct function *f = current_func;
829 int stack_size = f->stack_size;
831 if (f->str_list)
832 emit_string_list(f);
834 /* function prologue */
835 emit_section(".text");
836 if ((sym->ctype.modifiers & MOD_STATIC) == 0)
837 printf(".globl %s\n", name);
838 printf("\t.type\t%s, @function\n", name);
839 printf("%s:\n", name);
841 if (stack_size) {
842 char pseudo_const[16];
844 sprintf(pseudo_const, "$%d", stack_size);
845 printf("\tsubl\t%s, %%esp\n", pseudo_const);
848 /* function epilogue */
850 /* jump target for 'return' statements */
851 emit_label(f->ret_target, NULL);
853 if (stack_size) {
854 struct storage *val;
856 val = new_storage(STOR_VALUE);
857 val->value = (long long) (stack_size);
858 val->flags = STOR_WANTS_FREE;
860 insn("addl", val, REG_ESP, NULL);
863 insn("ret", NULL, NULL, NULL);
865 /* output everything to stdout */
866 fflush(stdout); /* paranoia; needed? */
867 emit_atom_list(f);
869 /* function footer */
870 name = show_ident(sym->ident);
871 printf("\t.size\t%s, .-%s\n", name, name);
873 func_cleanup(f);
874 current_func = NULL;
877 /* emit object (a.k.a. variable, a.k.a. data) prologue */
878 static void emit_object_pre(const char *name, unsigned long modifiers,
879 unsigned long alignment, unsigned int byte_size)
881 if ((modifiers & MOD_STATIC) == 0)
882 printf(".globl %s\n", name);
883 emit_section(".data");
884 if (alignment)
885 printf("\t.align %lu\n", alignment);
886 printf("\t.type\t%s, @object\n", name);
887 printf("\t.size\t%s, %d\n", name, byte_size);
888 printf("%s:\n", name);
891 /* emit value (only) for an initializer scalar */
892 static void emit_scalar(struct expression *expr, unsigned int bit_size)
894 const char *type;
895 long long ll;
897 assert(expr->type == EXPR_VALUE);
899 if (expr->value == 0ULL) {
900 printf("\t.zero\t%d\n", bit_size / 8);
901 return;
904 ll = (long long) expr->value;
906 switch (bit_size) {
907 case 8: type = "byte"; ll = (char) ll; break;
908 case 16: type = "value"; ll = (short) ll; break;
909 case 32: type = "long"; ll = (int) ll; break;
910 case 64: type = "quad"; break;
911 default: type = NULL; break;
914 assert(type != NULL);
916 printf("\t.%s\t%Ld\n", type, ll);
919 static void emit_global_noinit(const char *name, unsigned long modifiers,
920 unsigned long alignment, unsigned int byte_size)
922 char s[64];
924 if (modifiers & MOD_STATIC) {
925 sprintf(s, "\t.local\t%s\n", name);
926 textbuf_push(&unit_post_text, s);
928 if (alignment)
929 sprintf(s, "\t.comm\t%s,%d,%lu\n", name, byte_size, alignment);
930 else
931 sprintf(s, "\t.comm\t%s,%d\n", name, byte_size);
932 textbuf_push(&unit_post_text, s);
935 static int ea_current, ea_last;
937 static void emit_initializer(struct symbol *sym,
938 struct expression *expr)
940 int distance = ea_current - ea_last - 1;
942 if (distance > 0)
943 printf("\t.zero\t%d\n", (sym->bit_size / 8) * distance);
945 if (expr->type == EXPR_VALUE) {
946 struct symbol *base_type = sym->ctype.base_type;
947 assert(base_type != NULL);
949 emit_scalar(expr, sym->bit_size / get_expression_value(base_type->array_size));
950 return;
952 if (expr->type != EXPR_INITIALIZER)
953 return;
955 assert(0); /* FIXME */
958 static int sort_array_cmp(const struct expression *a,
959 const struct expression *b)
961 int a_ofs = 0, b_ofs = 0;
963 if (a->type == EXPR_POS)
964 a_ofs = (int) a->init_offset;
965 if (b->type == EXPR_POS)
966 b_ofs = (int) b->init_offset;
968 return a_ofs - b_ofs;
971 /* move to front-end? */
972 static void sort_array(struct expression *expr)
974 struct expression *entry, **list;
975 unsigned int elem, sorted, i;
977 elem = 0;
978 FOR_EACH_PTR(expr->expr_list, entry) {
979 elem++;
980 } END_FOR_EACH_PTR;
982 if (!elem)
983 return;
985 list = malloc(sizeof(entry) * elem);
986 if (!list)
987 die("OOM in sort_array");
989 /* this code is no doubt evil and ignores EXPR_INDEX possibly
990 * to its detriment and other nasty things. improvements
991 * welcome.
993 i = 0;
994 sorted = 0;
995 FOR_EACH_PTR(expr->expr_list, entry) {
996 if ((entry->type == EXPR_POS) || (entry->type == EXPR_VALUE)) {
997 /* add entry to list[], in sorted order */
998 if (sorted == 0) {
999 list[0] = entry;
1000 sorted = 1;
1001 } else {
1002 unsigned int i;
1004 for (i = 0; i < sorted; i++)
1005 if (sort_array_cmp(entry, list[i]) <= 0)
1006 break;
1008 /* If inserting into the middle of list[]
1009 * instead of appending, we memmove.
1010 * This is ugly, but thankfully
1011 * uncommon. Input data with tons of
1012 * entries very rarely have explicit
1013 * offsets. convert to qsort eventually...
1015 if (i != sorted)
1016 memmove(&list[i + 1], &list[i],
1017 (sorted - i) * sizeof(entry));
1018 list[i] = entry;
1019 sorted++;
1022 } END_FOR_EACH_PTR;
1024 i = 0;
1025 FOR_EACH_PTR(expr->expr_list, entry) {
1026 if ((entry->type == EXPR_POS) || (entry->type == EXPR_VALUE))
1027 __list->list[__i] = list[i++];
1028 } END_FOR_EACH_PTR;
1032 static void emit_array(struct symbol *sym)
1034 struct symbol *base_type = sym->ctype.base_type;
1035 struct expression *expr = sym->initializer;
1036 struct expression *entry;
1038 assert(base_type != NULL);
1040 stor_sym_init(sym);
1042 ea_last = -1;
1044 emit_object_pre(show_ident(sym->ident), sym->ctype.modifiers,
1045 sym->ctype.alignment,
1046 sym->bit_size / 8);
1048 sort_array(expr);
1050 FOR_EACH_PTR(expr->expr_list, entry) {
1051 if (entry->type == EXPR_VALUE) {
1052 ea_current = 0;
1053 emit_initializer(sym, entry);
1054 ea_last = ea_current;
1055 } else if (entry->type == EXPR_POS) {
1056 ea_current =
1057 entry->init_offset / (base_type->bit_size / 8);
1058 emit_initializer(sym, entry->init_expr);
1059 ea_last = ea_current;
1061 } END_FOR_EACH_PTR;
1064 void emit_one_symbol(struct symbol *sym)
1066 x86_symbol(sym);
1069 static void emit_copy(struct storage *dest, struct storage *src,
1070 struct symbol *ctype)
1072 struct storage *reg = NULL;
1073 unsigned int bit_size;
1075 /* FIXME: Bitfield copy! */
1077 bit_size = src->size * 8;
1078 if (!bit_size)
1079 bit_size = 32;
1080 if ((src->type == STOR_ARG) && (bit_size < 32))
1081 bit_size = 32;
1083 reg = temp_from_bits(bit_size);
1084 emit_move(src, reg, ctype, "begin copy ..");
1086 bit_size = dest->size * 8;
1087 if (!bit_size)
1088 bit_size = 32;
1089 if ((dest->type == STOR_ARG) && (bit_size < 32))
1090 bit_size = 32;
1092 emit_move(reg, dest, ctype, ".... end copy");
1093 put_reg(reg);
1096 static void emit_store(struct expression *dest_expr, struct storage *dest,
1097 struct storage *src, int bits)
1099 /* FIXME: Bitfield store! */
1100 printf("\tst.%d\t\tv%d,[v%d]\n", bits, src->pseudo, dest->pseudo);
1103 static void emit_scalar_noinit(struct symbol *sym)
1105 emit_global_noinit(show_ident(sym->ident),
1106 sym->ctype.modifiers, sym->ctype.alignment,
1107 sym->bit_size / 8);
1108 stor_sym_init(sym);
1111 static void emit_array_noinit(struct symbol *sym)
1113 emit_global_noinit(show_ident(sym->ident),
1114 sym->ctype.modifiers, sym->ctype.alignment,
1115 get_expression_value(sym->array_size) * (sym->bit_size / 8));
1116 stor_sym_init(sym);
1119 static const char *opbits(const char *insn, unsigned int bits)
1121 static char opbits_str[32];
1122 char c;
1124 switch (bits) {
1125 case 8: c = 'b'; break;
1126 case 16: c = 'w'; break;
1127 case 32: c = 'l'; break;
1128 case 64: c = 'q'; break;
1129 default: assert(0); break;
1132 sprintf(opbits_str, "%s%c", insn, c);
1134 return opbits_str;
1137 static void emit_move(struct storage *src, struct storage *dest,
1138 struct symbol *ctype, const char *comment)
1140 unsigned int bits;
1141 unsigned int is_signed;
1142 unsigned int is_dest = (src->type == STOR_REG);
1143 const char *opname;
1145 if (ctype) {
1146 bits = ctype->bit_size;
1147 is_signed = type_is_signed(ctype);
1148 } else {
1149 bits = 32;
1150 is_signed = 0;
1154 * Are we moving from a register to a register?
1155 * Make the new reg to be the "cache".
1157 if ((dest->type == STOR_REG) && (src->type == STOR_REG)) {
1158 struct storage *backing;
1160 reg_reg_move:
1161 if (dest == src)
1162 return;
1164 backing = src->reg->contains;
1165 if (backing) {
1166 /* Is it still valid? */
1167 if (backing->reg != src->reg)
1168 backing = NULL;
1169 else
1170 backing->reg = dest->reg;
1172 dest->reg->contains = backing;
1173 insn("mov", src, dest, NULL);
1174 return;
1178 * Are we moving to a register from a non-reg?
1180 * See if we have the non-reg source already cached
1181 * in a register..
1183 if (dest->type == STOR_REG) {
1184 if (src->reg) {
1185 struct reg_info *info = src->reg;
1186 if (info->contains == src) {
1187 src = reginfo_reg(info);
1188 goto reg_reg_move;
1191 dest->reg->contains = src;
1192 src->reg = dest->reg;
1195 if (src->type == STOR_REG) {
1196 /* We could just mark the register dirty here and do lazy store.. */
1197 src->reg->contains = dest;
1198 dest->reg = src->reg;
1201 if ((bits == 8) || (bits == 16)) {
1202 if (is_dest)
1203 opname = "mov";
1204 else
1205 opname = is_signed ? "movsx" : "movzx";
1206 } else
1207 opname = "mov";
1209 insn(opbits(opname, bits), src, dest, comment);
1212 static struct storage *emit_compare(struct expression *expr)
1214 struct storage *left = x86_expression(expr->left);
1215 struct storage *right = x86_expression(expr->right);
1216 struct storage *reg1, *reg2;
1217 struct storage *new, *val;
1218 const char *opname = NULL;
1219 unsigned int right_bits = expr->right->ctype->bit_size;
1221 switch(expr->op) {
1222 case '<': opname = "setl"; break;
1223 case '>': opname = "setg"; break;
1224 case SPECIAL_LTE:
1225 opname = "setle"; break;
1226 case SPECIAL_GTE:
1227 opname = "setge"; break;
1228 case SPECIAL_EQUAL: opname = "sete"; break;
1229 case SPECIAL_NOTEQUAL: opname = "setne"; break;
1230 case SPECIAL_UNSIGNED_LT:
1231 opname = "setb"; break;
1232 case SPECIAL_UNSIGNED_GT:
1233 opname = "seta"; break;
1234 case SPECIAL_UNSIGNED_LTE:
1235 opname = "setb"; break;
1236 case SPECIAL_UNSIGNED_GTE:
1237 opname = "setae"; break;
1238 default:
1239 assert(0);
1240 break;
1243 /* init EDX to 0 */
1244 val = new_storage(STOR_VALUE);
1245 val->flags = STOR_WANTS_FREE;
1247 reg1 = get_reg(&regclass_32_8);
1248 emit_move(val, reg1, NULL, NULL);
1250 /* move op1 into EAX */
1251 reg2 = get_reg_value(left, get_regclass(expr->left));
1253 /* perform comparison, RHS (op1, right) and LHS (op2, EAX) */
1254 insn(opbits("cmp", right_bits), right, reg2, NULL);
1255 put_reg(reg2);
1257 /* store result of operation, 0 or 1, in DL using SETcc */
1258 insn(opname, byte_reg(reg1), NULL, NULL);
1260 /* finally, store the result (DL) in a new pseudo / stack slot */
1261 new = stack_alloc(4);
1262 emit_move(reg1, new, NULL, "end EXPR_COMPARE");
1263 put_reg(reg1);
1265 return new;
1268 static struct storage *emit_value(struct expression *expr)
1270 #if 0 /* old and slow way */
1271 struct storage *new = stack_alloc(4);
1272 struct storage *val;
1274 val = new_storage(STOR_VALUE);
1275 val->value = (long long) expr->value;
1276 val->flags = STOR_WANTS_FREE;
1277 insn("movl", val, new, NULL);
1279 return new;
1280 #else
1281 struct storage *val;
1283 val = new_storage(STOR_VALUE);
1284 val->value = (long long) expr->value;
1286 return val; /* FIXME: memory leak */
1287 #endif
1290 static struct storage *emit_divide(struct expression *expr, struct storage *left, struct storage *right)
1292 struct storage *eax_edx;
1293 struct storage *reg, *new;
1294 struct storage *val = new_storage(STOR_VALUE);
1296 emit_comment("begin DIVIDE");
1297 eax_edx = get_hardreg(hardreg_storage_table + EAX_EDX, 1);
1299 /* init EDX to 0 */
1300 val = new_storage(STOR_VALUE);
1301 val->flags = STOR_WANTS_FREE;
1302 emit_move(val, REG_EDX, NULL, NULL);
1304 new = stack_alloc(expr->ctype->bit_size / 8);
1306 /* EAX is dividend */
1307 emit_move(left, REG_EAX, NULL, NULL);
1309 reg = get_reg_value(right, &regclass_32);
1311 /* perform binop */
1312 insn("div", reg, REG_EAX, NULL);
1313 put_reg(reg);
1315 reg = REG_EAX;
1316 if (expr->op == '%')
1317 reg = REG_EDX;
1318 emit_move(reg, new, NULL, NULL);
1320 put_reg(eax_edx);
1321 emit_comment("end DIVIDE");
1322 return new;
1325 static struct storage *emit_binop(struct expression *expr)
1327 struct storage *left = x86_expression(expr->left);
1328 struct storage *right = x86_expression(expr->right);
1329 struct storage *new;
1330 struct storage *dest, *src;
1331 const char *opname = NULL;
1332 const char *suffix = NULL;
1333 char opstr[16];
1334 int is_signed;
1336 /* Divides have special register constraints */
1337 if ((expr->op == '/') || (expr->op == '%'))
1338 return emit_divide(expr, left, right);
1340 is_signed = type_is_signed(expr->ctype);
1342 switch (expr->op) {
1343 case '+':
1344 opname = "add";
1345 break;
1346 case '-':
1347 opname = "sub";
1348 break;
1349 case '&':
1350 opname = "and";
1351 break;
1352 case '|':
1353 opname = "or";
1354 break;
1355 case '^':
1356 opname = "xor";
1357 break;
1358 case SPECIAL_LEFTSHIFT:
1359 opname = "shl";
1360 break;
1361 case SPECIAL_RIGHTSHIFT:
1362 if (is_signed)
1363 opname = "sar";
1364 else
1365 opname = "shr";
1366 break;
1367 case '*':
1368 if (is_signed)
1369 opname = "imul";
1370 else
1371 opname = "mul";
1372 break;
1373 case SPECIAL_LOGICAL_AND:
1374 warn(expr->pos, "bogus bitwise and for logical op (should use '2*setne + and' or something)");
1375 opname = "and";
1376 break;
1377 case SPECIAL_LOGICAL_OR:
1378 warn(expr->pos, "bogus bitwise or for logical op (should use 'or + setne' or something)");
1379 opname = "or";
1380 break;
1381 default:
1382 error(expr->pos, "unhandled binop '%s'\n", show_special(expr->op));
1383 break;
1386 dest = get_reg_value(right, &regclass_32);
1387 src = get_reg_value(left, &regclass_32);
1388 switch (expr->ctype->bit_size) {
1389 case 8:
1390 suffix = "b";
1391 break;
1392 case 16:
1393 suffix = "w";
1394 break;
1395 case 32:
1396 suffix = "l";
1397 break;
1398 case 64:
1399 suffix = "q"; /* FIXME */
1400 break;
1401 default:
1402 assert(0);
1403 break;
1406 snprintf(opstr, sizeof(opstr), "%s%s", opname, suffix);
1408 /* perform binop */
1409 insn(opstr, src, dest, NULL);
1410 put_reg(src);
1412 /* store result in new pseudo / stack slot */
1413 new = stack_alloc(expr->ctype->bit_size / 8);
1414 emit_move(dest, new, NULL, "end EXPR_BINOP");
1416 put_reg(dest);
1418 return new;
1421 static int emit_conditional_test(struct storage *val)
1423 struct storage *reg;
1424 struct storage *target_val;
1425 int target_false;
1427 /* load result into EAX */
1428 emit_comment("begin if/conditional");
1429 reg = get_reg_value(val, &regclass_32);
1431 /* compare result with zero */
1432 insn("test", reg, reg, NULL);
1433 put_reg(reg);
1435 /* create conditional-failed label to jump to */
1436 target_false = new_label();
1437 target_val = new_storage(STOR_LABEL);
1438 target_val->label = target_false;
1439 target_val->flags = STOR_WANTS_FREE;
1440 insn("jz", target_val, NULL, NULL);
1442 return target_false;
1445 static int emit_conditional_end(int target_false)
1447 struct storage *cond_end_st;
1448 int cond_end;
1450 /* finished generating code for if-true statement.
1451 * add a jump-to-end jump to avoid falling through
1452 * to the if-false statement code.
1454 cond_end = new_label();
1455 cond_end_st = new_storage(STOR_LABEL);
1456 cond_end_st->label = cond_end;
1457 cond_end_st->flags = STOR_WANTS_FREE;
1458 insn("jmp", cond_end_st, NULL, NULL);
1460 /* if we have both if-true and if-false statements,
1461 * the failed-conditional case will fall through to here
1463 emit_label(target_false, NULL);
1465 return cond_end;
1468 static void emit_if_conditional(struct statement *stmt)
1470 struct storage *val;
1471 int cond_end;
1473 /* emit test portion of conditional */
1474 val = x86_expression(stmt->if_conditional);
1475 cond_end = emit_conditional_test(val);
1477 /* emit if-true statement */
1478 x86_statement(stmt->if_true);
1480 /* emit if-false statement, if present */
1481 if (stmt->if_false) {
1482 cond_end = emit_conditional_end(cond_end);
1483 x86_statement(stmt->if_false);
1486 /* end of conditional; jump target for if-true branch */
1487 emit_label(cond_end, "end if");
1490 static struct storage *emit_inc_dec(struct expression *expr, int postop)
1492 struct storage *addr = x86_address_gen(expr->unop);
1493 struct storage *retval;
1494 char opname[16];
1496 strcpy(opname, opbits(expr->op == SPECIAL_INCREMENT ? "inc" : "dec",
1497 expr->ctype->bit_size));
1499 if (postop) {
1500 struct storage *new = stack_alloc(4);
1502 emit_copy(new, addr, expr->unop->ctype);
1504 retval = new;
1505 } else
1506 retval = addr;
1508 insn(opname, addr, NULL, NULL);
1510 return retval;
1513 static struct storage *emit_postop(struct expression *expr)
1515 return emit_inc_dec(expr, 1);
1518 static struct storage *emit_return_stmt(struct statement *stmt)
1520 struct function *f = current_func;
1521 struct expression *expr = stmt->ret_value;
1522 struct storage *val = NULL, *jmplbl;
1524 if (expr && expr->ctype) {
1525 val = x86_expression(expr);
1526 assert(val != NULL);
1527 emit_move(val, REG_EAX, expr->ctype, "return");
1530 jmplbl = new_storage(STOR_LABEL);
1531 jmplbl->flags |= STOR_WANTS_FREE;
1532 jmplbl->label = f->ret_target;
1533 insn("jmp", jmplbl, NULL, NULL);
1535 return val;
1538 static struct storage *emit_conditional_expr(struct expression *expr)
1540 struct storage *cond, *true = NULL, *false = NULL;
1541 struct storage *new = stack_alloc(expr->ctype->bit_size / 8);
1542 int target_false, cond_end;
1544 /* evaluate conditional */
1545 cond = x86_expression(expr->conditional);
1546 target_false = emit_conditional_test(cond);
1548 /* handle if-true part of the expression */
1549 if (!expr->cond_true)
1550 true = cond;
1551 else
1552 true = x86_expression(expr->cond_true);
1554 emit_copy(new, true, expr->ctype);
1556 cond_end = emit_conditional_end(target_false);
1558 /* handle if-false part of the expression */
1559 false = x86_expression(expr->cond_false);
1561 emit_copy(new, false, expr->ctype);
1563 /* end of conditional; jump target for if-true branch */
1564 emit_label(cond_end, "end conditional");
1566 return new;
1569 static struct storage *emit_select_expr(struct expression *expr)
1571 struct storage *cond = x86_expression(expr->conditional);
1572 struct storage *true = x86_expression(expr->cond_true);
1573 struct storage *false = x86_expression(expr->cond_false);
1574 struct storage *reg_cond, *reg_true, *reg_false;
1575 struct storage *new = stack_alloc(4);
1577 emit_comment("begin SELECT");
1578 reg_cond = get_reg_value(cond, get_regclass(expr->conditional));
1579 reg_true = reg_cond;
1580 if (true) {
1581 reg_true = get_reg_value(true, get_regclass(expr));
1583 reg_false = get_reg_value(false, get_regclass(expr));
1586 * Do the actual select: check the conditional for zero,
1587 * move false over true if zero
1589 insn("test", reg_cond, reg_cond, NULL);
1590 insn("cmovz", reg_false, reg_true, NULL);
1592 /* Store it back */
1593 emit_move(reg_true, new, expr->ctype, NULL);
1594 put_reg(reg_cond);
1595 if (true)
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;
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, void *data, int flags)
1786 if (flags & ITERATE_FIRST)
1787 printf(" {\n\t");
1788 printf("%s:%d:%ld at offset %ld", show_ident(sym->ident), sym->bit_size, sym->ctype.alignment, sym->offset);
1789 if (sym->fieldwidth)
1790 printf("[%d..%d]", sym->bit_offset, sym->bit_offset+sym->fieldwidth-1);
1791 if (flags & ITERATE_LAST)
1792 printf("\n} ");
1793 else
1794 printf(", ");
1797 static void x86_symbol(struct symbol *sym)
1799 struct symbol *type;
1801 if (!sym)
1802 return;
1804 type = sym->ctype.base_type;
1805 if (!type)
1806 return;
1809 * Show actual implementation information
1811 switch (type->type) {
1813 case SYM_ARRAY:
1814 if (sym->initializer)
1815 emit_array(sym);
1816 else
1817 emit_array_noinit(sym);
1818 break;
1820 case SYM_BASETYPE:
1821 if (sym->initializer) {
1822 emit_object_pre(show_ident(sym->ident),
1823 sym->ctype.modifiers,
1824 sym->ctype.alignment,
1825 sym->bit_size / 8);
1826 emit_scalar(sym->initializer, sym->bit_size);
1827 stor_sym_init(sym);
1828 } else
1829 emit_scalar_noinit(sym);
1830 break;
1832 case SYM_STRUCT:
1833 symbol_iterate(type->symbol_list, x86_struct_member, NULL);
1834 break;
1836 case SYM_UNION:
1837 symbol_iterate(type->symbol_list, x86_struct_member, NULL);
1838 break;
1840 case SYM_FN: {
1841 struct statement *stmt = type->stmt;
1842 if (stmt) {
1843 emit_func_pre(sym);
1844 x86_statement(stmt);
1845 emit_func_post(sym);
1847 break;
1850 default:
1851 break;
1854 if (sym->initializer && (type->type != SYM_BASETYPE) &&
1855 (type->type != SYM_ARRAY)) {
1856 printf(" = \n");
1857 x86_expression(sym->initializer);
1861 static void x86_symbol_init(struct symbol *sym);
1863 static void x86_symbol_decl(struct symbol_list *syms)
1865 struct symbol *sym;
1866 FOR_EACH_PTR(syms, sym) {
1867 x86_symbol_init(sym);
1868 } END_FOR_EACH_PTR;
1871 static void loopstk_push(int cont_lbl, int loop_bottom_lbl)
1873 struct function *f = current_func;
1874 struct loop_stack *ls;
1876 ls = malloc(sizeof(*ls));
1877 ls->continue_lbl = cont_lbl;
1878 ls->loop_bottom_lbl = loop_bottom_lbl;
1879 ls->next = f->loop_stack;
1880 f->loop_stack = ls;
1883 static void loopstk_pop(void)
1885 struct function *f = current_func;
1886 struct loop_stack *ls;
1888 assert(f->loop_stack != NULL);
1889 ls = f->loop_stack;
1890 f->loop_stack = f->loop_stack->next;
1891 free(ls);
1894 static int loopstk_break(void)
1896 return current_func->loop_stack->loop_bottom_lbl;
1899 static int loopstk_continue(void)
1901 return current_func->loop_stack->continue_lbl;
1904 static void emit_loop(struct statement *stmt)
1906 struct statement *pre_statement = stmt->iterator_pre_statement;
1907 struct expression *pre_condition = stmt->iterator_pre_condition;
1908 struct statement *statement = stmt->iterator_statement;
1909 struct statement *post_statement = stmt->iterator_post_statement;
1910 struct expression *post_condition = stmt->iterator_post_condition;
1911 int loop_top = 0, loop_bottom, loop_continue;
1912 int have_bottom = 0;
1913 struct storage *val;
1915 loop_bottom = new_label();
1916 loop_continue = new_label();
1917 loopstk_push(loop_continue, loop_bottom);
1919 x86_symbol_decl(stmt->iterator_syms);
1920 x86_statement(pre_statement);
1921 if (pre_condition) {
1922 if (pre_condition->type == EXPR_VALUE) {
1923 if (!pre_condition->value) {
1924 struct storage *lbv;
1925 lbv = new_storage(STOR_LABEL);
1926 lbv->label = loop_bottom;
1927 lbv->flags = STOR_WANTS_FREE;
1928 insn("jmp", lbv, NULL, "go to loop bottom");
1929 have_bottom = 1;
1931 } else {
1932 struct storage *lbv = new_storage(STOR_LABEL);
1933 lbv->label = loop_bottom;
1934 lbv->flags = STOR_WANTS_FREE;
1935 have_bottom = 1;
1937 val = x86_expression(pre_condition);
1939 emit_move(val, REG_EAX, NULL, "loop pre condition");
1940 insn("test", REG_EAX, REG_EAX, NULL);
1941 insn("jz", lbv, NULL, NULL);
1944 if (!post_condition || post_condition->type != EXPR_VALUE || post_condition->value) {
1945 loop_top = new_label();
1946 emit_label(loop_top, "loop top");
1948 x86_statement(statement);
1949 if (stmt->iterator_continue->used)
1950 emit_label(loop_continue, "'continue' iterator");
1951 x86_statement(post_statement);
1952 if (!post_condition) {
1953 struct storage *lbv = new_storage(STOR_LABEL);
1954 lbv->label = loop_top;
1955 lbv->flags = STOR_WANTS_FREE;
1956 insn("jmp", lbv, NULL, "go to loop top");
1957 } else if (post_condition->type == EXPR_VALUE) {
1958 if (post_condition->value) {
1959 struct storage *lbv = new_storage(STOR_LABEL);
1960 lbv->label = loop_top;
1961 lbv->flags = STOR_WANTS_FREE;
1962 insn("jmp", lbv, NULL, "go to loop top");
1964 } else {
1965 struct storage *lbv = new_storage(STOR_LABEL);
1966 lbv->label = loop_top;
1967 lbv->flags = STOR_WANTS_FREE;
1969 val = x86_expression(post_condition);
1971 emit_move(val, REG_EAX, NULL, "loop post condition");
1972 insn("test", REG_EAX, REG_EAX, NULL);
1973 insn("jnz", lbv, NULL, NULL);
1975 if (have_bottom || stmt->iterator_break->used)
1976 emit_label(loop_bottom, "loop bottom");
1978 loopstk_pop();
1982 * Print out a statement
1984 static struct storage *x86_statement(struct statement *stmt)
1986 if (!stmt)
1987 return NULL;
1988 switch (stmt->type) {
1989 case STMT_RETURN:
1990 return emit_return_stmt(stmt);
1991 case STMT_COMPOUND: {
1992 struct statement *s;
1993 struct storage *last = NULL;
1995 x86_symbol_decl(stmt->syms);
1996 FOR_EACH_PTR(stmt->stmts, s) {
1997 last = x86_statement(s);
1998 } END_FOR_EACH_PTR;
2000 return last;
2003 case STMT_EXPRESSION:
2004 return x86_expression(stmt->expression);
2005 case STMT_IF:
2006 emit_if_conditional(stmt);
2007 return NULL;
2009 case STMT_CASE:
2010 emit_case_statement(stmt);
2011 break;
2012 case STMT_SWITCH:
2013 emit_switch_statement(stmt);
2014 break;
2016 case STMT_ITERATOR:
2017 emit_loop(stmt);
2018 break;
2020 case STMT_NONE:
2021 break;
2023 case STMT_LABEL:
2024 printf(".L%p:\n", stmt->label_identifier);
2025 x86_statement(stmt->label_statement);
2026 break;
2028 case STMT_GOTO:
2029 if (stmt->goto_expression) {
2030 struct storage *val = x86_expression(stmt->goto_expression);
2031 printf("\tgoto *v%d\n", val->pseudo);
2032 } else if (!strcmp("break", show_ident(stmt->goto_label->ident))) {
2033 struct storage *lbv = new_storage(STOR_LABEL);
2034 lbv->label = loopstk_break();
2035 lbv->flags = STOR_WANTS_FREE;
2036 insn("jmp", lbv, NULL, "'break'; go to loop bottom");
2037 } else if (!strcmp("continue", show_ident(stmt->goto_label->ident))) {
2038 struct storage *lbv = new_storage(STOR_LABEL);
2039 lbv->label = loopstk_continue();
2040 lbv->flags = STOR_WANTS_FREE;
2041 insn("jmp", lbv, NULL, "'continue'; go to loop top");
2042 } else {
2043 struct storage *labelsym = new_labelsym(stmt->goto_label);
2044 insn("jmp", labelsym, NULL, NULL);
2046 break;
2047 case STMT_ASM:
2048 printf("\tasm( .... )\n");
2049 break;
2051 return NULL;
2054 static struct storage *x86_call_expression(struct expression *expr)
2056 struct function *f = current_func;
2057 struct symbol *direct;
2058 struct expression *arg, *fn;
2059 struct storage *retval, *fncall;
2060 int framesize;
2061 char s[64];
2063 if (!expr->ctype) {
2064 warn(expr->pos, "\tcall with no type!");
2065 return NULL;
2068 framesize = 0;
2069 FOR_EACH_PTR_REVERSE(expr->args, arg) {
2070 struct storage *new = x86_expression(arg);
2071 int size = arg->ctype->bit_size;
2074 * FIXME: i386 SysV ABI dictates that values
2075 * smaller than 32 bits should be placed onto
2076 * the stack as 32-bit objects. We should not
2077 * blindly do a 32-bit push on objects smaller
2078 * than 32 bits.
2080 if (size < 32)
2081 size = 32;
2082 insn("pushl", new, NULL,
2083 !framesize ? "begin function call" : NULL);
2085 framesize += size >> 3;
2086 } END_FOR_EACH_PTR_REVERSE;
2088 fn = expr->fn;
2090 /* Remove dereference, if any */
2091 direct = NULL;
2092 if (fn->type == EXPR_PREOP) {
2093 if (fn->unop->type == EXPR_SYMBOL) {
2094 struct symbol *sym = fn->unop->symbol;
2095 if (sym->ctype.base_type->type == SYM_FN)
2096 direct = sym;
2099 if (direct) {
2100 struct storage *direct_stor = new_storage(STOR_SYM);
2101 direct_stor->flags |= STOR_WANTS_FREE;
2102 direct_stor->sym = direct;
2103 insn("call", direct_stor, NULL, NULL);
2104 } else {
2105 fncall = x86_expression(fn);
2106 emit_move(fncall, REG_EAX, fn->ctype, NULL);
2108 strcpy(s, "\tcall\t*%eax\n");
2109 push_text_atom(f, s);
2112 /* FIXME: pay attention to BITS_IN_POINTER */
2113 if (framesize) {
2114 struct storage *val = new_storage(STOR_VALUE);
2115 val->value = (long long) framesize;
2116 val->flags = STOR_WANTS_FREE;
2117 insn("addl", val, REG_ESP, NULL);
2120 retval = stack_alloc(4);
2121 emit_move(REG_EAX, retval, NULL, "end function call");
2123 return retval;
2126 static struct storage *x86_address_gen(struct expression *expr)
2128 struct function *f = current_func;
2129 struct storage *addr;
2130 struct storage *new;
2131 char s[32];
2133 if ((expr->type != EXPR_PREOP) || (expr->op != '*'))
2134 return x86_expression(expr->address);
2136 addr = x86_expression(expr->unop);
2137 if (expr->unop->type == EXPR_SYMBOL)
2138 return addr;
2140 emit_move(addr, REG_EAX, NULL, "begin deref ..");
2142 /* FIXME: operand size */
2143 strcpy(s, "\tmovl\t(%eax), %ecx\n");
2144 push_text_atom(f, s);
2146 new = stack_alloc(4);
2147 emit_move(REG_ECX, new, NULL, ".... end deref");
2149 return new;
2152 static struct storage *x86_assignment(struct expression *expr)
2154 struct expression *target = expr->left;
2155 struct storage *val, *addr;
2157 if (!expr->ctype)
2158 return NULL;
2160 val = x86_expression(expr->right);
2161 addr = x86_address_gen(target);
2163 switch (val->type) {
2164 /* copy, where both operands are memory */
2165 case STOR_PSEUDO:
2166 case STOR_ARG:
2167 emit_copy(addr, val, expr->ctype);
2168 break;
2170 /* copy, one or zero operands are memory */
2171 case STOR_REG:
2172 case STOR_SYM:
2173 case STOR_VALUE:
2174 case STOR_LABEL:
2175 emit_move(val, addr, expr->left->ctype, NULL);
2176 break;
2178 case STOR_LABELSYM:
2179 assert(0);
2180 break;
2182 return val;
2185 static int x86_initialization(struct symbol *sym, struct expression *expr)
2187 struct storage *val, *addr;
2188 int bits;
2190 if (!expr->ctype)
2191 return 0;
2193 bits = expr->ctype->bit_size;
2194 val = x86_expression(expr);
2195 addr = x86_symbol_expr(sym);
2196 // FIXME! The "target" expression is for bitfield store information.
2197 // Leave it NULL, which works fine.
2198 emit_store(NULL, addr, val, bits);
2199 return 0;
2202 static struct storage *x86_access(struct expression *expr)
2204 return x86_address_gen(expr);
2207 static struct storage *x86_preop(struct expression *expr)
2210 * '*' is an lvalue access, and is fundamentally different
2211 * from an arithmetic operation. Maybe it should have an
2212 * expression type of its own..
2214 if (expr->op == '*')
2215 return x86_access(expr);
2216 if (expr->op == SPECIAL_INCREMENT || expr->op == SPECIAL_DECREMENT)
2217 return emit_inc_dec(expr, 0);
2218 return emit_regular_preop(expr);
2221 static struct storage *x86_symbol_expr(struct symbol *sym)
2223 struct storage *new = stack_alloc(4);
2225 if (sym->ctype.modifiers & (MOD_TOPLEVEL | MOD_EXTERN | MOD_STATIC)) {
2226 printf("\tmovi.%d\t\tv%d,$%s\n", bits_in_pointer, new->pseudo, show_ident(sym->ident));
2227 return new;
2229 if (sym->ctype.modifiers & MOD_ADDRESSABLE) {
2230 printf("\taddi.%d\t\tv%d,vFP,$%lld\n", bits_in_pointer, new->pseudo, sym->value);
2231 return new;
2233 printf("\taddi.%d\t\tv%d,vFP,$offsetof(%s:%p)\n", bits_in_pointer, new->pseudo, show_ident(sym->ident), sym);
2234 return new;
2237 static void x86_symbol_init(struct symbol *sym)
2239 struct symbol_private *priv = sym->aux;
2240 struct expression *expr = sym->initializer;
2241 struct storage *new;
2243 if (expr)
2244 new = x86_expression(expr);
2245 else
2246 new = stack_alloc(sym->bit_size / 8);
2248 if (!priv) {
2249 priv = calloc(1, sizeof(*priv));
2250 sym->aux = priv;
2251 /* FIXME: leak! we don't free... */
2252 /* (well, we don't free symbols either) */
2255 priv->addr = new;
2258 static int type_is_signed(struct symbol *sym)
2260 if (sym->type == SYM_NODE)
2261 sym = sym->ctype.base_type;
2262 if (sym->type == SYM_PTR)
2263 return 0;
2264 return !(sym->ctype.modifiers & MOD_UNSIGNED);
2267 static struct storage *x86_bitfield_expr(struct expression *expr)
2269 return x86_access(expr);
2272 static struct storage *x86_label_expr(struct expression *expr)
2274 struct storage *new = stack_alloc(4);
2275 printf("\tmovi.%d\t\tv%d,.L%p\n", bits_in_pointer, new->pseudo, expr->label_symbol);
2276 return new;
2279 static struct storage *x86_statement_expr(struct expression *expr)
2281 return x86_statement(expr->statement);
2284 static int x86_position_expr(struct expression *expr, struct symbol *base)
2286 struct storage *new = x86_expression(expr->init_expr);
2287 struct symbol *ctype = expr->init_sym;
2289 printf("\tinsert v%d at [%d:%d] of %s\n", new->pseudo,
2290 expr->init_offset, ctype->bit_offset,
2291 show_ident(base->ident));
2292 return 0;
2295 static void x86_initializer_expr(struct expression *expr, struct symbol *ctype)
2297 struct expression *entry;
2299 FOR_EACH_PTR(expr->expr_list, entry) {
2300 // Nested initializers have their positions already
2301 // recursively calculated - just output them too
2302 if (entry->type == EXPR_INITIALIZER) {
2303 x86_initializer_expr(entry, ctype);
2304 continue;
2307 // Ignore initializer indexes and identifiers - the
2308 // evaluator has taken them into account
2309 if (entry->type == EXPR_IDENTIFIER || entry->type == EXPR_INDEX)
2310 continue;
2311 if (entry->type == EXPR_POS) {
2312 x86_position_expr(entry, ctype);
2313 continue;
2315 x86_initialization(ctype, entry);
2316 } END_FOR_EACH_PTR;
2320 * Print out an expression. Return the pseudo that contains the
2321 * variable.
2323 static struct storage *x86_expression(struct expression *expr)
2325 if (!expr)
2326 return NULL;
2328 if (!expr->ctype) {
2329 struct position *pos = &expr->pos;
2330 printf("\tno type at %s:%d:%d\n",
2331 input_streams[pos->stream].name,
2332 pos->line, pos->pos);
2333 return NULL;
2336 switch (expr->type) {
2337 case EXPR_CALL:
2338 return x86_call_expression(expr);
2340 case EXPR_ASSIGNMENT:
2341 return x86_assignment(expr);
2343 case EXPR_COMPARE:
2344 return emit_compare(expr);
2345 case EXPR_BINOP:
2346 case EXPR_COMMA:
2347 case EXPR_LOGICAL:
2348 return emit_binop(expr);
2349 case EXPR_PREOP:
2350 return x86_preop(expr);
2351 case EXPR_POSTOP:
2352 return emit_postop(expr);
2353 case EXPR_SYMBOL:
2354 return emit_symbol_expr_init(expr->symbol);
2355 case EXPR_DEREF:
2356 case EXPR_SIZEOF:
2357 case EXPR_ALIGNOF:
2358 warn(expr->pos, "invalid expression after evaluation");
2359 return NULL;
2360 case EXPR_CAST:
2361 return emit_cast_expr(expr);
2362 case EXPR_VALUE:
2363 return emit_value(expr);
2364 case EXPR_STRING:
2365 return emit_string_expr(expr);
2366 case EXPR_BITFIELD:
2367 return x86_bitfield_expr(expr);
2368 case EXPR_INITIALIZER:
2369 x86_initializer_expr(expr, expr->ctype);
2370 return NULL;
2371 case EXPR_SELECT:
2372 return emit_select_expr(expr);
2373 case EXPR_CONDITIONAL:
2374 return emit_conditional_expr(expr);
2375 case EXPR_STATEMENT:
2376 return x86_statement_expr(expr);
2377 case EXPR_LABEL:
2378 return x86_label_expr(expr);
2380 // None of these should exist as direct expressions: they are only
2381 // valid as sub-expressions of initializers.
2382 case EXPR_POS:
2383 warn(expr->pos, "unable to show plain initializer position expression");
2384 return NULL;
2385 case EXPR_IDENTIFIER:
2386 warn(expr->pos, "unable to show identifier expression");
2387 return NULL;
2388 case EXPR_INDEX:
2389 warn(expr->pos, "unable to show index expression");
2390 return NULL;
2391 case EXPR_TYPE:
2392 warn(expr->pos, "unable to show type expression");
2393 return NULL;
2394 case EXPR_FVALUE:
2395 warn(expr->pos, "floating point support is not implemented");
2396 return NULL;
2398 return NULL;