mirror of
https://github.com/DarkPlacesEngine/gmqcc.git
synced 2025-01-31 12:00:38 +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);
|
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_ifthen* ast_ifthen_new(lex_ctx ctx, ast_expression *cond, ast_expression *ontrue, ast_expression *onfalse)
|
||||||
{
|
{
|
||||||
ast_instantiate(ast_ifthen, ctx, ast_ifthen_delete);
|
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;
|
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)
|
bool ast_ifthen_codegen(ast_ifthen *self, ast_function *func, bool lvalue, ir_value **out)
|
||||||
{
|
{
|
||||||
ast_expression_codegen *cgen;
|
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_call_s ast_call;
|
||||||
typedef struct ast_unary_s ast_unary;
|
typedef struct ast_unary_s ast_unary;
|
||||||
typedef struct ast_return_s ast_return;
|
typedef struct ast_return_s ast_return;
|
||||||
|
typedef struct ast_member_s ast_member;
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
TYPE_ast_node,
|
TYPE_ast_node,
|
||||||
|
@ -58,7 +59,8 @@ enum {
|
||||||
TYPE_ast_loop,
|
TYPE_ast_loop,
|
||||||
TYPE_ast_call,
|
TYPE_ast_call,
|
||||||
TYPE_ast_unary,
|
TYPE_ast_unary,
|
||||||
TYPE_ast_return
|
TYPE_ast_return,
|
||||||
|
TYPE_ast_member
|
||||||
};
|
};
|
||||||
|
|
||||||
#define ast_istype(x, t) ( ((ast_node_common*)x)->nodetype == (t) )
|
#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**);
|
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
|
/* Store
|
||||||
*
|
*
|
||||||
* Stores left<-right and returns left.
|
* 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
|
*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* ir_value_var(const char *name, int storetype, int vtype)
|
||||||
{
|
{
|
||||||
ir_value *self;
|
ir_value *self;
|
||||||
|
@ -571,6 +576,27 @@ ir_value* ir_value_var(const char *name, int storetype, int vtype)
|
||||||
MEM_VECTOR_INIT(self, life);
|
MEM_VECTOR_INIT(self, life);
|
||||||
return self;
|
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(ir_value, ir_life_entry_t, life)
|
||||||
MEM_VEC_FUNCTIONS_ALL(ir_value, ir_instr*, reads)
|
MEM_VEC_FUNCTIONS_ALL(ir_value, ir_instr*, reads)
|
||||||
MEM_VEC_FUNCTIONS_ALL(ir_value, ir_instr*, writes)
|
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)
|
void ir_value_delete(ir_value* self)
|
||||||
{
|
{
|
||||||
|
size_t i;
|
||||||
if (self->name)
|
if (self->name)
|
||||||
mem_d((void*)self->name);
|
mem_d((void*)self->name);
|
||||||
if (self->isconst)
|
if (self->isconst)
|
||||||
|
@ -597,6 +624,10 @@ void ir_value_delete(ir_value* self)
|
||||||
if (self->vtype == TYPE_STRING)
|
if (self->vtype == TYPE_STRING)
|
||||||
mem_d((void*)self->constval.vstring);
|
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, reads);
|
||||||
MEM_VECTOR_CLEAR(self, writes);
|
MEM_VECTOR_CLEAR(self, writes);
|
||||||
MEM_VECTOR_CLEAR(self, life);
|
MEM_VECTOR_CLEAR(self, life);
|
||||||
|
@ -2237,7 +2268,7 @@ tailcall:
|
||||||
* come first: eg. optimize IFs without ELSE...
|
* 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.o2.u1 = 0;
|
||||||
stmt.o3.s1 = 0;
|
stmt.o3.s1 = 0;
|
||||||
|
|
||||||
|
@ -2316,7 +2347,7 @@ tailcall:
|
||||||
stmt.o3.u1 = 0;
|
stmt.o3.u1 = 0;
|
||||||
|
|
||||||
stmt.opcode = type_store_instr[param->vtype];
|
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;
|
stmt.o2.u1 = OFS_PARM0 + 3 * p;
|
||||||
if (code_statements_add(stmt) < 0)
|
if (code_statements_add(stmt) < 0)
|
||||||
return false;
|
return false;
|
||||||
|
@ -2324,7 +2355,7 @@ tailcall:
|
||||||
stmt.opcode = INSTR_CALL0 + instr->params_count;
|
stmt.opcode = INSTR_CALL0 + instr->params_count;
|
||||||
if (stmt.opcode > INSTR_CALL8)
|
if (stmt.opcode > INSTR_CALL8)
|
||||||
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.o2.u1 = 0;
|
||||||
stmt.o3.u1 = 0;
|
stmt.o3.u1 = 0;
|
||||||
if (code_statements_add(stmt) < 0)
|
if (code_statements_add(stmt) < 0)
|
||||||
|
@ -2336,7 +2367,7 @@ tailcall:
|
||||||
/* not to be kept in OFS_RETURN */
|
/* not to be kept in OFS_RETURN */
|
||||||
stmt.opcode = type_store_instr[retvalue->vtype];
|
stmt.opcode = type_store_instr[retvalue->vtype];
|
||||||
stmt.o1.u1 = OFS_RETURN;
|
stmt.o1.u1 = OFS_RETURN;
|
||||||
stmt.o2.u1 = retvalue->code.globaladdr;
|
stmt.o2.u1 = ir_value_code_addr(retvalue);
|
||||||
stmt.o3.u1 = 0;
|
stmt.o3.u1 = 0;
|
||||||
if (code_statements_add(stmt) < 0)
|
if (code_statements_add(stmt) < 0)
|
||||||
return false;
|
return false;
|
||||||
|
@ -2356,13 +2387,13 @@ tailcall:
|
||||||
|
|
||||||
/* This is the general order of operands */
|
/* This is the general order of operands */
|
||||||
if (instr->_ops[0])
|
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])
|
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])
|
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)
|
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;
|
int32_t name;
|
||||||
/* filled by the local-allocator */
|
/* filled by the local-allocator */
|
||||||
int32_t local;
|
int32_t local;
|
||||||
|
/* added for members */
|
||||||
|
int32_t addroffset;
|
||||||
} code;
|
} code;
|
||||||
|
|
||||||
|
/* for acessing vectors */
|
||||||
|
struct ir_value_s *members[3];
|
||||||
|
|
||||||
/* For the temp allocator */
|
/* For the temp allocator */
|
||||||
MEM_VECTOR_MAKE(ir_life_entry_t, life);
|
MEM_VECTOR_MAKE(ir_life_entry_t, life);
|
||||||
} ir_value;
|
} ir_value;
|
||||||
|
|
||||||
|
int32_t ir_value_code_addr(const ir_value*);
|
||||||
|
|
||||||
/* ir_value can be a variable, or created by an operation */
|
/* ir_value can be a variable, or created by an operation */
|
||||||
ir_value* ir_value_var(const char *name, int st, int vtype);
|
ir_value* ir_value_var(const char *name, int st, int vtype);
|
||||||
/* if a result of an operation: the function should store
|
/* 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);
|
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_delete(ir_value*);
|
||||||
void ir_value_set_name(ir_value*, const char *name);
|
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*, reads);
|
||||||
MEM_VECTOR_PROTO_ALL(ir_value, struct ir_instr_s*, writes);
|
MEM_VECTOR_PROTO_ALL(ir_value, struct ir_instr_s*, writes);
|
||||||
|
|
Loading…
Reference in a new issue