Skip to content

Commit

Permalink
support return
Browse files Browse the repository at this point in the history
  • Loading branch information
lvlnaga committed Feb 1, 2023
1 parent 94d87ca commit d6ff92f
Show file tree
Hide file tree
Showing 9 changed files with 119 additions and 41 deletions.
5 changes: 5 additions & 0 deletions .vscode/settings.json
@@ -0,0 +1,5 @@
{
"files.associations": {
"typeinfo": "c"
}
}
5 changes: 5 additions & 0 deletions 9cc.c
Expand Up @@ -48,6 +48,11 @@ int main(int argc, char **argv)

// お手本はtokenize()のreturnが無いが、ここは実装を変えない
token = tokenize();

#ifdef DEBUG
token_preview(token);
#endif

program();

// アセンブリ前半部分を出力
Expand Down
7 changes: 5 additions & 2 deletions 9cc.h
Expand Up @@ -9,7 +9,7 @@
#include <string.h>

// For Debug
// #define DEBUG
//#define DEBUG

//
// tokenize.c
Expand All @@ -21,6 +21,7 @@ typedef enum
TK_RESERVED, // 記号
TK_IDENT, // 識別子(変数)
TK_NUM, // 整数トークン
TK_RETURN, // return
TK_EOF, // 入力の終わりを表すトークン
} TokenKind;

Expand Down Expand Up @@ -50,6 +51,7 @@ struct LVar
void error(char *fmt, ...);
void error_at(char *loc, char *fmt, ...);
Token *tokenize();
void token_preview();

//
// parse.c
Expand All @@ -68,7 +70,8 @@ typedef enum
ND_LT, // <
ND_LE, // <=
ND_LVAR, // ローカル変数
ND_NUM // 整数
ND_NUM, // 整数
ND_RETURN // return
} NodeKind;

// 抽象構文木のノードの型
Expand Down
10 changes: 10 additions & 0 deletions codegen.c
Expand Up @@ -19,6 +19,16 @@ void gen(Node *node)
// 左辺の評価
switch (node->kind)
{
case ND_RETURN:
gen(node->lhs);
printf(" pop rax\n"); // スタックに積まれているローカル変数のアドレスをpop
printf(" mov rsp, rbp\n");
printf(" pop rbp\n");
printf(" ret\n");
return;



case ND_NUM:
printf(" push %d\n", node->val);
return;
Expand Down
Binary file modified docs/9cc-memo.xmind
Binary file not shown.
8 changes: 4 additions & 4 deletions docs/step10/ローカル変数用連結リスト.drawio.svg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
66 changes: 45 additions & 21 deletions parse.c
Expand Up @@ -26,6 +26,19 @@ static Token *consume_ident()
return ret;
}


// 次のトークンがreturnのときには、トークンを1つ読み進めて
// Trueをかえす。それ以外の場合はFalseを返す。
static bool consume_return()
{
if (token->kind != TK_RETURN)
return false; // 期待するトークンと不一致(変数でなければ)の場合はNULL
// tokenを次にconsumeする
token = token->next;
return true;
}


// 次のトークンが期待している記号のときには、トークンを1つ読み進める。
// それ以外の場合にはエラーを報告する。
static void expect(char *op)
Expand Down Expand Up @@ -90,15 +103,15 @@ static LVar *find_lvar(Token *tok)
// memcmpはメモリ比較、トークンの文字とvarの文字が一致しているかをチェックしている
{
// すでにlocalsに登録されている場合はその変数のアドレスを返す。
#ifdef DEBUG
#ifdef DEBUG
fprintf(stderr, "lvar is found \n");
#endif
#endif
return var;
}
}
#ifdef DEBUG
fprintf(stderr, "lvar is not found \n");
#endif
#ifdef DEBUG
fprintf(stderr, "lvar is not found \n");
#endif

return NULL;
}
Expand Down Expand Up @@ -136,9 +149,22 @@ void *program()
}

// stmt = expr ";"
// stmt = expr ";"
// | "return" expr ";"
static Node *stmt()
{
Node *node = expr();
Node *node;

if (consume_return())
{
node = calloc(1, sizeof(Node));
node->kind = ND_RETURN;
node->lhs = expr();
}
else
{
node = expr();
}
expect(";");
return node;
}
Expand Down Expand Up @@ -254,37 +280,35 @@ static Node *primary()
node->kind = ND_LVAR;

LVar *lvar = find_lvar(tok);
if (lvar) //既に出現していた変数の場合はその変数のoffsetを使う
if (lvar) // 既に出現していた変数の場合はその変数のoffsetを使う
{
node->offset = lvar->offset;
}
else //新たな変数の場合
else // 新たな変数の場合
{
#ifdef DEBUG
fprintf(stderr, "-------locals pre------------\n");
fprintf(stderr, "locals: %p\n",locals);
fprintf(stderr, "locals->next: %p\n",locals->next);
fprintf(stderr, "locals->tok: %s\n",locals->name);
fprintf(stderr, "locals->offset: %d\n",locals->offset);
fprintf(stderr, "locals: %p\n", locals);
fprintf(stderr, "locals->next: %p\n", locals->next);
fprintf(stderr, "locals->tok: %s\n", locals->name);
fprintf(stderr, "locals->offset: %d\n", locals->offset);
#endif
// 新しいLVarを作る
lvar = calloc(1, sizeof(LVar));
lvar->next = locals;
lvar->name = tok->str;
lvar->len = tok->len;
lvar->offset = locals->offset +8; //TODO:ここでsegumentationフォールと起こったことを書く
node->offset = lvar-> offset;
locals = lvar; //localsを今追加した変数を指すように更新
lvar->offset = locals->offset + 8;
node->offset = lvar->offset;
locals = lvar; // localsを今追加した変数を指すように更新

#ifdef DEBUG
fprintf(stderr, "-------locals post------------\n");
fprintf(stderr, "locals: %p\n",locals);
fprintf(stderr, "locals->next: %p\n",locals->next);
fprintf(stderr, "locals->tok: %s\n",locals->name);
fprintf(stderr, "locals->offset: %d\n",locals->offset);
fprintf(stderr, "locals: %p\n", locals);
fprintf(stderr, "locals->next: %p\n", locals->next);
fprintf(stderr, "locals->tok: %s\n", locals->name);
fprintf(stderr, "locals->offset: %d\n", locals->offset);
#endif
// TODO: localsの連結リストを作っていく流れがよくわからない。next=NULLになっている感じがしない。
// 最後に出てきた変数のnextはlocalsを指していそう。ただ、localsのnextはNULLじゃなさそう
}

return node;
Expand Down
5 changes: 5 additions & 0 deletions test.sh
Expand Up @@ -55,4 +55,9 @@ assert 5 'bar = 2 + 3; bar;'
assert 6 'foo = 1; bar = 2 + 3; foo+bar;'
assert 8 'foo123 = 3; bar = 2 + 3; foo123+bar;'

#Support return
assert 1 'foo = 1; return foo;'
assert 14 'a = 3; b = 5 * 6 - 8; return a + b / 2;'
assert 2 'return 2; return 3;'

echo OK

0 comments on commit d6ff92f

Please sign in to comment.