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 struct storage *x86_address_gen(struct expression *expr);
197 static struct storage *x86_symbol_expr(struct symbol *sym);
198 static void x86_symbol(struct symbol *sym);
199 static struct storage *x86_statement(struct statement *stmt);
200 static struct storage *x86_expression(struct expression *expr);
201
202 enum registers {
203 NOREG,
204 AL, DL, CL, BL, AH, DH, CH, BH, // 8-bit
205 AX, DX, CX, BX, SI, DI, BP, SP, // 16-bit
206 EAX, EDX, ECX, EBX, ESI, EDI, EBP, ESP, // 32-bit
207 EAX_EDX, ECX_EBX, ESI_EDI, // 64-bit
208 };
209
210 /* This works on regno's, reg_info's and hardreg_storage's */
211 #define byte_reg(reg) ((reg) - 16)
212 #define highbyte_reg(reg) ((reg)-12)
213 #define word_reg(reg) ((reg)-8)
214
215 #define REGINFO(nr, str, conflicts...) [nr] = { .name = str, .aliases = { nr , conflicts } }
216
217 static struct reg_info reg_info_table[] = {
218 REGINFO( AL, "%al", AX, EAX, EAX_EDX),
219 REGINFO( DL, "%dl", DX, EDX, EAX_EDX),
220 REGINFO( CL, "%cl", CX, ECX, ECX_EBX),
221 REGINFO( BL, "%bl", BX, EBX, ECX_EBX),
222 REGINFO( AH, "%ah", AX, EAX, EAX_EDX),
223 REGINFO( DH, "%dh", DX, EDX, EAX_EDX),
224 REGINFO( CH, "%ch", CX, ECX, ECX_EBX),
225 REGINFO( BH, "%bh", BX, EBX, ECX_EBX),
226 REGINFO( AX, "%ax", AL, AH, EAX, EAX_EDX),
227 REGINFO( DX, "%dx", DL, DH, EDX, EAX_EDX),
228 REGINFO( CX, "%cx", CL, CH, ECX, ECX_EBX),
229 REGINFO( BX, "%bx", BL, BH, EBX, ECX_EBX),
230 REGINFO( SI, "%si", ESI, ESI_EDI),
231 REGINFO( DI, "%di", EDI, ESI_EDI),
232 REGINFO( BP, "%bp", EBP),
233 REGINFO( SP, "%sp", ESP),
234 REGINFO(EAX, "%eax", AL, AH, AX, EAX_EDX),
235 REGINFO(EDX, "%edx", DL, DH, DX, EAX_EDX),
236 REGINFO(ECX, "%ecx", CL, CH, CX, ECX_EBX),
237 REGINFO(EBX, "%ebx", BL, BH, BX, ECX_EBX),
238 REGINFO(ESI, "%esi", SI, ESI_EDI),
239 REGINFO(EDI, "%edi", DI, ESI_EDI),
240 REGINFO(EBP, "%ebp", BP),
241 REGINFO(ESP, "%esp", SP),
242 REGINFO(EAX_EDX, "%eax:%edx", AL, AH, AX, EAX, DL, DH, DX, EDX),
243 REGINFO(ECX_EBX, "%ecx:%ebx", CL, CH, CX, ECX, BL, BH, BX, EBX),
244 REGINFO(ESI_EDI, "%esi:%edi", SI, ESI, DI, EDI),
245 };
246
247 #define REGSTORAGE(nr) [nr] = { .type = STOR_REG, .reg = reg_info_table + (nr) }
248
249 static struct storage hardreg_storage_table[] = {
250 REGSTORAGE(AL), REGSTORAGE(DL), REGSTORAGE(CL), REGSTORAGE(BL),
251 REGSTORAGE(AH), REGSTORAGE(DH), REGSTORAGE(CH), REGSTORAGE(BH),
252 REGSTORAGE(AX), REGSTORAGE(DX), REGSTORAGE(CX), REGSTORAGE(BX),
253 REGSTORAGE(SI), REGSTORAGE(DI), REGSTORAGE(BP), REGSTORAGE(SP),
254 REGSTORAGE(EAX), REGSTORAGE(EDX), REGSTORAGE(ECX), REGSTORAGE(EBX),
255 REGSTORAGE(ESI), REGSTORAGE(EDI), REGSTORAGE(EBP), REGSTORAGE(ESP),
256 REGSTORAGE(EAX_EDX), REGSTORAGE(ECX_EBX), REGSTORAGE(ESI_EDI),
257 };
258
259 #define REG_EAX (&hardreg_storage_table[EAX])
260 #define REG_ECX (&hardreg_storage_table[ECX])
261 #define REG_EDX (&hardreg_storage_table[EDX])
262 #define REG_ESP (&hardreg_storage_table[ESP])
263 #define REG_DL (&hardreg_storage_table[DL])
264 #define REG_DX (&hardreg_storage_table[DX])
265 #define REG_AL (&hardreg_storage_table[AL])
266 #define REG_AX (&hardreg_storage_table[AX])
267
268 static DECLARE_BITMAP(regs_in_use, 256);
269
reginfo_reg(struct reg_info * info)270 static inline struct storage * reginfo_reg(struct reg_info *info)
271 {
272 return hardreg_storage_table + info->own_regno;
273 }
274
get_hardreg(struct storage * reg,int clear)275 static struct storage * get_hardreg(struct storage *reg, int clear)
276 {
277 struct reg_info *info = reg->reg;
278 const unsigned char *aliases;
279 int regno;
280
281 aliases = info->aliases;
282 while ((regno = *aliases++) != NOREG) {
283 if (test_bit(regno, regs_in_use))
284 goto busy;
285 if (clear)
286 reg_info_table[regno].contains = NULL;
287 }
288 set_bit(info->own_regno, regs_in_use);
289 return reg;
290 busy:
291 fprintf(stderr, "register %s is busy\n", info->name);
292 if (regno + reg_info_table != info)
293 fprintf(stderr, " conflicts with %s\n", reg_info_table[regno].name);
294 exit(1);
295 }
296
put_reg(struct storage * reg)297 static void put_reg(struct storage *reg)
298 {
299 struct reg_info *info = reg->reg;
300 int regno = info->own_regno;
301
302 if (test_and_clear_bit(regno, regs_in_use))
303 return;
304 fprintf(stderr, "freeing already free'd register %s\n", reg_info_table[regno].name);
305 }
306
307 struct regclass {
308 const char *name;
309 const unsigned char regs[30];
310 };
311
312 static struct regclass regclass_8 = { "8-bit", { AL, DL, CL, BL, AH, DH, CH, BH }};
313 static struct regclass regclass_16 = { "16-bit", { AX, DX, CX, BX, SI, DI, BP }};
314 static struct regclass regclass_32 = { "32-bit", { EAX, EDX, ECX, EBX, ESI, EDI, EBP }};
315 static struct regclass regclass_64 = { "64-bit", { EAX_EDX, ECX_EBX, ESI_EDI }};
316
317 static struct regclass regclass_32_8 = { "32-bit bytes", { EAX, EDX, ECX, EBX }};
318
get_regclass_bits(int bits)319 static struct regclass *get_regclass_bits(int bits)
320 {
321 switch (bits) {
322 case 8: return ®class_8;
323 case 16: return ®class_16;
324 case 64: return ®class_64;
325 default: return ®class_32;
326 }
327 }
328
get_regclass(struct expression * expr)329 static struct regclass *get_regclass(struct expression *expr)
330 {
331 return get_regclass_bits(expr->ctype->bit_size);
332 }
333
register_busy(int regno)334 static int register_busy(int regno)
335 {
336 if (!test_bit(regno, regs_in_use)) {
337 struct reg_info *info = reg_info_table + regno;
338 const unsigned char *regs = info->aliases+1;
339
340 while ((regno = *regs) != NOREG) {
341 regs++;
342 if (test_bit(regno, regs_in_use))
343 goto busy;
344 }
345 return 0;
346 }
347 busy:
348 return 1;
349 }
350
get_reg(struct regclass * class)351 static struct storage *get_reg(struct regclass *class)
352 {
353 const unsigned char *regs = class->regs;
354 int regno;
355
356 while ((regno = *regs) != NOREG) {
357 regs++;
358 if (register_busy(regno))
359 continue;
360 return get_hardreg(hardreg_storage_table + regno, 1);
361 }
362 fprintf(stderr, "Ran out of %s registers\n", class->name);
363 exit(1);
364 }
365
get_reg_value(struct storage * value,struct regclass * class)366 static struct storage *get_reg_value(struct storage *value, struct regclass *class)
367 {
368 struct reg_info *info;
369 struct storage *reg;
370
371 /* Do we already have it somewhere */
372 info = value->reg;
373 if (info && info->contains == value) {
374 emit_comment("already have register %s", info->name);
375 return get_hardreg(hardreg_storage_table + info->own_regno, 0);
376 }
377
378 reg = get_reg(class);
379 emit_move(value, reg, value->ctype, "reload register");
380 info = reg->reg;
381 info->contains = value;
382 value->reg = info;
383 return reg;
384 }
385
temp_from_bits(unsigned int bit_size)386 static struct storage *temp_from_bits(unsigned int bit_size)
387 {
388 return get_reg(get_regclass_bits(bit_size));
389 }
390
pseudo_offset(struct storage * s)391 static inline unsigned int pseudo_offset(struct storage *s)
392 {
393 if (s->type != STOR_PSEUDO)
394 return 123456; /* intentionally bogus value */
395
396 return s->offset;
397 }
398
arg_offset(struct storage * s)399 static inline unsigned int arg_offset(struct storage *s)
400 {
401 if (s->type != STOR_ARG)
402 return 123456; /* intentionally bogus value */
403
404 /* FIXME: this is wrong wrong wrong */
405 return current_func->stack_size + ((1 + s->idx) * 4);
406 }
407
pretty_offset(int ofs)408 static const char *pretty_offset(int ofs)
409 {
410 static char esp_buf[64];
411
412 if (ofs)
413 sprintf(esp_buf, "%d(%%esp)", ofs);
414 else
415 strcpy(esp_buf, "(%esp)");
416
417 return esp_buf;
418 }
419
stor_sym_init(struct symbol * sym)420 static void stor_sym_init(struct symbol *sym)
421 {
422 struct storage *stor;
423 struct symbol_private *priv;
424
425 priv = calloc(1, sizeof(*priv) + sizeof(*stor));
426 if (!priv)
427 die("OOM in stor_sym_init");
428
429 stor = (struct storage *) (priv + 1);
430
431 priv->addr = stor;
432 stor->type = STOR_SYM;
433 stor->sym = sym;
434 }
435
stor_op_name(struct storage * s)436 static const char *stor_op_name(struct storage *s)
437 {
438 static char name[32];
439
440 switch (s->type) {
441 case STOR_PSEUDO:
442 strcpy(name, pretty_offset((int) pseudo_offset(s)));
443 break;
444 case STOR_ARG:
445 strcpy(name, pretty_offset((int) arg_offset(s)));
446 break;
447 case STOR_SYM:
448 strcpy(name, show_ident(s->sym->ident));
449 break;
450 case STOR_REG:
451 strcpy(name, s->reg->name);
452 break;
453 case STOR_VALUE:
454 sprintf(name, "$%lld", s->value);
455 break;
456 case STOR_LABEL:
457 sprintf(name, "%s.L%d", s->flags & STOR_LABEL_VAL ? "$" : "",
458 s->label);
459 break;
460 case STOR_LABELSYM:
461 sprintf(name, "%s.LS%p", s->flags & STOR_LABEL_VAL ? "$" : "",
462 s->labelsym);
463 break;
464 }
465
466 return name;
467 }
468
new_atom(enum atom_type type)469 static struct atom *new_atom(enum atom_type type)
470 {
471 struct atom *atom;
472
473 atom = calloc(1, sizeof(*atom)); /* TODO: chunked alloc */
474 if (!atom)
475 die("nuclear OOM");
476
477 atom->type = type;
478
479 return atom;
480 }
481
push_cstring(struct function * f,struct string * str,int label)482 static inline void push_cstring(struct function *f, struct string *str,
483 int label)
484 {
485 struct atom *atom;
486
487 atom = new_atom(ATOM_CSTR);
488 atom->string = str;
489 atom->label = label;
490
491 add_ptr_list(&f->str_list, atom); /* note: _not_ atom_list */
492 }
493
push_atom(struct function * f,struct atom * atom)494 static inline void push_atom(struct function *f, struct atom *atom)
495 {
496 add_ptr_list(&f->atom_list, atom);
497 }
498
push_text_atom(struct function * f,const char * text)499 static void push_text_atom(struct function *f, const char *text)
500 {
501 struct atom *atom = new_atom(ATOM_TEXT);
502
503 atom->text = strdup(text);
504 atom->text_len = strlen(text);
505
506 push_atom(f, atom);
507 }
508
new_storage(enum storage_type type)509 static struct storage *new_storage(enum storage_type type)
510 {
511 struct storage *stor;
512
513 stor = calloc(1, sizeof(*stor));
514 if (!stor)
515 die("OOM in new_storage");
516
517 stor->type = type;
518
519 return stor;
520 }
521
stack_alloc(int n_bytes)522 static struct storage *stack_alloc(int n_bytes)
523 {
524 struct function *f = current_func;
525 struct storage *stor;
526
527 assert(f != NULL);
528
529 stor = new_storage(STOR_PSEUDO);
530 stor->type = STOR_PSEUDO;
531 stor->pseudo = f->pseudo_nr;
532 stor->offset = f->stack_size; /* FIXME: stack req. natural align */
533 stor->size = n_bytes;
534 f->stack_size += n_bytes;
535 f->pseudo_nr++;
536
537 add_ptr_list(&f->pseudo_list, stor);
538
539 return stor;
540 }
541
new_labelsym(struct symbol * sym)542 static struct storage *new_labelsym(struct symbol *sym)
543 {
544 struct storage *stor;
545
546 stor = new_storage(STOR_LABELSYM);
547
548 if (stor) {
549 stor->flags |= STOR_WANTS_FREE;
550 stor->labelsym = sym;
551 }
552
553 return stor;
554 }
555
new_val(long long value)556 static struct storage *new_val(long long value)
557 {
558 struct storage *stor;
559
560 stor = new_storage(STOR_VALUE);
561
562 if (stor) {
563 stor->flags |= STOR_WANTS_FREE;
564 stor->value = value;
565 }
566
567 return stor;
568 }
569
new_label(void)570 static int new_label(void)
571 {
572 static int label = 0;
573 return ++label;
574 }
575
textbuf_push(struct textbuf ** buf_p,const char * text)576 static void textbuf_push(struct textbuf **buf_p, const char *text)
577 {
578 struct textbuf *tmp, *list = *buf_p;
579 unsigned int text_len = strlen(text);
580 unsigned int alloc_len = text_len + 1 + sizeof(*list);
581
582 tmp = calloc(1, alloc_len);
583 if (!tmp)
584 die("OOM on textbuf alloc");
585
586 tmp->text = ((void *) tmp) + sizeof(*tmp);
587 memcpy(tmp->text, text, text_len + 1);
588 tmp->len = text_len;
589
590 /* add to end of list */
591 if (!list) {
592 list = tmp;
593 tmp->prev = tmp;
594 } else {
595 tmp->prev = list->prev;
596 tmp->prev->next = tmp;
597 list->prev = tmp;
598 }
599 tmp->next = list;
600
601 *buf_p = list;
602 }
603
textbuf_emit(struct textbuf ** buf_p)604 static void textbuf_emit(struct textbuf **buf_p)
605 {
606 struct textbuf *tmp, *list = *buf_p;
607
608 while (list) {
609 tmp = list;
610 if (tmp->next == tmp)
611 list = NULL;
612 else {
613 tmp->prev->next = tmp->next;
614 tmp->next->prev = tmp->prev;
615 list = tmp->next;
616 }
617
618 fputs(tmp->text, stdout);
619
620 free(tmp);
621 }
622
623 *buf_p = list;
624 }
625
insn(const char * insn,struct storage * op1,struct storage * op2,const char * comment_in)626 static void insn(const char *insn, struct storage *op1, struct storage *op2,
627 const char *comment_in)
628 {
629 struct function *f = current_func;
630 struct atom *atom = new_atom(ATOM_INSN);
631
632 assert(insn != NULL);
633
634 strcpy(atom->insn, insn);
635 if (comment_in && (*comment_in))
636 strncpy(atom->comment, comment_in,
637 sizeof(atom->comment) - 1);
638
639 atom->op1 = op1;
640 atom->op2 = op2;
641
642 push_atom(f, atom);
643 }
644
emit_comment(const char * fmt,...)645 static void emit_comment(const char *fmt, ...)
646 {
647 struct function *f = current_func;
648 static char tmpbuf[100] = "\t# ";
649 va_list args;
650 int i;
651
652 va_start(args, fmt);
653 i = vsnprintf(tmpbuf+3, sizeof(tmpbuf)-4, fmt, args);
654 va_end(args);
655 tmpbuf[i+3] = '\n';
656 tmpbuf[i+4] = '\0';
657 push_text_atom(f, tmpbuf);
658 }
659
emit_label(int label,const char * comment)660 static void emit_label (int label, const char *comment)
661 {
662 struct function *f = current_func;
663 char s[64];
664
665 if (!comment)
666 sprintf(s, ".L%d:\n", label);
667 else
668 sprintf(s, ".L%d:\t\t\t\t\t# %s\n", label, comment);
669
670 push_text_atom(f, s);
671 }
672
emit_labelsym(struct symbol * sym,const char * comment)673 static void emit_labelsym (struct symbol *sym, const char *comment)
674 {
675 struct function *f = current_func;
676 char s[64];
677
678 if (!comment)
679 sprintf(s, ".LS%p:\n", sym);
680 else
681 sprintf(s, ".LS%p:\t\t\t\t# %s\n", sym, comment);
682
683 push_text_atom(f, s);
684 }
685
emit_unit_begin(const char * basename)686 void emit_unit_begin(const char *basename)
687 {
688 printf("\t.file\t\"%s\"\n", basename);
689 }
690
emit_unit_end(void)691 void emit_unit_end(void)
692 {
693 textbuf_emit(&unit_post_text);
694 printf("\t.ident\t\"sparse silly x86 backend (version %s)\"\n", SPARSE_VERSION);
695 }
696
697 /* conditionally switch sections */
emit_section(const char * s)698 static void emit_section(const char *s)
699 {
700 if (s == current_section)
701 return;
702 if (current_section && (!strcmp(s, current_section)))
703 return;
704
705 printf("\t%s\n", s);
706 current_section = s;
707 }
708
emit_insn_atom(struct function * f,struct atom * atom)709 static void emit_insn_atom(struct function *f, struct atom *atom)
710 {
711 char s[128];
712 char comment[64];
713 struct storage *op1 = atom->op1;
714 struct storage *op2 = atom->op2;
715
716 if (atom->comment[0])
717 sprintf(comment, "\t\t# %s", atom->comment);
718 else
719 comment[0] = 0;
720
721 if (atom->op2) {
722 char tmp[16];
723 strcpy(tmp, stor_op_name(op1));
724 sprintf(s, "\t%s\t%s, %s%s\n",
725 atom->insn, tmp, stor_op_name(op2), comment);
726 } else if (atom->op1)
727 sprintf(s, "\t%s\t%s%s%s\n",
728 atom->insn, stor_op_name(op1),
729 comment[0] ? "\t" : "", comment);
730 else
731 sprintf(s, "\t%s\t%s%s\n",
732 atom->insn,
733 comment[0] ? "\t\t" : "", comment);
734
735 if (write(STDOUT_FILENO, s, strlen(s)) < 0)
736 die("can't write to stdout");
737 }
738
emit_atom_list(struct function * f)739 static void emit_atom_list(struct function *f)
740 {
741 struct atom *atom;
742
743 FOR_EACH_PTR(f->atom_list, atom) {
744 switch (atom->type) {
745 case ATOM_TEXT: {
746 if (write(STDOUT_FILENO, atom->text, atom->text_len) < 0)
747 die("can't write to stdout");
748 break;
749 }
750 case ATOM_INSN:
751 emit_insn_atom(f, atom);
752 break;
753 case ATOM_CSTR:
754 assert(0);
755 break;
756 }
757 } END_FOR_EACH_PTR(atom);
758 }
759
emit_string_list(struct function * f)760 static void emit_string_list(struct function *f)
761 {
762 struct atom *atom;
763
764 emit_section(".section\t.rodata");
765
766 FOR_EACH_PTR(f->str_list, atom) {
767 /* FIXME: escape " in string */
768 printf(".L%d:\n", atom->label);
769 printf("\t.string\t%s\n", show_string(atom->string));
770
771 free(atom);
772 } END_FOR_EACH_PTR(atom);
773 }
774
func_cleanup(struct function * f)775 static void func_cleanup(struct function *f)
776 {
777 struct storage *stor;
778 struct atom *atom;
779
780 FOR_EACH_PTR(f->atom_list, atom) {
781 if ((atom->type == ATOM_TEXT) && (atom->text))
782 free(atom->text);
783 if (atom->op1 && (atom->op1->flags & STOR_WANTS_FREE))
784 free(atom->op1);
785 if (atom->op2 && (atom->op2->flags & STOR_WANTS_FREE))
786 free(atom->op2);
787 free(atom);
788 } END_FOR_EACH_PTR(atom);
789
790 FOR_EACH_PTR(f->pseudo_list, stor) {
791 free(stor);
792 } END_FOR_EACH_PTR(stor);
793
794 free_ptr_list(&f->pseudo_list);
795 free(f);
796 }
797
798 /* function prologue */
emit_func_pre(struct symbol * sym)799 static void emit_func_pre(struct symbol *sym)
800 {
801 struct function *f;
802 struct symbol *arg;
803 unsigned int i, argc = 0, alloc_len;
804 unsigned char *mem;
805 struct symbol_private *privbase;
806 struct storage *storage_base;
807 struct symbol *base_type = sym->ctype.base_type;
808
809 FOR_EACH_PTR(base_type->arguments, arg) {
810 argc++;
811 } END_FOR_EACH_PTR(arg);
812
813 alloc_len =
814 sizeof(*f) +
815 (argc * sizeof(struct symbol *)) +
816 (argc * sizeof(struct symbol_private)) +
817 (argc * sizeof(struct storage));
818 mem = calloc(1, alloc_len);
819 if (!mem)
820 die("OOM on func info");
821
822 f = (struct function *) mem;
823 mem += sizeof(*f);
824 f->argv = (struct symbol **) mem;
825 mem += (argc * sizeof(struct symbol *));
826 privbase = (struct symbol_private *) mem;
827 mem += (argc * sizeof(struct symbol_private));
828 storage_base = (struct storage *) mem;
829
830 f->argc = argc;
831 f->ret_target = new_label();
832
833 i = 0;
834 FOR_EACH_PTR(base_type->arguments, arg) {
835 f->argv[i] = arg;
836 arg->aux = &privbase[i];
837 storage_base[i].type = STOR_ARG;
838 storage_base[i].idx = i;
839 privbase[i].addr = &storage_base[i];
840 i++;
841 } END_FOR_EACH_PTR(arg);
842
843 assert(current_func == NULL);
844 current_func = f;
845 }
846
847 /* function epilogue */
emit_func_post(struct symbol * sym)848 static void emit_func_post(struct symbol *sym)
849 {
850 const char *name = show_ident(sym->ident);
851 struct function *f = current_func;
852 int stack_size = f->stack_size;
853
854 if (f->str_list)
855 emit_string_list(f);
856
857 /* function prologue */
858 emit_section(".text");
859 if ((sym->ctype.modifiers & MOD_STATIC) == 0)
860 printf(".globl %s\n", name);
861 printf("\t.type\t%s, @function\n", name);
862 printf("%s:\n", name);
863
864 if (stack_size) {
865 char pseudo_const[16];
866
867 sprintf(pseudo_const, "$%d", stack_size);
868 printf("\tsubl\t%s, %%esp\n", pseudo_const);
869 }
870
871 /* function epilogue */
872
873 /* jump target for 'return' statements */
874 emit_label(f->ret_target, NULL);
875
876 if (stack_size) {
877 struct storage *val;
878
879 val = new_storage(STOR_VALUE);
880 val->value = (long long) (stack_size);
881 val->flags = STOR_WANTS_FREE;
882
883 insn("addl", val, REG_ESP, NULL);
884 }
885
886 insn("ret", NULL, NULL, NULL);
887
888 /* output everything to stdout */
889 fflush(stdout); /* paranoia; needed? */
890 emit_atom_list(f);
891
892 /* function footer */
893 name = show_ident(sym->ident);
894 printf("\t.size\t%s, .-%s\n", name, name);
895
896 func_cleanup(f);
897 current_func = NULL;
898 }
899
900 /* emit object (a.k.a. variable, a.k.a. data) prologue */
emit_object_pre(const char * name,unsigned long modifiers,unsigned long alignment,unsigned int byte_size)901 static void emit_object_pre(const char *name, unsigned long modifiers,
902 unsigned long alignment, unsigned int byte_size)
903 {
904 if ((modifiers & MOD_STATIC) == 0)
905 printf(".globl %s\n", name);
906 emit_section(".data");
907 if (alignment)
908 printf("\t.align %lu\n", alignment);
909 printf("\t.type\t%s, @object\n", name);
910 printf("\t.size\t%s, %d\n", name, byte_size);
911 printf("%s:\n", name);
912 }
913
914 /* emit value (only) for an initializer scalar */
emit_scalar(struct expression * expr,unsigned int bit_size)915 static void emit_scalar(struct expression *expr, unsigned int bit_size)
916 {
917 const char *type;
918 long long ll;
919
920 assert(expr->type == EXPR_VALUE);
921
922 if (expr->value == 0ULL) {
923 printf("\t.zero\t%d\n", bit_size / 8);
924 return;
925 }
926
927 ll = (long long) expr->value;
928
929 switch (bit_size) {
930 case 8: type = "byte"; ll = (char) ll; break;
931 case 16: type = "value"; ll = (short) ll; break;
932 case 32: type = "long"; ll = (int) ll; break;
933 case 64: type = "quad"; break;
934 default: type = NULL; break;
935 }
936
937 assert(type != NULL);
938
939 printf("\t.%s\t%lld\n", type, ll);
940 }
941
emit_global_noinit(const char * name,unsigned long modifiers,unsigned long alignment,unsigned int byte_size)942 static void emit_global_noinit(const char *name, unsigned long modifiers,
943 unsigned long alignment, unsigned int byte_size)
944 {
945 char s[64];
946
947 if (modifiers & MOD_STATIC) {
948 sprintf(s, "\t.local\t%s\n", name);
949 textbuf_push(&unit_post_text, s);
950 }
951 if (alignment)
952 sprintf(s, "\t.comm\t%s,%d,%lu\n", name, byte_size, alignment);
953 else
954 sprintf(s, "\t.comm\t%s,%d\n", name, byte_size);
955 textbuf_push(&unit_post_text, s);
956 }
957
958 static int ea_current, ea_last;
959
emit_initializer(struct symbol * sym,struct expression * expr)960 static void emit_initializer(struct symbol *sym,
961 struct expression *expr)
962 {
963 int distance = ea_current - ea_last - 1;
964
965 if (distance > 0)
966 printf("\t.zero\t%d\n", (sym->bit_size / 8) * distance);
967
968 if (expr->type == EXPR_VALUE) {
969 struct symbol *base_type = sym->ctype.base_type;
970 assert(base_type != NULL);
971
972 emit_scalar(expr, sym->bit_size / get_expression_value(base_type->array_size));
973 return;
974 }
975 if (expr->type != EXPR_INITIALIZER)
976 return;
977
978 assert(0); /* FIXME */
979 }
980
sort_array_cmp(const struct expression * a,const struct expression * b)981 static int sort_array_cmp(const struct expression *a,
982 const struct expression *b)
983 {
984 int a_ofs = 0, b_ofs = 0;
985
986 if (a->type == EXPR_POS)
987 a_ofs = (int) a->init_offset;
988 if (b->type == EXPR_POS)
989 b_ofs = (int) b->init_offset;
990
991 return a_ofs - b_ofs;
992 }
993
994 /* move to front-end? */
sort_array(struct expression * expr)995 static void sort_array(struct expression *expr)
996 {
997 struct expression *entry, **list;
998 unsigned int elem, sorted, i;
999
1000 elem = expression_list_size(expr->expr_list);
1001 if (!elem)
1002 return;
1003
1004 list = malloc(sizeof(entry) * elem);
1005 if (!list)
1006 die("OOM in sort_array");
1007
1008 /* this code is no doubt evil and ignores EXPR_INDEX possibly
1009 * to its detriment and other nasty things. improvements
1010 * welcome.
1011 */
1012 i = 0;
1013 sorted = 0;
1014 FOR_EACH_PTR(expr->expr_list, entry) {
1015 if ((entry->type == EXPR_POS) || (entry->type == EXPR_VALUE)) {
1016 /* add entry to list[], in sorted order */
1017 if (sorted == 0) {
1018 list[0] = entry;
1019 sorted = 1;
1020 } else {
1021 for (i = 0; i < sorted; i++)
1022 if (sort_array_cmp(entry, list[i]) <= 0)
1023 break;
1024
1025 /* If inserting into the middle of list[]
1026 * instead of appending, we memmove.
1027 * This is ugly, but thankfully
1028 * uncommon. Input data with tons of
1029 * entries very rarely have explicit
1030 * offsets. convert to qsort eventually...
1031 */
1032 if (i != sorted)
1033 memmove(&list[i + 1], &list[i],
1034 (sorted - i) * sizeof(entry));
1035 list[i] = entry;
1036 sorted++;
1037 }
1038 }
1039 } END_FOR_EACH_PTR(entry);
1040
1041 i = 0;
1042 FOR_EACH_PTR(expr->expr_list, entry) {
1043 if ((entry->type == EXPR_POS) || (entry->type == EXPR_VALUE))
1044 *THIS_ADDRESS(entry) = list[i++];
1045 } END_FOR_EACH_PTR(entry);
1046
1047 free(list);
1048 }
1049
emit_array(struct symbol * sym)1050 static void emit_array(struct symbol *sym)
1051 {
1052 struct symbol *base_type = sym->ctype.base_type;
1053 struct expression *expr = sym->initializer;
1054 struct expression *entry;
1055
1056 assert(base_type != NULL);
1057
1058 stor_sym_init(sym);
1059
1060 ea_last = -1;
1061
1062 emit_object_pre(show_ident(sym->ident), sym->ctype.modifiers,
1063 sym->ctype.alignment,
1064 sym->bit_size / 8);
1065
1066 sort_array(expr);
1067
1068 FOR_EACH_PTR(expr->expr_list, entry) {
1069 if (entry->type == EXPR_VALUE) {
1070 ea_current = 0;
1071 emit_initializer(sym, entry);
1072 ea_last = ea_current;
1073 } else if (entry->type == EXPR_POS) {
1074 ea_current =
1075 entry->init_offset / (base_type->bit_size / 8);
1076 emit_initializer(sym, entry->init_expr);
1077 ea_last = ea_current;
1078 }
1079 } END_FOR_EACH_PTR(entry);
1080 }
1081
emit_one_symbol(struct symbol * sym)1082 void emit_one_symbol(struct symbol *sym)
1083 {
1084 x86_symbol(sym);
1085 }
1086
emit_copy(struct storage * dest,struct storage * src,struct symbol * ctype)1087 static void emit_copy(struct storage *dest, struct storage *src,
1088 struct symbol *ctype)
1089 {
1090 struct storage *reg = NULL;
1091 unsigned int bit_size;
1092
1093 /* FIXME: Bitfield copy! */
1094
1095 bit_size = src->size * 8;
1096 if (!bit_size)
1097 bit_size = 32;
1098 if ((src->type == STOR_ARG) && (bit_size < 32))
1099 bit_size = 32;
1100
1101 reg = temp_from_bits(bit_size);
1102 emit_move(src, reg, ctype, "begin copy ..");
1103
1104 bit_size = dest->size * 8;
1105 if (!bit_size)
1106 bit_size = 32;
1107 if ((dest->type == STOR_ARG) && (bit_size < 32))
1108 bit_size = 32;
1109
1110 emit_move(reg, dest, ctype, ".... end copy");
1111 put_reg(reg);
1112 }
1113
emit_store(struct expression * dest_expr,struct storage * dest,struct storage * src,int bits)1114 static void emit_store(struct expression *dest_expr, struct storage *dest,
1115 struct storage *src, int bits)
1116 {
1117 /* FIXME: Bitfield store! */
1118 printf("\tst.%d\t\tv%d,[v%d]\n", bits, src->pseudo, dest->pseudo);
1119 }
1120
emit_scalar_noinit(struct symbol * sym)1121 static void emit_scalar_noinit(struct symbol *sym)
1122 {
1123 emit_global_noinit(show_ident(sym->ident),
1124 sym->ctype.modifiers, sym->ctype.alignment,
1125 sym->bit_size / 8);
1126 stor_sym_init(sym);
1127 }
1128
emit_array_noinit(struct symbol * sym)1129 static void emit_array_noinit(struct symbol *sym)
1130 {
1131 emit_global_noinit(show_ident(sym->ident),
1132 sym->ctype.modifiers, sym->ctype.alignment,
1133 get_expression_value(sym->array_size) * (sym->bit_size / 8));
1134 stor_sym_init(sym);
1135 }
1136
opbits(const char * insn,unsigned int bits)1137 static const char *opbits(const char *insn, unsigned int bits)
1138 {
1139 static char opbits_str[32];
1140 char c;
1141
1142 switch (bits) {
1143 case 8: c = 'b'; break;
1144 case 16: c = 'w'; break;
1145 case 32: c = 'l'; break;
1146 case 64: c = 'q'; break;
1147 default: abort(); break;
1148 }
1149
1150 sprintf(opbits_str, "%s%c", insn, c);
1151
1152 return opbits_str;
1153 }
1154
emit_move(struct storage * src,struct storage * dest,struct symbol * ctype,const char * comment)1155 static void emit_move(struct storage *src, struct storage *dest,
1156 struct symbol *ctype, const char *comment)
1157 {
1158 unsigned int bits;
1159 unsigned int is_signed;
1160 unsigned int is_dest = (src->type == STOR_REG);
1161 const char *opname;
1162
1163 if (ctype) {
1164 bits = ctype->bit_size;
1165 is_signed = is_signed_type(ctype);
1166 } else {
1167 bits = 32;
1168 is_signed = 0;
1169 }
1170
1171 /*
1172 * Are we moving from a register to a register?
1173 * Make the new reg to be the "cache".
1174 */
1175 if ((dest->type == STOR_REG) && (src->type == STOR_REG)) {
1176 struct storage *backing;
1177
1178 reg_reg_move:
1179 if (dest == src)
1180 return;
1181
1182 backing = src->reg->contains;
1183 if (backing) {
1184 /* Is it still valid? */
1185 if (backing->reg != src->reg)
1186 backing = NULL;
1187 else
1188 backing->reg = dest->reg;
1189 }
1190 dest->reg->contains = backing;
1191 insn("mov", src, dest, NULL);
1192 return;
1193 }
1194
1195 /*
1196 * Are we moving to a register from a non-reg?
1197 *
1198 * See if we have the non-reg source already cached
1199 * in a register..
1200 */
1201 if (dest->type == STOR_REG) {
1202 if (src->reg) {
1203 struct reg_info *info = src->reg;
1204 if (info->contains == src) {
1205 src = reginfo_reg(info);
1206 goto reg_reg_move;
1207 }
1208 }
1209 dest->reg->contains = src;
1210 src->reg = dest->reg;
1211 }
1212
1213 if (src->type == STOR_REG) {
1214 /* We could just mark the register dirty here and do lazy store.. */
1215 src->reg->contains = dest;
1216 dest->reg = src->reg;
1217 }
1218
1219 if ((bits == 8) || (bits == 16)) {
1220 if (is_dest)
1221 opname = "mov";
1222 else
1223 opname = is_signed ? "movsx" : "movzx";
1224 } else
1225 opname = "mov";
1226
1227 insn(opbits(opname, bits), src, dest, comment);
1228 }
1229
emit_compare(struct expression * expr)1230 static struct storage *emit_compare(struct expression *expr)
1231 {
1232 struct storage *left = x86_expression(expr->left);
1233 struct storage *right = x86_expression(expr->right);
1234 struct storage *reg1, *reg2;
1235 struct storage *new, *val;
1236 const char *opname = NULL;
1237 unsigned int right_bits = expr->right->ctype->bit_size;
1238
1239 switch(expr->op) {
1240 case '<': opname = "setl"; break;
1241 case '>': opname = "setg"; break;
1242 case SPECIAL_LTE:
1243 opname = "setle"; break;
1244 case SPECIAL_GTE:
1245 opname = "setge"; break;
1246 case SPECIAL_EQUAL: opname = "sete"; break;
1247 case SPECIAL_NOTEQUAL: opname = "setne"; break;
1248 case SPECIAL_UNSIGNED_LT:
1249 opname = "setb"; break;
1250 case SPECIAL_UNSIGNED_GT:
1251 opname = "seta"; break;
1252 case SPECIAL_UNSIGNED_LTE:
1253 opname = "setb"; break;
1254 case SPECIAL_UNSIGNED_GTE:
1255 opname = "setae"; break;
1256 default:
1257 assert(0);
1258 break;
1259 }
1260
1261 /* init EDX to 0 */
1262 val = new_storage(STOR_VALUE);
1263 val->flags = STOR_WANTS_FREE;
1264
1265 reg1 = get_reg(®class_32_8);
1266 emit_move(val, reg1, NULL, NULL);
1267
1268 /* move op1 into EAX */
1269 reg2 = get_reg_value(left, get_regclass(expr->left));
1270
1271 /* perform comparison, RHS (op1, right) and LHS (op2, EAX) */
1272 insn(opbits("cmp", right_bits), right, reg2, NULL);
1273 put_reg(reg2);
1274
1275 /* store result of operation, 0 or 1, in DL using SETcc */
1276 insn(opname, byte_reg(reg1), NULL, NULL);
1277
1278 /* finally, store the result (DL) in a new pseudo / stack slot */
1279 new = stack_alloc(4);
1280 emit_move(reg1, new, NULL, "end EXPR_COMPARE");
1281 put_reg(reg1);
1282
1283 return new;
1284 }
1285
emit_value(struct expression * expr)1286 static struct storage *emit_value(struct expression *expr)
1287 {
1288 #if 0 /* old and slow way */
1289 struct storage *new = stack_alloc(4);
1290 struct storage *val;
1291
1292 val = new_storage(STOR_VALUE);
1293 val->value = (long long) expr->value;
1294 val->flags = STOR_WANTS_FREE;
1295 insn("movl", val, new, NULL);
1296
1297 return new;
1298 #else
1299 struct storage *val;
1300
1301 val = new_storage(STOR_VALUE);
1302 val->value = (long long) expr->value;
1303
1304 return val; /* FIXME: memory leak */
1305 #endif
1306 }
1307
emit_divide(struct expression * expr,struct storage * left,struct storage * right)1308 static struct storage *emit_divide(struct expression *expr, struct storage *left, struct storage *right)
1309 {
1310 struct storage *eax_edx;
1311 struct storage *reg, *new;
1312 struct storage *val = new_storage(STOR_VALUE);
1313
1314 emit_comment("begin DIVIDE");
1315 eax_edx = get_hardreg(hardreg_storage_table + EAX_EDX, 1);
1316
1317 /* init EDX to 0 */
1318 val->flags = STOR_WANTS_FREE;
1319 emit_move(val, REG_EDX, NULL, NULL);
1320
1321 new = stack_alloc(expr->ctype->bit_size / 8);
1322
1323 /* EAX is dividend */
1324 emit_move(left, REG_EAX, NULL, NULL);
1325
1326 reg = get_reg_value(right, ®class_32);
1327
1328 /* perform binop */
1329 insn("div", reg, REG_EAX, NULL);
1330 put_reg(reg);
1331
1332 reg = REG_EAX;
1333 if (expr->op == '%')
1334 reg = REG_EDX;
1335 emit_move(reg, new, NULL, NULL);
1336
1337 put_reg(eax_edx);
1338 emit_comment("end DIVIDE");
1339 return new;
1340 }
1341
emit_binop(struct expression * expr)1342 static struct storage *emit_binop(struct expression *expr)
1343 {
1344 struct storage *left = x86_expression(expr->left);
1345 struct storage *right = x86_expression(expr->right);
1346 struct storage *new;
1347 struct storage *dest, *src;
1348 const char *opname = NULL;
1349 const char *suffix = NULL;
1350 char opstr[16];
1351 int is_signed;
1352
1353 /* Divides have special register constraints */
1354 if ((expr->op == '/') || (expr->op == '%'))
1355 return emit_divide(expr, left, right);
1356
1357 is_signed = is_signed_type(expr->ctype);
1358
1359 switch (expr->op) {
1360 case '+':
1361 opname = "add";
1362 break;
1363 case '-':
1364 opname = "sub";
1365 break;
1366 case '&':
1367 opname = "and";
1368 break;
1369 case '|':
1370 opname = "or";
1371 break;
1372 case '^':
1373 opname = "xor";
1374 break;
1375 case SPECIAL_LEFTSHIFT:
1376 opname = "shl";
1377 break;
1378 case SPECIAL_RIGHTSHIFT:
1379 if (is_signed)
1380 opname = "sar";
1381 else
1382 opname = "shr";
1383 break;
1384 case '*':
1385 if (is_signed)
1386 opname = "imul";
1387 else
1388 opname = "mul";
1389 break;
1390 case SPECIAL_LOGICAL_AND:
1391 warning(expr->pos, "bogus bitwise and for logical op (should use '2*setne + and' or something)");
1392 opname = "and";
1393 break;
1394 case SPECIAL_LOGICAL_OR:
1395 warning(expr->pos, "bogus bitwise or for logical op (should use 'or + setne' or something)");
1396 opname = "or";
1397 break;
1398 default:
1399 error_die(expr->pos, "unhandled binop '%s'\n", show_special(expr->op));
1400 break;
1401 }
1402
1403 dest = get_reg_value(right, ®class_32);
1404 src = get_reg_value(left, ®class_32);
1405 switch (expr->ctype->bit_size) {
1406 case 8:
1407 suffix = "b";
1408 break;
1409 case 16:
1410 suffix = "w";
1411 break;
1412 case 32:
1413 suffix = "l";
1414 break;
1415 case 64:
1416 suffix = "q"; /* FIXME */
1417 break;
1418 default:
1419 assert(0);
1420 break;
1421 }
1422
1423 snprintf(opstr, sizeof(opstr), "%s%s", opname, suffix);
1424
1425 /* perform binop */
1426 insn(opstr, src, dest, NULL);
1427 put_reg(src);
1428
1429 /* store result in new pseudo / stack slot */
1430 new = stack_alloc(expr->ctype->bit_size / 8);
1431 emit_move(dest, new, NULL, "end EXPR_BINOP");
1432
1433 put_reg(dest);
1434
1435 return new;
1436 }
1437
emit_conditional_test(struct storage * val)1438 static int emit_conditional_test(struct storage *val)
1439 {
1440 struct storage *reg;
1441 struct storage *target_val;
1442 int target_false;
1443
1444 /* load result into EAX */
1445 emit_comment("begin if/conditional");
1446 reg = get_reg_value(val, ®class_32);
1447
1448 /* compare result with zero */
1449 insn("test", reg, reg, NULL);
1450 put_reg(reg);
1451
1452 /* create conditional-failed label to jump to */
1453 target_false = new_label();
1454 target_val = new_storage(STOR_LABEL);
1455 target_val->label = target_false;
1456 target_val->flags = STOR_WANTS_FREE;
1457 insn("jz", target_val, NULL, NULL);
1458
1459 return target_false;
1460 }
1461
emit_conditional_end(int target_false)1462 static int emit_conditional_end(int target_false)
1463 {
1464 struct storage *cond_end_st;
1465 int cond_end;
1466
1467 /* finished generating code for if-true statement.
1468 * add a jump-to-end jump to avoid falling through
1469 * to the if-false statement code.
1470 */
1471 cond_end = new_label();
1472 cond_end_st = new_storage(STOR_LABEL);
1473 cond_end_st->label = cond_end;
1474 cond_end_st->flags = STOR_WANTS_FREE;
1475 insn("jmp", cond_end_st, NULL, NULL);
1476
1477 /* if we have both if-true and if-false statements,
1478 * the failed-conditional case will fall through to here
1479 */
1480 emit_label(target_false, NULL);
1481
1482 return cond_end;
1483 }
1484
emit_if_conditional(struct statement * stmt)1485 static void emit_if_conditional(struct statement *stmt)
1486 {
1487 struct storage *val;
1488 int cond_end;
1489
1490 /* emit test portion of conditional */
1491 val = x86_expression(stmt->if_conditional);
1492 cond_end = emit_conditional_test(val);
1493
1494 /* emit if-true statement */
1495 x86_statement(stmt->if_true);
1496
1497 /* emit if-false statement, if present */
1498 if (stmt->if_false) {
1499 cond_end = emit_conditional_end(cond_end);
1500 x86_statement(stmt->if_false);
1501 }
1502
1503 /* end of conditional; jump target for if-true branch */
1504 emit_label(cond_end, "end if");
1505 }
1506
emit_inc_dec(struct expression * expr,int postop)1507 static struct storage *emit_inc_dec(struct expression *expr, int postop)
1508 {
1509 struct storage *addr = x86_address_gen(expr->unop);
1510 struct storage *retval;
1511 char opname[16];
1512
1513 strcpy(opname, opbits(expr->op == SPECIAL_INCREMENT ? "inc" : "dec",
1514 expr->ctype->bit_size));
1515
1516 if (postop) {
1517 struct storage *new = stack_alloc(4);
1518
1519 emit_copy(new, addr, expr->unop->ctype);
1520
1521 retval = new;
1522 } else
1523 retval = addr;
1524
1525 insn(opname, addr, NULL, NULL);
1526
1527 return retval;
1528 }
1529
emit_postop(struct expression * expr)1530 static struct storage *emit_postop(struct expression *expr)
1531 {
1532 return emit_inc_dec(expr, 1);
1533 }
1534
emit_return_stmt(struct statement * stmt)1535 static struct storage *emit_return_stmt(struct statement *stmt)
1536 {
1537 struct function *f = current_func;
1538 struct expression *expr = stmt->ret_value;
1539 struct storage *val = NULL, *jmplbl;
1540
1541 if (expr && expr->ctype) {
1542 val = x86_expression(expr);
1543 assert(val != NULL);
1544 emit_move(val, REG_EAX, expr->ctype, "return");
1545 }
1546
1547 jmplbl = new_storage(STOR_LABEL);
1548 jmplbl->flags |= STOR_WANTS_FREE;
1549 jmplbl->label = f->ret_target;
1550 insn("jmp", jmplbl, NULL, NULL);
1551
1552 return val;
1553 }
1554
emit_conditional_expr(struct expression * expr)1555 static struct storage *emit_conditional_expr(struct expression *expr)
1556 {
1557 struct storage *cond, *stot = NULL, *stof = NULL;
1558 struct storage *new = stack_alloc(expr->ctype->bit_size / 8);
1559 int target_false, cond_end;
1560
1561 /* evaluate conditional */
1562 cond = x86_expression(expr->conditional);
1563 target_false = emit_conditional_test(cond);
1564
1565 /* handle if-true part of the expression */
1566 stot = x86_expression(expr->cond_true);
1567
1568 emit_copy(new, stot, expr->ctype);
1569
1570 cond_end = emit_conditional_end(target_false);
1571
1572 /* handle if-false part of the expression */
1573 stof = x86_expression(expr->cond_false);
1574
1575 emit_copy(new, stof, expr->ctype);
1576
1577 /* end of conditional; jump target for if-true branch */
1578 emit_label(cond_end, "end conditional");
1579
1580 return new;
1581 }
1582
emit_select_expr(struct expression * expr)1583 static struct storage *emit_select_expr(struct expression *expr)
1584 {
1585 struct storage *cond = x86_expression(expr->conditional);
1586 struct storage *stot = x86_expression(expr->cond_true);
1587 struct storage *stof = x86_expression(expr->cond_false);
1588 struct storage *reg_cond, *reg_true, *reg_false;
1589 struct storage *new = stack_alloc(4);
1590
1591 emit_comment("begin SELECT");
1592 reg_cond = get_reg_value(cond, get_regclass(expr->conditional));
1593 reg_true = get_reg_value(stot, get_regclass(expr));
1594 reg_false = get_reg_value(stof, get_regclass(expr));
1595
1596 /*
1597 * Do the actual select: check the conditional for zero,
1598 * move false over true if zero
1599 */
1600 insn("test", reg_cond, reg_cond, NULL);
1601 insn("cmovz", reg_false, reg_true, NULL);
1602
1603 /* Store it back */
1604 emit_move(reg_true, new, expr->ctype, NULL);
1605 put_reg(reg_cond);
1606 put_reg(reg_true);
1607 put_reg(reg_false);
1608 emit_comment("end SELECT");
1609 return new;
1610 }
1611
emit_symbol_expr_init(struct symbol * sym)1612 static struct storage *emit_symbol_expr_init(struct symbol *sym)
1613 {
1614 struct expression *expr = sym->initializer;
1615 struct symbol_private *priv = sym->aux;
1616
1617 if (priv == NULL) {
1618 priv = calloc(1, sizeof(*priv));
1619 sym->aux = priv;
1620
1621 if (expr == NULL) {
1622 struct storage *new = stack_alloc(4);
1623 fprintf(stderr, "FIXME! no value for symbol %s. creating pseudo %d (stack offset %d)\n",
1624 show_ident(sym->ident),
1625 new->pseudo, new->pseudo * 4);
1626 priv->addr = new;
1627 } else {
1628 priv->addr = x86_expression(expr);
1629 }
1630 }
1631
1632 return priv->addr;
1633 }
1634
emit_string_expr(struct expression * expr)1635 static struct storage *emit_string_expr(struct expression *expr)
1636 {
1637 struct function *f = current_func;
1638 int label = new_label();
1639 struct storage *new;
1640
1641 push_cstring(f, expr->string, label);
1642
1643 new = new_storage(STOR_LABEL);
1644 new->label = label;
1645 new->flags = STOR_LABEL_VAL | STOR_WANTS_FREE;
1646 return new;
1647 }
1648
emit_cast_expr(struct expression * expr)1649 static struct storage *emit_cast_expr(struct expression *expr)
1650 {
1651 struct symbol *old_type, *new_type;
1652 struct storage *op = x86_expression(expr->cast_expression);
1653 int oldbits, newbits;
1654 struct storage *new;
1655
1656 old_type = expr->cast_expression->ctype;
1657 new_type = expr->cast_type;
1658
1659 oldbits = old_type->bit_size;
1660 newbits = new_type->bit_size;
1661 if (oldbits >= newbits)
1662 return op;
1663
1664 emit_move(op, REG_EAX, old_type, "begin cast ..");
1665
1666 new = stack_alloc(newbits / 8);
1667 emit_move(REG_EAX, new, new_type, ".... end cast");
1668
1669 return new;
1670 }
1671
emit_regular_preop(struct expression * expr)1672 static struct storage *emit_regular_preop(struct expression *expr)
1673 {
1674 struct storage *target = x86_expression(expr->unop);
1675 struct storage *val, *new = stack_alloc(4);
1676 const char *opname = NULL;
1677
1678 switch (expr->op) {
1679 case '!':
1680 val = new_storage(STOR_VALUE);
1681 val->flags = STOR_WANTS_FREE;
1682 emit_move(val, REG_EDX, NULL, NULL);
1683 emit_move(target, REG_EAX, expr->unop->ctype, NULL);
1684 insn("test", REG_EAX, REG_EAX, NULL);
1685 insn("setz", REG_DL, NULL, NULL);
1686 emit_move(REG_EDX, new, expr->unop->ctype, NULL);
1687
1688 break;
1689 case '~':
1690 opname = "not";
1691 case '-':
1692 if (!opname)
1693 opname = "neg";
1694 emit_move(target, REG_EAX, expr->unop->ctype, NULL);
1695 insn(opname, REG_EAX, NULL, NULL);
1696 emit_move(REG_EAX, new, expr->unop->ctype, NULL);
1697 break;
1698 default:
1699 assert(0);
1700 break;
1701 }
1702
1703 return new;
1704 }
1705
emit_case_statement(struct statement * stmt)1706 static void emit_case_statement(struct statement *stmt)
1707 {
1708 emit_labelsym(stmt->case_label, NULL);
1709 x86_statement(stmt->case_statement);
1710 }
1711
emit_switch_statement(struct statement * stmt)1712 static void emit_switch_statement(struct statement *stmt)
1713 {
1714 struct storage *val = x86_expression(stmt->switch_expression);
1715 struct symbol *sym, *default_sym = NULL;
1716 struct storage *labelsym, *label;
1717 int switch_end = 0;
1718
1719 emit_move(val, REG_EAX, stmt->switch_expression->ctype, "begin case");
1720
1721 /*
1722 * This is where a _real_ back-end would go through the
1723 * cases to decide whether to use a lookup table or a
1724 * series of comparisons etc
1725 */
1726 FOR_EACH_PTR(stmt->switch_case->symbol_list, sym) {
1727 struct statement *case_stmt = sym->stmt;
1728 struct expression *expr = case_stmt->case_expression;
1729 struct expression *to = case_stmt->case_to;
1730
1731 /* default: */
1732 if (!expr)
1733 default_sym = sym;
1734
1735 /* case NNN: */
1736 else {
1737 struct storage *case_val = new_val(expr->value);
1738
1739 assert (expr->type == EXPR_VALUE);
1740
1741 insn("cmpl", case_val, REG_EAX, NULL);
1742
1743 if (!to) {
1744 labelsym = new_labelsym(sym);
1745 insn("je", labelsym, NULL, NULL);
1746 } else {
1747 int next_test;
1748
1749 label = new_storage(STOR_LABEL);
1750 label->flags |= STOR_WANTS_FREE;
1751 label->label = next_test = new_label();
1752
1753 /* FIXME: signed/unsigned */
1754 insn("jl", label, NULL, NULL);
1755
1756 case_val = new_val(to->value);
1757 insn("cmpl", case_val, REG_EAX, NULL);
1758
1759 /* TODO: implement and use refcounting... */
1760 label = new_storage(STOR_LABEL);
1761 label->flags |= STOR_WANTS_FREE;
1762 label->label = next_test;
1763
1764 /* FIXME: signed/unsigned */
1765 insn("jg", label, NULL, NULL);
1766
1767 labelsym = new_labelsym(sym);
1768 insn("jmp", labelsym, NULL, NULL);
1769
1770 emit_label(next_test, NULL);
1771 }
1772 }
1773 } END_FOR_EACH_PTR(sym);
1774
1775 if (default_sym) {
1776 labelsym = new_labelsym(default_sym);
1777 insn("jmp", labelsym, NULL, "default");
1778 } else {
1779 label = new_storage(STOR_LABEL);
1780 label->flags |= STOR_WANTS_FREE;
1781 label->label = switch_end = new_label();
1782 insn("jmp", label, NULL, "goto end of switch");
1783 }
1784
1785 x86_statement(stmt->switch_statement);
1786
1787 if (stmt->switch_break->used)
1788 emit_labelsym(stmt->switch_break, NULL);
1789
1790 if (switch_end)
1791 emit_label(switch_end, NULL);
1792 }
1793
x86_struct_member(struct symbol * sym)1794 static void x86_struct_member(struct symbol *sym)
1795 {
1796 printf("\t%s:%d:%ld at offset %ld.%d", show_ident(sym->ident), sym->bit_size, sym->ctype.alignment, sym->offset, sym->bit_offset);
1797 printf("\n");
1798 }
1799
x86_symbol(struct symbol * sym)1800 static void x86_symbol(struct symbol *sym)
1801 {
1802 struct symbol *type;
1803
1804 if (!sym)
1805 return;
1806
1807 type = sym->ctype.base_type;
1808 if (!type)
1809 return;
1810
1811 /*
1812 * Show actual implementation information
1813 */
1814 switch (type->type) {
1815
1816 case SYM_ARRAY:
1817 if (sym->initializer)
1818 emit_array(sym);
1819 else
1820 emit_array_noinit(sym);
1821 break;
1822
1823 case SYM_BASETYPE:
1824 if (sym->initializer) {
1825 emit_object_pre(show_ident(sym->ident),
1826 sym->ctype.modifiers,
1827 sym->ctype.alignment,
1828 sym->bit_size / 8);
1829 emit_scalar(sym->initializer, sym->bit_size);
1830 stor_sym_init(sym);
1831 } else
1832 emit_scalar_noinit(sym);
1833 break;
1834
1835 case SYM_STRUCT:
1836 case SYM_UNION: {
1837 struct symbol *member;
1838
1839 printf(" {\n");
1840 FOR_EACH_PTR(type->symbol_list, member) {
1841 x86_struct_member(member);
1842 } END_FOR_EACH_PTR(member);
1843 printf("}\n");
1844 break;
1845 }
1846
1847 case SYM_FN: {
1848 struct statement *stmt = type->stmt;
1849 if (stmt) {
1850 emit_func_pre(sym);
1851 x86_statement(stmt);
1852 emit_func_post(sym);
1853 }
1854 break;
1855 }
1856
1857 default:
1858 break;
1859 }
1860
1861 if (sym->initializer && (type->type != SYM_BASETYPE) &&
1862 (type->type != SYM_ARRAY)) {
1863 printf(" = \n");
1864 x86_expression(sym->initializer);
1865 }
1866 }
1867
1868 static void x86_symbol_init(struct symbol *sym);
1869
x86_symbol_decl(struct symbol_list * syms)1870 static void x86_symbol_decl(struct symbol_list *syms)
1871 {
1872 struct symbol *sym;
1873 FOR_EACH_PTR(syms, sym) {
1874 x86_symbol_init(sym);
1875 } END_FOR_EACH_PTR(sym);
1876 }
1877
loopstk_push(int cont_lbl,int loop_bottom_lbl)1878 static void loopstk_push(int cont_lbl, int loop_bottom_lbl)
1879 {
1880 struct function *f = current_func;
1881 struct loop_stack *ls;
1882
1883 ls = malloc(sizeof(*ls));
1884 ls->continue_lbl = cont_lbl;
1885 ls->loop_bottom_lbl = loop_bottom_lbl;
1886 ls->next = f->loop_stack;
1887 f->loop_stack = ls;
1888 }
1889
loopstk_pop(void)1890 static void loopstk_pop(void)
1891 {
1892 struct function *f = current_func;
1893 struct loop_stack *ls;
1894
1895 assert(f->loop_stack != NULL);
1896 ls = f->loop_stack;
1897 f->loop_stack = f->loop_stack->next;
1898 free(ls);
1899 }
1900
loopstk_break(void)1901 static int loopstk_break(void)
1902 {
1903 return current_func->loop_stack->loop_bottom_lbl;
1904 }
1905
loopstk_continue(void)1906 static int loopstk_continue(void)
1907 {
1908 return current_func->loop_stack->continue_lbl;
1909 }
1910
emit_loop(struct statement * stmt)1911 static void emit_loop(struct statement *stmt)
1912 {
1913 struct statement *pre_statement = stmt->iterator_pre_statement;
1914 struct expression *pre_condition = stmt->iterator_pre_condition;
1915 struct statement *statement = stmt->iterator_statement;
1916 struct statement *post_statement = stmt->iterator_post_statement;
1917 struct expression *post_condition = stmt->iterator_post_condition;
1918 int loop_top = 0, loop_bottom, loop_continue;
1919 int have_bottom = 0;
1920 struct storage *val;
1921
1922 loop_bottom = new_label();
1923 loop_continue = new_label();
1924 loopstk_push(loop_continue, loop_bottom);
1925
1926 x86_symbol_decl(stmt->iterator_syms);
1927 x86_statement(pre_statement);
1928 if (!post_condition || post_condition->type != EXPR_VALUE || post_condition->value) {
1929 loop_top = new_label();
1930 emit_label(loop_top, "loop top");
1931 }
1932 if (pre_condition) {
1933 if (pre_condition->type == EXPR_VALUE) {
1934 if (!pre_condition->value) {
1935 struct storage *lbv;
1936 lbv = new_storage(STOR_LABEL);
1937 lbv->label = loop_bottom;
1938 lbv->flags = STOR_WANTS_FREE;
1939 insn("jmp", lbv, NULL, "go to loop bottom");
1940 have_bottom = 1;
1941 }
1942 } else {
1943 struct storage *lbv = new_storage(STOR_LABEL);
1944 lbv->label = loop_bottom;
1945 lbv->flags = STOR_WANTS_FREE;
1946 have_bottom = 1;
1947
1948 val = x86_expression(pre_condition);
1949
1950 emit_move(val, REG_EAX, NULL, "loop pre condition");
1951 insn("test", REG_EAX, REG_EAX, NULL);
1952 insn("jz", lbv, NULL, NULL);
1953 }
1954 }
1955 x86_statement(statement);
1956 if (stmt->iterator_continue->used)
1957 emit_label(loop_continue, "'continue' iterator");
1958 x86_statement(post_statement);
1959 if (!post_condition) {
1960 struct storage *lbv = new_storage(STOR_LABEL);
1961 lbv->label = loop_top;
1962 lbv->flags = STOR_WANTS_FREE;
1963 insn("jmp", lbv, NULL, "go to loop top");
1964 } else if (post_condition->type == EXPR_VALUE) {
1965 if (post_condition->value) {
1966 struct storage *lbv = new_storage(STOR_LABEL);
1967 lbv->label = loop_top;
1968 lbv->flags = STOR_WANTS_FREE;
1969 insn("jmp", lbv, NULL, "go to loop top");
1970 }
1971 } else {
1972 struct storage *lbv = new_storage(STOR_LABEL);
1973 lbv->label = loop_top;
1974 lbv->flags = STOR_WANTS_FREE;
1975
1976 val = x86_expression(post_condition);
1977
1978 emit_move(val, REG_EAX, NULL, "loop post condition");
1979 insn("test", REG_EAX, REG_EAX, NULL);
1980 insn("jnz", lbv, NULL, NULL);
1981 }
1982 if (have_bottom || stmt->iterator_break->used)
1983 emit_label(loop_bottom, "loop bottom");
1984
1985 loopstk_pop();
1986 }
1987
1988 /*
1989 * Print out a statement
1990 */
x86_statement(struct statement * stmt)1991 static struct storage *x86_statement(struct statement *stmt)
1992 {
1993 if (!stmt)
1994 return NULL;
1995 switch (stmt->type) {
1996 default:
1997 return NULL;
1998 case STMT_RETURN:
1999 return emit_return_stmt(stmt);
2000 case STMT_DECLARATION:
2001 x86_symbol_decl(stmt->declaration);
2002 break;
2003 case STMT_COMPOUND: {
2004 struct statement *s;
2005 struct storage *last = NULL;
2006
2007 FOR_EACH_PTR(stmt->stmts, s) {
2008 last = x86_statement(s);
2009 } END_FOR_EACH_PTR(s);
2010
2011 return last;
2012 }
2013
2014 case STMT_EXPRESSION:
2015 return x86_expression(stmt->expression);
2016 case STMT_IF:
2017 emit_if_conditional(stmt);
2018 return NULL;
2019
2020 case STMT_CASE:
2021 emit_case_statement(stmt);
2022 break;
2023 case STMT_SWITCH:
2024 emit_switch_statement(stmt);
2025 break;
2026
2027 case STMT_ITERATOR:
2028 emit_loop(stmt);
2029 break;
2030
2031 case STMT_NONE:
2032 break;
2033
2034 case STMT_LABEL:
2035 printf(".L%p:\n", stmt->label_identifier);
2036 x86_statement(stmt->label_statement);
2037 break;
2038
2039 case STMT_GOTO:
2040 if (stmt->goto_expression) {
2041 struct storage *val = x86_expression(stmt->goto_expression);
2042 printf("\tgoto *v%d\n", val->pseudo);
2043 } else if (!strcmp("break", show_ident(stmt->goto_label->ident))) {
2044 struct storage *lbv = new_storage(STOR_LABEL);
2045 lbv->label = loopstk_break();
2046 lbv->flags = STOR_WANTS_FREE;
2047 insn("jmp", lbv, NULL, "'break'; go to loop bottom");
2048 } else if (!strcmp("continue", show_ident(stmt->goto_label->ident))) {
2049 struct storage *lbv = new_storage(STOR_LABEL);
2050 lbv->label = loopstk_continue();
2051 lbv->flags = STOR_WANTS_FREE;
2052 insn("jmp", lbv, NULL, "'continue'; go to loop top");
2053 } else {
2054 struct storage *labelsym = new_labelsym(stmt->goto_label);
2055 insn("jmp", labelsym, NULL, NULL);
2056 }
2057 break;
2058 case STMT_ASM:
2059 printf("\tasm( .... )\n");
2060 break;
2061 }
2062 return NULL;
2063 }
2064
x86_call_expression(struct expression * expr)2065 static struct storage *x86_call_expression(struct expression *expr)
2066 {
2067 struct function *f = current_func;
2068 struct symbol *direct;
2069 struct expression *arg, *fn;
2070 struct storage *retval, *fncall;
2071 int framesize;
2072 char s[64];
2073
2074 if (!expr->ctype) {
2075 warning(expr->pos, "\tcall with no type!");
2076 return NULL;
2077 }
2078
2079 framesize = 0;
2080 FOR_EACH_PTR_REVERSE(expr->args, arg) {
2081 struct storage *new = x86_expression(arg);
2082 int size = arg->ctype->bit_size;
2083
2084 /*
2085 * FIXME: i386 SysV ABI dictates that values
2086 * smaller than 32 bits should be placed onto
2087 * the stack as 32-bit objects. We should not
2088 * blindly do a 32-bit push on objects smaller
2089 * than 32 bits.
2090 */
2091 if (size < 32)
2092 size = 32;
2093 insn("pushl", new, NULL,
2094 !framesize ? "begin function call" : NULL);
2095
2096 framesize += bits_to_bytes(size);
2097 } END_FOR_EACH_PTR_REVERSE(arg);
2098
2099 fn = expr->fn;
2100
2101 /* Remove dereference, if any */
2102 direct = NULL;
2103 if (fn->type == EXPR_PREOP) {
2104 if (fn->unop->type == EXPR_SYMBOL) {
2105 struct symbol *sym = fn->unop->symbol;
2106 if (sym->ctype.base_type->type == SYM_FN)
2107 direct = sym;
2108 }
2109 }
2110 if (direct) {
2111 struct storage *direct_stor = new_storage(STOR_SYM);
2112 direct_stor->flags |= STOR_WANTS_FREE;
2113 direct_stor->sym = direct;
2114 insn("call", direct_stor, NULL, NULL);
2115 } else {
2116 fncall = x86_expression(fn);
2117 emit_move(fncall, REG_EAX, fn->ctype, NULL);
2118
2119 strcpy(s, "\tcall\t*%eax\n");
2120 push_text_atom(f, s);
2121 }
2122
2123 /* FIXME: pay attention to BITS_IN_POINTER */
2124 if (framesize) {
2125 struct storage *val = new_storage(STOR_VALUE);
2126 val->value = (long long) framesize;
2127 val->flags = STOR_WANTS_FREE;
2128 insn("addl", val, REG_ESP, NULL);
2129 }
2130
2131 retval = stack_alloc(4);
2132 emit_move(REG_EAX, retval, NULL, "end function call");
2133
2134 return retval;
2135 }
2136
x86_address_gen(struct expression * expr)2137 static struct storage *x86_address_gen(struct expression *expr)
2138 {
2139 struct function *f = current_func;
2140 struct storage *addr;
2141 struct storage *new;
2142 char s[32];
2143
2144 addr = x86_expression(expr->unop);
2145 if (expr->unop->type == EXPR_SYMBOL)
2146 return addr;
2147
2148 emit_move(addr, REG_EAX, NULL, "begin deref ..");
2149
2150 /* FIXME: operand size */
2151 strcpy(s, "\tmovl\t(%eax), %ecx\n");
2152 push_text_atom(f, s);
2153
2154 new = stack_alloc(4);
2155 emit_move(REG_ECX, new, NULL, ".... end deref");
2156
2157 return new;
2158 }
2159
x86_assignment(struct expression * expr)2160 static struct storage *x86_assignment(struct expression *expr)
2161 {
2162 struct expression *target = expr->left;
2163 struct storage *val, *addr;
2164
2165 if (!expr->ctype)
2166 return NULL;
2167
2168 val = x86_expression(expr->right);
2169 addr = x86_address_gen(target);
2170
2171 switch (val->type) {
2172 /* copy, where both operands are memory */
2173 case STOR_PSEUDO:
2174 case STOR_ARG:
2175 emit_copy(addr, val, expr->ctype);
2176 break;
2177
2178 /* copy, one or zero operands are memory */
2179 case STOR_REG:
2180 case STOR_SYM:
2181 case STOR_VALUE:
2182 case STOR_LABEL:
2183 emit_move(val, addr, expr->left->ctype, NULL);
2184 break;
2185
2186 case STOR_LABELSYM:
2187 assert(0);
2188 break;
2189 }
2190 return val;
2191 }
2192
x86_initialization(struct symbol * sym,struct expression * expr)2193 static int x86_initialization(struct symbol *sym, struct expression *expr)
2194 {
2195 struct storage *val, *addr;
2196 int bits;
2197
2198 if (!expr->ctype)
2199 return 0;
2200
2201 bits = expr->ctype->bit_size;
2202 val = x86_expression(expr);
2203 addr = x86_symbol_expr(sym);
2204 // FIXME! The "target" expression is for bitfield store information.
2205 // Leave it NULL, which works fine.
2206 emit_store(NULL, addr, val, bits);
2207 return 0;
2208 }
2209
x86_access(struct expression * expr)2210 static struct storage *x86_access(struct expression *expr)
2211 {
2212 return x86_address_gen(expr);
2213 }
2214
x86_preop(struct expression * expr)2215 static struct storage *x86_preop(struct expression *expr)
2216 {
2217 /*
2218 * '*' is an lvalue access, and is fundamentally different
2219 * from an arithmetic operation. Maybe it should have an
2220 * expression type of its own..
2221 */
2222 if (expr->op == '*')
2223 return x86_access(expr);
2224 if (expr->op == SPECIAL_INCREMENT || expr->op == SPECIAL_DECREMENT)
2225 return emit_inc_dec(expr, 0);
2226 return emit_regular_preop(expr);
2227 }
2228
x86_symbol_expr(struct symbol * sym)2229 static struct storage *x86_symbol_expr(struct symbol *sym)
2230 {
2231 struct storage *new = stack_alloc(4);
2232
2233 if (sym->ctype.modifiers & (MOD_TOPLEVEL | MOD_EXTERN | MOD_STATIC)) {
2234 printf("\tmovi.%d\t\tv%d,$%s\n", bits_in_pointer, new->pseudo, show_ident(sym->ident));
2235 return new;
2236 }
2237 if (sym->ctype.modifiers & MOD_ADDRESSABLE) {
2238 printf("\taddi.%d\t\tv%d,vFP,$%lld\n", bits_in_pointer, new->pseudo, 0LL);
2239 return new;
2240 }
2241 printf("\taddi.%d\t\tv%d,vFP,$offsetof(%s:%p)\n", bits_in_pointer, new->pseudo, show_ident(sym->ident), sym);
2242 return new;
2243 }
2244
x86_symbol_init(struct symbol * sym)2245 static void x86_symbol_init(struct symbol *sym)
2246 {
2247 struct symbol_private *priv = sym->aux;
2248 struct expression *expr = sym->initializer;
2249 struct storage *new;
2250
2251 if (expr)
2252 new = x86_expression(expr);
2253 else
2254 new = stack_alloc(sym->bit_size / 8);
2255
2256 if (!priv) {
2257 priv = calloc(1, sizeof(*priv));
2258 sym->aux = priv;
2259 /* FIXME: leak! we don't free... */
2260 /* (well, we don't free symbols either) */
2261 }
2262
2263 priv->addr = new;
2264 }
2265
x86_label_expr(struct expression * expr)2266 static struct storage *x86_label_expr(struct expression *expr)
2267 {
2268 struct storage *new = stack_alloc(4);
2269 printf("\tmovi.%d\t\tv%d,.L%p\n", bits_in_pointer, new->pseudo, expr->label_symbol);
2270 return new;
2271 }
2272
x86_statement_expr(struct expression * expr)2273 static struct storage *x86_statement_expr(struct expression *expr)
2274 {
2275 return x86_statement(expr->statement);
2276 }
2277
x86_position_expr(struct expression * expr,struct symbol * base)2278 static int x86_position_expr(struct expression *expr, struct symbol *base)
2279 {
2280 struct storage *new = x86_expression(expr->init_expr);
2281 struct symbol *ctype = expr->init_expr->ctype;
2282
2283 printf("\tinsert v%d at [%d:%d] of %s\n", new->pseudo,
2284 expr->init_offset, ctype->bit_offset,
2285 show_ident(base->ident));
2286 return 0;
2287 }
2288
x86_initializer_expr(struct expression * expr,struct symbol * ctype)2289 static void x86_initializer_expr(struct expression *expr, struct symbol *ctype)
2290 {
2291 struct expression *entry;
2292
2293 FOR_EACH_PTR(expr->expr_list, entry) {
2294 // Nested initializers have their positions already
2295 // recursively calculated - just output them too
2296 if (entry->type == EXPR_INITIALIZER) {
2297 x86_initializer_expr(entry, ctype);
2298 continue;
2299 }
2300
2301 // Ignore initializer indexes and identifiers - the
2302 // evaluator has taken them into account
2303 if (entry->type == EXPR_IDENTIFIER || entry->type == EXPR_INDEX)
2304 continue;
2305 if (entry->type == EXPR_POS) {
2306 x86_position_expr(entry, ctype);
2307 continue;
2308 }
2309 x86_initialization(ctype, entry);
2310 } END_FOR_EACH_PTR(entry);
2311 }
2312
2313 /*
2314 * Print out an expression. Return the pseudo that contains the
2315 * variable.
2316 */
x86_expression(struct expression * expr)2317 static struct storage *x86_expression(struct expression *expr)
2318 {
2319 if (!expr)
2320 return NULL;
2321
2322 if (!expr->ctype) {
2323 struct position *pos = &expr->pos;
2324 printf("\tno type at %s:%d:%d\n",
2325 stream_name(pos->stream),
2326 pos->line, pos->pos);
2327 return NULL;
2328 }
2329
2330 switch (expr->type) {
2331 default:
2332 return NULL;
2333 case EXPR_CALL:
2334 return x86_call_expression(expr);
2335
2336 case EXPR_ASSIGNMENT:
2337 return x86_assignment(expr);
2338
2339 case EXPR_COMPARE:
2340 return emit_compare(expr);
2341 case EXPR_BINOP:
2342 case EXPR_COMMA:
2343 case EXPR_LOGICAL:
2344 return emit_binop(expr);
2345 case EXPR_PREOP:
2346 return x86_preop(expr);
2347 case EXPR_POSTOP:
2348 return emit_postop(expr);
2349 case EXPR_SYMBOL:
2350 return emit_symbol_expr_init(expr->symbol);
2351 case EXPR_DEREF:
2352 case EXPR_SIZEOF:
2353 case EXPR_ALIGNOF:
2354 warning(expr->pos, "invalid expression after evaluation");
2355 return NULL;
2356 case EXPR_CAST:
2357 case EXPR_FORCE_CAST:
2358 case EXPR_IMPLIED_CAST:
2359 return emit_cast_expr(expr);
2360 case EXPR_VALUE:
2361 return emit_value(expr);
2362 case EXPR_STRING:
2363 return emit_string_expr(expr);
2364 case EXPR_INITIALIZER:
2365 x86_initializer_expr(expr, expr->ctype);
2366 return NULL;
2367 case EXPR_SELECT:
2368 return emit_select_expr(expr);
2369 case EXPR_CONDITIONAL:
2370 return emit_conditional_expr(expr);
2371 case EXPR_STATEMENT:
2372 return x86_statement_expr(expr);
2373 case EXPR_LABEL:
2374 return x86_label_expr(expr);
2375
2376 // None of these should exist as direct expressions: they are only
2377 // valid as sub-expressions of initializers.
2378 case EXPR_POS:
2379 warning(expr->pos, "unable to show plain initializer position expression");
2380 return NULL;
2381 case EXPR_IDENTIFIER:
2382 warning(expr->pos, "unable to show identifier expression");
2383 return NULL;
2384 case EXPR_INDEX:
2385 warning(expr->pos, "unable to show index expression");
2386 return NULL;
2387 case EXPR_TYPE:
2388 warning(expr->pos, "unable to show type expression");
2389 return NULL;
2390 case EXPR_FVALUE:
2391 warning(expr->pos, "floating point support is not implemented");
2392 return NULL;
2393 }
2394 return NULL;
2395 }
2396