replacing the current [[accumulate]] implementation: shorter and simpler, and also supports non-void return types

This commit is contained in:
Wolfgang Bumiller 2013-10-18 11:26:41 +02:00
parent 0cfc275f82
commit 8d5e719026
5 changed files with 17 additions and 71 deletions

13
ast.c
View file

@ -1213,9 +1213,6 @@ ast_function* ast_function_new(lex_ctx_t ctx, const char *name, ast_value *vtype
self->fixedparams = NULL;
self->return_value = NULL;
self->accumulate = NULL;
self->accumulation = 0;
return self;
cleanup:
@ -1873,16 +1870,6 @@ bool ast_function_codegen(ast_function *self, ir_builder *ir)
}
}
/* generate the call for any accumulation */
if (self->accumulate) {
ast_call *call = ast_call_new(ast_ctx(self), (ast_expression*)self->accumulate->vtype);
for (i = 0; i < vec_size(ec->params); i++)
vec_push(call->params, (ast_expression*)ec->params[i]);
vec_push(vec_last(self->blocks)->exprs, (ast_expression*)call);
self->ir_func->flags |= IR_FLAG_ACCUMULATE;
}
for (i = 0; i < vec_size(self->blocks); ++i) {
cgen = self->blocks[i]->expression.codegen;
if (!(*cgen)((ast_expression*)self->blocks[i], self, false, &dummy))

4
ast.h
View file

@ -617,10 +617,6 @@ struct ast_function_s
int builtin;
/* function accumulation */
ast_function *accumulate; /* pointer to the next function in the chain */
size_t accumulation; /* base functions # of accumulations */
ir_function *ir_func;
ir_block *curblock;
ir_block **breakblocks;

4
ir.c
View file

@ -1586,10 +1586,6 @@ bool ir_block_create_return(ir_block *self, lex_ctx_t ctx, ir_value *v)
self->final = true;
/* can eliminate the return instructions for accumulation */
if (self->owner->flags & IR_FLAG_ACCUMULATE)
return true;
self->is_return = true;
in = ir_instr_new(ctx, self, INSTR_RETURN);
if (!in)

1
ir.h
View file

@ -232,7 +232,6 @@ typedef struct ir_function_s
#define IR_FLAG_HAS_GOTO (1<<3)
#define IR_FLAG_INCLUDE_DEF (1<<4)
#define IR_FLAG_ERASEABLE (1<<5)
#define IR_FLAG_ACCUMULATE (1<<6)
#define IR_FLAG_MASK_NO_OVERLAP (IR_FLAG_HAS_ARRAYS | IR_FLAG_HAS_UNINITIALIZED)
#define IR_FLAG_MASK_NO_LOCAL_TEMPS (IR_FLAG_HAS_ARRAYS | IR_FLAG_HAS_UNINITIALIZED)

View file

@ -3984,59 +3984,28 @@ static bool parse_function_body(parser_t *parser, ast_value *var)
}
}
if (var->hasvalue && !(var->expression.flags & AST_FLAG_ACCUMULATE)) {
parseerror(parser, "function `%s` declared with multiple bodies", var->name);
ast_block_delete(block);
goto enderr;
}
/* accumulation? */
if (var->hasvalue && var->expression.vtype == TYPE_FUNCTION) {
ast_value *accum = NULL;
ast_function *previous = NULL;
char acname[1024];
/* only void please */
if (var->expression.next->vtype != TYPE_VOID) {
parseerror(parser, "accumulated function `%s` declared with return type `%s` (accumulated functions must return void)",
var->name,
type_name[var->expression.next->vtype]
);
if (var->hasvalue) {
if (!(var->expression.flags & AST_FLAG_ACCUMULATE)) {
parseerror(parser, "function `%s` declared with multiple bodies", var->name);
ast_block_delete(block);
goto enderr;
}
func = var->constval.vfunc;
/* generate a new name increasing the accumulation count*/
util_snprintf(acname, sizeof(acname), "##ACCUMULATE_%s_%d", var->name, var->constval.vfunc->accumulation++);
accum = ast_value_new(parser_ctx(parser), acname, ((ast_expression*)var)->vtype);
if (!accum)
return false;
ast_type_adopt(accum, var);
func = ast_function_new(ast_ctx(var), NULL, accum);
if (!func)
return false;
parser_addglobal(parser, acname, (ast_expression*)accum);
vec_push(parser->functions, func);
/* update the previous calls accumulate pointer for the codegen */
previous = var->constval.vfunc;
while (previous->accumulate)
previous = previous->accumulate;
if (ast_istype(previous, ast_function))
previous->accumulate = func;
if (!func) {
parseerror(parser, "internal error: NULL function: `%s`", var->name);
ast_block_delete(block);
goto enderr;
}
} else {
func = ast_function_new(ast_ctx(var), var->name, var);
vec_push(parser->functions, func);
}
if (!func) {
parseerror(parser, "failed to allocate function for `%s`", var->name);
ast_block_delete(block);
goto enderr;
if (!func) {
parseerror(parser, "failed to allocate function for `%s`", var->name);
ast_block_delete(block);
goto enderr;
}
vec_push(parser->functions, func);
}
parser_enterblock(parser);
@ -4064,13 +4033,13 @@ static bool parse_function_body(parser_t *parser, ast_value *var)
}
}
if (var->argcounter) {
if (var->argcounter && !func->argc) {
ast_value *argc = ast_value_new(ast_ctx(var), var->argcounter, TYPE_FLOAT);
parser_addlocal(parser, argc->name, (ast_expression*)argc);
func->argc = argc;
}
if (OPTS_FLAG(VARIADIC_ARGS) && var->expression.flags & AST_FLAG_VARIADIC) {
if (OPTS_FLAG(VARIADIC_ARGS) && var->expression.flags & AST_FLAG_VARIADIC && !func->varargs) {
char name[1024];
ast_value *varargs = ast_value_new(ast_ctx(var), "reserved:va_args", TYPE_ARRAY);
varargs->expression.flags |= AST_FLAG_IS_VARARG;
@ -4100,7 +4069,6 @@ static bool parse_function_body(parser_t *parser, ast_value *var)
vec_push(func->blocks, block);
parser->function = old;
if (!parser_leaveblock(parser))
retval = false;