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