Make the varargs counter more stable, it'll now work with a function pointer with...
authorWolfgang Bumiller <blub@speed.at>
Thu, 17 Jan 2013 09:30:32 +0000 (10:30 +0100)
committerWolfgang Bumiller <blub@speed.at>
Thu, 17 Jan 2013 09:30:32 +0000 (10:30 +0100)
ast.c
ast.h
parser.c

diff --git a/ast.c b/ast.c
index 5a553cfffbf3fe366084b9ba15e48d719853c03b..108489ff24ad51f563d1d854f4739e6a7adebcfe 100644 (file)
--- a/ast.c
+++ b/ast.c
@@ -348,7 +348,7 @@ ast_value* ast_value_new(lex_ctx ctx, const char *name, int t)
     self->getter = NULL;
     self->desc   = NULL;
 
-    self->argcounter = NULL;
+    self->argcounter  = NULL;
 
     return self;
 }
@@ -1083,8 +1083,9 @@ ast_function* ast_function_new(lex_ctx ctx, const char *name, ast_value *vtype)
     vtype->hasvalue = true;
     vtype->constval.vfunc = self;
 
-    self->varargs = NULL;
-    self->argc    = NULL;
+    self->varargs     = NULL;
+    self->argc        = NULL;
+    self->fixedparams = NULL;
 
     return self;
 }
@@ -1112,6 +1113,8 @@ void ast_function_delete(ast_function *self)
         ast_delete(self->varargs);
     if (self->argc)
         ast_delete(self->argc);
+    if (self->fixedparams)
+        ast_unref(self->fixedparams);
     mem_d(self);
 }
 
@@ -1612,13 +1615,23 @@ bool ast_function_codegen(ast_function *self, ir_builder *ir)
 
     if (self->argc) {
         ir_value *va_count;
+        ir_value *fixed;
+        ir_value *sub;
         if (!ast_local_codegen(self->argc, self->ir_func, true))
             return false;
         cgen = self->argc->expression.codegen;
         if (!(*cgen)((ast_expression*)(self->argc), self, false, &va_count))
             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,
-                                      va_count, ir_builder_get_va_count(ir)))
+                                      va_count, sub))
         {
             return false;
         }
diff --git a/ast.h b/ast.h
index 2e9858fc85054ed6c6ff81dd7ebbe295d7bd7e77..94f388e596a36ee395788a29585799d83a49546d 100644 (file)
--- a/ast.h
+++ b/ast.h
@@ -648,6 +648,7 @@ struct ast_function_s
 
     ast_value   *varargs;
     ast_value   *argc;
+    ast_value   *fixedparams;
 };
 ast_function* ast_function_new(lex_ctx ctx, const char *name, ast_value *vtype);
 /* This will NOT delete the underlying ast_value */
index 2616081a1b52d0d7263494b03f57356d5dbc729f..f5891e7f9864e74c264804154859c56dafbbd63d 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -1450,12 +1450,7 @@ static bool parser_close_call(parser_t *parser, shunt *sy)
         if ((fun->expression.flags & AST_FLAG_VARIADIC) &&
             !(/*funval->cvq == CV_CONST && */ funval->hasvalue && funval->constval.vfunc->builtin))
         {
-            size_t va_count;
-            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);
+            call->va_count = (ast_expression*)parser_const_float(parser, (double)paramcount);
         }
     }
 
@@ -4065,6 +4060,8 @@ static bool parse_function_body(parser_t *parser, ast_value *var)
             goto enderrfn;
         }
         func->varargs = varargs;
+
+        func->fixedparams = parser_const_float(parser, vec_size(var->expression.params));
     }
 
     parser->function = func;