From: Wolfgang Bumiller Date: Thu, 26 Jul 2012 18:45:18 +0000 (+0200) Subject: ast/ir support for unary instructions X-Git-Tag: 0.1-rc1~396^2~2 X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=e22d340e2313c841e9a6c0aeae292a41ac112396;p=xonotic%2Fgmqcc.git ast/ir support for unary instructions --- diff --git a/ast.c b/ast.c index 404df57..70bc037 100644 --- a/ast.c +++ b/ast.c @@ -181,6 +181,25 @@ void ast_binary_delete(ast_binary *self) mem_d(self); } +ast_unary* ast_unary_new(lex_ctx ctx, int op, + ast_expression *expr) +{ + ast_instantiate(ast_unary, ctx, ast_unary_delete); + ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_unary_codegen); + + self->op = op; + self->operand = expr; + + return self; +} + +void ast_unary_delete(ast_unary *self) +{ + ast_unref(self->operand); + ast_expression_delete((ast_expression*)self); + mem_d(self); +} + ast_entfield* ast_entfield_new(lex_ctx ctx, ast_expression *entity, ast_expression *field) { const ast_expression *outtype; @@ -751,6 +770,29 @@ bool ast_binary_codegen(ast_binary *self, ast_function *func, bool lvalue, ir_va return true; } +bool ast_unary_codegen(ast_unary *self, ast_function *func, bool lvalue, ir_value **out) +{ + ast_expression_codegen *cgen; + ir_value *operand; + + /* In the context of a unary operation, we can disregard + * the lvalue flag. + */ + (void)lvalue; + + cgen = self->operand->expression.codegen; + /* lvalue! */ + if (!(*cgen)((ast_expression*)(self->operand), func, false, &operand)) + return false; + + *out = ir_block_create_unary(func->curblock, ast_function_label(func, "bin"), + self->op, operand); + if (!*out) + return false; + + return true; +} + bool ast_entfield_codegen(ast_entfield *self, ast_function *func, bool lvalue, ir_value **out) { ast_expression_codegen *cgen; diff --git a/ast.h b/ast.h index 8ae190d..663099d 100644 --- a/ast.h +++ b/ast.h @@ -41,6 +41,8 @@ typedef struct ast_ifthen_s ast_ifthen; typedef struct ast_ternary_s ast_ternary; 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; /* Node interface with common components */ @@ -148,6 +150,24 @@ void ast_binary_delete(ast_binary*); bool ast_binary_codegen(ast_binary*, ast_function*, bool lvalue, ir_value**); +/* Unary + * + * Regular unary expressions: not,neg + */ +struct ast_unary_s +{ + ast_expression_common expression; + + int op; + ast_expression *operand; +}; +ast_unary* ast_unary_new(lex_ctx ctx, + int op, + ast_expression *expr); +void ast_unary_delete(ast_unary*); + +bool ast_unary_codegen(ast_unary*, ast_function*, bool lvalue, ir_value**); + /* Entity-field * * This must do 2 things: diff --git a/ir.c b/ir.c index 2a5018b..7508f90 100644 --- a/ir.c +++ b/ir.c @@ -1169,6 +1169,39 @@ ir_value* ir_block_create_binop(ir_block *self, return ir_block_create_general_instr(self, label, opcode, left, right, ot); } +ir_value* ir_block_create_unary(ir_block *self, + const char *label, int opcode, + ir_value *operand) +{ + int ot = TYPE_FLOAT; + switch (opcode) { + case INSTR_NOT_F: + case INSTR_NOT_V: + case INSTR_NOT_S: + case INSTR_NOT_ENT: + case INSTR_NOT_FNC: +#if 0 + case INSTR_NOT_I: +#endif + ot = TYPE_FLOAT; + break; + /* QC doesn't have other unary operations. We expect extensions to fill + * the above list, otherwise we assume out-type = in-type, eg for an + * unary minus + */ + default: + ot = operand->vtype; + break; + }; + if (ot == TYPE_VOID) { + /* The AST or parser were supposed to check this! */ + return NULL; + } + + /* let's use the general instruction creator and pass NULL for OPB */ + return ir_block_create_general_instr(self, label, opcode, operand, NULL, ot); +} + ir_value* ir_block_create_general_instr(ir_block *self, const char *label, int op, ir_value *a, ir_value *b, int outype) { diff --git a/ir.h b/ir.h index fb0f699..9eab51f 100644 --- a/ir.h +++ b/ir.h @@ -177,6 +177,8 @@ MEM_VECTOR_PROTO_ALL(ir_block, ir_block*, entries); ir_value* ir_block_create_binop(ir_block*, const char *label, int op, ir_value *left, ir_value *right); +ir_value* ir_block_create_unary(ir_block*, const char *label, int op, + ir_value *operand); bool GMQCC_WARN ir_block_create_store_op(ir_block*, int op, ir_value *target, ir_value *what); bool GMQCC_WARN ir_block_create_store(ir_block*, ir_value *target, ir_value *what); bool GMQCC_WARN ir_block_create_storep(ir_block*, ir_value *target, ir_value *what);