From 6dedddc545e2f1930bdc2256784eb1551bd4231d Mon Sep 17 00:00:00 2001 From: nsfisis Date: Sun, 1 Feb 2026 00:49:15 +0900 Subject: feat(nuldoc): rewrite nuldoc in Ruby --- .../make-tiny-self-hosted-c-compiler/index.html | 78 ++++++++++++---------- 1 file changed, 41 insertions(+), 37 deletions(-) (limited to 'services/nuldoc/public/blog/posts/2025-05-05/make-tiny-self-hosted-c-compiler/index.html') diff --git a/services/nuldoc/public/blog/posts/2025-05-05/make-tiny-self-hosted-c-compiler/index.html b/services/nuldoc/public/blog/posts/2025-05-05/make-tiny-self-hosted-c-compiler/index.html index 29af749d..e2e8bb11 100644 --- a/services/nuldoc/public/blog/posts/2025-05-05/make-tiny-self-hosted-c-compiler/index.html +++ b/services/nuldoc/public/blog/posts/2025-05-05/make-tiny-self-hosted-c-compiler/index.html @@ -359,9 +359,10 @@ compilerbook では整数一つのパース・コード生成から始めるが、今回は以下のようなソースをパースしてコード生成するところからスタートすることにした。

-
int main() {
-    return 42;
-}
+
int main() {
+    return 42;
+}
+

この時点で、struct Tokenstruct Parserstruct AstNodestruct CodeGen といった主要なデータ構造が定義され、この後もほぼ同じソース設計のまま進めている。 @@ -408,23 +409,24 @@ 一日の終わりには、次のようなプログラムのテストが通るようになった。

-
int printf();
-
-int main() {
-    int i;
-    for (i = 1; i <= 100; i = i + 1) {
-        if (i % 15 == 0) {
-            printf("FizzBuzz\n");
-        } else if (i % 3 == 0) {
-            printf("Fizz\n");
-        } else if (i % 5 == 0) {
-            printf("Buzz\n");
-        } else {
-            printf("%d\n", i);
-        }
-    }
-    return 0;
-}
+
int printf();
+
+int main() {
+    int i;
+    for (i = 1; i <= 100; i = i + 1) {
+        if (i % 15 == 0) {
+            printf("FizzBuzz\n");
+        } else if (i % 3 == 0) {
+            printf("Fizz\n");
+        } else if (i % 5 == 0) {
+            printf("Buzz\n");
+        } else {
+            printf("%d\n", i);
+        }
+    }
+    return 0;
+}
+
@@ -513,13 +515,14 @@ 記念すべき (?) 最後のバグはこちら。

-
         gen_expr(g, ast->expr1, GEN_RVAL);
-     } else {
-         gen_expr(g, ast->expr1, GEN_RVAL);
--        gen_lval2rval(ast->expr1->ty);
-+        gen_lval2rval(ast->expr1->ty->to);
-     }
- }
+
         gen_expr(g, ast->expr1, GEN_RVAL);
+     } else {
+         gen_expr(g, ast->expr1, GEN_RVAL);
+-        gen_lval2rval(ast->expr1->ty);
++        gen_lval2rval(ast->expr1->ty->to);
+     }
+ }
+

メモリアドレスから参照先の値を得る際、その型によってロードする命令の種類を変える必要があるのだが、その切替をポインタ型でおこなっていた。正しくは、そのポインタ型が指す型を元にして切り替えなければならない。 @@ -534,16 +537,17 @@ 一体どこが異なるのか。hexdump の差分がこちら。

-
$ diff -u <(hexdump -C p4dcc2) <(hexdump -C p4dcc3)
-@@ -5090,7 +5090,7 @@
- 00015db0  72 72 61 79 5f 65 6e 74  72 79 00 66 72 61 6d 65  |rray_entry.frame|
- 00015dc0  5f 64 75 6d 6d 79 00 5f  5f 66 72 61 6d 65 5f 64  |_dummy.__frame_d|
- 00015dd0  75 6d 6d 79 5f 69 6e 69  74 5f 61 72 72 61 79 5f  |ummy_init_array_|
--00015de0  65 6e 74 72 79 00 63 63  6d 69 42 49 59 6b 2e 6f  |entry.ccmiBIYk.o|
-+00015de0  65 6e 74 72 79 00 63 63  53 71 64 47 76 57 2e 6f  |entry.ccSqdGvW.o|
- 00015df0  00 66 61 74 61 6c 5f 65  72 72 6f 72 00 72 65 61  |.fatal_error.rea|
- 00015e00  64 5f 61 6c 6c 00 74 6f  6b 65 6e 69 7a 65 00 74  |d_all.tokenize.t|
- 00015e10  79 70 65 5f 6e 65 77 00  74 79 70 65 5f 6e 65 77  |ype_new.type_new|
+
$ diff -u <(hexdump -C p4dcc2) <(hexdump -C p4dcc3)
+@@ -5090,7 +5090,7 @@
+ 00015db0  72 72 61 79 5f 65 6e 74  72 79 00 66 72 61 6d 65  |rray_entry.frame|
+ 00015dc0  5f 64 75 6d 6d 79 00 5f  5f 66 72 61 6d 65 5f 64  |_dummy.__frame_d|
+ 00015dd0  75 6d 6d 79 5f 69 6e 69  74 5f 61 72 72 61 79 5f  |ummy_init_array_|
+-00015de0  65 6e 74 72 79 00 63 63  6d 69 42 49 59 6b 2e 6f  |entry.ccmiBIYk.o|
++00015de0  65 6e 74 72 79 00 63 63  53 71 64 47 76 57 2e 6f  |entry.ccSqdGvW.o|
+ 00015df0  00 66 61 74 61 6c 5f 65  72 72 6f 72 00 72 65 61  |.fatal_error.rea|
+ 00015e00  64 5f 61 6c 6c 00 74 6f  6b 65 6e 69 7a 65 00 74  |d_all.tokenize.t|
+ 00015e10  79 70 65 5f 6e 65 77 00  74 79 70 65 5f 6e 65 77  |ype_new.type_new|
+

fatal_errorread_alltokenize type_new はいずれも main.c で定義された関数の名前である。このことから考えると、これは GCC が埋め込んだシンボルテーブルである可能性が高い。わずかに異なっている 6バイトは、ランダム生成された何かのように見える。 -- cgit v1.3-1-g0d28