]> git.xonotic.org Git - xonotic/gmqcc.git/blobdiff - ir.cpp
ir: fix vector negation using the nil value
[xonotic/gmqcc.git] / ir.cpp
diff --git a/ir.cpp b/ir.cpp
index f3a4dca13b0b089838ddae273223308e33cb5dc2..7a2583bea832c99090d676b57126735cad9a88b4 100644 (file)
--- a/ir.cpp
+++ b/ir.cpp
@@ -1643,7 +1643,7 @@ ir_value* ir_block_create_unary(ir_block *self, lex_ctx_t ctx,
         case VINSTR_NEG_F:
             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, nullptr, operand, TYPE_VECTOR);
+            return ir_block_create_general_instr(self, ctx, label, INSTR_SUB_V, self->m_owner->m_owner->m_nil, operand, TYPE_VECTOR);
 
         default:
             ot = operand->m_vtype;
@@ -1836,10 +1836,10 @@ void ir_function_enumerate(ir_function *self)
  * This is the counterpart to register-allocation in register machines.
  */
 struct function_allocator {
-    ir_value **locals;
-    size_t *sizes;
-    size_t *positions;
-    bool *unique;
+    std::vector<std::unique_ptr<ir_value>> locals;
+    std::vector<size_t> sizes;
+    std::vector<size_t> positions;
+    std::vector<bool> unique;
 };
 
 static bool function_allocator_alloc(function_allocator *alloc, ir_value *var)
@@ -1847,7 +1847,7 @@ static bool function_allocator_alloc(function_allocator *alloc, ir_value *var)
     ir_value *slot;
     size_t vsize = var->size();
 
-    var->m_code.local = vec_size(alloc->locals);
+    var->m_code.local = alloc->locals.size();
 
     slot = new ir_value("reg", store_global, var->m_vtype);
     if (!slot)
@@ -1856,9 +1856,9 @@ static bool function_allocator_alloc(function_allocator *alloc, ir_value *var)
     if (!slot->mergeLife(var))
         goto localerror;
 
-    vec_push(alloc->locals, slot);
-    vec_push(alloc->sizes, vsize);
-    vec_push(alloc->unique, var->m_unique_life);
+    alloc->locals.emplace_back(slot);
+    alloc->sizes.push_back(vsize);
+    alloc->unique.push_back(var->m_unique_life);
 
     return true;
 
