]> de.git.xonotic.org Git - xonotic/gmqcc.git/commitdiff
ast_call_codegen, ir_block_create_call plus call-related functions, ir_value->outtype...
authorWolfgang (Blub) Bumiller <blub@speed.at>
Thu, 28 Jun 2012 15:21:26 +0000 (17:21 +0200)
committerWolfgang (Blub) Bumiller <blub@speed.at>
Thu, 28 Jun 2012 15:21:26 +0000 (17:21 +0200)
ast.c
ir.c
ir.h

diff --git a/ast.c b/ast.c
index 409285d16b9b686286f3f455693b8a3a4ade50c0..a155f50d879662f4b0bbd4231d405bff1b647d2b 100644 (file)
--- a/ast.c
+++ b/ast.c
@@ -1177,5 +1177,52 @@ bool ast_loop_codegen(ast_loop *self, ast_function *func, bool lvalue, ir_value
 bool ast_call_codegen(ast_call *self, ast_function *func, bool lvalue, ir_value **out)
 {
     /* TODO: call ir codegen */
+    ast_expression_codegen *cgen;
+    ir_value_vector         params;
+    ir_instr               *callinstr;
+    size_t i;
+
+    ir_value *funval = NULL;
+
+    /* return values are never rvalues */
+    (void)lvalue;
+
+    cgen = self->func->expression.codegen;
+    if (!(*cgen)((ast_expression*)(self->func), func, false, &funval))
+        return false;
+    if (!funval)
+        return false;
+
+    MEM_VECTOR_INIT(&params, v);
+
+    /* parameters */
+    for (i = 0; i < self->params_count; ++i)
+    {
+        ir_value *param;
+        ast_expression *expr = self->params[i];
+
+        cgen = expr->expression.codegen;
+        if (!(*cgen)(expr, func, false, &param))
+            goto error;
+        if (!param)
+            goto error;
+        if (!ir_value_vector_v_add(&params, param))
+            goto error;
+    }
+
+    callinstr = ir_block_create_call(func->curblock, ast_function_label(func, "call"), funval, funval->outtype);
+    if (!callinstr)
+        goto error;
+
+    for (i = 0; i < params.v_count; ++i) {
+        if (!ir_call_param(callinstr, params.v[i]))
+            goto error;
+    }
+
+    *out = ir_call_value(callinstr);
+
+    return true;
+error:
+    MEM_VECTOR_CLEAR(&params, v);
     return false;
 }
diff --git a/ir.c b/ir.c
index 5cddb2ec07be9f24f0b58b2fd0752720d51197b4..2aa879b07b643be98996d5bc5034ef946e2787ff 100644 (file)
--- a/ir.c
+++ b/ir.c
@@ -44,6 +44,8 @@ size_t type_sizeof[TYPE_COUNT] = {
     3, /* TYPE_VARIANT  */
 };
 
+MEM_VEC_FUNCTIONS(ir_value_vector, ir_value*, v)
+
 /***********************************************************************
  *IR Builder
  */
@@ -362,6 +364,7 @@ ir_instr* ir_instr_new(ir_block* owner, int op)
     return self;
 }
 MEM_VEC_FUNCTIONS(ir_instr, ir_phi_entry_t, phi)
+MEM_VEC_FUNCTIONS(ir_instr, ir_value*, params)
 
 void ir_instr_delete(ir_instr *self)
 {
@@ -432,6 +435,7 @@ ir_value* ir_value_var(const char *name, int storetype, int vtype)
     self = (ir_value*)mem_a(sizeof(*self));
     self->vtype = vtype;
     self->fieldtype = TYPE_VOID;
+    self->outtype = TYPE_VOID;
     self->store = storetype;
     MEM_VECTOR_INIT(self, reads);
     MEM_VECTOR_INIT(self, writes);
@@ -1026,6 +1030,47 @@ bool ir_phi_add(ir_instr* self, ir_block *b, ir_value *v)
     return ir_instr_phi_add(self, pe);
 }
 
