以下のような関数処理もコンパイルできるようにする
sum(m, n) { acc = 0; for (i = m; i <= n; i = i + 1) acc = acc + i; return acc; } main() { return sum(1, 10); }
Cではローカル変数はスタックに置くことにしている、グローバル変数はメモリに置く
関数ごとに呼び出されるメモリ領域を「関数フレーム」「アクティベーションレコード」という
レジスタで関数フレームを常に指しているレジスタをベースレジスタ、値をベースポインタと呼ぶ
ベースレジスタはRBPレジスタを使用する
push rbp
mov rbp, rsp
sub rsp, 16
アルファベットの小文字ならばident
// token type 構造体 typedef enum { TK_RESERVED, // op TK_INDENT, TK_NUM, TK_EOF, // end of input } TokenKind;
program = stmt*
stmt = expr “;”
expr = assign
assign = equality (“=” assign)?
equality = relational (“==” relational | “!=” relational)*
relational = add(“<" add | "<=" add | ">” add | “>=” add)*
add = mul (“+” mul | “-” mul)*
mul = unary (“*” unary | “/” unary)*
unary = (“+” | “-“)? primary
primary = num | “(” expr “)”
Node *assign(){ Node *node = equality(); if (consume("=")) node = new_node(ND_ASSIGN, node, assign()); return node; } Node *expr() { return assign(); } Node *stmt() { Node *node = expr(); expect(";"); return node; } void program() { int i = 0; while (!at_eof()) code[i++] = stmt(); code[i] = NULL; }