mirror of
https://github.com/DarkPlacesEngine/gmqcc.git
synced 2025-01-18 22:31:36 +00:00
Merge branch 'master' into blub/bc3
This commit is contained in:
commit
55743936d9
4 changed files with 108 additions and 8 deletions
43
ast.c
43
ast.c
|
@ -298,6 +298,32 @@ void ast_entfield_delete(ast_entfield *self)
|
|||
mem_d(self);
|
||||
}
|
||||
|
||||
ast_member* ast_member_new(lex_ctx ctx, ast_expression *owner, unsigned int field)
|
||||
{
|
||||
ast_instantiate(ast_member, ctx, ast_member_delete);
|
||||
if (field >= 3) {
|
||||
mem_d(self);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_member_codegen);
|
||||
|
||||
self->expression.vtype = TYPE_FLOAT;
|
||||
self->expression.next = NULL;
|
||||
|
||||
self->owner = owner;
|
||||
self->field = field;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
void ast_member_delete(ast_member *self)
|
||||
{
|
||||
ast_unref(self->owner);
|
||||
ast_expression_delete((ast_expression*)self);
|
||||
mem_d(self);
|
||||
}
|
||||
|
||||
ast_ifthen* ast_ifthen_new(lex_ctx ctx, ast_expression *cond, ast_expression *ontrue, ast_expression *onfalse)
|
||||
{
|
||||
ast_instantiate(ast_ifthen, ctx, ast_ifthen_delete);
|
||||
|
@ -925,6 +951,23 @@ bool ast_entfield_codegen(ast_entfield *self, ast_function *func, bool lvalue, i
|
|||
return true;
|
||||
}
|
||||
|
||||
bool ast_member_codegen(ast_member *self, ast_function *func, bool lvalue, ir_value **out)
|
||||
{
|
||||
ast_expression_codegen *cgen;
|
||||
ir_value *vec, *field;
|
||||
|
||||
cgen = self->owner->expression.codegen;
|
||||
if (!(*cgen)((ast_expression*)(self->owner), func, true, &vec))
|
||||
return false;
|
||||
|
||||
if (vec->vtype != TYPE_VECTOR)
|
||||
return false;
|
||||
|
||||
*out = ir_value_vector_member(vec, self->field);
|
||||
|
||||
return (*out != NULL);
|
||||
}
|
||||
|
||||
bool ast_ifthen_codegen(ast_ifthen *self, ast_function *func, bool lvalue, ir_value **out)
|
||||
{
|
||||
ast_expression_codegen *cgen;
|
||||
|
|
20
ast.h
20
ast.h
|
@ -43,6 +43,7 @@ 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;
|
||||
typedef struct ast_member_s ast_member;
|
||||
|
||||
enum {
|
||||
TYPE_ast_node,
|
||||
|
@ -58,7 +59,8 @@ enum {
|
|||
TYPE_ast_loop,
|
||||
TYPE_ast_call,
|
||||
TYPE_ast_unary,
|
||||
TYPE_ast_return
|
||||
TYPE_ast_return,
|
||||
TYPE_ast_member
|
||||
};
|
||||
|
||||
#define ast_istype(x, t) ( ((ast_node_common*)x)->nodetype == (t) )
|
||||
|
@ -231,6 +233,22 @@ void ast_entfield_delete(ast_entfield*);
|
|||
|
||||
bool ast_entfield_codegen(ast_entfield*, ast_function*, bool lvalue, ir_value**);
|
||||
|
||||
/* Member access:
|
||||
*
|
||||
* For now used for vectors. If we get structs or unions
|
||||
* we can have them handled here as well.
|
||||
*/
|
||||
struct ast_member_s
|
||||
{
|
||||
ast_expression_common expression;
|
||||
ast_expression *owner;
|
||||
unsigned int field;
|
||||
};
|
||||
ast_member* ast_member_new(lex_ctx ctx, ast_expression *owner, unsigned int field);
|
||||
void ast_member_delete(ast_member*);
|
||||
|
||||
bool ast_member_codegen(ast_member*, ast_function*, bool lvalue, ir_value**);
|
||||
|
||||
/* Store
|
||||
*
|
||||
* Stores left<-right and returns left.
|
||||
|
|
45
ir.c
45
ir.c
|
@ -549,6 +549,11 @@ bool ir_instr_op(ir_instr *self, int op, ir_value *v, bool writing)
|
|||
*IR Value
|
||||
*/
|
||||
|
||||
int32_t ir_value_code_addr(const ir_value *self)
|
||||
{
|
||||
return self->code.globaladdr + self->code.addroffset;
|
||||
}
|
||||
|
||||
ir_value* ir_value_var(const char *name, int storetype, int vtype)
|
||||
{
|
||||
ir_value *self;
|
||||
|
@ -571,6 +576,27 @@ ir_value* ir_value_var(const char *name, int storetype, int vtype)
|
|||
MEM_VECTOR_INIT(self, life);
|
||||
return self;
|
||||
}
|
||||
|
||||
ir_value* ir_value_vector_member(ir_value *self, unsigned int member)
|
||||
{
|
||||
ir_value *m;
|
||||
if (member >= 3)
|
||||
return NULL;
|
||||
|
||||
if (self->members[member])
|
||||
return self->members[member];
|
||||
|
||||
m = ir_value_var(self->name, self->store, TYPE_FLOAT);
|
||||
if (!m)
|
||||
return NULL;
|
||||
m->context = self->context;
|
||||
|
||||
self->members[member] = m;
|
||||
m->code.addroffset = member;
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
MEM_VEC_FUNCTIONS(ir_value, ir_life_entry_t, life)
|
||||
MEM_VEC_FUNCTIONS_ALL(ir_value, ir_instr*, reads)
|
||||
MEM_VEC_FUNCTIONS_ALL(ir_value, ir_instr*, writes)
|
||||
|
@ -590,6 +616,7 @@ ir_value* ir_value_out(ir_function *owner, const char *name, int storetype, int
|
|||
|
||||
void ir_value_delete(ir_value* self)
|
||||
{
|
||||
size_t i;
|
||||
if (self->name)
|
||||
mem_d((void*)self->name);
|
||||
if (self->isconst)
|
||||
|
@ -597,6 +624,10 @@ void ir_value_delete(ir_value* self)
|
|||
if (self->vtype == TYPE_STRING)
|
||||
mem_d((void*)self->constval.vstring);
|
||||
}
|
||||
for (i = 0; i < 3; ++i) {
|
||||
if (self->members[i])
|
||||
ir_value_delete(self->members[i]);
|
||||
}
|
||||
MEM_VECTOR_CLEAR(self, reads);
|
||||
MEM_VECTOR_CLEAR(self, writes);
|
||||
MEM_VECTOR_CLEAR(self, life);
|
||||
|
@ -2237,7 +2268,7 @@ tailcall:
|
|||
* come first: eg. optimize IFs without ELSE...
|
||||
*/
|
||||
|
||||
stmt.o1.u1 = instr->_ops[0]->code.globaladdr;
|
||||
stmt.o1.u1 = ir_value_code_addr(instr->_ops[0]);
|
||||
stmt.o2.u1 = 0;
|
||||
stmt.o3.s1 = 0;
|
||||
|
||||
|
@ -2316,7 +2347,7 @@ tailcall:
|
|||
stmt.o3.u1 = 0;
|
||||
|
||||
stmt.opcode = type_store_instr[param->vtype];
|
||||
stmt.o1.u1 = param->code.globaladdr;
|
||||
stmt.o1.u1 = ir_value_code_addr(param);
|
||||
stmt.o2.u1 = OFS_PARM0 + 3 * p;
|
||||
if (code_statements_add(stmt) < 0)
|
||||
return false;
|
||||
|
@ -2324,7 +2355,7 @@ tailcall:
|
|||
stmt.opcode = INSTR_CALL0 + instr->params_count;
|
||||
if (stmt.opcode > INSTR_CALL8)
|
||||
stmt.opcode = INSTR_CALL8;
|
||||
stmt.o1.u1 = instr->_ops[1]->code.globaladdr;
|
||||
stmt.o1.u1 = ir_value_code_addr(instr->_ops[1]);
|
||||
stmt.o2.u1 = 0;
|
||||
stmt.o3.u1 = 0;
|
||||
if (code_statements_add(stmt) < 0)
|
||||
|
@ -2336,7 +2367,7 @@ tailcall:
|
|||
/* not to be kept in OFS_RETURN */
|
||||
stmt.opcode = type_store_instr[retvalue->vtype];
|
||||
stmt.o1.u1 = OFS_RETURN;
|
||||
stmt.o2.u1 = retvalue->code.globaladdr;
|
||||
stmt.o2.u1 = ir_value_code_addr(retvalue);
|
||||
stmt.o3.u1 = 0;
|
||||
if (code_statements_add(stmt) < 0)
|
||||
return false;
|
||||
|
@ -2356,13 +2387,13 @@ tailcall:
|
|||
|
||||
/* This is the general order of operands */
|
||||
if (instr->_ops[0])
|
||||
stmt.o3.u1 = instr->_ops[0]->code.globaladdr;
|
||||
stmt.o3.u1 = ir_value_code_addr(instr->_ops[0]);
|
||||
|
||||
if (instr->_ops[1])
|
||||
stmt.o1.u1 = instr->_ops[1]->code.globaladdr;
|
||||
stmt.o1.u1 = ir_value_code_addr(instr->_ops[1]);
|
||||
|
||||
if (instr->_ops[2])
|
||||
stmt.o2.u1 = instr->_ops[2]->code.globaladdr;
|
||||
stmt.o2.u1 = ir_value_code_addr(instr->_ops[2]);
|
||||
|
||||
if (stmt.opcode == INSTR_RETURN || stmt.opcode == INSTR_DONE)
|
||||
{
|
||||
|
|
8
ir.h
8
ir.h
|
@ -64,12 +64,19 @@ typedef struct ir_value_s {
|
|||
int32_t name;
|
||||
/* filled by the local-allocator */
|
||||
int32_t local;
|
||||
/* added for members */
|
||||
int32_t addroffset;
|
||||
} code;
|
||||
|
||||
/* for acessing vectors */
|
||||
struct ir_value_s *members[3];
|
||||
|
||||
/* For the temp allocator */
|
||||
MEM_VECTOR_MAKE(ir_life_entry_t, life);
|
||||
} ir_value;
|
||||
|
||||
int32_t ir_value_code_addr(const ir_value*);
|
||||
|
||||
/* ir_value can be a variable, or created by an operation */
|
||||
ir_value* ir_value_var(const char *name, int st, int vtype);
|
||||
/* if a result of an operation: the function should store
|
||||
|
@ -78,6 +85,7 @@ ir_value* ir_value_var(const char *name, int st, int vtype);
|
|||
ir_value* ir_value_out(struct ir_function_s *owner, const char *name, int st, int vtype);
|
||||
void ir_value_delete(ir_value*);
|
||||
void ir_value_set_name(ir_value*, const char *name);
|
||||
ir_value* ir_value_vector_member(ir_value*, unsigned int member);
|
||||
|
||||
MEM_VECTOR_PROTO_ALL(ir_value, struct ir_instr_s*, reads);
|
||||
MEM_VECTOR_PROTO_ALL(ir_value, struct ir_instr_s*, writes);
|
||||
|
|
Loading…
Reference in a new issue