Remove parser m_uses in favor of {IR,AST}_FLAG_NOREF instead
authorDale Weiler <weilercdale@gmail.com>
Thu, 24 Nov 2016 15:33:58 +0000 (15:33 +0000)
committerDale Weiler <weilercdale@gmail.com>
Thu, 24 Nov 2016 15:33:58 +0000 (15:33 +0000)
ast.cpp
ast.h
ir.cpp
ir.h
parser.cpp

diff --git a/ast.cpp b/ast.cpp
index 7529acd..b507a6b 100644 (file)
--- a/ast.cpp
+++ b/ast.cpp
@@ -1132,6 +1132,8 @@ bool ast_value::generateGlobal(ir_builder *ir, bool isfield)
         m_ir_v->m_flags |= IR_FLAG_INCLUDE_DEF;
     if (m_flags & AST_FLAG_ERASEABLE)
         m_ir_v->m_flags |= IR_FLAG_ERASABLE;
+    if (m_flags & AST_FLAG_NOREF)
+        m_ir_v->m_flags |= IR_FLAG_NOREF;
 
     /* initialize */
     if (m_hasvalue) {
@@ -1236,6 +1238,8 @@ bool ast_value::generateGlobalField(ir_builder *ir)
             m_ir_v->m_flags |= IR_FLAG_INCLUDE_DEF;
         if (m_flags & AST_FLAG_ERASEABLE)
             m_ir_v->m_flags |= IR_FLAG_ERASABLE;
+        if (m_flags & AST_FLAG_NOREF)
+            m_ir_v->m_flags |= IR_FLAG_NOREF;
 
         const size_t namelen = m_name.length();
         std::unique_ptr<char[]> name(new char[namelen+16]);
@@ -1254,7 +1258,9 @@ bool ast_value::generateGlobalField(ir_builder *ir)
             array->m_ir_values[ai]->m_unique_life = true;
             array->m_ir_values[ai]->m_locked      = true;
             if (m_flags & AST_FLAG_INCLUDE_DEF)
-                m_ir_values[ai]->m_flags |= IR_FLAG_INCLUDE_DEF;
+                array->m_ir_values[ai]->m_flags |= IR_FLAG_INCLUDE_DEF;
+            if (m_flags & AST_FLAG_NOREF)
+                array->m_ir_values[ai]->m_flags |= IR_FLAG_NOREF;
         }
     }
     else
@@ -1266,9 +1272,10 @@ bool ast_value::generateGlobalField(ir_builder *ir)
         m_ir_v = v;
         if (m_flags & AST_FLAG_INCLUDE_DEF)
             m_ir_v->m_flags |= IR_FLAG_INCLUDE_DEF;
-
         if (m_flags & AST_FLAG_ERASEABLE)
             m_ir_v->m_flags |= IR_FLAG_ERASABLE;
+        if (m_flags & AST_FLAG_NOREF)
+            m_ir_v->m_flags |= IR_FLAG_NOREF;
     }
     return true;
 }
@@ -1299,7 +1306,9 @@ ir_value *ast_value::prepareGlobalArray(ir_builder *ir)
     if (m_flags & AST_FLAG_INCLUDE_DEF)
         v->m_flags |= IR_FLAG_INCLUDE_DEF;
     if (m_flags & AST_FLAG_ERASEABLE)
-        m_ir_v->m_flags |= IR_FLAG_ERASABLE;
+        v->m_flags |= IR_FLAG_ERASABLE;
+    if (m_flags & AST_FLAG_NOREF)
+        v->m_flags |= IR_FLAG_NOREF;
 
     const size_t namelen = m_name.length();
     std::unique_ptr<char[]> name(new char[namelen+16]);
@@ -1319,6 +1328,8 @@ ir_value *ast_value::prepareGlobalArray(ir_builder *ir)
         m_ir_values[ai]->m_locked      = true;
         if (m_flags & AST_FLAG_INCLUDE_DEF)
             m_ir_values[ai]->m_flags |= IR_FLAG_INCLUDE_DEF;
