mirror of
https://github.com/DarkPlacesEngine/gmqcc.git
synced 2025-02-17 09:02:25 +00:00
replacing the current [[accumulate]] implementation: shorter and simpler, and also supports non-void return types
This commit is contained in:
parent
0cfc275f82
commit
8d5e719026
5 changed files with 17 additions and 71 deletions
13
ast.c
13
ast.c
|
@ -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
4
ast.h
|
@ -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
4
ir.c
|
@ -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
1
ir.h
|
@ -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)
|
||||
|
||||
|
|
66
parser.c
66
parser.c
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue