]> git.xonotic.org Git - xonotic/gmqcc.git/blobdiff - ast.cpp
c++: ir_block::m_instr
[xonotic/gmqcc.git] / ast.cpp
diff --git a/ast.cpp b/ast.cpp
index cf8ffc70f445bb029b6bfa76396c8be4147e679a..eca80dee374f629805b15229a11d935e205a117c 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;
@@ -1562,7 +1582,7 @@ bool ast_function::generateFunction(ir_builder *ir)
         {
             return ir_block_create_return(m_curblock, m_context, nullptr);
         }
-        else if (vec_size(m_curblock->m_entries) || m_curblock == irf->m_first)
+        else if (m_curblock->m_entries.size() || m_curblock == irf->m_first)
         {
             if (m_return_value) {
                 if (!m_return_value->codegen(this, false, &dummy))
@@ -1784,7 +1804,7 @@ bool ast_binary::codegen(ast_function *func, bool lvalue, ir_value **out)
                 return false;
         }
         /* use the likely flag */
-        vec_last(func->m_curblock->m_instr)->m_likely = true;
+        func->m_curblock->m_instr.back()->m_likely = true;
 
         /* enter the right-expression's block */
         func->m_curblock = other;
@@ -2098,13 +2118,45 @@ bool ast_member::codegen(ast_function *func, bool lvalue, ir_value **out)
         compile_error(m_context, "not an l-value (member access)");
         return false;
     }
-    if (m_outl) {
+    if (lvalue && m_outl) {
         *out = m_outl;
         return true;
     }
+    if (!lvalue && m_outr) {
+        *out = m_outr;
+        return true;
+    }
 
-    if (!m_owner->codegen(func, false, &vec))
-        return false;
+    if (ast_istype(m_owner, ast_entfield)) {
+        ir_value *ent, *field;
+        auto entfield = reinterpret_cast<ast_entfield*>(m_owner);
+        if (!entfield->m_entity->codegen(func, false, &ent))
+            return false;
+        if (!entfield->m_field->codegen(func, false, &vec))
+            return false;
+        field = vec->vectorMember(m_field);
+        if (lvalue) {
+            *out = ir_block_create_fieldaddress(func->m_curblock, m_context, func->makeLabel("mefa"),
+                                                ent, field);
+        } else {
+            *out = ir_block_create_load_from_ent(func->m_curblock, m_context, func->makeLabel("mefv"),
+                                                 ent, field, m_vtype);
+        }
+        if (!*out) {
+            compile_error(m_context, "failed to create %s instruction (output type %s)",
+                     (lvalue ? "ADDRESS" : "FIELD"),
+                     type_name[m_vtype]);
+            return false;
+        }
+        if (lvalue)
+            m_outl = *out;
+        else
+            m_outr = *out;
+        return (*out != nullptr);
+    } else {
+        if (!m_owner->codegen(func, false, &vec))
+            return false;
+    }
 
     if (vec->m_vtype != TYPE_VECTOR &&
         !(vec->m_vtype == TYPE_FIELD && m_owner->m_next->m_vtype == TYPE_VECTOR))