X-Git-Url: https://git.xonotic.org/?a=blobdiff_plain;f=ir.c;h=7ce418d9049971da2a84219d94c3a84de9703db9;hb=67bc99223d064fd5ff5e719433e200ca8ca83b84;hp=b31c0629b25f25e8cb3756a6b969cee69cd69f08;hpb=db5484bdefc9ac572e61101c25308e36888cad7c;p=xonotic%2Fgmqcc.git diff --git a/ir.c b/ir.c index b31c062..7ce418d 100644 --- a/ir.c +++ b/ir.c @@ -45,7 +45,7 @@ const char *type_name[TYPE_COUNT] = { "array" }; -size_t type_sizeof[TYPE_COUNT] = { +size_t type_sizeof_[TYPE_COUNT] = { 1, /* TYPE_VOID */ 1, /* TYPE_STRING */ 1, /* TYPE_FLOAT */ @@ -285,6 +285,8 @@ ir_builder* ir_builder_new(const char *modulename) self->htfields = util_htnew(IR_HT_SIZE); self->htfunctions = util_htnew(IR_HT_SIZE); + self->max_locals = 0; + self->str_immediate = 0; self->name = NULL; if (!ir_builder_set_name(self, modulename)) { @@ -433,6 +435,8 @@ ir_function* ir_function_new(ir_builder* owner, int outtype) mem_d(self); return NULL; } + self->flags = 0; + self->owner = owner; self->context.file = "<@no context>"; self->context.line = 0; @@ -527,7 +531,8 @@ static bool instr_is_operation(uint16_t op) (op >= INSTR_LOAD_F && op <= INSTR_LOAD_FNC) || (op == INSTR_ADDRESS) || (op >= INSTR_NOT_F && op <= INSTR_NOT_FNC) || - (op >= INSTR_AND && op <= INSTR_BITOR) ); + (op >= INSTR_AND && op <= INSTR_BITOR) || + (op >= INSTR_CALL0 && op <= INSTR_CALL8) ); } bool ir_function_pass_peephole(ir_function *self) @@ -638,7 +643,7 @@ bool ir_function_pass_peephole(ir_function *self) return true; } -bool ir_function_pass_tailcall(ir_function *self) +bool ir_function_pass_tailrecursion(ir_function *self) { size_t b, p; @@ -738,8 +743,8 @@ bool ir_function_finalize(ir_function *self) } if (OPTS_OPTIMIZATION(OPTIM_TAIL_RECURSION)) { - if (!ir_function_pass_tailcall(self)) { - irerror(self->context, "tailcall optimization pass broke something in `%s`", self->name); + if (!ir_function_pass_tailrecursion(self)) { + irerror(self->context, "tail-recursion optimization pass broke something in `%s`", self->name); return false; } } @@ -988,6 +993,8 @@ ir_value* ir_value_var(const char *name, int storetype, int vtype) ir_value* ir_value_vector_member(ir_value *self, unsigned int member) { + char *name; + size_t len; ir_value *m; if (member >= 3) return NULL; @@ -995,9 +1002,22 @@ ir_value* ir_value_vector_member(ir_value *self, unsigned int member) if (self->members[member]) return self->members[member]; + if (self->name) { + len = strlen(self->name); + name = (char*)mem_a(len + 3); + memcpy(name, self->name, len); + name[len+0] = '_'; + name[len+1] = 'x' + member; + name[len+2] = '\0'; + } + else + name = NULL; + if (self->vtype == TYPE_VECTOR) { - m = ir_value_var(self->name, self->store, TYPE_FLOAT); + m = ir_value_var(name, self->store, TYPE_FLOAT); + if (name) + mem_d(name); if (!m) return NULL; m->context = self->context; @@ -1009,7 +1029,9 @@ ir_value* ir_value_vector_member(ir_value *self, unsigned int member) { if (self->fieldtype != TYPE_VECTOR) return NULL; - m = ir_value_var(self->name, self->store, TYPE_FIELD); + m = ir_value_var(name, self->store, TYPE_FIELD); + if (name) + mem_d(name); if (!m) return NULL; m->fieldtype = TYPE_FLOAT; @@ -1028,6 +1050,13 @@ ir_value* ir_value_vector_member(ir_value *self, unsigned int member) return m; } +static GMQCC_INLINE size_t ir_value_sizeof(const ir_value *self) +{ + if (self->vtype == TYPE_FIELD && self->fieldtype == TYPE_VECTOR) + return type_sizeof_[TYPE_VECTOR]; + return type_sizeof_[self->vtype]; +} + ir_value* ir_value_out(ir_function *owner, const char *name, int storetype, int vtype) { ir_value *v = ir_value_var(name, storetype, vtype); @@ -1105,7 +1134,7 @@ static char *ir_strdup(const char *str) { if (str && !*str) { /* actually dup empty strings */ - char *out = mem_a(1); + char *out = (char*)mem_a(1); *out = 0; return out; } @@ -1350,15 +1379,19 @@ bool ir_values_overlap(const ir_value *a, const ir_value *b) *IR main operations */ +static bool ir_check_unreachable(ir_block *self) +{ + /* The IR should never have to deal with unreachable code */ + if (!self->final/* || OPTS_FLAG(ALLOW_UNREACHABLE_CODE)*/) + return true; + irerror(self->context, "unreachable statement (%s)", self->label); + return false; +} + bool ir_block_create_store_op(ir_block *self, lex_ctx ctx, int op, ir_value *target, ir_value *what) { ir_instr *in; - if (self->final) { - irerror(self->context, "unreachable statement (%s)", self->label); - return false; - } - in = ir_instr_new(ctx, self, op); - if (!in) + if (!ir_check_unreachable(self)) return false; if (target->store == store_value && @@ -1370,9 +1403,14 @@ bool ir_block_create_store_op(ir_block *self, lex_ctx ctx, int op, ir_value *tar return false; } + in = ir_instr_new(ctx, self, op); + if (!in) + return false; + if (!ir_instr_op(in, 0, target, true) || !ir_instr_op(in, 1, what, false)) { + ir_instr_delete(in); return false; } vec_push(self->instr, in); @@ -1429,18 +1467,18 @@ bool ir_block_create_storep(ir_block *self, lex_ctx ctx, ir_value *target, ir_va bool ir_block_create_return(ir_block *self, lex_ctx ctx, ir_value *v) { ir_instr *in; - if (self->final) { - irerror(self->context, "unreachable statement (%s)", self->label); + if (!ir_check_unreachable(self)) return false; - } self->final = true; self->is_return = true; in = ir_instr_new(ctx, self, INSTR_RETURN); if (!in) return false; - if (v && !ir_instr_op(in, 0, v, false)) + if (v && !ir_instr_op(in, 0, v, false)) { + ir_instr_delete(in); return false; + } vec_push(self->instr, in); return true; @@ -1450,10 +1488,8 @@ bool ir_block_create_if(ir_block *self, lex_ctx ctx, ir_value *v, ir_block *ontrue, ir_block *onfalse) { ir_instr *in; - if (self->final) { - irerror(self->context, "unreachable statement (%s)", self->label); + if (!ir_check_unreachable(self)) return false; - } self->final = true; /*in = ir_instr_new(ctx, self, (v->vtype == TYPE_STRING ? INSTR_IF_S : INSTR_IF_F));*/ in = ir_instr_new(ctx, self, VINSTR_COND); @@ -1480,10 +1516,8 @@ bool ir_block_create_if(ir_block *self, lex_ctx ctx, ir_value *v, bool ir_block_create_jump(ir_block *self, lex_ctx ctx, ir_block *to) { ir_instr *in; - if (self->final) { - irerror(self->context, "unreachable statement (%s)", self->label); + if (!ir_check_unreachable(self)) return false; - } self->final = true; in = ir_instr_new(ctx, self, VINSTR_JUMP); if (!in) @@ -1499,28 +1533,16 @@ bool ir_block_create_jump(ir_block *self, lex_ctx ctx, ir_block *to) bool ir_block_create_goto(ir_block *self, lex_ctx ctx, ir_block *to) { - ir_instr *in; - if (self->final) { - irerror(self->context, "unreachable statement (%s)", self->label); - return false; - } - self->final = true; - in = ir_instr_new(ctx, self, INSTR_GOTO); - if (!in) - return false; - - in->bops[0] = to; - vec_push(self->instr, in); - - vec_push(self->exits, to); - vec_push(to->entries, self); - return true; + self->owner->flags |= IR_FLAG_HAS_GOTO; + return ir_block_create_jump(self, ctx, to); } ir_instr* ir_block_create_phi(ir_block *self, lex_ctx ctx, const char *label, int ot) { ir_value *out; ir_instr *in; + if (!ir_check_unreachable(self)) + return NULL; in = ir_instr_new(ctx, self, VINSTR_PHI); if (!in) return NULL; @@ -1562,13 +1584,19 @@ void ir_phi_add(ir_instr* self, ir_block *b, ir_value *v) } /* call related code */ -ir_instr* ir_block_create_call(ir_block *self, lex_ctx ctx, const char *label, ir_value *func) +ir_instr* ir_block_create_call(ir_block *self, lex_ctx ctx, const char *label, ir_value *func, bool noreturn) { ir_value *out; ir_instr *in; - in = ir_instr_new(ctx, self, INSTR_CALL0); + if (!ir_check_unreachable(self)) + return NULL; + in = ir_instr_new(ctx, self, (noreturn ? VINSTR_NRCALL : INSTR_CALL0)); if (!in) return NULL; + if (noreturn) { + self->final = true; + self->is_return = true; + } out = ir_value_out(self->owner, label, (func->outtype == TYPE_VOID) ? store_return : store_value, func->outtype); if (!out) { ir_instr_delete(in); @@ -1582,6 +1610,15 @@ ir_instr* ir_block_create_call(ir_block *self, lex_ctx ctx, const char *label, i return NULL; } vec_push(self->instr, in); + /* + if (noreturn) { + if (!ir_block_create_return(self, ctx, NULL)) { + compile_error(ctx, "internal error: failed to generate dummy-return instruction"); + ir_instr_delete(in); + return NULL; + } + } + */ return in; } @@ -2169,8 +2206,25 @@ bool ir_function_calculate_liferanges(ir_function *self) ir_block *block = self->blocks[0]; for (i = 0; i < vec_size(block->living); ++i) { ir_value *v = block->living[i]; - if (v->memberof || v->store != store_local) + if (v->store != store_local) continue; + if ((v->members[0] && v->members[1] && v->members[2])) { + /* all vector members have been accessed - only treat this as uninitialized + * if any of them is also uninitialized. + */ + if (!vec_ir_value_find(block->living, v->members[0], NULL) && + !vec_ir_value_find(block->living, v->members[1], NULL) && + !vec_ir_value_find(block->living, v->members[2], NULL)) + { + continue; + } + } + if (v->memberof) { + /* A member is only uninitialized if the whole vector is also uninitialized */ + if (!vec_ir_value_find(block->living, v->memberof, NULL)) + continue; + } + self->flags |= IR_FLAG_HAS_UNINITIALIZED; if (irwarning(v->context, WARN_USED_UNINITIALIZED, "variable `%s` may be used uninitialized in this function", v->name)) { @@ -2196,7 +2250,7 @@ typedef struct { static bool function_allocator_alloc(function_allocator *alloc, const ir_value *var) { ir_value *slot; - size_t vsize = type_sizeof[var->vtype]; + size_t vsize = ir_value_sizeof(var); slot = ir_value_var("reg", store_global, var->vtype); if (!slot) @@ -2237,7 +2291,9 @@ bool ir_function_allocate_locals(ir_function *self) for (i = 0; i < vec_size(self->locals); ++i) { +#if 0 if (!OPTS_OPTIMIZATION(OPTIM_LOCALTEMPS)) +#endif self->locals[i]->unique_life = true; if (!function_allocator_alloc(&alloc, self->locals[i])) goto error; @@ -2263,7 +2319,7 @@ bool ir_function_allocate_locals(ir_function *self) * will be required later when overlapping temps + locals */ if (a < vec_size(self->params) && - alloc.sizes[a] < type_sizeof[v->vtype]) + alloc.sizes[a] < ir_value_sizeof(v)) { continue; } @@ -2275,8 +2331,8 @@ bool ir_function_allocate_locals(ir_function *self) goto error; /* adjust size for this slot */ - if (alloc.sizes[a] < type_sizeof[v->vtype]) - alloc.sizes[a] = type_sizeof[v->vtype]; + if (alloc.sizes[a] < ir_value_sizeof(v)) + alloc.sizes[a] = ir_value_sizeof(v); self->values[i]->code.local = a; break; @@ -2323,6 +2379,7 @@ error: cleanup: for (i = 0; i < vec_size(alloc.locals); ++i) ir_value_delete(alloc.locals[i]); + vec_free(alloc.unique); vec_free(alloc.locals); vec_free(alloc.sizes); vec_free(alloc.positions); @@ -2446,8 +2503,6 @@ static bool ir_block_life_propagate(ir_block *self, ir_block *prev, bool *change for (p = 0; p < vec_size(instr->phi); ++p) { value = instr->phi[p].value; - if (value->memberof) - value = value->memberof; if (!vec_ir_value_find(self->living, value, NULL)) vec_push(self->living, value); } @@ -2456,8 +2511,6 @@ static bool ir_block_life_propagate(ir_block *self, ir_block *prev, bool *change for (p = 0; p < vec_size(instr->params); ++p) { value = instr->params[p]; - if (value->memberof) - value = value->memberof; if (!vec_ir_value_find(self->living, value, NULL)) vec_push(self->living, value); } @@ -2485,8 +2538,6 @@ static bool ir_block_life_propagate(ir_block *self, ir_block *prev, bool *change continue; value = instr->_ops[o]; - if (value->memberof) - value = value->memberof; /* We only care about locals */ /* we also calculate parameter liferanges so that locals @@ -2712,12 +2763,14 @@ tailcall: if (ontrue->generated) { stmt.opcode = INSTR_IF; stmt.o2.s1 = (ontrue->code_start) - vec_size(code_statements); - code_push_statement(&stmt, instr->context.line); + if (stmt.o2.s1 != 1) + code_push_statement(&stmt, instr->context.line); } if (onfalse->generated) { stmt.opcode = INSTR_IFNOT; stmt.o2.s1 = (onfalse->code_start) - vec_size(code_statements); - code_push_statement(&stmt, instr->context.line); + if (stmt.o2.s1 != 1) + code_push_statement(&stmt, instr->context.line); } if (!ontrue->generated) { if (onfalse->generated) { @@ -2751,6 +2804,12 @@ tailcall: if (onfalse->generated) { /* fixup the jump address */ code_statements[stidx].o2.s1 = (onfalse->code_start) - (stidx); + if (code_statements[stidx].o2.s1 == 1) { + code_statements[stidx] = code_statements[stidx+1]; + if (code_statements[stidx].o1.s1 < 0) + code_statements[stidx].o1.s1++; + code_pop_statement(); + } stmt.opcode = vec_last(code_statements).opcode; if (stmt.opcode == INSTR_GOTO || stmt.opcode == INSTR_IF || @@ -2770,12 +2829,20 @@ tailcall: code_push_statement(&stmt, instr->context.line); return true; } + else if (code_statements[stidx].o2.s1 == 1) { + code_statements[stidx] = code_statements[stidx+1]; + if (code_statements[stidx].o1.s1 < 0) + code_statements[stidx].o1.s1++; + code_pop_statement(); + } /* if not, generate now */ block = onfalse; goto tailcall; } - if (instr->opcode >= INSTR_CALL0 && instr->opcode <= INSTR_CALL8) { + if ( (instr->opcode >= INSTR_CALL0 && instr->opcode <= INSTR_CALL8) + || instr->opcode == VINSTR_NRCALL) + { /* Trivial call translation: * copy all params to OFS_PARM* * if the output's storetype is not store_return, @@ -2844,11 +2911,11 @@ tailcall: code_push_statement(&stmt, instr->context.line); retvalue = instr->_ops[0]; - if (retvalue && retvalue->store != store_return && vec_size(retvalue->life)) + if (retvalue && retvalue->store != store_return && (vec_size(retvalue->life) || retvalue->store == store_global)) { /* not to be kept in OFS_RETURN */ - if (retvalue->vtype == TYPE_FIELD) - stmt.opcode = field_store_instr[retvalue->vtype]; + if (retvalue->vtype == TYPE_FIELD && OPTS_FLAG(ADJUST_VECTOR_FIELDS)) + stmt.opcode = field_store_instr[retvalue->fieldtype]; else stmt.opcode = type_store_instr[retvalue->vtype]; stmt.o1.u1 = OFS_RETURN; @@ -2965,9 +3032,6 @@ static bool gen_global_function(ir_builder *ir, ir_value *global) ir_function *irfun; size_t i; -#ifndef NEW_ALLOC_STRAT - size_t local_var_end; -#endif if (!global->hasvalue || (!global->constval.vfunc)) { @@ -2988,40 +3052,11 @@ static bool gen_global_function(ir_builder *ir, ir_value *global) if ((int32_t)i >= fun.nargs) fun.argsize[i] = 0; else - fun.argsize[i] = type_sizeof[irfun->params[i]]; + fun.argsize[i] = type_sizeof_[irfun->params[i]]; } fun.firstlocal = vec_size(code_globals); -#ifndef NEW_ALLOC_STRAT - local_var_end = fun.firstlocal; - for (i = 0; i < vec_size(irfun->locals); ++i) { - if (!ir_builder_gen_global(ir, irfun->locals[i], true)) { - irerror(irfun->locals[i]->context, "Failed to generate local %s", irfun->locals[i]->name); - return false; - } - } - if (vec_size(irfun->locals)) { - ir_value *last = vec_last(irfun->locals); - local_var_end = last->code.globaladdr; - if (last->vtype == TYPE_FIELD && last->fieldtype == TYPE_VECTOR) - local_var_end += type_sizeof[TYPE_VECTOR]; - else - local_var_end += type_sizeof[last->vtype]; - } - for (i = 0; i < vec_size(irfun->values); ++i) - { - /* generate code.globaladdr for ssa values */ - ir_value *v = irfun->values[i]; - ir_value_code_setaddr(v, local_var_end + v->code.local); - } - for (i = 0; i < irfun->allocated_locals; ++i) { - /* fill the locals with zeros */ - vec_push(code_globals, 0); - } - - fun.locals = vec_size(code_globals) - fun.firstlocal; -#else fun.locals = irfun->allocated_locals; for (i = 0; i < vec_size(irfun->locals); ++i) { if (!ir_builder_gen_global(ir, irfun->locals[i], true)) { @@ -3030,16 +3065,14 @@ static bool gen_global_function(ir_builder *ir, ir_value *global) } ir_value_code_setaddr(irfun->locals[i], fun.firstlocal + irfun->locals[i]->code.local); } - for (i = vec_size(code_globals) - fun.firstlocal; i < fun.locals; ++i) { - vec_push(code_globals, 0); - } for (i = 0; i < vec_size(irfun->values); ++i) { /* generate code.globaladdr for ssa values */ ir_value *v = irfun->values[i]; ir_value_code_setaddr(v, fun.firstlocal + v->code.local); } -#endif + for (i = vec_size(code_globals); i < fun.firstlocal + irfun->allocated_locals; ++i) + vec_push(code_globals, 0); if (irfun->builtin) fun.entry = irfun->builtin+1; @@ -3147,26 +3180,87 @@ static bool gen_global_function_code(ir_builder *ir, ir_value *global) return true; } +static void gen_vector_defs(prog_section_def def, const char *name) +{ + char *component; + size_t len, i; + + if (!name || name[0] == '#' || OPTS_FLAG(SINGLE_VECTOR_DEFS)) + return; + + def.type = TYPE_FLOAT; + + len = strlen(name); + + component = (char*)mem_a(len+3); + memcpy(component, name, len); + len += 2; + component[len-0] = 0; + component[len-2] = '_'; + + component[len-1] = 'x'; + + for (i = 0; i < 3; ++i) { + def.name = code_genstring(component); + vec_push(code_defs, def); + def.offset++; + component[len-1]++; + } +} + +static void gen_vector_fields(prog_section_field fld, const char *name) +{ + char *component; + size_t len, i; + + if (!name || OPTS_FLAG(SINGLE_VECTOR_DEFS)) + return; + + fld.type = TYPE_FLOAT; + + len = strlen(name); + + component = (char*)mem_a(len+3); + memcpy(component, name, len); + len += 2; + component[len-0] = 0; + component[len-2] = '_'; + + component[len-1] = 'x'; + + for (i = 0; i < 3; ++i) { + fld.name = code_genstring(component); + vec_push(code_fields, fld); + fld.offset++; + component[len-1]++; + } +} + static bool ir_builder_gen_global(ir_builder *self, ir_value *global, bool islocal) { size_t i; int32_t *iptr; prog_section_def def; + bool pushdef = false; - def.type = global->vtype; - def.offset = vec_size(code_globals); - - if (global->name) { - if (global->name[0] == '#') { - if (!self->str_immediate) - self->str_immediate = code_genstring("IMMEDIATE"); - def.name = global->code.name = self->str_immediate; + if (opts.g || !islocal) + { + pushdef = true; + def.type = global->vtype; + def.offset = vec_size(code_globals); + + if (global->name) { + if (global->name[0] == '#') { + if (!self->str_immediate) + self->str_immediate = code_genstring("IMMEDIATE"); + def.name = global->code.name = self->str_immediate; + } + else + def.name = global->code.name = code_genstring(global->name); } else - def.name = global->code.name = code_genstring(global->name); + def.name = 0; } - else - def.name = 0; switch (global->vtype) { @@ -3191,13 +3285,16 @@ static bool ir_builder_gen_global(ir_builder *self, ir_value *global, bool isloc ir_value_code_setaddr(global, vec_size(code_globals)); vec_push(code_globals, 0); /* Add the def */ - vec_push(code_defs, def); + if (pushdef) vec_push(code_defs, def); return true; case TYPE_POINTER: - vec_push(code_defs, def); + if (pushdef) vec_push(code_defs, def); return gen_global_pointer(global); case TYPE_FIELD: - vec_push(code_defs, def); + if (pushdef) { + vec_push(code_defs, def); + gen_vector_defs(def, global->name); + } return gen_global_field(global); case TYPE_ENTITY: /* fall through */ @@ -3212,7 +3309,7 @@ static bool ir_builder_gen_global(ir_builder *self, ir_value *global, bool isloc } if (!islocal && global->cvq != CV_CONST) def.type |= DEF_SAVEGLOBAL; - vec_push(code_defs, def); + if (pushdef) vec_push(code_defs, def); return global->code.globaladdr >= 0; } @@ -3226,7 +3323,7 @@ static bool ir_builder_gen_global(ir_builder *self, ir_value *global, bool isloc } if (!islocal && global->cvq != CV_CONST) def.type |= DEF_SAVEGLOBAL; - vec_push(code_defs, def); + if (pushdef) vec_push(code_defs, def); return global->code.globaladdr >= 0; } case TYPE_VECTOR: @@ -3238,21 +3335,25 @@ static bool ir_builder_gen_global(ir_builder *self, ir_value *global, bool isloc vec_push(code_globals, iptr[0]); if (global->code.globaladdr < 0) return false; - for (d = 1; d < type_sizeof[global->vtype]; ++d) { + for (d = 1; d < type_sizeof_[global->vtype]; ++d) { vec_push(code_globals, iptr[d]); } } else { vec_push(code_globals, 0); if (global->code.globaladdr < 0) return false; - for (d = 1; d < type_sizeof[global->vtype]; ++d) { + for (d = 1; d < type_sizeof_[global->vtype]; ++d) { vec_push(code_globals, 0); } } if (!islocal && global->cvq != CV_CONST) def.type |= DEF_SAVEGLOBAL; - vec_push(code_defs, def); + if (pushdef) { + vec_push(code_defs, def); + def.type &= ~DEF_SAVEGLOBAL; + gen_vector_defs(def, global->name); + } return global->code.globaladdr >= 0; } case TYPE_FUNCTION: @@ -3268,13 +3369,13 @@ static bool ir_builder_gen_global(ir_builder *self, ir_value *global, bool isloc } if (!islocal && global->cvq != CV_CONST) def.type |= DEF_SAVEGLOBAL; - vec_push(code_defs, def); + if (pushdef) vec_push(code_defs, def); return true; case TYPE_VARIANT: /* assume biggest type */ ir_value_code_setaddr(global, vec_size(code_globals)); vec_push(code_globals, 0); - for (i = 1; i < type_sizeof[TYPE_VARIANT]; ++i) + for (i = 1; i < type_sizeof_[TYPE_VARIANT]; ++i) vec_push(code_globals, 0); return true; default: @@ -3287,7 +3388,7 @@ static bool ir_builder_gen_global(ir_builder *self, ir_value *global, bool isloc static void ir_builder_prepare_field(ir_value *field) { - field->code.fieldaddr = code_alloc_field(type_sizeof[field->fieldtype]); + field->code.fieldaddr = code_alloc_field(type_sizeof_[field->fieldtype]); } static bool ir_builder_gen_field(ir_builder *self, ir_value *field) @@ -3352,6 +3453,11 @@ static bool ir_builder_gen_field(ir_builder *self, ir_value *field) vec_push(code_globals, fld.offset+2); } + if (field->fieldtype == TYPE_VECTOR) { + gen_vector_defs(def, field->name); + gen_vector_fields(fld, field->name); + } + return field->code.globaladdr >= 0; } @@ -3373,6 +3479,11 @@ bool ir_builder_generate(ir_builder *self, const char *filename) if (!ir_builder_gen_global(self, self->globals[i], false)) { return false; } + if (self->globals[i]->vtype == TYPE_FUNCTION) { + ir_function *func = self->globals[i]->constval.vfunc; + if (func && self->max_locals < func->allocated_locals) + self->max_locals = func->allocated_locals; + } } for (i = 0; i < vec_size(self->fields); ++i) @@ -3446,8 +3557,8 @@ bool ir_builder_generate(ir_builder *self, const char *filename) #define IND_BUFSZ 1024 -#ifdef WIN32 -# define strncat(dst, src, sz) strncat_s(dst, sz, src, _TRUNCATE) +#ifdef _MSC_VER +# define strncat(dst, src, sz) strncat_s(dst, sz, src, _TRUNCATE) #endif const char *qc_opname(int op) @@ -3581,7 +3692,7 @@ void ir_instr_dump(ir_instr *in, char *ind, if (in->_ops[1] || in->_ops[2]) oprintf(" <- "); } - if (in->opcode == INSTR_CALL0) { + if (in->opcode == INSTR_CALL0 || in->opcode == VINSTR_NRCALL) { oprintf("CALL%i\t", vec_size(in->params)); } else oprintf("%s\t", qc_opname(in->opcode));