more c++ migration for ast/ir/code; reached a working condition here
authorWolfgang Bumiller <wry.git@bumiller.com>
Tue, 20 Jan 2015 19:25:56 +0000 (20:25 +0100)
committerWolfgang Bumiller <wry.git@bumiller.com>
Tue, 20 Jan 2015 19:25:56 +0000 (20:25 +0100)
algo.h [new file with mode: 0644]
ast.cpp
ast.h
code.cpp
gmqcc.h
intrin.cpp
ir.cpp
ir.h
parser.cpp
test.cpp

diff --git a/algo.h b/algo.h
new file mode 100644 (file)
index 0000000..3218b1b
--- /dev/null
+++ b/algo.h
@@ -0,0 +1,18 @@
+#ifndef GMQCC_ALGO_HDR
+#define GMQCC_ALGO_HDR
+
+namespace algo {
+
+template<typename ITER>
+void shiftback(ITER element, ITER end) {
+    //typename ITER::value_type backup(move(*element)); // hold the element
+    typename std::remove_reference<decltype(*element)>::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 (file)
--- 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<unique_ptr<>>
+    //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 (file)
--- 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<ast_block*> blocks;
+    std::vector<std::unique_ptr<ast_block>> blocks;
     ast_value *varargs;
     ast_value *argc;
     ast_value *fixedparams;
index 2f55535..645ad25 100644 (file)
--- 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 (file)
--- 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<prog_section_statement_t> statements;
     std::vector<int> linenums;
     std::vector<int> columnnums;
@@ -510,10 +514,10 @@ struct code_t {
     std::vector<prog_section_function_t> functions;
     std::vector<int> globals;
     std::vector<char> 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;
 };
 
 /*
index 793cd7f..ebdacd9 100644 (file)
@@ -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 (file)
--- 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 (file)
--- 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<ir_phi_entry_t> phi;
     std::vector<ir_value *> 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<std::unique_ptr<ir_value>> extparams;
+    // extparams' ir_values reference the ones from extparam_protos
     std::vector<std::unique_ptr<ir_value>> extparam_protos;
+    std::vector<ir_value*>                 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_t> code;
 };
 
 ir_function* ir_builder_create_function(ir_builder*, const std::string& name, qc_type outtype);
index bfe2db6..75f9312 100644 (file)
@@ -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);
 }
 
index 840e6b6..6d783f7 100644 (file)
--- 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",