Support function call with up to 6 arguments

This commit is contained in:
Rui Ueyama 2019-08-04 19:03:46 +09:00
parent 30a3992627
commit 964b1d2a0e
4 changed files with 50 additions and 9 deletions

View File

@ -108,6 +108,7 @@ struct Node {
// Function call
char *funcname;
Node *args;
Obj *var; // Used if kind == ND_VAR
int val; // Used if kind == ND_NUM

View File

@ -1,6 +1,7 @@
#include "chibicc.h"
static int depth;
static char *argreg[] = {"%rdi", "%rsi", "%rdx", "%rcx", "%r8", "%r9"};
static void gen_expr(Node *node);
@ -68,11 +69,22 @@ static void gen_expr(Node *node) {
pop("%rdi");
printf(" mov %%rax, (%%rdi)\n");
return;
case ND_FUNCALL:
case ND_FUNCALL: {
int nargs = 0;
for (Node *arg = node->args; arg; arg = arg->next) {
gen_expr(arg);
push();
nargs++;
}
for (int i = nargs - 1; i >= 0; i--)
pop(argreg[i]);
printf(" mov $0, %%rax\n");
printf(" call %s\n", node->funcname);
return;
}
}
gen_expr(node->rhs);
push();

33
parse.c
View File

@ -418,8 +418,29 @@ static Node *unary(Token **rest, Token *tok) {
return primary(rest, tok);
}
// primary = "(" expr ")" | ident args? | num
// args = "(" ")"
// funcall = ident "(" (assign ("," assign)*)? ")"
static Node *funcall(Token **rest, Token *tok) {
Token *start = tok;
tok = tok->next->next;
Node head = {};
Node *cur = &head;
while (!equal(tok, ")")) {
if (cur != &head)
tok = skip(tok, ",");
cur = cur->next = assign(&tok, tok);
}
*rest = skip(tok, ")");
Node *node = new_node(ND_FUNCALL, start);
node->funcname = strndup(start->loc, start->len);
node->args = head.next;
return node;
}
// primary = "(" expr ")" | ident func-args? | num
static Node *primary(Token **rest, Token *tok) {
if (equal(tok, "(")) {
Node *node = expr(&tok, tok->next);
@ -429,12 +450,8 @@ static Node *primary(Token **rest, Token *tok) {
if (tok->kind == TK_IDENT) {
// Function call
if (equal(tok->next, "(")) {
Node *node = new_node(ND_FUNCALL, tok);
node->funcname = strndup(tok->loc, tok->len);
*rest = skip(tok->next->next, ")");
return node;
}
if (equal(tok->next, "("))
return funcall(rest, tok);
// Variable
Obj *var = find_var(tok);

11
test.sh
View File

@ -2,6 +2,12 @@
cat <<EOF | gcc -xc -c -o tmp2.o -
int ret3() { return 3; }
int ret5() { return 5; }
int add(int x, int y) { return x+y; }
int sub(int x, int y) { return x-y; }
int add6(int a, int b, int c, int d, int e, int f) {
return a+b+c+d+e+f;
}
EOF
assert() {
@ -99,5 +105,10 @@ assert 8 '{ int x=3, y=5; return x+y; }'
assert 3 '{ return ret3(); }'
assert 5 '{ return ret5(); }'
assert 8 '{ return add(3, 5); }'
assert 2 '{ return sub(5, 3); }'
assert 21 '{ return add6(1,2,3,4,5,6); }'
assert 66 '{ return add6(1,2,add6(3,4,5,6,7,8),9,10,11); }'
assert 136 '{ return add6(1,2,add6(3,add6(4,5,6,7,8,9),10,11,12,13),14,15,16); }'
echo OK