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