From: Wolfgang (Blub) Bumiller Date: Thu, 28 Jun 2012 15:21:26 +0000 (+0200) Subject: ast_call_codegen, ir_block_create_call plus call-related functions, ir_value->outtype... X-Git-Tag: 0.1-rc1~469 X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=01b3f5ef5834a24a2f2e3743fb4eaeff9eca3ab4;p=xonotic%2Fgmqcc.git ast_call_codegen, ir_block_create_call plus call-related functions, ir_value->outtype TODO: fill outtype in ir_value --- diff --git a/ast.c b/ast.c index 409285d..a155f50 100644 --- 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(¶ms, 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, ¶m)) + goto error; + if (!param) + goto error; + if (!ir_value_vector_v_add(¶ms, 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(¶ms, v); return false; } diff --git a/ir.c b/ir.c index 5cddb2e..2aa879b 100644 --- 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 8bb0789..9379d70 100644 --- 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);