aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2026-01-08 00:36:43 +0900
committernsfisis <nsfisis@gmail.com>2026-01-08 00:42:05 +0900
commite631486866eed1a1d68911d79aa7b5415e94815a (patch)
treec904a4e85c12e318732a0abcd591f1f441f51042
parent41d24c967eb5fce3f811fc567f60204c77dada15 (diff)
downloadducc-e631486866eed1a1d68911d79aa7b5415e94815a.tar.gz
ducc-e631486866eed1a1d68911d79aa7b5415e94815a.tar.zst
ducc-e631486866eed1a1d68911d79aa7b5415e94815a.zip
feat: fib() now compiles to wasm target
-rw-r--r--src/codegen_wasm.c49
-rw-r--r--tests/wasm.sh31
2 files changed, 76 insertions, 4 deletions
diff --git a/src/codegen_wasm.c b/src/codegen_wasm.c
index 1072b67..335a527 100644
--- a/src/codegen_wasm.c
+++ b/src/codegen_wasm.c
@@ -39,11 +39,19 @@ static void codegen_func_prologue(CodeGen* g, AstNode* ast) {
static void codegen_func_epilogue(CodeGen* g, AstNode* ast) {
}
+static void codegen_int_expr(CodeGen* g, AstNode* ast) {
+ fprintf(g->out, " i32.const %d\n", ast->node_int_value);
+}
+
static void codegen_binary_expr(CodeGen* g, AstNode* ast, GenMode gen_mode) {
codegen_expr(g, ast->node_lhs, gen_mode);
codegen_expr(g, ast->node_rhs, gen_mode);
if (ast->node_op == TokenKind_plus) {
- fprintf(g->out, "i32.add\n");
+ fprintf(g->out, " i32.add\n");
+ } else if (ast->node_op == TokenKind_minus) {
+ fprintf(g->out, " i32.sub\n");
+ } else if (ast->node_op == TokenKind_le) {
+ fprintf(g->out, " i32.le_s\n");
} else {
unreachable();
}
@@ -53,11 +61,24 @@ static void codegen_lvar(CodeGen* g, AstNode* ast, GenMode gen_mode) {
fprintf(g->out, " local.get $l_%s\n", ast->name);
}
+static void codegen_func_call(CodeGen* g, AstNode* ast) {
+ AstNode* args = ast->node_args;
+ for (int i = 0; i < args->node_len; ++i) {
+ AstNode* arg = args->node_items + i;
+ codegen_expr(g, arg, GenMode_rval);
+ }
+ fprintf(g->out, " call $%s\n", ast->name);
+}
+
static void codegen_expr(CodeGen* g, AstNode* ast, GenMode gen_mode) {
- if (ast->kind == AstNodeKind_binary_expr) {
+ if (ast->kind == AstNodeKind_int_expr) {
+ codegen_int_expr(g, ast);
+ } else if (ast->kind == AstNodeKind_binary_expr) {
codegen_binary_expr(g, ast, gen_mode);
} else if (ast->kind == AstNodeKind_lvar) {
codegen_lvar(g, ast, gen_mode);
+ } else if (ast->kind == AstNodeKind_func_call) {
+ codegen_func_call(g, ast);
} else {
unreachable();
}
@@ -67,7 +88,25 @@ static void codegen_return_stmt(CodeGen* g, AstNode* ast) {
if (ast->node_expr) {
codegen_expr(g, ast->node_expr, GenMode_rval);
}
- codegen_func_epilogue(g, ast);
+ fprintf(g->out, " return\n");
+}
+
+static void codegen_if_stmt(CodeGen* g, AstNode* ast) {
+ codegen_expr(g, ast->node_cond, GenMode_rval);
+ fprintf(g->out, " (if (result i32)\n");
+ fprintf(g->out, " (then\n");
+ codegen_stmt(g, ast->node_then);
+ fprintf(g->out, " )\n");
+ if (ast->node_else) {
+ fprintf(g->out, " (else\n");
+ codegen_stmt(g, ast->node_else);
+ fprintf(g->out, " )\n");
+ } else {
+ fprintf(g->out, " (else\n");
+ fprintf(g->out, " i32.const 0\n");
+ fprintf(g->out, " )\n");
+ }
+ fprintf(g->out, " )\n");
}
static void codegen_nop(CodeGen* g, AstNode* ast) {
@@ -85,6 +124,8 @@ static void codegen_stmt(CodeGen* g, AstNode* ast) {
codegen_block_stmt(g, ast);
} else if (ast->kind == AstNodeKind_return_stmt) {
codegen_return_stmt(g, ast);
+ } else if (ast->kind == AstNodeKind_if_stmt) {
+ codegen_if_stmt(g, ast);
} else if (ast->kind == AstNodeKind_nop) {
codegen_nop(g, ast);
} else {
@@ -95,7 +136,7 @@ static void codegen_stmt(CodeGen* g, AstNode* ast) {
static void codegen_func(CodeGen* g, AstNode* ast) {
g->current_func = ast;
- fprintf(g->out, "(func (export \"%s\") \n", ast->name);
+ fprintf(g->out, "(func $%s (export \"%s\")", ast->name, ast->name);
codegen_func_prologue(g, ast);
codegen_stmt(g, ast->node_body);
diff --git a/tests/wasm.sh b/tests/wasm.sh
index d024989..e97c05f 100644
--- a/tests/wasm.sh
+++ b/tests/wasm.sh
@@ -23,3 +23,34 @@ cat > expected <<'EOF'
EOF
diff -u expected output
+
+
+cat > main.c <<'EOF'
+int fib(int n) {
+ if (n <= 1) {
+ return 1;
+ } else {
+ return fib(n - 1) + fib(n - 2);
+ }
+}
+EOF
+
+"$ducc" "${CFLAGS:-}" --wasm -o main.wat main.c
+
+wat2wasm main.wat -o main.wasm
+
+cat > main.mjs <<'EOF'
+import { readFile } from 'fs/promises';
+
+const wasmBuffer = await readFile('./main.wasm');
+const { instance } = await WebAssembly.instantiate(wasmBuffer);
+
+console.log(instance.exports.fib(10));
+EOF
+node main.mjs > output
+
+cat > expected <<'EOF'
+89
+EOF
+
+diff -u expected output