コンパイラ作りの魅力を語る / Making compilers is fun

7b606c5039f083d13e2d2320ce6ddcfa?s=47 DQNEO
March 30, 2019

コンパイラ作りの魅力を語る / Making compilers is fun

PHPerKaigi 2019で、C/Goコンパイラを作る過程で学んだことについて話しました。

7b606c5039f083d13e2d2320ce6ddcfa?s=128

DQNEO

March 30, 2019
Tweet

Transcript

  1. 11.

    Cコンパイラ (8cc) int sum(int a, int b) { return a

    + b; } sum: push %rbp mov %rsp, %rbp push %rdi push %rsi mov -8(%rbp), %rax mov -16(%rbp), %rcx add %rcx, %rax leave ret C言語 GNU assembler
  2. 14.

    sum: push %rbp mov %rsp, %rbp push %rdi push %rsi

    mov -8(%rbp), %rax mov -16(%rbp), %rcx add %rcx, %rax leave ret アセンブリ言語 ≒ マシン語 • 各行がCPUへの「命令」 • どの行も、ハードウェア に対して副作用を生じる (レジスタ(後述)またはメ モリ上のデータを変更す る)
  3. 15.

    sum: push %rbp mov %rsp, %rbp push %rdi push %rsi

    mov -8(%rbp), %rax mov -16(%rbp), %rcx add %rcx, %rax leave ret GNU Assembler CPUへの命令
  4. 16.

    sum: push %rbp mov %rsp, %rbp push %rdi push %rsi

    mov -8(%rbp), %rax mov -16(%rbp), %rcx add %rcx, %rax leave ret GNU assembler メモリ 読み書き
  5. 17.

    sum: push %rbp mov %rsp, %rbp push %rdi push %rsi

    mov -8(%rbp), %rax mov -16(%rbp), %rcx add %rcx, %rax leave ret GNU assembler レジスタ 読み書き
  6. 20.

    Cコンパイラ (8cc) int sum(int a, int b) { return a

    + b; } sum: push %rbp mov %rsp, %rbp push %rdi push %rsi mov -8(%rbp), %rax mov -16(%rbp), %rcx add %rcx, %rax leave ret C GNU Assembler 関数 → 関数 変数 → メモリ何番目
  7. 29.

    式を評価して値を得る x + y; mov -8(%rbp), %rax mov -16(%rbp), %rcx

    add %rcx, %rax 演算の結果をraxに書き込む
  8. 31.

    関数の戻り値 int sum(int x, int y) { return x +

    y; } sum: push %rbp mov %rsp, %rbp push %rdi push %rsi mov -8(%rbp), %rax mov -16(%rbp), %rcx add %rcx, %rax leave ret raxに値を書き込ん で関数を抜ける。 これが戻り値。 受け取る側は、rax から値を読み出す。 int sum(int x, int y) { return x + y; }
  9. 32.

    関数の戻り値 int sum(int x, int y) { return x +

    y; } sum: push %rbp mov %rsp, %rbp push %rdi push %rsi mov -8(%rbp), %rax mov -16(%rbp), %rcx add %rcx, %rax leave ret int sum(int x, int y) { return x + y; } 「純粋な関数」 も、ハードウェア レベルでは副作 用がある
  10. 38.
  11. 46.

    8cc 1コミット目 #include <stdio.h> #include <stdlib.h> int main(int argc, char

    **argv) { int val; if (scanf("%d", &val) == EOF) { perror("scanf"); exit(1); } printf("\t.text\n\t" ".global mymain\n" "mymain:\n\t" "mov $%d, %%eax\n\t" "ret\n", val); return 0; } #include <stdio.h> extern int mymain(void); int main(int argc, char **argv) { int val = mymain(); printf("%d\n", val); return 0; } https://github.com/rui314/8cc/commit/3764b2071b9601067b81976d80175a0851d0f209