]> git.xonotic.org Git - xonotic/gmqcc.git/blobdiff - ir.cpp
c++: ir_block::m_entries
[xonotic/gmqcc.git] / ir.cpp
diff --git a/ir.cpp b/ir.cpp
index 76d9db3d57b15cf5dad83b494dfe21d9ee8286a3..5f2ef7e3801037ee504702ee9aca50cd5b935ea5 100644 (file)
--- a/ir.cpp
+++ b/ir.cpp
@@ -235,15 +235,14 @@ static bool GMQCC_WARN vec_ir_value_find(std::vector<ir_value *> &vec, const ir_
     return false;
 }
 
-static bool GMQCC_WARN vec_ir_block_find(ir_block **vec, ir_block *what, size_t *idx)
+static bool GMQCC_WARN vec_ir_block_find(std::vector<ir_block *> &vec, ir_block *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;
 }
@@ -631,6 +630,36 @@ bool ir_function_finalize(ir_function *self)
     if (self->m_builtin)
         return true;
 
+    for (auto& lp : self->m_locals) {
+        ir_value *v = lp.get();
+        if (v->m_reads.empty() && v->m_writes.size() && !(v->m_flags & IR_FLAG_NOREF)) {
+            // if it's a vector check to ensure all it's members are unused before
+            // claiming it's unused, otherwise skip the vector entierly
+            if (v->m_vtype == TYPE_VECTOR)
+            {
+                size_t mask = (1 << 3) - 1, bits = 0;
+                for (size_t i = 0; i < 3; i++)
+                    if (!v->m_members[i] || (v->m_members[i]->m_reads.empty()
+                        && v->m_members[i]->m_writes.size()))
+                        bits |= (1 << i);
+                // all components are unused so just report the vector
+                if (bits == mask && irwarning(v->m_context, WARN_UNUSED_VARIABLE,
+                    "unused variable: `%s`", v->m_name.c_str()))
+                    return false;
+                else if (bits != mask)
+                    // individual components are unused so mention them
+                    for (size_t i = 0; i < 3; i++)
+                        if ((bits & (1 << i))
+                            && irwarning(v->m_context, WARN_UNUSED_COMPONENT,
+                                "unused vector component: `%s.%c`", v->m_name.c_str(), "xyz"[i]))
+                            return false;
+            }
+            // just a standard variable
+            else if (irwarning(v->m_context, WARN_UNUSED_VARIABLE,
+                    "unused variable: `%s`", v->m_name.c_str())) return false;
+        }
+    }
+
     if (OPTS_OPTIMIZATION(OPTIM_PEEPHOLE)) {
         if (!ir_function_pass_peephole(self)) {
             irerror(self->m_context, "generic optimization pass broke something in `%s`", self->m_name.c_str());
@@ -716,7 +745,6 @@ ir_block::~ir_block()
     for (size_t i = 0; i != vec_size(m_instr); ++i)
         delete m_instr[i];
     vec_free(m_instr);
-    vec_free(m_entries);
     vec_free(m_exits);
 }
 
@@ -914,7 +942,7 @@ ir_value* ir_value::vectorMember(unsigned int member)
         m = new ir_value(move(name), m_store, TYPE_FIELD);
         if (!m)
             return nullptr;
-        m->m_fieldtype = TYPE_VECTOR;
+        m->m_fieldtype = TYPE_FLOAT;
         m->m_context = m_context;
 
         m_members[member] = m;
@@ -1353,8 +1381,8 @@ bool ir_block_create_if(ir_block *self, lex_ctx_t ctx, ir_value *v,
 
     vec_push(self->m_exits, ontrue);
     vec_push(self->m_exits, onfalse);
-    vec_push(ontrue->m_entries,  self);
-    vec_push(onfalse->m_entries, self);
+    ontrue->m_entries.push_back(self);
+    onfalse->m_entries.push_back(self);
     return true;
 }
 
@@ -1372,7 +1400,7 @@ bool ir_block_create_jump(ir_block *self, lex_ctx_t ctx, ir_block *to)
     vec_push(self->m_instr, in);
 
     vec_push(self->m_exits, to);
-    vec_push(to->m_entries, self);
+    to->m_entries.push_back(self);
     return true;
 }