mirror of
https://github.com/DarkPlacesEngine/gmqcc.git
synced 2025-01-19 14:50:48 +00:00
Merge branch 'master' into blub/bc3
This commit is contained in:
commit
22e6b8558b
4 changed files with 156 additions and 4 deletions
81
ast.c
81
ast.c
|
@ -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
38
ast.h
|
@ -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
39
ir.c
|
@ -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
2
ir.h
|
@ -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);
|
||||||
|
|
Loading…
Reference in a new issue