X-Git-Url: https://git.xonotic.org/?p=xonotic%2Fgmqcc.git;a=blobdiff_plain;f=ir.cpp;h=787a126cd6907bd68027fe24d26125ca0a6f796b;hp=5920361c7314bb36394bb16a09058adcb665754e;hb=e7d1e701c4498040ff77024d76a81cbc178c78f7;hpb=aabefd1bfe0c5b08bea9341c1394cfa8b96d754d diff --git a/ir.cpp b/ir.cpp index 5920361..787a126 100644 --- a/ir.cpp +++ b/ir.cpp @@ -190,30 +190,19 @@ const uint16_t type_not_instr[TYPE_COUNT] = { }; /* protos */ -static ir_value* ir_value_var(const char *name, int st, int vtype); -static bool ir_value_set_name(ir_value*, const char *name); static void ir_value_dump(ir_value*, int (*oprintf)(const char*,...)); static ir_value* ir_gen_extparam_proto(ir_builder *ir); static void ir_gen_extparam (ir_builder *ir); -static bool ir_builder_set_name(ir_builder *self, const char *name); - -static ir_function* ir_function_new(ir_builder *owner, int returntype); -static bool ir_function_set_name(ir_function*, const char *name); -static void ir_function_delete(ir_function*); static void ir_function_dump(ir_function*, char *ind, int (*oprintf)(const char*,...)); static ir_value* ir_block_create_general_instr(ir_block *self, lex_ctx_t, const char *label, - int op, ir_value *a, ir_value *b, int outype); -static void ir_block_delete(ir_block*); -static ir_block* ir_block_new(ir_function *owner, const char *label); + int op, ir_value *a, ir_value *b, qc_type outype); static bool GMQCC_WARN ir_block_create_store(ir_block*, lex_ctx_t, ir_value *target, ir_value *what); -static bool ir_block_set_label(ir_block*, const char *label); static void ir_block_dump(ir_block*, char *ind, int (*oprintf)(const char*,...)); static bool ir_instr_op(ir_instr*, int op, ir_value *value, bool writing); -static void ir_instr_delete(ir_instr*); static void ir_instr_dump(ir_instr* in, char *ind, int (*oprintf)(const char*,...)); /* error functions */ @@ -239,15 +228,14 @@ static bool GMQCC_WARN irwarning(lex_ctx_t ctx, int warntype, const char *fmt, . * Vector utility functions */ -static bool GMQCC_WARN vec_ir_value_find(ir_value **vec, const ir_value *what, size_t *idx) +static bool GMQCC_WARN vec_ir_value_find(std::vector &vec, const ir_value *what, size_t *idx) { - size_t i; - size_t len = vec_size(vec); - for (i = 0; i < len; ++i) { - if (vec[i] == what) { - if (idx) *idx = i; - return true; - } + for (auto &it : vec) { + if (it != what) + continue; + if (idx) + *idx = &it - &vec[0]; + return true; } return false; } @@ -265,15 +253,14 @@ static bool GMQCC_WARN vec_ir_block_find(ir_block **vec, ir_block *what, size_t return false; } -static bool GMQCC_WARN vec_ir_instr_find(ir_instr **vec, ir_instr *what, size_t *idx) +static bool GMQCC_WARN vec_ir_instr_find(std::vector &vec, ir_instr *what, size_t *idx) { - size_t i; - size_t len = vec_size(vec); - for (i = 0; i < len; ++i) { - if (vec[i] == what) { - if (idx) *idx = i; - return true; - } + for (auto &it : vec) { + if (it != what) + continue; + if (idx) + *idx = &it - &vec[0]; + return true; } return false; } @@ -286,100 +273,54 @@ static void ir_block_delete_quick(ir_block* self); static void ir_instr_delete_quick(ir_instr *self); static void ir_function_delete_quick(ir_function *self); -ir_builder* ir_builder_new(const char *modulename) +void* ir_builder::operator new(std::size_t bytes) { - ir_builder* self; - size_t i; - - self = (ir_builder*)mem_a(sizeof(*self)); - if (!self) - return NULL; - - self->functions = NULL; - self->globals = NULL; - self->fields = NULL; - self->filenames = NULL; - self->filestrings = NULL; - self->htglobals = util_htnew(IR_HT_SIZE); - self->htfields = util_htnew(IR_HT_SIZE); - self->htfunctions = util_htnew(IR_HT_SIZE); - - self->extparams = NULL; - self->extparam_protos = NULL; + return mem_a(bytes); +} - self->first_common_globaltemp = 0; - self->max_globaltemps = 0; - self->first_common_local = 0; - self->max_locals = 0; +void ir_builder::operator delete(void *ptr) +{ + mem_d(ptr); +} - self->str_immediate = 0; - self->name = NULL; - if (!ir_builder_set_name(self, modulename)) { - mem_d(self); - return NULL; - } +ir_builder::ir_builder(const std::string& modulename) +: name(modulename), + code(new code_t) +{ + htglobals = util_htnew(IR_HT_SIZE); + htfields = util_htnew(IR_HT_SIZE); + htfunctions = util_htnew(IR_HT_SIZE); - self->nil = ir_value_var("nil", store_value, TYPE_NIL); - self->nil->cvq = CV_CONST; + nil = new ir_value("nil", store_value, TYPE_NIL); + nil->cvq = CV_CONST; - for (i = 0; i != IR_MAX_VINSTR_TEMPS; ++i) { + for (size_t i = 0; i != IR_MAX_VINSTR_TEMPS; ++i) { /* we write to them, but they're not supposed to be used outside the IR, so * let's not allow the generation of ir_instrs which use these. * So it's a constant noexpr. */ - self->vinstr_temp[i] = ir_value_var("vinstr_temp", store_value, TYPE_NOEXPR); - self->vinstr_temp[i]->cvq = CV_CONST; + vinstr_temp[i] = new ir_value("vinstr_temp", store_value, TYPE_NOEXPR); + vinstr_temp[i]->cvq = CV_CONST; } - - self->reserved_va_count = NULL; - self->coverage_func = NULL; - - self->code = code_init(); - - return self; } -void ir_builder_delete(ir_builder* self) +ir_builder::~ir_builder() { - size_t i; - util_htdel(self->htglobals); - util_htdel(self->htfields); - util_htdel(self->htfunctions); - mem_d((void*)self->name); - for (i = 0; i != vec_size(self->functions); ++i) { - ir_function_delete_quick(self->functions[i]); - } - vec_free(self->functions); - for (i = 0; i != vec_size(self->extparams); ++i) { - ir_value_delete(self->extparams[i]); - } - vec_free(self->extparams); - vec_free(self->extparam_protos); - for (i = 0; i != vec_size(self->globals); ++i) { - ir_value_delete(self->globals[i]); - } - vec_free(self->globals); - for (i = 0; i != vec_size(self->fields); ++i) { - ir_value_delete(self->fields[i]); - } - ir_value_delete(self->nil); - for (i = 0; i != IR_MAX_VINSTR_TEMPS; ++i) { - ir_value_delete(self->vinstr_temp[i]); - } - vec_free(self->fields); - vec_free(self->filenames); - vec_free(self->filestrings); - - code_cleanup(self->code); - mem_d(self); -} + util_htdel(htglobals); + util_htdel(htfields); + util_htdel(htfunctions); + for (auto& f : functions) + ir_function_delete_quick(f.release()); + functions.clear(); // delete them now before deleting the rest: -bool ir_builder_set_name(ir_builder *self, const char *name) -{ - if (self->name) - mem_d((void*)self->name); - self->name = util_strdup(name); - return !!self->name; + delete nil; + + for (size_t i = 0; i != IR_MAX_VINSTR_TEMPS; ++i) { + delete vinstr_temp[i]; + } + + extparams.clear(); + extparam_protos.clear(); } static ir_function* ir_builder_get_function(ir_builder *self, const char *name) @@ -387,26 +328,22 @@ static ir_function* ir_builder_get_function(ir_builder *self, const char *name) return (ir_function*)util_htget(self->htfunctions, name); } -ir_function* ir_builder_create_function(ir_builder *self, const char *name, int outtype) +ir_function* ir_builder_create_function(ir_builder *self, const std::string& name, qc_type outtype) { - ir_function *fn = ir_builder_get_function(self, name); + ir_function *fn = ir_builder_get_function(self, name.c_str()); if (fn) { - return NULL; + return nullptr; } - fn = ir_function_new(self, outtype); - if (!ir_function_set_name(fn, name)) - { - ir_function_delete(fn); - return NULL; - } - vec_push(self->functions, fn); - util_htset(self->htfunctions, name, fn); + fn = new ir_function(self, outtype); + fn->name = name; + self->functions.emplace_back(fn); + util_htset(self->htfunctions, name.c_str(), fn); fn->value = ir_builder_create_global(self, fn->name, TYPE_FUNCTION); if (!fn->value) { - ir_function_delete(fn); - return NULL; + delete fn; + return nullptr; } fn->value->hasvalue = true; @@ -422,21 +359,21 @@ static ir_value* ir_builder_get_global(ir_builder *self, const char *name) return (ir_value*)util_htget(self->htglobals, name); } -ir_value* ir_builder_create_global(ir_builder *self, const char *name, int vtype) +ir_value* ir_builder_create_global(ir_builder *self, const std::string& name, qc_type vtype) { ir_value *ve; if (name[0] != '#') { - ve = ir_builder_get_global(self, name); + ve = ir_builder_get_global(self, name.c_str()); if (ve) { - return NULL; + return nullptr; } } - ve = ir_value_var(name, store_global, vtype); - vec_push(self->globals, ve); - util_htset(self->htglobals, name, ve); + ve = new ir_value(std::string(name), store_global, vtype); + self->globals.emplace_back(ve); + util_htset(self->htglobals, name.c_str(), ve); return ve; } @@ -453,17 +390,17 @@ static ir_value* ir_builder_get_field(ir_builder *self, const char *name) } -ir_value* ir_builder_create_field(ir_builder *self, const char *name, int vtype) +ir_value* ir_builder_create_field(ir_builder *self, const std::string& name, qc_type vtype) { - ir_value *ve = ir_builder_get_field(self, name); + ir_value *ve = ir_builder_get_field(self, name.c_str()); if (ve) { - return NULL; + return nullptr; } - ve = ir_value_var(name, store_global, TYPE_FIELD); + ve = new ir_value(std::string(name), store_global, TYPE_FIELD); ve->fieldtype = vtype; - vec_push(self->fields, ve); - util_htset(self->htfields, name, ve); + self->fields.emplace_back(ve); + util_htset(self->htfields, name.c_str(), ve); return ve; } @@ -476,114 +413,49 @@ static void ir_function_enumerate(ir_function*); static bool ir_function_calculate_liferanges(ir_function*); static bool ir_function_allocate_locals(ir_function*); -ir_function* ir_function_new(ir_builder* owner, int outtype) +void* ir_function::operator new(std::size_t bytes) { - ir_function *self; - self = (ir_function*)mem_a(sizeof(*self)); - - if (!self) - return NULL; - - memset(self, 0, sizeof(*self)); - - self->name = NULL; - if (!ir_function_set_name(self, "<@unnamed>")) { - mem_d(self); - return NULL; - } - self->flags = 0; - - self->owner = owner; - self->context.file = "<@no context>"; - self->context.line = 0; - self->outtype = outtype; - self->value = NULL; - self->builtin = 0; - - self->params = NULL; - self->blocks = NULL; - self->values = NULL; - self->locals = NULL; - - self->max_varargs = 0; - - self->code_function_def = -1; - self->allocated_locals = 0; - self->globaltemps = 0; - - self->run_id = 0; - return self; + return mem_a(bytes); } -bool ir_function_set_name(ir_function *self, const char *name) +void ir_function::operator delete(void *ptr) { - if (self->name) - mem_d((void*)self->name); - self->name = util_strdup(name); - return !!self->name; + mem_d(ptr); } -static void ir_function_delete_quick(ir_function *self) +ir_function::ir_function(ir_builder* owner_, qc_type outtype_) +: owner(owner_), + name("<@unnamed>"), + outtype(outtype_) { - size_t i; - mem_d((void*)self->name); - - for (i = 0; i != vec_size(self->blocks); ++i) - ir_block_delete_quick(self->blocks[i]); - vec_free(self->blocks); - - vec_free(self->params); - - for (i = 0; i != vec_size(self->values); ++i) - ir_value_delete(self->values[i]); - vec_free(self->values); - - for (i = 0; i != vec_size(self->locals); ++i) - ir_value_delete(self->locals[i]); - vec_free(self->locals); - - /* self->value is deleted by the builder */ - - mem_d(self); + context.file = "<@no context>"; + context.line = 0; } -void ir_function_delete(ir_function *self) +ir_function::~ir_function() { - size_t i; - mem_d((void*)self->name); - - for (i = 0; i != vec_size(self->blocks); ++i) - ir_block_delete(self->blocks[i]); - vec_free(self->blocks); - - vec_free(self->params); - - for (i = 0; i != vec_size(self->values); ++i) - ir_value_delete(self->values[i]); - vec_free(self->values); - - for (i = 0; i != vec_size(self->locals); ++i) - ir_value_delete(self->locals[i]); - vec_free(self->locals); - - /* self->value is deleted by the builder */ +} - mem_d(self); +static void ir_function_delete_quick(ir_function *self) +{ + for (auto& b : self->blocks) + ir_block_delete_quick(b.release()); + delete self; } static void ir_function_collect_value(ir_function *self, ir_value *v) { - vec_push(self->values, v); + self->values.emplace_back(v); } ir_block* ir_function_create_block(lex_ctx_t ctx, ir_function *self, const char *label) { - ir_block* bn = ir_block_new(self, label); + ir_block* bn = new ir_block(self, label ? std::string(label) : std::string()); bn->context = ctx; - vec_push(self->blocks, bn); + self->blocks.emplace_back(bn); if ((self->flags & IR_FLAG_BLOCK_COVERAGE) && self->owner->coverage_func) - (void)ir_block_create_call(bn, ctx, NULL, self->owner->coverage_func, false); + (void)ir_block_create_call(bn, ctx, nullptr, self->owner->coverage_func, false); return bn; } @@ -601,13 +473,9 @@ static bool instr_is_operation(uint16_t op) static bool ir_function_pass_peephole(ir_function *self) { - size_t b; - - for (b = 0; b < vec_size(self->blocks); ++b) { - size_t i; - ir_block *block = self->blocks[b]; - - for (i = 0; i < vec_size(block->instr); ++i) { + for (auto& bp : self->blocks) { + ir_block *block = bp.get(); + for (size_t i = 0; i < vec_size(block->instr); ++i) { ir_instr *inst; inst = block->instr[i]; @@ -640,7 +508,7 @@ static bool ir_function_pass_peephole(ir_function *self) continue; /* don't optimize out the temp if it's used later again */ - if (vec_size(value->reads) != 1) + if (value->reads.size() != 1) continue; /* The very next store must use this value */ @@ -656,7 +524,7 @@ static bool ir_function_pass_peephole(ir_function *self) (void)!ir_instr_op(oper, 0, store->_ops[0], true); vec_remove(block->instr, i, 1); - ir_instr_delete(store); + delete store; } else if (inst->opcode == VINSTR_COND) { @@ -670,12 +538,8 @@ static bool ir_function_pass_peephole(ir_function *self) ir_value *value; value = inst->_ops[0]; - if (value->store != store_value || - vec_size(value->reads) != 1 || - value->reads[0] != inst) - { + if (value->store != store_value || value->reads.size() != 1 || value->reads[0] != inst) break; - } inot = value->writes[0]; if (inot->_ops[0] != value || @@ -702,7 +566,7 @@ static bool ir_function_pass_peephole(ir_function *self) return false; } vec_remove(tmp->instr, inotid, 1); - ir_instr_delete(inot); + delete inot; /* swap ontrue/onfalse */ tmp = inst->bops[0]; inst->bops[0] = inst->bops[1]; @@ -718,12 +582,13 @@ static bool ir_function_pass_peephole(ir_function *self) static bool ir_function_pass_tailrecursion(ir_function *self) { - size_t b, p; + size_t p; + + for (auto& bp : self->blocks) { + ir_block *block = bp.get(); - for (b = 0; b < vec_size(self->blocks); ++b) { ir_value *funcval; - ir_instr *ret, *call, *store = NULL; - ir_block *block = self->blocks[b]; + ir_instr *ret, *call, *store = nullptr; if (!block->final || vec_size(block->instr) < 2) continue; @@ -759,7 +624,7 @@ static bool ir_function_pass_tailrecursion(ir_function *self) ++opts_optimizationcount[OPTIM_PEEPHOLE]; call->_ops[0] = store->_ops[0]; vec_remove(block->instr, vec_size(block->instr) - 2, 1); - ir_instr_delete(store); + delete store; } else continue; @@ -784,20 +649,20 @@ static bool ir_function_pass_tailrecursion(ir_function *self) block->final = false; /* open it back up */ /* emite parameter-stores */ - for (p = 0; p < vec_size(call->params); ++p) { + for (p = 0; p < call->params.size(); ++p) { /* assert(call->params_count <= self->locals_count); */ - if (!ir_block_create_store(block, call->context, self->locals[p], call->params[p])) { + if (!ir_block_create_store(block, call->context, self->locals[p].get(), call->params[p])) { irerror(call->context, "failed to create tailcall store instruction for parameter %i", (int)p); return false; } } - if (!ir_block_create_jump(block, call->context, self->blocks[0])) { + if (!ir_block_create_jump(block, call->context, self->blocks[0].get())) { irerror(call->context, "failed to create tailcall jump"); return false; } - ir_instr_delete(call); - ir_instr_delete(ret); + delete call; + delete ret; } return true; @@ -805,21 +670,19 @@ static bool ir_function_pass_tailrecursion(ir_function *self) bool ir_function_finalize(ir_function *self) { - size_t i; - if (self->builtin) return true; if (OPTS_OPTIMIZATION(OPTIM_PEEPHOLE)) { if (!ir_function_pass_peephole(self)) { - irerror(self->context, "generic optimization pass broke something in `%s`", self->name); + irerror(self->context, "generic optimization pass broke something in `%s`", self->name.c_str()); return false; } } if (OPTS_OPTIMIZATION(OPTIM_TAIL_RECURSION)) { if (!ir_function_pass_tailrecursion(self)) { - irerror(self->context, "tail-recursion optimization pass broke something in `%s`", self->name); + irerror(self->context, "tail-recursion optimization pass broke something in `%s`", self->name.c_str()); return false; } } @@ -829,8 +692,8 @@ bool ir_function_finalize(ir_function *self) return false; } - for (i = 0; i < vec_size(self->locals); ++i) { - ir_value *v = self->locals[i]; + for (auto& lp : self->locals) { + ir_value *v = lp.get(); if (v->vtype == TYPE_VECTOR || (v->vtype == TYPE_FIELD && v->outtype == TYPE_VECTOR)) { @@ -839,8 +702,8 @@ bool ir_function_finalize(ir_function *self) ir_value_vector_member(v, 2); } } - for (i = 0; i < vec_size(self->values); ++i) { - ir_value *v = self->values[i]; + for (auto& vp : self->values) { + ir_value *v = vp.get(); if (v->vtype == TYPE_VECTOR || (v->vtype == TYPE_FIELD && v->outtype == TYPE_VECTOR)) { @@ -859,21 +722,22 @@ bool ir_function_finalize(ir_function *self) return true; } -ir_value* ir_function_create_local(ir_function *self, const char *name, int vtype, bool param) +ir_value* ir_function_create_local(ir_function *self, const std::string& name, qc_type vtype, bool param) { ir_value *ve; if (param && - vec_size(self->locals) && - self->locals[vec_size(self->locals)-1]->store != store_param) { + !self->locals.empty() && + self->locals.back()->store != store_param) + { irerror(self->context, "cannot add parameters after adding locals"); - return NULL; + return nullptr; } - ve = ir_value_var(name, (param ? store_param : store_local), vtype); + ve = new ir_value(std::string(name), (param ? store_param : store_local), vtype); if (param) ve->locked = true; - vec_push(self->locals, ve); + self->locals.emplace_back(ve); return ve; } @@ -881,138 +745,90 @@ ir_value* ir_function_create_local(ir_function *self, const char *name, int vtyp *IR Block */ -ir_block* ir_block_new(ir_function* owner, const char *name) -{ - ir_block *self; - self = (ir_block*)mem_a(sizeof(*self)); - if (!self) - return NULL; - - memset(self, 0, sizeof(*self)); - - self->label = NULL; - if (name && !ir_block_set_label(self, name)) { - mem_d(self); - return NULL; - } - self->owner = owner; - self->context.file = "<@no context>"; - self->context.line = 0; - self->final = false; - - self->instr = NULL; - self->entries = NULL; - self->exits = NULL; - - self->eid = 0; - self->is_return = false; - - self->living = NULL; +void* ir_block::operator new(std::size_t bytes) { + return mem_a(bytes); +} - self->generated = false; +void ir_block::operator delete(void *data) { + mem_d(data); +} - return self; +ir_block::ir_block(ir_function* owner, const std::string& name) +: owner(owner), + label(name) +{ + context.file = "<@no context>"; + context.line = 0; } -static void ir_block_delete_quick(ir_block* self) +ir_block::~ir_block() { - size_t i; - if (self->label) mem_d(self->label); - for (i = 0; i != vec_size(self->instr); ++i) - ir_instr_delete_quick(self->instr[i]); - vec_free(self->instr); - vec_free(self->entries); - vec_free(self->exits); - vec_free(self->living); - mem_d(self); + for (size_t i = 0; i != vec_size(instr); ++i) + delete instr[i]; + vec_free(instr); + vec_free(entries); + vec_free(exits); } -void ir_block_delete(ir_block* self) +static void ir_block_delete_quick(ir_block* self) { size_t i; - if (self->label) mem_d(self->label); for (i = 0; i != vec_size(self->instr); ++i) - ir_instr_delete(self->instr[i]); + ir_instr_delete_quick(self->instr[i]); vec_free(self->instr); - vec_free(self->entries); - vec_free(self->exits); - vec_free(self->living); - mem_d(self); -} - -bool ir_block_set_label(ir_block *self, const char *name) -{ - if (self->label) - mem_d((void*)self->label); - self->label = util_strdup(name); - return !!self->label; + delete self; } /*********************************************************************** *IR Instructions */ -static ir_instr* ir_instr_new(lex_ctx_t ctx, ir_block* owner, int op) -{ - ir_instr *self; - self = (ir_instr*)mem_a(sizeof(*self)); - if (!self) - return NULL; - - self->owner = owner; - self->context = ctx; - self->opcode = op; - self->_ops[0] = NULL; - self->_ops[1] = NULL; - self->_ops[2] = NULL; - self->bops[0] = NULL; - self->bops[1] = NULL; - - self->phi = NULL; - self->params = NULL; - - self->eid = 0; - - self->likely = true; - return self; +void* ir_instr::operator new(std::size_t bytes) { + return mem_a(bytes); } -static void ir_instr_delete_quick(ir_instr *self) +void ir_instr::operator delete(void *data) { + mem_d(data); +} + +ir_instr::ir_instr(lex_ctx_t ctx, ir_block* owner_, int op) +: opcode(op), + context(ctx), + owner(owner_) { - vec_free(self->phi); - vec_free(self->params); - mem_d(self); } -static void ir_instr_delete(ir_instr *self) +ir_instr::~ir_instr() { - size_t i; - /* The following calls can only delete from - * vectors, we still want to delete this instruction - * so ignore the return value. Since with the warn_unused_result attribute - * gcc doesn't care about an explicit: (void)foo(); to ignore the result, - * I have to improvise here and use if(foo()); - */ - for (i = 0; i < vec_size(self->phi); ++i) { + // The following calls can only delete from + // vectors, we still want to delete this instruction + // so ignore the return value. Since with the warn_unused_result attribute + // gcc doesn't care about an explicit: (void)foo(); to ignore the result, + // I have to improvise here and use if(foo()); + for (auto &it : phi) { size_t idx; - if (vec_ir_instr_find(self->phi[i].value->writes, self, &idx)) - vec_remove(self->phi[i].value->writes, idx, 1); - if (vec_ir_instr_find(self->phi[i].value->reads, self, &idx)) - vec_remove(self->phi[i].value->reads, idx, 1); + if (vec_ir_instr_find(it.value->writes, this, &idx)) + it.value->writes.erase(it.value->writes.begin() + idx); + if (vec_ir_instr_find(it.value->reads, this, &idx)) + it.value->reads.erase(it.value->reads.begin() + idx); } - vec_free(self->phi); - for (i = 0; i < vec_size(self->params); ++i) { + for (auto &it : params) { size_t idx; - if (vec_ir_instr_find(self->params[i]->writes, self, &idx)) - vec_remove(self->params[i]->writes, idx, 1); - if (vec_ir_instr_find(self->params[i]->reads, self, &idx)) - vec_remove(self->params[i]->reads, idx, 1); - } - vec_free(self->params); - (void)!ir_instr_op(self, 0, NULL, false); - (void)!ir_instr_op(self, 1, NULL, false); - (void)!ir_instr_op(self, 2, NULL, false); - mem_d(self); + if (vec_ir_instr_find(it->writes, this, &idx)) + it->writes.erase(it->writes.begin() + idx); + if (vec_ir_instr_find(it->reads, this, &idx)) + it->reads.erase(it->reads.begin() + idx); + } + (void)!ir_instr_op(this, 0, nullptr, false); + (void)!ir_instr_op(this, 1, nullptr, false); + (void)!ir_instr_op(this, 2, nullptr, false); +} + +static void ir_instr_delete_quick(ir_instr *self) +{ + self->phi.clear(); + self->params.clear(); + delete self; } static bool ir_instr_op(ir_instr *self, int op, ir_value *v, bool writing) @@ -1025,15 +841,15 @@ static bool ir_instr_op(ir_instr *self, int op, ir_value *v, bool writing) if (self->_ops[op]) { size_t idx; if (writing && vec_ir_instr_find(self->_ops[op]->writes, self, &idx)) - vec_remove(self->_ops[op]->writes, idx, 1); + self->_ops[op]->writes.erase(self->_ops[op]->writes.begin() + idx); else if (vec_ir_instr_find(self->_ops[op]->reads, self, &idx)) - vec_remove(self->_ops[op]->reads, idx, 1); + self->_ops[op]->reads.erase(self->_ops[op]->reads.begin() + idx); } if (v) { if (writing) - vec_push(v->writes, self); + v->writes.push_back(self); else - vec_push(v->reads, self); + v->reads.push_back(self); } self->_ops[op] = v; return true; @@ -1058,89 +874,91 @@ static int32_t ir_value_code_addr(const ir_value *self) return self->code.globaladdr + self->code.addroffset; } -ir_value* ir_value_var(const char *name, int storetype, int vtype) +void* ir_value::operator new(std::size_t bytes) { + return mem_a(bytes); +} + +void ir_value::operator delete(void *data) { + mem_d(data); +} + +ir_value::ir_value(std::string&& name_, store_type store_, qc_type vtype_) +: name(move(name_)), + vtype(vtype_), + store(store_) { - ir_value *self; - self = (ir_value*)mem_a(sizeof(*self)); - self->vtype = vtype; - self->fieldtype = TYPE_VOID; - self->outtype = TYPE_VOID; - self->store = storetype; - self->flags = 0; - - self->reads = NULL; - self->writes = NULL; - - self->cvq = CV_NONE; - self->hasvalue = false; - self->context.file = "<@no context>"; - self->context.line = 0; - self->name = NULL; - if (name && !ir_value_set_name(self, name)) { - irerror(self->context, "out of memory"); - mem_d(self); - return NULL; - } - - memset(&self->constval, 0, sizeof(self->constval)); - memset(&self->code, 0, sizeof(self->code)); - - self->members[0] = NULL; - self->members[1] = NULL; - self->members[2] = NULL; - self->memberof = NULL; - - self->unique_life = false; - self->locked = false; - self->callparam = false; - - self->life = NULL; - return self; + fieldtype = TYPE_VOID; + outtype = TYPE_VOID; + flags = 0; + + cvq = CV_NONE; + hasvalue = false; + context.file = "<@no context>"; + context.line = 0; + + memset(&constval, 0, sizeof(constval)); + memset(&code, 0, sizeof(code)); + + members[0] = nullptr; + members[1] = nullptr; + members[2] = nullptr; + memberof = nullptr; + + unique_life = false; + locked = false; + callparam = false; +} + +ir_value::~ir_value() +{ + size_t i; + if (hasvalue) { + if (vtype == TYPE_STRING) + mem_d((void*)constval.vstring); + } + if (!(flags & IR_FLAG_SPLIT_VECTOR)) { + for (i = 0; i < 3; ++i) { + if (members[i]) + delete members[i]; + } + } } + /* helper function */ static ir_value* ir_builder_imm_float(ir_builder *self, float value, bool add_to_list) { - ir_value *v = ir_value_var("#IMMEDIATE", store_global, TYPE_FLOAT); + ir_value *v = new ir_value("#IMMEDIATE", store_global, TYPE_FLOAT); v->flags |= IR_FLAG_ERASABLE; v->hasvalue = true; v->cvq = CV_CONST; v->constval.vfloat = value; - vec_push(self->globals, v); + self->globals.emplace_back(v); if (add_to_list) - vec_push(self->const_floats, v); + self->const_floats.emplace_back(v); return v; } ir_value* ir_value_vector_member(ir_value *self, unsigned int member) { - char *name; - size_t len; + std::string name; ir_value *m; if (member >= 3) - return NULL; + return nullptr; 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'; + if (!self->name.empty()) { + char member_name[3] = { '_', char('x' + member), 0 }; + name = self->name + member_name; } - else - name = NULL; if (self->vtype == TYPE_VECTOR) { - m = ir_value_var(name, self->store, TYPE_FLOAT); - if (name) - mem_d(name); + m = new ir_value(move(name), self->store, TYPE_FLOAT); if (!m) - return NULL; + return nullptr; m->context = self->context; self->members[member] = m; @@ -1149,12 +967,10 @@ ir_value* ir_value_vector_member(ir_value *self, unsigned int member) else if (self->vtype == TYPE_FIELD) { if (self->fieldtype != TYPE_VECTOR) - return NULL; - m = ir_value_var(name, self->store, TYPE_FIELD); - if (name) - mem_d(name); + return nullptr; + m = new ir_value(move(name), self->store, TYPE_FIELD); if (!m) - return NULL; + return nullptr; m->fieldtype = TYPE_FLOAT; m->context = self->context; @@ -1163,8 +979,8 @@ ir_value* ir_value_vector_member(ir_value *self, unsigned int member) } else { - irerror(self->context, "invalid member access on %s", self->name); - return NULL; + irerror(self->context, "invalid member access on %s", self->name.c_str()); + return nullptr; } m->memberof = self; @@ -1178,45 +994,15 @@ static GMQCC_INLINE size_t ir_value_sizeof(const ir_value *self) return type_sizeof_[self->vtype]; } -static ir_value* ir_value_out(ir_function *owner, const char *name, int storetype, int vtype) +static ir_value* ir_value_out(ir_function *owner, const char *name, store_type storetype, qc_type vtype) { - ir_value *v = ir_value_var(name, storetype, vtype); + ir_value *v = new ir_value(name ? std::string(name) : std::string(), storetype, vtype); if (!v) - return NULL; + return nullptr; ir_function_collect_value(owner, v); return v; } -void ir_value_delete(ir_value* self) -{ - size_t i; - if (self->name) - mem_d((void*)self->name); - if (self->hasvalue) - { - if (self->vtype == TYPE_STRING) - mem_d((void*)self->constval.vstring); - } - if (!(self->flags & IR_FLAG_SPLIT_VECTOR)) { - for (i = 0; i < 3; ++i) { - if (self->members[i]) - ir_value_delete(self->members[i]); - } - } - vec_free(self->reads); - vec_free(self->writes); - vec_free(self->life); - mem_d(self); -} - -bool ir_value_set_name(ir_value *self, const char *name) -{ - if (self->name) - mem_d((void*)self->name); - self->name = util_strdup(name); - return !!self->name; -} - bool ir_value_set_float(ir_value *self, float f) { if (self->vtype != TYPE_FLOAT) @@ -1275,13 +1061,10 @@ bool ir_value_set_int(ir_value *self, int i) bool ir_value_lives(ir_value *self, size_t at) { - size_t i; - for (i = 0; i < vec_size(self->life); ++i) - { - ir_life_entry_t *life = &self->life[i]; - if (life->start <= at && at <= life->end) + for (auto& l : self->life) { + if (l.start <= at && at <= l.end) return true; - if (life->start > at) /* since it's ordered */ + if (l.start > at) /* since it's ordered */ return false; } return false; @@ -1289,54 +1072,50 @@ bool ir_value_lives(ir_value *self, size_t at) static bool ir_value_life_insert(ir_value *self, size_t idx, ir_life_entry_t e) { - size_t k; - vec_push(self->life, e); - for (k = vec_size(self->life)-1; k > idx; --k) - self->life[k] = self->life[k-1]; - self->life[idx] = e; + self->life.insert(self->life.begin() + idx, e); return true; } static bool ir_value_life_merge(ir_value *self, size_t s) { size_t i; - const size_t vs = vec_size(self->life); - ir_life_entry_t *life = NULL; - ir_life_entry_t *before = NULL; + const size_t vs = self->life.size(); + ir_life_entry_t *life_found = nullptr; + ir_life_entry_t *before = nullptr; ir_life_entry_t new_entry; /* Find the first range >= s */ for (i = 0; i < vs; ++i) { - before = life; - life = &self->life[i]; - if (life->start > s) + before = life_found; + life_found = &self->life[i]; + if (life_found->start > s) break; } /* nothing found? append */ if (i == vs) { ir_life_entry_t e; - if (life && life->end+1 == s) + if (life_found && life_found->end+1 == s) { /* previous life range can be merged in */ - life->end++; + life_found->end++; return true; } - if (life && life->end >= s) + if (life_found && life_found->end >= s) return false; e.start = e.end = s; - vec_push(self->life, e); + self->life.emplace_back(e); return true; } /* found */ if (before) { if (before->end + 1 == s && - life->start - 1 == s) + life_found->start - 1 == s) { /* merge */ - before->end = life->end; - vec_remove(self->life, i, 1); + before->end = life_found->end; + self->life.erase(self->life.begin()+i); return true; } if (before->end + 1 == s) @@ -1350,9 +1129,9 @@ static bool ir_value_life_merge(ir_value *self, size_t s) return false; } /* extend */ - if (life->start - 1 == s) + if (life_found->start - 1 == s) { - life->start--; + life_found->start--; return true; } /* insert a new entry */ @@ -1364,65 +1143,63 @@ static bool ir_value_life_merge_into(ir_value *self, const ir_value *other) { size_t i, myi; - if (!vec_size(other->life)) + if (other->life.empty()) return true; - if (!vec_size(self->life)) { - size_t count = vec_size(other->life); - ir_life_entry_t *life = vec_add(self->life, count); - memcpy(life, other->life, count * sizeof(*life)); + if (self->life.empty()) { + self->life = other->life; return true; } myi = 0; - for (i = 0; i < vec_size(other->life); ++i) + for (i = 0; i < other->life.size(); ++i) { - const ir_life_entry_t *life = &other->life[i]; + const ir_life_entry_t &otherlife = other->life[i]; while (true) { ir_life_entry_t *entry = &self->life[myi]; - if (life->end+1 < entry->start) + if (otherlife.end+1 < entry->start) { /* adding an interval before entry */ - if (!ir_value_life_insert(self, myi, *life)) + if (!ir_value_life_insert(self, myi, otherlife)) return false; ++myi; break; } - if (life->start < entry->start && - life->end+1 >= entry->start) + if (otherlife.start < entry->start && + otherlife.end+1 >= entry->start) { /* starts earlier and overlaps */ - entry->start = life->start; + entry->start = otherlife.start; } - if (life->end > entry->end && - life->start <= entry->end+1) + if (otherlife.end > entry->end && + otherlife.start <= entry->end+1) { /* ends later and overlaps */ - entry->end = life->end; + entry->end = otherlife.end; } /* see if our change combines it with the next ranges */ - while (myi+1 < vec_size(self->life) && + while (myi+1 < self->life.size() && entry->end+1 >= self->life[1+myi].start) { /* overlaps with (myi+1) */ if (entry->end < self->life[1+myi].end) entry->end = self->life[1+myi].end; - vec_remove(self->life, myi+1, 1); + self->life.erase(self->life.begin() + (myi + 1)); entry = &self->life[myi]; } /* see if we're after the entry */ - if (life->start > entry->end) + if (otherlife.start > entry->end) { ++myi; /* append if we're at the end */ - if (myi >= vec_size(self->life)) { - vec_push(self->life, *life); + if (myi >= self->life.size()) { + self->life.emplace_back(otherlife); break; } /* otherweise check the next range */ @@ -1443,16 +1220,16 @@ static bool ir_values_overlap(const ir_value *a, const ir_value *b) * statement above. */ - ir_life_entry_t *la, *lb, *enda, *endb; + const ir_life_entry_t *la, *lb, *enda, *endb; /* first of all, if either has no life range, they cannot clash */ - if (!vec_size(a->life) || !vec_size(b->life)) + if (a->life.empty() || b->life.empty()) return false; - la = a->life; - lb = b->life; - enda = la + vec_size(a->life); - endb = lb + vec_size(b->life); + la = &a->life.front(); + lb = &b->life.front(); + enda = &a->life.back() + 1; + endb = &b->life.back() + 1; while (true) { /* check if the entries overlap, for that, @@ -1497,7 +1274,7 @@ 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); + irerror(self->context, "unreachable statement (%s)", self->label.c_str()); return false; } @@ -1511,19 +1288,19 @@ bool ir_block_create_store_op(ir_block *self, lex_ctx_t ctx, int op, ir_value *t (op < INSTR_STOREP_F || op > INSTR_STOREP_FNC)) { irerror(self->context, "cannot store to an SSA value"); - irerror(self->context, "trying to store: %s <- %s", target->name, what->name); + irerror(self->context, "trying to store: %s <- %s", target->name.c_str(), what->name.c_str()); irerror(self->context, "instruction: %s", util_instr_str[op]); return false; } - in = ir_instr_new(ctx, self, op); + in = new ir_instr(ctx, self, op); if (!in) return false; if (!ir_instr_op(in, 0, target, (op < INSTR_STOREP_F || op > INSTR_STOREP_FNC)) || !ir_instr_op(in, 1, what, false)) { - ir_instr_delete(in); + delete in; return false; } vec_push(self->instr, in); @@ -1536,14 +1313,14 @@ bool ir_block_create_state_op(ir_block *self, lex_ctx_t ctx, ir_value *frame, ir if (!ir_check_unreachable(self)) return false; - in = ir_instr_new(ctx, self, INSTR_STATE); + in = new ir_instr(ctx, self, INSTR_STATE); if (!in) return false; if (!ir_instr_op(in, 0, frame, false) || !ir_instr_op(in, 1, think, false)) { - ir_instr_delete(in); + delete in; return false; } vec_push(self->instr, in); @@ -1553,7 +1330,7 @@ bool ir_block_create_state_op(ir_block *self, lex_ctx_t ctx, ir_value *frame, ir static bool ir_block_create_store(ir_block *self, lex_ctx_t ctx, ir_value *target, ir_value *what) { int op = 0; - int vtype; + qc_type vtype; if (target->vtype == TYPE_VARIANT) vtype = what->vtype; else @@ -1578,7 +1355,7 @@ static bool ir_block_create_store(ir_block *self, lex_ctx_t ctx, ir_value *targe bool ir_block_create_storep(ir_block *self, lex_ctx_t ctx, ir_value *target, ir_value *what) { int op = 0; - int vtype; + qc_type vtype; if (target->vtype != TYPE_POINTER) return false; @@ -1606,12 +1383,12 @@ bool ir_block_create_return(ir_block *self, lex_ctx_t ctx, ir_value *v) self->final = true; self->is_return = true; - in = ir_instr_new(ctx, self, INSTR_RETURN); + in = new ir_instr(ctx, self, INSTR_RETURN); if (!in) return false; if (v && !ir_instr_op(in, 0, v, false)) { - ir_instr_delete(in); + delete in; return false; } @@ -1626,13 +1403,13 @@ bool ir_block_create_if(ir_block *self, lex_ctx_t ctx, ir_value *v, 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); + /*in = new ir_instr(ctx, self, (v->vtype == TYPE_STRING ? INSTR_IF_S : INSTR_IF_F));*/ + in = new ir_instr(ctx, self, VINSTR_COND); if (!in) return false; if (!ir_instr_op(in, 0, v, false)) { - ir_instr_delete(in); + delete in; return false; } @@ -1654,7 +1431,7 @@ bool ir_block_create_jump(ir_block *self, lex_ctx_t ctx, ir_block *to) if (!ir_check_unreachable(self)) return false; self->final = true; - in = ir_instr_new(ctx, self, VINSTR_JUMP); + in = new ir_instr(ctx, self, VINSTR_JUMP); if (!in) return false; @@ -1672,24 +1449,23 @@ bool ir_block_create_goto(ir_block *self, lex_ctx_t ctx, ir_block *to) return ir_block_create_jump(self, ctx, to); } -ir_instr* ir_block_create_phi(ir_block *self, lex_ctx_t ctx, const char *label, int ot) +ir_instr* ir_block_create_phi(ir_block *self, lex_ctx_t ctx, const char *label, qc_type ot) { ir_value *out; ir_instr *in; if (!ir_check_unreachable(self)) - return NULL; - in = ir_instr_new(ctx, self, VINSTR_PHI); + return nullptr; + in = new ir_instr(ctx, self, VINSTR_PHI); if (!in) - return NULL; + return nullptr; out = ir_value_out(self->owner, label, store_value, ot); if (!out) { - ir_instr_delete(in); - return NULL; + delete in; + return nullptr; } if (!ir_instr_op(in, 0, out, true)) { - ir_instr_delete(in); - ir_value_delete(out); - return NULL; + delete in; + return nullptr; } vec_push(self->instr, in); return in; @@ -1704,18 +1480,17 @@ void ir_phi_add(ir_instr* self, ir_block *b, ir_value *v) { ir_phi_entry_t pe; - if (!vec_ir_block_find(self->owner->entries, b, NULL)) { - /* Must not be possible to cause this, otherwise the AST - * is doing something wrong. - */ + if (!vec_ir_block_find(self->owner->entries, b, nullptr)) { + // Must not be possible to cause this, otherwise the AST + // is doing something wrong. irerror(self->context, "Invalid entry block for PHI"); exit(EXIT_FAILURE); } pe.value = v; pe.from = b; - vec_push(v->reads, self); - vec_push(self->phi, pe); + v->reads.push_back(self); + self->phi.push_back(pe); } /* call related code */ @@ -1724,33 +1499,32 @@ ir_instr* ir_block_create_call(ir_block *self, lex_ctx_t ctx, const char *label, ir_value *out; ir_instr *in; if (!ir_check_unreachable(self)) - return NULL; - in = ir_instr_new(ctx, self, (noreturn ? VINSTR_NRCALL : INSTR_CALL0)); + return nullptr; + in = new ir_instr(ctx, self, (noreturn ? VINSTR_NRCALL : INSTR_CALL0)); if (!in) - return NULL; + return nullptr; 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); - return NULL; + delete in; + return nullptr; } if (!ir_instr_op(in, 0, out, true) || !ir_instr_op(in, 1, func, false)) { - ir_instr_delete(in); - ir_value_delete(out); - return NULL; + delete in; + return nullptr; } vec_push(self->instr, in); /* if (noreturn) { - if (!ir_block_create_return(self, ctx, NULL)) { + if (!ir_block_create_return(self, ctx, nullptr)) { compile_error(ctx, "internal error: failed to generate dummy-return instruction"); - ir_instr_delete(in); - return NULL; + delete in; + return nullptr; } } */ @@ -1764,8 +1538,8 @@ ir_value* ir_call_value(ir_instr *self) void ir_call_param(ir_instr* self, ir_value *v) { - vec_push(self->params, v); - vec_push(v->reads, self); + self->params.push_back(v); + v->reads.push_back(self); } /* binary op related code */ @@ -1774,7 +1548,7 @@ ir_value* ir_block_create_binop(ir_block *self, lex_ctx_t ctx, const char *label, int opcode, ir_value *left, ir_value *right) { - int ot = TYPE_VOID; + qc_type ot = TYPE_VOID; switch (opcode) { case INSTR_ADD_F: case INSTR_SUB_F: @@ -1883,7 +1657,7 @@ ir_value* ir_block_create_binop(ir_block *self, lex_ctx_t ctx, }; if (ot == TYPE_VOID) { /* The AST or parser were supposed to check this! */ - return NULL; + return nullptr; } return ir_block_create_general_instr(self, ctx, label, opcode, left, right, ot); @@ -1893,7 +1667,7 @@ ir_value* ir_block_create_unary(ir_block *self, lex_ctx_t ctx, const char *label, int opcode, ir_value *operand) { - int ot = TYPE_FLOAT; + qc_type ot = TYPE_FLOAT; switch (opcode) { case INSTR_NOT_F: case INSTR_NOT_V: @@ -1909,9 +1683,9 @@ ir_value* ir_block_create_unary(ir_block *self, lex_ctx_t ctx, * the operand for 0 already exists so we just source it from here. */ case VINSTR_NEG_F: - return ir_block_create_general_instr(self, ctx, label, INSTR_SUB_F, NULL, operand, ot); + return ir_block_create_general_instr(self, ctx, label, INSTR_SUB_F, nullptr, operand, ot); case VINSTR_NEG_V: - return ir_block_create_general_instr(self, ctx, label, INSTR_SUB_V, NULL, operand, TYPE_VECTOR); + return ir_block_create_general_instr(self, ctx, label, INSTR_SUB_V, nullptr, operand, TYPE_VECTOR); default: ot = operand->vtype; @@ -1919,27 +1693,26 @@ ir_value* ir_block_create_unary(ir_block *self, lex_ctx_t ctx, }; if (ot == TYPE_VOID) { /* The AST or parser were supposed to check this! */ - return NULL; + return nullptr; } - /* let's use the general instruction creator and pass NULL for OPB */ - return ir_block_create_general_instr(self, ctx, label, opcode, operand, NULL, ot); + /* let's use the general instruction creator and pass nullptr for OPB */ + return ir_block_create_general_instr(self, ctx, label, opcode, operand, nullptr, ot); } static ir_value* ir_block_create_general_instr(ir_block *self, lex_ctx_t ctx, const char *label, - int op, ir_value *a, ir_value *b, int outype) + int op, ir_value *a, ir_value *b, qc_type outype) { ir_instr *instr; ir_value *out; out = ir_value_out(self->owner, label, store_value, outype); if (!out) - return NULL; + return nullptr; - instr = ir_instr_new(ctx, self, op); + instr = new ir_instr(ctx, self, op); if (!instr) { - ir_value_delete(out); - return NULL; + return nullptr; } if (!ir_instr_op(instr, 0, out, true) || @@ -1953,9 +1726,8 @@ static ir_value* ir_block_create_general_instr(ir_block *self, lex_ctx_t ctx, co return out; on_error: - ir_instr_delete(instr); - ir_value_delete(out); - return NULL; + delete instr; + return nullptr; } ir_value* ir_block_create_fieldaddress(ir_block *self, lex_ctx_t ctx, const char *label, ir_value *ent, ir_value *field) @@ -1964,25 +1736,25 @@ ir_value* ir_block_create_fieldaddress(ir_block *self, lex_ctx_t ctx, const char /* Support for various pointer types todo if so desired */ if (ent->vtype != TYPE_ENTITY) - return NULL; + return nullptr; if (field->vtype != TYPE_FIELD) - return NULL; + return nullptr; v = ir_block_create_general_instr(self, ctx, label, INSTR_ADDRESS, ent, field, TYPE_POINTER); v->fieldtype = field->fieldtype; return v; } -ir_value* ir_block_create_load_from_ent(ir_block *self, lex_ctx_t ctx, const char *label, ir_value *ent, ir_value *field, int outype) +ir_value* ir_block_create_load_from_ent(ir_block *self, lex_ctx_t ctx, const char *label, ir_value *ent, ir_value *field, qc_type outype) { int op; if (ent->vtype != TYPE_ENTITY) - return NULL; + return nullptr; /* at some point we could redirect for TYPE_POINTER... but that could lead to carelessness */ if (field->vtype != TYPE_FIELD) - return NULL; + return nullptr; switch (outype) { @@ -1998,7 +1770,7 @@ ir_value* ir_block_create_load_from_ent(ir_block *self, lex_ctx_t ctx, const cha #endif default: irerror(self->context, "invalid type for ir_block_create_load_from_ent: %s", type_name[outype]); - return NULL; + return nullptr; } return ir_block_create_general_instr(self, ctx, label, op, ent, field, outype); @@ -2011,19 +1783,15 @@ ir_value* ir_block_create_load_from_ent(ir_block *self, lex_ctx_t ctx, const cha static bool ir_block_naive_phi(ir_block *self); bool ir_function_naive_phi(ir_function *self) { - size_t i; - - for (i = 0; i < vec_size(self->blocks); ++i) - { - if (!ir_block_naive_phi(self->blocks[i])) + for (auto& b : self->blocks) + if (!ir_block_naive_phi(b.get())) return false; - } return true; } static bool ir_block_naive_phi(ir_block *self) { - size_t i, p; /*, w;*/ + size_t i; /* FIXME: optionally, create_phi can add the phis * to a list so we don't need to loop through blocks * - anyway: "don't optimize YET" @@ -2037,21 +1805,14 @@ static bool ir_block_naive_phi(ir_block *self) vec_remove(self->instr, i, 1); --i; /* NOTE: i+1 below */ - for (p = 0; p < vec_size(instr->phi); ++p) - { - ir_value *v = instr->phi[p].value; - ir_block *b = instr->phi[p].from; - - if (v->store == store_value && - vec_size(v->reads) == 1 && - vec_size(v->writes) == 1) - { + for (auto &it : instr->phi) { + ir_value *v = it.value; + ir_block *b = it.from; + if (v->store == store_value && v->reads.size() == 1 && v->writes.size() == 1) { /* replace the value */ if (!ir_instr_op(v->writes[0], 0, instr->_ops[0], true)) return false; - } - else - { + } else { /* force a move instruction */ ir_instr *prevjump = vec_last(b->instr); vec_pop(b->instr); @@ -2064,7 +1825,7 @@ static bool ir_block_naive_phi(ir_block *self) b->final = true; } } - ir_instr_delete(instr); + delete instr; } return true; } @@ -2098,18 +1859,19 @@ static void ir_block_enumerate(ir_block *self, size_t *_eid) */ void ir_function_enumerate(ir_function *self) { - size_t i; size_t instruction_id = 0; - for (i = 0; i < vec_size(self->blocks); ++i) + size_t block_eid = 0; + for (auto& block : self->blocks) { /* each block now gets an additional "entry" instruction id * we can use to avoid point-life issues */ - self->blocks[i]->entry_id = instruction_id; + block->entry_id = instruction_id; + block->eid = block_eid; ++instruction_id; + ++block_eid; - self->blocks[i]->eid = i; - ir_block_enumerate(self->blocks[i], &instruction_id); + ir_block_enumerate(block.get(), &instruction_id); } } @@ -2118,12 +1880,12 @@ void ir_function_enumerate(ir_function *self) * we can allocate their global-positions. * This is the counterpart to register-allocation in register machines. */ -typedef struct { +struct function_allocator { ir_value **locals; - size_t *sizes; - size_t *positions; - bool *unique; -} function_allocator; + size_t *sizes; + size_t *positions; + bool *unique; +}; static bool function_allocator_alloc(function_allocator *alloc, ir_value *var) { @@ -2132,7 +1894,7 @@ static bool function_allocator_alloc(function_allocator *alloc, ir_value *var) var->code.local = vec_size(alloc->locals); - slot = ir_value_var("reg", store_global, var->vtype); + slot = new ir_value("reg", store_global, var->vtype); if (!slot) return false; @@ -2146,7 +1908,7 @@ static bool function_allocator_alloc(function_allocator *alloc, ir_value *var) return true; localerror: - ir_value_delete(slot); + delete slot; return false; } @@ -2197,30 +1959,28 @@ static bool ir_function_allocator_assign(ir_function *self, function_allocator * bool ir_function_allocate_locals(ir_function *self) { - size_t i; bool retval = true; size_t pos; bool opt_gt = OPTS_OPTIMIZATION(OPTIM_GLOBAL_TEMPS); - ir_value *v; - function_allocator lockalloc, globalloc; - if (!vec_size(self->locals) && !vec_size(self->values)) + if (self->locals.empty() && self->values.empty()) return true; - globalloc.locals = NULL; - globalloc.sizes = NULL; - globalloc.positions = NULL; - globalloc.unique = NULL; - lockalloc.locals = NULL; - lockalloc.sizes = NULL; - lockalloc.positions = NULL; - lockalloc.unique = NULL; + globalloc.locals = nullptr; + globalloc.sizes = nullptr; + globalloc.positions = nullptr; + globalloc.unique = nullptr; + lockalloc.locals = nullptr; + lockalloc.sizes = nullptr; + lockalloc.positions = nullptr; + lockalloc.unique = nullptr; - for (i = 0; i < vec_size(self->locals); ++i) + size_t i; + for (i = 0; i < self->locals.size(); ++i) { - v = self->locals[i]; + ir_value *v = self->locals[i].get(); if ((self->flags & IR_FLAG_MASK_NO_LOCAL_TEMPS) || !OPTS_OPTIMIZATION(OPTIM_LOCAL_TEMPS)) { v->locked = true; v->unique_life = true; @@ -2232,21 +1992,21 @@ bool ir_function_allocate_locals(ir_function *self) if (!function_allocator_alloc((v->locked || !opt_gt ? &lockalloc : &globalloc), v)) goto error; } - for (; i < vec_size(self->locals); ++i) + for (; i < self->locals.size(); ++i) { - v = self->locals[i]; - if (!vec_size(v->life)) + ir_value *v = self->locals[i].get(); + if (v->life.empty()) continue; if (!ir_function_allocator_assign(self, (v->locked || !opt_gt ? &lockalloc : &globalloc), v)) goto error; } /* Allocate a slot for any value that still exists */ - for (i = 0; i < vec_size(self->values); ++i) + for (i = 0; i < self->values.size(); ++i) { - v = self->values[i]; + ir_value *v = self->values[i].get(); - if (!vec_size(v->life)) + if (v->life.empty()) continue; /* CALL optimization: @@ -2254,16 +2014,16 @@ bool ir_function_allocate_locals(ir_function *self) * and it's not "locked", write it to the OFS_PARM directly. */ if (OPTS_OPTIMIZATION(OPTIM_CALL_STORES) && !v->locked && !v->unique_life) { - if (vec_size(v->reads) == 1 && vec_size(v->writes) == 1 && + if (v->reads.size() == 1 && v->writes.size() == 1 && (v->reads[0]->opcode == VINSTR_NRCALL || (v->reads[0]->opcode >= INSTR_CALL0 && v->reads[0]->opcode <= INSTR_CALL8) ) ) { - size_t param; + size_t param; ir_instr *call = v->reads[0]; if (!vec_ir_value_find(call->params, v, ¶m)) { - irerror(call->context, "internal error: unlocked parameter %s not found", v->name); + irerror(call->context, "internal error: unlocked parameter %s not found", v->name.c_str()); goto error; } ++opts_optimizationcount[OPTIM_CALL_STORES]; @@ -2271,11 +2031,11 @@ bool ir_function_allocate_locals(ir_function *self) if (param < 8) ir_value_code_setaddr(v, OFS_PARM0 + 3*param); else { - size_t nprotos = vec_size(self->owner->extparam_protos); + size_t nprotos = self->owner->extparam_protos.size(); ir_value *ep; param -= 8; if (nprotos > param) - ep = self->owner->extparam_protos[param]; + ep = self->owner->extparam_protos[param].get(); else { ep = ir_gen_extparam_proto(self->owner); @@ -2287,8 +2047,7 @@ bool ir_function_allocate_locals(ir_function *self) } continue; } - if (vec_size(v->writes) == 1 && v->writes[0]->opcode == INSTR_CALL0) - { + if (v->writes.size() == 1 && v->writes[0]->opcode == INSTR_CALL0) { v->store = store_return; if (v->members[0]) v->members[0]->store = store_return; if (v->members[1]) v->members[1]->store = store_return; @@ -2329,20 +2088,18 @@ bool ir_function_allocate_locals(ir_function *self) } /* Locals need to know their new position */ - for (i = 0; i < vec_size(self->locals); ++i) { - v = self->locals[i]; - if (v->locked || !opt_gt) - v->code.local = lockalloc.positions[v->code.local]; + for (auto& local : self->locals) { + if (local->locked || !opt_gt) + local->code.local = lockalloc.positions[local->code.local]; else - v->code.local = globalloc.positions[v->code.local]; + local->code.local = globalloc.positions[local->code.local]; } /* Take over the actual slot positions on values */ - for (i = 0; i < vec_size(self->values); ++i) { - v = self->values[i]; - if (v->locked || !opt_gt) - v->code.local = lockalloc.positions[v->code.local]; + for (auto& value : self->values) { + if (value->locked || !opt_gt) + value->code.local = lockalloc.positions[value->code.local]; else - v->code.local = globalloc.positions[v->code.local]; + value->code.local = globalloc.positions[value->code.local]; } goto cleanup; @@ -2351,9 +2108,9 @@ error: retval = false; cleanup: for (i = 0; i < vec_size(lockalloc.locals); ++i) - ir_value_delete(lockalloc.locals[i]); + delete lockalloc.locals[i]; for (i = 0; i < vec_size(globalloc.locals); ++i) - ir_value_delete(globalloc.locals[i]); + delete globalloc.locals[i]; vec_free(globalloc.unique); vec_free(globalloc.locals); vec_free(globalloc.sizes); @@ -2404,29 +2161,21 @@ static void ir_op_read_write(int op, size_t *read, size_t *write) }; } -static bool ir_block_living_add_instr(ir_block *self, size_t eid) -{ - size_t i; - const size_t vs = vec_size(self->living); - bool changed = false; - for (i = 0; i != vs; ++i) - { - if (ir_value_life_merge(self->living[i], eid)) +static bool ir_block_living_add_instr(ir_block *self, size_t eid) { + bool changed = false; + for (auto &it : self->living) + if (ir_value_life_merge(it, eid)) changed = true; - } return changed; } -static bool ir_block_living_lock(ir_block *self) -{ - size_t i; +static bool ir_block_living_lock(ir_block *self) { bool changed = false; - for (i = 0; i != vec_size(self->living); ++i) - { - if (!self->living[i]->locked) { - self->living[i]->locked = true; - changed = true; - } + for (auto &it : self->living) { + if (it->locked) + continue; + it->locked = true; + changed = true; } return changed; } @@ -2435,24 +2184,18 @@ static bool ir_block_life_propagate(ir_block *self, bool *changed) { ir_instr *instr; ir_value *value; - size_t i, o, p, mem, cnt; - /* bitmasks which operands are read from or written to */ + size_t i, o, p, mem; + // bitmasks which operands are read from or written to size_t read, write; - char dbg_ind[16]; - dbg_ind[0] = '#'; - dbg_ind[1] = '0'; - (void)dbg_ind; - vec_free(self->living); + self->living.clear(); p = vec_size(self->exits); for (i = 0; i < p; ++i) { ir_block *prev = self->exits[i]; - cnt = vec_size(prev->living); - for (o = 0; o < cnt; ++o) { - if (!vec_ir_value_find(self->living, prev->living[o], NULL)) - vec_push(self->living, prev->living[o]); - } + for (auto &it : prev->living) + if (!vec_ir_value_find(self->living, it, nullptr)) + self->living.push_back(it); } i = vec_size(self->instr); @@ -2509,28 +2252,28 @@ static bool ir_block_life_propagate(ir_block *self, bool *changed) */ if (ir_value_life_merge(value, instr->eid)) *changed = true; - /* Then remove */ - vec_remove(self->living, idx, 1); + // Then remove + self->living.erase(self->living.begin() + idx); } /* Removing a vector removes all members */ for (mem = 0; mem < 3; ++mem) { if (value->members[mem] && vec_ir_value_find(self->living, value->members[mem], &idx)) { if (ir_value_life_merge(value->members[mem], instr->eid)) *changed = true; - vec_remove(self->living, idx, 1); + self->living.erase(self->living.begin() + idx); } } /* Removing the last member removes the vector */ if (value->memberof) { value = value->memberof; for (mem = 0; mem < 3; ++mem) { - if (value->members[mem] && vec_ir_value_find(self->living, value->members[mem], NULL)) + if (value->members[mem] && vec_ir_value_find(self->living, value->members[mem], nullptr)) break; } if (mem == 3 && vec_ir_value_find(self->living, value, &idx)) { if (ir_value_life_merge(value, instr->eid)) *changed = true; - vec_remove(self->living, idx, 1); + self->living.erase(self->living.begin() + idx); } } } @@ -2588,29 +2331,28 @@ static bool ir_block_life_propagate(ir_block *self, bool *changed) /* read operands */ if (read & (1<living, value, NULL)) - vec_push(self->living, value); + if (!vec_ir_value_find(self->living, value, nullptr)) + self->living.push_back(value); /* reading adds the full vector */ - if (value->memberof && !vec_ir_value_find(self->living, value->memberof, NULL)) - vec_push(self->living, value->memberof); + if (value->memberof && !vec_ir_value_find(self->living, value->memberof, nullptr)) + self->living.push_back(value->memberof); for (mem = 0; mem < 3; ++mem) { - if (value->members[mem] && !vec_ir_value_find(self->living, value->members[mem], NULL)) - vec_push(self->living, value->members[mem]); + if (value->members[mem] && !vec_ir_value_find(self->living, value->members[mem], nullptr)) + self->living.push_back(value->members[mem]); } } } /* PHI operands are always read operands */ - for (p = 0; p < vec_size(instr->phi); ++p) - { - value = instr->phi[p].value; - if (!vec_ir_value_find(self->living, value, NULL)) - vec_push(self->living, value); + for (auto &it : instr->phi) { + value = it.value; + if (!vec_ir_value_find(self->living, value, nullptr)) + self->living.push_back(value); /* reading adds the full vector */ - if (value->memberof && !vec_ir_value_find(self->living, value->memberof, NULL)) - vec_push(self->living, value->memberof); + if (value->memberof && !vec_ir_value_find(self->living, value->memberof, nullptr)) + self->living.push_back(value->memberof); for (mem = 0; mem < 3; ++mem) { - if (value->members[mem] && !vec_ir_value_find(self->living, value->members[mem], NULL)) - vec_push(self->living, value->members[mem]); + if (value->members[mem] && !vec_ir_value_find(self->living, value->members[mem], nullptr)) + self->living.push_back(value->members[mem]); } } @@ -2620,17 +2362,16 @@ static bool ir_block_life_propagate(ir_block *self, bool *changed) *changed = true; } /* call params are read operands too */ - for (p = 0; p < vec_size(instr->params); ++p) - { - value = instr->params[p]; - if (!vec_ir_value_find(self->living, value, NULL)) - vec_push(self->living, value); + for (auto &it : instr->params) { + value = it; + if (!vec_ir_value_find(self->living, value, nullptr)) + self->living.push_back(value); /* reading adds the full vector */ - if (value->memberof && !vec_ir_value_find(self->living, value->memberof, NULL)) - vec_push(self->living, value->memberof); + if (value->memberof && !vec_ir_value_find(self->living, value->memberof, nullptr)) + self->living.push_back(value->memberof); for (mem = 0; mem < 3; ++mem) { - if (value->members[mem] && !vec_ir_value_find(self->living, value->members[mem], NULL)) - vec_push(self->living, value->members[mem]); + if (value->members[mem] && !vec_ir_value_find(self->living, value->members[mem], nullptr)) + self->living.push_back(value->members[mem]); } } @@ -2647,42 +2388,39 @@ static bool ir_block_life_propagate(ir_block *self, bool *changed) bool ir_function_calculate_liferanges(ir_function *self) { - size_t i, s; - bool changed; - /* parameters live at 0 */ - for (i = 0; i < vec_size(self->params); ++i) - if (!ir_value_life_merge(self->locals[i], 0)) + for (size_t i = 0; i < vec_size(self->params); ++i) + if (!ir_value_life_merge(self->locals[i].get(), 0)) compile_error(self->context, "internal error: failed value-life merging"); + bool changed; do { self->run_id++; changed = false; - i = vec_size(self->blocks); - while (i--) { - ir_block_life_propagate(self->blocks[i], &changed); - } + for (auto i = self->blocks.rbegin(); i != self->blocks.rend(); ++i) + ir_block_life_propagate(i->get(), &changed); } while (changed); - if (vec_size(self->blocks)) { - ir_block *block = self->blocks[0]; - for (i = 0; i < vec_size(block->living); ++i) { - ir_value *v = block->living[i]; + if (self->blocks.size()) { + ir_block *block = self->blocks[0].get(); + for (auto &it : block->living) { + ir_value *v = it; if (v->store != store_local) continue; if (v->vtype == TYPE_VECTOR) continue; self->flags |= IR_FLAG_HAS_UNINITIALIZED; /* find the instruction reading from it */ - for (s = 0; s < vec_size(v->reads); ++s) { + size_t s = 0; + for (; s < v->reads.size(); ++s) { if (v->reads[s]->eid == v->life[0].end) break; } - if (s < vec_size(v->reads)) { + if (s < v->reads.size()) { if (irwarning(v->context, WARN_USED_UNINITIALIZED, "variable `%s` may be used uninitialized in this function\n" " -> %s:%i", - v->name, + v->name.c_str(), v->reads[s]->context.file, v->reads[s]->context.line) ) { @@ -2692,15 +2430,15 @@ bool ir_function_calculate_liferanges(ir_function *self) } if (v->memberof) { ir_value *vec = v->memberof; - for (s = 0; s < vec_size(vec->reads); ++s) { + for (s = 0; s < vec->reads.size(); ++s) { if (vec->reads[s]->eid == v->life[0].end) break; } - if (s < vec_size(vec->reads)) { + if (s < vec->reads.size()) { if (irwarning(v->context, WARN_USED_UNINITIALIZED, "variable `%s` may be used uninitialized in this function\n" " -> %s:%i", - v->name, + v->name.c_str(), vec->reads[s]->context.file, vec->reads[s]->context.line) ) { @@ -2710,7 +2448,7 @@ bool ir_function_calculate_liferanges(ir_function *self) } } if (irwarning(v->context, WARN_USED_UNINITIALIZED, - "variable `%s` may be used uninitialized in this function", v->name)) + "variable `%s` may be used uninitialized in this function", v->name.c_str())) { return false; } @@ -2742,25 +2480,25 @@ static bool gen_global_field(code_t *code, ir_value *global) { ir_value *fld = global->constval.vpointer; if (!fld) { - irerror(global->context, "Invalid field constant with no field: %s", global->name); + irerror(global->context, "Invalid field constant with no field: %s", global->name.c_str()); return false; } /* copy the field's value */ - ir_value_code_setaddr(global, vec_size(code->globals)); - vec_push(code->globals, fld->code.fieldaddr); + ir_value_code_setaddr(global, code->globals.size()); + code->globals.push_back(fld->code.fieldaddr); if (global->fieldtype == TYPE_VECTOR) { - vec_push(code->globals, fld->code.fieldaddr+1); - vec_push(code->globals, fld->code.fieldaddr+2); + code->globals.push_back(fld->code.fieldaddr+1); + code->globals.push_back(fld->code.fieldaddr+2); } } else { - ir_value_code_setaddr(global, vec_size(code->globals)); - vec_push(code->globals, 0); + ir_value_code_setaddr(global, code->globals.size()); + code->globals.push_back(0); if (global->fieldtype == TYPE_VECTOR) { - vec_push(code->globals, 0); - vec_push(code->globals, 0); + code->globals.push_back(0); + code->globals.push_back(0); } } if (global->code.globaladdr < 0) @@ -2774,8 +2512,8 @@ static bool gen_global_pointer(code_t *code, ir_value *global) { ir_value *target = global->constval.vpointer; if (!target) { - irerror(global->context, "Invalid pointer constant: %s", global->name); - /* NULL pointers are pointing to the NULL constant, which also + irerror(global->context, "Invalid pointer constant: %s", global->name.c_str()); + /* nullptr pointers are pointing to the nullptr constant, which also * sits at address 0, but still has an ir_value for itself. */ return false; @@ -2794,13 +2532,13 @@ static bool gen_global_pointer(code_t *code, ir_value *global) return false; } - ir_value_code_setaddr(global, vec_size(code->globals)); - vec_push(code->globals, target->code.globaladdr); + ir_value_code_setaddr(global, code->globals.size()); + code->globals.push_back(target->code.globaladdr); } else { - ir_value_code_setaddr(global, vec_size(code->globals)); - vec_push(code->globals, 0); + ir_value_code_setaddr(global, code->globals.size()); + code->globals.push_back(0); } if (global->code.globaladdr < 0) return false; @@ -2819,7 +2557,7 @@ static bool gen_blocks_recursive(code_t *code, ir_function *func, ir_block *bloc int j; block->generated = true; - block->code_start = vec_size(code->statements); + block->code_start = code->statements.size(); for (i = 0; i < vec_size(block->instr); ++i) { instr = block->instr[i]; @@ -2839,7 +2577,7 @@ static bool gen_blocks_recursive(code_t *code, ir_function *func, ir_block *bloc /* otherwise we generate a jump instruction */ stmt.opcode = INSTR_GOTO; - stmt.o1.s1 = (target->code_start) - vec_size(code->statements); + stmt.o1.s1 = target->code_start - code->statements.size(); stmt.o2.s1 = 0; stmt.o3.s1 = 0; if (stmt.o1.s1 != 1) @@ -3023,13 +2761,13 @@ static bool gen_blocks_recursive(code_t *code, ir_function *func, ir_block *bloc if (ontrue->generated) { stmt.opcode = INSTR_IF; - stmt.o2.s1 = (ontrue->code_start) - vec_size(code->statements); + stmt.o2.s1 = ontrue->code_start - code->statements.size(); if (stmt.o2.s1 != 1) code_push_statement(code, &stmt, instr->context); } if (onfalse->generated) { stmt.opcode = INSTR_IFNOT; - stmt.o2.s1 = (onfalse->code_start) - vec_size(code->statements); + stmt.o2.s1 = onfalse->code_start - code->statements.size(); if (stmt.o2.s1 != 1) code_push_statement(code, &stmt, instr->context); } @@ -3050,24 +2788,24 @@ static bool gen_blocks_recursive(code_t *code, ir_function *func, ir_block *bloc onfalse = ontrue; ontrue = tmp; } - stidx = vec_size(code->statements); + stidx = code->statements.size(); code_push_statement(code, &stmt, instr->context); /* on false we jump, so add ontrue-path */ if (!gen_blocks_recursive(code, func, ontrue)) return false; /* fixup the jump address */ - code->statements[stidx].o2.s1 = vec_size(code->statements) - stidx; + code->statements[stidx].o2.s1 = code->statements.size() - stidx; /* generate onfalse path */ if (onfalse->generated) { /* fixup the jump address */ - code->statements[stidx].o2.s1 = (onfalse->code_start) - (stidx); - if (stidx+2 == vec_size(code->statements) && code->statements[stidx].o2.s1 == 1) { + code->statements[stidx].o2.s1 = onfalse->code_start - stidx; + if (stidx+2 == code->statements.size() && 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(code); } - stmt.opcode = vec_last(code->statements).opcode; + stmt.opcode = code->statements.back().opcode; if (stmt.opcode == INSTR_GOTO || stmt.opcode == INSTR_IF || stmt.opcode == INSTR_IFNOT || @@ -3079,14 +2817,14 @@ static bool gen_blocks_recursive(code_t *code, ir_function *func, ir_block *bloc } /* may have been generated in the previous recursive call */ stmt.opcode = INSTR_GOTO; - stmt.o1.s1 = (onfalse->code_start) - vec_size(code->statements); + stmt.o1.s1 = onfalse->code_start - code->statements.size(); stmt.o2.s1 = 0; stmt.o3.s1 = 0; if (stmt.o1.s1 != 1) code_push_statement(code, &stmt, instr->context); return true; } - else if (stidx+2 == vec_size(code->statements) && code->statements[stidx].o2.s1 == 1) { + else if (stidx+2 == code->statements.size() && 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++; @@ -3102,7 +2840,7 @@ static bool gen_blocks_recursive(code_t *code, ir_function *func, ir_block *bloc size_t p, first; ir_value *retvalue; - first = vec_size(instr->params); + first = instr->params.size(); if (first > 8) first = 8; for (p = 0; p < first; ++p) @@ -3139,7 +2877,7 @@ static bool gen_blocks_recursive(code_t *code, ir_function *func, ir_block *bloc code_push_statement(code, &stmt, instr->context); } /* Now handle extparams */ - first = vec_size(instr->params); + first = instr->params.size(); for (; p < first; ++p) { ir_builder *ir = func->owner; @@ -3149,7 +2887,7 @@ static bool gen_blocks_recursive(code_t *code, ir_function *func, ir_block *bloc if (param->callparam) continue; - if (p-8 >= vec_size(ir->extparams)) + if (p-8 >= ir->extparams.size()) ir_gen_extparam(ir); targetparam = ir->extparams[p-8]; @@ -3181,7 +2919,7 @@ static bool gen_blocks_recursive(code_t *code, ir_function *func, ir_block *bloc code_push_statement(code, &stmt, instr->context); } - stmt.opcode = INSTR_CALL0 + vec_size(instr->params); + stmt.opcode = INSTR_CALL0 + instr->params.size(); if (stmt.opcode > INSTR_CALL8) stmt.opcode = INSTR_CALL8; stmt.o1.u1 = ir_value_code_addr(instr->_ops[1]); @@ -3191,7 +2929,7 @@ static bool gen_blocks_recursive(code_t *code, ir_function *func, ir_block *bloc retvalue = instr->_ops[0]; if (retvalue && retvalue->store != store_return && - (retvalue->store == store_global || vec_size(retvalue->life))) + (retvalue->store == store_global || retvalue->life.size())) { /* not to be kept in OFS_RETURN */ if (retvalue->vtype == TYPE_FIELD && OPTS_FLAG(ADJUST_VECTOR_FIELDS)) @@ -3269,22 +3007,22 @@ static bool gen_function_code(code_t *code, ir_function *self) /* Starting from entry point, we generate blocks "as they come" * for now. Dead blocks will not be translated obviously. */ - if (!vec_size(self->blocks)) { - irerror(self->context, "Function '%s' declared without body.", self->name); + if (self->blocks.empty()) { + irerror(self->context, "Function '%s' declared without body.", self->name.c_str()); return false; } - block = self->blocks[0]; + block = self->blocks[0].get(); if (block->generated) return true; if (!gen_blocks_recursive(code, self, block)) { - irerror(self->context, "failed to generate blocks for '%s'", self->name); + irerror(self->context, "failed to generate blocks for '%s'", self->name.c_str()); return false; } /* code_write and qcvm -disasm need to know that the function ends here */ - retst = &vec_last(code->statements); + retst = &code->statements.back(); if (OPTS_OPTIMIZATION(OPTIM_VOID_RETURN) && self->outtype == TYPE_VOID && retst->opcode == INSTR_RETURN && @@ -3299,8 +3037,8 @@ static bool gen_function_code(code_t *code, ir_function *self) stmt.o1.u1 = 0; stmt.o2.u1 = 0; stmt.o3.u1 = 0; - last.line = vec_last(code->linenums); - last.column = vec_last(code->columnnums); + last.line = code->linenums.back(); + last.column = code->columnnums.back(); code_push_statement(code, &stmt, last); } @@ -3312,17 +3050,16 @@ static qcint_t ir_builder_filestring(ir_builder *ir, const char *filename) /* NOTE: filename pointers are copied, we never strdup them, * thus we can use pointer-comparison to find the string. */ - size_t i; qcint_t str; - for (i = 0; i < vec_size(ir->filenames); ++i) { - if (ir->filenames[i] == filename) - return ir->filestrings[i]; + for (size_t i = 0; i != ir->filenames.size(); ++i) { + if (!strcmp(ir->filenames[i], filename)) + return i; } - str = code_genstring(ir->code, filename); - vec_push(ir->filenames, filename); - vec_push(ir->filestrings, str); + str = code_genstring(ir->code.get(), filename); + ir->filenames.push_back(filename); + ir->filestrings.push_back(str); return str; } @@ -3333,22 +3070,20 @@ static bool gen_global_function(ir_builder *ir, ir_value *global) size_t i; - if (!global->hasvalue || (!global->constval.vfunc)) - { - irerror(global->context, "Invalid state of function-global: not constant: %s", global->name); + if (!global->hasvalue || (!global->constval.vfunc)) { + irerror(global->context, "Invalid state of function-global: not constant: %s", global->name.c_str()); return false; } irfun = global->constval.vfunc; - - fun.name = global->code.name; - fun.file = ir_builder_filestring(ir, global->context.file); + fun.name = global->code.name; + fun.file = ir_builder_filestring(ir, global->context.file); fun.profile = 0; /* always 0 */ - fun.nargs = vec_size(irfun->params); + fun.nargs = vec_size(irfun->params); if (fun.nargs > 8) fun.nargs = 8; - for (i = 0;i < 8; ++i) { + for (i = 0; i < 8; ++i) { if ((int32_t)i >= fun.nargs) fun.argsize[i] = 0; else @@ -3356,28 +3091,27 @@ static bool gen_global_function(ir_builder *ir, ir_value *global) } fun.firstlocal = 0; - fun.locals = irfun->allocated_locals; + fun.locals = irfun->allocated_locals; if (irfun->builtin) fun.entry = irfun->builtin+1; else { - irfun->code_function_def = vec_size(ir->code->functions); - fun.entry = vec_size(ir->code->statements); + irfun->code_function_def = ir->code->functions.size(); + fun.entry = ir->code->statements.size(); } - vec_push(ir->code->functions, fun); + ir->code->functions.push_back(fun); return true; } static ir_value* ir_gen_extparam_proto(ir_builder *ir) { - ir_value *global; char name[128]; - util_snprintf(name, sizeof(name), "EXTPARM#%i", (int)(vec_size(ir->extparam_protos))); - global = ir_value_var(name, store_global, TYPE_VECTOR); + util_snprintf(name, sizeof(name), "EXTPARM#%i", (int)(ir->extparam_protos.size())); + ir_value *global = new ir_value(name, store_global, TYPE_VECTOR); + ir->extparam_protos.emplace_back(global); - vec_push(ir->extparam_protos, global); return global; } @@ -3386,46 +3120,43 @@ static void ir_gen_extparam(ir_builder *ir) prog_section_def_t def; ir_value *global; - if (vec_size(ir->extparam_protos) < vec_size(ir->extparams)+1) + if (ir->extparam_protos.size() < ir->extparams.size()+1) global = ir_gen_extparam_proto(ir); else - global = ir->extparam_protos[vec_size(ir->extparams)]; + global = ir->extparam_protos[ir->extparams.size()].get(); - def.name = code_genstring(ir->code, global->name); - def.type = TYPE_VECTOR; - def.offset = vec_size(ir->code->globals); + def.name = code_genstring(ir->code.get(), global->name.c_str()); + def.type = TYPE_VECTOR; + def.offset = ir->code->globals.size(); - vec_push(ir->code->defs, def); + ir->code->defs.push_back(def); ir_value_code_setaddr(global, def.offset); - vec_push(ir->code->globals, 0); - vec_push(ir->code->globals, 0); - vec_push(ir->code->globals, 0); + ir->code->globals.push_back(0); + ir->code->globals.push_back(0); + ir->code->globals.push_back(0); - vec_push(ir->extparams, global); + ir->extparams.emplace_back(global); } static bool gen_function_extparam_copy(code_t *code, ir_function *self) { - size_t i, ext, numparams; - ir_builder *ir = self->owner; - ir_value *ep; - prog_section_statement_t stmt; - numparams = vec_size(self->params); + size_t numparams = vec_size(self->params); if (!numparams) return true; + prog_section_statement_t stmt; stmt.opcode = INSTR_STORE_F; stmt.o3.s1 = 0; - for (i = 8; i < numparams; ++i) { - ext = i - 8; - if (ext >= vec_size(ir->extparams)) + for (size_t i = 8; i < numparams; ++i) { + size_t ext = i - 8; + if (ext >= ir->extparams.size()) ir_gen_extparam(ir); - ep = ir->extparams[ext]; + ir_value *ep = ir->extparams[ext]; stmt.opcode = type_store_instr[self->locals[i]->vtype]; if (self->locals[i]->vtype == TYPE_FIELD && @@ -3434,7 +3165,7 @@ static bool gen_function_extparam_copy(code_t *code, ir_function *self) stmt.opcode = INSTR_STORE_V; } stmt.o1.u1 = ir_value_code_addr(ep); - stmt.o2.u1 = ir_value_code_addr(self->locals[i]); + stmt.o2.u1 = ir_value_code_addr(self->locals[i].get()); code_push_statement(code, &stmt, self->context); } @@ -3459,18 +3190,18 @@ static bool gen_function_varargs_copy(code_t *code, ir_function *self) for (i = numparams; i < maxparams; ++i) { if (i < 8) { stmt.o1.u1 = OFS_PARM0 + 3*i; - stmt.o2.u1 = ir_value_code_addr(self->locals[i]); + stmt.o2.u1 = ir_value_code_addr(self->locals[i].get()); code_push_statement(code, &stmt, self->context); continue; } ext = i - 8; - while (ext >= vec_size(ir->extparams)) + while (ext >= ir->extparams.size()) ir_gen_extparam(ir); ep = ir->extparams[ext]; stmt.o1.u1 = ir_value_code_addr(ep); - stmt.o2.u1 = ir_value_code_addr(self->locals[i]); + stmt.o2.u1 = ir_value_code_addr(self->locals[i].get()); code_push_statement(code, &stmt, self->context); } @@ -3481,17 +3212,16 @@ static bool gen_function_locals(ir_builder *ir, ir_value *global) { prog_section_function_t *def; ir_function *irfun; - size_t i; uint32_t firstlocal, firstglobal; irfun = global->constval.vfunc; - def = ir->code->functions + irfun->code_function_def; + def = &ir->code->functions[0] + irfun->code_function_def; if (OPTS_OPTION_BOOL(OPTION_G) || !OPTS_OPTIMIZATION(OPTIM_OVERLAP_LOCALS) || (irfun->flags & IR_FLAG_MASK_NO_OVERLAP)) { - firstlocal = def->firstlocal = vec_size(ir->code->globals); + firstlocal = def->firstlocal = ir->code->globals.size(); } else { firstlocal = def->firstlocal = ir->first_common_local; ++opts_optimizationcount[OPTIM_OVERLAP_LOCALS]; @@ -3499,23 +3229,23 @@ static bool gen_function_locals(ir_builder *ir, ir_value *global) firstglobal = (OPTS_OPTIMIZATION(OPTIM_GLOBAL_TEMPS) ? ir->first_common_globaltemp : firstlocal); - for (i = vec_size(ir->code->globals); i < firstlocal + irfun->allocated_locals; ++i) - vec_push(ir->code->globals, 0); - for (i = 0; i < vec_size(irfun->locals); ++i) { - ir_value *v = irfun->locals[i]; + for (size_t i = ir->code->globals.size(); i < firstlocal + irfun->allocated_locals; ++i) + ir->code->globals.push_back(0); + + for (auto& lp : irfun->locals) { + ir_value *v = lp.get(); if (v->locked || !OPTS_OPTIMIZATION(OPTIM_GLOBAL_TEMPS)) { ir_value_code_setaddr(v, firstlocal + v->code.local); - if (!ir_builder_gen_global(ir, irfun->locals[i], true)) { - irerror(irfun->locals[i]->context, "failed to generate local %s", irfun->locals[i]->name); + if (!ir_builder_gen_global(ir, v, true)) { + irerror(v->context, "failed to generate local %s", v->name.c_str()); return false; } } else ir_value_code_setaddr(v, firstglobal + v->code.local); } - for (i = 0; i < vec_size(irfun->values); ++i) - { - ir_value *v = irfun->values[i]; + for (auto& vp : irfun->values) { + ir_value *v = vp.get(); if (v->callparam) continue; if (v->locked) @@ -3538,7 +3268,7 @@ static bool gen_global_function_code(ir_builder *ir, ir_value *global) if (global->cvq == CV_NONE) { if (irwarning(global->context, WARN_IMPLICIT_FUNCTION_POINTER, "function `%s` has no body and in QC implicitly becomes a function-pointer", - global->name)) + global->name.c_str())) { /* Not bailing out just now. If this happens a lot you don't want to have * to rerun gmqcc for each such function. @@ -3563,26 +3293,26 @@ static bool gen_global_function_code(ir_builder *ir, ir_value *global) } if (irfun->code_function_def < 0) { - irerror(irfun->context, "`%s`: IR global wasn't generated, failed to access function-def", irfun->name); + irerror(irfun->context, "`%s`: IR global wasn't generated, failed to access function-def", irfun->name.c_str()); return false; } fundef = &ir->code->functions[irfun->code_function_def]; - fundef->entry = vec_size(ir->code->statements); + fundef->entry = ir->code->statements.size(); if (!gen_function_locals(ir, global)) { - irerror(irfun->context, "Failed to generate locals for function %s", irfun->name); + irerror(irfun->context, "Failed to generate locals for function %s", irfun->name.c_str()); return false; } - if (!gen_function_extparam_copy(ir->code, irfun)) { - irerror(irfun->context, "Failed to generate extparam-copy code for function %s", irfun->name); + if (!gen_function_extparam_copy(ir->code.get(), irfun)) { + irerror(irfun->context, "Failed to generate extparam-copy code for function %s", irfun->name.c_str()); return false; } - if (irfun->max_varargs && !gen_function_varargs_copy(ir->code, irfun)) { - irerror(irfun->context, "Failed to generate vararg-copy code for function %s", irfun->name); + if (irfun->max_varargs && !gen_function_varargs_copy(ir->code.get(), irfun)) { + irerror(irfun->context, "Failed to generate vararg-copy code for function %s", irfun->name.c_str()); return false; } - if (!gen_function_code(ir->code, irfun)) { - irerror(irfun->context, "Failed to generate code for function %s", irfun->name); + if (!gen_function_code(ir->code.get(), irfun)) { + irerror(irfun->context, "Failed to generate code for function %s", irfun->name.c_str()); return false; } return true; @@ -3610,7 +3340,7 @@ static void gen_vector_defs(code_t *code, prog_section_def_t def, const char *na for (i = 0; i < 3; ++i) { def.name = code_genstring(code, component); - vec_push(code->defs, def); + code->defs.push_back(def); def.offset++; component[len-1]++; } @@ -3640,7 +3370,7 @@ static void gen_vector_fields(code_t *code, prog_section_field_t fld, const char for (i = 0; i < 3; ++i) { fld.name = code_genstring(code, component); - vec_push(code->fields, fld); + code->fields.push_back(fld); fld.offset++; component[len-1]++; } @@ -3659,9 +3389,9 @@ static bool ir_builder_gen_global(ir_builder *self, ir_value *global, bool isloc if (global->vtype == TYPE_VECTOR && (global->flags & IR_FLAG_SPLIT_VECTOR)) return true; - def.type = global->vtype; - def.offset = vec_size(self->code->globals); - def.name = 0; + def.type = global->vtype; + def.offset = self->code->globals.size(); + def.name = 0; if (OPTS_OPTION_BOOL(OPTION_G) || !islocal) { pushdef = true; @@ -3670,7 +3400,7 @@ static bool ir_builder_gen_global(ir_builder *self, ir_value *global, bool isloc * if we're eraseable and the function isn't referenced ignore outputting * the function. */ - if (global->flags & IR_FLAG_ERASABLE && vec_size(global->reads) == 0) { + if (global->flags & IR_FLAG_ERASABLE && global->reads.empty()) { return true; } @@ -3684,21 +3414,21 @@ static bool ir_builder_gen_global(ir_builder *self, ir_value *global, bool isloc if (pushdef) { if (global->name[0] == '#') { if (!self->str_immediate) - self->str_immediate = code_genstring(self->code, "IMMEDIATE"); + self->str_immediate = code_genstring(self->code.get(), "IMMEDIATE"); def.name = global->code.name = self->str_immediate; } else - def.name = global->code.name = code_genstring(self->code, global->name); + def.name = global->code.name = code_genstring(self->code.get(), global->name.c_str()); } else def.name = 0; if (islocal) { def.offset = ir_value_code_addr(global); - vec_push(self->code->defs, def); + self->code->defs.push_back(def); if (global->vtype == TYPE_VECTOR) - gen_vector_defs(self->code, def, global->name); + gen_vector_defs(self->code.get(), def, global->name.c_str()); else if (global->vtype == TYPE_FIELD && global->fieldtype == TYPE_VECTOR) - gen_vector_defs(self->code, def, global->name); + gen_vector_defs(self->code.get(), def, global->name.c_str()); return true; } } @@ -3708,17 +3438,15 @@ static bool ir_builder_gen_global(ir_builder *self, ir_value *global, bool isloc switch (global->vtype) { case TYPE_VOID: - if (!strcmp(global->name, "end_sys_globals")) { - /* TODO: remember this point... all the defs before this one - * should be checksummed and added to progdefs.h when we generate it. - */ + if (0 == global->name.compare("end_sys_globals")) { + // TODO: remember this point... all the defs before this one + // should be checksummed and added to progdefs.h when we generate it. } - else if (!strcmp(global->name, "end_sys_fields")) { - /* TODO: same as above but for entity-fields rather than globsl - */ + else if (0 == global->name.compare("end_sys_fields")) { + // TODO: same as above but for entity-fields rather than globsl } else if(irwarning(global->context, WARN_VOID_VARIABLES, "unrecognized variable of type void `%s`", - global->name)) + global->name.c_str())) { /* Not bailing out */ /* return false; */ @@ -3728,108 +3456,108 @@ static bool ir_builder_gen_global(ir_builder *self, ir_value *global, bool isloc * Maybe this could be an -foption * fteqcc creates data for end_sys_* - of size 1, so let's do the same */ - ir_value_code_setaddr(global, vec_size(self->code->globals)); - vec_push(self->code->globals, 0); + ir_value_code_setaddr(global, self->code->globals.size()); + self->code->globals.push_back(0); /* Add the def */ - if (pushdef) vec_push(self->code->defs, def); + if (pushdef) self->code->defs.push_back(def); return true; case TYPE_POINTER: - if (pushdef) vec_push(self->code->defs, def); - return gen_global_pointer(self->code, global); + if (pushdef) self->code->defs.push_back(def); + return gen_global_pointer(self->code.get(), global); case TYPE_FIELD: if (pushdef) { - vec_push(self->code->defs, def); + self->code->defs.push_back(def); if (global->fieldtype == TYPE_VECTOR) - gen_vector_defs(self->code, def, global->name); + gen_vector_defs(self->code.get(), def, global->name.c_str()); } - return gen_global_field(self->code, global); + return gen_global_field(self->code.get(), global); case TYPE_ENTITY: /* fall through */ case TYPE_FLOAT: { - ir_value_code_setaddr(global, vec_size(self->code->globals)); + ir_value_code_setaddr(global, self->code->globals.size()); if (global->hasvalue) { iptr = (int32_t*)&global->constval.ivec[0]; - vec_push(self->code->globals, *iptr); + self->code->globals.push_back(*iptr); } else { - vec_push(self->code->globals, 0); + self->code->globals.push_back(0); } if (!islocal && global->cvq != CV_CONST) def.type |= DEF_SAVEGLOBAL; - if (pushdef) vec_push(self->code->defs, def); + if (pushdef) self->code->defs.push_back(def); return global->code.globaladdr >= 0; } case TYPE_STRING: { - ir_value_code_setaddr(global, vec_size(self->code->globals)); + ir_value_code_setaddr(global, self->code->globals.size()); if (global->hasvalue) { - uint32_t load = code_genstring(self->code, global->constval.vstring); - vec_push(self->code->globals, load); + uint32_t load = code_genstring(self->code.get(), global->constval.vstring); + self->code->globals.push_back(load); } else { - vec_push(self->code->globals, 0); + self->code->globals.push_back(0); } if (!islocal && global->cvq != CV_CONST) def.type |= DEF_SAVEGLOBAL; - if (pushdef) vec_push(self->code->defs, def); + if (pushdef) self->code->defs.push_back(def); return global->code.globaladdr >= 0; } case TYPE_VECTOR: { size_t d; - ir_value_code_setaddr(global, vec_size(self->code->globals)); + ir_value_code_setaddr(global, self->code->globals.size()); if (global->hasvalue) { iptr = (int32_t*)&global->constval.ivec[0]; - vec_push(self->code->globals, iptr[0]); + self->code->globals.push_back(iptr[0]); if (global->code.globaladdr < 0) return false; for (d = 1; d < type_sizeof_[global->vtype]; ++d) { - vec_push(self->code->globals, iptr[d]); + self->code->globals.push_back(iptr[d]); } } else { - vec_push(self->code->globals, 0); + self->code->globals.push_back(0); if (global->code.globaladdr < 0) return false; for (d = 1; d < type_sizeof_[global->vtype]; ++d) { - vec_push(self->code->globals, 0); + self->code->globals.push_back(0); } } if (!islocal && global->cvq != CV_CONST) def.type |= DEF_SAVEGLOBAL; if (pushdef) { - vec_push(self->code->defs, def); + self->code->defs.push_back(def); def.type &= ~DEF_SAVEGLOBAL; - gen_vector_defs(self->code, def, global->name); + gen_vector_defs(self->code.get(), def, global->name.c_str()); } return global->code.globaladdr >= 0; } case TYPE_FUNCTION: - ir_value_code_setaddr(global, vec_size(self->code->globals)); + ir_value_code_setaddr(global, self->code->globals.size()); if (!global->hasvalue) { - vec_push(self->code->globals, 0); + self->code->globals.push_back(0); if (global->code.globaladdr < 0) return false; } else { - vec_push(self->code->globals, vec_size(self->code->functions)); + self->code->globals.push_back(self->code->functions.size()); if (!gen_global_function(self, global)) return false; } if (!islocal && global->cvq != CV_CONST) def.type |= DEF_SAVEGLOBAL; - if (pushdef) vec_push(self->code->defs, def); + if (pushdef) self->code->defs.push_back(def); return true; case TYPE_VARIANT: /* assume biggest type */ - ir_value_code_setaddr(global, vec_size(self->code->globals)); - vec_push(self->code->globals, 0); + ir_value_code_setaddr(global, self->code->globals.size()); + self->code->globals.push_back(0); for (i = 1; i < type_sizeof_[TYPE_VARIANT]; ++i) - vec_push(self->code->globals, 0); + self->code->globals.push_back(0); return true; default: /* refuse to create 'void' type or any other fancy business. */ irerror(global->context, "Invalid type for global variable `%s`: %s", - global->name, type_name[global->vtype]); + global->name.c_str(), type_name[global->vtype]); return false; } } @@ -3847,12 +3575,12 @@ static bool ir_builder_gen_field(ir_builder *self, ir_value *field) (void)self; def.type = (uint16_t)field->vtype; - def.offset = (uint16_t)vec_size(self->code->globals); + def.offset = (uint16_t)self->code->globals.size(); /* create a global named the same as the field */ if (OPTS_OPTION_U32(OPTION_STANDARD) == COMPILER_GMQCC) { /* in our standard, the global gets a dot prefix */ - size_t len = strlen(field->name); + size_t len = field->name.length(); char name[1024]; /* we really don't want to have to allocate this, and 1024 @@ -3864,10 +3592,10 @@ static bool ir_builder_gen_field(ir_builder *self, ir_value *field) } name[0] = '.'; - memcpy(name+1, field->name, len); /* no strncpy - we used strlen above */ + memcpy(name+1, field->name.c_str(), len); // no strncpy - we used strlen above name[len+1] = 0; - def.name = code_genstring(self->code, name); + def.name = code_genstring(self->code.get(), name); fld.name = def.name + 1; /* we reuse that string table entry */ } else { /* in plain QC, there cannot be a global with the same name, @@ -3875,83 +3603,80 @@ static bool ir_builder_gen_field(ir_builder *self, ir_value *field) * FIXME: fteqcc should create a global as well * check if it actually uses the same name. Probably does */ - def.name = code_genstring(self->code, field->name); + def.name = code_genstring(self->code.get(), field->name.c_str()); fld.name = def.name; } field->code.name = def.name; - vec_push(self->code->defs, def); + self->code->defs.push_back(def); fld.type = field->fieldtype; if (fld.type == TYPE_VOID) { - irerror(field->context, "field is missing a type: %s - don't know its size", field->name); + irerror(field->context, "field is missing a type: %s - don't know its size", field->name.c_str()); return false; } fld.offset = field->code.fieldaddr; - vec_push(self->code->fields, fld); + self->code->fields.push_back(fld); - ir_value_code_setaddr(field, vec_size(self->code->globals)); - vec_push(self->code->globals, fld.offset); + ir_value_code_setaddr(field, self->code->globals.size()); + self->code->globals.push_back(fld.offset); if (fld.type == TYPE_VECTOR) { - vec_push(self->code->globals, fld.offset+1); - vec_push(self->code->globals, fld.offset+2); + self->code->globals.push_back(fld.offset+1); + self->code->globals.push_back(fld.offset+2); } if (field->fieldtype == TYPE_VECTOR) { - gen_vector_defs (self->code, def, field->name); - gen_vector_fields(self->code, fld, field->name); + gen_vector_defs (self->code.get(), def, field->name.c_str()); + gen_vector_fields(self->code.get(), fld, field->name.c_str()); } return field->code.globaladdr >= 0; } static void ir_builder_collect_reusables(ir_builder *builder) { - size_t i; - ir_value **reusables = NULL; - for (i = 0; i < vec_size(builder->globals); ++i) { - ir_value *value = builder->globals[i]; + std::vector reusables; + + for (auto& gp : builder->globals) { + ir_value *value = gp.get(); if (value->vtype != TYPE_FLOAT || !value->hasvalue) continue; - if (value->cvq == CV_CONST || (value->name && value->name[0] == '#')) { - vec_push(reusables, value); - } + if (value->cvq == CV_CONST || (value->name.length() >= 1 && value->name[0] == '#')) + reusables.emplace_back(value); } - builder->const_floats = reusables; + builder->const_floats = move(reusables); } static void ir_builder_split_vector(ir_builder *self, ir_value *vec) { - size_t i, count; - ir_value* found[3] = { NULL, NULL, NULL }; + ir_value* found[3] = { nullptr, nullptr, nullptr }; - /* must not be written to */ - if (vec_size(vec->writes)) + // must not be written to + if (vec->writes.size()) return; - /* must not be trying to access individual members */ + // must not be trying to access individual members if (vec->members[0] || vec->members[1] || vec->members[2]) return; - /* should be actually used otherwise it won't be generated anyway */ - count = vec_size(vec->reads); - if (!count) + // should be actually used otherwise it won't be generated anyway + if (vec->reads.empty()) return; + //size_t count = vec->reads.size(); + //if (!count) + // return; - /* may only be used directly as function parameters, so if we find some other instruction cancel */ - for (i = 0; i != count; ++i) { - /* we only split vectors if they're used directly as parameter to a call only! */ - ir_instr *user = vec->reads[i]; + // may only be used directly as function parameters, so if we find some other instruction cancel + for (ir_instr *user : vec->reads) { + // we only split vectors if they're used directly as parameter to a call only! if ((user->opcode < INSTR_CALL0 || user->opcode > INSTR_CALL8) && user->opcode != VINSTR_NRCALL) return; } vec->flags |= IR_FLAG_SPLIT_VECTOR; - /* find existing floats making up the split */ - count = vec_size(self->const_floats); - for (i = 0; i != count; ++i) { - ir_value *c = self->const_floats[i]; + // find existing floats making up the split + for (ir_value *c : self->const_floats) { if (!found[0] && c->constval.vfloat == vec->constval.vvec.x) found[0] = c; if (!found[1] && c->constval.vfloat == vec->constval.vvec.y) @@ -3962,7 +3687,7 @@ static void ir_builder_split_vector(ir_builder *self, ir_value *vec) { break; } - /* generate floats for not yet found components */ + // generate floats for not yet found components if (!found[0]) found[0] = ir_builder_imm_float(self, vec->constval.vvec.x, true); if (!found[1]) { @@ -3980,54 +3705,51 @@ static void ir_builder_split_vector(ir_builder *self, ir_value *vec) { found[2] = ir_builder_imm_float(self, vec->constval.vvec.z, true); } - /* the .members array should be safe to use here. */ + // the .members array should be safe to use here vec->members[0] = found[0]; vec->members[1] = found[1]; vec->members[2] = found[2]; - /* register the readers for these floats */ - count = vec_size(vec->reads); - for (i = 0; i != count; ++i) { - vec_push(found[0]->reads, vec->reads[i]); - vec_push(found[1]->reads, vec->reads[i]); - vec_push(found[2]->reads, vec->reads[i]); - } + // register the readers for these floats + found[0]->reads.insert(found[0]->reads.end(), vec->reads.begin(), vec->reads.end()); + found[1]->reads.insert(found[1]->reads.end(), vec->reads.begin(), vec->reads.end()); + found[2]->reads.insert(found[2]->reads.end(), vec->reads.begin(), vec->reads.end()); } static void ir_builder_split_vectors(ir_builder *self) { - size_t i, count = vec_size(self->globals); - for (i = 0; i != count; ++i) { - ir_value *v = self->globals[i]; - if (v->vtype != TYPE_VECTOR || !v->name || v->name[0] != '#') + // member values may be added to self->globals during this operation, but + // no new vectors will be added, we need to iterate via an index as + // c++ iterators would be invalidated + const size_t count = self->globals.size(); + for (size_t i = 0; i != count; ++i) { + ir_value *v = self->globals[i].get(); + if (v->vtype != TYPE_VECTOR || !v->name.length() || v->name[0] != '#') continue; - ir_builder_split_vector(self, self->globals[i]); + ir_builder_split_vector(self, v); } } bool ir_builder_generate(ir_builder *self, const char *filename) { prog_section_statement_t stmt; - size_t i; - char *lnofile = NULL; + char *lnofile = nullptr; if (OPTS_FLAG(SPLIT_VECTOR_PARAMETERS)) { ir_builder_collect_reusables(self); - if (vec_size(self->const_floats) > 0) + if (!self->const_floats.empty()) ir_builder_split_vectors(self); } - for (i = 0; i < vec_size(self->fields); ++i) - { - ir_builder_prepare_field(self->code, self->fields[i]); - } + for (auto& fp : self->fields) + ir_builder_prepare_field(self->code.get(), fp.get()); - for (i = 0; i < vec_size(self->globals); ++i) - { - if (!ir_builder_gen_global(self, self->globals[i], false)) { + for (auto& gp : self->globals) { + ir_value *global = gp.get(); + if (!ir_builder_gen_global(self, global, false)) { return false; } - if (self->globals[i]->vtype == TYPE_FUNCTION) { - ir_function *func = self->globals[i]->constval.vfunc; + if (global->vtype == TYPE_FUNCTION) { + ir_function *func = global->constval.vfunc; if (func && self->max_locals < func->allocated_locals && !(func->flags & IR_FLAG_MASK_NO_OVERLAP)) { @@ -4038,55 +3760,60 @@ bool ir_builder_generate(ir_builder *self, const char *filename) } } - for (i = 0; i < vec_size(self->fields); ++i) - { - if (!ir_builder_gen_field(self, self->fields[i])) { + for (auto& fp : self->fields) { + if (!ir_builder_gen_field(self, fp.get())) return false; - } - } - - /* generate nil */ - ir_value_code_setaddr(self->nil, vec_size(self->code->globals)); - vec_push(self->code->globals, 0); - vec_push(self->code->globals, 0); - vec_push(self->code->globals, 0); - - /* generate virtual-instruction temps */ - for (i = 0; i < IR_MAX_VINSTR_TEMPS; ++i) { - ir_value_code_setaddr(self->vinstr_temp[i], vec_size(self->code->globals)); - vec_push(self->code->globals, 0); - vec_push(self->code->globals, 0); - vec_push(self->code->globals, 0); - } - - /* generate global temps */ - self->first_common_globaltemp = vec_size(self->code->globals); - for (i = 0; i < self->max_globaltemps; ++i) { - vec_push(self->code->globals, 0); - } - /* generate common locals */ - self->first_common_local = vec_size(self->code->globals); - for (i = 0; i < self->max_locals; ++i) { - vec_push(self->code->globals, 0); } - /* generate function code */ - for (i = 0; i < vec_size(self->globals); ++i) - { - if (self->globals[i]->vtype == TYPE_FUNCTION) { - if (!gen_global_function_code(self, self->globals[i])) { + // generate nil + ir_value_code_setaddr(self->nil, self->code->globals.size()); + self->code->globals.push_back(0); + self->code->globals.push_back(0); + self->code->globals.push_back(0); + + // generate virtual-instruction temps + for (size_t i = 0; i < IR_MAX_VINSTR_TEMPS; ++i) { + ir_value_code_setaddr(self->vinstr_temp[i], self->code->globals.size()); + self->code->globals.push_back(0); + self->code->globals.push_back(0); + self->code->globals.push_back(0); + } + + // generate global temps + self->first_common_globaltemp = self->code->globals.size(); + self->code->globals.insert(self->code->globals.end(), self->max_globaltemps, 0); + // FIXME:DELME: + //for (size_t i = 0; i < self->max_globaltemps; ++i) { + // self->code->globals.push_back(0); + //} + // generate common locals + self->first_common_local = self->code->globals.size(); + self->code->globals.insert(self->code->globals.end(), self->max_locals, 0); + // FIXME:DELME: + //for (i = 0; i < self->max_locals; ++i) { + // self->code->globals.push_back(0); + //} + + // generate function code + + for (auto& gp : self->globals) { + ir_value *global = gp.get(); + if (global->vtype == TYPE_FUNCTION) { + if (!gen_global_function_code(self, global)) { return false; } } } - if (vec_size(self->code->globals) >= 65536) { - irerror(vec_last(self->globals)->context, "This progs file would require more globals than the metadata can handle (%u). Bailing out.", (unsigned int)vec_size(self->code->globals)); + if (self->code->globals.size() >= 65536) { + irerror(self->globals.back()->context, + "This progs file would require more globals than the metadata can handle (%zu). Bailing out.", + self->code->globals.size()); return false; } /* DP errors if the last instruction is not an INSTR_DONE. */ - if (vec_last(self->code->statements).opcode != INSTR_DONE) + if (self->code->statements.back().opcode != INSTR_DONE) { lex_ctx_t last; @@ -4094,19 +3821,19 @@ bool ir_builder_generate(ir_builder *self, const char *filename) stmt.o1.u1 = 0; stmt.o2.u1 = 0; stmt.o3.u1 = 0; - last.line = vec_last(self->code->linenums); - last.column = vec_last(self->code->columnnums); + last.line = self->code->linenums.back(); + last.column = self->code->columnnums.back(); - code_push_statement(self->code, &stmt, last); + code_push_statement(self->code.get(), &stmt, last); } if (OPTS_OPTION_BOOL(OPTION_PP_ONLY)) return true; - if (vec_size(self->code->statements) != vec_size(self->code->linenums)) { + if (self->code->statements.size() != self->code->linenums.size()) { con_err("Linecounter wrong: %lu != %lu\n", - (unsigned long)vec_size(self->code->statements), - (unsigned long)vec_size(self->code->linenums)); + self->code->statements.size(), + self->code->linenums.size()); } else if (OPTS_FLAG(LNO)) { char *dot; size_t filelen = strlen(filename); @@ -4121,7 +3848,7 @@ bool ir_builder_generate(ir_builder *self, const char *filename) memcpy(vec_add(lnofile, 5), ".lno", 5); } - if (!code_write(self->code, filename, lnofile)) { + if (!code_write(self->code.get(), filename, lnofile)) { vec_free(lnofile); return false; } @@ -4167,18 +3894,18 @@ void ir_builder_dump(ir_builder *b, int (*oprintf)(const char*, ...)) indent[0] = '\t'; indent[1] = 0; - oprintf("module %s\n", b->name); - for (i = 0; i < vec_size(b->globals); ++i) + oprintf("module %s\n", b->name.c_str()); + for (i = 0; i < b->globals.size(); ++i) { oprintf("global "); if (b->globals[i]->hasvalue) - oprintf("%s = ", b->globals[i]->name); - ir_value_dump(b->globals[i], oprintf); + oprintf("%s = ", b->globals[i]->name.c_str()); + ir_value_dump(b->globals[i].get(), oprintf); oprintf("\n"); } - for (i = 0; i < vec_size(b->functions); ++i) - ir_function_dump(b->functions[i], indent, oprintf); - oprintf("endmodule %s\n", b->name); + for (i = 0; i < b->functions.size(); ++i) + ir_function_dump(b->functions[i].get(), indent, oprintf); + oprintf("endmodule %s\n", b->name.c_str()); } static const char *storenames[] = { @@ -4190,38 +3917,38 @@ void ir_function_dump(ir_function *f, char *ind, { size_t i; if (f->builtin != 0) { - oprintf("%sfunction %s = builtin %i\n", ind, f->name, -f->builtin); + oprintf("%sfunction %s = builtin %i\n", ind, f->name.c_str(), -f->builtin); return; } - oprintf("%sfunction %s\n", ind, f->name); + oprintf("%sfunction %s\n", ind, f->name.c_str()); util_strncat(ind, "\t", IND_BUFSZ-1); - if (vec_size(f->locals)) + if (f->locals.size()) { - oprintf("%s%i locals:\n", ind, (int)vec_size(f->locals)); - for (i = 0; i < vec_size(f->locals); ++i) { + oprintf("%s%i locals:\n", ind, (int)f->locals.size()); + for (i = 0; i < f->locals.size(); ++i) { oprintf("%s\t", ind); - ir_value_dump(f->locals[i], oprintf); + ir_value_dump(f->locals[i].get(), oprintf); oprintf("\n"); } } oprintf("%sliferanges:\n", ind); - for (i = 0; i < vec_size(f->locals); ++i) { + for (i = 0; i < f->locals.size(); ++i) { const char *attr = ""; size_t l, m; - ir_value *v = f->locals[i]; + ir_value *v = f->locals[i].get(); if (v->unique_life && v->locked) attr = "unique,locked "; else if (v->unique_life) attr = "unique "; else if (v->locked) attr = "locked "; - oprintf("%s\t%s: %s %s %s%s@%i ", ind, v->name, type_name[v->vtype], + oprintf("%s\t%s: %s %s %s%s@%i ", ind, v->name.c_str(), type_name[v->vtype], storenames[v->store], attr, (v->callparam ? "callparam " : ""), (int)v->code.local); - if (!v->life) + if (v->life.empty()) oprintf("[null]"); - for (l = 0; l < vec_size(v->life); ++l) { + for (l = 0; l < v->life.size(); ++l) { oprintf("[%i,%i] ", v->life[l].start, v->life[l].end); } oprintf("\n"); @@ -4229,30 +3956,30 @@ void ir_function_dump(ir_function *f, char *ind, ir_value *vm = v->members[m]; if (!vm) continue; - oprintf("%s\t%s: @%i ", ind, vm->name, (int)vm->code.local); - for (l = 0; l < vec_size(vm->life); ++l) { + oprintf("%s\t%s: @%i ", ind, vm->name.c_str(), (int)vm->code.local); + for (l = 0; l < vm->life.size(); ++l) { oprintf("[%i,%i] ", vm->life[l].start, vm->life[l].end); } oprintf("\n"); } } - for (i = 0; i < vec_size(f->values); ++i) { + for (i = 0; i < f->values.size(); ++i) { const char *attr = ""; size_t l, m; - ir_value *v = f->values[i]; + ir_value *v = f->values[i].get(); if (v->unique_life && v->locked) attr = "unique,locked "; else if (v->unique_life) attr = "unique "; else if (v->locked) attr = "locked "; - oprintf("%s\t%s: %s %s %s%s@%i ", ind, v->name, type_name[v->vtype], + oprintf("%s\t%s: %s %s %s%s@%i ", ind, v->name.c_str(), type_name[v->vtype], storenames[v->store], attr, (v->callparam ? "callparam " : ""), (int)v->code.local); - if (!v->life) + if (v->life.empty()) oprintf("[null]"); - for (l = 0; l < vec_size(v->life); ++l) { + for (l = 0; l < v->life.size(); ++l) { oprintf("[%i,%i] ", v->life[l].start, v->life[l].end); } oprintf("\n"); @@ -4266,30 +3993,30 @@ void ir_function_dump(ir_function *f, char *ind, attr = "unique "; else if (vm->locked) attr = "locked "; - oprintf("%s\t%s: %s@%i ", ind, vm->name, attr, (int)vm->code.local); - for (l = 0; l < vec_size(vm->life); ++l) { + oprintf("%s\t%s: %s@%i ", ind, vm->name.c_str(), attr, (int)vm->code.local); + for (l = 0; l < vm->life.size(); ++l) { oprintf("[%i,%i] ", vm->life[l].start, vm->life[l].end); } oprintf("\n"); } } - if (vec_size(f->blocks)) + if (f->blocks.size()) { oprintf("%slife passes: %i\n", ind, (int)f->run_id); - for (i = 0; i < vec_size(f->blocks); ++i) { - ir_block_dump(f->blocks[i], ind, oprintf); + for (i = 0; i < f->blocks.size(); ++i) { + ir_block_dump(f->blocks[i].get(), ind, oprintf); } } ind[strlen(ind)-1] = 0; - oprintf("%sendfunction %s\n", ind, f->name); + oprintf("%sendfunction %s\n", ind, f->name.c_str()); } void ir_block_dump(ir_block* b, char *ind, int (*oprintf)(const char*, ...)) { size_t i; - oprintf("%s:%s\n", ind, b->label); + oprintf("%s:%s\n", ind, b->label.c_str()); util_strncat(ind, "\t", IND_BUFSZ-1); if (b->instr && b->instr[0]) @@ -4301,12 +4028,10 @@ void ir_block_dump(ir_block* b, char *ind, static void dump_phi(ir_instr *in, int (*oprintf)(const char*, ...)) { - size_t i; - oprintf("%s <- phi ", in->_ops[0]->name); - for (i = 0; i < vec_size(in->phi); ++i) - { - oprintf("([%s] : %s) ", in->phi[i].from->label, - in->phi[i].value->name); + oprintf("%s <- phi ", in->_ops[0]->name.c_str()); + for (auto &it : in->phi) { + oprintf("([%s] : %s) ", it.from->label.c_str(), + it.value->name.c_str()); } oprintf("\n"); } @@ -4315,7 +4040,7 @@ void ir_instr_dump(ir_instr *in, char *ind, int (*oprintf)(const char*, ...)) { size_t i; - const char *comma = NULL; + const char *comma = nullptr; oprintf("%s (%i) ", ind, (int)in->eid); @@ -4332,7 +4057,7 @@ void ir_instr_dump(ir_instr *in, char *ind, oprintf(" <- "); } if (in->opcode == INSTR_CALL0 || in->opcode == VINSTR_NRCALL) { - oprintf("CALL%i\t", vec_size(in->params)); + oprintf("CALL%i\t", in->params.size()); } else oprintf("%s\t", qc_opname(in->opcode)); @@ -4354,16 +4079,15 @@ void ir_instr_dump(ir_instr *in, char *ind, if (in->bops[0]) { if (comma) oprintf(comma); - oprintf("[%s]", in->bops[0]->label); + oprintf("[%s]", in->bops[0]->label.c_str()); comma = ",\t"; } if (in->bops[1]) - oprintf("%s[%s]", comma, in->bops[1]->label); - if (vec_size(in->params)) { + oprintf("%s[%s]", comma, in->bops[1]->label.c_str()); + if (in->params.size()) { oprintf("\tparams: "); - for (i = 0; i != vec_size(in->params); ++i) { - oprintf("%s, ", in->params[i]->name); - } + for (auto &it : in->params) + oprintf("%s, ", it->name.c_str()); } oprintf("\n"); ind[strlen(ind)-1] = 0; @@ -4398,7 +4122,7 @@ void ir_value_dump(ir_value* v, int (*oprintf)(const char*, ...)) oprintf("(void)"); break; case TYPE_FUNCTION: - oprintf("fn:%s", v->name); + oprintf("fn:%s", v->name.c_str()); break; case TYPE_FLOAT: oprintf("%g", v->constval.vfloat); @@ -4422,19 +4146,18 @@ void ir_value_dump(ir_value* v, int (*oprintf)(const char*, ...)) #endif case TYPE_POINTER: oprintf("&%s", - v->constval.vpointer->name); + v->constval.vpointer->name.c_str()); break; } } else { - oprintf("%s", v->name); + oprintf("%s", v->name.c_str()); } } void ir_value_dump_life(const ir_value *self, int (*oprintf)(const char*,...)) { - size_t i; - oprintf("Life of %12s:", self->name); - for (i = 0; i < vec_size(self->life); ++i) + oprintf("Life of %12s:", self->name.c_str()); + for (size_t i = 0; i < self->life.size(); ++i) { oprintf(" + [%i, %i]\n", self->life[i].start, self->life[i].end); }