1 /*
2 * sparse/compile-i386.c
3 *
4 * Copyright (C) 2003 Transmeta Corp.
5 * 2003 Linus Torvalds
6 * Copyright 2003 Jeff Garzik
7 *
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:
14 *
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
17 *
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.
25 *
26 * x86 backend
27 *
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
39 *
40 */
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>
49
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"
61
62 struct textbuf {
63 unsigned int len; /* does NOT include terminating null */
64 char *text;
65 struct textbuf *next;
66 struct textbuf *prev;
67 };
68
69 struct loop_stack {
70 int continue_lbl;
71 int loop_bottom_lbl;
72 struct loop_stack *next;
73 };
74
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);
80
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;
91 };
92
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 */
101 };
102
103 struct reg_info {
104 const char *name;
105 struct storage *contains;
106 const unsigned char aliases[12];
107 #define own_regno aliases[0]
108 };
109
110 struct storage {
111 enum storage_type type;
112 unsigned long flags;
113
114 /* STOR_REG */
115 struct reg_info *reg;
116 struct symbol *ctype;
117
118 union {
119 /* STOR_PSEUDO */
120 struct {
121 int pseudo;
122 int offset;
123 int size;
124 };
125 /* STOR_ARG */
126 struct {
127 int idx;
128 };
129 /* STOR_SYM */
130 struct {
131 struct symbol *sym;
132 };
133 /* STOR_VALUE */
134 struct {
135 long long value;
136 };
137 /* STOR_LABEL */
138 struct {
139 int label;
140 };
141 /* STOR_LABELSYM */
142 struct {
143 struct symbol *labelsym;
144 };
145 };
146 };
147
148 enum {
149 STOR_LABEL_VAL = (1 << 0),
150 STOR_WANTS_FREE = (1 << 1),
151 };
152
153 struct symbol_private {
154 struct storage *addr;
155 };
156
157 enum atom_type {
158 ATOM_TEXT,
159 ATOM_INSN,
160 ATOM_CSTR,
161 };
162
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 */
170 };
171
172 /* stuff for insns */
173 struct {
174 char insn[32];
175 char comment[40];
176 struct storage *op1;
177 struct storage *op2;
178 };
179
180 /* stuff for C strings */
181 struct {
182 struct string *string;
183 int label;
184 };
185 };
186 };
187
188
189 static struct function *current_func = NULL;
190 static struct textbuf *unit_post_text = NULL;
191 static const char *current_section;
192
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);
202
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
209 };
210
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)
215
216 #define REGINFO(nr, str, conflicts...) [nr] = { .name = str, .aliases = { nr , conflicts } }
217
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),
246 };
247
248 #define REGSTORAGE(nr) [nr] = { .type = STOR_REG, .reg = reg_info_table + (nr) }
249
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),
258 };
259
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])
268
269 static DECLARE_BITMAP(regs_in_use, 256);
270
271 static inline struct storage * reginfo_reg(struct reg_info *info)
272 {
273 return hardreg_storage_table + info->own_regno;
274 }
275
276 static struct storage * get_hardreg(struct storage *reg, int clear)
277 {
278 struct reg_info *info = reg->reg;
279 const unsigned char *aliases;
280 int regno;
281
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;
288 }
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);
296 }
297
298 static void put_reg(struct storage *reg)
299 {
300 struct reg_info *info = reg->reg;
301 int regno = info->own_regno;
302
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);
306 }
307
308 struct regclass {
309 const char *name;
310 const unsigned char regs[30];
311 };
312
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 }};
317
318 static struct regclass regclass_32_8 = { "32-bit bytes", { EAX, EDX, ECX, EBX }};
319
320 static struct regclass *get_regclass_bits(int bits)
321 {
322 switch (bits) {
323 case 8: return ®class_8;
324 case 16: return ®class_16;
325 case 64: return ®class_64;
326 default: return ®class_32;
327 }
328 }
329
330 static struct regclass *get_regclass(struct expression *expr)
331 {
332 return get_regclass_bits(expr->ctype->bit_size);
333 }
334
335 static int register_busy(int regno)
336 {
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;
340
341 while ((regno = *regs) != NOREG) {
342 regs++;
343 if (test_bit(regno, regs_in_use))
344 goto busy;
345 }
346 return 0;
347 }
348 busy:
349 return 1;
350 }
351
352 static struct storage *get_reg(struct regclass *class)
353 {
354 const unsigned char *regs = class->regs;
355 int regno;
356
357 while ((regno = *regs) != NOREG) {
358 regs++;
359 if (register_busy(regno))
360 continue;
361 return get_hardreg(hardreg_storage_table + regno, 1);
362 }
363 fprintf(stderr, "Ran out of %s registers\n", class->name);
364 exit(1);
365 }
366
367 static struct storage *get_reg_value(struct storage *value, struct regclass *class)
368 {
369 struct reg_info *info;
370 struct storage *reg;
371
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);
377 }
378
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;
385 }
386
387 static struct storage *temp_from_bits(unsigned int bit_size)
388 {
389 return get_reg(get_regclass_bits(bit_size));
390 }
391
392 static inline unsigned int pseudo_offset(struct storage *s)
393 {
394 if (s->type != STOR_PSEUDO)
395 return 123456; /* intentionally bogus value */
396
397 return s->offset;
398 }
399
400 static inline unsigned int arg_offset(struct storage *s)
401 {
402 if (s->type != STOR_ARG)
403 return 123456; /* intentionally bogus value */
404
405 /* FIXME: this is wrong wrong wrong */
406 return current_func->stack_size + ((1 + s->idx) * 4);
407 }
408
409 static const char *pretty_offset(int ofs)
410 {
411 static char esp_buf[64];
412
413 if (ofs)
414 sprintf(esp_buf, "%d(%%esp)", ofs);
415 else
416 strcpy(esp_buf, "(%esp)");
417
418 return esp_buf;
419 }
420
421 static void stor_sym_init(struct symbol *sym)
422 {
423 struct storage *stor;
424 struct symbol_private *priv;
425
426 priv = calloc(1, sizeof(*priv) + sizeof(*stor));
427 if (!priv)
428 die("OOM in stor_sym_init");
429
430 stor = (struct storage *) (priv + 1);
431
432 priv->addr = stor;
433 stor->type = STOR_SYM;
434 stor->sym = sym;
435 }
436
437 static const char *stor_op_name(struct storage *s)
438 {
439 static char name[32];
440
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;
465 }
466
467 return name;
468 }
469
470 static struct atom *new_atom(enum atom_type type)
471 {
472 struct atom *atom;
473
474 atom = calloc(1, sizeof(*atom)); /* TODO: chunked alloc */
475 if (!atom)
476 die("nuclear OOM");
477
478 atom->type = type;
479
480 return atom;
481 }
482
483 static inline void push_cstring(struct function *f, struct string *str,
484 int label)
485 {
486 struct atom *atom;
487
488 atom = new_atom(ATOM_CSTR);
489 atom->string = str;
490 atom->label = label;
491
492 add_ptr_list(&f->str_list, atom); /* note: _not_ atom_list */
493 }
494
495 static inline void push_atom(struct function *f, struct atom *atom)
496 {
497 add_ptr_list(&f->atom_list, atom);
498 }
499
500 static void push_text_atom(struct function *f, const char *text)
501 {
502 struct atom *atom = new_atom(ATOM_TEXT);
503
504 atom->text = strdup(text);
505 atom->text_len = strlen(text);
506
507 push_atom(f, atom);
508 }
509
510 static struct storage *new_storage(enum storage_type type)
511 {
512 struct storage *stor;
513
514 stor = calloc(1, sizeof(*stor));
515 if (!stor)
516 die("OOM in new_storage");
517
518 stor->type = type;
519
520 return stor;
521 }
522
523 static struct storage *stack_alloc(int n_bytes)
524 {
525 struct function *f = current_func;
526 struct storage *stor;
527
528 assert(f != NULL);
529
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++;
537
538 add_ptr_list(&f->pseudo_list, stor);
539
540 return stor;
541 }
542
543 static struct storage *new_labelsym(struct symbol *sym)
544 {
545 struct storage *stor;
546
547 stor = new_storage(STOR_LABELSYM);
548
549 if (stor) {
550 stor->flags |= STOR_WANTS_FREE;
551 stor->labelsym = sym;
552 }
553
554 return stor;
555 }
556
557 static struct storage *new_val(long long value)
558 {
559 struct storage *stor;
560
561 stor = new_storage(STOR_VALUE);
562
563 if (stor) {
564 stor->flags |= STOR_WANTS_FREE;
565 stor->value = value;
566 }
567
568 return stor;
569 }
570
571 static int new_label(void)
572 {
573 static int label = 0;
574 return ++label;
575 }
576
577 static void textbuf_push(struct textbuf **buf_p, const char *text)
578 {
579 struct textbuf *tmp, *list = *buf_p;
580 unsigned int text_len = strlen(text);
581 unsigned int alloc_len = text_len + 1 + sizeof(*list);
582
583 tmp = calloc(1, alloc_len);
584 if (!tmp)
585 die("OOM on textbuf alloc");
586
587 tmp->text = ((void *) tmp) + sizeof(*tmp);
588 memcpy(tmp->text, text, text_len + 1);
589 tmp->len = text_len;
590
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;
599 }
600 tmp->next = list;
601
602 *buf_p = list;
603 }
604
605 static void textbuf_emit(struct textbuf **buf_p)
606 {
607 struct textbuf *tmp, *list = *buf_p;
608
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;
617 }
618
619 fputs(tmp->text, stdout);
620
621 free(tmp);
622 }
623
624 *buf_p = list;
625 }
626
627 static void insn(const char *insn, struct storage *op1, struct storage *op2,
628 const char *comment_in)
629 {
630 struct function *f = current_func;
631 struct atom *atom = new_atom(ATOM_INSN);
632
633 assert(insn != NULL);
634
635 strcpy(atom->insn, insn);
636 if (comment_in && (*comment_in))
637 strncpy(atom->comment, comment_in,
638 sizeof(atom->comment) - 1);
639
640 atom->op1 = op1;
641 atom->op2 = op2;
642
643 push_atom(f, atom);
644 }
645
646 static void emit_comment(const char *fmt, ...)
647 {
648 struct function *f = current_func;
649 static char tmpbuf[100] = "\t# ";
650 va_list args;
651 int i;
652
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);
659 }
660
661 static void emit_label (int label, const char *comment)
662 {
663 struct function *f = current_func;
664 char s[64];
665
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);
670
671 push_text_atom(f, s);
672 }
673
674 static void emit_labelsym (struct symbol *sym, const char *comment)
675 {
676 struct function *f = current_func;
677 char s[64];
678
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);
683
684 push_text_atom(f, s);
685 }
686
687 void emit_unit_begin(const char *basename)
688 {
689 printf("\t.file\t\"%s\"\n", basename);
690 }
691
692 void emit_unit_end(void)
693 {
694 textbuf_emit(&unit_post_text);
695 printf("\t.ident\t\"sparse silly x86 backend (version %s)\"\n", SPARSE_VERSION);
696 }
697
698 /* conditionally switch sections */
699 static void emit_section(const char *s)
700 {
701 if (s == current_section)
702 return;
703 if (current_section && (!strcmp(s, current_section)))
704 return;
705
706 printf("\t%s\n", s);
707 current_section = s;
708 }
709
710 static void emit_insn_atom(struct function *f, struct atom *atom)
711 {
712 char s[128];
713 char comment[64];
714 struct storage *op1 = atom->op1;
715 struct storage *op2 = atom->op2;
716
717 if (atom->comment[0])
718 sprintf(comment, "\t\t# %s", atom->comment);
719 else
720 comment[0] = 0;
721
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);
735
736 if (write(STDOUT_FILENO, s, strlen(s)) < 0)
737 die("can't write to stdout");
738 }
739
740 static void emit_atom_list(struct function *f)
741 {
742 struct atom *atom;
743
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;
750 }
751 case ATOM_INSN:
752 emit_insn_atom(f, atom);
753 break;
754 case ATOM_CSTR:
755 assert(0);
756 break;
757 }
758 } END_FOR_EACH_PTR(atom);
759 }
760
761 static void emit_string_list(struct function *f)
762 {
763 struct atom *atom;
764
765 emit_section(".section\t.rodata");
766
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));
771
772 free(atom);
773 } END_FOR_EACH_PTR(atom);
774 }
775
776 static void func_cleanup(struct function *f)
777 {
778 struct storage *stor;
779 struct atom *atom;
780
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);
790
791 FOR_EACH_PTR(f->pseudo_list, stor) {
792 free(stor);
793 } END_FOR_EACH_PTR(stor);
794
795 free_ptr_list(&f->pseudo_list);
796 free(f);
797 }
798
799 /* function prologue */
800 static void emit_func_pre(struct symbol *sym)
801 {
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;
809
810 FOR_EACH_PTR(base_type->arguments, arg) {
811 argc++;
812 } END_FOR_EACH_PTR(arg);
813
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");
822
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;
830
831 f->argc = argc;
832 f->ret_target = new_label();
833
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);
843
844 assert(current_func == NULL);
845 current_func = f;
846 }
847
848 /* function epilogue */
849 static void emit_func_post(struct symbol *sym)
850 {
851 const char *name = show_ident(sym->ident);
852 struct function *f = current_func;
853 int stack_size = f->stack_size;
854
855 if (f->str_list)
856 emit_string_list(f);
857
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);
864
865 if (stack_size) {
866 char pseudo_const[16];
867
868 sprintf(pseudo_const, "$%d", stack_size);
869 printf("\tsubl\t%s, %%esp\n", pseudo_const);
870 }
871
872 /* function epilogue */
873
874 /* jump target for 'return' statements */
875 emit_label(f->ret_target, NULL);
876
877 if (stack_size) {
878 struct storage *val;
879
880 val = new_storage(STOR_VALUE);
881 val->value = (long long) (stack_size);
882 val->flags = STOR_WANTS_FREE;
883
884 insn("addl", val, REG_ESP, NULL);
885 }
886
887 insn("ret", NULL, NULL, NULL);
888
889 /* output everything to stdout */
890 fflush(stdout); /* paranoia; needed? */
891 emit_atom_list(f);
892
893 /* function footer */
894 name = show_ident(sym->ident);
895 printf("\t.size\t%s, .-%s\n", name, name);
896
897 func_cleanup(f);
898 current_func = NULL;
899 }
900
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)
904 {
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);
913 }
914
915 /* emit value (only) for an initializer scalar */
916 static void emit_scalar(struct expression *expr, unsigned int bit_size)
917 {
918 const char *type;
919 long long ll;
920
921 assert(expr->type == EXPR_VALUE);
922
923 if (expr->value == 0ULL) {
924 printf("\t.zero\t%d\n", bit_size / 8);
925 return;
926 }
927
928 ll = (long long) expr->value;
929
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;
936 }
937
938 assert(type != NULL);
939
940 printf("\t.%s\t%Ld\n", type, ll);
941 }
942
943 static void emit_global_noinit(const char *name, unsigned long modifiers,
944 unsigned long alignment, unsigned int byte_size)
945 {
946 char s[64];
947
948 if (modifiers & MOD_STATIC) {
949 sprintf(s, "\t.local\t%s\n", name);
950 textbuf_push(&unit_post_text, s);
951 }
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);
957 }
958
959 static int ea_current, ea_last;
960
961 static void emit_initializer(struct symbol *sym,
962 struct expression *expr)
963 {
964 int distance = ea_current - ea_last - 1;
965
966 if (distance > 0)
967 printf("\t.zero\t%d\n", (sym->bit_size / 8) * distance);
968
969 if (expr->type == EXPR_VALUE) {
970 struct symbol *base_type = sym->ctype.base_type;
971 assert(base_type != NULL);
972
973 emit_scalar(expr, sym->bit_size / get_expression_value(base_type->array_size));
974 return;
975 }
976 if (expr->type != EXPR_INITIALIZER)
977 return;
978
979 assert(0); /* FIXME */
980 }
981
982 static int sort_array_cmp(const struct expression *a,
983 const struct expression *b)
984 {
985 int a_ofs = 0, b_ofs = 0;
986
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;
991
992 return a_ofs - b_ofs;
993 }
994
995 /* move to front-end? */
996 static void sort_array(struct expression *expr)
997 {
998 struct expression *entry, **list;
999 unsigned int elem, sorted, i;
1000
1001 elem = expression_list_size(expr->expr_list);
1002 if (!elem)
1003 return;
1004
1005 list = malloc(sizeof(entry) * elem);
1006 if (!list)
1007 die("OOM in sort_array");
1008
1009 /* this code is no doubt evil and ignores EXPR_INDEX possibly
1010 * to its detriment and other nasty things. improvements
1011 * welcome.
1012 */
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;
1025
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...
1032 */
1033 if (i != sorted)
1034 memmove(&list[i + 1], &list[i],
1035 (sorted - i) * sizeof(entry));
1036 list[i] = entry;
1037 sorted++;
1038 }
1039 }
1040 } END_FOR_EACH_PTR(entry);
1041
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);
1047
1048 free(list);
1049 }
1050
1051 static void emit_array(struct symbol *sym)
1052 {
1053 struct symbol *base_type = sym->ctype.base_type;
1054 struct expression *expr = sym->initializer;
1055 struct expression *entry;
1056
1057 assert(base_type != NULL);
1058
1059 stor_sym_init(sym);
1060
1061 ea_last = -1;
1062
1063 emit_object_pre(show_ident(sym->ident), sym->ctype.modifiers,
1064 sym->ctype.alignment,
1065 sym->bit_size / 8);
1066
1067 sort_array(expr);
1068
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;
1079 }
1080 } END_FOR_EACH_PTR(entry);
1081 }
1082
1083 void emit_one_symbol(struct symbol *sym)
1084 {
1085 x86_symbol(sym);
1086 }
1087
1088 static void emit_copy(struct storage *dest, struct storage *src,
1089 struct symbol *ctype)
1090 {
1091 struct storage *reg = NULL;
1092 unsigned int bit_size;
1093
1094 /* FIXME: Bitfield copy! */
1095
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;
1101
1102 reg = temp_from_bits(bit_size);
1103 emit_move(src, reg, ctype, "begin copy ..");
1104
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;
1110
1111 emit_move(reg, dest, ctype, ".... end copy");
1112 put_reg(reg);
1113 }
1114
1115 static void emit_store(struct expression *dest_expr, struct storage *dest,
1116 struct storage *src, int bits)
1117 {
1118 /* FIXME: Bitfield store! */
1119 printf("\tst.%d\t\tv%d,[v%d]\n", bits, src->pseudo, dest->pseudo);
1120 }
1121
1122 static void emit_scalar_noinit(struct symbol *sym)
1123 {
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);
1128 }
1129
1130 static void emit_array_noinit(struct symbol *sym)
1131 {
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);
1136 }
1137
1138 static const char *opbits(const char *insn, unsigned int bits)
1139 {
1140 static char opbits_str[32];
1141 char c;
1142
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;
1149 }
1150
1151 sprintf(opbits_str, "%s%c", insn, c);
1152
1153 return opbits_str;
1154 }
1155
1156 static void emit_move(struct storage *src, struct storage *dest,
1157 struct symbol *ctype, const char *comment)
1158 {
1159 unsigned int bits;
1160 unsigned int is_signed;
1161 unsigned int is_dest = (src->type == STOR_REG);
1162 const char *opname;
1163
1164 if (ctype) {
1165 bits = ctype->bit_size;
1166 is_signed = type_is_signed(ctype);
1167 } else {
1168 bits = 32;
1169 is_signed = 0;
1170 }
1171
1172 /*
1173 * Are we moving from a register to a register?
1174 * Make the new reg to be the "cache".
1175 */
1176 if ((dest->type == STOR_REG) && (src->type == STOR_REG)) {
1177 struct storage *backing;
1178
1179 reg_reg_move:
1180 if (dest == src)
1181 return;
1182
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;
1190 }
1191 dest->reg->contains = backing;
1192 insn("mov", src, dest, NULL);
1193 return;
1194 }
1195
1196 /*
1197 * Are we moving to a register from a non-reg?
1198 *
1199 * See if we have the non-reg source already cached
1200 * in a register..
1201 */
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;
1208 }
1209 }
1210 dest->reg->contains = src;
1211 src->reg = dest->reg;
1212 }
1213
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;
1218 }
1219
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";
1227
1228 insn(opbits(opname, bits), src, dest, comment);
1229 }
1230
1231 static struct storage *emit_compare(struct expression *expr)
1232 {
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;
1239
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;
1260 }
1261
1262 /* init EDX to 0 */
1263 val = new_storage(STOR_VALUE);
1264 val->flags = STOR_WANTS_FREE;
1265
1266 reg1 = get_reg(®class_32_8);
1267 emit_move(val, reg1, NULL, NULL);
1268
1269 /* move op1 into EAX */
1270 reg2 = get_reg_value(left, get_regclass(expr->left));
1271
1272 /* perform comparison, RHS (op1, right) and LHS (op2, EAX) */
1273 insn(opbits("cmp", right_bits), right, reg2, NULL);
1274 put_reg(reg2);
1275
1276 /* store result of operation, 0 or 1, in DL using SETcc */
1277 insn(opname, byte_reg(reg1), NULL, NULL);
1278
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);
1283
1284 return new;
1285 }
1286
1287 static struct storage *emit_value(struct expression *expr)
1288 {
1289 #if 0 /* old and slow way */
1290 struct storage *new = stack_alloc(4);
1291 struct storage *val;
1292
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);
1297
1298 return new;
1299 #else
1300 struct storage *val;
1301
1302 val = new_storage(STOR_VALUE);
1303 val->value = (long long) expr->value;
1304
1305 return val; /* FIXME: memory leak */
1306 #endif
1307 }
1308
1309 static struct storage *emit_divide(struct expression *expr, struct storage *left, struct storage *right)
1310 {
1311 struct storage *eax_edx;
1312 struct storage *reg, *new;
1313 struct storage *val = new_storage(STOR_VALUE);
1314
1315 emit_comment("begin DIVIDE");
1316 eax_edx = get_hardreg(hardreg_storage_table + EAX_EDX, 1);
1317
1318 /* init EDX to 0 */
1319 val->flags = STOR_WANTS_FREE;
1320 emit_move(val, REG_EDX, NULL, NULL);
1321
1322 new = stack_alloc(expr->ctype->bit_size / 8);
1323
1324 /* EAX is dividend */
1325 emit_move(left, REG_EAX, NULL, NULL);
1326
1327 reg = get_reg_value(right, ®class_32);
1328
1329 /* perform binop */
1330 insn("div", reg, REG_EAX, NULL);
1331 put_reg(reg);
1332
1333 reg = REG_EAX;
1334 if (expr->op == '%')
1335 reg = REG_EDX;
1336 emit_move(reg, new, NULL, NULL);
1337
1338 put_reg(eax_edx);
1339 emit_comment("end DIVIDE");
1340 return new;
1341 }
1342
1343 static struct storage *emit_binop(struct expression *expr)
1344 {
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;
1353
1354 /* Divides have special register constraints */
1355 if ((expr->op == '/') || (expr->op == '%'))
1356 return emit_divide(expr, left, right);
1357
1358 is_signed = type_is_signed(expr->ctype);
1359
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;
1402 }
1403
1404 dest = get_reg_value(right, ®class_32);
1405 src = get_reg_value(left, ®class_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;
1422 }
1423
1424 snprintf(opstr, sizeof(opstr), "%s%s", opname, suffix);
1425
1426 /* perform binop */
1427 insn(opstr, src, dest, NULL);
1428 put_reg(src);
1429
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");
1433
1434 put_reg(dest);
1435
1436 return new;
1437 }
1438
1439 static int emit_conditional_test(struct storage *val)
1440 {
1441 struct storage *reg;
1442 struct storage *target_val;
1443 int target_false;
1444
1445 /* load result into EAX */
1446 emit_comment("begin if/conditional");
1447 reg = get_reg_value(val, ®class_32);
1448
1449 /* compare result with zero */
1450 insn("test", reg, reg, NULL);
1451 put_reg(reg);
1452
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);
1459
1460 return target_false;
1461 }
1462
1463 static int emit_conditional_end(int target_false)
1464 {
1465 struct storage *cond_end_st;
1466 int cond_end;
1467
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.
1471 */
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);
1477
1478 /* if we have both if-true and if-false statements,
1479 * the failed-conditional case will fall through to here
1480 */
1481 emit_label(target_false, NULL);
1482
1483 return cond_end;
1484 }
1485
1486 static void emit_if_conditional(struct statement *stmt)
1487 {
1488 struct storage *val;
1489 int cond_end;
1490
1491 /* emit test portion of conditional */
1492 val = x86_expression(stmt->if_conditional);
1493 cond_end = emit_conditional_test(val);
1494
1495 /* emit if-true statement */
1496 x86_statement(stmt->if_true);
1497
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);
1502 }
1503
1504 /* end of conditional; jump target for if-true branch */
1505 emit_label(cond_end, "end if");
1506 }
1507
1508 static struct storage *emit_inc_dec(struct expression *expr, int postop)
1509 {
1510 struct storage *addr = x86_address_gen(expr->unop);
1511 struct storage *retval;
1512 char opname[16];
1513
1514 strcpy(opname, opbits(expr->op == SPECIAL_INCREMENT ? "inc" : "dec",
1515 expr->ctype->bit_size));
1516
1517 if (postop) {
1518 struct storage *new = stack_alloc(4);
1519
1520 emit_copy(new, addr, expr->unop->ctype);
1521
1522 retval = new;
1523 } else
1524 retval = addr;
1525
1526 insn(opname, addr, NULL, NULL);
1527
1528 return retval;
1529 }
1530
1531 static struct storage *emit_postop(struct expression *expr)
1532 {
1533 return emit_inc_dec(expr, 1);
1534 }
1535
1536 static struct storage *emit_return_stmt(struct statement *stmt)
1537 {
1538 struct function *f = current_func;
1539 struct expression *expr = stmt->ret_value;
1540 struct storage *val = NULL, *jmplbl;
1541
1542 if (expr && expr->ctype) {
1543 val = x86_expression(expr);
1544 assert(val != NULL);
1545 emit_move(val, REG_EAX, expr->ctype, "return");
1546 }
1547
1548 jmplbl = new_storage(STOR_LABEL);
1549 jmplbl->flags |= STOR_WANTS_FREE;
1550 jmplbl->label = f->ret_target;
1551 insn("jmp", jmplbl, NULL, NULL);
1552
1553 return val;
1554 }
1555
1556 static struct storage *emit_conditional_expr(struct expression *expr)
1557 {
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;
1561
1562 /* evaluate conditional */
1563 cond = x86_expression(expr->conditional);
1564 target_false = emit_conditional_test(cond);
1565
1566 /* handle if-true part of the expression */
1567 true = x86_expression(expr->cond_true);
1568
1569 emit_copy(new, true, expr->ctype);
1570
1571 cond_end = emit_conditional_end(target_false);
1572
1573 /* handle if-false part of the expression */
1574 false = x86_expression(expr->cond_false);
1575
1576 emit_copy(new, false, expr->ctype);
1577
1578 /* end of conditional; jump target for if-true branch */
1579 emit_label(cond_end, "end conditional");
1580
1581 return new;
1582 }
1583
1584 static struct storage *emit_select_expr(struct expression *expr)
1585 {
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);
1591
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));
1596
1597 /*
1598 * Do the actual select: check the conditional for zero,
1599 * move false over true if zero
1600 */
1601 insn("test", reg_cond, reg_cond, NULL);
1602 insn("cmovz", reg_false, reg_true, NULL);
1603
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;
1611 }
1612
1613 static struct storage *emit_symbol_expr_init(struct symbol *sym)
1614 {
1615 struct expression *expr = sym->initializer;
1616 struct symbol_private *priv = sym->aux;
1617
1618 if (priv == NULL) {
1619 priv = calloc(1, sizeof(*priv));
1620 sym->aux = priv;
1621
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);
1630 }
1631 }
1632
1633 return priv->addr;
1634 }
1635
1636 static struct storage *emit_string_expr(struct expression *expr)
1637 {
1638 struct function *f = current_func;
1639 int label = new_label();
1640 struct storage *new;
1641
1642 push_cstring(f, expr->string, label);
1643
1644 new = new_storage(STOR_LABEL);
1645 new->label = label;
1646 new->flags = STOR_LABEL_VAL | STOR_WANTS_FREE;
1647 return new;
1648 }
1649
1650 static struct storage *emit_cast_expr(struct expression *expr)
1651 {
1652 struct symbol *old_type, *new_type;
1653 struct storage *op = x86_expression(expr->cast_expression);
1654 int oldbits, newbits;
1655 struct storage *new;
1656
1657 old_type = expr->cast_expression->ctype;
1658 new_type = expr->cast_type;
1659
1660 oldbits = old_type->bit_size;
1661 newbits = new_type->bit_size;
1662 if (oldbits >= newbits)
1663 return op;
1664
1665 emit_move(op, REG_EAX, old_type, "begin cast ..");
1666
1667 new = stack_alloc(newbits / 8);
1668 emit_move(REG_EAX, new, new_type, ".... end cast");
1669
1670 return new;
1671 }
1672
1673 static struct storage *emit_regular_preop(struct expression *expr)
1674 {
1675 struct storage *target = x86_expression(expr->unop);
1676 struct storage *val, *new = stack_alloc(4);
1677 const char *opname = NULL;
1678
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);
1688
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;
1702 }
1703
1704 return new;
1705 }
1706
1707 static void emit_case_statement(struct statement *stmt)
1708 {
1709 emit_labelsym(stmt->case_label, NULL);
1710 x86_statement(stmt->case_statement);
1711 }
1712
1713 static void emit_switch_statement(struct statement *stmt)
1714 {
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;
1719
1720 emit_move(val, REG_EAX, stmt->switch_expression->ctype, "begin case");
1721
1722 /*
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
1726 */
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;
1731
1732 /* default: */
1733 if (!expr)
1734 default_sym = sym;
1735
1736 /* case NNN: */
1737 else {
1738 struct storage *case_val = new_val(expr->value);
1739
1740 assert (expr->type == EXPR_VALUE);
1741
1742 insn("cmpl", case_val, REG_EAX, NULL);
1743
1744 if (!to) {
1745 labelsym = new_labelsym(sym);
1746 insn("je", labelsym, NULL, NULL);
1747 } else {
1748 int next_test;
1749
1750 label = new_storage(STOR_LABEL);
1751 label->flags |= STOR_WANTS_FREE;
1752 label->label = next_test = new_label();
1753
1754 /* FIXME: signed/unsigned */
1755 insn("jl", label, NULL, NULL);
1756
1757 case_val = new_val(to->value);
1758 insn("cmpl", case_val, REG_EAX, NULL);
1759
1760 /* TODO: implement and use refcounting... */
1761 label = new_storage(STOR_LABEL);
1762 label->flags |= STOR_WANTS_FREE;
1763 label->label = next_test;
1764
1765 /* FIXME: signed/unsigned */
1766 insn("jg", label, NULL, NULL);
1767
1768 labelsym = new_labelsym(sym);
1769 insn("jmp", labelsym, NULL, NULL);
1770
1771 emit_label(next_test, NULL);
1772 }
1773 }
1774 } END_FOR_EACH_PTR(sym);
1775
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");
1784 }
1785
1786 x86_statement(stmt->switch_statement);
1787
1788 if (stmt->switch_break->used)
1789 emit_labelsym(stmt->switch_break, NULL);
1790
1791 if (switch_end)
1792 emit_label(switch_end, NULL);
1793 }
1794
1795 static void x86_struct_member(struct symbol *sym)
1796 {
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");
1799 }
1800
1801 static void x86_symbol(struct symbol *sym)
1802 {
1803 struct symbol *type;
1804
1805 if (!sym)
1806 return;
1807
1808 type = sym->ctype.base_type;
1809 if (!type)
1810 return;
1811
1812 /*
1813 * Show actual implementation information
1814 */
1815 switch (type->type) {
1816
1817 case SYM_ARRAY:
1818 if (sym->initializer)
1819 emit_array(sym);
1820 else
1821 emit_array_noinit(sym);
1822 break;
1823
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;
1835
1836 case SYM_STRUCT:
1837 case SYM_UNION: {
1838 struct symbol *member;
1839
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;
1846 }
1847
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);
1854 }
1855 break;
1856 }
1857
1858 default:
1859 break;
1860 }
1861
1862 if (sym->initializer && (type->type != SYM_BASETYPE) &&
1863 (type->type != SYM_ARRAY)) {
1864 printf(" = \n");
1865 x86_expression(sym->initializer);
1866 }
1867 }
1868
1869 static void x86_symbol_init(struct symbol *sym);
1870
1871 static void x86_symbol_decl(struct symbol_list *syms)
1872 {
1873 struct symbol *sym;
1874 FOR_EACH_PTR(syms, sym) {
1875 x86_symbol_init(sym);
1876 } END_FOR_EACH_PTR(sym);
1877 }
1878
1879 static void loopstk_push(int cont_lbl, int loop_bottom_lbl)
1880 {
1881 struct function *f = current_func;
1882 struct loop_stack *ls;
1883
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;
1889 }
1890
1891 static void loopstk_pop(void)
1892 {
1893 struct function *f = current_func;
1894 struct loop_stack *ls;
1895
1896 assert(f->loop_stack != NULL);
1897 ls = f->loop_stack;
1898 f->loop_stack = f->loop_stack->next;
1899 free(ls);
1900 }
1901
1902 static int loopstk_break(void)
1903 {
1904 return current_func->loop_stack->loop_bottom_lbl;
1905 }
1906
1907 static int loopstk_continue(void)
1908 {
1909 return current_func->loop_stack->continue_lbl;
1910 }
1911
1912 static void emit_loop(struct statement *stmt)
1913 {
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;
1922
1923 loop_bottom = new_label();
1924 loop_continue = new_label();
1925 loopstk_push(loop_continue, loop_bottom);
1926
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");
1932 }
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;
1942 }
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;
1948
1949 val = x86_expression(pre_condition);
1950
1951 emit_move(val, REG_EAX, NULL, "loop pre condition");
1952 insn("test", REG_EAX, REG_EAX, NULL);
1953 insn("jz", lbv, NULL, NULL);
1954 }
1955 }
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");
1971 }
1972 } else {
1973 struct storage *lbv = new_storage(STOR_LABEL);
1974 lbv->label = loop_top;
1975 lbv->flags = STOR_WANTS_FREE;
1976
1977 val = x86_expression(post_condition);
1978
1979 emit_move(val, REG_EAX, NULL, "loop post condition");
1980 insn("test", REG_EAX, REG_EAX, NULL);
1981 insn("jnz", lbv, NULL, NULL);
1982 }
1983 if (have_bottom || stmt->iterator_break->used)
1984 emit_label(loop_bottom, "loop bottom");
1985
1986 loopstk_pop();
1987 }
1988
1989 /*
1990 * Print out a statement
1991 */
1992 static struct storage *x86_statement(struct statement *stmt)
1993 {
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;
2007
2008 FOR_EACH_PTR(stmt->stmts, s) {
2009 last = x86_statement(s);
2010 } END_FOR_EACH_PTR(s);
2011
2012 return last;
2013 }
2014
2015 case STMT_EXPRESSION:
2016 return x86_expression(stmt->expression);
2017 case STMT_IF:
2018 emit_if_conditional(stmt);
2019 return NULL;
2020
2021 case STMT_CASE:
2022 emit_case_statement(stmt);
2023 break;
2024 case STMT_SWITCH:
2025 emit_switch_statement(stmt);
2026 break;
2027
2028 case STMT_ITERATOR:
2029 emit_loop(stmt);
2030 break;
2031
2032 case STMT_NONE:
2033 break;
2034
2035 case STMT_LABEL:
2036 printf(".L%p:\n", stmt->label_identifier);
2037 x86_statement(stmt->label_statement);
2038 break;
2039
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);
2057 }
2058 break;
2059 case STMT_ASM:
2060 printf("\tasm( .... )\n");
2061 break;
2062 }
2063 return NULL;
2064 }
2065
2066 static struct storage *x86_call_expression(struct expression *expr)
2067 {
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];
2074
2075 if (!expr->ctype) {
2076 warning(expr->pos, "\tcall with no type!");
2077 return NULL;
2078 }
2079
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;
2084
2085 /*
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.
2091 */
2092 if (size < 32)
2093 size = 32;
2094 insn("pushl", new, NULL,
2095 !framesize ? "begin function call" : NULL);
2096
2097 framesize += bits_to_bytes(size);
2098 } END_FOR_EACH_PTR_REVERSE(arg);
2099
2100 fn = expr->fn;
2101
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;
2109 }
2110 }
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);
2119
2120 strcpy(s, "\tcall\t*%eax\n");
2121 push_text_atom(f, s);
2122 }
2123
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);
2130 }
2131
2132 retval = stack_alloc(4);
2133 emit_move(REG_EAX, retval, NULL, "end function call");
2134
2135 return retval;
2136 }
2137
2138 static struct storage *x86_address_gen(struct expression *expr)
2139 {
2140 struct function *f = current_func;
2141 struct storage *addr;
2142 struct storage *new;
2143 char s[32];
2144
2145 addr = x86_expression(expr->unop);
2146 if (expr->unop->type == EXPR_SYMBOL)
2147 return addr;
2148
2149 emit_move(addr, REG_EAX, NULL, "begin deref ..");
2150
2151 /* FIXME: operand size */
2152 strcpy(s, "\tmovl\t(%eax), %ecx\n");
2153 push_text_atom(f, s);
2154
2155 new = stack_alloc(4);
2156 emit_move(REG_ECX, new, NULL, ".... end deref");
2157
2158 return new;
2159 }
2160
2161 static struct storage *x86_assignment(struct expression *expr)
2162 {
2163 struct expression *target = expr->left;
2164 struct storage *val, *addr;
2165
2166 if (!expr->ctype)
2167 return NULL;
2168
2169 val = x86_expression(expr->right);
2170 addr = x86_address_gen(target);
2171
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;
2178
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;
2186
2187 case STOR_LABELSYM:
2188 assert(0);
2189 break;
2190 }
2191 return val;
2192 }
2193
2194 static int x86_initialization(struct symbol *sym, struct expression *expr)
2195 {
2196 struct storage *val, *addr;
2197 int bits;
2198
2199 if (!expr->ctype)
2200 return 0;
2201
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;
2209 }
2210
2211 static struct storage *x86_access(struct expression *expr)
2212 {
2213 return x86_address_gen(expr);
2214 }
2215
2216 static struct storage *x86_preop(struct expression *expr)
2217 {
2218 /*
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..
2222 */
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);
2228 }
2229
2230 static struct storage *x86_symbol_expr(struct symbol *sym)
2231 {
2232 struct storage *new = stack_alloc(4);
2233
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;
2237 }
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;
2241 }
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;
2244 }
2245
2246 static void x86_symbol_init(struct symbol *sym)
2247 {
2248 struct symbol_private *priv = sym->aux;
2249 struct expression *expr = sym->initializer;
2250 struct storage *new;
2251
2252 if (expr)
2253 new = x86_expression(expr);
2254 else
2255 new = stack_alloc(sym->bit_size / 8);
2256
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) */
2262 }
2263
2264 priv->addr = new;
2265 }
2266
2267 static int type_is_signed(struct symbol *sym)
2268 {
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);
2274 }
2275
2276 static struct storage *x86_label_expr(struct expression *expr)
2277 {
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;
2281 }
2282
2283 static struct storage *x86_statement_expr(struct expression *expr)
2284 {
2285 return x86_statement(expr->statement);
2286 }
2287
2288 static int x86_position_expr(struct expression *expr, struct symbol *base)
2289 {
2290 struct storage *new = x86_expression(expr->init_expr);
2291 struct symbol *ctype = expr->init_expr->ctype;
2292
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;
2297 }
2298
2299 static void x86_initializer_expr(struct expression *expr, struct symbol *ctype)
2300 {
2301 struct expression *entry;
2302
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;
2309 }
2310
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;
2318 }
2319 x86_initialization(ctype, entry);
2320 } END_FOR_EACH_PTR(entry);
2321 }
2322
2323 /*
2324 * Print out an expression. Return the pseudo that contains the
2325 * variable.
2326 */
2327 static struct storage *x86_expression(struct expression *expr)
2328 {
2329 if (!expr)
2330 return NULL;
2331
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;
2338 }
2339
2340 switch (expr->type) {
2341 default:
2342 return NULL;
2343 case EXPR_CALL:
2344 return x86_call_expression(expr);
2345
2346 case EXPR_ASSIGNMENT:
2347 return x86_assignment(expr);
2348
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);
2385
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;
2403 }
2404 return NULL;
2405 }