From: Wolfgang Bumiller Date: Tue, 20 Jan 2015 19:25:56 +0000 (+0100) Subject: more c++ migration for ast/ir/code; reached a working condition here X-Git-Tag: xonotic-v0.8.2~23 X-Git-Url: https://git.xonotic.org/?p=xonotic%2Fgmqcc.git;a=commitdiff_plain;h=566e7615466c776fc296b67894621a85691cd42b;hp=f09c6a5d63faaad1b915868c461b658efd374a34 more c++ migration for ast/ir/code; reached a working condition here --- diff --git a/algo.h b/algo.h new file mode 100644 index 0000000..3218b1b --- /dev/null +++ b/algo.h @@ -0,0 +1,18 @@ +#ifndef GMQCC_ALGO_HDR +#define GMQCC_ALGO_HDR + +namespace algo { + +template +void shiftback(ITER element, ITER end) { + //typename ITER::value_type backup(move(*element)); // hold the element + typename std::remove_reference::type backup(move(*element)); // hold the element + ITER p = element++; + for (; element != end; p = element++) + *p = move(*element); + *p = move(backup); +} + +} // ::algo + +#endif diff --git a/ast.cpp b/ast.cpp index c2c3b47..7f87bc0 100644 --- a/ast.cpp +++ b/ast.cpp @@ -8,6 +8,8 @@ #include "fold.h" //#include "parser.h" +#include "algo.h" + #define ast_instantiate(T, ctx, destroyfn) \ T* self = (T*)mem_a(sizeof(T)); \ if (!self) { \ @@ -387,6 +389,7 @@ void ast_value_delete(ast_value* self) } ast_expression_delete((ast_expression*)self); + self->~ast_value(); mem_d(self); } @@ -1211,8 +1214,9 @@ void ast_function_delete(ast_function *self) } for (auto &it : self->static_names) mem_d(it); - for (auto &it : self->blocks) - ast_delete(it); + // FIXME::DELME:: unique_ptr used on ast_block + //for (auto &it : self->blocks) + // ast_delete(it); if (self->varargs) ast_delete(self->varargs); if (self->argc) @@ -1844,7 +1848,7 @@ bool ast_function_codegen(ast_function *self, ir_builder *ir) for (auto &it : self->blocks) { cgen = it->codegen; - if (!(*cgen)((ast_expression*)it, self, false, &dummy)) + if (!(*cgen)(it.get(), self, false, &dummy)) return false; } @@ -2105,8 +2109,12 @@ bool ast_binary_codegen(ast_binary *self, ast_function *func, bool lvalue, ir_va if (!ir_block_create_jump(func->curblock, ast_ctx(self), merge)) return false; - func->ir_func->blocks.erase(func->ir_func->blocks.begin() + merge_id); - func->ir_func->blocks.emplace_back(merge); + algo::shiftback(func->ir_func->blocks.begin() + merge_id, + func->ir_func->blocks.end()); + // FIXME::DELME:: + //func->ir_func->blocks[merge_id].release(); + //func->ir_func->blocks.erase(func->ir_func->blocks.begin() + merge_id); + //func->ir_func->blocks.emplace_back(merge); func->curblock = merge; phi = ir_block_create_phi(func->curblock, ast_ctx(self), @@ -3011,8 +3019,12 @@ bool ast_loop_codegen(ast_loop *self, ast_function *func, bool lvalue, ir_value } /* Move 'bout' to the end */ - func->ir_func->blocks.erase(func->ir_func->blocks.begin() + bout_id); - func->ir_func->blocks.emplace_back(bout); + algo::shiftback(func->ir_func->blocks.begin() + bout_id, + func->ir_func->blocks.end()); + // FIXME::DELME:: + //func->ir_func->blocks[bout_id].release(); // it's a vector> + //func->ir_func->blocks.erase(func->ir_func->blocks.begin() + bout_id); + //func->ir_func->blocks.emplace_back(bout); return true; } @@ -3151,8 +3163,12 @@ bool ast_switch_codegen(ast_switch *self, ast_function *func, bool lvalue, ir_va /* enter the else and move it down */ func->curblock = bnot; - func->ir_func->blocks.erase(func->ir_func->blocks.begin() + bnot_id); - func->ir_func->blocks.emplace_back(bnot); + algo::shiftback(func->ir_func->blocks.begin() + bnot_id, + func->ir_func->blocks.end()); + // FIXME::DELME:: + //func->ir_func->blocks[bnot_id].release(); + //func->ir_func->blocks.erase(func->ir_func->blocks.begin() + bnot_id); + //func->ir_func->blocks.emplace_back(bnot); } else { /* The default case */ /* Remember where to fall through from: */ @@ -3209,8 +3225,12 @@ bool ast_switch_codegen(ast_switch *self, ast_function *func, bool lvalue, ir_va func->breakblocks.pop_back(); /* Move 'bout' to the end, it's nicer */ - func->ir_func->blocks.erase(func->ir_func->blocks.begin() + bout_id); - func->ir_func->blocks.emplace_back(bout); + algo::shiftback(func->ir_func->blocks.begin() + bout_id, + func->ir_func->blocks.end()); + // FIXME::DELME:: + //func->ir_func->blocks[bout_id].release(); + //func->ir_func->blocks.erase(func->ir_func->blocks.begin() + bout_id); + //func->ir_func->blocks.emplace_back(bout); return true; } diff --git a/ast.h b/ast.h index 65abffd..eeedfcc 100644 --- a/ast.h +++ b/ast.h @@ -626,7 +626,7 @@ struct ast_function * here to use in ast_function_label. */ char labelbuf[64]; - std::vector blocks; + std::vector> blocks; ast_value *varargs; ast_value *argc; ast_value *fixedparams; diff --git a/code.cpp b/code.cpp index 2f55535..645ad25 100644 --- a/code.cpp +++ b/code.cpp @@ -106,35 +106,39 @@ void code_pop_statement(code_t *code) code->columnnums.pop_back(); } -code_t *code_init() { +void *code_t::operator new(std::size_t bytes) { + return mem_a(bytes); +} + +void code_t::operator delete(void *ptr) { + mem_d(ptr); +} + +code_t::code_t() +{ static lex_ctx_t empty_ctx = {0, 0, 0}; static prog_section_function_t empty_function = {0,0,0,0,0,0,0,{0,0,0,0,0,0,0,0}}; static prog_section_statement_t empty_statement = {0,{0},{0},{0}}; static prog_section_def_t empty_def = {0, 0, 0}; - code_t *code = (code_t*)mem_a(sizeof(code_t)); - int i = 0; + string_cache = util_htnew(OPTS_OPTIMIZATION(OPTIM_OVERLAP_STRINGS) ? 0x100 : 1024); - memset(code, 0, sizeof(code_t)); - code->entfields = 0; - code->string_cache = util_htnew(OPTS_OPTIMIZATION(OPTIM_OVERLAP_STRINGS) ? 0x100 : 1024); + // The way progs.dat is suppose to work is odd, there needs to be + // some null (empty) statements, functions, and 28 globals + globals.insert(globals.begin(), 28, 0); - /* - * The way progs.dat is suppose to work is odd, there needs to be - * some null (empty) statements, functions, and 28 globals - */ - for(; i < 28; i++) - code->globals.push_back(0); + chars.push_back('\0'); + functions.push_back(empty_function); - code->chars.push_back('\0'); - code->functions.push_back(empty_function); + code_push_statement(this, &empty_statement, empty_ctx); - code_push_statement(code, &empty_statement, empty_ctx); - - code->defs.push_back(empty_def); - code->fields.push_back(empty_def); + defs.push_back(empty_def); + fields.push_back(empty_def); +} - return code; +code_t::~code_t() +{ + util_htdel(string_cache); } void *code_util_str_htgeth(hash_table_t *ht, const char *key, size_t bin); @@ -342,8 +346,3 @@ bool code_write(code_t *code, const char *filename, const char *lnofile) { code_stats(filename, lnofile, code, &code_header); return true; } - -void code_cleanup(code_t *code) { - util_htdel(code->string_cache); - mem_d(code); -} diff --git a/gmqcc.h b/gmqcc.h index 1c18959..88cf7ff 100644 --- a/gmqcc.h +++ b/gmqcc.h @@ -502,6 +502,10 @@ typedef int32_t qcint_t; typedef uint32_t qcuint_t; struct code_t { + void* operator new(std::size_t); + void operator delete(void*); + code_t(); + ~code_t(); std::vector statements; std::vector linenums; std::vector columnnums; @@ -510,10 +514,10 @@ struct code_t { std::vector functions; std::vector globals; std::vector chars; - uint16_t crc; - uint32_t entfields; + uint16_t crc = 0; + uint32_t entfields = 0; ht string_cache; - qcint_t string_cached_empty; + qcint_t string_cached_empty = 0; }; /* diff --git a/intrin.cpp b/intrin.cpp index 793cd7f..ebdacd9 100644 --- a/intrin.cpp +++ b/intrin.cpp @@ -80,7 +80,7 @@ ast_expression *intrin::isfinite_() { ) ); - func->blocks.push_back(block); + func->blocks.emplace_back(block); reg(val, func); return (ast_expression*)val;; @@ -125,7 +125,7 @@ ast_expression *intrin::isinf_() { ); val->type_params.push_back(x); - func->blocks.push_back(body); + func->blocks.emplace_back(body); reg(val, func); @@ -170,7 +170,7 @@ ast_expression *intrin::isnan_() { ); val->type_params.push_back(arg1); - func->blocks.push_back(body); + func->blocks.emplace_back(body); reg(val, func); @@ -200,7 +200,7 @@ ast_expression *intrin::isnormal_() { ) ); - func->blocks.push_back(body); + func->blocks.emplace_back(body); reg(val, func); return (ast_expression*)val; } @@ -236,7 +236,7 @@ ast_expression *intrin::signbit_() { ) ); - func->blocks.push_back(body); + func->blocks.emplace_back(body); reg(val, func); return (ast_expression*)val; } @@ -289,7 +289,7 @@ ast_expression *intrin::acosh_() { ) ); - func->blocks.push_back(body); + func->blocks.emplace_back(body); reg(val, func); return (ast_expression*)val; } @@ -342,7 +342,7 @@ ast_expression *intrin::asinh_() { ) ); - func->blocks.push_back(body); + func->blocks.emplace_back(body); reg(val, func); return (ast_expression*)val; } @@ -391,7 +391,7 @@ ast_expression *intrin::atanh_() { ) ); - func->blocks.push_back(body); + func->blocks.emplace_back(body); reg(val, func); return (ast_expression*)val; } @@ -504,7 +504,7 @@ ast_expression *intrin::exp_() { ) ); - func->blocks.push_back(body); + func->blocks.emplace_back(body); reg(val, func); return (ast_expression*)val; } @@ -534,7 +534,7 @@ ast_expression *intrin::exp2_() { ) ); - func->blocks.push_back(body); + func->blocks.emplace_back(body); reg(val, func); return (ast_expression*)val; } @@ -569,7 +569,7 @@ ast_expression *intrin::expm1_() { ) ); - func->blocks.push_back(body); + func->blocks.emplace_back(body); reg(val, func); return (ast_expression*)val; } @@ -1014,7 +1014,7 @@ ast_expression *intrin::pow_() { ); /* } */ - func->blocks.push_back(body); + func->blocks.emplace_back(body); reg(val, func); return (ast_expression*)val; } @@ -1110,7 +1110,7 @@ ast_expression *intrin::mod_() { ) ); - func->blocks.push_back(body); + func->blocks.emplace_back(body); reg(val, func); return (ast_expression*)val; } @@ -1149,7 +1149,7 @@ ast_expression *intrin::fabs_() { val->type_params.push_back(arg1); - func->blocks.push_back(body); + func->blocks.emplace_back(body); reg(val, func); return (ast_expression*)val; } @@ -1221,7 +1221,7 @@ ast_expression *intrin::epsilon_() { ) ); - func->blocks.push_back(body); + func->blocks.emplace_back(body); reg(val, func); return (ast_expression*)val; } @@ -1261,7 +1261,7 @@ ast_expression *intrin::nan_() { ) ); - func->blocks.push_back(block); + func->blocks.emplace_back(block); reg(val, func); return (ast_expression*)val; } @@ -1308,7 +1308,7 @@ ast_expression *intrin::inf_() { ) ); - func->blocks.push_back(block); + func->blocks.emplace_back(block); reg(val, func); return (ast_expression*)val; } @@ -1852,7 +1852,7 @@ ast_expression *intrin::ln_() { ) ); - func->blocks.push_back(block); + func->blocks.emplace_back(block); reg(val, func); return (ast_expression*)val; } @@ -1876,7 +1876,7 @@ ast_expression *intrin::log_variant(const char *name, float base) { ) ); - func->blocks.push_back(body); + func->blocks.emplace_back(body); reg(val, func); return (ast_expression*)val; } @@ -1933,7 +1933,7 @@ ast_expression *intrin::shift_variant(const char *name, size_t instr) { ) ); - func->blocks.push_back(body); + func->blocks.emplace_back(body); reg(val, func); return (ast_expression*)val; } diff --git a/ir.cpp b/ir.cpp index 6cfe110..e9aa7b7 100644 --- a/ir.cpp +++ b/ir.cpp @@ -203,7 +203,6 @@ static bool GMQCC_WARN ir_block_create_store(ir_block*, lex_ctx_t, ir_value *tar 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 */ @@ -285,7 +284,8 @@ void ir_builder::operator delete(void *ptr) } ir_builder::ir_builder(const std::string& modulename) -: name(modulename) +: name(modulename), + code(new code_t) { htglobals = util_htnew(IR_HT_SIZE); htfields = util_htnew(IR_HT_SIZE); @@ -302,8 +302,6 @@ ir_builder::ir_builder(const std::string& modulename) vinstr_temp[i] = new ir_value("vinstr_temp", store_value, TYPE_NOEXPR); vinstr_temp[i]->cvq = CV_CONST; } - - code = code_init(); } ir_builder::~ir_builder() @@ -321,7 +319,8 @@ ir_builder::~ir_builder() delete vinstr_temp[i]; } - code_cleanup(code); + extparams.clear(); + extparam_protos.clear(); } static ir_function* ir_builder_get_function(ir_builder *self, const char *name) @@ -527,7 +526,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) { @@ -569,7 +568,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]; @@ -627,7 +626,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; @@ -664,8 +663,8 @@ static bool ir_function_pass_tailrecursion(ir_function *self) return false; } - ir_instr_delete(call); - ir_instr_delete(ret); + delete call; + delete ret; } return true; @@ -767,7 +766,7 @@ ir_block::ir_block(ir_function* owner, const std::string& name) ir_block::~ir_block() { for (size_t i = 0; i != vec_size(instr); ++i) - ir_instr_delete(instr[i]); + delete instr[i]; vec_free(instr); vec_free(entries); vec_free(exits); @@ -786,53 +785,52 @@ static void ir_block_delete_quick(ir_block* self) *IR Instructions */ -static ir_instr* ir_instr_new(lex_ctx_t ctx, ir_block* owner, int op) -{ - ir_instr *self = new ir_instr; - self->owner = owner; - self->context = ctx; - self->opcode = op; - self->_ops[0] = nullptr; - self->_ops[1] = nullptr; - self->_ops[2] = nullptr; - self->bops[0] = nullptr; - self->bops[1] = nullptr; - 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_) { - delete self; } -static void ir_instr_delete(ir_instr *self) +ir_instr::~ir_instr() { - /* 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 : self->phi) { + // 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(it.value->writes, self, &idx)) + 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, self, &idx)) + if (vec_ir_instr_find(it.value->reads, this, &idx)) it.value->reads.erase(it.value->reads.begin() + idx); } - for (auto &it : self->params) { + for (auto &it : params) { size_t idx; - if (vec_ir_instr_find(it->writes, self, &idx)) + if (vec_ir_instr_find(it->writes, this, &idx)) it->writes.erase(it->writes.begin() + idx); - if (vec_ir_instr_find(it->reads, self, &idx)) + if (vec_ir_instr_find(it->reads, this, &idx)) it->reads.erase(it->reads.begin() + idx); } - (void)!ir_instr_op(self, 0, nullptr, false); - (void)!ir_instr_op(self, 1, nullptr, false); - (void)!ir_instr_op(self, 2, nullptr, false); - mem_d(self); + (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) @@ -1119,7 +1117,7 @@ static bool ir_value_life_merge(ir_value *self, size_t s) { /* merge */ before->end = life_found->end; - self->life.erase(self->life.begin()+1); + self->life.erase(self->life.begin()+i); return true; } if (before->end + 1 == s) @@ -1297,14 +1295,14 @@ bool ir_block_create_store_op(ir_block *self, lex_ctx_t ctx, int op, ir_value *t 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); @@ -1317,14 +1315,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); @@ -1387,12 +1385,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; } @@ -1407,13 +1405,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; } @@ -1435,7 +1433,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; @@ -1459,16 +1457,16 @@ ir_instr* ir_block_create_phi(ir_block *self, lex_ctx_t ctx, const char *label, ir_instr *in; if (!ir_check_unreachable(self)) return nullptr; - in = ir_instr_new(ctx, self, VINSTR_PHI); + in = new ir_instr(ctx, self, VINSTR_PHI); if (!in) return nullptr; out = ir_value_out(self->owner, label, store_value, ot); if (!out) { - ir_instr_delete(in); + delete in; return nullptr; } if (!ir_instr_op(in, 0, out, true)) { - ir_instr_delete(in); + delete in; return nullptr; } vec_push(self->instr, in); @@ -1485,9 +1483,8 @@ 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, nullptr)) { - /* Must not be possible to cause this, otherwise the AST - * is doing something wrong. - */ + // 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); } @@ -1505,7 +1502,7 @@ ir_instr* ir_block_create_call(ir_block *self, lex_ctx_t ctx, const char *label, ir_instr *in; if (!ir_check_unreachable(self)) return nullptr; - in = ir_instr_new(ctx, self, (noreturn ? VINSTR_NRCALL : INSTR_CALL0)); + in = new ir_instr(ctx, self, (noreturn ? VINSTR_NRCALL : INSTR_CALL0)); if (!in) return nullptr; if (noreturn) { @@ -1514,13 +1511,13 @@ ir_instr* ir_block_create_call(ir_block *self, lex_ctx_t ctx, const char *label, } out = ir_value_out(self->owner, label, (func->outtype == TYPE_VOID) ? store_return : store_value, func->outtype); if (!out) { - ir_instr_delete(in); + delete in; return nullptr; } if (!ir_instr_op(in, 0, out, true) || !ir_instr_op(in, 1, func, false)) { - ir_instr_delete(in); + delete in; return nullptr; } vec_push(self->instr, in); @@ -1528,7 +1525,7 @@ ir_instr* ir_block_create_call(ir_block *self, lex_ctx_t ctx, const char *label, if (noreturn) { if (!ir_block_create_return(self, ctx, nullptr)) { compile_error(ctx, "internal error: failed to generate dummy-return instruction"); - ir_instr_delete(in); + delete in; return nullptr; } } @@ -1715,7 +1712,7 @@ static ir_value* ir_block_create_general_instr(ir_block *self, lex_ctx_t ctx, co if (!out) return nullptr; - instr = ir_instr_new(ctx, self, op); + instr = new ir_instr(ctx, self, op); if (!instr) { return nullptr; } @@ -1731,7 +1728,7 @@ static ir_value* ir_block_create_general_instr(ir_block *self, lex_ctx_t ctx, co return out; on_error: - ir_instr_delete(instr); + delete instr; return nullptr; } @@ -1830,7 +1827,7 @@ static bool ir_block_naive_phi(ir_block *self) b->final = true; } } - ir_instr_delete(instr); + delete instr; } return true; } @@ -2190,12 +2187,8 @@ static bool ir_block_life_propagate(ir_block *self, bool *changed) ir_instr *instr; ir_value *value; size_t i, o, p, mem; - /* bitmasks which operands are read from or written to */ + // 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; self->living.clear(); @@ -2397,21 +2390,17 @@ 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) + 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 = self->blocks.size(); - while (i--) { - ir_block_life_propagate(self->blocks[i].get(), &changed); - } + for (auto i = self->blocks.rbegin(); i != self->blocks.rend(); ++i) + ir_block_life_propagate(i->get(), &changed); } while (changed); if (self->blocks.size()) { @@ -2424,7 +2413,8 @@ bool ir_function_calculate_liferanges(ir_function *self) continue; self->flags |= IR_FLAG_HAS_UNINITIALIZED; /* find the instruction reading from it */ - for (s = 0; s < v->reads.size(); ++s) { + size_t s = 0; + for (; s < v->reads.size(); ++s) { if (v->reads[s]->eid == v->life[0].end) break; } @@ -2902,7 +2892,7 @@ static bool gen_blocks_recursive(code_t *code, ir_function *func, ir_block *bloc if (p-8 >= ir->extparams.size()) ir_gen_extparam(ir); - targetparam = ir->extparams[p-8].get(); + targetparam = ir->extparams[p-8]; stmt.opcode = INSTR_STORE_F; stmt.o3.u1 = 0; @@ -3069,7 +3059,7 @@ static qcint_t ir_builder_filestring(ir_builder *ir, const char *filename) return i; } - str = code_genstring(ir->code, filename); + str = code_genstring(ir->code.get(), filename); ir->filenames.push_back(filename); ir->filestrings.push_back(str); return str; @@ -3137,7 +3127,7 @@ static void ir_gen_extparam(ir_builder *ir) else global = ir->extparam_protos[ir->extparams.size()].get(); - def.name = code_genstring(ir->code, global->name.c_str()); + def.name = code_genstring(ir->code.get(), global->name.c_str()); def.type = TYPE_VECTOR; def.offset = ir->code->globals.size(); @@ -3168,7 +3158,7 @@ static bool gen_function_extparam_copy(code_t *code, ir_function *self) if (ext >= ir->extparams.size()) ir_gen_extparam(ir); - ir_value *ep = ir->extparams[ext].get(); + ir_value *ep = ir->extparams[ext]; stmt.opcode = type_store_instr[self->locals[i]->vtype]; if (self->locals[i]->vtype == TYPE_FIELD && @@ -3210,7 +3200,7 @@ static bool gen_function_varargs_copy(code_t *code, ir_function *self) while (ext >= ir->extparams.size()) ir_gen_extparam(ir); - ep = ir->extparams[ext].get(); + ep = ir->extparams[ext]; stmt.o1.u1 = ir_value_code_addr(ep); stmt.o2.u1 = ir_value_code_addr(self->locals[i].get()); @@ -3315,15 +3305,15 @@ static bool gen_global_function_code(ir_builder *ir, ir_value *global) irerror(irfun->context, "Failed to generate locals for function %s", irfun->name.c_str()); return false; } - if (!gen_function_extparam_copy(ir->code, irfun)) { + 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)) { + 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)) { + if (!gen_function_code(ir->code.get(), irfun)) { irerror(irfun->context, "Failed to generate code for function %s", irfun->name.c_str()); return false; } @@ -3426,11 +3416,11 @@ 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.c_str()); + def.name = global->code.name = code_genstring(self->code.get(), global->name.c_str()); } else def.name = 0; @@ -3438,9 +3428,9 @@ static bool ir_builder_gen_global(ir_builder *self, ir_value *global, bool isloc def.offset = ir_value_code_addr(global); self->code->defs.push_back(def); if (global->vtype == TYPE_VECTOR) - gen_vector_defs(self->code, def, global->name.c_str()); + 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.c_str()); + gen_vector_defs(self->code.get(), def, global->name.c_str()); return true; } } @@ -3475,14 +3465,14 @@ static bool ir_builder_gen_global(ir_builder *self, ir_value *global, bool isloc return true; case TYPE_POINTER: if (pushdef) self->code->defs.push_back(def); - return gen_global_pointer(self->code, global); + return gen_global_pointer(self->code.get(), global); case TYPE_FIELD: if (pushdef) { self->code->defs.push_back(def); if (global->fieldtype == TYPE_VECTOR) - gen_vector_defs(self->code, def, global->name.c_str()); + 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: @@ -3504,7 +3494,7 @@ static bool ir_builder_gen_global(ir_builder *self, ir_value *global, bool isloc { ir_value_code_setaddr(global, self->code->globals.size()); if (global->hasvalue) { - uint32_t load = code_genstring(self->code, global->constval.vstring); + uint32_t load = code_genstring(self->code.get(), global->constval.vstring); self->code->globals.push_back(load); } else { self->code->globals.push_back(0); @@ -3540,7 +3530,7 @@ static bool ir_builder_gen_global(ir_builder *self, ir_value *global, bool isloc if (pushdef) { self->code->defs.push_back(def); def.type &= ~DEF_SAVEGLOBAL; - gen_vector_defs(self->code, def, global->name.c_str()); + gen_vector_defs(self->code.get(), def, global->name.c_str()); } return global->code.globaladdr >= 0; } @@ -3607,7 +3597,7 @@ static bool ir_builder_gen_field(ir_builder *self, ir_value *field) 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, @@ -3615,7 +3605,7 @@ 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.c_str()); + def.name = code_genstring(self->code.get(), field->name.c_str()); fld.name = def.name; } @@ -3642,8 +3632,8 @@ static bool ir_builder_gen_field(ir_builder *self, ir_value *field) } if (field->fieldtype == TYPE_VECTOR) { - gen_vector_defs (self->code, def, field->name.c_str()); - gen_vector_fields(self->code, fld, field->name.c_str()); + 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; @@ -3729,8 +3719,12 @@ static void ir_builder_split_vector(ir_builder *self, ir_value *vec) { } static void ir_builder_split_vectors(ir_builder *self) { - for (auto& gp : self->globals) { - ir_value *v = gp.get(); + // 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, v); @@ -3749,7 +3743,7 @@ bool ir_builder_generate(ir_builder *self, const char *filename) } for (auto& fp : self->fields) - ir_builder_prepare_field(self->code, fp.get()); + ir_builder_prepare_field(self->code.get(), fp.get()); for (auto& gp : self->globals) { ir_value *global = gp.get(); @@ -3832,7 +3826,7 @@ bool ir_builder_generate(ir_builder *self, const char *filename) 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)) @@ -3856,7 +3850,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; } diff --git a/ir.h b/ir.h index 44ceccf..1820317 100644 --- a/ir.h +++ b/ir.h @@ -108,19 +108,25 @@ struct ir_phi_entry_t { /* instruction */ struct ir_instr { + void* operator new(std::size_t); + void operator delete(void*); + + ir_instr(lex_ctx_t, ir_block *owner, int opcode); + ~ir_instr(); + int opcode; lex_ctx_t context; - ir_value *(_ops[3]); - ir_block *(bops[2]); + ir_value *(_ops[3]) = { nullptr, nullptr, nullptr }; + ir_block *(bops[2]) = { nullptr, nullptr }; std::vector phi; std::vector params; // For the temp-allocation - size_t eid; + size_t eid = 0; // For IFs - bool likely; + bool likely = true; ir_block *owner; }; @@ -262,8 +268,9 @@ struct ir_builder { ht htglobals; ht htfields; - std::vector> extparams; + // extparams' ir_values reference the ones from extparam_protos std::vector> extparam_protos; + std::vector extparams; // the highest func->allocated_locals size_t max_locals = 0; @@ -288,7 +295,7 @@ struct ir_builder { ir_value *vinstr_temp[IR_MAX_VINSTR_TEMPS]; /* code generator */ - code_t *code; + std::unique_ptr code; }; ir_function* ir_builder_create_function(ir_builder*, const std::string& name, qc_type outtype); diff --git a/parser.cpp b/parser.cpp index bfe2db6..75f9312 100644 --- a/parser.cpp +++ b/parser.cpp @@ -4088,7 +4088,7 @@ static bool parse_function_body(parser_t *parser, ast_value *var) goto enderrfn; } - func->blocks.push_back(block); + func->blocks.emplace_back(block); parser->function = old; if (!parser_leaveblock(parser)) @@ -4348,7 +4348,7 @@ static bool parser_create_array_accessor(parser_t *parser, ast_value *array, con return false; } - func->blocks.push_back(body); + func->blocks.emplace_back(body); *out = fval; parser->accessors.push_back(fval); @@ -4405,7 +4405,7 @@ static bool parser_create_array_setter_impl(parser_t *parser, ast_value *array) parseerror(parser, "failed to build accessor search tree"); return false; } - if (!ast_block_add_expr(array->setter->constval.vfunc->blocks[0], root)) { + if (!ast_block_add_expr(array->setter->constval.vfunc->blocks[0].get(), root)) { ast_delete(root); return false; } @@ -4457,7 +4457,7 @@ static bool parser_create_array_field_setter(parser_t *parser, ast_value *array, } array->setter = fval; - return ast_block_add_expr(func->blocks[0], root); + return ast_block_add_expr(func->blocks[0].get(), root); cleanup: if (entity) ast_delete(entity); if (index) ast_delete(index); @@ -4513,7 +4513,7 @@ static bool parser_create_array_getter_impl(parser_t *parser, ast_value *array) parseerror(parser, "failed to build accessor search tree"); return false; } - if (!ast_block_add_expr(array->getter->constval.vfunc->blocks[0], root)) { + if (!ast_block_add_expr(array->getter->constval.vfunc->blocks[0].get(), root)) { ast_delete(root); return false; } @@ -6123,6 +6123,7 @@ static void parser_remove_ast(parser_t *parser) void parser_cleanup(parser_t *parser) { parser_remove_ast(parser); + parser->~parser_t(); mem_d(parser); } diff --git a/test.cpp b/test.cpp index 840e6b6..6d783f7 100644 --- a/test.cpp +++ b/test.cpp @@ -76,7 +76,7 @@ static FILE **task_popen(const char *command, const char *mode) { dup2(errhandle[1], 2); execvp(argv[0], &argv[0]); - exit(EXIT_FAILURE); + exit(95); } else { /* fork failed */ goto task_popen_error_3; @@ -98,11 +98,17 @@ static int task_pclose(FILE **handles) { close(data->pipes[1]); /* stdout */ close(data->pipes[2]); /* stderr */ - waitpid(data->pid, &status, 0); + if (data->pid != waitpid(data->pid, &status, 0)) { + abort(); + } + if (!WIFEXITED(status)) + return -1; + if (WIFSIGNALED(status)) + con_out("got signaled!\n"); mem_d(data); - return status; + return status ? 1 : 0; } #define TASK_COMPILE 0 @@ -997,6 +1003,10 @@ static size_t task_schedualize(size_t *pad) { util_snprintf(space[1], sizeof(space[1]), "%d", (int)(i)); con_out("test #%u %*s", i, strlen(space[0]) - strlen(space[1]), ""); + //con_out("[[%*s]]", + // (pad[0] + pad[1] - strlen(it.tmpl->description)) + (strlen(it.tmpl->rulesfile) - pad[1]), + // it.tmpl->rulesfile); + //fflush(stdout); /* * Generate a task from thin air if it requires execution in @@ -1057,6 +1067,16 @@ static size_t task_schedualize(size_t *pad) { } status = task_pclose(it.runhandles); + if (status != 0 && status != 1) { + con_out("compiler failure (returned: %i): `%s` %*s\n", + status, + it.tmpl->description, + (pad[0] + pad[1] - strlen(it.tmpl->description)) + (strlen(it.tmpl->rulesfile) - pad[1]), + it.tmpl->rulesfile + ); + failed++; + continue; + } if ((!strcmp(it.tmpl->proceduretype, "-fail") && status == EXIT_SUCCESS) || ( strcmp(it.tmpl->proceduretype, "-fail") && status == EXIT_FAILURE)) { con_out("failure: `%s` %*s %*s\n",