mirror of
https://github.com/DarkPlacesEngine/gmqcc.git
synced 2025-01-19 06:40:49 +00:00
Type information moved to ast_expression from ast_value, every ast node should in theory know its type - it is important for dereferencing pointers or entity fields, to figure out the output type. Eg. so that ast_entfield knows what kind of OP_LOAD it needs to use
This commit is contained in:
parent
c1a85378d5
commit
da9a4fef29
2 changed files with 94 additions and 16 deletions
97
ast.c
97
ast.c
|
@ -55,6 +55,52 @@ static void ast_expression_init(ast_expression *self,
|
||||||
ast_expression_codegen *codegen)
|
ast_expression_codegen *codegen)
|
||||||
{
|
{
|
||||||
self->expression.codegen = codegen;
|
self->expression.codegen = codegen;
|
||||||
|
self->expression.vtype = TYPE_VOID;
|
||||||
|
self->expression.next = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ast_expression_delete(ast_expression *self)
|
||||||
|
{
|
||||||
|
if (self->expression.next)
|
||||||
|
ast_delete(self->expression.next);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ast_expression_delete_full(ast_expression *self)
|
||||||
|
{
|
||||||
|
ast_expression_delete(self);
|
||||||
|
mem_d(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ast_expression* ast_type_copy(lex_ctx ctx, const ast_expression *ex)
|
||||||
|
{
|
||||||
|
const ast_expression_common *cpex;
|
||||||
|
ast_expression_common *selfex;
|
||||||
|
|
||||||
|
if (!ex)
|
||||||
|
return NULL;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ast_instantiate(ast_expression, ctx, ast_expression_delete_full);
|
||||||
|
|
||||||
|
cpex = &ex->expression;
|
||||||
|
selfex = &self->expression;
|
||||||
|
|
||||||
|
selfex->vtype = cpex->vtype;
|
||||||
|
if (cpex->next)
|
||||||
|
{
|
||||||
|
selfex->next = ast_type_copy(ctx, cpex->next);
|
||||||
|
if (!selfex->next) {
|
||||||
|
mem_d(self);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
selfex->next = NULL;
|
||||||
|
|
||||||
|
/* This may never be codegen()d */
|
||||||
|
selfex->codegen = NULL;
|
||||||
|
return self;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ast_value* ast_value_new(lex_ctx ctx, const char *name, int t)
|
ast_value* ast_value_new(lex_ctx ctx, const char *name, int t)
|
||||||
|
@ -65,8 +111,8 @@ ast_value* ast_value_new(lex_ctx ctx, const char *name, int t)
|
||||||
self->expression.node.keep = true; /* keep */
|
self->expression.node.keep = true; /* keep */
|
||||||
|
|
||||||
self->name = name ? util_strdup(name) : NULL;
|
self->name = name ? util_strdup(name) : NULL;
|
||||||
self->vtype = t;
|
self->expression.vtype = t;
|
||||||
self->next = NULL;
|
self->expression.next = NULL;
|
||||||
MEM_VECTOR_INIT(self, params);
|
MEM_VECTOR_INIT(self, params);
|
||||||
self->isconst = false;
|
self->isconst = false;
|
||||||
memset(&self->constval, 0, sizeof(self->constval));
|
memset(&self->constval, 0, sizeof(self->constval));
|
||||||
|
@ -85,10 +131,8 @@ void ast_value_delete(ast_value* self)
|
||||||
for (i = 0; i < self->params_count; ++i)
|
for (i = 0; i < self->params_count; ++i)
|
||||||
ast_value_delete(self->params[i]); /* delete, the ast_function is expected to die first */
|
ast_value_delete(self->params[i]); /* delete, the ast_function is expected to die first */
|
||||||
MEM_VECTOR_CLEAR(self, params);
|
MEM_VECTOR_CLEAR(self, params);
|
||||||
if (self->next) /* delete, not unref, types are always copied */
|
|
||||||
ast_delete(self->next);
|
|
||||||
if (self->isconst) {
|
if (self->isconst) {
|
||||||
switch (self->vtype)
|
switch (self->expression.vtype)
|
||||||
{
|
{
|
||||||
case TYPE_STRING:
|
case TYPE_STRING:
|
||||||
mem_d((void*)self->constval.vstring);
|
mem_d((void*)self->constval.vstring);
|
||||||
|
@ -104,6 +148,7 @@ void ast_value_delete(ast_value* self)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ast_expression_delete((ast_expression*)self);
|
||||||
mem_d(self);
|
mem_d(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -132,14 +177,33 @@ void ast_binary_delete(ast_binary *self)
|
||||||
{
|
{
|
||||||
ast_unref(self->left);
|
ast_unref(self->left);
|
||||||
ast_unref(self->right);
|
ast_unref(self->right);
|
||||||
|
ast_expression_delete((ast_expression*)self);
|
||||||
mem_d(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;
|
||||||
|
|
||||||
ast_instantiate(ast_entfield, ctx, ast_entfield_delete);
|
ast_instantiate(ast_entfield, ctx, ast_entfield_delete);
|
||||||
|
|
||||||
|
if (field->expression.vtype != TYPE_FIELD) {
|
||||||
|
mem_d(self);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
outtype = field->expression.next;
|
||||||
|
if (!outtype) {
|
||||||
|
mem_d(self);
|
||||||
|
/* Error: field has no type... */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_entfield_codegen);
|
ast_expression_init((ast_expression*)self, (ast_expression_codegen*)&ast_entfield_codegen);
|
||||||
|
|
||||||
|
self->expression.vtype = outtype->expression.vtype;
|
||||||
|
self->expression.next = ast_type_copy(ctx, outtype->expression.next);
|
||||||
|
|
||||||
self->entity = entity;
|
self->entity = entity;
|
||||||
self->field = field;
|
self->field = field;
|
||||||
|
|
||||||
|
@ -150,6 +214,7 @@ void ast_entfield_delete(ast_entfield *self)
|
||||||
{
|
{
|
||||||
ast_unref(self->entity);
|
ast_unref(self->entity);
|
||||||
ast_unref(self->field);
|
ast_unref(self->field);
|
||||||
|
ast_expression_delete((ast_expression*)self);
|
||||||
mem_d(self);
|
mem_d(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -175,6 +240,7 @@ void ast_ifthen_delete(ast_ifthen *self)
|
||||||
ast_unref(self->cond);
|
ast_unref(self->cond);
|
||||||
ast_unref(self->on_true);
|
ast_unref(self->on_true);
|
||||||
ast_unref(self->on_false);
|
ast_unref(self->on_false);
|
||||||
|
ast_expression_delete((ast_expression*)self);
|
||||||
mem_d(self);
|
mem_d(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -201,6 +267,7 @@ void ast_ternary_delete(ast_ternary *self)
|
||||||
ast_unref(self->cond);
|
ast_unref(self->cond);
|
||||||
ast_unref(self->on_true);
|
ast_unref(self->on_true);
|
||||||
ast_unref(self->on_false);
|
ast_unref(self->on_false);
|
||||||
|
ast_expression_delete((ast_expression*)self);
|
||||||
mem_d(self);
|
mem_d(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -221,6 +288,7 @@ void ast_store_delete(ast_store *self)
|
||||||
{
|
{
|
||||||
ast_unref(self->dest);
|
ast_unref(self->dest);
|
||||||
ast_unref(self->source);
|
ast_unref(self->source);
|
||||||
|
ast_expression_delete((ast_expression*)self);
|
||||||
mem_d(self);
|
mem_d(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -247,6 +315,7 @@ void ast_block_delete(ast_block *self)
|
||||||
for (i = 0; i < self->locals_count; ++i)
|
for (i = 0; i < self->locals_count; ++i)
|
||||||
ast_delete(self->locals[i]);
|
ast_delete(self->locals[i]);
|
||||||
MEM_VECTOR_CLEAR(self, locals);
|
MEM_VECTOR_CLEAR(self, locals);
|
||||||
|
ast_expression_delete((ast_expression*)self);
|
||||||
mem_d(self);
|
mem_d(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -256,7 +325,7 @@ ast_function* ast_function_new(lex_ctx ctx, const char *name, ast_value *vtype)
|
||||||
|
|
||||||
if (!vtype ||
|
if (!vtype ||
|
||||||
vtype->isconst ||
|
vtype->isconst ||
|
||||||
vtype->vtype != TYPE_FUNCTION)
|
vtype->expression.vtype != TYPE_FUNCTION)
|
||||||
{
|
{
|
||||||
mem_d(self);
|
mem_d(self);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -331,7 +400,7 @@ bool ast_value_codegen(ast_value *self, ast_function *func, bool lvalue, ir_valu
|
||||||
bool ast_global_codegen(ast_value *self, ir_builder *ir)
|
bool ast_global_codegen(ast_value *self, ir_builder *ir)
|
||||||
{
|
{
|
||||||
ir_value *v = NULL;
|
ir_value *v = NULL;
|
||||||
if (self->isconst && self->vtype == TYPE_FUNCTION)
|
if (self->isconst && self->expression.vtype == TYPE_FUNCTION)
|
||||||
{
|
{
|
||||||
ir_function *func = ir_builder_create_function(ir, self->name);
|
ir_function *func = ir_builder_create_function(ir, self->name);
|
||||||
if (!func)
|
if (!func)
|
||||||
|
@ -342,12 +411,12 @@ bool ast_global_codegen(ast_value *self, ir_builder *ir)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
v = ir_builder_create_global(ir, self->name, self->vtype);
|
v = ir_builder_create_global(ir, self->name, self->expression.vtype);
|
||||||
if (!v)
|
if (!v)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (self->isconst) {
|
if (self->isconst) {
|
||||||
switch (self->vtype)
|
switch (self->expression.vtype)
|
||||||
{
|
{
|
||||||
case TYPE_FLOAT:
|
case TYPE_FLOAT:
|
||||||
if (!ir_value_set_float(v, self->constval.vfloat))
|
if (!ir_value_set_float(v, self->constval.vfloat))
|
||||||
|
@ -367,7 +436,7 @@ bool ast_global_codegen(ast_value *self, ir_builder *ir)
|
||||||
*/
|
*/
|
||||||
goto error;
|
goto error;
|
||||||
default:
|
default:
|
||||||
printf("TODO: global constant type %i\n", self->vtype);
|
printf("TODO: global constant type %i\n", self->expression.vtype);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -384,7 +453,7 @@ error: /* clean up */
|
||||||
bool ast_local_codegen(ast_value *self, ir_function *func)
|
bool ast_local_codegen(ast_value *self, ir_function *func)
|
||||||
{
|
{
|
||||||
ir_value *v = NULL;
|
ir_value *v = NULL;
|
||||||
if (self->isconst && self->vtype == TYPE_FUNCTION)
|
if (self->isconst && self->expression.vtype == TYPE_FUNCTION)
|
||||||
{
|
{
|
||||||
/* Do we allow local functions? I think not...
|
/* Do we allow local functions? I think not...
|
||||||
* this is NOT a function pointer atm.
|
* this is NOT a function pointer atm.
|
||||||
|
@ -392,7 +461,7 @@ bool ast_local_codegen(ast_value *self, ir_function *func)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
v = ir_function_create_local(func, self->name, self->vtype);
|
v = ir_function_create_local(func, self->name, self->expression.vtype);
|
||||||
if (!v)
|
if (!v)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -400,7 +469,7 @@ bool ast_local_codegen(ast_value *self, ir_function *func)
|
||||||
* I suppose the IR will have to deal with this
|
* I suppose the IR will have to deal with this
|
||||||
*/
|
*/
|
||||||
if (self->isconst) {
|
if (self->isconst) {
|
||||||
switch (self->vtype)
|
switch (self->expression.vtype)
|
||||||
{
|
{
|
||||||
case TYPE_FLOAT:
|
case TYPE_FLOAT:
|
||||||
if (!ir_value_set_float(v, self->constval.vfloat))
|
if (!ir_value_set_float(v, self->constval.vfloat))
|
||||||
|
@ -415,7 +484,7 @@ bool ast_local_codegen(ast_value *self, ir_function *func)
|
||||||
goto error;
|
goto error;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printf("TODO: global constant type %i\n", self->vtype);
|
printf("TODO: global constant type %i\n", self->expression.vtype);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
13
ast.h
13
ast.h
|
@ -75,6 +75,8 @@ typedef struct
|
||||||
{
|
{
|
||||||
ast_node_common node;
|
ast_node_common node;
|
||||||
ast_expression_codegen *codegen;
|
ast_expression_codegen *codegen;
|
||||||
|
int vtype;
|
||||||
|
ast_expression *next;
|
||||||
} ast_expression_common;
|
} ast_expression_common;
|
||||||
|
|
||||||
/* Value
|
/* Value
|
||||||
|
@ -90,8 +92,10 @@ struct ast_value_s
|
||||||
|
|
||||||
const char *name;
|
const char *name;
|
||||||
|
|
||||||
|
/*
|
||||||
int vtype;
|
int vtype;
|
||||||
ast_value *next;
|
ast_value *next;
|
||||||
|
*/
|
||||||
|
|
||||||
bool isconst;
|
bool isconst;
|
||||||
union {
|
union {
|
||||||
|
@ -305,8 +309,13 @@ union ast_expression_u
|
||||||
{
|
{
|
||||||
ast_expression_common expression;
|
ast_expression_common expression;
|
||||||
|
|
||||||
ast_binary binary;
|
ast_value value;
|
||||||
ast_block block;
|
ast_binary binary;
|
||||||
|
ast_block block;
|
||||||
|
ast_ternary ternary;
|
||||||
|
ast_ifthen ifthen;
|
||||||
|
ast_store store;
|
||||||
|
ast_entfield entfield;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Node union
|
/* Node union
|
||||||
|
|
Loading…
Reference in a new issue