+        if (m_flags & AST_FLAG_NOREF)
+            m_ir_values[ai]->m_flags |= IR_FLAG_NOREF;
     }
 
     return v;
@@ -1365,6 +1376,9 @@ bool ast_value::generateLocal(ir_function *func, bool param)
         v->m_unique_life = true;
         v->m_locked      = true;
 
+        if (m_flags & AST_FLAG_NOREF)
+            v->m_flags |= IR_FLAG_NOREF;
+
         const size_t namelen = m_name.length();
         std::unique_ptr<char[]> name(new char[namelen+16]);
         util_strncpy(name.get(), m_name.c_str(), namelen);
@@ -1379,7 +1393,10 @@ bool ast_value::generateLocal(ir_function *func, bool param)
             }
             m_ir_values[ai]->m_context = m_context;
             m_ir_values[ai]->m_unique_life = true;
-            m_ir_values[ai]->m_locked      = true;
+            m_ir_values[ai]->m_locked = true;
+
+            if (m_flags & AST_FLAG_NOREF)
+                m_ir_values[ai]->m_flags |= IR_FLAG_NOREF;
         }
     }
     else
@@ -1418,6 +1435,9 @@ bool ast_value::generateLocal(ir_function *func, bool param)
     v->m_cvq = m_cvq;
     m_ir_v = v;
 
+    if (m_flags & AST_FLAG_NOREF)
+        m_ir_v->m_flags |= IR_FLAG_NOREF;
+
     if (!generateAccessors(func->m_owner))
         return false;
     return true;