@@ -1870,23 +1870,22 @@ localerror:
 static bool ir_function_allocator_assign(ir_function *self, function_allocator *alloc, ir_value *v)
 {
     size_t a;
-    ir_value *slot;
 
     if (v->m_unique_life)
         return function_allocator_alloc(alloc, v);
 
-    for (a = 0; a < vec_size(alloc->locals); ++a)
+    for (a = 0; a < alloc->locals.size(); ++a)
     {
         /* if it's reserved for a unique liferange: skip */
         if (alloc->unique[a])
             continue;
 
-        slot = alloc->locals[a];
+        ir_value *slot = alloc->locals[a].get();
 
         /* never resize parameters
          * will be required later when overlapping temps + locals
          */
-        if (a < vec_size(self->m_params) &&
+        if (a < self->m_params.size() &&
             alloc->sizes[a] < v->size())
         {
             continue;
@@ -1905,7 +1904,7 @@ static bool ir_function_allocator_assign(ir_function *self, function_allocator *
         v->m_code.local = a;
         return true;
     }
-    if (a >= vec_size(alloc->locals)) {
+    if (a >= alloc->locals.size()) {
         if (!function_allocator_alloc(alloc, v))
             return false;
     }
@@ -1914,7 +1913,6 @@ static bool ir_function_allocator_assign(ir_function *self, function_allocator *
 
 bool ir_function_allocate_locals(ir_function *self)
 {
-    bool   retval = true;
     size_t pos;
     bool   opt_gt = OPTS_OPTIMIZATION(OPTIM_GLOBAL_TEMPS);
 
@@ -1923,15 +1921,6 @@ bool ir_function_allocate_locals(ir_function *self)
     if (self->m_locals.empty() && self->m_values.empty())
         return true;
 
-    globalloc.locals    = nullptr;
-    globalloc.sizes     = nullptr;
-    globalloc.positions = nullptr;
-    globalloc.unique    = nullptr;
-    lockalloc.locals    = nullptr;
-    lockalloc.sizes     = nullptr;
-    lockalloc.positions = nullptr;
-    lockalloc.unique    = nullptr;
-
     size_t i;
     for (i = 0; i < self->m_locals.size(); ++i)
     {
@@ -1940,12 +1929,12 @@ bool ir_function_allocate_locals(ir_function *self)
             v->m_locked      = true;
             v->m_unique_life = true;
         }
-        else if (i >= vec_size(self->m_params))
+        else if (i >= self->m_params.size())
             break;
         else
             v->m_locked = true; /* lock parameters locals */
         if (!function_allocator_alloc((v->m_locked || !opt_gt ? &lockalloc : &globalloc), v))
-            goto error;
+            return false;
     }
     for (; i < self->m_locals.size(); ++i)
     {
@@ -1953,7 +1942,7 @@ bool ir_function_allocate_locals(ir_function *self)
         if (v->m_life.empty())
             continue;
         if (!ir_function_allocator_assign(self, (v->m_locked || !opt_gt ? &lockalloc : &globalloc), v))
-            goto error;
+            return false;
     }
 
     /* Allocate a slot for any value that still exists */
@@ -1979,7 +1968,7 @@ bool ir_function_allocate_locals(ir_function *self)
                 ir_instr *call = v->m_reads[0];
                 if (!vec_ir_value_find(call->m_params, v, &param)) {
                     irerror(call->m_context, "internal error: unlocked parameter %s not found", v->m_name.c_str());
-                    goto error;
+                    return false;
                 }
                 ++opts_optimizationcount[OPTIM_CALL_STORES];
                 v->m_callparam = true;
@@ -2013,33 +2002,33 @@ bool ir_function_allocate_locals(ir_function *self)
         }
 
         if (!ir_function_allocator_assign(self, (v->m_locked || !opt_gt ? &lockalloc : &globalloc), v))
-            goto error;
+            return false;
     }
 
-    if (!lockalloc.sizes && !globalloc.sizes) {
-        goto cleanup;
-    }
-    vec_push(lockalloc.positions, 0);
-    vec_push(globalloc.positions, 0);
+    if (lockalloc.sizes.empty() && globalloc.sizes.empty())
+        return true;
+
+    lockalloc.positions.push_back(0);
+    globalloc.positions.push_back(0);
 
     /* Adjust slot positions based on sizes */
-    if (lockalloc.sizes) {
-        pos = (vec_size(lockalloc.sizes) ? lockalloc.positions[0] : 0);
-        for (i = 1; i < vec_size(lockalloc.sizes); ++i)
+    if (!lockalloc.sizes.empty()) {
+        pos = (lockalloc.sizes.size() ? lockalloc.positions[0] : 0);
+        for (i = 1; i < lockalloc.sizes.size(); ++i)
         {
             pos = lockalloc.positions[i-1] + lockalloc.sizes[i-1];
-            vec_push(lockalloc.positions, pos);
+            lockalloc.positions.push_back(pos);
         }
-        self->m_allocated_locals = pos + vec_last(lockalloc.sizes);
+        self->m_allocated_locals = pos + lockalloc.sizes.back();
     }
-    if (globalloc.sizes) {
-        pos = (vec_size(globalloc.sizes) ? globalloc.positions[0] : 0);
-        for (i = 1; i < vec_size(globalloc.sizes); ++i)
+    if (!globalloc.sizes.empty()) {
+        pos = (globalloc.sizes.size() ? globalloc.positions[0] : 0);
+        for (i = 1; i < globalloc.sizes.size(); ++i)
         {
             pos = globalloc.positions[i-1] + globalloc.sizes[i-1];
-            vec_push(globalloc.positions, pos);
+            globalloc.positions.push_back(pos);
         }
-        self->m_globaltemps = pos + vec_last(globalloc.sizes);
+        self->m_globaltemps = pos + globalloc.sizes.back();
     }
 
     /* Locals need to know their new position */
@@ -2057,24 +2046,7 @@ bool ir_function_allocate_locals(ir_function *self)
             value->m_code.local = globalloc.positions[value->m_code.local];
     }
 
-    goto cleanup;
-
-error:
-    retval = false;
-cleanup:
-    for (i = 0; i < vec_size(lockalloc.locals); ++i)
-        delete lockalloc.locals[i];
-    for (i = 0; i < vec_size(globalloc.locals); ++i)
-        delete globalloc.locals[i];
-    vec_free(globalloc.unique);
-    vec_free(globalloc.locals);
-    vec_free(globalloc.sizes);
-    vec_free(globalloc.positions);
-    vec_free(lockalloc.unique);
-    vec_free(lockalloc.locals);
-    vec_free(lockalloc.sizes);
-    vec_free(lockalloc.positions);
-    return retval;
+    return true;
 }
 
 /* Get information about which operand
@@ -2342,7 +2314,7 @@ static bool ir_block_life_propagate(ir_block *self, bool *changed)
 bool ir_function_calculate_liferanges(ir_function *self)
 {
     /* parameters live at 0 */
-    for (size_t i = 0; i < vec_size(self->m_params); ++i)
+    for (size_t i = 0; i < self->m_params.size(); ++i)
         if (!self->m_locals[i].get()->setAlive(0))
             compile_error(self->m_context, "internal error: failed value-life merging");
 
@@ -3030,7 +3002,7 @@ bool ir_builder::generateGlobalFunction(ir_value *global)
     fun.name = global->m_code.name;
     fun.file = filestring(global->m_context.file);
     fun.profile = 0; /* always 0 */
-    fun.nargs = vec_size(irfun->m_params);
+    fun.nargs = irfun->m_params.size();
     if (fun.nargs > 8)
         fun.nargs = 8;
 
@@ -3095,7 +3067,7 @@ static bool gen_function_extparam_copy(code_t *code, ir_function *self)
 {
     ir_builder *ir = self->m_owner;
 
-    size_t numparams = vec_size(self->m_params);
+    size_t numparams = self->m_params.size();
     if (!numparams)
         return true;
 
@@ -3131,7 +3103,7 @@ static bool gen_function_varargs_copy(code_t *code, ir_function *self)
     ir_value   *ep;
     prog_section_statement_t stmt;
 
-    numparams = vec_size(self->m_params);
+    numparams = self->m_params.size();
     if (!numparams)
         return true;