mirror of https://github.com/rui314/chibicc
Support function definition up to 6 parameters
This commit is contained in:
parent
4cd0e82bf1
commit
c86f637f6d
11
chibi.h
11
chibi.h
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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
4
main.c
|
@ -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
42
parse.c
|
@ -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;
|
||||
|
|
3
test.sh
3
test.sh
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue