
関数呼び出しに対応するの大変でした。
正しいかわかりませんが、生成規則を以下のように定義しました。
(試行錯誤のすえ以下のようになったのですが...)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | program: stmt program program: ε stmt: assign ";" assign: equality assign: equality "=" assign equality: add equality: add "==" equality equality: add "!=" equality add: mul add: add "+" mul add: add "-" mul mul: func mul: mul "*" func mul: mul "/" func func: ident "(" argument ")" func: term argument: equality argument: equality "," equality argument: ε term: num term: ident term: "(" assign ")" digit: "0" | "1" | "2" | "3" | "4" | "5 | "6" | "7" | "8" | "9" ident: "a" - "z" |
funcの定義をmulより下に持ってきてさらに引数用のargumentを定義しました。
新しくfuncとargumentを導入したので、コード生成の部分にもそれぞれのパターンを定義してパースしたらうまく動きました。
一旦最大の引数は6個までを制限にしています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | void gen(Node *node) { : if (node->ty == ND_FUNCTION) { // 引数がある場合は引数を評価 if (node->rhs != NULL) { gen(node->rhs); } // 引数をレジスタにセット gen_arguments(node->name, node->val); // 関数名を指定して実行 printf ( " call %s\n" , node->name); // 結果をスタックに入れる printf ( " push rax\n" ); return ; } if (node->ty == ND_ARGUMENT) { // 引数を評価 gen(node->lhs); gen(node->rhs); return ; } : |
あと、RSPを16の倍数にするとの事ですが、変数領域を確保するところで16の倍数にするようにしたのですがよかったのでしょうか。
1 2 3 4 5 6 7 8 9 10 11 12 | : // プロローグ // 変数の数分の領域を確保する // 関数呼び出しをする際にはRSPが16の倍数になっている必要があるとのこと // ココで調整しているけど、正しい? int size_of_variables = variables->keys->len * SIZE_OF_ADDRESS; int rsp_offset = size_of_variables % 16; size_of_variables += rsp_offset; printf ( " push rbp\n" ); printf ( " mov rbp, rsp\n" ); printf ( " sub rsp, %d\n" , size_of_variables); : |
実装したものが動作するかどうかはテスト用の関数が入ったソースを用意して 実際に動作させて確認します。
$ . /9cc "a = hoge(1, 2) * 3;" > tmp.s $ gcc -o tmp tmp.s test .o $ . /tmp $ echo $? # 結果の値になるはず |
ひとまず動作したのでよしとします。
0 件のコメント :
コメントを投稿