Support function definition up to 6 parameters

This commit is contained in:
Rui Ueyama 2019-08-05 08:35:49 +09:00
parent 4cd0e82bf1
commit c86f637f6d
5 changed files with 53 additions and 14 deletions

11
chibi.h
View File

@ -48,11 +48,16 @@ extern Token *token;
// Local variable
typedef struct Var Var;
struct Var {
Var *next;
char *name; // Variable name
int offset; // Offset from RBP
};
typedef struct VarList VarList;
struct VarList {
VarList *next;
Var *var;
};
// AST node
typedef enum {
ND_ADD, // +
@ -106,8 +111,10 @@ typedef struct Function Function;
struct Function {
Function *next;
char *name;
VarList *params;
Node *node;
Var *locals;
VarList *locals;
int stack_size;
};

View File

@ -198,6 +198,13 @@ void codegen(Function *prog) {
printf(" mov rbp, rsp\n");
printf(" sub rsp, %d\n", fn->stack_size);
// Push arguments to the stack
int i = 0;
for (VarList *vl = fn->params; vl; vl = vl->next) {
Var *var = vl->var;
printf(" mov [rbp-%d], %s\n", var->offset, argreg[i++]);
}
// Emit code
for (Node *node = fn->node; node; node = node->next)
gen(node);

4
main.c
View File

@ -12,9 +12,9 @@ int main(int argc, char **argv) {
// Assign offsets to local variables.
for (Function *fn = prog; fn; fn = fn->next) {
int offset = 0;
for (Var *var = prog->locals; var; var = var->next) {
for (VarList *vl = fn->locals; vl; vl = vl->next) {
offset += 8;
var->offset = offset;
vl->var->offset = offset;
}
fn->stack_size = offset;
}

42
parse.c
View File

@ -2,13 +2,15 @@
// All local variable instances created during parsing are
// accumulated to this list.
Var *locals;
static VarList *locals;
// Find a local variable by name.
static Var *find_var(Token *tok) {
for (Var *var = locals; var; var = var->next)
for (VarList *vl = locals; vl; vl = vl->next) {
Var *var = vl->var;
if (strlen(var->name) == tok->len && !strncmp(tok->str, var->name, tok->len))
return var;
}
return NULL;
}
@ -45,9 +47,12 @@ static Node *new_var_node(Var *var) {
static Var *new_lvar(char *name) {
Var *var = calloc(1, sizeof(Var));
var->next = locals;
var->name = name;
locals = var;
VarList *vl = calloc(1, sizeof(VarList));
vl->var = var;
vl->next = locals;
locals = vl;
return var;
}
@ -74,25 +79,42 @@ Function *program(void) {
return head.next;
}
// function = ident "(" ")" "{" stmt* "}"
static VarList *read_func_params(void) {
if (consume(")"))
return NULL;
VarList *head = calloc(1, sizeof(VarList));
head->var = new_lvar(expect_ident());
VarList *cur = head;
while (!consume(")")) {
expect(",");
cur->next = calloc(1, sizeof(VarList));
cur->next->var = new_lvar(expect_ident());
cur = cur->next;
}
return head;
}
// function = ident "(" params? ")" "{" stmt* "}"
// params = ident ("," ident)*
static Function *function(void) {
locals = NULL;
char *name = expect_ident();
Function *fn = calloc(1, sizeof(Function));
fn->name = expect_ident();
expect("(");
expect(")");
fn->params = read_func_params();
expect("{");
Node head = {};
Node *cur = &head;
while (!consume("}")) {
cur->next = stmt();
cur = cur->next;
}
Function *fn = calloc(1, sizeof( Function));
fn->name = name;
fn->node = head.next;
fn->locals = locals;
return fn;

View File

@ -87,5 +87,8 @@ assert 2 'main() { return sub(5, 3); }'
assert 21 'main() { return add6(1,2,3,4,5,6); }'
assert 32 'main() { return ret32(); } ret32() { return 32; }'
assert 7 'main() { return add2(3,4); } add2(x,y) { return x+y; }'
assert 1 'main() { return sub2(4,3); } sub2(x,y) { return x-y; }'
assert 55 'main() { return fib(9); } fib(x) { if (x<=1) return 1; return fib(x-1) + fib(x-2); }'
echo OK