Merge branch 'master' into blub/bc3

This commit is contained in:
Wolfgang Bumiller 2012-07-26 23:22:53 +02:00
commit 22e6b8558b
4 changed files with 156 additions and 4 deletions

81
ast.c
View file

@ -193,6 +193,43 @@ void ast_binary_delete(ast_binary *self)
mem_d(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_return* ast_return_new(lex_ctx ctx, int op,
ast_expression *expr)
{
ast_instantiate(ast_return, ctx, ast_return_delete);
ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_return_codegen);
self->operand = expr;
return self;
}
void ast_return_delete(ast_return *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) ast_entfield* ast_entfield_new(lex_ctx ctx, ast_expression *entity, ast_expression *field)
{ {
const ast_expression *outtype; const ast_expression *outtype;
@ -765,6 +802,50 @@ bool ast_binary_codegen(ast_binary *self, ast_function *func, bool lvalue, ir_va
return true; 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, "unary"),
self->op, operand);
if (!*out)
return false;
return true;
}
bool ast_return_codegen(ast_return *self, ast_function *func, bool lvalue, ir_value **out)
{
ast_expression_codegen *cgen;
ir_value *operand;
/* In the context of a return 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;
if (!ir_block_create_return(func->curblock, operand))
return false;
return true;
}
bool ast_entfield_codegen(ast_entfield *self, ast_function *func, bool lvalue, ir_value **out) bool ast_entfield_codegen(ast_entfield *self, ast_function *func, bool lvalue, ir_value **out)
{ {
ast_expression_codegen *cgen; ast_expression_codegen *cgen;

38
ast.h
View file

@ -41,6 +41,8 @@ typedef struct ast_ifthen_s ast_ifthen;
typedef struct ast_ternary_s ast_ternary; typedef struct ast_ternary_s ast_ternary;
typedef struct ast_loop_s ast_loop; typedef struct ast_loop_s ast_loop;
typedef struct ast_call_s ast_call; 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 /* Node interface with common components
*/ */
@ -150,6 +152,42 @@ void ast_binary_delete(ast_binary*);
bool ast_binary_codegen(ast_binary*, ast_function*, bool lvalue, ir_value**); 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**);
/* Return
*
* Make sure 'return' only happens at the end of a block, otherwise the IR
* will refuse to create further instructions.
* This should be honored by the parser.
*/
struct ast_return_s
{
ast_expression_common expression;
ast_expression *operand;
};
ast_return* ast_return_new(lex_ctx ctx,
int op,
ast_expression *expr);
void ast_return_delete(ast_return*);
bool ast_return_codegen(ast_return*, ast_function*, bool lvalue, ir_value**);
/* Entity-field /* Entity-field
* *
* This must do 2 things: * This must do 2 things:

39
ir.c
View file

@ -1216,6 +1216,39 @@ ir_value* ir_block_create_binop(ir_block *self,
return ir_block_create_general_instr(self, label, opcode, left, right, ot); 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, ir_value* ir_block_create_general_instr(ir_block *self, const char *label,
int op, ir_value *a, ir_value *b, int outype) int op, ir_value *a, ir_value *b, int outype)
{ {
@ -2313,10 +2346,8 @@ tailcall:
stmt.o1.u1 = stmt.o3.u1; stmt.o1.u1 = stmt.o3.u1;
stmt.o3.u1 = 0; stmt.o3.u1 = 0;
} }
else if ((stmt.opcode >= INSTR_STORE_F && else if (stmt.opcode >= INSTR_STORE_F &&
stmt.opcode <= INSTR_STORE_FNC) || stmt.opcode <= INSTR_STORE_FNC)
(stmt.opcode >= INSTR_NOT_F &&
stmt.opcode <= INSTR_NOT_FNC))
{ {
/* 2-operand instructions with A -> B */ /* 2-operand instructions with A -> B */
stmt.o2.u1 = stmt.o3.u1; stmt.o2.u1 = stmt.o3.u1;

2
ir.h
View file

@ -181,6 +181,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* ir_block_create_binop(ir_block*, const char *label, int op,
ir_value *left, ir_value *right); 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_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_store(ir_block*, ir_value *target, ir_value *what);
bool GMQCC_WARN ir_block_create_storep(ir_block*, ir_value *target, ir_value *what); bool GMQCC_WARN ir_block_create_storep(ir_block*, ir_value *target, ir_value *what);