]> git.xonotic.org Git - xonotic/gmqcc.git/commitdiff
Experimental ast_member to access vector members
authorWolfgang (Blub) Bumiller <blub@speed.at>
Wed, 8 Aug 2012 12:49:37 +0000 (14:49 +0200)
committerWolfgang (Blub) Bumiller <blub@speed.at>
Wed, 8 Aug 2012 12:49:37 +0000 (14:49 +0200)
ast.c
ast.h
ir.c
ir.h

diff --git a/ast.c b/ast.c
index 0b61fe0653afbf5b6b6701ff714d0ee98899656c..c19fad2656ba70d43a2d3d3b242c512548bc9ce4 100644 (file)
--- a/ast.c
+++ b/ast.c
@@ -286,6 +286,32 @@ void ast_entfield_delete(ast_entfield *self)
     mem_d(self);
 }
 
+ast_member* ast_member_new(lex_ctx ctx, ast_expression *owner, unsigned int field)
+{
+    ast_instantiate(ast_member, ctx, ast_member_delete);
+    if (field >= 3) {
+        mem_d(self);
+        return NULL;
+    }
+
+    ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_member_codegen);
+
+    self->expression.vtype = TYPE_FLOAT;
+    self->expression.next  = NULL;
+
+    self->owner = owner;
+    self->field = field;
+
+    return self;
+}
+
+void ast_member_delete(ast_member *self)
+{
+    ast_unref(self->owner);
+    ast_expression_delete((ast_expression*)self);
+    mem_d(self);
+}
+
 ast_ifthen* ast_ifthen_new(lex_ctx ctx, ast_expression *cond, ast_expression *ontrue, ast_expression *onfalse)
 {
     ast_instantiate(ast_ifthen, ctx, ast_ifthen_delete);
@@ -911,6 +937,23 @@ bool ast_entfield_codegen(ast_entfield *self, ast_function *func, bool lvalue, i
     return true;
 }
 
+bool ast_member_codegen(ast_member *self, ast_function *func, bool lvalue, ir_value **out)
+{
+    ast_expression_codegen *cgen;
+    ir_value *vec, *field;
+
+    cgen = self->owner->expression.codegen;
+    if (!(*cgen)((ast_expression*)(self->owner), func, true, &vec))
+        return false;
+
+    if (vec->vtype != TYPE_VECTOR)
+        return false;
+
+    *out = ir_value_vector_member(vec, self->field);
+
+    return (*out != NULL);
+}
+
 bool ast_ifthen_codegen(ast_ifthen *self, ast_function *func, bool lvalue, ir_value **out)
 {
     ast_expression_codegen *cgen;
diff --git a/ast.h b/ast.h
index 32b28e537e2f2a08e760df8396c0c9b2dfe2e300..5a09b434764598f282d7ecf10f8981a8b65d2eb7 100644 (file)
--- a/ast.h
+++ b/ast.h
@@ -43,6 +43,7 @@ typedef struct ast_loop_s       ast_loop;
 typedef struct ast_call_s       ast_call;
 typedef struct ast_unary_s      ast_unary;
 typedef struct ast_return_s     ast_return;
+typedef struct ast_member_s     ast_member;
 
 enum {
     TYPE_ast_node,
@@ -58,7 +59,8 @@ enum {
     TYPE_ast_loop,
     TYPE_ast_call,
     TYPE_ast_unary,
-    TYPE_ast_return
+    TYPE_ast_return,
+    TYPE_ast_member
 };
 
 #define ast_istype(x, t) ( ((ast_node_common*)x)->nodetype == (t) )
@@ -229,6 +231,22 @@ void ast_entfield_delete(ast_entfield*);
 
 bool ast_entfield_codegen(ast_entfield*, ast_function*, bool lvalue, ir_value**);
 
+/* Member access:
+ *
+ * For now used for vectors. If we get structs or unions
+ * we can have them handled here as well.
+ */
+struct ast_member_s
+{
+    ast_expression_common expression;
+    ast_expression *owner;
+    unsigned int    field;
+};
+ast_member* ast_member_new(lex_ctx ctx, ast_expression *owner, unsigned int field);
+void ast_member_delete(ast_member*);
+
+bool ast_member_codegen(ast_member*, ast_function*, bool lvalue, ir_value**);
+
 /* Store
  *
  * Stores left<-right and returns left.
diff --git a/ir.c b/ir.c
index 35f00b262c6e607458dfdb86ef6c173d7c6b8cf7..42999c53564770bb53e3910993b630d57568f7ae 100644 (file)
--- a/ir.c
+++ b/ir.c
@@ -519,6 +519,11 @@ bool ir_instr_op(ir_instr *self, int op, ir_value *v, bool writing)
  *IR Value
  */
 
+int32_t ir_value_code_addr(const ir_value *self)
+{
+    return self->code.globaladdr + self->code.addroffset;
+}
+
 ir_value* ir_value_var(const char *name, int storetype, int vtype)
 {
     ir_value *self;
@@ -541,6 +546,27 @@ ir_value* ir_value_var(const char *name, int storetype, int vtype)
     MEM_VECTOR_INIT(self, life);
     return self;
 }
+
+ir_value* ir_value_vector_member(ir_value *self, unsigned int member)
+{
+    ir_value *m;
+    if (member >= 3)
+        return NULL;
+
+    if (self->members[member])
+        return self->members[member];
+
+    m = ir_value_var(self->name, self->store, TYPE_FLOAT);
+    if (!m)
+        return NULL;
+    m->context = self->context;
+
+    self->members[member] = m;
+    m->code.addroffset = member;
+
+    return m;
+}
+
 MEM_VEC_FUNCTIONS(ir_value, ir_life_entry_t, life)
 MEM_VEC_FUNCTIONS_ALL(ir_value, ir_instr*, reads)
 MEM_VEC_FUNCTIONS_ALL(ir_value, ir_instr*, writes)
@@ -560,6 +586,7 @@ ir_value* ir_value_out(ir_function *owner, const char *name, int storetype, int
 
 void ir_value_delete(ir_value* self)
 {
+    size_t i;
     if (self->name)
         mem_d((void*)self->name);
     if (self->isconst)
@@ -567,6 +594,10 @@ void ir_value_delete(ir_value* self)
         if (self->vtype == TYPE_STRING)
             mem_d((void*)self->constval.vstring);
     }
+    for (i = 0; i < 3; ++i) {
+        if (self->members[i])
+            ir_value_delete(self->members[i]);
+    }
     MEM_VECTOR_CLEAR(self, reads);
     MEM_VECTOR_CLEAR(self, writes);
     MEM_VECTOR_CLEAR(self, life);
@@ -2178,7 +2209,7 @@ tailcall:
              * come first: eg. optimize IFs without ELSE...
              */
 
-            stmt.o1.u1 = instr->_ops[0]->code.globaladdr;
+            stmt.o1.u1 = ir_value_code_addr(instr->_ops[0]);
             stmt.o2.u1 = 0;
             stmt.o3.s1 = 0;
 
@@ -2257,7 +2288,7 @@ tailcall:
                 stmt.o3.u1 = 0;
 
                 stmt.opcode = type_store_instr[param->vtype];
-                stmt.o1.u1 = param->code.globaladdr;
+                stmt.o1.u1 = ir_value_code_addr(param);
                 stmt.o2.u1 = OFS_PARM0 + 3 * p;
                 if (code_statements_add(stmt) < 0)
                     return false;
@@ -2265,7 +2296,7 @@ tailcall:
             stmt.opcode = INSTR_CALL0 + instr->params_count;
             if (stmt.opcode > INSTR_CALL8)
                 stmt.opcode = INSTR_CALL8;
-            stmt.o1.u1 = instr->_ops[1]->code.globaladdr;
+            stmt.o1.u1 = ir_value_code_addr(instr->_ops[1]);
             stmt.o2.u1 = 0;
             stmt.o3.u1 = 0;
             if (code_statements_add(stmt) < 0)
@@ -2277,7 +2308,7 @@ tailcall:
                 /* not to be kept in OFS_RETURN */
                 stmt.opcode = type_store_instr[retvalue->vtype];
                 stmt.o1.u1 = OFS_RETURN;
-                stmt.o2.u1 = retvalue->code.globaladdr;
+                stmt.o2.u1 = ir_value_code_addr(retvalue);
                 stmt.o3.u1 = 0;
                 if (code_statements_add(stmt) < 0)
                     return false;
@@ -2297,13 +2328,13 @@ tailcall:
 
         /* This is the general order of operands */
         if (instr->_ops[0])
-            stmt.o3.u1 = instr->_ops[0]->code.globaladdr;
+            stmt.o3.u1 = ir_value_code_addr(instr->_ops[0]);
 
         if (instr->_ops[1])
-            stmt.o1.u1 = instr->_ops[1]->code.globaladdr;
+            stmt.o1.u1 = ir_value_code_addr(instr->_ops[1]);
 
         if (instr->_ops[2])
-            stmt.o2.u1 = instr->_ops[2]->code.globaladdr;
+            stmt.o2.u1 = ir_value_code_addr(instr->_ops[2]);
 
         if (stmt.opcode == INSTR_RETURN || stmt.opcode == INSTR_DONE)
         {
diff --git a/ir.h b/ir.h
index 47ff96b88b30fc279e2be9c91486c0a7133e16ac..e36aa086eb04f3d4a916d713dda275d37c6ad85f 100644 (file)
--- a/ir.h
+++ b/ir.h
@@ -62,12 +62,19 @@ typedef struct ir_value_s {
         int32_t name;
         /* filled by the local-allocator */
         int32_t local;
+        /* added for members */
+        int32_t addroffset;
     } code;
 
+    /* for acessing vectors */
+    struct ir_value_s *members[3];
+
     /* For the temp allocator */
     MEM_VECTOR_MAKE(ir_life_entry_t, life);
 } ir_value;
 
+int32_t ir_value_code_addr(const ir_value*);
+
 /* ir_value can be a variable, or created by an operation */
 ir_value* ir_value_var(const char *name, int st, int vtype);
 /* if a result of an operation: the function should store
@@ -76,6 +83,7 @@ ir_value* ir_value_var(const char *name, int st, int vtype);
 ir_value* ir_value_out(struct ir_function_s *owner, const char *name, int st, int vtype);
 void      ir_value_delete(ir_value*);
 void      ir_value_set_name(ir_value*, const char *name);
+ir_value* ir_value_vector_member(ir_value*, unsigned int member);
 
 MEM_VECTOR_PROTO_ALL(ir_value, struct ir_instr_s*, reads);
 MEM_VECTOR_PROTO_ALL(ir_value, struct ir_instr_s*, writes);