]> git.xonotic.org Git - xonotic/gmqcc.git/blobdiff - ast.cpp
added -fdefault-eraseable which is the same as adding [[eraseable]] to all definitions
[xonotic/gmqcc.git] / ast.cpp
diff --git a/ast.cpp b/ast.cpp
index 1b6d40131aa66738af83cf21e1d5b47d89092758..7b444f8a402dfdf18efaab0ae3d171c1174972ae 100644 (file)
--- a/ast.cpp
+++ b/ast.cpp
@@ -37,6 +37,8 @@ ast_expression::ast_expression(lex_ctx_t ctx, int nodetype, qc_type type)
 {
     if (OPTS_OPTION_BOOL(OPTION_COVERAGE))
         m_flags |= AST_FLAG_BLOCK_COVERAGE;
+    if (OPTS_FLAG(DEFAULT_ERASEABLE))
+        m_flags |= AST_FLAG_ERASEABLE;
 }
 ast_expression::ast_expression(lex_ctx_t ctx, int nodetype)
     : ast_expression(ctx, nodetype, TYPE_VOID)
@@ -1130,7 +1132,7 @@ bool ast_value::generateGlobal(ir_builder *ir, bool isfield)
 
     if (m_flags & AST_FLAG_INCLUDE_DEF)
         m_ir_v->m_flags |= IR_FLAG_INCLUDE_DEF;
-    if (m_flags & AST_FLAG_ERASEABLE)
+    if (m_flags & AST_FLAG_ERASEABLE && !(m_flags & AST_FLAG_NOERASE))
         m_ir_v->m_flags |= IR_FLAG_ERASABLE;
     if (m_flags & AST_FLAG_NOREF)
         m_ir_v->m_flags |= IR_FLAG_NOREF;
@@ -1194,7 +1196,7 @@ bool ast_value::generateGlobalFunction(ir_builder *ir)
     m_ir_v = func->m_value;
     if (m_flags & AST_FLAG_INCLUDE_DEF)
         m_ir_v->m_flags |= IR_FLAG_INCLUDE_DEF;
-    if (m_flags & AST_FLAG_ERASEABLE)
+    if (m_flags & AST_FLAG_ERASEABLE && !(m_flags & AST_FLAG_NOERASE))
         m_ir_v->m_flags |= IR_FLAG_ERASABLE;
     if (m_flags & AST_FLAG_BLOCK_COVERAGE)
         func->m_flags |= IR_FLAG_BLOCK_COVERAGE;
@@ -1236,7 +1238,7 @@ bool ast_value::generateGlobalField(ir_builder *ir)
 
         if (m_flags & AST_FLAG_INCLUDE_DEF)
             m_ir_v->m_flags |= IR_FLAG_INCLUDE_DEF;
-        if (m_flags & AST_FLAG_ERASEABLE)
+        if (m_flags & AST_FLAG_ERASEABLE && !(m_flags & AST_FLAG_NOERASE))
             m_ir_v->m_flags |= IR_FLAG_ERASABLE;
         if (m_flags & AST_FLAG_NOREF)
             m_ir_v->m_flags |= IR_FLAG_NOREF;
@@ -1272,7 +1274,7 @@ 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)
+        if (m_flags & AST_FLAG_ERASEABLE && !(m_flags & AST_FLAG_NOERASE))
             m_ir_v->m_flags |= IR_FLAG_ERASABLE;
         if (m_flags & AST_FLAG_NOREF)
             m_ir_v->m_flags |= IR_FLAG_NOREF;
@@ -1305,7 +1307,7 @@ 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)
+    if (m_flags & AST_FLAG_ERASEABLE && !(m_flags & AST_FLAG_NOERASE))
         v->m_flags |= IR_FLAG_ERASABLE;
     if (m_flags & AST_FLAG_NOREF)
         v->m_flags |= IR_FLAG_NOREF;
@@ -1510,9 +1512,9 @@ bool ast_function::generateFunction(ir_builder *ir)
     /* fill the parameter list */
     for (auto &it : m_function_type->m_type_params) {
         if (it->m_vtype == TYPE_FIELD)
-            vec_push(irf->m_params, it->m_next->m_vtype);
+            irf->m_params.push_back(it->m_next->m_vtype);
         else
-            vec_push(irf->m_params, it->m_vtype);
+            irf->m_params.push_back(it->m_vtype);
         if (!m_builtin) {
             if (!it->generateLocal(m_ir_func, true))
                 return false;
@@ -1804,7 +1806,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;
@@ -1932,6 +1934,7 @@ bool ast_binstore::codegen(ast_function *func, bool lvalue, ir_value **out)
         if (!idx->codegen(func, false, &iridx))
             return false;
     }
+
     if (!m_dest->codegen(func, false, &leftr))
         return false;
 
@@ -2153,19 +2156,28 @@ bool ast_member::codegen(ast_function *func, bool lvalue, ir_value **out)
         else
             m_outr = *out;
         return (*out != nullptr);
-    } else {
-        if (!m_owner->codegen(func, false, &vec))
-            return false;
     }
 
+    // Vector member access
+    if (!m_owner->codegen(func, lvalue, &vec))
+        return false;
+
     if (vec->m_vtype != TYPE_VECTOR &&
         !(vec->m_vtype == TYPE_FIELD && m_owner->m_next->m_vtype == TYPE_VECTOR))
     {
+        compile_error(m_context, "vector member produced neither vector nor field");
         return false;
     }
 
     *out = vec->vectorMember(m_field);
-    m_outl = *out;
+    if (!*out) {
+        compile_error(m_context, "internal error: failed to create vector member access");
+        return false;
+    }
+    if (lvalue)
+        m_outl = *out;
+    else
+        m_outr = *out;
 
     return (*out != nullptr);
 }