assigned_expression: get the assigned expression using the name and sym
[smatch.git] / compile-i386.c
blob88169ecbcb5aa55b106a45d7f3bfa65d6e906aaa
1 /*
2 * sparse/compile-i386.c
4 * Copyright (C) 2003 Transmeta Corp.
5 * 2003 Linus Torvalds
6 * Copyright 2003 Jeff Garzik
8 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 * of this software and associated documentation files (the "Software"), to deal
10 * in the Software without restriction, including without limitation the rights
11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 * copies of the Software, and to permit persons to whom the Software is
13 * furnished to do so, subject to the following conditions:
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 * THE SOFTWARE.
26 * x86 backend
28 * TODO list:
29 * in general, any non-32bit SYM_BASETYPE is unlikely to work.
30 * complex initializers
31 * bitfields
32 * global struct/union variables
33 * addressing structures, and members of structures (as opposed to
34 * scalars) on the stack. Requires smarter stack frame allocation.
35 * labels / goto
36 * any function argument that isn't 32 bits (or promoted to such)
37 * inline asm
38 * floating point
41 #include <stdarg.h>
42 #include <stdlib.h>
43 #include <stdio.h>
44 #include <string.h>
45 #include <ctype.h>
46 #include <unistd.h>
47 #include <fcntl.h>
48 #include <assert.h>
50 #include "lib.h"
51 #include "allocate.h"
52 #include "token.h"
53 #include "parse.h"
54 #include "symbol.h"
55 #include "scope.h"
56 #include "expression.h"
57 #include "target.h"
58 #include "compile.h"
59 #include "bitmap.h"
61 struct textbuf {
62 unsigned int len; /* does NOT include terminating null */
63 char *text;
64 struct textbuf *next;
65 struct textbuf *prev;
68 struct loop_stack {
69 int continue_lbl;
70 int loop_bottom_lbl;
71 struct loop_stack *next;
74 struct atom;
75 struct storage;
76 DECLARE_PTR_LIST(str_list, struct atom);
77 DECLARE_PTR_LIST(atom_list, struct atom);
78 DECLARE_PTR_LIST(storage_list, struct storage);
80 struct function {
81 int stack_size;
82 int pseudo_nr;
83 struct storage_list *pseudo_list;
84 struct atom_list *atom_list;
85 struct str_list *str_list;
86 struct loop_stack *loop_stack;
87 struct symbol **argv;
88 unsigned int argc;
89 int ret_target;
92 enum storage_type {
93 STOR_PSEUDO, /* variable stored on the stack */
94 STOR_ARG, /* function argument */
95 STOR_SYM, /* a symbol we can directly ref in the asm */
96 STOR_REG, /* scratch register */
97 STOR_VALUE, /* integer constant */
98 STOR_LABEL, /* label / jump target */
99 STOR_LABELSYM, /* label generated from symbol's pointer value */
102 struct reg_info {
103 const char *name;
104 struct storage *contains;
105 const unsigned char aliases[12];
106 #define own_regno aliases[0]
109 struct storage {
110 enum storage_type type;
111 unsigned long flags;
113 /* STOR_REG */
114 struct reg_info *reg;
115 struct symbol *ctype;
117 union {
118 /* STOR_PSEUDO */
119 struct {
120 int pseudo;
121 int offset;
122 int size;
124 /* STOR_ARG */
125 struct {
126 int idx;
128 /* STOR_SYM */
129 struct {
130 struct symbol *sym;
132 /* STOR_VALUE */
133 struct {
134 long long value;
136 /* STOR_LABEL */
137 struct {
138 int label;
140 /* STOR_LABELSYM */
141 struct {
142 struct symbol *labelsym;
147 enum {
148 STOR_LABEL_VAL = (1 << 0),
149 STOR_WANTS_FREE = (1 << 1),
152 struct symbol_private {
153 struct storage *addr;
156 enum atom_type {
157 ATOM_TEXT,
158 ATOM_INSN,
159 ATOM_CSTR,
162 struct atom {
163 enum atom_type type;
164 union {
165 /* stuff for text */
166 struct {
167 char *text;
168 unsigned int text_len; /* w/o terminating null */
171 /* stuff for insns */
172 struct {
173 char insn[32];
174 char comment[40];
175 struct storage *op1;
176 struct storage *op2;
179 /* stuff for C strings */
180 struct {
181 struct string *string;
182 int label;
188 static struct function *current_func = NULL;
189 static struct textbuf *unit_post_text = NULL;
190 static const char *current_section;
192 static void emit_comment(const char * fmt, ...) FORMAT_ATTR(1);
193 static void emit_move(struct storage *src, struct storage *dest,
194 struct symbol *ctype, const char *comment);
195 static int type_is_signed(struct symbol *sym);
196 static struct storage *x86_address_gen(struct expression *expr);
197 static struct storage *x86_symbol_expr(struct symbol *sym);
198 static void x86_symbol(struct symbol *sym);
199 static struct storage *x86_statement(struct statement *stmt);
200 static struct storage *x86_expression(struct expression *expr);
202 enum registers {
203 NOREG,
204 AL, DL, CL, BL, AH, DH, CH, BH, // 8-bit
205 AX, DX, CX, BX, SI, DI, BP, SP, // 16-bit
206 EAX, EDX, ECX, EBX, ESI, EDI, EBP, ESP, // 32-bit
207 EAX_EDX, ECX_EBX, ESI_EDI, // 64-bit
210 /* This works on regno's, reg_info's and hardreg_storage's */
211 #define byte_reg(reg) ((reg) - 16)
212 #define highbyte_reg(reg) ((reg)-12)
213 #define word_reg(reg) ((reg)-8)
215 #define REGINFO(nr, str, conflicts...) [nr] = { .name = str, .aliases = { nr , conflicts } }
217 static struct reg_info reg_info_table[] = {
218 REGINFO( AL, "%al", AX, EAX, EAX_EDX),
219 REGINFO( DL, "%dl", DX, EDX, EAX_EDX),
220 REGINFO( CL, "%cl", CX, ECX, ECX_EBX),
221 REGINFO( BL, "%bl", BX, EBX, ECX_EBX),
222 REGINFO( AH, "%ah", AX, EAX, EAX_EDX),
223 REGINFO( DH, "%dh", DX, EDX, EAX_EDX),
224 REGINFO( CH, "%ch", CX, ECX, ECX_EBX),
225 REGINFO( BH, "%bh", BX, EBX, ECX_EBX),
226 REGINFO( AX, "%ax", AL, AH, EAX, EAX_EDX),
227 REGINFO( DX, "%dx", DL, DH, EDX, EAX_EDX),
228 REGINFO( CX, "%cx", CL, CH, ECX, ECX_EBX),
229 REGINFO( BX, "%bx", BL, BH, EBX, ECX_EBX),
230 REGINFO( SI, "%si", ESI, ESI_EDI),
231 REGINFO( DI, "%di", EDI, ESI_EDI),
232 REGINFO( BP, "%bp", EBP),
233 REGINFO( SP, "%sp", ESP),
234 REGINFO(EAX, "%eax", AL, AH, AX, EAX_EDX),
235 REGINFO(EDX, "%edx", DL, DH, DX, EAX_EDX),
236 REGINFO(ECX, "%ecx", CL, CH, CX, ECX_EBX),
237 REGINFO(EBX, "%ebx", BL, BH, BX, ECX_EBX),
238 REGINFO(ESI, "%esi", SI, ESI_EDI),
239 REGINFO(EDI, "%edi", DI, ESI_EDI),
240 REGINFO(EBP, "%ebp", BP),
241 REGINFO(ESP, "%esp", SP),
242 REGINFO(EAX_EDX, "%eax:%edx", AL, AH, AX, EAX, DL, DH, DX, EDX),
243 REGINFO(ECX_EBX, "%ecx:%ebx", CL, CH, CX, ECX, BL, BH, BX, EBX),
244 REGINFO(ESI_EDI, "%esi:%edi", SI, ESI, DI, EDI),
247 #define REGSTORAGE(nr) [nr] = { .type = STOR_REG, .reg = reg_info_table + (nr) }
249 static struct storage hardreg_storage_table[] = {
250 REGSTORAGE(AL), REGSTORAGE(DL), REGSTORAGE(CL), REGSTORAGE(BL),
251 REGSTORAGE(AH), REGSTORAGE(DH), REGSTORAGE(CH), REGSTORAGE(BH),
252 REGSTORAGE(AX), REGSTORAGE(DX), REGSTORAGE(CX), REGSTORAGE(BX),
253 REGSTORAGE(SI), REGSTORAGE(DI), REGSTORAGE(BP), REGSTORAGE(SP),
254 REGSTORAGE(EAX), REGSTORAGE(EDX), REGSTORAGE(ECX), REGSTORAGE(EBX),
255 REGSTORAGE(ESI), REGSTORAGE(EDI), REGSTORAGE(EBP), REGSTORAGE(ESP),
256 REGSTORAGE(EAX_EDX), REGSTORAGE(ECX_EBX), REGSTORAGE(ESI_EDI),
259 #define REG_EAX (&hardreg_storage_table[EAX])
260 #define REG_ECX (&hardreg_storage_table[ECX])
261 #define REG_EDX (&hardreg_storage_table[EDX])
262 #define REG_ESP (&hardreg_storage_table[ESP])
263 #define REG_DL (&hardreg_storage_table[DL])
264 #define REG_DX (&hardreg_storage_table[DX])
265 #define REG_AL (&hardreg_storage_table[AL])
266 #define REG_AX (&hardreg_storage_table[AX])
268 static DECLARE_BITMAP(regs_in_use, 256);
270 static inline struct storage * reginfo_reg(struct reg_info *info)
272 return hardreg_storage_table + info->own_regno;
275 static struct storage * get_hardreg(struct storage *reg, int clear)
277 struct reg_info *info = reg->reg;
278 const unsigned char *aliases;
279 int regno;
281 aliases = info->aliases;
282 while ((regno = *aliases++) != NOREG) {
283 if (test_bit(regno, regs_in_use))
284 goto busy;
285 if (clear)
286 reg_info_table[regno].contains = NULL;
288 set_bit(info->own_regno, regs_in_use);
289 return reg;
290 busy:
291 fprintf(stderr, "register %s is busy\n", info->name);
292 if (regno + reg_info_table != info)
293 fprintf(stderr, " conflicts with %s\n", reg_info_table[regno].name);
294 exit(1);
297 static void put_reg(struct storage *reg)
299 struct reg_info *info = reg->reg;
300 int regno = info->own_regno;
302 if (test_and_clear_bit(regno, regs_in_use))
303 return;
304 fprintf(stderr, "freeing already free'd register %s\n", reg_info_table[regno].name);
307 struct regclass {
308 const char *name;
309 const unsigned char regs[30];
312 static struct regclass regclass_8 = { "8-bit", { AL, DL, CL, BL, AH, DH, CH, BH }};
313 static struct regclass regclass_16 = { "16-bit", { AX, DX, CX, BX, SI, DI, BP }};
314 static struct regclass regclass_32 = { "32-bit", { EAX, EDX, ECX, EBX, ESI, EDI, EBP }};
315 static struct regclass regclass_64 = { "64-bit", { EAX_EDX, ECX_EBX, ESI_EDI }};
317 static struct regclass regclass_32_8 = { "32-bit bytes", { EAX, EDX, ECX, EBX }};
319 static struct regclass *get_regclass_bits(int bits)
321 switch (bits) {
322 case 8: return &regclass_8;
323 case 16: return &regclass_16;
324 case 64: return &regclass_64;
325 default: return &regclass_32;
329 static struct regclass *get_regclass(struct expression *expr)
331 return get_regclass_bits(expr->ctype->bit_size);
334 static int register_busy(int regno)
336 if (!test_bit(regno, regs_in_use)) {
337 struct reg_info *info = reg_info_table + regno;
338 const unsigned char *regs = info->aliases+1;
340 while ((regno = *regs) != NOREG) {
341 regs++;
342 if (test_bit(regno, regs_in_use))
343 goto busy;
345 return 0;
347 busy:
348 return 1;
351 static struct storage *get_reg(struct regclass *class)
353 const unsigned char *regs = class->regs;
354 int regno;
356 while ((regno = *regs) != NOREG) {
357 regs++;
358 if (register_busy(regno))
359 continue;
360 return get_hardreg(hardreg_storage_table + regno, 1);
362 fprintf(stderr, "Ran out of %s registers\n", class->name);
363 exit(1);
366 static struct storage *get_reg_value(struct storage *value, struct regclass *class)
368 struct reg_info *info;
369 struct storage *reg;
371 /* Do we already have it somewhere */
372 info = value->reg;
373 if (info && info->contains == value) {
374 emit_comment("already have register %s", info->name);
375 return get_hardreg(hardreg_storage_table + info->own_regno, 0);
378 reg = get_reg(class);
379 emit_move(value, reg, value->ctype, "reload register");
380 info = reg->reg;
381 info->contains = value;
382 value->reg = info;
383 return reg;
386 static struct storage *temp_from_bits(unsigned int bit_size)
388 return get_reg(get_regclass_bits(bit_size));
391 static inline unsigned int pseudo_offset(struct storage *s)
393 if (s->type != STOR_PSEUDO)
394 return 123456; /* intentionally bogus value */
396 return s->offset;
399 static inline unsigned int arg_offset(struct storage *s)
401 if (s->type != STOR_ARG)
402 return 123456; /* intentionally bogus value */
404 /* FIXME: this is wrong wrong wrong */
405 return current_func->stack_size + ((1 + s->idx) * 4);
408 static const char *pretty_offset(int ofs)
410 static char esp_buf[64];
412 if (ofs)
413 sprintf(esp_buf, "%d(%%esp)", ofs);
414 else
415 strcpy(esp_buf, "(%esp)");
417 return esp_buf;
420 static void stor_sym_init(struct symbol *sym)
422 struct storage *stor;
423 struct symbol_private *priv;
425 priv = calloc(1, sizeof(*priv) + sizeof(*stor));
426 if (!priv)
427 die("OOM in stor_sym_init");
429 stor = (struct storage *) (priv + 1);
431 priv->addr = stor;
432 stor->type = STOR_SYM;
433 stor->sym = sym;
436 static const char *stor_op_name(struct storage *s)
438 static char name[32];
440 switch (s->type) {
441 case STOR_PSEUDO:
442 strcpy(name, pretty_offset((int) pseudo_offset(s)));
443 break;
444 case STOR_ARG:
445 strcpy(name, pretty_offset((int) arg_offset(s)));
446 break;
447 case STOR_SYM:
448 strcpy(name, show_ident(s->sym->ident));
449 break;
450 case STOR_REG:
451 strcpy(name, s->reg->name);
452 break;
453 case STOR_VALUE:
454 sprintf(name, "$%Ld", s->value);
455 break;
456 case STOR_LABEL:
457 sprintf(name, "%s.L%d", s->flags & STOR_LABEL_VAL ? "$" : "",
458 s->label);
459 break;
460 case STOR_LABELSYM:
461 sprintf(name, "%s.LS%p", s->flags & STOR_LABEL_VAL ? "$" : "",
462 s->labelsym);
463 break;
466 return name;
469 static struct atom *new_atom(enum atom_type type)
471 struct atom *atom;
473 atom = calloc(1, sizeof(*atom)); /* TODO: chunked alloc */
474 if (!atom)
475 die("nuclear OOM");
477 atom->type = type;
479 return atom;
482 static inline void push_cstring(struct function *f, struct string *str,
483 int label)
485 struct atom *atom;
487 atom = new_atom(ATOM_CSTR);
488 atom->string = str;
489 atom->label = label;
491 add_ptr_list(&f->str_list, atom); /* note: _not_ atom_list */
494 static inline void push_atom(struct function *f, struct atom *atom)
496 add_ptr_list(&f->atom_list, atom);
499 static void push_text_atom(struct function *f, const char *text)
501 struct atom *atom = new_atom(ATOM_TEXT);
503 atom->text = strdup(text);
504 atom->text_len = strlen(text);
506 push_atom(f, atom);
509 static struct storage *new_storage(enum storage_type type)
511 struct storage *stor;
513 stor = calloc(1, sizeof(*stor));
514 if (!stor)
515 die("OOM in new_storage");
517 stor->type = type;
519 return stor;
522 static struct storage *stack_alloc(int n_bytes)
524 struct function *f = current_func;
525 struct storage *stor;
527 assert(f != NULL);
529 stor = new_storage(STOR_PSEUDO);
530 stor->type = STOR_PSEUDO;
531 stor->pseudo = f->pseudo_nr;
532 stor->offset = f->stack_size; /* FIXME: stack req. natural align */
533 stor->size = n_bytes;
534 f->stack_size += n_bytes;
535 f->pseudo_nr++;
537 add_ptr_list(&f->pseudo_list, stor);
539 return stor;
542 static struct storage *new_labelsym(struct symbol *sym)
544 struct storage *stor;
546 stor = new_storage(STOR_LABELSYM);
548 if (stor) {
549 stor->flags |= STOR_WANTS_FREE;
550 stor->labelsym = sym;
553 return stor;
556 static struct storage *new_val(long long value)
558 struct storage *stor;
560 stor = new_storage(STOR_VALUE);
562 if (stor) {
563 stor->flags |= STOR_WANTS_FREE;
564 stor->value = value;
567 return stor;
570 static int new_label(void)
572 static int label = 0;
573 return ++label;
576 static void textbuf_push(struct textbuf **buf_p, const char *text)
578 struct textbuf *tmp, *list = *buf_p;
579 unsigned int text_len = strlen(text);
580 unsigned int alloc_len = text_len + 1 + sizeof(*list);
582 tmp = calloc(1, alloc_len);
583 if (!tmp)
584 die("OOM on textbuf alloc");
586 tmp->text = ((void *) tmp) + sizeof(*tmp);
587 memcpy(tmp->text, text, text_len + 1);
588 tmp->len = text_len;
590 /* add to end of list */
591 if (!list) {
592 list = tmp;
593 tmp->prev = tmp;
594 } else {
595 tmp->prev = list->prev;
596 tmp->prev->next = tmp;
597 list->prev = tmp;
599 tmp->next = list;
601 *buf_p = list;
604 static void textbuf_emit(struct textbuf **buf_p)
606 struct textbuf *tmp, *list = *buf_p;
608 while (list) {
609 tmp = list;
610 if (tmp->next == tmp)
611 list = NULL;
612 else {
613 tmp->prev->next = tmp->next;
614 tmp->next->prev = tmp->prev;
615 list = tmp->next;
618 fputs(tmp->text, stdout);
620 free(tmp);
623 *buf_p = list;
626 static void insn(const char *insn, struct storage *op1, struct storage *op2,
627 const char *comment_in)
629 struct function *f = current_func;
630 struct atom *atom = new_atom(ATOM_INSN);
632 assert(insn != NULL);
634 strcpy(atom->insn, insn);
635 if (comment_in && (*comment_in))
636 strncpy(atom->comment, comment_in,
637 sizeof(atom->comment) - 1);
639 atom->op1 = op1;
640 atom->op2 = op2;
642 push_atom(f, atom);
645 static void emit_comment(const char *fmt, ...)
647 struct function *f = current_func;
648 static char tmpbuf[100] = "\t# ";
649 va_list args;
650 int i;
652 va_start(args, fmt);
653 i = vsnprintf(tmpbuf+3, sizeof(tmpbuf)-4, fmt, args);
654 va_end(args);
655 tmpbuf[i+3] = '\n';
656 tmpbuf[i+4] = '\0';
657 push_text_atom(f, tmpbuf);
660 static void emit_label (int label, const char *comment)
662 struct function *f = current_func;
663 char s[64];
665 if (!comment)
666 sprintf(s, ".L%d:\n", label);
667 else
668 sprintf(s, ".L%d:\t\t\t\t\t# %s\n", label, comment);
670 push_text_atom(f, s);
673 static void emit_labelsym (struct symbol *sym, const char *comment)
675 struct function *f = current_func;
676 char s[64];
678 if (!comment)
679 sprintf(s, ".LS%p:\n", sym);
680 else
681 sprintf(s, ".LS%p:\t\t\t\t# %s\n", sym, comment);
683 push_text_atom(f, s);
686 void emit_unit_begin(const char *basename)
688 printf("\t.file\t\"%s\"\n", basename);
691 void emit_unit_end(void)
693 textbuf_emit(&unit_post_text);
694 printf("\t.ident\t\"sparse silly x86 backend (built %s)\"\n", __DATE__);
697 /* conditionally switch sections */
698 static void emit_section(const char *s)
700 if (s == current_section)
701 return;
702 if (current_section && (!strcmp(s, current_section)))
703 return;
705 printf("\t%s\n", s);
706 current_section = s;
709 static void emit_insn_atom(struct function *f, struct atom *atom)
711 char s[128];
712 char comment[64];
713 struct storage *op1 = atom->op1;
714 struct storage *op2 = atom->op2;
716 if (atom->comment[0])
717 sprintf(comment, "\t\t# %s", atom->comment);
718 else
719 comment[0] = 0;
721 if (atom->op2) {
722 char tmp[16];
723 strcpy(tmp, stor_op_name(op1));
724 sprintf(s, "\t%s\t%s, %s%s\n",
725 atom->insn, tmp, stor_op_name(op2), comment);
726 } else if (atom->op1)
727 sprintf(s, "\t%s\t%s%s%s\n",
728 atom->insn, stor_op_name(op1),
729 comment[0] ? "\t" : "", comment);
730 else
731 sprintf(s, "\t%s\t%s%s\n",
732 atom->insn,
733 comment[0] ? "\t\t" : "", comment);
735 write(STDOUT_FILENO, s, strlen(s));
738 static void emit_atom_list(struct function *f)
740 struct atom *atom;
742 FOR_EACH_PTR(f->atom_list, atom) {
743 switch (atom->type) {
744 case ATOM_TEXT: {
745 ssize_t rc = write(STDOUT_FILENO, atom->text,
746 atom->text_len);
747 (void) rc; /* FIXME */
748 break;
750 case ATOM_INSN:
751 emit_insn_atom(f, atom);
752 break;
753 case ATOM_CSTR:
754 assert(0);
755 break;
757 } END_FOR_EACH_PTR(atom);
760 static void emit_string_list(struct function *f)
762 struct atom *atom;
764 emit_section(".section\t.rodata");
766 FOR_EACH_PTR(f->str_list, atom) {
767 /* FIXME: escape " in string */
768 printf(".L%d:\n", atom->label);
769 printf("\t.string\t%s\n", show_string(atom->string));
771 free(atom);
772 } END_FOR_EACH_PTR(atom);
775 static void func_cleanup(struct function *f)
777 struct storage *stor;
778 struct atom *atom;
780 FOR_EACH_PTR(f->atom_list, atom) {
781 if ((atom->type == ATOM_TEXT) && (atom->text))
782 free(atom->text);
783 if (atom->op1 && (atom->op1->flags & STOR_WANTS_FREE))
784 free(atom->op1);
785 if (atom->op2 && (atom->op2->flags & STOR_WANTS_FREE))
786 free(atom->op2);
787 free(atom);
788 } END_FOR_EACH_PTR(atom);
790 FOR_EACH_PTR(f->pseudo_list, stor) {
791 free(stor);
792 } END_FOR_EACH_PTR(stor);
794 free_ptr_list(&f->pseudo_list);
795 free(f);
798 /* function prologue */
799 static void emit_func_pre(struct symbol *sym)
801 struct function *f;
802 struct symbol *arg;
803 unsigned int i, argc = 0, alloc_len;
804 unsigned char *mem;
805 struct symbol_private *privbase;
806 struct storage *storage_base;
807 struct symbol *base_type = sym->ctype.base_type;
809 FOR_EACH_PTR(base_type->arguments, arg) {
810 argc++;
811 } END_FOR_EACH_PTR(arg);
813 alloc_len =
814 sizeof(*f) +
815 (argc * sizeof(struct symbol *)) +
816 (argc * sizeof(struct symbol_private)) +
817 (argc * sizeof(struct storage));
818 mem = calloc(1, alloc_len);
819 if (!mem)
820 die("OOM on func info");
822 f = (struct function *) mem;
823 mem += sizeof(*f);
824 f->argv = (struct symbol **) mem;
825 mem += (argc * sizeof(struct symbol *));
826 privbase = (struct symbol_private *) mem;
827 mem += (argc * sizeof(struct symbol_private));
828 storage_base = (struct storage *) mem;
830 f->argc = argc;
831 f->ret_target = new_label();
833 i = 0;
834 FOR_EACH_PTR(base_type->arguments, arg) {
835 f->argv[i] = arg;
836 arg->aux = &privbase[i];
837 storage_base[i].type = STOR_ARG;
838 storage_base[i].idx = i;
839 privbase[i].addr = &storage_base[i];
840 i++;
841 } END_FOR_EACH_PTR(arg);
843 assert(current_func == NULL);
844 current_func = f;
847 /* function epilogue */
848 static void emit_func_post(struct symbol *sym)
850 const char *name = show_ident(sym->ident);
851 struct function *f = current_func;
852 int stack_size = f->stack_size;
854 if (f->str_list)
855 emit_string_list(f);
857 /* function prologue */
858 emit_section(".text");
859 if ((sym->ctype.modifiers & MOD_STATIC) == 0)
860 printf(".globl %s\n", name);
861 printf("\t.type\t%s, @function\n", name);
862 printf("%s:\n", name);
864 if (stack_size) {
865 char pseudo_const[16];
867 sprintf(pseudo_const, "$%d", stack_size);
868 printf("\tsubl\t%s, %%esp\n", pseudo_const);
871 /* function epilogue */
873 /* jump target for 'return' statements */
874 emit_label(f->ret_target, NULL);
876 if (stack_size) {
877 struct storage *val;
879 val = new_storage(STOR_VALUE);
880 val->value = (long long) (stack_size);
881 val->flags = STOR_WANTS_FREE;
883 insn("addl", val, REG_ESP, NULL);
886 insn("ret", NULL, NULL, NULL);
888 /* output everything to stdout */
889 fflush(stdout); /* paranoia; needed? */
890 emit_atom_list(f);
892 /* function footer */
893 name = show_ident(sym->ident);
894 printf("\t.size\t%s, .-%s\n", name, name);
896 func_cleanup(f);
897 current_func = NULL;
900 /* emit object (a.k.a. variable, a.k.a. data) prologue */
901 static void emit_object_pre(const char *name, unsigned long modifiers,
902 unsigned long alignment, unsigned int byte_size)
904 if ((modifiers & MOD_STATIC) == 0)
905 printf(".globl %s\n", name);
906 emit_section(".data");
907 if (alignment)
908 printf("\t.align %lu\n", alignment);
909 printf("\t.type\t%s, @object\n", name);
910 printf("\t.size\t%s, %d\n", name, byte_size);
911 printf("%s:\n", name);
914 /* emit value (only) for an initializer scalar */
915 static void emit_scalar(struct expression *expr, unsigned int bit_size)
917 const char *type;
918 long long ll;
920 assert(expr->type == EXPR_VALUE);
922 if (expr->value == 0ULL) {
923 printf("\t.zero\t%d\n", bit_size / 8);
924 return;
927 ll = (long long) expr->value;
929 switch (bit_size) {
930 case 8: type = "byte"; ll = (char) ll; break;
931 case 16: type = "value"; ll = (short) ll; break;
932 case 32: type = "long"; ll = (int) ll; break;
933 case 64: type = "quad"; break;
934 default: type = NULL; break;
937 assert(type != NULL);
939 printf("\t.%s\t%Ld\n", type, ll);
942 static void emit_global_noinit(const char *name, unsigned long modifiers,
943 unsigned long alignment, unsigned int byte_size)
945 char s[64];
947 if (modifiers & MOD_STATIC) {
948 sprintf(s, "\t.local\t%s\n", name);
949 textbuf_push(&unit_post_text, s);
951 if (alignment)
952 sprintf(s, "\t.comm\t%s,%d,%lu\n", name, byte_size, alignment);
953 else
954 sprintf(s, "\t.comm\t%s,%d\n", name, byte_size);
955 textbuf_push(&unit_post_text, s);
958 static int ea_current, ea_last;
960 static void emit_initializer(struct symbol *sym,
961 struct expression *expr)
963 int distance = ea_current - ea_last - 1;
965 if (distance > 0)
966 printf("\t.zero\t%d\n", (sym->bit_size / 8) * distance);
968 if (expr->type == EXPR_VALUE) {
969 struct symbol *base_type = sym->ctype.base_type;
970 assert(base_type != NULL);
972 emit_scalar(expr, sym->bit_size / get_expression_value(base_type->array_size));
973 return;
975 if (expr->type != EXPR_INITIALIZER)
976 return;
978 assert(0); /* FIXME */
981 static int sort_array_cmp(const struct expression *a,
982 const struct expression *b)
984 int a_ofs = 0, b_ofs = 0;
986 if (a->type == EXPR_POS)
987 a_ofs = (int) a->init_offset;
988 if (b->type == EXPR_POS)
989 b_ofs = (int) b->init_offset;
991 return a_ofs - b_ofs;
994 /* move to front-end? */
995 static void sort_array(struct expression *expr)
997 struct expression *entry, **list;
998 unsigned int elem, sorted, i;
1000 elem = 0;
1001 FOR_EACH_PTR(expr->expr_list, entry) {
1002 elem++;
1003 } END_FOR_EACH_PTR(entry);
1005 if (!elem)
1006 return;
1008 list = malloc(sizeof(entry) * elem);
1009 if (!list)
1010 die("OOM in sort_array");
1012 /* this code is no doubt evil and ignores EXPR_INDEX possibly
1013 * to its detriment and other nasty things. improvements
1014 * welcome.
1016 i = 0;
1017 sorted = 0;
1018 FOR_EACH_PTR(expr->expr_list, entry) {
1019 if ((entry->type == EXPR_POS) || (entry->type == EXPR_VALUE)) {
1020 /* add entry to list[], in sorted order */
1021 if (sorted == 0) {
1022 list[0] = entry;
1023 sorted = 1;
1024 } else {
1025 for (i = 0; i < sorted; i++)
1026 if (sort_array_cmp(entry, list[i]) <= 0)
1027 break;
1029 /* If inserting into the middle of list[]
1030 * instead of appending, we memmove.
1031 * This is ugly, but thankfully
1032 * uncommon. Input data with tons of
1033 * entries very rarely have explicit
1034 * offsets. convert to qsort eventually...
1036 if (i != sorted)
1037 memmove(&list[i + 1], &list[i],
1038 (sorted - i) * sizeof(entry));
1039 list[i] = entry;
1040 sorted++;
1043 } END_FOR_EACH_PTR(entry);
1045 i = 0;
1046 FOR_EACH_PTR(expr->expr_list, entry) {
1047 if ((entry->type == EXPR_POS) || (entry->type == EXPR_VALUE))
1048 *THIS_ADDRESS(entry) = list[i++];
1049 } END_FOR_EACH_PTR(entry);
1053 static void emit_array(struct symbol *sym)
1055 struct symbol *base_type = sym->ctype.base_type;
1056 struct expression *expr = sym->initializer;
1057 struct expression *entry;
1059 assert(base_type != NULL);
1061 stor_sym_init(sym);
1063 ea_last = -1;
1065 emit_object_pre(show_ident(sym->ident), sym->ctype.modifiers,
1066 sym->ctype.alignment,
1067 sym->bit_size / 8);
1069 sort_array(expr);
1071 FOR_EACH_PTR(expr->expr_list, entry) {
1072 if (entry->type == EXPR_VALUE) {
1073 ea_current = 0;
1074 emit_initializer(sym, entry);
1075 ea_last = ea_current;
1076 } else if (entry->type == EXPR_POS) {
1077 ea_current =
1078 entry->init_offset / (base_type->bit_size / 8);
1079 emit_initializer(sym, entry->init_expr);
1080 ea_last = ea_current;
1082 } END_FOR_EACH_PTR(entry);
1085 void emit_one_symbol(struct symbol *sym)
1087 x86_symbol(sym);
1090 static void emit_copy(struct storage *dest, struct storage *src,
1091 struct symbol *ctype)
1093 struct storage *reg = NULL;
1094 unsigned int bit_size;
1096 /* FIXME: Bitfield copy! */
1098 bit_size = src->size * 8;
1099 if (!bit_size)
1100 bit_size = 32;
1101 if ((src->type == STOR_ARG) && (bit_size < 32))
1102 bit_size = 32;
1104 reg = temp_from_bits(bit_size);
1105 emit_move(src, reg, ctype, "begin copy ..");
1107 bit_size = dest->size * 8;
1108 if (!bit_size)
1109 bit_size = 32;
1110 if ((dest->type == STOR_ARG) && (bit_size < 32))
1111 bit_size = 32;
1113 emit_move(reg, dest, ctype, ".... end copy");
1114 put_reg(reg);
1117 static void emit_store(struct expression *dest_expr, struct storage *dest,
1118 struct storage *src, int bits)
1120 /* FIXME: Bitfield store! */
1121 printf("\tst.%d\t\tv%d,[v%d]\n", bits, src->pseudo, dest->pseudo);
1124 static void emit_scalar_noinit(struct symbol *sym)
1126 emit_global_noinit(show_ident(sym->ident),
1127 sym->ctype.modifiers, sym->ctype.alignment,
1128 sym->bit_size / 8);
1129 stor_sym_init(sym);
1132 static void emit_array_noinit(struct symbol *sym)
1134 emit_global_noinit(show_ident(sym->ident),
1135 sym->ctype.modifiers, sym->ctype.alignment,
1136 get_expression_value(sym->array_size) * (sym->bit_size / 8));
1137 stor_sym_init(sym);
1140 static const char *opbits(const char *insn, unsigned int bits)
1142 static char opbits_str[32];
1143 char c;
1145 switch (bits) {
1146 case 8: c = 'b'; break;
1147 case 16: c = 'w'; break;
1148 case 32: c = 'l'; break;
1149 case 64: c = 'q'; break;
1150 default: abort(); break;
1153 sprintf(opbits_str, "%s%c", insn, c);
1155 return opbits_str;
1158 static void emit_move(struct storage *src, struct storage *dest,
1159 struct symbol *ctype, const char *comment)
1161 unsigned int bits;
1162 unsigned int is_signed;
1163 unsigned int is_dest = (src->type == STOR_REG);
1164 const char *opname;
1166 if (ctype) {
1167 bits = ctype->bit_size;
1168 is_signed = type_is_signed(ctype);
1169 } else {
1170 bits = 32;
1171 is_signed = 0;
1175 * Are we moving from a register to a register?
1176 * Make the new reg to be the "cache".
1178 if ((dest->type == STOR_REG) && (src->type == STOR_REG)) {
1179 struct storage *backing;
1181 reg_reg_move:
1182 if (dest == src)
1183 return;
1185 backing = src->reg->contains;
1186 if (backing) {
1187 /* Is it still valid? */
1188 if (backing->reg != src->reg)
1189 backing = NULL;
1190 else
1191 backing->reg = dest->reg;
1193 dest->reg->contains = backing;
1194 insn("mov", src, dest, NULL);
1195 return;
1199 * Are we moving to a register from a non-reg?
1201 * See if we have the non-reg source already cached
1202 * in a register..
1204 if (dest->type == STOR_REG) {
1205 if (src->reg) {
1206 struct reg_info *info = src->reg;
1207 if (info->contains == src) {
1208 src = reginfo_reg(info);
1209 goto reg_reg_move;
1212 dest->reg->contains = src;
1213 src->reg = dest->reg;
1216 if (src->type == STOR_REG) {
1217 /* We could just mark the register dirty here and do lazy store.. */
1218 src->reg->contains = dest;
1219 dest->reg = src->reg;
1222 if ((bits == 8) || (bits == 16)) {
1223 if (is_dest)
1224 opname = "mov";
1225 else
1226 opname = is_signed ? "movsx" : "movzx";
1227 } else
1228 opname = "mov";
1230 insn(opbits(opname, bits), src, dest, comment);
1233 static struct storage *emit_compare(struct expression *expr)
1235 struct storage *left = x86_expression(expr->left);
1236 struct storage *right = x86_expression(expr->right);
1237 struct storage *reg1, *reg2;
1238 struct storage *new, *val;
1239 const char *opname = NULL;
1240 unsigned int right_bits = expr->right->ctype->bit_size;
1242 switch(expr->op) {
1243 case '<': opname = "setl"; break;
1244 case '>': opname = "setg"; break;
1245 case SPECIAL_LTE:
1246 opname = "setle"; break;
1247 case SPECIAL_GTE:
1248 opname = "setge"; break;
1249 case SPECIAL_EQUAL: opname = "sete"; break;
1250 case SPECIAL_NOTEQUAL: opname = "setne"; break;
1251 case SPECIAL_UNSIGNED_LT:
1252 opname = "setb"; break;
1253 case SPECIAL_UNSIGNED_GT:
1254 opname = "seta"; break;
1255 case SPECIAL_UNSIGNED_LTE:
1256 opname = "setb"; break;
1257 case SPECIAL_UNSIGNED_GTE:
1258 opname = "setae"; break;
1259 default:
1260 assert(0);
1261 break;
1264 /* init EDX to 0 */
1265 val = new_storage(STOR_VALUE);
1266 val->flags = STOR_WANTS_FREE;
1268 reg1 = get_reg(&regclass_32_8);
1269 emit_move(val, reg1, NULL, NULL);
1271 /* move op1 into EAX */
1272 reg2 = get_reg_value(left, get_regclass(expr->left));
1274 /* perform comparison, RHS (op1, right) and LHS (op2, EAX) */
1275 insn(opbits("cmp", right_bits), right, reg2, NULL);
1276 put_reg(reg2);
1278 /* store result of operation, 0 or 1, in DL using SETcc */
1279 insn(opname, byte_reg(reg1), NULL, NULL);
1281 /* finally, store the result (DL) in a new pseudo / stack slot */
1282 new = stack_alloc(4);
1283 emit_move(reg1, new, NULL, "end EXPR_COMPARE");
1284 put_reg(reg1);
1286 return new;
1289 static struct storage *emit_value(struct expression *expr)
1291 #if 0 /* old and slow way */
1292 struct storage *new = stack_alloc(4);
1293 struct storage *val;
1295 val = new_storage(STOR_VALUE);
1296 val->value = (long long) expr->value;
1297 val->flags = STOR_WANTS_FREE;
1298 insn("movl", val, new, NULL);
1300 return new;
1301 #else
1302 struct storage *val;
1304 val = new_storage(STOR_VALUE);
1305 val->value = (long long) expr->value;
1307 return val; /* FIXME: memory leak */
1308 #endif
1311 static struct storage *emit_divide(struct expression *expr, struct storage *left, struct storage *right)
1313 struct storage *eax_edx;
1314 struct storage *reg, *new;
1315 struct storage *val = new_storage(STOR_VALUE);
1317 emit_comment("begin DIVIDE");
1318 eax_edx = get_hardreg(hardreg_storage_table + EAX_EDX, 1);
1320 /* init EDX to 0 */
1321 val->flags = STOR_WANTS_FREE;
1322 emit_move(val, REG_EDX, NULL, NULL);
1324 new = stack_alloc(expr->ctype->bit_size / 8);
1326 /* EAX is dividend */
1327 emit_move(left, REG_EAX, NULL, NULL);
1329 reg = get_reg_value(right, &regclass_32);
1331 /* perform binop */
1332 insn("div", reg, REG_EAX, NULL);
1333 put_reg(reg);
1335 reg = REG_EAX;
1336 if (expr->op == '%')
1337 reg = REG_EDX;
1338 emit_move(reg, new, NULL, NULL);
1340 put_reg(eax_edx);
1341 emit_comment("end DIVIDE");
1342 return new;
1345 static struct storage *emit_binop(struct expression *expr)
1347 struct storage *left = x86_expression(expr->left);
1348 struct storage *right = x86_expression(expr->right);
1349 struct storage *new;
1350 struct storage *dest, *src;
1351 const char *opname = NULL;
1352 const char *suffix = NULL;
1353 char opstr[16];
1354 int is_signed;
1356 /* Divides have special register constraints */
1357 if ((expr->op == '/') || (expr->op == '%'))
1358 return emit_divide(expr, left, right);
1360 is_signed = type_is_signed(expr->ctype);
1362 switch (expr->op) {
1363 case '+':
1364 opname = "add";
1365 break;
1366 case '-':
1367 opname = "sub";
1368 break;
1369 case '&':
1370 opname = "and";
1371 break;
1372 case '|':
1373 opname = "or";
1374 break;
1375 case '^':
1376 opname = "xor";
1377 break;
1378 case SPECIAL_LEFTSHIFT:
1379 opname = "shl";
1380 break;
1381 case SPECIAL_RIGHTSHIFT:
1382 if (is_signed)
1383 opname = "sar";
1384 else
1385 opname = "shr";
1386 break;
1387 case '*':
1388 if (is_signed)
1389 opname = "imul";
1390 else
1391 opname = "mul";
1392 break;
1393 case SPECIAL_LOGICAL_AND:
1394 warning(expr->pos, "bogus bitwise and for logical op (should use '2*setne + and' or something)");
1395 opname = "and";
1396 break;
1397 case SPECIAL_LOGICAL_OR:
1398 warning(expr->pos, "bogus bitwise or for logical op (should use 'or + setne' or something)");
1399 opname = "or";
1400 break;
1401 default:
1402 error_die(expr->pos, "unhandled binop '%s'\n", show_special(expr->op));
1403 break;
1406 dest = get_reg_value(right, &regclass_32);
1407 src = get_reg_value(left, &regclass_32);
1408 switch (expr->ctype->bit_size) {
1409 case 8:
1410 suffix = "b";
1411 break;
1412 case 16:
1413 suffix = "w";
1414 break;
1415 case 32:
1416 suffix = "l";
1417 break;
1418 case 64:
1419 suffix = "q"; /* FIXME */
1420 break;
1421 default:
1422 assert(0);
1423 break;
1426 snprintf(opstr, sizeof(opstr), "%s%s", opname, suffix);
1428 /* perform binop */
1429 insn(opstr, src, dest, NULL);
1430 put_reg(src);
1432 /* store result in new pseudo / stack slot */
1433 new = stack_alloc(expr->ctype->bit_size / 8);
1434 emit_move(dest, new, NULL, "end EXPR_BINOP");
1436 put_reg(dest);
1438 return new;
1441 static int emit_conditional_test(struct storage *val)
1443 struct storage *reg;
1444 struct storage *target_val;
1445 int target_false;
1447 /* load result into EAX */
1448 emit_comment("begin if/conditional");
1449 reg = get_reg_value(val, &regclass_32);
1451 /* compare result with zero */
1452 insn("test", reg, reg, NULL);
1453 put_reg(reg);
1455 /* create conditional-failed label to jump to */
1456 target_false = new_label();
1457 target_val = new_storage(STOR_LABEL);
1458 target_val->label = target_false;
1459 target_val->flags = STOR_WANTS_FREE;
1460 insn("jz", target_val, NULL, NULL);
1462 return target_false;
1465 static int emit_conditional_end(int target_false)
1467 struct storage *cond_end_st;
1468 int cond_end;
1470 /* finished generating code for if-true statement.
1471 * add a jump-to-end jump to avoid falling through
1472 * to the if-false statement code.
1474 cond_end = new_label();
1475 cond_end_st = new_storage(STOR_LABEL);
1476 cond_end_st->label = cond_end;
1477 cond_end_st->flags = STOR_WANTS_FREE;
1478 insn("jmp", cond_end_st, NULL, NULL);
1480 /* if we have both if-true and if-false statements,
1481 * the failed-conditional case will fall through to here
1483 emit_label(target_false, NULL);
1485 return cond_end;
1488 static void emit_if_conditional(struct statement *stmt)
1490 struct storage *val;
1491 int cond_end;
1493 /* emit test portion of conditional */
1494 val = x86_expression(stmt->if_conditional);
1495 cond_end = emit_conditional_test(val);
1497 /* emit if-true statement */
1498 x86_statement(stmt->if_true);
1500 /* emit if-false statement, if present */
1501 if (stmt->if_false) {
1502 cond_end = emit_conditional_end(cond_end);
1503 x86_statement(stmt->if_false);
1506 /* end of conditional; jump target for if-true branch */
1507 emit_label(cond_end, "end if");
1510 static struct storage *emit_inc_dec(struct expression *expr, int postop)
1512 struct storage *addr = x86_address_gen(expr->unop);
1513 struct storage *retval;
1514 char opname[16];
1516 strcpy(opname, opbits(expr->op == SPECIAL_INCREMENT ? "inc" : "dec",
1517 expr->ctype->bit_size));
1519 if (postop) {
1520 struct storage *new = stack_alloc(4);
1522 emit_copy(new, addr, expr->unop->ctype);
1524 retval = new;
1525 } else
1526 retval = addr;
1528 insn(opname, addr, NULL, NULL);
1530 return retval;
1533 static struct storage *emit_postop(struct expression *expr)
1535 return emit_inc_dec(expr, 1);
1538 static struct storage *emit_return_stmt(struct statement *stmt)
1540 struct function *f = current_func;
1541 struct expression *expr = stmt->ret_value;
1542 struct storage *val = NULL, *jmplbl;
1544 if (expr && expr->ctype) {
1545 val = x86_expression(expr);
1546 assert(val != NULL);
1547 emit_move(val, REG_EAX, expr->ctype, "return");
1550 jmplbl = new_storage(STOR_LABEL);
1551 jmplbl->flags |= STOR_WANTS_FREE;
1552 jmplbl->label = f->ret_target;
1553 insn("jmp", jmplbl, NULL, NULL);
1555 return val;
1558 static struct storage *emit_conditional_expr(struct expression *expr)
1560 struct storage *cond, *true = NULL, *false = NULL;
1561 struct storage *new = stack_alloc(expr->ctype->bit_size / 8);
1562 int target_false, cond_end;
1564 /* evaluate conditional */
1565 cond = x86_expression(expr->conditional);
1566 target_false = emit_conditional_test(cond);
1568 /* handle if-true part of the expression */
1569 true = x86_expression(expr->cond_true);
1571 emit_copy(new, true, expr->ctype);
1573 cond_end = emit_conditional_end(target_false);
1575 /* handle if-false part of the expression */
1576 false = x86_expression(expr->cond_false);
1578 emit_copy(new, false, expr->ctype);
1580 /* end of conditional; jump target for if-true branch */
1581 emit_label(cond_end, "end conditional");
1583 return new;
1586 static struct storage *emit_select_expr(struct expression *expr)
1588 struct storage *cond = x86_expression(expr->conditional);
1589 struct storage *true = x86_expression(expr->cond_true);
1590 struct storage *false = x86_expression(expr->cond_false);
1591 struct storage *reg_cond, *reg_true, *reg_false;
1592 struct storage *new = stack_alloc(4);
1594 emit_comment("begin SELECT");
1595 reg_cond = get_reg_value(cond, get_regclass(expr->conditional));
1596 reg_true = get_reg_value(true, get_regclass(expr));
1597 reg_false = get_reg_value(false, get_regclass(expr));
1600 * Do the actual select: check the conditional for zero,
1601 * move false over true if zero
1603 insn("test", reg_cond, reg_cond, NULL);
1604 insn("cmovz", reg_false, reg_true, NULL);
1606 /* Store it back */
1607 emit_move(reg_true, new, expr->ctype, NULL);
1608 put_reg(reg_cond);
1609 put_reg(reg_true);
1610 put_reg(reg_false);
1611 emit_comment("end SELECT");
1612 return new;
1615 static struct storage *emit_symbol_expr_init(struct symbol *sym)
1617 struct expression *expr = sym->initializer;
1618 struct symbol_private *priv = sym->aux;
1620 if (priv == NULL) {
1621 priv = calloc(1, sizeof(*priv));
1622 sym->aux = priv;
1624 if (expr == NULL) {
1625 struct storage *new = stack_alloc(4);
1626 fprintf(stderr, "FIXME! no value for symbol %s. creating pseudo %d (stack offset %d)\n",
1627 show_ident(sym->ident),
1628 new->pseudo, new->pseudo * 4);
1629 priv->addr = new;
1630 } else {
1631 priv->addr = x86_expression(expr);
1635 return priv->addr;
1638 static struct storage *emit_string_expr(struct expression *expr)
1640 struct function *f = current_func;
1641 int label = new_label();
1642 struct storage *new;
1644 push_cstring(f, expr->string, label);
1646 new = new_storage(STOR_LABEL);
1647 new->label = label;
1648 new->flags = STOR_LABEL_VAL | STOR_WANTS_FREE;
1649 return new;
1652 static struct storage *emit_cast_expr(struct expression *expr)
1654 struct symbol *old_type, *new_type;
1655 struct storage *op = x86_expression(expr->cast_expression);
1656 int oldbits, newbits;
1657 struct storage *new;
1659 old_type = expr->cast_expression->ctype;
1660 new_type = expr->cast_type;
1662 oldbits = old_type->bit_size;
1663 newbits = new_type->bit_size;
1664 if (oldbits >= newbits)
1665 return op;
1667 emit_move(op, REG_EAX, old_type, "begin cast ..");
1669 new = stack_alloc(newbits / 8);
1670 emit_move(REG_EAX, new, new_type, ".... end cast");
1672 return new;
1675 static struct storage *emit_regular_preop(struct expression *expr)
1677 struct storage *target = x86_expression(expr->unop);
1678 struct storage *val, *new = stack_alloc(4);
1679 const char *opname = NULL;
1681 switch (expr->op) {
1682 case '!':
1683 val = new_storage(STOR_VALUE);
1684 val->flags = STOR_WANTS_FREE;
1685 emit_move(val, REG_EDX, NULL, NULL);
1686 emit_move(target, REG_EAX, expr->unop->ctype, NULL);
1687 insn("test", REG_EAX, REG_EAX, NULL);
1688 insn("setz", REG_DL, NULL, NULL);
1689 emit_move(REG_EDX, new, expr->unop->ctype, NULL);
1691 break;
1692 case '~':
1693 opname = "not";
1694 case '-':
1695 if (!opname)
1696 opname = "neg";
1697 emit_move(target, REG_EAX, expr->unop->ctype, NULL);
1698 insn(opname, REG_EAX, NULL, NULL);
1699 emit_move(REG_EAX, new, expr->unop->ctype, NULL);
1700 break;
1701 default:
1702 assert(0);
1703 break;
1706 return new;
1709 static void emit_case_statement(struct statement *stmt)
1711 emit_labelsym(stmt->case_label, NULL);
1712 x86_statement(stmt->case_statement);
1715 static void emit_switch_statement(struct statement *stmt)
1717 struct storage *val = x86_expression(stmt->switch_expression);
1718 struct symbol *sym, *default_sym = NULL;
1719 struct storage *labelsym, *label;
1720 int switch_end = 0;
1722 emit_move(val, REG_EAX, stmt->switch_expression->ctype, "begin case");
1725 * This is where a _real_ back-end would go through the
1726 * cases to decide whether to use a lookup table or a
1727 * series of comparisons etc
1729 FOR_EACH_PTR(stmt->switch_case->symbol_list, sym) {
1730 struct statement *case_stmt = sym->stmt;
1731 struct expression *expr = case_stmt->case_expression;
1732 struct expression *to = case_stmt->case_to;
1734 /* default: */
1735 if (!expr)
1736 default_sym = sym;
1738 /* case NNN: */
1739 else {
1740 struct storage *case_val = new_val(expr->value);
1742 assert (expr->type == EXPR_VALUE);
1744 insn("cmpl", case_val, REG_EAX, NULL);
1746 if (!to) {
1747 labelsym = new_labelsym(sym);
1748 insn("je", labelsym, NULL, NULL);
1749 } else {
1750 int next_test;
1752 label = new_storage(STOR_LABEL);
1753 label->flags |= STOR_WANTS_FREE;
1754 label->label = next_test = new_label();
1756 /* FIXME: signed/unsigned */
1757 insn("jl", label, NULL, NULL);
1759 case_val = new_val(to->value);
1760 insn("cmpl", case_val, REG_EAX, NULL);
1762 /* TODO: implement and use refcounting... */
1763 label = new_storage(STOR_LABEL);
1764 label->flags |= STOR_WANTS_FREE;
1765 label->label = next_test;
1767 /* FIXME: signed/unsigned */
1768 insn("jg", label, NULL, NULL);
1770 labelsym = new_labelsym(sym);
1771 insn("jmp", labelsym, NULL, NULL);
1773 emit_label(next_test, NULL);
1776 } END_FOR_EACH_PTR(sym);
1778 if (default_sym) {
1779 labelsym = new_labelsym(default_sym);
1780 insn("jmp", labelsym, NULL, "default");
1781 } else {
1782 label = new_storage(STOR_LABEL);
1783 label->flags |= STOR_WANTS_FREE;
1784 label->label = switch_end = new_label();
1785 insn("jmp", label, NULL, "goto end of switch");
1788 x86_statement(stmt->switch_statement);
1790 if (stmt->switch_break->used)
1791 emit_labelsym(stmt->switch_break, NULL);
1793 if (switch_end)
1794 emit_label(switch_end, NULL);
1797 static void x86_struct_member(struct symbol *sym)
1799 printf("\t%s:%d:%ld at offset %ld.%d", show_ident(sym->ident), sym->bit_size, sym->ctype.alignment, sym->offset, sym->bit_offset);
1800 printf("\n");
1803 static void x86_symbol(struct symbol *sym)
1805 struct symbol *type;
1807 if (!sym)
1808 return;
1810 type = sym->ctype.base_type;
1811 if (!type)
1812 return;
1815 * Show actual implementation information
1817 switch (type->type) {
1819 case SYM_ARRAY:
1820 if (sym->initializer)
1821 emit_array(sym);
1822 else
1823 emit_array_noinit(sym);
1824 break;
1826 case SYM_BASETYPE:
1827 if (sym->initializer) {
1828 emit_object_pre(show_ident(sym->ident),
1829 sym->ctype.modifiers,
1830 sym->ctype.alignment,
1831 sym->bit_size / 8);
1832 emit_scalar(sym->initializer, sym->bit_size);
1833 stor_sym_init(sym);
1834 } else
1835 emit_scalar_noinit(sym);
1836 break;
1838 case SYM_STRUCT:
1839 case SYM_UNION: {
1840 struct symbol *member;
1842 printf(" {\n");
1843 FOR_EACH_PTR(type->symbol_list, member) {
1844 x86_struct_member(member);
1845 } END_FOR_EACH_PTR(member);
1846 printf("}\n");
1847 break;
1850 case SYM_FN: {
1851 struct statement *stmt = type->stmt;
1852 if (stmt) {
1853 emit_func_pre(sym);
1854 x86_statement(stmt);
1855 emit_func_post(sym);
1857 break;
1860 default:
1861 break;
1864 if (sym->initializer && (type->type != SYM_BASETYPE) &&
1865 (type->type != SYM_ARRAY)) {
1866 printf(" = \n");
1867 x86_expression(sym->initializer);
1871 static void x86_symbol_init(struct symbol *sym);
1873 static void x86_symbol_decl(struct symbol_list *syms)
1875 struct symbol *sym;
1876 FOR_EACH_PTR(syms, sym) {
1877 x86_symbol_init(sym);
1878 } END_FOR_EACH_PTR(sym);
1881 static void loopstk_push(int cont_lbl, int loop_bottom_lbl)
1883 struct function *f = current_func;
1884 struct loop_stack *ls;
1886 ls = malloc(sizeof(*ls));
1887 ls->continue_lbl = cont_lbl;
1888 ls->loop_bottom_lbl = loop_bottom_lbl;
1889 ls->next = f->loop_stack;
1890 f->loop_stack = ls;
1893 static void loopstk_pop(void)
1895 struct function *f = current_func;
1896 struct loop_stack *ls;
1898 assert(f->loop_stack != NULL);
1899 ls = f->loop_stack;
1900 f->loop_stack = f->loop_stack->next;
1901 free(ls);
1904 static int loopstk_break(void)
1906 return current_func->loop_stack->loop_bottom_lbl;
1909 static int loopstk_continue(void)
1911 return current_func->loop_stack->continue_lbl;
1914 static void emit_loop(struct statement *stmt)
1916 struct statement *pre_statement = stmt->iterator_pre_statement;
1917 struct expression *pre_condition = stmt->iterator_pre_condition;
1918 struct statement *statement = stmt->iterator_statement;
1919 struct statement *post_statement = stmt->iterator_post_statement;
1920 struct expression *post_condition = stmt->iterator_post_condition;
1921 int loop_top = 0, loop_bottom, loop_continue;
1922 int have_bottom = 0;
1923 struct storage *val;
1925 loop_bottom = new_label();
1926 loop_continue = new_label();
1927 loopstk_push(loop_continue, loop_bottom);
1929 x86_symbol_decl(stmt->iterator_syms);
1930 x86_statement(pre_statement);
1931 if (!post_condition || post_condition->type != EXPR_VALUE || post_condition->value) {
1932 loop_top = new_label();
1933 emit_label(loop_top, "loop top");
1935 if (pre_condition) {
1936 if (pre_condition->type == EXPR_VALUE) {
1937 if (!pre_condition->value) {
1938 struct storage *lbv;
1939 lbv = new_storage(STOR_LABEL);
1940 lbv->label = loop_bottom;
1941 lbv->flags = STOR_WANTS_FREE;
1942 insn("jmp", lbv, NULL, "go to loop bottom");
1943 have_bottom = 1;
1945 } else {
1946 struct storage *lbv = new_storage(STOR_LABEL);
1947 lbv->label = loop_bottom;
1948 lbv->flags = STOR_WANTS_FREE;
1949 have_bottom = 1;
1951 val = x86_expression(pre_condition);
1953 emit_move(val, REG_EAX, NULL, "loop pre condition");
1954 insn("test", REG_EAX, REG_EAX, NULL);
1955 insn("jz", lbv, NULL, NULL);
1958 x86_statement(statement);
1959 if (stmt->iterator_continue->used)
1960 emit_label(loop_continue, "'continue' iterator");
1961 x86_statement(post_statement);
1962 if (!post_condition) {
1963 struct storage *lbv = new_storage(STOR_LABEL);
1964 lbv->label = loop_top;
1965 lbv->flags = STOR_WANTS_FREE;
1966 insn("jmp", lbv, NULL, "go to loop top");
1967 } else if (post_condition->type == EXPR_VALUE) {
1968 if (post_condition->value) {
1969 struct storage *lbv = new_storage(STOR_LABEL);
1970 lbv->label = loop_top;
1971 lbv->flags = STOR_WANTS_FREE;
1972 insn("jmp", lbv, NULL, "go to loop top");
1974 } else {
1975 struct storage *lbv = new_storage(STOR_LABEL);
1976 lbv->label = loop_top;
1977 lbv->flags = STOR_WANTS_FREE;
1979 val = x86_expression(post_condition);
1981 emit_move(val, REG_EAX, NULL, "loop post condition");
1982 insn("test", REG_EAX, REG_EAX, NULL);
1983 insn("jnz", lbv, NULL, NULL);
1985 if (have_bottom || stmt->iterator_break->used)
1986 emit_label(loop_bottom, "loop bottom");
1988 loopstk_pop();
1992 * Print out a statement
1994 static struct storage *x86_statement(struct statement *stmt)
1996 if (!stmt)
1997 return NULL;
1998 switch (stmt->type) {
1999 default:
2000 return NULL;
2001 case STMT_RETURN:
2002 return emit_return_stmt(stmt);
2003 case STMT_DECLARATION:
2004 x86_symbol_decl(stmt->declaration);
2005 break;
2006 case STMT_COMPOUND: {
2007 struct statement *s;
2008 struct storage *last = NULL;
2010 FOR_EACH_PTR(stmt->stmts, s) {
2011 last = x86_statement(s);
2012 } END_FOR_EACH_PTR(s);
2014 return last;
2017 case STMT_EXPRESSION:
2018 return x86_expression(stmt->expression);
2019 case STMT_IF:
2020 emit_if_conditional(stmt);
2021 return NULL;
2023 case STMT_CASE:
2024 emit_case_statement(stmt);
2025 break;
2026 case STMT_SWITCH:
2027 emit_switch_statement(stmt);
2028 break;
2030 case STMT_ITERATOR:
2031 emit_loop(stmt);
2032 break;
2034 case STMT_NONE:
2035 break;
2037 case STMT_LABEL:
2038 printf(".L%p:\n", stmt->label_identifier);
2039 x86_statement(stmt->label_statement);
2040 break;
2042 case STMT_GOTO:
2043 if (stmt->goto_expression) {
2044 struct storage *val = x86_expression(stmt->goto_expression);
2045 printf("\tgoto *v%d\n", val->pseudo);
2046 } else if (!strcmp("break", show_ident(stmt->goto_label->ident))) {
2047 struct storage *lbv = new_storage(STOR_LABEL);
2048 lbv->label = loopstk_break();
2049 lbv->flags = STOR_WANTS_FREE;
2050 insn("jmp", lbv, NULL, "'break'; go to loop bottom");
2051 } else if (!strcmp("continue", show_ident(stmt->goto_label->ident))) {
2052 struct storage *lbv = new_storage(STOR_LABEL);
2053 lbv->label = loopstk_continue();
2054 lbv->flags = STOR_WANTS_FREE;
2055 insn("jmp", lbv, NULL, "'continue'; go to loop top");
2056 } else {
2057 struct storage *labelsym = new_labelsym(stmt->goto_label);
2058 insn("jmp", labelsym, NULL, NULL);
2060 break;
2061 case STMT_ASM:
2062 printf("\tasm( .... )\n");
2063 break;
2065 return NULL;
2068 static struct storage *x86_call_expression(struct expression *expr)
2070 struct function *f = current_func;
2071 struct symbol *direct;
2072 struct expression *arg, *fn;
2073 struct storage *retval, *fncall;
2074 int framesize;
2075 char s[64];
2077 if (!expr->ctype) {
2078 warning(expr->pos, "\tcall with no type!");
2079 return NULL;
2082 framesize = 0;
2083 FOR_EACH_PTR_REVERSE(expr->args, arg) {
2084 struct storage *new = x86_expression(arg);
2085 int size = arg->ctype->bit_size;
2088 * FIXME: i386 SysV ABI dictates that values
2089 * smaller than 32 bits should be placed onto
2090 * the stack as 32-bit objects. We should not
2091 * blindly do a 32-bit push on objects smaller
2092 * than 32 bits.
2094 if (size < 32)
2095 size = 32;
2096 insn("pushl", new, NULL,
2097 !framesize ? "begin function call" : NULL);
2099 framesize += bits_to_bytes(size);
2100 } END_FOR_EACH_PTR_REVERSE(arg);
2102 fn = expr->fn;
2104 /* Remove dereference, if any */
2105 direct = NULL;
2106 if (fn->type == EXPR_PREOP) {
2107 if (fn->unop->type == EXPR_SYMBOL) {
2108 struct symbol *sym = fn->unop->symbol;
2109 if (sym->ctype.base_type->type == SYM_FN)
2110 direct = sym;
2113 if (direct) {
2114 struct storage *direct_stor = new_storage(STOR_SYM);
2115 direct_stor->flags |= STOR_WANTS_FREE;
2116 direct_stor->sym = direct;
2117 insn("call", direct_stor, NULL, NULL);
2118 } else {
2119 fncall = x86_expression(fn);
2120 emit_move(fncall, REG_EAX, fn->ctype, NULL);
2122 strcpy(s, "\tcall\t*%eax\n");
2123 push_text_atom(f, s);
2126 /* FIXME: pay attention to BITS_IN_POINTER */
2127 if (framesize) {
2128 struct storage *val = new_storage(STOR_VALUE);
2129 val->value = (long long) framesize;
2130 val->flags = STOR_WANTS_FREE;
2131 insn("addl", val, REG_ESP, NULL);
2134 retval = stack_alloc(4);
2135 emit_move(REG_EAX, retval, NULL, "end function call");
2137 return retval;
2140 static struct storage *x86_address_gen(struct expression *expr)
2142 struct function *f = current_func;
2143 struct storage *addr;
2144 struct storage *new;
2145 char s[32];
2147 addr = x86_expression(expr->unop);
2148 if (expr->unop->type == EXPR_SYMBOL)
2149 return addr;
2151 emit_move(addr, REG_EAX, NULL, "begin deref ..");
2153 /* FIXME: operand size */
2154 strcpy(s, "\tmovl\t(%eax), %ecx\n");
2155 push_text_atom(f, s);
2157 new = stack_alloc(4);
2158 emit_move(REG_ECX, new, NULL, ".... end deref");
2160 return new;
2163 static struct storage *x86_assignment(struct expression *expr)
2165 struct expression *target = expr->left;
2166 struct storage *val, *addr;
2168 if (!expr->ctype)
2169 return NULL;
2171 val = x86_expression(expr->right);
2172 addr = x86_address_gen(target);
2174 switch (val->type) {
2175 /* copy, where both operands are memory */
2176 case STOR_PSEUDO:
2177 case STOR_ARG:
2178 emit_copy(addr, val, expr->ctype);
2179 break;
2181 /* copy, one or zero operands are memory */
2182 case STOR_REG:
2183 case STOR_SYM:
2184 case STOR_VALUE:
2185 case STOR_LABEL:
2186 emit_move(val, addr, expr->left->ctype, NULL);
2187 break;
2189 case STOR_LABELSYM:
2190 assert(0);
2191 break;
2193 return val;
2196 static int x86_initialization(struct symbol *sym, struct expression *expr)
2198 struct storage *val, *addr;
2199 int bits;
2201 if (!expr->ctype)
2202 return 0;
2204 bits = expr->ctype->bit_size;
2205 val = x86_expression(expr);
2206 addr = x86_symbol_expr(sym);
2207 // FIXME! The "target" expression is for bitfield store information.
2208 // Leave it NULL, which works fine.
2209 emit_store(NULL, addr, val, bits);
2210 return 0;
2213 static struct storage *x86_access(struct expression *expr)
2215 return x86_address_gen(expr);
2218 static struct storage *x86_preop(struct expression *expr)
2221 * '*' is an lvalue access, and is fundamentally different
2222 * from an arithmetic operation. Maybe it should have an
2223 * expression type of its own..
2225 if (expr->op == '*')
2226 return x86_access(expr);
2227 if (expr->op == SPECIAL_INCREMENT || expr->op == SPECIAL_DECREMENT)
2228 return emit_inc_dec(expr, 0);
2229 return emit_regular_preop(expr);
2232 static struct storage *x86_symbol_expr(struct symbol *sym)
2234 struct storage *new = stack_alloc(4);
2236 if (sym->ctype.modifiers & (MOD_TOPLEVEL | MOD_EXTERN | MOD_STATIC)) {
2237 printf("\tmovi.%d\t\tv%d,$%s\n", bits_in_pointer, new->pseudo, show_ident(sym->ident));
2238 return new;
2240 if (sym->ctype.modifiers & MOD_ADDRESSABLE) {
2241 printf("\taddi.%d\t\tv%d,vFP,$%lld\n", bits_in_pointer, new->pseudo, sym->value);
2242 return new;
2244 printf("\taddi.%d\t\tv%d,vFP,$offsetof(%s:%p)\n", bits_in_pointer, new->pseudo, show_ident(sym->ident), sym);
2245 return new;
2248 static void x86_symbol_init(struct symbol *sym)
2250 struct symbol_private *priv = sym->aux;
2251 struct expression *expr = sym->initializer;
2252 struct storage *new;
2254 if (expr)
2255 new = x86_expression(expr);
2256 else
2257 new = stack_alloc(sym->bit_size / 8);
2259 if (!priv) {
2260 priv = calloc(1, sizeof(*priv));
2261 sym->aux = priv;
2262 /* FIXME: leak! we don't free... */
2263 /* (well, we don't free symbols either) */
2266 priv->addr = new;
2269 static int type_is_signed(struct symbol *sym)
2271 if (sym->type == SYM_NODE)
2272 sym = sym->ctype.base_type;
2273 if (sym->type == SYM_PTR)
2274 return 0;
2275 return !(sym->ctype.modifiers & MOD_UNSIGNED);
2278 static struct storage *x86_label_expr(struct expression *expr)
2280 struct storage *new = stack_alloc(4);
2281 printf("\tmovi.%d\t\tv%d,.L%p\n", bits_in_pointer, new->pseudo, expr->label_symbol);
2282 return new;
2285 static struct storage *x86_statement_expr(struct expression *expr)
2287 return x86_statement(expr->statement);
2290 static int x86_position_expr(struct expression *expr, struct symbol *base)
2292 struct storage *new = x86_expression(expr->init_expr);
2293 struct symbol *ctype = expr->init_expr->ctype;
2295 printf("\tinsert v%d at [%d:%d] of %s\n", new->pseudo,
2296 expr->init_offset, ctype->bit_offset,
2297 show_ident(base->ident));
2298 return 0;
2301 static void x86_initializer_expr(struct expression *expr, struct symbol *ctype)
2303 struct expression *entry;
2305 FOR_EACH_PTR(expr->expr_list, entry) {
2306 // Nested initializers have their positions already
2307 // recursively calculated - just output them too
2308 if (entry->type == EXPR_INITIALIZER) {
2309 x86_initializer_expr(entry, ctype);
2310 continue;
2313 // Ignore initializer indexes and identifiers - the
2314 // evaluator has taken them into account
2315 if (entry->type == EXPR_IDENTIFIER || entry->type == EXPR_INDEX)
2316 continue;
2317 if (entry->type == EXPR_POS) {
2318 x86_position_expr(entry, ctype);
2319 continue;
2321 x86_initialization(ctype, entry);
2322 } END_FOR_EACH_PTR(entry);
2326 * Print out an expression. Return the pseudo that contains the
2327 * variable.
2329 static struct storage *x86_expression(struct expression *expr)
2331 if (!expr)
2332 return NULL;
2334 if (!expr->ctype) {
2335 struct position *pos = &expr->pos;
2336 printf("\tno type at %s:%d:%d\n",
2337 stream_name(pos->stream),
2338 pos->line, pos->pos);
2339 return NULL;
2342 switch (expr->type) {
2343 default:
2344 return NULL;
2345 case EXPR_CALL:
2346 return x86_call_expression(expr);
2348 case EXPR_ASSIGNMENT:
2349 return x86_assignment(expr);
2351 case EXPR_COMPARE:
2352 return emit_compare(expr);
2353 case EXPR_BINOP:
2354 case EXPR_COMMA:
2355 case EXPR_LOGICAL:
2356 return emit_binop(expr);
2357 case EXPR_PREOP:
2358 return x86_preop(expr);
2359 case EXPR_POSTOP:
2360 return emit_postop(expr);
2361 case EXPR_SYMBOL:
2362 return emit_symbol_expr_init(expr->symbol);
2363 case EXPR_DEREF:
2364 case EXPR_SIZEOF:
2365 case EXPR_ALIGNOF:
2366 warning(expr->pos, "invalid expression after evaluation");
2367 return NULL;
2368 case EXPR_CAST:
2369 case EXPR_FORCE_CAST:
2370 case EXPR_IMPLIED_CAST:
2371 return emit_cast_expr(expr);
2372 case EXPR_VALUE:
2373 return emit_value(expr);
2374 case EXPR_STRING:
2375 return emit_string_expr(expr);
2376 case EXPR_INITIALIZER:
2377 x86_initializer_expr(expr, expr->ctype);
2378 return NULL;
2379 case EXPR_SELECT:
2380 return emit_select_expr(expr);
2381 case EXPR_CONDITIONAL:
2382 return emit_conditional_expr(expr);
2383 case EXPR_STATEMENT:
2384 return x86_statement_expr(expr);
2385 case EXPR_LABEL:
2386 return x86_label_expr(expr);
2388 // None of these should exist as direct expressions: they are only
2389 // valid as sub-expressions of initializers.
2390 case EXPR_POS:
2391 warning(expr->pos, "unable to show plain initializer position expression");
2392 return NULL;
2393 case EXPR_IDENTIFIER:
2394 warning(expr->pos, "unable to show identifier expression");
2395 return NULL;
2396 case EXPR_INDEX:
2397 warning(expr->pos, "unable to show index expression");
2398 return NULL;
2399 case EXPR_TYPE:
2400 warning(expr->pos, "unable to show type expression");
2401 return NULL;
2402 case EXPR_FVALUE:
2403 warning(expr->pos, "floating point support is not implemented");
2404 return NULL;
2406 return NULL;