Merge Function with Var

No functional change
This commit is contained in:
Rui Ueyama 2020-09-04 17:58:53 +09:00
parent a901ea056d
commit 7986889a93
4 changed files with 58 additions and 36 deletions

View File

@ -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);

View File

@ -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
View File

@ -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
View File

@ -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;
}