+/* call related code */
+ir_instr* ir_block_create_call(ir_block *self, const char *label, ir_value *func, int ot)
+{
+    ir_value *out;
+    ir_instr *in;
+    in = ir_instr_new(self, INSTR_CALL0);
+    if (!in)
+        return NULL;
+    out = ir_value_out(self->owner, label, store_value, ot);
+    if (!out) {
+        ir_instr_delete(in);
+        return NULL;
+    }
+    if (!ir_instr_op(in, 0, out, true) ||
+        !ir_instr_op(in, 1, func, false) ||
+        !ir_block_instr_add(self, in))
+    {
+        ir_instr_delete(in);
+        ir_value_delete(out);
+        return NULL;
+    }
+    return in;
+}
+
+ir_value* ir_call_value(ir_instr *self)
+{
+    return self->_ops[0];
+}
+
+bool ir_call_param(ir_instr* self, ir_value *v)
+{
+    if (!ir_instr_params_add(self, v))
+        return false;
+    if (!ir_value_reads_add(v, self)) {
+        if (!ir_instr_params_remove(self, self->params_count-1))
+            GMQCC_SUPRESS_EMPTY_BODY;
+        return false;
+    }
+    return true;
+}
+
 /* binary op related code */
 
 ir_value* ir_block_create_binop(ir_block *self,
diff --git a/ir.h b/ir.h
index 8bb0789922ca5f86c81bdb34755f0c625f171c4b..9379d70d416bff90c130beaa7a3d7454a237d70e 100644 (file)
--- a/ir.h
+++ b/ir.h
@@ -40,6 +40,8 @@ typedef struct ir_value_s {
     lex_ctx   context;
     /* even the IR knows the subtype of a field */
     int       fieldtype;
+    /* and the output type of a function */
+    int       outtype;
 
     MEM_VECTOR_MAKE(struct ir_instr_s*, reads);
     MEM_VECTOR_MAKE(struct ir_instr_s*, writes);
@@ -100,6 +102,13 @@ bool ir_values_overlap(const ir_value*, const ir_value*);
 void ir_value_dump(ir_value*, int (*oprintf)(const char*,...));
 void ir_value_dump_life(ir_value *self, int (*oprintf)(const char*,...));
 
+/* A vector of IR values */
+typedef struct {
+    MEM_VECTOR_MAKE(ir_value*, v);
+} ir_value_vector;
+MEM_VECTOR_PROTO(ir_value_vector, ir_value*, v);
+
+/* PHI data */
 typedef struct ir_phi_entry_s
 {
     ir_value          *value;
@@ -129,6 +138,8 @@ void      ir_instr_delete(ir_instr*);
 MEM_VECTOR_PROTO(ir_value, ir_phi_entry_t, phi);
 bool GMQCC_WARN ir_instr_op(ir_instr*, int op, ir_value *value, bool writing);
 
+MEM_VECTOR_PROTO(ir_value, ir_value*, params);
+
 void ir_instr_dump(ir_instr* in, char *ind, int (*oprintf)(const char*,...));
 
 /* block */
@@ -187,6 +198,9 @@ ir_value* ir_block_create_div(ir_block*, const char *label, ir_value *l, ir_valu
 ir_instr* ir_block_create_phi(ir_block*, const char *label, int vtype);
 ir_value* ir_phi_value(ir_instr*);
 bool GMQCC_WARN ir_phi_add(ir_instr*, ir_block *b, ir_value *v);
+ir_instr* ir_block_create_call(ir_block*, const char *label, ir_value *func, int otype);
+ir_value* ir_call_value(ir_instr*);
+bool GMQCC_WARN ir_call_param(ir_instr*, ir_value*);
 
 bool GMQCC_WARN ir_block_create_return(ir_block*, ir_value *opt_value);