diff --git a/ast.h b/ast.h
index b305dac..04fa4d8 100644 (file)
--- a/ast.h
+++ b/ast.h
@@ -62,6 +62,12 @@ enum {
     AST_FLAG_COVERAGE       = 1 << 12,
     AST_FLAG_BLOCK_COVERAGE = 1 << 13,
 
+    /*
+     * Propagates norefness to the IR so the unused (read/write) check can be
+     * more intelligently done.
+     */
+    AST_FLAG_NOREF          = 1 << 14,
+
     AST_FLAG_LAST,
     AST_FLAG_TYPE_MASK      = (AST_FLAG_VARIADIC | AST_FLAG_NORETURN),
     AST_FLAG_COVERAGE_MASK  = (AST_FLAG_BLOCK_COVERAGE)
@@ -223,9 +229,6 @@ struct ast_value : ast_expression
      */
     std::vector<basic_value_t> m_initlist;
 
-    /* usecount for the parser */
-    size_t m_uses = 0;
-
     ir_value *m_ir_v = nullptr;
     std::vector<ir_value*> m_ir_values;
     size_t m_ir_value_count = 0;
diff --git a/ir.cpp b/ir.cpp
index c71cad8..3b78c35 100644 (file)
--- a/ir.cpp
+++ b/ir.cpp
@@ -633,7 +633,7 @@ bool ir_function_finalize(ir_function *self)
 
     for (auto& lp : self->m_locals) {
         ir_value *v = lp.get();
-        if (v->m_reads.empty() && v->m_writes.size()) {
+        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)
diff --git a/ir.h b/ir.h
index 9fa8ab5..fe07198 100644 (file)
--- a/ir.h
+++ b/ir.h
@@ -27,8 +27,8 @@ enum {
     IR_FLAG_INCLUDE_DEF             = 1 << 3,
     IR_FLAG_ERASABLE                = 1 << 4,
     IR_FLAG_BLOCK_COVERAGE          = 1 << 5,
-
-    IR_FLAG_SPLIT_VECTOR            = 1 << 6,
+    IR_FLAG_NOREF                   = 1 << 6,
+    IR_FLAG_SPLIT_VECTOR            = 1 << 7,
 
     IR_FLAG_LAST,
     IR_FLAG_MASK_NO_OVERLAP      = (IR_FLAG_HAS_ARRAYS | IR_FLAG_HAS_UNINITIALIZED),
index 518a06d..ed5bde1 100644 (file)
@@ -1668,13 +1668,16 @@ static bool parse_sya_operand(parser_t *parser, shunt *sy, bool with_labels)
         }
         else
         {
-            if (ast_istype(var, ast_value)) {
-                ((ast_value*)var)->m_uses++;
+            // promote these to norefs
+            if (ast_istype(var, ast_value))
+            {
+                ((ast_value *)var)->m_flags |= AST_FLAG_NOREF;
             }
-            else if (ast_istype(var, ast_member)) {
-                ast_member *mem = (ast_member*)var;
+            else if (ast_istype(var, ast_member))
+            {
+                ast_member *mem = (ast_member *)var;
                 if (ast_istype(mem->m_owner, ast_value))
-                    ((ast_value*)(mem->m_owner))->m_uses++;
+                    ((ast_value *)mem->m_owner)->m_flags |= AST_FLAG_NOREF;
             }
         }
         sy->out.push_back(syexp(parser_ctx(parser), var));
@@ -2020,15 +2023,8 @@ static bool parser_leaveblock(parser_t *parser)
 
     locals = vec_last(parser->_blocklocals);
     vec_pop(parser->_blocklocals);
-    while (vec_size(parser->_locals) != locals) {
-        ast_expression *e = vec_last(parser->_locals);
-        ast_value      *v = (ast_value*)e;
+    while (vec_size(parser->_locals) != locals)
         vec_pop(parser->_locals);
-        if (ast_istype(e, ast_value) && !v->m_uses) {
-            if (compile_warning(v->m_context, WARN_UNUSED_VARIABLE, "unused variable: `%s`", v->m_name))
-                rv = false;
-        }
-    }
 
     typedefs = vec_last(parser->_blocktypedefs);
     while (vec_size(parser->_typedefs) != typedefs) {
@@ -5232,12 +5228,12 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield
             /* Deal with end_sys_ vars */
             was_end = false;
             if (var->m_name == "end_sys_globals") {
-                var->m_uses++;
+                var->m_flags |= AST_FLAG_NOREF;
                 parser->crc_globals = parser->globals.size();
                 was_end = true;
             }
             else if (var->m_name == "end_sys_fields") {
-                var->m_uses++;
+                var->m_flags |= AST_FLAG_NOREF;
                 parser->crc_fields = parser->fields.size();
                 was_end = true;
             }
@@ -5397,9 +5393,8 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield
             }
         }
 
-        /* in a noref section we simply bump the usecount */
         if (noref || parser->noref)
-            var->m_uses++;
+            var->m_flags |= AST_FLAG_NOREF;
 
         /* Part 2:
          * Create the global/local, and deal with vector types.
@@ -5800,7 +5795,10 @@ skipvar:
                         var->m_cvq = CV_CONST;
                     }
                     if (cval == parser->nil)
+                    {
                         var->m_flags |= AST_FLAG_INITIALIZED;
+                        var->m_flags |= AST_FLAG_NOREF;
+                    }
                     else
                     {
                         var->m_hasvalue = true;
@@ -6075,6 +6073,7 @@ parser_t *parser_create()
         parser->reserved_version->m_cvq = CV_CONST;
         parser->reserved_version->m_hasvalue = true;
         parser->reserved_version->m_flags |= AST_FLAG_INCLUDE_DEF;
+        parser->reserved_version->m_flags |= AST_FLAG_NOREF;
         parser->reserved_version->m_constval.vstring = util_strdup(GMQCC_FULL_VERSION_STRING);
     } else {
         parser->reserved_version = nullptr;
@@ -6272,7 +6271,7 @@ bool parser_finish(parser_t *parser, const char *output)
         if (!ast_istype(it, ast_value))
             continue;
         asvalue = (ast_value*)it;
-        if (!asvalue->m_uses && asvalue->m_cvq != CV_CONST && asvalue->m_vtype != TYPE_FUNCTION) {
+        if (!(asvalue->m_flags & AST_FLAG_NOREF) && asvalue->m_cvq != CV_CONST && asvalue->m_vtype != TYPE_FUNCTION) {
             retval = retval && !compile_warning(asvalue->m_context, WARN_UNUSED_VARIABLE,
                                                 "unused global: `%s`", asvalue->m_name);
         }