Make the varargs counter more stable, it'll now work with a function pointer with a different number of fixed params

This commit is contained in:
Wolfgang Bumiller 2013-01-17 10:30:32 +01:00
parent 4c0a358e2b
commit 1410840ef6
3 changed files with 21 additions and 10 deletions

21
ast.c
View file

@ -348,7 +348,7 @@ ast_value* ast_value_new(lex_ctx ctx, const char *name, int t)
self->getter = NULL; self->getter = NULL;
self->desc = NULL; self->desc = NULL;
self->argcounter = NULL; self->argcounter = NULL;
return self; return self;
} }
@ -1083,8 +1083,9 @@ ast_function* ast_function_new(lex_ctx ctx, const char *name, ast_value *vtype)
vtype->hasvalue = true; vtype->hasvalue = true;
vtype->constval.vfunc = self; vtype->constval.vfunc = self;
self->varargs = NULL; self->varargs = NULL;
self->argc = NULL; self->argc = NULL;
self->fixedparams = NULL;
return self; return self;
} }
@ -1112,6 +1113,8 @@ void ast_function_delete(ast_function *self)
ast_delete(self->varargs); ast_delete(self->varargs);
if (self->argc) if (self->argc)
ast_delete(self->argc); ast_delete(self->argc);
if (self->fixedparams)
ast_unref(self->fixedparams);
mem_d(self); mem_d(self);
} }
@ -1612,13 +1615,23 @@ bool ast_function_codegen(ast_function *self, ir_builder *ir)
if (self->argc) { if (self->argc) {
ir_value *va_count; ir_value *va_count;
ir_value *fixed;
ir_value *sub;
if (!ast_local_codegen(self->argc, self->ir_func, true)) if (!ast_local_codegen(self->argc, self->ir_func, true))
return false; return false;
cgen = self->argc->expression.codegen; cgen = self->argc->expression.codegen;
if (!(*cgen)((ast_expression*)(self->argc), self, false, &va_count)) if (!(*cgen)((ast_expression*)(self->argc), self, false, &va_count))
return false; return false;
cgen = self->fixedparams->expression.codegen;
if (!(*cgen)((ast_expression*)(self->fixedparams), self, false, &fixed))
return false;
sub = ir_block_create_binop(self->curblock, ast_ctx(self),
ast_function_label(self, "va_count"), INSTR_SUB_F,
ir_builder_get_va_count(ir), fixed);
if (!sub)
return false;
if (!ir_block_create_store_op(self->curblock, ast_ctx(self), INSTR_STORE_F, if (!ir_block_create_store_op(self->curblock, ast_ctx(self), INSTR_STORE_F,
va_count, ir_builder_get_va_count(ir))) va_count, sub))
{ {
return false; return false;
} }

1
ast.h
View file

@ -648,6 +648,7 @@ struct ast_function_s
ast_value *varargs; ast_value *varargs;
ast_value *argc; ast_value *argc;
ast_value *fixedparams;
}; };
ast_function* ast_function_new(lex_ctx ctx, const char *name, ast_value *vtype); ast_function* ast_function_new(lex_ctx ctx, const char *name, ast_value *vtype);
/* This will NOT delete the underlying ast_value */ /* This will NOT delete the underlying ast_value */

View file

@ -1450,12 +1450,7 @@ static bool parser_close_call(parser_t *parser, shunt *sy)
if ((fun->expression.flags & AST_FLAG_VARIADIC) && if ((fun->expression.flags & AST_FLAG_VARIADIC) &&
!(/*funval->cvq == CV_CONST && */ funval->hasvalue && funval->constval.vfunc->builtin)) !(/*funval->cvq == CV_CONST && */ funval->hasvalue && funval->constval.vfunc->builtin))
{ {
size_t va_count; call->va_count = (ast_expression*)parser_const_float(parser, (double)paramcount);
if (paramcount < vec_size(fun->expression.params))
va_count = 0;
else
va_count = paramcount - vec_size(fun->expression.params);
call->va_count = (ast_expression*)parser_const_float(parser, (double)va_count);
} }
} }
@ -4065,6 +4060,8 @@ static bool parse_function_body(parser_t *parser, ast_value *var)
goto enderrfn; goto enderrfn;
} }
func->varargs = varargs; func->varargs = varargs;
func->fixedparams = parser_const_float(parser, vec_size(var->expression.params));
} }
parser->function = func; parser->function = func;