diff --git a/chibicc.h b/chibicc.h index f49aed4..1a03824 100644 --- a/chibicc.h +++ b/chibicc.h @@ -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 diff --git a/codegen.c b/codegen.c index 1a8f2ff..43846f1 100644 --- a/codegen.c +++ b/codegen.c @@ -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(); diff --git a/parse.c b/parse.c index 1f5d754..f55285d 100644 --- a/parse.c +++ b/parse.c @@ -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); diff --git a/test.sh b/test.sh index 973e5cd..1d3bdb3 100755 --- a/test.sh +++ b/test.sh @@ -2,6 +2,12 @@ cat <