Allow variadic functions to be called

This commit is contained in:
Rui Ueyama 2019-08-25 10:06:54 +09:00
parent d85319fa28
commit 308dc70609
6 changed files with 52 additions and 11 deletions

View File

@ -212,6 +212,7 @@ struct Function {
char *name;
VarList *params;
bool is_static;
bool has_varargs;
Node *node;
VarList *locals;

21
parse.c
View File

@ -609,25 +609,30 @@ static VarList *read_func_param(void) {
return vl;
}
static VarList *read_func_params(void) {
static void read_func_params(Function *fn) {
if (consume(")"))
return NULL;
return;
Token *tok = token;
if (consume("void") && consume(")"))
return NULL;
return;
token = tok;
VarList *head = read_func_param();
VarList *cur = head;
fn->params = read_func_param();
VarList *cur = fn->params;
while (!consume(")")) {
expect(",");
if (consume("...")) {
fn->has_varargs = true;
expect(")");
return;
}
cur->next = read_func_param();
cur = cur->next;
}
return head;
}
// function = basetype declarator "(" params? ")" ("{" stmt* "}" | ";")
@ -651,7 +656,7 @@ static Function *function(void) {
expect("(");
Scope *sc = enter_scope();
fn->params = read_func_params();
read_func_params(fn);
if (consume(";")) {
leave_scope(sc);

View File

@ -36,7 +36,6 @@ EOF
sed -i 's/\berrno\b/*__errno_location()/g' $TMP/$1
sed -i 's/\btrue\b/1/g; s/\bfalse\b/0/g;' $TMP/$1
sed -i 's/\bNULL\b/0/g' $TMP/$1
sed -i 's/, \.\.\.//g' $TMP/$1
sed -i 's/INT_MAX/2147483647/g' $TMP/$1
./chibicc $TMP/$1 > $TMP/${1%.c}.s

9
tests
View File

@ -137,6 +137,9 @@ int counter() {
_Bool true_fn();
_Bool false_fn();
int add_all1(int x, ...);
int add_all3(int z, int b, int c, ...);
int main() {
assert(8, ({ int a=3; int z=5; a+z; }), "int a=3; int z=5; a+z;");
@ -700,6 +703,12 @@ int main() {
assert(1, true_fn(), "true_fn()");
assert(0, false_fn(), "false_fn()");
assert(6, add_all1(1,2,3,0), "add_all1(1,2,3,0)");
assert(5, add_all1(1,2,3,-1,0), "add_all1(1,2,3,-1,0)");
assert(6, add_all3(1,2,3,0), "add_all3(1,2,3,0)");
assert(5, add_all3(1,2,3,-1,0), "add_all3(1,2,3,-1,0)");
printf("OK\n");
return 0;
}

View File

@ -1,7 +1,34 @@
// -*- c -*-
#include <stdarg.h>
int ext1;
int *ext2;
int false_fn() { return 512; }
int true_fn() { return 513; }
int static_fn() { return 5; }
int add_all1(int x, ...) {
va_list ap;
va_start(ap, x);
for (;;) {
int y = va_arg(ap, int);
if (y == 0)
return x;
x += y;
}
}
int add_all3(int x, int y, int z, ...) {
va_list ap;
va_start(ap, z);
x = x + y + z;
for (;;) {
int y = va_arg(ap, int);
if (y == 0)
return x;
x += y;
}
}

View File

@ -160,8 +160,8 @@ static char *starts_with_reserved(char *p) {
}
// Multi-letter punctuator
static char *ops[] = {"<<=", ">>=", "==", "!=", "<=", ">=", "->",
"++", "--", "<<", ">>", "+=", "-=", "*=",
static char *ops[] = {"<<=", ">>=", "...", "==", "!=", "<=", ">=",
"->", "++", "--", "<<", ">>", "+=", "-=", "*=",
"/=", "&&", "||", "&=", "|=", "^="};
for (int i = 0; i < sizeof(ops) / sizeof(*ops); i++)