From: Wolfgang Bumiller Date: Wed, 29 May 2013 14:51:59 +0000 (+0200) Subject: assignable return value now lives in ast_function, as globals can get overwritten... X-Git-Tag: v0.3.0~151^2~36 X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=afdc0c9dc8c0e71130ee458136415dfd76ac6ab9;p=xonotic%2Fgmqcc.git assignable return value now lives in ast_function, as globals can get overwritten randomly; removed parser_find_retval; updated parse_return --- diff --git a/ast.c b/ast.c index 5039653..4af3e3c 100644 --- a/ast.c +++ b/ast.c @@ -1104,6 +1104,7 @@ ast_function* ast_function_new(lex_ctx ctx, const char *name, ast_value *vtype) self->varargs = NULL; self->argc = NULL; self->fixedparams = NULL; + self->return_value = NULL; return self; } @@ -1133,6 +1134,8 @@ void ast_function_delete(ast_function *self) ast_delete(self->argc); if (self->fixedparams) ast_unref(self->fixedparams); + if (self->return_value) + ast_unref(self->return_value); mem_d(self); } @@ -1625,6 +1628,12 @@ bool ast_function_codegen(ast_function *self, ir_builder *ir) return true; } + // have a local return value variable? + if (self->return_value) { + if (!ast_local_codegen(self->return_value, self->ir_func, false)) + return false; + } + if (!vec_size(self->blocks)) { compile_error(ast_ctx(self), "function `%s` has no body", self->name); return false; diff --git a/ast.h b/ast.h index c624a1f..a0fa14d 100644 --- a/ast.h +++ b/ast.h @@ -622,6 +622,7 @@ struct ast_function_s ast_value *varargs; ast_value *argc; ast_value *fixedparams; + ast_value *return_value; }; ast_function* ast_function_new(lex_ctx ctx, const char *name, ast_value *vtype); /* This will NOT delete the underlying ast_value */ diff --git a/parser.c b/parser.c index d0563c1..5823793 100644 --- a/parser.c +++ b/parser.c @@ -106,13 +106,6 @@ typedef struct parser_s { /* code generator */ code_t *code; - - /* vector of global return vars. - * for example, you can return string, float, vector, or other - * things, hese will be created as globals here instead of - * locals in a function (saves space). - */ - ast_value **returns; } parser_t; static ast_expression * const intrinsic_debug_typestring = (ast_expression*)0x1; @@ -352,29 +345,6 @@ static ast_expression* parser_find_global(parser_t *parser, const char *name) return (ast_expression*)util_htget(parser->htglobals, name); } -static ast_value* parser_find_returnvalue(parser_t *parser, int vtype) -{ - ast_value *out; - size_t i; - char *name = NULL; - - /* find existing global for the job */ - for (i = 0; i < vec_size(parser->returns); i++) - if (parser->returns[i]->expression.vtype == vtype) - return parser->returns[i]; - - util_asprintf(&name, "#ret_%s", type_name[vtype]); - - out = ast_value_new(parser_ctx(parser), name, vtype); - out->hasvalue = false; - out->isimm = false; - - vec_push(parser->returns, out); - - mem_d(name); - return out; -} - static ast_expression* parser_find_param(parser_t *parser, const char *name) { size_t i; @@ -2926,7 +2896,7 @@ static bool parse_return(parser_t *parser, ast_block *block, ast_expression **ou ast_expression *exp = NULL; ast_expression *var = NULL; ast_return *ret = NULL; - ast_expression *find = NULL; + ast_value *retval = parser->function->return_value; ast_value *expected = parser->function->vtype; lex_ctx ctx = parser_ctx(parser); @@ -2944,34 +2914,47 @@ static bool parse_return(parser_t *parser, ast_block *block, ast_expression **ou parseerror(parser, "return assignments not activated, try using -freturn-assigments"); return false; } - + + if (type_store_instr[expected->expression.next->vtype] == VINSTR_END) { + char ty1[1024]; + ast_type_to_string(expected->expression.next, ty1, sizeof(ty1)); + parseerror(parser, "invalid return type: `%s'", ty1); + return false; + } + if (!parser_next(parser)) { parseerror(parser, "expected return assignment expression"); return false; } - + if (!(exp = parse_expression_leave(parser, false, false, false))) return false; - - if (exp->vtype != TYPE_NIL && - exp->vtype != ((ast_expression*)expected)->next->vtype) - { - parseerror(parser, "return assignment with invalid expression"); + + /* prepare the return value */ + if (!retval) { + retval = ast_value_new(ctx, "#LOCAL_RETURN", TYPE_VOID); + ast_type_adopt(retval, expected->expression.next); + parser->function->return_value = retval; + } + + if (!ast_compare_type(exp, (ast_expression*)retval)) { + char ty1[1024], ty2[1024]; + ast_type_to_string(exp, ty1, sizeof(ty1)); + ast_type_to_string(&retval->expression, ty2, sizeof(ty2)); + parseerror(parser, "invalid type for return value: `%s', expected `%s'", ty1, ty2); } - + /* store to 'return' local variable */ var = (ast_expression*)ast_store_new( ctx, - type_store_instr[exp->vtype], - (ast_expression*)parser_find_returnvalue(parser, exp->vtype), - (ast_expression*)exp - ); - + type_store_instr[expected->expression.next->vtype], + (ast_expression*)retval, exp); + if (!var) { ast_unref(exp); return false; } - + *out = var; return true; } @@ -2995,16 +2978,12 @@ static bool parse_return(parser_t *parser, ast_block *block, ast_expression **ou } else { if (!parser_next(parser)) parseerror(parser, "parse error"); - - /* build expression to return */ - if ((find = (ast_expression*)parser_find_returnvalue(parser, expected->expression.next->vtype)) && OPTS_FLAG(RETURN_ASSIGNMENTS)) - ret = ast_return_new(ctx, find); - - else if (expected->expression.next->vtype != TYPE_VOID) + + if (!retval && expected->expression.next->vtype != TYPE_VOID) { (void)!parsewarning(parser, WARN_MISSING_RETURN_VALUES, "return without value"); - ret = ast_return_new(ctx, NULL); } + ret = ast_return_new(ctx, (ast_expression*)retval); } *out = (ast_expression*)ret; return true; @@ -6144,7 +6123,6 @@ parser_t *parser_create() parser->reserved_version = NULL; } - parser->returns = NULL; return parser; } @@ -6226,9 +6204,6 @@ void parser_cleanup(parser_t *parser) for (i = 0; i < vec_size(parser->globals); ++i) { ast_delete(parser->globals[i]); } - for (i = 0; i < vec_size(parser->returns); ++i) { - ast_delete(parser->returns[i]); - } vec_free(parser->accessors); vec_free(parser->functions); vec_free(parser->imm_vector); @@ -6420,13 +6395,6 @@ bool parser_finish(parser_t *parser, const char *output) return false; } } - for (i = 0; i < vec_size(parser->returns); ++i) { - if (!ast_global_codegen(parser->returns[i], ir, false)) { - con_out("internal error: failed to generate return assignment %s\n", parser->returns[i]->name); - ir_builder_delete(ir); - return false; - } - } if (parser->reserved_version && !ast_global_codegen(parser->reserved_version, ir, false)) {