function_hooks: hack around fallout from moving the assignment to the end
[smatch.git] / compile-i386.c
blob1242d384191385bc6f95825fce2d226dcade3303
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"
60 #include "version.h"
62 struct textbuf {
63 unsigned int len; /* does NOT include terminating null */
64 char *text;
65 struct textbuf *next;
66 struct textbuf *prev;
69 struct loop_stack {
70 int continue_lbl;
71 int loop_bottom_lbl;
72 struct loop_stack *next;
75 struct atom;
76 struct storage;
77 DECLARE_PTR_LIST(str_list, struct atom);
78 DECLARE_PTR_LIST(atom_list, struct atom);
79 DECLARE_PTR_LIST(storage_list, struct storage);
81 struct function {
82 int stack_size;
83 int pseudo_nr;
84 struct storage_list *pseudo_list;
85 struct atom_list *atom_list;
86 struct str_list *str_list;
87 struct loop_stack *loop_stack;
88 struct symbol **argv;
89 unsigned int argc;
90 int ret_target;
93 enum storage_type {
94 STOR_PSEUDO, /* variable stored on the stack */
95 STOR_ARG, /* function argument */
96 STOR_SYM, /* a symbol we can directly ref in the asm */
97 STOR_REG, /* scratch register */
98 STOR_VALUE, /* integer constant */
99 STOR_LABEL, /* label / jump target */
100 STOR_LABELSYM, /* label generated from symbol's pointer value */
103 struct reg_info {
104 const char *name;
105 struct storage *contains;
106 const unsigned char aliases[12];
107 #define own_regno aliases[0]
110 struct storage {
111 enum storage_type type;
112 unsigned long flags;
114 /* STOR_REG */
115 struct reg_info *reg;
116 struct symbol *ctype;
118 union {
119 /* STOR_PSEUDO */
120 struct {
121 int pseudo;
122 int offset;
123 int size;
125 /* STOR_ARG */
126 struct {
127 int idx;
129 /* STOR_SYM */
130 struct {
131 struct symbol *sym;
133 /* STOR_VALUE */
134 struct {
135 long long value;
137 /* STOR_LABEL */
138 struct {
139 int label;
141 /* STOR_LABELSYM */
142 struct {
143 struct symbol *labelsym;
148 enum {
149 STOR_LABEL_VAL = (1 << 0),
150 STOR_WANTS_FREE = (1 << 1),
153 struct symbol_private {
154 struct storage *addr;
157 enum atom_type {
158 ATOM_TEXT,
159 ATOM_INSN,
160 ATOM_CSTR,
163 struct atom {
164 enum atom_type type;
165 union {
166 /* stuff for text */
167 struct {
168 char *text;
169 unsigned int text_len; /* w/o terminating null */
172 /* stuff for insns */
173 struct {
174 char insn[32];
175 char comment[40];
176 struct storage *op1;
177 struct storage *op2;
180 /* stuff for C strings */
181 struct {
182 struct string *string;
183 int label;
189 static struct function *current_func = NULL;
190 static struct textbuf *unit_post_text = NULL;
191 static const char *current_section;
193 static void emit_comment(const char * fmt, ...) FORMAT_ATTR(1);
194 static void emit_move(struct storage *src, struct storage *dest,
195 struct symbol *ctype, const char *comment);
196 static int type_is_signed(struct symbol *sym);
197 static struct storage *x86_address_gen(struct expression *expr);
198 static struct storage *x86_symbol_expr(struct symbol *sym);
199 static void x86_symbol(struct symbol *sym);
200 static struct storage *x86_statement(struct statement *stmt);
201 static struct storage *x86_expression(struct expression *expr);
203 enum registers {
204 NOREG,
205 AL, DL, CL, BL, AH, DH, CH, BH, // 8-bit
206 AX, DX, CX, BX, SI, DI, BP, SP, // 16-bit
207 EAX, EDX, ECX, EBX, ESI, EDI, EBP, ESP, // 32-bit
208 EAX_EDX, ECX_EBX, ESI_EDI, // 64-bit
211 /* This works on regno's, reg_info's and hardreg_storage's */
212 #define byte_reg(reg) ((reg) - 16)
213 #define highbyte_reg(reg) ((reg)-12)
214 #define word_reg(reg) ((reg)-8)
216 #define REGINFO(nr, str, conflicts...) [nr] = { .name = str, .aliases = { nr , conflicts } }
218 static struct reg_info reg_info_table[] = {
219 REGINFO( AL, "%al", AX, EAX, EAX_EDX),
220 REGINFO( DL, "%dl", DX, EDX, EAX_EDX),
221 REGINFO( CL, "%cl", CX, ECX, ECX_EBX),
222 REGINFO( BL, "%bl", BX, EBX, ECX_EBX),
223 REGINFO( AH, "%ah", AX, EAX, EAX_EDX),
224 REGINFO( DH, "%dh", DX, EDX, EAX_EDX),
225 REGINFO( CH, "%ch", CX, ECX, ECX_EBX),
226 REGINFO( BH, "%bh", BX, EBX, ECX_EBX),
227 REGINFO( AX, "%ax", AL, AH, EAX, EAX_EDX),
228 REGINFO( DX, "%dx", DL, DH, EDX, EAX_EDX),
229 REGINFO( CX, "%cx", CL, CH, ECX, ECX_EBX),
230 REGINFO( BX, "%bx", BL, BH, EBX, ECX_EBX),
231 REGINFO( SI, "%si", ESI, ESI_EDI),
232 REGINFO( DI, "%di", EDI, ESI_EDI),
233 REGINFO( BP, "%bp", EBP),
234 REGINFO( SP, "%sp", ESP),
235 REGINFO(EAX, "%eax", AL, AH, AX, EAX_EDX),
236 REGINFO(EDX, "%edx", DL, DH, DX, EAX_EDX),
237 REGINFO(ECX, "%ecx", CL, CH, CX, ECX_EBX),
238 REGINFO(EBX, "%ebx", BL, BH, BX, ECX_EBX),
239 REGINFO(ESI, "%esi", SI, ESI_EDI),
240 REGINFO(EDI, "%edi", DI, ESI_EDI),
241 REGINFO(EBP, "%ebp", BP),
242 REGINFO(ESP, "%esp", SP),
243 REGINFO(EAX_EDX, "%eax:%edx", AL, AH, AX, EAX, DL, DH, DX, EDX),
244 REGINFO(ECX_EBX, "%ecx:%ebx", CL, CH, CX, ECX, BL, BH, BX, EBX),
245 REGINFO(ESI_EDI, "%esi:%edi", SI, ESI, DI, EDI),
248 #define REGSTORAGE(nr) [nr] = { .type = STOR_REG, .reg = reg_info_table + (nr) }
250 static struct storage hardreg_storage_table[] = {
251 REGSTORAGE(AL), REGSTORAGE(DL), REGSTORAGE(CL), REGSTORAGE(BL),
252 REGSTORAGE(AH), REGSTORAGE(DH), REGSTORAGE(CH), REGSTORAGE(BH),
253 REGSTORAGE(AX), REGSTORAGE(DX), REGSTORAGE(CX), REGSTORAGE(BX),
254 REGSTORAGE(SI), REGSTORAGE(DI), REGSTORAGE(BP), REGSTORAGE(SP),
255 REGSTORAGE(EAX), REGSTORAGE(EDX), REGSTORAGE(ECX), REGSTORAGE(EBX),
256 REGSTORAGE(ESI), REGSTORAGE(EDI), REGSTORAGE(EBP), REGSTORAGE(ESP),
257 REGSTORAGE(EAX_EDX), REGSTORAGE(ECX_EBX), REGSTORAGE(ESI_EDI),
260 #define REG_EAX (&hardreg_storage_table[EAX])
261 #define REG_ECX (&hardreg_storage_table[ECX])
262 #define REG_EDX (&hardreg_storage_table[EDX])
263 #define REG_ESP (&hardreg_storage_table[ESP])
264 #define REG_DL (&hardreg_storage_table[DL])
265 #define REG_DX (&hardreg_storage_table[DX])
266 #define REG_AL (&hardreg_storage_table[AL])
267 #define REG_AX (&hardreg_storage_table[AX])
269 static DECLARE_BITMAP(regs_in_use, 256);
271 static inline struct storage * reginfo_reg(struct reg_info *info)
273 return hardreg_storage_table + info->own_regno;
276 static struct storage * get_hardreg(struct storage *reg, int clear)
278 struct reg_info *info = reg->reg;
279 const unsigned char *aliases;
280 int regno;
282 aliases = info->aliases;
283 while ((regno = *aliases++) != NOREG) {
284 if (test_bit(regno, regs_in_use))
285 goto busy;
286 if (clear)
287 reg_info_table[regno].contains = NULL;
289 set_bit(info->own_regno, regs_in_use);
290 return reg;
291 busy:
292 fprintf(stderr, "register %s is busy\n", info->name);
293 if (regno + reg_info_table != info)
294 fprintf(stderr, " conflicts with %s\n", reg_info_table[regno].name);
295 exit(1);
298 static void put_reg(struct storage *reg)
300 struct reg_info *info = reg->reg;
301 int regno = info->own_regno;
303 if (test_and_clear_bit(regno, regs_in_use))
304 return;
305 fprintf(stderr, "freeing already free'd register %s\n", reg_info_table[regno].name);
308 struct regclass {
309 const char *name;
310 const unsigned char regs[30];
313 static struct regclass regclass_8 = { "8-bit", { AL, DL, CL, BL, AH, DH, CH, BH }};
314 static struct regclass regclass_16 = { "16-bit", { AX, DX, CX, BX, SI, DI, BP }};
315 static struct regclass regclass_32 = { "32-bit", { EAX, EDX, ECX, EBX, ESI, EDI, EBP }};
316 static struct regclass regclass_64 = { "64-bit", { EAX_EDX, ECX_EBX, ESI_EDI }};
318 static struct regclass regclass_32_8 = { "32-bit bytes", { EAX, EDX, ECX, EBX }};
320 static struct regclass *get_regclass_bits(int bits)
322 switch (bits) {
323 case 8: return &regclass_8;
324 case 16: return &regclass_16;
325 case 64: return &regclass_64;
326 default: return &regclass_32;
330 static struct regclass *get_regclass(struct expression *expr)
332 return get_regclass_bits(expr->ctype->bit_size);
335 static int register_busy(int regno)
337 if (!test_bit(regno, regs_in_use)) {
338 struct reg_info *info = reg_info_table + regno;
339 const unsigned char *regs = info->aliases+1;
341 while ((regno = *regs) != NOREG) {
342 regs++;
343 if (test_bit(regno, regs_in_use))
344 goto busy;
346 return 0;
348 busy:
349 return 1;
352 static struct storage *get_reg(struct regclass *class)
354 const unsigned char *regs = class->regs;
355 int regno;
357 while ((regno = *regs) != NOREG) {
358 regs++;
359 if (register_busy(regno))
360 continue;
361 return get_hardreg(hardreg_storage_table + regno, 1);
363 fprintf(stderr, "Ran out of %s registers\n", class->name);
364 exit(1);
367 static struct storage *get_reg_value(struct storage *value, struct regclass *class)
369 struct reg_info *info;
370 struct storage *reg;
372 /* Do we already have it somewhere */
373 info = value->reg;
374 if (info && info->contains == value) {
375 emit_comment("already have register %s", info->name);
376 return get_hardreg(hardreg_storage_table + info->own_regno, 0);
379 reg = get_reg(class);
380 emit_move(value, reg, value->ctype, "reload register");
381 info = reg->reg;
382 info->contains = value;
383 value->reg = info;
384 return reg;
387 static struct storage *temp_from_bits(unsigned int bit_size)
389 return get_reg(get_regclass_bits(bit_size));
392 static inline unsigned int pseudo_offset(struct storage *s)
394 if (s->type != STOR_PSEUDO)
395 return 123456; /* intentionally bogus value */
397 return s->offset;
400 static inline unsigned int arg_offset(struct storage *s)
402 if (s->type != STOR_ARG)
403 return 123456; /* intentionally bogus value */
405 /* FIXME: this is wrong wrong wrong */
406 return current_func->stack_size + ((1 + s->idx) * 4);
409 static const char *pretty_offset(int ofs)
411 static char esp_buf[64];
413 if (ofs)
414 sprintf(esp_buf, "%d(%%esp)", ofs);
415 else
416 strcpy(esp_buf, "(%esp)");
418 return esp_buf;
421 static void stor_sym_init(struct symbol *sym)
423 struct storage *stor;
424 struct symbol_private *priv;
426 priv = calloc(1, sizeof(*priv) + sizeof(*stor));
427 if (!priv)
428 die("OOM in stor_sym_init");
430 stor = (struct storage *) (priv + 1);
432 priv->addr = stor;
433 stor->type = STOR_SYM;
434 stor->sym = sym;
437 static const char *stor_op_name(struct storage *s)
439 static char name[32];
441 switch (s->type) {
442 case STOR_PSEUDO:
443 strcpy(name, pretty_offset((int) pseudo_offset(s)));
444 break;
445 case STOR_ARG:
446 strcpy(name, pretty_offset((int) arg_offset(s)));
447 break;
448 case STOR_SYM:
449 strcpy(name, show_ident(s->sym->ident));
450 break;
451 case STOR_REG:
452 strcpy(name, s->reg->name);
453 break;
454 case STOR_VALUE:
455 sprintf(name, "$%Ld", s->value);
456 break;
457 case STOR_LABEL:
458 sprintf(name, "%s.L%d", s->flags & STOR_LABEL_VAL ? "$" : "",
459 s->label);
460 break;
461 case STOR_LABELSYM:
462 sprintf(name, "%s.LS%p", s->flags & STOR_LABEL_VAL ? "$" : "",
463 s->labelsym);
464 break;
467 return name;
470 static struct atom *new_atom(enum atom_type type)
472 struct atom *atom;
474 atom = calloc(1, sizeof(*atom)); /* TODO: chunked alloc */
475 if (!atom)
476 die("nuclear OOM");
478 atom->type = type;
480 return atom;
483 static inline void push_cstring(struct function *f, struct string *str,
484 int label)
486 struct atom *atom;
488 atom = new_atom(ATOM_CSTR);
489 atom->string = str;
490 atom->label = label;
492 add_ptr_list(&f->str_list, atom); /* note: _not_ atom_list */
495 static inline void push_atom(struct function *f, struct atom *atom)
497 add_ptr_list(&f->atom_list, atom);
500 static void push_text_atom(struct function *f, const char *text)
502 struct atom *atom = new_atom(ATOM_TEXT);
504 atom->text = strdup(text);
505 atom->text_len = strlen(text);
507 push_atom(f, atom);
510 static struct storage *new_storage(enum storage_type type)
512 struct storage *stor;
514 stor = calloc(1, sizeof(*stor));
515 if (!stor)
516 die("OOM in new_storage");
518 stor->type = type;
520 return stor;
523 static struct storage *stack_alloc(int n_bytes)
525 struct function *f = current_func;
526 struct storage *stor;
528 assert(f != NULL);
530 stor = new_storage(STOR_PSEUDO);
531 stor->type = STOR_PSEUDO;
532 stor->pseudo = f->pseudo_nr;
533 stor->offset = f->stack_size; /* FIXME: stack req. natural align */
534 stor->size = n_bytes;
535 f->stack_size += n_bytes;
536 f->pseudo_nr++;
538 add_ptr_list(&f->pseudo_list, stor);
540 return stor;
543 static struct storage *new_labelsym(struct symbol *sym)
545 struct storage *stor;
547 stor = new_storage(STOR_LABELSYM);
549 if (stor) {
550 stor->flags |= STOR_WANTS_FREE;
551 stor->labelsym = sym;
554 return stor;
557 static struct storage *new_val(long long value)
559 struct storage *stor;
561 stor = new_storage(STOR_VALUE);
563 if (stor) {
564 stor->flags |= STOR_WANTS_FREE;
565 stor->value = value;
568 return stor;
571 static int new_label(void)
573 static int label = 0;
574 return ++label;
577 static void textbuf_push(struct textbuf **buf_p, const char *text)
579 struct textbuf *tmp, *list = *buf_p;
580 unsigned int text_len = strlen(text);
581 unsigned int alloc_len = text_len + 1 + sizeof(*list);
583 tmp = calloc(1, alloc_len);
584 if (!tmp)
585 die("OOM on textbuf alloc");
587 tmp->text = ((void *) tmp) + sizeof(*tmp);
588 memcpy(tmp->text, text, text_len + 1);
589 tmp->len = text_len;
591 /* add to end of list */
592 if (!list) {
593 list = tmp;
594 tmp->prev = tmp;
595 } else {
596 tmp->prev = list->prev;
597 tmp->prev->next = tmp;
598 list->prev = tmp;
600 tmp->next = list;
602 *buf_p = list;
605 static void textbuf_emit(struct textbuf **buf_p)
607 struct textbuf *tmp, *list = *buf_p;
609 while (list) {
610 tmp = list;
611 if (tmp->next == tmp)
612 list = NULL;
613 else {
614 tmp->prev->next = tmp->next;
615 tmp->next->prev = tmp->prev;
616 list = tmp->next;
619 fputs(tmp->text, stdout);
621 free(tmp);
624 *buf_p = list;
627 static void insn(const char *insn, struct storage *op1, struct storage *op2,
628 const char *comment_in)
630 struct function *f = current_func;
631 struct atom *atom = new_atom(ATOM_INSN);
633 assert(insn != NULL);
635 strcpy(atom->insn, insn);
636 if (comment_in && (*comment_in))
637 strncpy(atom->comment, comment_in,
638 sizeof(atom->comment) - 1);
640 atom->op1 = op1;
641 atom->op2 = op2;
643 push_atom(f, atom);
646 static void emit_comment(const char *fmt, ...)
648 struct function *f = current_func;
649 static char tmpbuf[100] = "\t# ";
650 va_list args;
651 int i;
653 va_start(args, fmt);
654 i = vsnprintf(tmpbuf+3, sizeof(tmpbuf)-4, fmt, args);
655 va_end(args);
656 tmpbuf[i+3] = '\n';
657 tmpbuf[i+4] = '\0';
658 push_text_atom(f, tmpbuf);
661 static void emit_label (int label, const char *comment)
663 struct function *f = current_func;
664 char s[64];
666 if (!comment)
667 sprintf(s, ".L%d:\n", label);
668 else
669 sprintf(s, ".L%d:\t\t\t\t\t# %s\n", label, comment);
671 push_text_atom(f, s);
674 static void emit_labelsym (struct symbol *sym, const char *comment)
676 struct function *f = current_func;
677 char s[64];
679 if (!comment)
680 sprintf(s, ".LS%p:\n", sym);
681 else
682 sprintf(s, ".LS%p:\t\t\t\t# %s\n", sym, comment);
684 push_text_atom(f, s);
687 void emit_unit_begin(const char *basename)
689 printf("\t.file\t\"%s\"\n", basename);
692 void emit_unit_end(void)
694 textbuf_emit(&unit_post_text);
695 printf("\t.ident\t\"sparse silly x86 backend (version %s)\"\n", SPARSE_VERSION);
698 /* conditionally switch sections */
699 static void emit_section(const char *s)
701 if (s == current_section)
702 return;
703 if (current_section && (!strcmp(s, current_section)))
704 return;
706 printf("\t%s\n", s);
707 current_section = s;
710 static void emit_insn_atom(struct function *f, struct atom *atom)
712 char s[128];
713 char comment[64];
714 struct storage *op1 = atom->op1;
715 struct storage *op2 = atom->op2;
717 if (atom->comment[0])
718 sprintf(comment, "\t\t# %s", atom->comment);
719 else
720 comment[0] = 0;
722 if (atom->op2) {
723 char tmp[16];
724 strcpy(tmp, stor_op_name(op1));
725 sprintf(s, "\t%s\t%s, %s%s\n",
726 atom->insn, tmp, stor_op_name(op2), comment);
727 } else if (atom->op1)
728 sprintf(s, "\t%s\t%s%s%s\n",
729 atom->insn, stor_op_name(op1),
730 comment[0] ? "\t" : "", comment);
731 else
732 sprintf(s, "\t%s\t%s%s\n",
733 atom->insn,
734 comment[0] ? "\t\t" : "", comment);
736 if (write(STDOUT_FILENO, s, strlen(s)) < 0)
737 die("can't write to stdout");
740 static void emit_atom_list(struct function *f)
742 struct atom *atom;
744 FOR_EACH_PTR(f->atom_list, atom) {
745 switch (atom->type) {
746 case ATOM_TEXT: {
747 if (write(STDOUT_FILENO, atom->text, atom->text_len) < 0)
748 die("can't write to stdout");
749 break;
751 case ATOM_INSN:
752 emit_insn_atom(f, atom);
753 break;
754 case ATOM_CSTR:
755 assert(0);
756 break;
758 } END_FOR_EACH_PTR(atom);
761 static void emit_string_list(struct function *f)
763 struct atom *atom;
765 emit_section(".section\t.rodata");
767 FOR_EACH_PTR(f->str_list, atom) {
768 /* FIXME: escape " in string */
769 printf(".L%d:\n", atom->label);
770 printf("\t.string\t%s\n", show_string(atom->string));
772 free(atom);
773 } END_FOR_EACH_PTR(atom);
776 static void func_cleanup(struct function *f)
778 struct storage *stor;
779 struct atom *atom;
781 FOR_EACH_PTR(f->atom_list, atom) {
782 if ((atom->type == ATOM_TEXT) && (atom->text))
783 free(atom->text);
784 if (atom->op1 && (atom->op1->flags & STOR_WANTS_FREE))
785 free(atom->op1);
786 if (atom->op2 && (atom->op2->flags & STOR_WANTS_FREE))
787 free(atom->op2);
788 free(atom);
789 } END_FOR_EACH_PTR(atom);
791 FOR_EACH_PTR(f->pseudo_list, stor) {
792 free(stor);
793 } END_FOR_EACH_PTR(stor);
795 free_ptr_list(&f->pseudo_list);
796 free(f);
799 /* function prologue */
800 static void emit_func_pre(struct symbol *sym)
802 struct function *f;
803 struct symbol *arg;
804 unsigned int i, argc = 0, alloc_len;
805 unsigned char *mem;
806 struct symbol_private *privbase;
807 struct storage *storage_base;
808 struct symbol *base_type = sym->ctype.base_type;
810 FOR_EACH_PTR(base_type->arguments, arg) {
811 argc++;
812 } END_FOR_EACH_PTR(arg);
814 alloc_len =
815 sizeof(*f) +
816 (argc * sizeof(struct symbol *)) +
817 (argc * sizeof(struct symbol_private)) +
818 (argc * sizeof(struct storage));
819 mem = calloc(1, alloc_len);
820 if (!mem)
821 die("OOM on func info");
823 f = (struct function *) mem;
824 mem += sizeof(*f);
825 f->argv = (struct symbol **) mem;
826 mem += (argc * sizeof(struct symbol *));
827 privbase = (struct symbol_private *) mem;
828 mem += (argc * sizeof(struct symbol_private));
829 storage_base = (struct storage *) mem;
831 f->argc = argc;
832 f->ret_target = new_label();
834 i = 0;
835 FOR_EACH_PTR(base_type->arguments, arg) {
836 f->argv[i] = arg;
837 arg->aux = &privbase[i];
838 storage_base[i].type = STOR_ARG;
839 storage_base[i].idx = i;
840 privbase[i].addr = &storage_base[i];
841 i++;
842 } END_FOR_EACH_PTR(arg);
844 assert(current_func == NULL);
845 current_func = f;
848 /* function epilogue */
849 static void emit_func_post(struct symbol *sym)
851 const char *name = show_ident(sym->ident);
852 struct function *f = current_func;
853 int stack_size = f->stack_size;
855 if (f->str_list)
856 emit_string_list(f);
858 /* function prologue */
859 emit_section(".text");
860 if ((sym->ctype.modifiers & MOD_STATIC) == 0)
861 printf(".globl %s\n", name);
862 printf("\t.type\t%s, @function\n", name);
863 printf("%s:\n", name);
865 if (stack_size) {
866 char pseudo_const[16];
868 sprintf(pseudo_const, "$%d", stack_size);
869 printf("\tsubl\t%s, %%esp\n", pseudo_const);
872 /* function epilogue */
874 /* jump target for 'return' statements */
875 emit_label(f->ret_target, NULL);
877 if (stack_size) {
878 struct storage *val;
880 val = new_storage(STOR_VALUE);
881 val->value = (long long) (stack_size);
882 val->flags = STOR_WANTS_FREE;
884 insn("addl", val, REG_ESP, NULL);
887 insn("ret", NULL, NULL, NULL);
889 /* output everything to stdout */
890 fflush(stdout); /* paranoia; needed? */
891 emit_atom_list(f);
893 /* function footer */
894 name = show_ident(sym->ident);
895 printf("\t.size\t%s, .-%s\n", name, name);
897 func_cleanup(f);
898 current_func = NULL;
901 /* emit object (a.k.a. variable, a.k.a. data) prologue */
902 static void emit_object_pre(const char *name, unsigned long modifiers,
903 unsigned long alignment, unsigned int byte_size)
905 if ((modifiers & MOD_STATIC) == 0)
906 printf(".globl %s\n", name);
907 emit_section(".data");
908 if (alignment)
909 printf("\t.align %lu\n", alignment);
910 printf("\t.type\t%s, @object\n", name);
911 printf("\t.size\t%s, %d\n", name, byte_size);
912 printf("%s:\n", name);
915 /* emit value (only) for an initializer scalar */
916 static void emit_scalar(struct expression *expr, unsigned int bit_size)
918 const char *type;
919 long long ll;
921 assert(expr->type == EXPR_VALUE);
923 if (expr->value == 0ULL) {
924 printf("\t.zero\t%d\n", bit_size / 8);
925 return;
928 ll = (long long) expr->value;
930 switch (bit_size) {
931 case 8: type = "byte"; ll = (char) ll; break;
932 case 16: type = "value"; ll = (short) ll; break;
933 case 32: type = "long"; ll = (int) ll; break;
934 case 64: type = "quad"; break;
935 default: type = NULL; break;
938 assert(type != NULL);
940 printf("\t.%s\t%Ld\n", type, ll);
943 static void emit_global_noinit(const char *name, unsigned long modifiers,
944 unsigned long alignment, unsigned int byte_size)
946 char s[64];
948 if (modifiers & MOD_STATIC) {
949 sprintf(s, "\t.local\t%s\n", name);
950 textbuf_push(&unit_post_text, s);
952 if (alignment)
953 sprintf(s, "\t.comm\t%s,%d,%lu\n", name, byte_size, alignment);
954 else
955 sprintf(s, "\t.comm\t%s,%d\n", name, byte_size);
956 textbuf_push(&unit_post_text, s);
959 static int ea_current, ea_last;
961 static void emit_initializer(struct symbol *sym,
962 struct expression *expr)
964 int distance = ea_current - ea_last - 1;
966 if (distance > 0)
967 printf("\t.zero\t%d\n", (sym->bit_size / 8) * distance);
969 if (expr->type == EXPR_VALUE) {
970 struct symbol *base_type = sym->ctype.base_type;
971 assert(base_type != NULL);
973 emit_scalar(expr, sym->bit_size / get_expression_value(base_type->array_size));
974 return;
976 if (expr->type != EXPR_INITIALIZER)
977 return;
979 assert(0); /* FIXME */
982 static int sort_array_cmp(const struct expression *a,
983 const struct expression *b)
985 int a_ofs = 0, b_ofs = 0;
987 if (a->type == EXPR_POS)
988 a_ofs = (int) a->init_offset;
989 if (b->type == EXPR_POS)
990 b_ofs = (int) b->init_offset;
992 return a_ofs - b_ofs;
995 /* move to front-end? */
996 static void sort_array(struct expression *expr)
998 struct expression *entry, **list;
999 unsigned int elem, sorted, i;
1001 elem = expression_list_size(expr->expr_list);
1002 if (!elem)
1003 return;
1005 list = malloc(sizeof(entry) * elem);
1006 if (!list)
1007 die("OOM in sort_array");
1009 /* this code is no doubt evil and ignores EXPR_INDEX possibly
1010 * to its detriment and other nasty things. improvements
1011 * welcome.
1013 i = 0;
1014 sorted = 0;
1015 FOR_EACH_PTR(expr->expr_list, entry) {
1016 if ((entry->type == EXPR_POS) || (entry->type == EXPR_VALUE)) {
1017 /* add entry to list[], in sorted order */
1018 if (sorted == 0) {
1019 list[0] = entry;
1020 sorted = 1;
1021 } else {
1022 for (i = 0; i < sorted; i++)
1023 if (sort_array_cmp(entry, list[i]) <= 0)
1024 break;
1026 /* If inserting into the middle of list[]
1027 * instead of appending, we memmove.
1028 * This is ugly, but thankfully
1029 * uncommon. Input data with tons of
1030 * entries very rarely have explicit
1031 * offsets. convert to qsort eventually...
1033 if (i != sorted)
1034 memmove(&list[i + 1], &list[i],
1035 (sorted - i) * sizeof(entry));
1036 list[i] = entry;
1037 sorted++;
1040 } END_FOR_EACH_PTR(entry);
1042 i = 0;
1043 FOR_EACH_PTR(expr->expr_list, entry) {
1044 if ((entry->type == EXPR_POS) || (entry->type == EXPR_VALUE))
1045 *THIS_ADDRESS(entry) = list[i++];
1046 } END_FOR_EACH_PTR(entry);
1048 free(list);
1051 static void emit_array(struct symbol *sym)
1053 struct symbol *base_type = sym->ctype.base_type;
1054 struct expression *expr = sym->initializer;
1055 struct expression *entry;
1057 assert(base_type != NULL);
1059 stor_sym_init(sym);
1061 ea_last = -1;
1063 emit_object_pre(show_ident(sym->ident), sym->ctype.modifiers,
1064 sym->ctype.alignment,
1065 sym->bit_size / 8);
1067 sort_array(expr);
1069 FOR_EACH_PTR(expr->expr_list, entry) {
1070 if (entry->type == EXPR_VALUE) {
1071 ea_current = 0;
1072 emit_initializer(sym, entry);
1073 ea_last = ea_current;
1074 } else if (entry->type == EXPR_POS) {
1075 ea_current =
1076 entry->init_offset / (base_type->bit_size / 8);
1077 emit_initializer(sym, entry->init_expr);
1078 ea_last = ea_current;
1080 } END_FOR_EACH_PTR(entry);
1083 void emit_one_symbol(struct symbol *sym)
1085 x86_symbol(sym);
1088 static void emit_copy(struct storage *dest, struct storage *src,
1089 struct symbol *ctype)
1091 struct storage *reg = NULL;
1092 unsigned int bit_size;
1094 /* FIXME: Bitfield copy! */
1096 bit_size = src->size * 8;
1097 if (!bit_size)
1098 bit_size = 32;
1099 if ((src->type == STOR_ARG) && (bit_size < 32))
1100 bit_size = 32;
1102 reg = temp_from_bits(bit_size);
1103 emit_move(src, reg, ctype, "begin copy ..");
1105 bit_size = dest->size * 8;
1106 if (!bit_size)
1107 bit_size = 32;
1108 if ((dest->type == STOR_ARG) && (bit_size < 32))
1109 bit_size = 32;
1111 emit_move(reg, dest, ctype, ".... end copy");
1112 put_reg(reg);
1115 static void emit_store(struct expression *dest_expr, struct storage *dest,
1116 struct storage *src, int bits)
1118 /* FIXME: Bitfield store! */
1119 printf("\tst.%d\t\tv%d,[v%d]\n", bits, src->pseudo, dest->pseudo);
1122 static void emit_scalar_noinit(struct symbol *sym)
1124 emit_global_noinit(show_ident(sym->ident),
1125 sym->ctype.modifiers, sym->ctype.alignment,
1126 sym->bit_size / 8);
1127 stor_sym_init(sym);
1130 static void emit_array_noinit(struct symbol *sym)
1132 emit_global_noinit(show_ident(sym->ident),
1133 sym->ctype.modifiers, sym->ctype.alignment,
1134 get_expression_value(sym->array_size) * (sym->bit_size / 8));
1135 stor_sym_init(sym);
1138 static const char *opbits(const char *insn, unsigned int bits)
1140 static char opbits_str[32];
1141 char c;
1143 switch (bits) {
1144 case 8: c = 'b'; break;
1145 case 16: c = 'w'; break;
1146 case 32: c = 'l'; break;
1147 case 64: c = 'q'; break;
1148 default: abort(); break;
1151 sprintf(opbits_str, "%s%c", insn, c);
1153 return opbits_str;
1156 static void emit_move(struct storage *src, struct storage *dest,
1157 struct symbol *ctype, const char *comment)
1159 unsigned int bits;
1160 unsigned int is_signed;
1161 unsigned int is_dest = (src->type == STOR_REG);
1162 const char *opname;
1164 if (ctype) {
1165 bits = ctype->bit_size;
1166 is_signed = type_is_signed(ctype);
1167 } else {
1168 bits = 32;
1169 is_signed = 0;
1173 * Are we moving from a register to a register?
1174 * Make the new reg to be the "cache".
1176 if ((dest->type == STOR_REG) && (src->type == STOR_REG)) {
1177 struct storage *backing;
1179 reg_reg_move:
1180 if (dest == src)
1181 return;
1183 backing = src->reg->contains;
1184 if (backing) {
1185 /* Is it still valid? */
1186 if (backing->reg != src->reg)
1187 backing = NULL;
1188 else
1189 backing->reg = dest->reg;
1191 dest->reg->contains = backing;
1192 insn("mov", src, dest, NULL);
1193 return;
1197 * Are we moving to a register from a non-reg?
1199 * See if we have the non-reg source already cached
1200 * in a register..
1202 if (dest->type == STOR_REG) {
1203 if (src->reg) {
1204 struct reg_info *info = src->reg;
1205 if (info->contains == src) {
1206 src = reginfo_reg(info);
1207 goto reg_reg_move;
1210 dest->reg->contains = src;
1211 src->reg = dest->reg;
1214 if (src->type == STOR_REG) {
1215 /* We could just mark the register dirty here and do lazy store.. */
1216 src->reg->contains = dest;
1217 dest->reg = src->reg;
1220 if ((bits == 8) || (bits == 16)) {
1221 if (is_dest)
1222 opname = "mov";
1223 else
1224 opname = is_signed ? "movsx" : "movzx";
1225 } else
1226 opname = "mov";
1228 insn(opbits(opname, bits), src, dest, comment);
1231 static struct storage *emit_compare(struct expression *expr)
1233 struct storage *left = x86_expression(expr->left);
1234 struct storage *right = x86_expression(expr->right);
1235 struct storage *reg1, *reg2;
1236 struct storage *new, *val;
1237 const char *opname = NULL;
1238 unsigned int right_bits = expr->right->ctype->bit_size;
1240 switch(expr->op) {
1241 case '<': opname = "setl"; break;
1242 case '>': opname = "setg"; break;
1243 case SPECIAL_LTE:
1244 opname = "setle"; break;
1245 case SPECIAL_GTE:
1246 opname = "setge"; break;
1247 case SPECIAL_EQUAL: opname = "sete"; break;
1248 case SPECIAL_NOTEQUAL: opname = "setne"; break;
1249 case SPECIAL_UNSIGNED_LT:
1250 opname = "setb"; break;
1251 case SPECIAL_UNSIGNED_GT:
1252 opname = "seta"; break;
1253 case SPECIAL_UNSIGNED_LTE:
1254 opname = "setb"; break;
1255 case SPECIAL_UNSIGNED_GTE:
1256 opname = "setae"; break;
1257 default:
1258 assert(0);
1259 break;
1262 /* init EDX to 0 */
1263 val = new_storage(STOR_VALUE);
1264 val->flags = STOR_WANTS_FREE;
1266 reg1 = get_reg(&regclass_32_8);
1267 emit_move(val, reg1, NULL, NULL);
1269 /* move op1 into EAX */
1270 reg2 = get_reg_value(left, get_regclass(expr->left));
1272 /* perform comparison, RHS (op1, right) and LHS (op2, EAX) */
1273 insn(opbits("cmp", right_bits), right, reg2, NULL);
1274 put_reg(reg2);
1276 /* store result of operation, 0 or 1, in DL using SETcc */
1277 insn(opname, byte_reg(reg1), NULL, NULL);
1279 /* finally, store the result (DL) in a new pseudo / stack slot */
1280 new = stack_alloc(4);
1281 emit_move(reg1, new, NULL, "end EXPR_COMPARE");
1282 put_reg(reg1);
1284 return new;
1287 static struct storage *emit_value(struct expression *expr)
1289 #if 0 /* old and slow way */
1290 struct storage *new = stack_alloc(4);
1291 struct storage *val;
1293 val = new_storage(STOR_VALUE);
1294 val->value = (long long) expr->value;
1295 val->flags = STOR_WANTS_FREE;
1296 insn("movl", val, new, NULL);
1298 return new;
1299 #else
1300 struct storage *val;
1302 val = new_storage(STOR_VALUE);
1303 val->value = (long long) expr->value;
1305 return val; /* FIXME: memory leak */
1306 #endif
1309 static struct storage *emit_divide(struct expression *expr, struct storage *left, struct storage *right)
1311 struct storage *eax_edx;
1312 struct storage *reg, *new;
1313 struct storage *val = new_storage(STOR_VALUE);
1315 emit_comment("begin DIVIDE");
1316 eax_edx = get_hardreg(hardreg_storage_table + EAX_EDX, 1);
1318 /* init EDX to 0 */
1319 val->flags = STOR_WANTS_FREE;
1320 emit_move(val, REG_EDX, NULL, NULL);
1322 new = stack_alloc(expr->ctype->bit_size / 8);
1324 /* EAX is dividend */
1325 emit_move(left, REG_EAX, NULL, NULL);
1327 reg = get_reg_value(right, &regclass_32);
1329 /* perform binop */
1330 insn("div", reg, REG_EAX, NULL);
1331 put_reg(reg);
1333 reg = REG_EAX;
1334 if (expr->op == '%')
1335 reg = REG_EDX;
1336 emit_move(reg, new, NULL, NULL);
1338 put_reg(eax_edx);
1339 emit_comment("end DIVIDE");
1340 return new;
1343 static struct storage *emit_binop(struct expression *expr)
1345 struct storage *left = x86_expression(expr->left);
1346 struct storage *right = x86_expression(expr->right);
1347 struct storage *new;
1348 struct storage *dest, *src;
1349 const char *opname = NULL;
1350 const char *suffix = NULL;
1351 char opstr[16];
1352 int is_signed;
1354 /* Divides have special register constraints */
1355 if ((expr->op == '/') || (expr->op == '%'))
1356 return emit_divide(expr, left, right);
1358 is_signed = type_is_signed(expr->ctype);
1360 switch (expr->op) {
1361 case '+':
1362 opname = "add";
1363 break;
1364 case '-':
1365 opname = "sub";
1366 break;
1367 case '&':
1368 opname = "and";
1369 break;
1370 case '|':
1371 opname = "or";
1372 break;
1373 case '^':
1374 opname = "xor";
1375 break;
1376 case SPECIAL_LEFTSHIFT:
1377 opname = "shl";
1378 break;
1379 case SPECIAL_RIGHTSHIFT:
1380 if (is_signed)
1381 opname = "sar";
1382 else
1383 opname = "shr";
1384 break;
1385 case '*':
1386 if (is_signed)
1387 opname = "imul";
1388 else
1389 opname = "mul";
1390 break;
1391 case SPECIAL_LOGICAL_AND:
1392 warning(expr->pos, "bogus bitwise and for logical op (should use '2*setne + and' or something)");
1393 opname = "and";
1394 break;
1395 case SPECIAL_LOGICAL_OR:
1396 warning(expr->pos, "bogus bitwise or for logical op (should use 'or + setne' or something)");
1397 opname = "or";
1398 break;
1399 default:
1400 error_die(expr->pos, "unhandled binop '%s'\n", show_special(expr->op));
1401 break;
1404 dest = get_reg_value(right, &regclass_32);
1405 src = get_reg_value(left, &regclass_32);
1406 switch (expr->ctype->bit_size) {
1407 case 8:
1408 suffix = "b";
1409 break;
1410 case 16:
1411 suffix = "w";
1412 break;
1413 case 32:
1414 suffix = "l";
1415 break;
1416 case 64:
1417 suffix = "q"; /* FIXME */
1418 break;
1419 default:
1420 assert(0);
1421 break;
1424 snprintf(opstr, sizeof(opstr), "%s%s", opname, suffix);
1426 /* perform binop */
1427 insn(opstr, src, dest, NULL);
1428 put_reg(src);
1430 /* store result in new pseudo / stack slot */
1431 new = stack_alloc(expr->ctype->bit_size / 8);
1432 emit_move(dest, new, NULL, "end EXPR_BINOP");
1434 put_reg(dest);
1436 return new;
1439 static int emit_conditional_test(struct storage *val)
1441 struct storage *reg;
1442 struct storage *target_val;
1443 int target_false;
1445 /* load result into EAX */
1446 emit_comment("begin if/conditional");
1447 reg = get_reg_value(val, &regclass_32);
1449 /* compare result with zero */
1450 insn("test", reg, reg, NULL);
1451 put_reg(reg);
1453 /* create conditional-failed label to jump to */
1454 target_false = new_label();
1455 target_val = new_storage(STOR_LABEL);
1456 target_val->label = target_false;
1457 target_val->flags = STOR_WANTS_FREE;
1458 insn("jz", target_val, NULL, NULL);
1460 return target_false;
1463 static int emit_conditional_end(int target_false)
1465 struct storage *cond_end_st;
1466 int cond_end;
1468 /* finished generating code for if-true statement.
1469 * add a jump-to-end jump to avoid falling through
1470 * to the if-false statement code.
1472 cond_end = new_label();
1473 cond_end_st = new_storage(STOR_LABEL);
1474 cond_end_st->label = cond_end;
1475 cond_end_st->flags = STOR_WANTS_FREE;
1476 insn("jmp", cond_end_st, NULL, NULL);
1478 /* if we have both if-true and if-false statements,
1479 * the failed-conditional case will fall through to here
1481 emit_label(target_false, NULL);
1483 return cond_end;
1486 static void emit_if_conditional(struct statement *stmt)
1488 struct storage *val;
1489 int cond_end;
1491 /* emit test portion of conditional */
1492 val = x86_expression(stmt->if_conditional);
1493 cond_end = emit_conditional_test(val);
1495 /* emit if-true statement */
1496 x86_statement(stmt->if_true);
1498 /* emit if-false statement, if present */
1499 if (stmt->if_false) {
1500 cond_end = emit_conditional_end(cond_end);
1501 x86_statement(stmt->if_false);
1504 /* end of conditional; jump target for if-true branch */
1505 emit_label(cond_end, "end if");
1508 static struct storage *emit_inc_dec(struct expression *expr, int postop)
1510 struct storage *addr = x86_address_gen(expr->unop);
1511 struct storage *retval;
1512 char opname[16];
1514 strcpy(opname, opbits(expr->op == SPECIAL_INCREMENT ? "inc" : "dec",
1515 expr->ctype->bit_size));
1517 if (postop) {
1518 struct storage *new = stack_alloc(4);
1520 emit_copy(new, addr, expr->unop->ctype);
1522 retval = new;
1523 } else
1524 retval = addr;
1526 insn(opname, addr, NULL, NULL);
1528 return retval;
1531 static struct storage *emit_postop(struct expression *expr)
1533 return emit_inc_dec(expr, 1);
1536 static struct storage *emit_return_stmt(struct statement *stmt)
1538 struct function *f = current_func;
1539 struct expression *expr = stmt->ret_value;
1540 struct storage *val = NULL, *jmplbl;
1542 if (expr && expr->ctype) {
1543 val = x86_expression(expr);
1544 assert(val != NULL);
1545 emit_move(val, REG_EAX, expr->ctype, "return");
1548 jmplbl = new_storage(STOR_LABEL);
1549 jmplbl->flags |= STOR_WANTS_FREE;
1550 jmplbl->label = f->ret_target;
1551 insn("jmp", jmplbl, NULL, NULL);
1553 return val;
1556 static struct storage *emit_conditional_expr(struct expression *expr)
1558 struct storage *cond, *true = NULL, *false = NULL;
1559 struct storage *new = stack_alloc(expr->ctype->bit_size / 8);
1560 int target_false, cond_end;
1562 /* evaluate conditional */
1563 cond = x86_expression(expr->conditional);
1564 target_false = emit_conditional_test(cond);
1566 /* handle if-true part of the expression */
1567 true = x86_expression(expr->cond_true);
1569 emit_copy(new, true, expr->ctype);
1571 cond_end = emit_conditional_end(target_false);
1573 /* handle if-false part of the expression */
1574 false = x86_expression(expr->cond_false);
1576 emit_copy(new, false, expr->ctype);
1578 /* end of conditional; jump target for if-true branch */
1579 emit_label(cond_end, "end conditional");
1581 return new;
1584 static struct storage *emit_select_expr(struct expression *expr)
1586 struct storage *cond = x86_expression(expr->conditional);
1587 struct storage *true = x86_expression(expr->cond_true);
1588 struct storage *false = x86_expression(expr->cond_false);
1589 struct storage *reg_cond, *reg_true, *reg_false;
1590 struct storage *new = stack_alloc(4);
1592 emit_comment("begin SELECT");
1593 reg_cond = get_reg_value(cond, get_regclass(expr->conditional));
1594 reg_true = get_reg_value(true, get_regclass(expr));
1595 reg_false = get_reg_value(false, get_regclass(expr));
1598 * Do the actual select: check the conditional for zero,
1599 * move false over true if zero
1601 insn("test", reg_cond, reg_cond, NULL);
1602 insn("cmovz", reg_false, reg_true, NULL);
1604 /* Store it back */
1605 emit_move(reg_true, new, expr->ctype, NULL);
1606 put_reg(reg_cond);
1607 put_reg(reg_true);
1608 put_reg(reg_false);
1609 emit_comment("end SELECT");
1610 return new;
1613 static struct storage *emit_symbol_expr_init(struct symbol *sym)
1615 struct expression *expr = sym->initializer;
1616 struct symbol_private *priv = sym->aux;
1618 if (priv == NULL) {
1619 priv = calloc(1, sizeof(*priv));
1620 sym->aux = priv;
1622 if (expr == NULL) {
1623 struct storage *new = stack_alloc(4);
1624 fprintf(stderr, "FIXME! no value for symbol %s. creating pseudo %d (stack offset %d)\n",
1625 show_ident(sym->ident),
1626 new->pseudo, new->pseudo * 4);
1627 priv->addr = new;
1628 } else {
1629 priv->addr = x86_expression(expr);
1633 return priv->addr;
1636 static struct storage *emit_string_expr(struct expression *expr)
1638 struct function *f = current_func;
1639 int label = new_label();
1640 struct storage *new;
1642 push_cstring(f, expr->string, label);
1644 new = new_storage(STOR_LABEL);
1645 new->label = label;
1646 new->flags = STOR_LABEL_VAL | STOR_WANTS_FREE;
1647 return new;
1650 static struct storage *emit_cast_expr(struct expression *expr)
1652 struct symbol *old_type, *new_type;
1653 struct storage *op = x86_expression(expr->cast_expression);
1654 int oldbits, newbits;
1655 struct storage *new;
1657 old_type = expr->cast_expression->ctype;
1658 new_type = expr->cast_type;
1660 oldbits = old_type->bit_size;
1661 newbits = new_type->bit_size;
1662 if (oldbits >= newbits)
1663 return op;
1665 emit_move(op, REG_EAX, old_type, "begin cast ..");
1667 new = stack_alloc(newbits / 8);
1668 emit_move(REG_EAX, new, new_type, ".... end cast");
1670 return new;
1673 static struct storage *emit_regular_preop(struct expression *expr)
1675 struct storage *target = x86_expression(expr->unop);
1676 struct storage *val, *new = stack_alloc(4);
1677 const char *opname = NULL;
1679 switch (expr->op) {
1680 case '!':
1681 val = new_storage(STOR_VALUE);
1682 val->flags = STOR_WANTS_FREE;
1683 emit_move(val, REG_EDX, NULL, NULL);
1684 emit_move(target, REG_EAX, expr->unop->ctype, NULL);
1685 insn("test", REG_EAX, REG_EAX, NULL);
1686 insn("setz", REG_DL, NULL, NULL);
1687 emit_move(REG_EDX, new, expr->unop->ctype, NULL);
1689 break;
1690 case '~':
1691 opname = "not";
1692 case '-':
1693 if (!opname)
1694 opname = "neg";
1695 emit_move(target, REG_EAX, expr->unop->ctype, NULL);
1696 insn(opname, REG_EAX, NULL, NULL);
1697 emit_move(REG_EAX, new, expr->unop->ctype, NULL);
1698 break;
1699 default:
1700 assert(0);
1701 break;
1704 return new;
1707 static void emit_case_statement(struct statement *stmt)
1709 emit_labelsym(stmt->case_label, NULL);
1710 x86_statement(stmt->case_statement);
1713 static void emit_switch_statement(struct statement *stmt)
1715 struct storage *val = x86_expression(stmt->switch_expression);
1716 struct symbol *sym, *default_sym = NULL;
1717 struct storage *labelsym, *label;
1718 int switch_end = 0;
1720 emit_move(val, REG_EAX, stmt->switch_expression->ctype, "begin case");
1723 * This is where a _real_ back-end would go through the
1724 * cases to decide whether to use a lookup table or a
1725 * series of comparisons etc
1727 FOR_EACH_PTR(stmt->switch_case->symbol_list, sym) {
1728 struct statement *case_stmt = sym->stmt;
1729 struct expression *expr = case_stmt->case_expression;
1730 struct expression *to = case_stmt->case_to;
1732 /* default: */
1733 if (!expr)
1734 default_sym = sym;
1736 /* case NNN: */
1737 else {
1738 struct storage *case_val = new_val(expr->value);
1740 assert (expr->type == EXPR_VALUE);
1742 insn("cmpl", case_val, REG_EAX, NULL);
1744 if (!to) {
1745 labelsym = new_labelsym(sym);
1746 insn("je", labelsym, NULL, NULL);
1747 } else {
1748 int next_test;
1750 label = new_storage(STOR_LABEL);
1751 label->flags |= STOR_WANTS_FREE;
1752 label->label = next_test = new_label();
1754 /* FIXME: signed/unsigned */
1755 insn("jl", label, NULL, NULL);
1757 case_val = new_val(to->value);
1758 insn("cmpl", case_val, REG_EAX, NULL);
1760 /* TODO: implement and use refcounting... */
1761 label = new_storage(STOR_LABEL);
1762 label->flags |= STOR_WANTS_FREE;
1763 label->label = next_test;
1765 /* FIXME: signed/unsigned */
1766 insn("jg", label, NULL, NULL);
1768 labelsym = new_labelsym(sym);
1769 insn("jmp", labelsym, NULL, NULL);
1771 emit_label(next_test, NULL);
1774 } END_FOR_EACH_PTR(sym);
1776 if (default_sym) {
1777 labelsym = new_labelsym(default_sym);
1778 insn("jmp", labelsym, NULL, "default");
1779 } else {
1780 label = new_storage(STOR_LABEL);
1781 label->flags |= STOR_WANTS_FREE;
1782 label->label = switch_end = new_label();
1783 insn("jmp", label, NULL, "goto end of switch");
1786 x86_statement(stmt->switch_statement);
1788 if (stmt->switch_break->used)
1789 emit_labelsym(stmt->switch_break, NULL);
1791 if (switch_end)
1792 emit_label(switch_end, NULL);
1795 static void x86_struct_member(struct symbol *sym)
1797 printf("\t%s:%d:%ld at offset %ld.%d", show_ident(sym->ident), sym->bit_size, sym->ctype.alignment, sym->offset, sym->bit_offset);
1798 printf("\n");
1801 static void x86_symbol(struct symbol *sym)
1803 struct symbol *type;
1805 if (!sym)
1806 return;
1808 type = sym->ctype.base_type;
1809 if (!type)
1810 return;
1813 * Show actual implementation information
1815 switch (type->type) {
1817 case SYM_ARRAY:
1818 if (sym->initializer)
1819 emit_array(sym);
1820 else
1821 emit_array_noinit(sym);
1822 break;
1824 case SYM_BASETYPE:
1825 if (sym->initializer) {
1826 emit_object_pre(show_ident(sym->ident),
1827 sym->ctype.modifiers,
1828 sym->ctype.alignment,
1829 sym->bit_size / 8);
1830 emit_scalar(sym->initializer, sym->bit_size);
1831 stor_sym_init(sym);
1832 } else
1833 emit_scalar_noinit(sym);
1834 break;
1836 case SYM_STRUCT:
1837 case SYM_UNION: {
1838 struct symbol *member;
1840 printf(" {\n");
1841 FOR_EACH_PTR(type->symbol_list, member) {
1842 x86_struct_member(member);
1843 } END_FOR_EACH_PTR(member);
1844 printf("}\n");
1845 break;
1848 case SYM_FN: {
1849 struct statement *stmt = type->stmt;
1850 if (stmt) {
1851 emit_func_pre(sym);
1852 x86_statement(stmt);
1853 emit_func_post(sym);
1855 break;
1858 default:
1859 break;
1862 if (sym->initializer && (type->type != SYM_BASETYPE) &&
1863 (type->type != SYM_ARRAY)) {
1864 printf(" = \n");
1865 x86_expression(sym->initializer);
1869 static void x86_symbol_init(struct symbol *sym);
1871 static void x86_symbol_decl(struct symbol_list *syms)
1873 struct symbol *sym;
1874 FOR_EACH_PTR(syms, sym) {
1875 x86_symbol_init(sym);
1876 } END_FOR_EACH_PTR(sym);
1879 static void loopstk_push(int cont_lbl, int loop_bottom_lbl)
1881 struct function *f = current_func;
1882 struct loop_stack *ls;
1884 ls = malloc(sizeof(*ls));
1885 ls->continue_lbl = cont_lbl;
1886 ls->loop_bottom_lbl = loop_bottom_lbl;
1887 ls->next = f->loop_stack;
1888 f->loop_stack = ls;
1891 static void loopstk_pop(void)
1893 struct function *f = current_func;
1894 struct loop_stack *ls;
1896 assert(f->loop_stack != NULL);
1897 ls = f->loop_stack;
1898 f->loop_stack = f->loop_stack->next;
1899 free(ls);
1902 static int loopstk_break(void)
1904 return current_func->loop_stack->loop_bottom_lbl;
1907 static int loopstk_continue(void)
1909 return current_func->loop_stack->continue_lbl;
1912 static void emit_loop(struct statement *stmt)
1914 struct statement *pre_statement = stmt->iterator_pre_statement;
1915 struct expression *pre_condition = stmt->iterator_pre_condition;
1916 struct statement *statement = stmt->iterator_statement;
1917 struct statement *post_statement = stmt->iterator_post_statement;
1918 struct expression *post_condition = stmt->iterator_post_condition;
1919 int loop_top = 0, loop_bottom, loop_continue;
1920 int have_bottom = 0;
1921 struct storage *val;
1923 loop_bottom = new_label();
1924 loop_continue = new_label();
1925 loopstk_push(loop_continue, loop_bottom);
1927 x86_symbol_decl(stmt->iterator_syms);
1928 x86_statement(pre_statement);
1929 if (!post_condition || post_condition->type != EXPR_VALUE || post_condition->value) {
1930 loop_top = new_label();
1931 emit_label(loop_top, "loop top");
1933 if (pre_condition) {
1934 if (pre_condition->type == EXPR_VALUE) {
1935 if (!pre_condition->value) {
1936 struct storage *lbv;
1937 lbv = new_storage(STOR_LABEL);
1938 lbv->label = loop_bottom;
1939 lbv->flags = STOR_WANTS_FREE;
1940 insn("jmp", lbv, NULL, "go to loop bottom");
1941 have_bottom = 1;
1943 } else {
1944 struct storage *lbv = new_storage(STOR_LABEL);
1945 lbv->label = loop_bottom;
1946 lbv->flags = STOR_WANTS_FREE;
1947 have_bottom = 1;
1949 val = x86_expression(pre_condition);
1951 emit_move(val, REG_EAX, NULL, "loop pre condition");
1952 insn("test", REG_EAX, REG_EAX, NULL);
1953 insn("jz", lbv, NULL, NULL);
1956 x86_statement(statement);
1957 if (stmt->iterator_continue->used)
1958 emit_label(loop_continue, "'continue' iterator");
1959 x86_statement(post_statement);
1960 if (!post_condition) {
1961 struct storage *lbv = new_storage(STOR_LABEL);
1962 lbv->label = loop_top;
1963 lbv->flags = STOR_WANTS_FREE;
1964 insn("jmp", lbv, NULL, "go to loop top");
1965 } else if (post_condition->type == EXPR_VALUE) {
1966 if (post_condition->value) {
1967 struct storage *lbv = new_storage(STOR_LABEL);
1968 lbv->label = loop_top;
1969 lbv->flags = STOR_WANTS_FREE;
1970 insn("jmp", lbv, NULL, "go to loop top");
1972 } else {
1973 struct storage *lbv = new_storage(STOR_LABEL);
1974 lbv->label = loop_top;
1975 lbv->flags = STOR_WANTS_FREE;
1977 val = x86_expression(post_condition);
1979 emit_move(val, REG_EAX, NULL, "loop post condition");
1980 insn("test", REG_EAX, REG_EAX, NULL);
1981 insn("jnz", lbv, NULL, NULL);
1983 if (have_bottom || stmt->iterator_break->used)
1984 emit_label(loop_bottom, "loop bottom");
1986 loopstk_pop();
1990 * Print out a statement
1992 static struct storage *x86_statement(struct statement *stmt)
1994 if (!stmt)
1995 return NULL;
1996 switch (stmt->type) {
1997 default:
1998 return NULL;
1999 case STMT_RETURN:
2000 return emit_return_stmt(stmt);
2001 case STMT_DECLARATION:
2002 x86_symbol_decl(stmt->declaration);
2003 break;
2004 case STMT_COMPOUND: {
2005 struct statement *s;
2006 struct storage *last = NULL;
2008 FOR_EACH_PTR(stmt->stmts, s) {
2009 last = x86_statement(s);
2010 } END_FOR_EACH_PTR(s);
2012 return last;
2015 case STMT_EXPRESSION:
2016 return x86_expression(stmt->expression);
2017 case STMT_IF:
2018 emit_if_conditional(stmt);
2019 return NULL;
2021 case STMT_CASE:
2022 emit_case_statement(stmt);
2023 break;
2024 case STMT_SWITCH:
2025 emit_switch_statement(stmt);
2026 break;
2028 case STMT_ITERATOR:
2029 emit_loop(stmt);
2030 break;
2032 case STMT_NONE:
2033 break;
2035 case STMT_LABEL:
2036 printf(".L%p:\n", stmt->label_identifier);
2037 x86_statement(stmt->label_statement);
2038 break;
2040 case STMT_GOTO:
2041 if (stmt->goto_expression) {
2042 struct storage *val = x86_expression(stmt->goto_expression);
2043 printf("\tgoto *v%d\n", val->pseudo);
2044 } else if (!strcmp("break", show_ident(stmt->goto_label->ident))) {
2045 struct storage *lbv = new_storage(STOR_LABEL);
2046 lbv->label = loopstk_break();
2047 lbv->flags = STOR_WANTS_FREE;
2048 insn("jmp", lbv, NULL, "'break'; go to loop bottom");
2049 } else if (!strcmp("continue", show_ident(stmt->goto_label->ident))) {
2050 struct storage *lbv = new_storage(STOR_LABEL);
2051 lbv->label = loopstk_continue();
2052 lbv->flags = STOR_WANTS_FREE;
2053 insn("jmp", lbv, NULL, "'continue'; go to loop top");
2054 } else {
2055 struct storage *labelsym = new_labelsym(stmt->goto_label);
2056 insn("jmp", labelsym, NULL, NULL);
2058 break;
2059 case STMT_ASM:
2060 printf("\tasm( .... )\n");
2061 break;
2063 return NULL;
2066 static struct storage *x86_call_expression(struct expression *expr)
2068 struct function *f = current_func;
2069 struct symbol *direct;
2070 struct expression *arg, *fn;
2071 struct storage *retval, *fncall;
2072 int framesize;
2073 char s[64];
2075 if (!expr->ctype) {
2076 warning(expr->pos, "\tcall with no type!");
2077 return NULL;
2080 framesize = 0;
2081 FOR_EACH_PTR_REVERSE(expr->args, arg) {
2082 struct storage *new = x86_expression(arg);
2083 int size = arg->ctype->bit_size;
2086 * FIXME: i386 SysV ABI dictates that values
2087 * smaller than 32 bits should be placed onto
2088 * the stack as 32-bit objects. We should not
2089 * blindly do a 32-bit push on objects smaller
2090 * than 32 bits.
2092 if (size < 32)
2093 size = 32;
2094 insn("pushl", new, NULL,
2095 !framesize ? "begin function call" : NULL);
2097 framesize += bits_to_bytes(size);
2098 } END_FOR_EACH_PTR_REVERSE(arg);
2100 fn = expr->fn;
2102 /* Remove dereference, if any */
2103 direct = NULL;
2104 if (fn->type == EXPR_PREOP) {
2105 if (fn->unop->type == EXPR_SYMBOL) {
2106 struct symbol *sym = fn->unop->symbol;
2107 if (sym->ctype.base_type->type == SYM_FN)
2108 direct = sym;
2111 if (direct) {
2112 struct storage *direct_stor = new_storage(STOR_SYM);
2113 direct_stor->flags |= STOR_WANTS_FREE;
2114 direct_stor->sym = direct;
2115 insn("call", direct_stor, NULL, NULL);
2116 } else {
2117 fncall = x86_expression(fn);
2118 emit_move(fncall, REG_EAX, fn->ctype, NULL);
2120 strcpy(s, "\tcall\t*%eax\n");
2121 push_text_atom(f, s);
2124 /* FIXME: pay attention to BITS_IN_POINTER */
2125 if (framesize) {
2126 struct storage *val = new_storage(STOR_VALUE);
2127 val->value = (long long) framesize;
2128 val->flags = STOR_WANTS_FREE;
2129 insn("addl", val, REG_ESP, NULL);
2132 retval = stack_alloc(4);
2133 emit_move(REG_EAX, retval, NULL, "end function call");
2135 return retval;
2138 static struct storage *x86_address_gen(struct expression *expr)
2140 struct function *f = current_func;
2141 struct storage *addr;
2142 struct storage *new;
2143 char s[32];
2145 addr = x86_expression(expr->unop);
2146 if (expr->unop->type == EXPR_SYMBOL)
2147 return addr;
2149 emit_move(addr, REG_EAX, NULL, "begin deref ..");
2151 /* FIXME: operand size */
2152 strcpy(s, "\tmovl\t(%eax), %ecx\n");
2153 push_text_atom(f, s);
2155 new = stack_alloc(4);
2156 emit_move(REG_ECX, new, NULL, ".... end deref");
2158 return new;
2161 static struct storage *x86_assignment(struct expression *expr)
2163 struct expression *target = expr->left;
2164 struct storage *val, *addr;
2166 if (!expr->ctype)
2167 return NULL;
2169 val = x86_expression(expr->right);
2170 addr = x86_address_gen(target);
2172 switch (val->type) {
2173 /* copy, where both operands are memory */
2174 case STOR_PSEUDO:
2175 case STOR_ARG:
2176 emit_copy(addr, val, expr->ctype);
2177 break;
2179 /* copy, one or zero operands are memory */
2180 case STOR_REG:
2181 case STOR_SYM:
2182 case STOR_VALUE:
2183 case STOR_LABEL:
2184 emit_move(val, addr, expr->left->ctype, NULL);
2185 break;
2187 case STOR_LABELSYM:
2188 assert(0);
2189 break;
2191 return val;
2194 static int x86_initialization(struct symbol *sym, struct expression *expr)
2196 struct storage *val, *addr;
2197 int bits;
2199 if (!expr->ctype)
2200 return 0;
2202 bits = expr->ctype->bit_size;
2203 val = x86_expression(expr);
2204 addr = x86_symbol_expr(sym);
2205 // FIXME! The "target" expression is for bitfield store information.
2206 // Leave it NULL, which works fine.
2207 emit_store(NULL, addr, val, bits);
2208 return 0;
2211 static struct storage *x86_access(struct expression *expr)
2213 return x86_address_gen(expr);
2216 static struct storage *x86_preop(struct expression *expr)
2219 * '*' is an lvalue access, and is fundamentally different
2220 * from an arithmetic operation. Maybe it should have an
2221 * expression type of its own..
2223 if (expr->op == '*')
2224 return x86_access(expr);
2225 if (expr->op == SPECIAL_INCREMENT || expr->op == SPECIAL_DECREMENT)
2226 return emit_inc_dec(expr, 0);
2227 return emit_regular_preop(expr);
2230 static struct storage *x86_symbol_expr(struct symbol *sym)
2232 struct storage *new = stack_alloc(4);
2234 if (sym->ctype.modifiers & (MOD_TOPLEVEL | MOD_EXTERN | MOD_STATIC)) {
2235 printf("\tmovi.%d\t\tv%d,$%s\n", bits_in_pointer, new->pseudo, show_ident(sym->ident));
2236 return new;
2238 if (sym->ctype.modifiers & MOD_ADDRESSABLE) {
2239 printf("\taddi.%d\t\tv%d,vFP,$%lld\n", bits_in_pointer, new->pseudo, sym->value);
2240 return new;
2242 printf("\taddi.%d\t\tv%d,vFP,$offsetof(%s:%p)\n", bits_in_pointer, new->pseudo, show_ident(sym->ident), sym);
2243 return new;
2246 static void x86_symbol_init(struct symbol *sym)
2248 struct symbol_private *priv = sym->aux;
2249 struct expression *expr = sym->initializer;
2250 struct storage *new;
2252 if (expr)
2253 new = x86_expression(expr);
2254 else
2255 new = stack_alloc(sym->bit_size / 8);
2257 if (!priv) {
2258 priv = calloc(1, sizeof(*priv));
2259 sym->aux = priv;
2260 /* FIXME: leak! we don't free... */
2261 /* (well, we don't free symbols either) */
2264 priv->addr = new;
2267 static int type_is_signed(struct symbol *sym)
2269 if (sym->type == SYM_NODE)
2270 sym = sym->ctype.base_type;
2271 if (sym->type == SYM_PTR)
2272 return 0;
2273 return !(sym->ctype.modifiers & MOD_UNSIGNED);
2276 static struct storage *x86_label_expr(struct expression *expr)
2278 struct storage *new = stack_alloc(4);
2279 printf("\tmovi.%d\t\tv%d,.L%p\n", bits_in_pointer, new->pseudo, expr->label_symbol);
2280 return new;
2283 static struct storage *x86_statement_expr(struct expression *expr)
2285 return x86_statement(expr->statement);
2288 static int x86_position_expr(struct expression *expr, struct symbol *base)
2290 struct storage *new = x86_expression(expr->init_expr);
2291 struct symbol *ctype = expr->init_expr->ctype;
2293 printf("\tinsert v%d at [%d:%d] of %s\n", new->pseudo,
2294 expr->init_offset, ctype->bit_offset,
2295 show_ident(base->ident));
2296 return 0;
2299 static void x86_initializer_expr(struct expression *expr, struct symbol *ctype)
2301 struct expression *entry;
2303 FOR_EACH_PTR(expr->expr_list, entry) {
2304 // Nested initializers have their positions already
2305 // recursively calculated - just output them too
2306 if (entry->type == EXPR_INITIALIZER) {
2307 x86_initializer_expr(entry, ctype);
2308 continue;
2311 // Ignore initializer indexes and identifiers - the
2312 // evaluator has taken them into account
2313 if (entry->type == EXPR_IDENTIFIER || entry->type == EXPR_INDEX)
2314 continue;
2315 if (entry->type == EXPR_POS) {
2316 x86_position_expr(entry, ctype);
2317 continue;
2319 x86_initialization(ctype, entry);
2320 } END_FOR_EACH_PTR(entry);
2324 * Print out an expression. Return the pseudo that contains the
2325 * variable.
2327 static struct storage *x86_expression(struct expression *expr)
2329 if (!expr)
2330 return NULL;
2332 if (!expr->ctype) {
2333 struct position *pos = &expr->pos;
2334 printf("\tno type at %s:%d:%d\n",
2335 stream_name(pos->stream),
2336 pos->line, pos->pos);
2337 return NULL;
2340 switch (expr->type) {
2341 default:
2342 return NULL;
2343 case EXPR_CALL:
2344 return x86_call_expression(expr);
2346 case EXPR_ASSIGNMENT:
2347 return x86_assignment(expr);
2349 case EXPR_COMPARE:
2350 return emit_compare(expr);
2351 case EXPR_BINOP:
2352 case EXPR_COMMA:
2353 case EXPR_LOGICAL:
2354 return emit_binop(expr);
2355 case EXPR_PREOP:
2356 return x86_preop(expr);
2357 case EXPR_POSTOP:
2358 return emit_postop(expr);
2359 case EXPR_SYMBOL:
2360 return emit_symbol_expr_init(expr->symbol);
2361 case EXPR_DEREF:
2362 case EXPR_SIZEOF:
2363 case EXPR_ALIGNOF:
2364 warning(expr->pos, "invalid expression after evaluation");
2365 return NULL;
2366 case EXPR_CAST:
2367 case EXPR_FORCE_CAST:
2368 case EXPR_IMPLIED_CAST:
2369 return emit_cast_expr(expr);
2370 case EXPR_VALUE:
2371 return emit_value(expr);
2372 case EXPR_STRING:
2373 return emit_string_expr(expr);
2374 case EXPR_INITIALIZER:
2375 x86_initializer_expr(expr, expr->ctype);
2376 return NULL;
2377 case EXPR_SELECT:
2378 return emit_select_expr(expr);
2379 case EXPR_CONDITIONAL:
2380 return emit_conditional_expr(expr);
2381 case EXPR_STATEMENT:
2382 return x86_statement_expr(expr);
2383 case EXPR_LABEL:
2384 return x86_label_expr(expr);
2386 // None of these should exist as direct expressions: they are only
2387 // valid as sub-expressions of initializers.
2388 case EXPR_POS:
2389 warning(expr->pos, "unable to show plain initializer position expression");
2390 return NULL;
2391 case EXPR_IDENTIFIER:
2392 warning(expr->pos, "unable to show identifier expression");
2393 return NULL;
2394 case EXPR_INDEX:
2395 warning(expr->pos, "unable to show index expression");
2396 return NULL;
2397 case EXPR_TYPE:
2398 warning(expr->pos, "unable to show type expression");
2399 return NULL;
2400 case EXPR_FVALUE:
2401 warning(expr->pos, "floating point support is not implemented");
2402 return NULL;
2404 return NULL;