]> git.xonotic.org Git - xonotic/gmqcc.git/blobdiff - ast.c
Fix array-index codegen conditions
[xonotic/gmqcc.git] / ast.c
diff --git a/ast.c b/ast.c
index cd6662fcfc5740ec6d7bd5cea55eb02bb93bff23..ac204d31808841135b060a23650ed4b4b77c50c9 100644 (file)
--- a/ast.c
+++ b/ast.c
@@ -327,6 +327,9 @@ ast_value* ast_value_new(lex_ctx ctx, const char *name, int t)
     self->ir_values      = NULL;
     self->ir_value_count = 0;
 
+    self->setter = NULL;
+    self->getter = NULL;
+
     return self;
 }
 
@@ -918,7 +921,9 @@ bool ast_value_codegen(ast_value *self, ast_function *func, bool lvalue, ir_valu
      * on all the globals.
      */
     if (!self->ir_v) {
-        asterror(ast_ctx(self), "ast_value used before generated (%s)", self->name);
+        char typename[1024];
+        ast_type_to_string((ast_expression*)self, typename, sizeof(typename));
+        asterror(ast_ctx(self), "ast_value used before generated %s %s", typename, self->name);
         return false;
     }
     *out = self->ir_v;
@@ -928,6 +933,7 @@ bool ast_value_codegen(ast_value *self, ast_function *func, bool lvalue, ir_valu
 bool ast_global_codegen(ast_value *self, ir_builder *ir, bool isfield)
 {
     ir_value *v = NULL;
+
     if (self->isconst && self->expression.vtype == TYPE_FUNCTION)
     {
         ir_function *func = ir_builder_create_function(ir, self->name, self->expression.next->expression.vtype);
@@ -1514,30 +1520,59 @@ bool ast_array_index_codegen(ast_array_index *self, ast_function *func, bool lva
     ast_value *arr;
     ast_value *idx;
 
+    if (!lvalue && self->expression.outr) {
+        *out = self->expression.outr;
+    }
+    if (lvalue && self->expression.outl) {
+        *out = self->expression.outl;
+    }
+
     if (!ast_istype(self->array, ast_value)) {
         asterror(ast_ctx(self), "array indexing this way is not supported");
+        /* note this would actually be pointer indexing because the left side is
+         * not an actual array but (hopefully) an indexable expression.
+         * Once we get integer arithmetic, and GADDRESS/GSTORE/GLOAD instruction
+         * support this path will be filled.
+         */
         return false;
     }
 
-    if (!ast_istype(self->index, ast_value)) {
+    arr = (ast_value*)self->array;
+    idx = (ast_value*)self->index;
+
+    if (!ast_istype(self->index, ast_value) || !idx->isconst) {
+        /* Time to use accessor functions */
+        ast_expression_codegen *cgen;
+        ir_value               *iridx, *funval;
+        ir_instr               *call;
+
         if (lvalue) {
-            asterror(ast_ctx(self), "array indexing here needs a compile-time constant");
+            asterror(ast_ctx(self), "(.2) array indexing here needs a compile-time constant");
             return false;
-        } else {
-            /* Time to use accessor functions */
-            /*
-            ast_expression_codegen *cgen;
-            ir_value               *iridx;
-            */
         }
-    }
 
-    arr = (ast_value*)self->array;
-    idx = (ast_value*)self->index;
+        if (!arr->getter) {
+            asterror(ast_ctx(self), "value has no getter, don't know how to index it");
+            return false;
+        }
 
-    if (!idx->isconst) {
-        asterror(ast_ctx(self), "(.2) array indexing here needs a compile-time constant");
-        return false;
+        cgen = self->index->expression.codegen;
+        if (!(*cgen)((ast_expression*)(self->index), func, true, &iridx))
+            return false;
+
+        cgen = arr->getter->expression.codegen;
+        if (!(*cgen)((ast_expression*)(arr->getter), func, true, &funval))
+            return false;
+
+        call = ir_block_create_call(func->curblock, ast_function_label(func, "fetch"), funval);
+        if (!call)
+            return false;
+        if (!ir_call_param(call, iridx))
+            return false;
+
+        *out = ir_call_value(call);
+        self->expression.outr = *out;
+        return true;
     }
 
     if (idx->expression.vtype == TYPE_FLOAT)