X-Git-Url: https://git.xonotic.org/?a=blobdiff_plain;f=ast.c;h=944fee9b613dec7ba830c4a5e3d5d05397e5a540;hb=975356cbce515a5d558a9def6f26a4b311965546;hp=f0fba0f99a6d3db764e8f1e51ba3d30f1b4e8e5e;hpb=a4617d0e610380f9048499114b3fc086876bb7eb;p=xonotic%2Fgmqcc.git diff --git a/ast.c b/ast.c index f0fba0f..944fee9 100644 --- a/ast.c +++ b/ast.c @@ -57,12 +57,18 @@ static void ast_expression_init(ast_expression *self, self->expression.codegen = codegen; self->expression.vtype = TYPE_VOID; self->expression.next = NULL; + MEM_VECTOR_INIT(&self->expression, params); } static void ast_expression_delete(ast_expression *self) { + size_t i; if (self->expression.next) ast_delete(self->expression.next); + for (i = 0; i < self->expression.params_count; ++i) { + ast_delete(self->expression.params[i]); + } + MEM_VECTOR_CLEAR(&self->expression, params); } static void ast_expression_delete_full(ast_expression *self) @@ -71,9 +77,26 @@ static void ast_expression_delete_full(ast_expression *self) mem_d(self); } +MEM_VEC_FUNCTIONS(ast_expression_common, ast_value*, params) + +static ast_expression* ast_type_copy(lex_ctx ctx, const ast_expression *ex); +static ast_value* ast_value_copy(const ast_value *self) +{ + ast_value *cp = ast_value_new(self->expression.node.context, self->name, self->expression.vtype); + if (self->expression.next) { + cp->expression.next = ast_type_copy(self->expression.node.context, self->expression.next); + if (!cp->expression.next) { + ast_value_delete(cp); + return NULL; + } + } + return cp; +} + static ast_expression* ast_type_copy(lex_ctx ctx, const ast_expression *ex) { - const ast_expression_common *cpex; + size_t i; + const ast_expression_common *fromex; ast_expression_common *selfex; if (!ex) @@ -82,23 +105,32 @@ static ast_expression* ast_type_copy(lex_ctx ctx, const ast_expression *ex) { ast_instantiate(ast_expression, ctx, ast_expression_delete_full); - cpex = &ex->expression; + fromex = &ex->expression; selfex = &self->expression; - selfex->vtype = cpex->vtype; - if (cpex->next) + /* This may never be codegen()d */ + selfex->codegen = NULL; + + selfex->vtype = fromex->vtype; + if (fromex->next) { - selfex->next = ast_type_copy(ctx, cpex->next); + selfex->next = ast_type_copy(ctx, fromex->next); if (!selfex->next) { - mem_d(self); + ast_expression_delete_full(self); return NULL; } } else selfex->next = NULL; - /* This may never be codegen()d */ - selfex->codegen = NULL; + for (i = 0; i < fromex->params_count; ++i) { + ast_value *v = ast_value_copy(fromex->params[i]); + if (!v || !ast_expression_common_params_add(selfex, v)) { + ast_expression_delete_full(self); + return NULL; + } + } + return self; } } @@ -113,7 +145,6 @@ ast_value* ast_value_new(lex_ctx ctx, const char *name, int t) self->name = name ? util_strdup(name) : NULL; self->expression.vtype = t; self->expression.next = NULL; - MEM_VECTOR_INIT(self, params); self->isconst = false; memset(&self->constval, 0, sizeof(self->constval)); @@ -121,16 +152,11 @@ ast_value* ast_value_new(lex_ctx ctx, const char *name, int t) return self; } -MEM_VEC_FUNCTIONS(ast_value, ast_value*, params) void ast_value_delete(ast_value* self) { - size_t i; if (self->name) mem_d((void*)self->name); - for (i = 0; i < self->params_count; ++i) - ast_value_delete(self->params[i]); /* delete, the ast_function is expected to die first */ - MEM_VECTOR_CLEAR(self, params); if (self->isconst) { switch (self->expression.vtype) { @@ -152,6 +178,11 @@ void ast_value_delete(ast_value* self) mem_d(self); } +bool GMQCC_WARN ast_value_params_add(ast_value *self, ast_value *p) +{ + return ast_expression_common_params_add(&self->expression, p); +} + bool ast_value_set_name(ast_value *self, const char *name) { if (self->name) @@ -170,6 +201,18 @@ ast_binary* ast_binary_new(lex_ctx ctx, int op, self->left = left; self->right = right; + if (op >= INSTR_EQ_F && op <= INSTR_GT) + self->expression.vtype = TYPE_FLOAT; + else if (op == INSTR_AND || op == INSTR_OR || + op == INSTR_BITAND || op == INSTR_BITOR) + self->expression.vtype = TYPE_FLOAT; + else if (op == INSTR_MUL_VF || op == INSTR_MUL_FV) + self->expression.vtype = TYPE_VECTOR; + else if (op == INSTR_MUL_V) + self->expression.vtype = TYPE_FLOAT; + else + self->expression.vtype = left->expression.vtype; + return self; } @@ -181,6 +224,42 @@ void ast_binary_delete(ast_binary *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, 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) { const ast_expression *outtype; @@ -384,6 +463,19 @@ void ast_block_delete(ast_block *self) mem_d(self); } +bool ast_block_set_type(ast_block *self, ast_expression *from) +{ + if (self->expression.next) + ast_delete(self->expression.next); + self->expression.vtype = from->expression.vtype; + if (from->expression.next) { + self->expression.next = ast_type_copy(self->expression.node.context, from->expression.next); + if (!self->expression.next) + return false; + } + return true; +} + ast_function* ast_function_new(lex_ctx ctx, const char *name, ast_value *vtype) { ast_instantiate(ast_function, ctx, ast_function_delete); @@ -399,7 +491,6 @@ ast_function* ast_function_new(lex_ctx ctx, const char *name, ast_value *vtype) self->vtype = vtype; self->name = name ? util_strdup(name) : NULL; MEM_VECTOR_INIT(self, blocks); - MEM_VECTOR_INIT(self, params); self->labelcount = 0; self->builtin = 0; @@ -417,7 +508,6 @@ ast_function* ast_function_new(lex_ctx ctx, const char *name, ast_value *vtype) } MEM_VEC_FUNCTIONS(ast_function, ast_block*, blocks) -MEM_VEC_FUNCTIONS(ast_function, ast_value*, params) void ast_function_delete(ast_function *self) { @@ -436,12 +526,6 @@ void ast_function_delete(ast_function *self) for (i = 0; i < self->blocks_count; ++i) ast_delete(self->blocks[i]); MEM_VECTOR_CLEAR(self, blocks); - /* ast_delete, not unref, there must only have been references - * to the parameter values inside the blocks deleted above. - */ - for (i = 0; i < self->params_count; ++i) - ast_delete(self->params[i]); - MEM_VECTOR_CLEAR(self, params); mem_d(self); } @@ -518,8 +602,10 @@ bool ast_global_codegen(ast_value *self, ir_builder *ir) } v = ir_builder_create_global(ir, self->name, self->expression.vtype); - if (!v) + if (!v) { + printf("ir_builder_create_global failed\n"); return false; + } if (self->isconst) { switch (self->expression.vtype) @@ -609,6 +695,7 @@ bool ast_function_codegen(ast_function *self, ir_builder *ir) { ir_function *irf; ir_value *dummy; + ast_expression_common *ec; size_t i; irf = self->ir_func; @@ -617,22 +704,16 @@ bool ast_function_codegen(ast_function *self, ir_builder *ir) return false; } - if (!self->builtin && self->vtype->params_count != self->params_count) { - printf("ast_function's parameter variables doesn't match the declared parameter count\n"); - printf("%i != %i\n", self->vtype->params_count, self->params_count); - return false; - } - /* fill the parameter list */ - for (i = 0; i < self->vtype->params_count; ++i) + ec = &self->vtype->expression; + for (i = 0; i < ec->params_count; ++i) { - if (!ir_function_params_add(irf, self->vtype->params[i]->expression.vtype)) - return false; - } - /* generate the parameter locals */ - for (i = 0; i < self->params_count; ++i) { - if (!ast_local_codegen(self->params[i], self->ir_func, true)) + if (!ir_function_params_add(irf, ec->params[i]->expression.vtype)) return false; + if (!self->builtin) { + if (!ast_local_codegen(ec->params[i], self->ir_func, true)) + return false; + } } if (self->builtin) { @@ -766,6 +847,50 @@ bool ast_binary_codegen(ast_binary *self, ast_function *func, bool lvalue, ir_va 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) { ast_expression_codegen *cgen; @@ -1261,6 +1386,7 @@ bool ast_call_codegen(ast_call *self, ast_function *func, bool lvalue, ir_value *out = ir_call_value(callinstr); + MEM_VECTOR_CLEAR(¶ms, v); return true; error: MEM_VECTOR_CLEAR(¶ms, v);