mirror of https://github.com/rui314/chibicc
parent
a901ea056d
commit
7986889a93
26
chibicc.h
26
chibicc.h
|
@ -44,22 +44,22 @@ Token *tokenize(char *input);
|
|||
// parse.c
|
||||
//
|
||||
|
||||
// Local variable
|
||||
// Variable or function
|
||||
typedef struct Var Var;
|
||||
struct Var {
|
||||
Var *next;
|
||||
char *name; // Variable name
|
||||
Type *ty; // Type
|
||||
int offset; // Offset from RBP
|
||||
};
|
||||
char *name; // Variable name
|
||||
Type *ty; // Type
|
||||
bool is_local; // local or global/function
|
||||
|
||||
// Function
|
||||
typedef struct Function Function;
|
||||
struct Function {
|
||||
Function *next;
|
||||
char *name;
|
||||
// Local variable
|
||||
int offset;
|
||||
|
||||
// Global variable or function
|
||||
bool is_function;
|
||||
|
||||
// Function
|
||||
Var *params;
|
||||
|
||||
Node *body;
|
||||
Var *locals;
|
||||
int stack_size;
|
||||
|
@ -116,7 +116,7 @@ struct Node {
|
|||
int val; // Used if kind == ND_NUM
|
||||
};
|
||||
|
||||
Function *parse(Token *tok);
|
||||
Var *parse(Token *tok);
|
||||
|
||||
//
|
||||
// type.c
|
||||
|
@ -168,4 +168,4 @@ void add_type(Node *node);
|
|||
// codegen.c
|
||||
//
|
||||
|
||||
void codegen(Function *prog);
|
||||
void codegen(Var *prog);
|
||||
|
|
17
codegen.c
17
codegen.c
|
@ -2,7 +2,7 @@
|
|||
|
||||
static int depth;
|
||||
static char *argreg[] = {"%rdi", "%rsi", "%rdx", "%rcx", "%r8", "%r9"};
|
||||
static Function *current_fn;
|
||||
static Var *current_fn;
|
||||
|
||||
static void gen_expr(Node *node);
|
||||
|
||||
|
@ -193,8 +193,11 @@ static void gen_stmt(Node *node) {
|
|||
}
|
||||
|
||||
// Assign offsets to local variables.
|
||||
static void assign_lvar_offsets(Function *prog) {
|
||||
for (Function *fn = prog; fn; fn = fn->next) {
|
||||
static void assign_lvar_offsets(Var *prog) {
|
||||
for (Var *fn = prog; fn; fn = fn->next) {
|
||||
if (!fn->is_function)
|
||||
continue;
|
||||
|
||||
int offset = 0;
|
||||
for (Var *var = fn->locals; var; var = var->next) {
|
||||
offset += var->ty->size;
|
||||
|
@ -204,11 +207,15 @@ static void assign_lvar_offsets(Function *prog) {
|
|||
}
|
||||
}
|
||||
|
||||
void codegen(Function *prog) {
|
||||
void codegen(Var *prog) {
|
||||
assign_lvar_offsets(prog);
|
||||
|
||||
for (Function *fn = prog; fn; fn = fn->next) {
|
||||
for (Var *fn = prog; fn; fn = fn->next) {
|
||||
if (!fn->is_function)
|
||||
continue;
|
||||
|
||||
printf(" .globl %s\n", fn->name);
|
||||
printf(" .text\n");
|
||||
printf("%s:\n", fn->name);
|
||||
current_fn = fn;
|
||||
|
||||
|
|
3
main.c
3
main.c
|
@ -4,8 +4,9 @@ int main(int argc, char **argv) {
|
|||
if (argc != 2)
|
||||
error("%s: invalid number of arguments", argv[0]);
|
||||
|
||||
// Tokenize and parse.
|
||||
Token *tok = tokenize(argv[1]);
|
||||
Function *prog = parse(tok);
|
||||
Var *prog = parse(tok);
|
||||
|
||||
// Traverse the AST to emit assembly.
|
||||
codegen(prog);
|
||||
|
|
48
parse.c
48
parse.c
|
@ -20,7 +20,8 @@
|
|||
|
||||
// All local variable instances created during parsing are
|
||||
// accumulated to this list.
|
||||
Var *locals;
|
||||
static Var *locals;
|
||||
static Var *globals;
|
||||
|
||||
static Type *typespec(Token **rest, Token *tok);
|
||||
static Type *declarator(Token **rest, Token *tok, Type *ty);
|
||||
|
@ -78,15 +79,28 @@ static Node *new_var_node(Var *var, Token *tok) {
|
|||
return node;
|
||||
}
|
||||
|
||||
static Var *new_lvar(char *name, Type *ty) {
|
||||
static Var *new_var(char *name, Type *ty) {
|
||||
Var *var = calloc(1, sizeof(Var));
|
||||
var->name = name;
|
||||
var->ty = ty;
|
||||
return var;
|
||||
}
|
||||
|
||||
static Var *new_lvar(char *name, Type *ty) {
|
||||
Var *var = new_var(name, ty);
|
||||
var->is_local = true;
|
||||
var->next = locals;
|
||||
locals = var;
|
||||
return var;
|
||||
}
|
||||
|
||||
static Var *new_gvar(char *name, Type *ty) {
|
||||
Var *var = new_var(name, ty);
|
||||
var->next = globals;
|
||||
globals = var;
|
||||
return var;
|
||||
}
|
||||
|
||||
static char *get_ident(Token *tok) {
|
||||
if (tok->kind != TK_IDENT)
|
||||
error_tok(tok, "expected an identifier");
|
||||
|
@ -544,29 +558,29 @@ static void create_param_lvars(Type *param) {
|
|||
}
|
||||
}
|
||||
|
||||
static Function *function(Token **rest, Token *tok) {
|
||||
Type *ty = typespec(&tok, tok);
|
||||
ty = declarator(&tok, tok, ty);
|
||||
static Token *function(Token *tok, Type *basety) {
|
||||
Type *ty = declarator(&tok, tok, basety);
|
||||
|
||||
Var *fn = new_gvar(get_ident(ty->name), ty);
|
||||
fn->is_function = true;
|
||||
|
||||
locals = NULL;
|
||||
|
||||
Function *fn = calloc(1, sizeof(Function));
|
||||
fn->name = get_ident(ty->name);
|
||||
create_param_lvars(ty->params);
|
||||
fn->params = locals;
|
||||
|
||||
tok = skip(tok, "{");
|
||||
fn->body = compound_stmt(rest, tok);
|
||||
fn->body = compound_stmt(&tok, tok);
|
||||
fn->locals = locals;
|
||||
return fn;
|
||||
return tok;
|
||||
}
|
||||
|
||||
// program = function-definition*
|
||||
Function *parse(Token *tok) {
|
||||
Function head = {};
|
||||
Function *cur = &head;
|
||||
// program = (function-definition | global-variable)*
|
||||
Var *parse(Token *tok) {
|
||||
globals = NULL;
|
||||
|
||||
while (tok->kind != TK_EOF)
|
||||
cur = cur->next = function(&tok, tok);
|
||||
return head.next;
|
||||
while (tok->kind != TK_EOF) {
|
||||
Type *basety = typespec(&tok, tok);
|
||||
tok = function(tok, basety);
|
||||
}
|
||||
return globals;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue