restore(lang): full lang tree from ff3ef452 (306 files) — compiler, vm, shared, runner, c-abi, etc.\n\n- Restores lang/ directory (files≈306, dirs≈64) as per historical branch with selfhost sources\n- Keeps our recent parser index changes in compiler/* (merged clean by checkout)\n- Unblocks selfhost development and documentation references
This commit is contained in:
252
lang/src/llvm_ir/boxes/aot_facade.hako
Normal file
252
lang/src/llvm_ir/boxes/aot_facade.hako
Normal file
@ -0,0 +1,252 @@
|
||||
// LLVMAotFacadeBox — IR 文字列(JSON v0)をファイルに書き出し、AotBox で compile/link する薄い委譲層
|
||||
using "lang/src/llvm_ir/boxes/builder.hako" as LLVMBuilderBox
|
||||
// Note: Convenience wrappers build JSON inline to avoid nested resolver issues
|
||||
|
||||
static box LLVMAotFacadeBox {
|
||||
_truthy(s){ if !s { return 0 } local l = s.toLowerCase(); return (l=="1"||l=="true"||l=="on"||l=="yes") }
|
||||
_route(){
|
||||
// Decide route by env (read-only). Default = lib (via AotBox)
|
||||
// HAKO_AOT_USE_FFI=1 → ffi, HAKO_AOT_USE_PLUGIN=1 → plugin, else lib
|
||||
local ffi = call("env.local.get/1", "HAKO_AOT_USE_FFI"); if LLVMAotFacadeBox._truthy(ffi) { return "ffi" }
|
||||
local plug = call("env.local.get/1", "HAKO_AOT_USE_PLUGIN"); if LLVMAotFacadeBox._truthy(plug) { return "plugin" }
|
||||
return "lib"
|
||||
}
|
||||
_q(s){ return "\"" + s + "\"" }
|
||||
_i(n){ return "" + n }
|
||||
_inst_const(dst, val){
|
||||
return "{\"op\":\"const\",\"dst\":" + me._i(dst) + ",\"value\":{\"type\":\"i64\",\"value\":" + me._i(val) + "}}"
|
||||
}
|
||||
_inst_ret(val){ return "{\"op\":\"ret\",\"value\":" + me._i(val) + "}" }
|
||||
_map_binop_kind(opk){
|
||||
if opk == "+" { return "Add" }
|
||||
if opk == "-" { return "Sub" }
|
||||
if opk == "*" { return "Mul" }
|
||||
if opk == "/" { return "Div" }
|
||||
if opk == "%" { return "Mod" }
|
||||
return opk
|
||||
}
|
||||
_inst_binop(kind, lhs, rhs, dst){
|
||||
return "{\"op\":\"binop\",\"op_kind\":" + me._q(kind) + ",\"lhs\":" + me._i(lhs) + ",\"rhs\":" + me._i(rhs) + ",\"dst\":" + me._i(dst) + "}"
|
||||
}
|
||||
_wrap_fn(body_json){
|
||||
return "{ \"version\": 0, \"functions\": [ { \"name\": \"main\", \"params\": [], \"blocks\": [ { \"id\": 0, \"instructions\": [" + body_json + "] } ] } ] }"
|
||||
}
|
||||
compile_link_json(json_text, obj_out, exe_out, flags){
|
||||
// Fail‑Fast: validate args
|
||||
if !json_text || !obj_out || !exe_out { return -1 }
|
||||
// Write JSON to a temp file next to obj_out
|
||||
local fb = new FileBox()
|
||||
local json_path = obj_out + ".json"
|
||||
// Ensure file is created and truncated
|
||||
fb.open(json_path, "w")
|
||||
fb.write(json_text)
|
||||
fb.close()
|
||||
// Delegate to AotBox (route is read-only; actual path is handled by C‑ABI/env)
|
||||
local _r = LLVMAotFacadeBox._route()
|
||||
local a = new AotBox()
|
||||
local rc1 = a.compile(json_path, obj_out)
|
||||
if rc1 != 0 { return rc1 }
|
||||
local rc2 = a.link(obj_out, exe_out, flags ? flags : "")
|
||||
return rc2
|
||||
}
|
||||
|
||||
// Convenience wrappers (delegate to LLVMBuilderBox when gate=on; else inline JSON)
|
||||
compile_link_ret0(obj_out, exe_out, flags){
|
||||
local on = call("env.local.get/1", "HAKO_LLVM_SCRIPT_BUILDER");
|
||||
if on && (LLVMAotFacadeBox._truthy(on)) {
|
||||
local json = LLVMBuilderBox.program_ret0()
|
||||
return LLVMAotFacadeBox.compile_link_json(json, obj_out, exe_out, flags)
|
||||
}
|
||||
// Inline JSON fallback to avoid nested using resolver dependencies
|
||||
local body = me._inst_const(1, 0) + "," + me._inst_ret(1)
|
||||
local json = me._wrap_fn(body)
|
||||
return LLVMAotFacadeBox.compile_link_json(json, obj_out, exe_out, flags)
|
||||
}
|
||||
compile_link_ret_i64(v, obj_out, exe_out, flags){
|
||||
local on = call("env.local.get/1", "HAKO_LLVM_SCRIPT_BUILDER");
|
||||
if on && (LLVMAotFacadeBox._truthy(on)) {
|
||||
local json = LLVMBuilderBox.program_ret_i64(v)
|
||||
return LLVMAotFacadeBox.compile_link_json(json, obj_out, exe_out, flags)
|
||||
}
|
||||
local body = me._inst_const(1, v) + "," + me._inst_ret(1)
|
||||
local json = me._wrap_fn(body)
|
||||
return LLVMAotFacadeBox.compile_link_json(json, obj_out, exe_out, flags)
|
||||
}
|
||||
compile_link_binop_i64(lhs, rhs, opk, obj_out, exe_out, flags){
|
||||
local on = call("env.local.get/1", "HAKO_LLVM_SCRIPT_BUILDER");
|
||||
if on && (LLVMAotFacadeBox._truthy(on)) {
|
||||
local json = LLVMBuilderBox.program_binop_i64(lhs, rhs, opk)
|
||||
return LLVMAotFacadeBox.compile_link_json(json, obj_out, exe_out, flags)
|
||||
}
|
||||
// Inline JSON fallback
|
||||
local kind = me._map_binop_kind(opk)
|
||||
local body = me._inst_const(1, lhs) + "," + me._inst_const(2, rhs) + "," + me._inst_binop(kind, 1, 2, 3) + "," + me._inst_ret(3)
|
||||
local json = me._wrap_fn(body)
|
||||
return LLVMAotFacadeBox.compile_link_json(json, obj_out, exe_out, flags)
|
||||
}
|
||||
|
||||
// v1(compare minimal) — emit a compare (Eq) but return 0 to keep exe exit code stable
|
||||
// This exercises the compare path in AOT while ensuring the process exit is 0.
|
||||
compile_link_compare_eq_i64(lhs, rhs, obj_out, exe_out, flags){
|
||||
// Build: const 1=lhs, const 2=rhs, compare(dst=3, operation==, lhs=1, rhs=2),
|
||||
// then const 4=0, binop(dst=5, op="*", lhs=3, rhs=4), ret 5
|
||||
local inst_c1 = "{\"op\":\"const\",\"dst\":1,\"value\":{\"type\":\"i64\",\"value\":" + me._i(lhs) + "}}"
|
||||
local inst_c2 = "{\"op\":\"const\",\"dst\":2,\"value\":{\"type\":\"i64\",\"value\":" + me._i(rhs) + "}}"
|
||||
local inst_cmp = "{\"op\":\"compare\",\"dst\":3,\"operation\":\"==\",\"lhs\":1,\"rhs\":2}"
|
||||
local inst_c0 = "{\"op\":\"const\",\"dst\":4,\"value\":{\"type\":\"i64\",\"value\":0}}"
|
||||
local inst_mul = "{\"op\":\"binop\",\"dst\":5,\"operation\":\"*\",\"lhs\":3,\"rhs\":4}"
|
||||
local inst_ret = "{\"op\":\"ret\",\"value\":5}"
|
||||
local body = inst_c1 + "," + inst_c2 + "," + inst_cmp + "," + inst_c0 + "," + inst_mul + "," + inst_ret
|
||||
local json = me._wrap_fn(body)
|
||||
return LLVMAotFacadeBox.compile_link_json(json, obj_out, exe_out, flags)
|
||||
}
|
||||
|
||||
// v1(compare+branch minimal) — generate multi-block JSON with conditional branch; both paths return 0
|
||||
compile_link_compare_branch_i64(lhs, rhs, opk, obj_out, exe_out, flags){
|
||||
local op = opk ? opk : ">"
|
||||
// blocks: 0=cmp+branch, 1=then(ret 0), 2=else(ret 0)
|
||||
local b0 = "{\"id\":0,\"instructions\":[" +
|
||||
"{\"op\":\"const\",\"dst\":1,\"value\":{\"type\":\"i64\",\"value\":" + me._i(lhs) + "}}," +
|
||||
"{\"op\":\"const\",\"dst\":2,\"value\":{\"type\":\"i64\",\"value\":" + me._i(rhs) + "}}," +
|
||||
"{\"op\":\"compare\",\"dst\":3,\"operation\":" + me._q(op) + ",\"lhs\":1,\"rhs\":2}," +
|
||||
"{\"op\":\"branch\",\"cond\":3,\"then\":1,\"else\":2}] }"
|
||||
local b1 = "{\"id\":1,\"instructions\":[" +
|
||||
"{\"op\":\"const\",\"dst\":4,\"value\":{\"type\":\"i64\",\"value\":0}}," +
|
||||
"{\"op\":\"ret\",\"value\":4}] }"
|
||||
local b2 = "{\"id\":2,\"instructions\":[" +
|
||||
"{\"op\":\"const\",\"dst\":5,\"value\":{\"type\":\"i64\",\"value\":0}}," +
|
||||
"{\"op\":\"ret\",\"value\":5}] }"
|
||||
local json = "{ \"version\": 0, \"functions\": [ { \"name\": \"main\", \"params\": [], \"blocks\": [" + b0 + "," + b1 + "," + b2 + "] } ] }"
|
||||
return LLVMAotFacadeBox.compile_link_json(json, obj_out, exe_out, flags)
|
||||
}
|
||||
|
||||
// v1(phi-if minimal) — diamond shape with PHI at merge; returns 0 to keep exit code stable
|
||||
compile_link_phi_if_i64(val_then, val_else, obj_out, exe_out, flags){
|
||||
// 0: jump->1 always via const(true) compare; 1: const then; 2: const else; 3: phi merge; ret 0
|
||||
local b0 = "{\"id\":0,\"instructions\":[" +
|
||||
"{\"op\":\"const\",\"dst\":1,\"value\":{\"type\":\"i64\",\"value\":1}}," +
|
||||
"{\"op\":\"compare\",\"dst\":2,\"operation\":\"==\",\"lhs\":1,\"rhs\":1}," +
|
||||
"{\"op\":\"branch\",\"cond\":2,\"then\":1,\"else\":2}] }"
|
||||
local b1 = "{\"id\":1,\"instructions\":[" +
|
||||
"{\"op\":\"const\",\"dst\":3,\"value\":{\"type\":\"i64\",\"value\":" + me._i(val_then) + "}}," +
|
||||
"{\"op\":\"jump\",\"target\":3}] }"
|
||||
local b2 = "{\"id\":2,\"instructions\":[" +
|
||||
"{\"op\":\"const\",\"dst\":4,\"value\":{\"type\":\"i64\",\"value\":" + me._i(val_else) + "}}," +
|
||||
"{\"op\":\"jump\",\"target\":3}] }"
|
||||
local b3 = "{\"id\":3,\"instructions\":[" +
|
||||
"{\"op\":\"phi\",\"dst\":5,\"type\":\"i64\",\"incoming\":[{\"block\":1,\"value\":3},{\"block\":2,\"value\":4}]}," +
|
||||
"{\"op\":\"const\",\"dst\":6,\"value\":{\"type\":\"i64\",\"value\":0}}," +
|
||||
"{\"op\":\"ret\",\"value\":6}] }"
|
||||
local json = "{ \"version\": 0, \"functions\": [ { \"name\": \"main\", \"params\": [], \"blocks\": [" + b0 + "," + b1 + "," + b2 + "," + b3 + "] } ] }"
|
||||
return LLVMAotFacadeBox.compile_link_json(json, obj_out, exe_out, flags)
|
||||
}
|
||||
|
||||
// extern call convenience wrappers (console.*) — build via Builder and link
|
||||
compile_link_call_console_log(obj_out, exe_out, flags){
|
||||
local on = call("env.local.get/1", "HAKO_LLVM_SCRIPT_BUILDER");
|
||||
local json
|
||||
if on && (LLVMAotFacadeBox._truthy(on)) { json = LLVMBuilderBox.program_call_console_log_ret0() }
|
||||
else {
|
||||
local body = "{\"op\":\"const\",\"dst\":1,\"value\":{\"type\":\"string\",\"value\":\"hello\"}}," +
|
||||
"{\"op\":\"mir_call\",\"dst\":2,\"mir_call\":{\"callee\":{\"type\":\"Extern\",\"name\":\"env.console.log\"},\"args\":[1],\"effects\":[]}}," +
|
||||
"{\"op\":\"const\",\"dst\":3,\"value\":{\"type\":\"i64\",\"value\":0}}," +
|
||||
"{\"op\":\"ret\",\"value\":3}"
|
||||
json = me._wrap_fn(body)
|
||||
}
|
||||
return LLVMAotFacadeBox.compile_link_json(json, obj_out, exe_out, flags)
|
||||
}
|
||||
compile_link_call_console_warn(obj_out, exe_out, flags){
|
||||
local on = call("env.local.get/1", "HAKO_LLVM_SCRIPT_BUILDER");
|
||||
local json
|
||||
if on && (LLVMAotFacadeBox._truthy(on)) { json = LLVMBuilderBox.program_call_console_warn_ret0() }
|
||||
else {
|
||||
local body = "{\"op\":\"const\",\"dst\":1,\"value\":{\"type\":\"string\",\"value\":\"warn-message\"}}," +
|
||||
"{\"op\":\"mir_call\",\"dst\":2,\"mir_call\":{\"callee\":{\"type\":\"Extern\",\"name\":\"env.console.warn\"},\"args\":[1],\"effects\":[]}}," +
|
||||
"{\"op\":\"const\",\"dst\":3,\"value\":{\"type\":\"i64\",\"value\":0}}," +
|
||||
"{\"op\":\"ret\",\"value\":3}"
|
||||
json = me._wrap_fn(body)
|
||||
}
|
||||
return LLVMAotFacadeBox.compile_link_json(json, obj_out, exe_out, flags)
|
||||
}
|
||||
compile_link_call_console_error(obj_out, exe_out, flags){
|
||||
local on = call("env.local.get/1", "HAKO_LLVM_SCRIPT_BUILDER");
|
||||
local json
|
||||
if on && (LLVMAotFacadeBox._truthy(on)) { json = LLVMBuilderBox.program_call_console_error_ret0() }
|
||||
else {
|
||||
local body = "{\"op\":\"const\",\"dst\":1,\"value\":{\"type\":\"string\",\"value\":\"error-message\"}}," +
|
||||
"{\"op\":\"mir_call\",\"dst\":\"null\",\"mir_call\":{\"callee\":{\"type\":\"Extern\",\"name\":\"env.console.error\"},\"args\":[1],\"effects\":[]}}," +
|
||||
"{\"op\":\"const\",\"dst\":3,\"value\":{\"type\":\"i64\",\"value\":0}}," +
|
||||
"{\"op\":\"ret\",\"value\":3}"
|
||||
json = me._wrap_fn(body)
|
||||
}
|
||||
return LLVMAotFacadeBox.compile_link_json(json, obj_out, exe_out, flags)
|
||||
}
|
||||
// Negative helper for smoke: invalid extern name to observe Fail‑Fast
|
||||
compile_link_call_console_invalid(obj_out, exe_out, flags){
|
||||
// Construct minimal JSON inline to avoid depending on Builder for invalid case
|
||||
local body = "{\"op\":\"const\",\"dst\":1,\"value\":{\"type\":\"string\",\"value\":\"hello\"}}," +
|
||||
"{\"op\":\"mir_call\",\"dst\":2,\"mir_call\":{\"callee\":{\"type\":\"Extern\",\"name\":\"env.console.nope\"},\"args\":[1],\"effects\":[]}}," +
|
||||
"{\"op\":\"const\",\"dst\":3,\"value\":{\"type\":\"i64\",\"value\":0}}," +
|
||||
"{\"op\":\"ret\",\"value\":3}"
|
||||
local json = me._wrap_fn(body)
|
||||
return LLVMAotFacadeBox.compile_link_json(json, obj_out, exe_out, flags)
|
||||
}
|
||||
// time.now_ms — build via Builder when gate, else inline JSON; ret 0
|
||||
compile_link_call_time_now_ms(obj_out, exe_out, flags){
|
||||
local on = call("env.local.get/1", "HAKO_LLVM_SCRIPT_BUILDER");
|
||||
local json
|
||||
if on && (LLVMAotFacadeBox._truthy(on)) { json = LLVMBuilderBox.program_call_time_now_ms_ret0() }
|
||||
else {
|
||||
local body = "{\"op\":\"mir_call\",\"dst\":2,\"mir_call\":{\"callee\":{\"type\":\"Extern\",\"name\":\"env.time.now_ms\"},\"args\":[],\"effects\":[]}}," +
|
||||
"{\"op\":\"const\",\"dst\":3,\"value\":{\"type\":\"i64\",\"value\":0}}," +
|
||||
"{\"op\":\"ret\",\"value\":3}"
|
||||
json = me._wrap_fn(body)
|
||||
}
|
||||
return LLVMAotFacadeBox.compile_link_json(json, obj_out, exe_out, flags)
|
||||
}
|
||||
// JSON.stringify(any) — via nyash.json.stringify_h; ret 0
|
||||
compile_link_call_json_stringify(obj_out, exe_out, flags){
|
||||
local on = call("env.local.get/1", "HAKO_LLVM_SCRIPT_BUILDER");
|
||||
local json
|
||||
if on && (LLVMAotFacadeBox._truthy(on)) { json = LLVMBuilderBox.program_call_json_stringify_ret0() }
|
||||
else {
|
||||
local body = "{\"op\":\"const\",\"dst\":1,\"value\":{\"type\":\"i64\",\"value\":42}}," +
|
||||
"{\"op\":\"mir_call\",\"dst\":2,\"mir_call\":{\"callee\":{\"type\":\"Extern\",\"name\":\"nyash.json.stringify_h\"},\"args\":[1],\"effects\":[]}}," +
|
||||
"{\"op\":\"const\",\"dst\":3,\"value\":{\"type\":\"i64\",\"value\":0}}," +
|
||||
"{\"op\":\"ret\",\"value\":3}"
|
||||
json = me._wrap_fn(body)
|
||||
}
|
||||
return LLVMAotFacadeBox.compile_link_json(json, obj_out, exe_out, flags)
|
||||
}
|
||||
// env.mem.alloc/free wrapper — ret 0
|
||||
compile_link_call_mem_alloc_free(sz, obj_out, exe_out, flags){
|
||||
local on = call("env.local.get/1", "HAKO_LLVM_SCRIPT_BUILDER");
|
||||
local json
|
||||
if on && (LLVMAotFacadeBox._truthy(on)) { json = LLVMBuilderBox.program_call_mem_alloc_free_ret0(sz) }
|
||||
else {
|
||||
local s = sz ? sz : 16
|
||||
local body = "{\"op\":\"const\",\"dst\":1,\"value\":{\"type\":\"i64\",\"value\":" + me._i(s) + "}}," +
|
||||
"{\"op\":\"mir_call\",\"dst\":2,\"mir_call\":{\"callee\":{\"type\":\"Extern\",\"name\":\"env.mem.alloc\"},\"args\":[1],\"effects\":[]}}," +
|
||||
"{\"op\":\"mir_call\",\"dst\":3,\"mir_call\":{\"callee\":{\"type\":\"Extern\",\"name\":\"env.mem.free\"},\"args\":[2],\"effects\":[]}}," +
|
||||
"{\"op\":\"const\",\"dst\":4,\"value\":{\"type\":\"i64\",\"value\":0}}," +
|
||||
"{\"op\":\"ret\",\"value\":4}"
|
||||
json = me._wrap_fn(body)
|
||||
}
|
||||
return LLVMAotFacadeBox.compile_link_json(json, obj_out, exe_out, flags)
|
||||
}
|
||||
// env.local.get wrapper — ret 0 (value ignored)
|
||||
compile_link_call_env_local_get(key, obj_out, exe_out, flags){
|
||||
local on = call("env.local.get/1", "HAKO_LLVM_SCRIPT_BUILDER");
|
||||
local json
|
||||
if on && (LLVMAotFacadeBox._truthy(on)) { json = LLVMBuilderBox.program_call_env_local_get_ret0(key) }
|
||||
else {
|
||||
local k = key ? key : "SMOKES_ENV_LOCAL_GET"
|
||||
local body = "{\"op\":\"const\",\"dst\":1,\"value\":{\"type\":\"string\",\"value\":\"" + k + "\"}}," +
|
||||
"{\"op\":\"mir_call\",\"dst\":2,\"mir_call\":{\"callee\":{\"type\":\"Extern\",\"name\":\"env.local.get\"},\"args\":[1],\"effects\":[]}}," +
|
||||
"{\"op\":\"const\",\"dst\":3,\"value\":{\"type\":\"i64\",\"value\":0}}," +
|
||||
"{\"op\":\"ret\",\"value\":3}"
|
||||
json = me._wrap_fn(body)
|
||||
}
|
||||
return LLVMAotFacadeBox.compile_link_json(json, obj_out, exe_out, flags)
|
||||
}
|
||||
}
|
||||
162
lang/src/llvm_ir/boxes/aot_prep.hako
Normal file
162
lang/src/llvm_ir/boxes/aot_prep.hako
Normal file
@ -0,0 +1,162 @@
|
||||
// aot_prep.hako — AotPrepBox (pre-MIR normalizer/optimizer; skeleton)
|
||||
// 入出力(最小仕様)
|
||||
// - AotPrepBox.prep/1(json_in_path: String) -> String (json_out_path)
|
||||
// 責務
|
||||
// - JSON(MIR v0) の軽量正規化(キー順/冗長キー削除)と安全な const/binop(+,-,*)/ret の単一ブロック畳み込み
|
||||
// - 既定ではパススルー(Rust 側 maybe_prepare_mir_json が実体)。段階的にこちらへ移管する
|
||||
|
||||
using "lang/src/shared/mir/mir_io_box.hako" as MirIoBox
|
||||
using "lang/src/shared/common/string_helpers.hako" as StringHelpers
|
||||
|
||||
static box AotPrepBox {
|
||||
// AotPrepBox.prep
|
||||
// 入力: JSONファイルパス(MIR v0)
|
||||
// 出力: 正規化後のJSONを書き出したパス(<in>.prep.json)。失敗時は入力パスを返す(Fail‑FastはRust側が継続)。
|
||||
prep(json_in_path) {
|
||||
if !json_in_path { return json_in_path }
|
||||
// Read input
|
||||
local fb = new FileBox()
|
||||
fb.open(json_in_path, "r")
|
||||
local src = fb.read()
|
||||
fb.close()
|
||||
if !src { return json_in_path }
|
||||
|
||||
// Phase‑1: 文字列正規化(安定化)
|
||||
// いまは canonicalize は恒等(将来はHostBridgeでキー順安定化)
|
||||
local canon = MirIoBox.normalize(src)
|
||||
|
||||
// Phase‑2: 安全な単一ブロック const/binop(+,-,*)/ret の畳み込み(最小実装)
|
||||
// 備考: まずは main 関数を優先対象とし、成立時のみ最小 JSON に置換(今後は in‑place 置換へ段階移行)。
|
||||
local out = AotPrepBox._try_fold_const_binop_ret(canon)
|
||||
if !out { out = canon }
|
||||
|
||||
// Decide output path
|
||||
local out_path = json_in_path + ".prep.json"
|
||||
fb.open(out_path, "w")
|
||||
fb.write(out)
|
||||
fb.close()
|
||||
return out_path
|
||||
}
|
||||
|
||||
// 内部: 最小の安全畳み込み(JSON文字列ベース)
|
||||
_try_fold_const_binop_ret(json) {
|
||||
if !json { return null }
|
||||
// Helper: find the [ ... ] span of the first block's instructions for the function near `start_from`.
|
||||
local find_instr_span_from = fun(s, start_from) {
|
||||
local key = "\"instructions\":["
|
||||
local pos = s.indexOf(key, start_from)
|
||||
if pos < 0 { return [-1, -1] }
|
||||
local ls = s.indexOf("[", pos)
|
||||
if ls < 0 { return [-1, -1] }
|
||||
local depth = 0
|
||||
local i = ls
|
||||
local L = s.size()
|
||||
local rs = -1
|
||||
loop(i < L) {
|
||||
local ch = s.substring(i, i+1)
|
||||
if ch == "[" { depth = depth + 1 }
|
||||
if ch == "]" { depth = depth - 1; if depth == 0 { rs = i; break } }
|
||||
i = i + 1
|
||||
}
|
||||
return [ls, rs]
|
||||
}
|
||||
// Helper: attempt to fold within a given [arr_start, arr_end] span; return replaced JSON on success
|
||||
local try_fold_in_span = fun(s, arr_start, arr_end) {
|
||||
if arr_start < 0 || arr_end < 0 { return null }
|
||||
local body = s.substring(arr_start, arr_end+1)
|
||||
// Need two const, a binop, and a ret in this span
|
||||
local p1 = body.indexOf("\"op\":\"const\"")
|
||||
local p2 = body.indexOf("\"op\":\"const\"", (p1>=0 ? (p1+1) : 0))
|
||||
local pb = body.indexOf("\"op\":\"binop\"", (p2>=0 ? (p2+1) : 0))
|
||||
local pr = body.indexOf("\"op\":\"ret\"", (pb>=0 ? (pb+1) : 0))
|
||||
if p1 < 0 || p2 < 0 || pb < 0 || pr < 0 { return null }
|
||||
// parse helpers within body
|
||||
local parse_dst = fun(ss, pos) {
|
||||
local k = "\"dst\":"
|
||||
local i = ss.indexOf(k, pos)
|
||||
if i < 0 { return -1 }
|
||||
i = i + k.size()
|
||||
local digs = StringHelpers.read_digits(ss, i)
|
||||
if digs == "" { return -1 }
|
||||
return StringHelpers.to_i64(digs)
|
||||
}
|
||||
local parse_val = fun(ss, pos) {
|
||||
local k = "\"value\":{\"type\":\"i64\",\"value\":"
|
||||
local i = ss.indexOf(k, pos)
|
||||
if i < 0 { return null }
|
||||
i = i + k.size()
|
||||
local digs = StringHelpers.read_digits(ss, i)
|
||||
if digs == "" { return null }
|
||||
return StringHelpers.to_i64(digs)
|
||||
}
|
||||
local d1 = parse_dst(body, p1)
|
||||
local a = parse_val(body, p1)
|
||||
local d2 = parse_dst(body, p2)
|
||||
local b = parse_val(body, p2)
|
||||
if d1 < 0 || d2 < 0 || a == null || b == null { return null }
|
||||
local find_num = fun(ss, key, pos) {
|
||||
local k = key
|
||||
local i = ss.indexOf(k, pos)
|
||||
if i < 0 { return -1 }
|
||||
i = i + k.size()
|
||||
local digs = StringHelpers.read_digits(ss, i)
|
||||
if digs == "" { return -1 }
|
||||
return StringHelpers.to_i64(digs)
|
||||
}
|
||||
local find_op = fun(ss, pos) {
|
||||
local k = "\"operation\":\""
|
||||
local i = ss.indexOf(k, pos)
|
||||
if i < 0 { return "" }
|
||||
i = i + k.size()
|
||||
local j = ss.indexOf("\"", i)
|
||||
if j < 0 { return "" }
|
||||
return ss.substring(i, j)
|
||||
}
|
||||
local lhs = find_num(body, "\"lhs\":", pb)
|
||||
local rhs = find_num(body, "\"rhs\":", pb)
|
||||
local bop = find_op(body, pb)
|
||||
local d3 = find_num(body, "\"dst\":", pb)
|
||||
if lhs != d1 || rhs != d2 || d3 < 0 { return null }
|
||||
local rv = find_num(body, "\"value\":", pr)
|
||||
if rv != d3 { return null }
|
||||
// binop allowed: +,-,* only
|
||||
local res = 0
|
||||
if bop == "+" { res = a + b } else { if bop == "-" { res = a - b } else { if bop == "*" { res = a * b } else { return null } } }
|
||||
// build new array and replace in-place
|
||||
local new_insts = "[" +
|
||||
"{\\\"op\\\":\\\"const\\\",\\\"dst\\\":" + StringHelpers.int_to_str(d1) + ",\\\"value\\\":{\\\"type\\\":\\\"i64\\\",\\\"value\\\":" + StringHelpers.int_to_str(res) + "}}," +
|
||||
"{\\\"op\\\":\\\"ret\\\",\\\"value\\\":" + StringHelpers.int_to_str(d1) + "}]"
|
||||
local head = s.substring(0, arr_start)
|
||||
local tail = s.substring(arr_end + 1, s.size())
|
||||
return head + new_insts + tail
|
||||
}
|
||||
// Pass 1: prefer name:"main"
|
||||
local fn_pos = json.indexOf("\"name\":\"main\"")
|
||||
if fn_pos >= 0 {
|
||||
local span = find_instr_span_from(json, fn_pos)
|
||||
local ls = span[0]; local rs = span[1]
|
||||
local repl = try_fold_in_span(json, ls, rs)
|
||||
if repl { return repl }
|
||||
}
|
||||
// Pass 2: scan functions sequentially and attempt per function
|
||||
local froot = json.indexOf("\"functions\":[")
|
||||
if froot < 0 { return null }
|
||||
local scan = froot
|
||||
local tries = 0
|
||||
loop(tries < 16) {
|
||||
local np = json.indexOf("\"name\":\"", scan+1)
|
||||
if np < 0 { break }
|
||||
local span2 = find_instr_span_from(json, np)
|
||||
local ls2 = span2[0]; local rs2 = span2[1]
|
||||
if ls2 >= 0 && rs2 >= 0 {
|
||||
local repl2 = try_fold_in_span(json, ls2, rs2)
|
||||
if repl2 { return repl2 }
|
||||
scan = rs2 + 1
|
||||
} else {
|
||||
scan = np + 8
|
||||
}
|
||||
tries = tries + 1
|
||||
}
|
||||
return null
|
||||
}
|
||||
}
|
||||
128
lang/src/llvm_ir/boxes/builder.hako
Normal file
128
lang/src/llvm_ir/boxes/builder.hako
Normal file
@ -0,0 +1,128 @@
|
||||
// LLVMBuilderBox — 命令構築(v0: const/binop/ret の骨格)
|
||||
static box LLVMBuilderBox {
|
||||
program_ret0(){
|
||||
return "{ \"version\": 0, \"functions\": [ { \"name\": \"main\", \"params\": [], \"blocks\": [ { \"id\": 0, \"instructions\": [{\"op\":\"const\",\"dst\":1,\"value\":{\"type\":\"i64\",\"value\":0}},{\"op\":\"ret\",\"value\":1}] } ] } ] }"
|
||||
}
|
||||
program_binop_i64(lhs, rhs, opk){
|
||||
local op = opk ? opk : "+"
|
||||
return "{ \"version\": 0, \"functions\": [ { \"name\": \"main\", \"params\": [], \"blocks\": [ { \"id\": 0, \"instructions\": [" +
|
||||
"{\"op\":\"const\",\"dst\":1,\"value\":{\"type\":\"i64\",\"value\":" + lhs + "}}," +
|
||||
"{\"op\":\"const\",\"dst\":2,\"value\":{\"type\":\"i64\",\"value\":" + rhs + "}}," +
|
||||
"{\"op\":\"binop\",\"dst\":3,\"operation\":\"" + op + "\",\"lhs\":1,\"rhs\":2}," +
|
||||
"{\"op\":\"ret\",\"value\":3}] } ] } ] }"
|
||||
}
|
||||
program_ret_i64(v){
|
||||
return "{ \"version\": 0, \"functions\": [ { \"name\": \"main\", \"params\": [], \"blocks\": [ { \"id\": 0, \"instructions\": [" +
|
||||
"{\\\"op\\\":\\\"const\\\",\\\"dst\\\":1,\\\"value\\\":{\\\"type\\\":\\\"i64\\\",\\\"value\\\":" + v + "}}," +
|
||||
"{\\\"op\\\":\\\"ret\\\",\\\"value\\\":1}] } ] } ] }"
|
||||
}
|
||||
const_i64(fn_handle, value){
|
||||
local strict = call("env.local.get/1", "HAKO_LLVM_SCRIPT_BUILDER_STRICT");
|
||||
if strict && strict != "0" && strict != "false" { print("UNSUPPORTED: const_i64 (stub)"); return -1 }
|
||||
return 0
|
||||
}
|
||||
binop_add(fn_handle, lhs, rhs){
|
||||
local strict = call("env.local.get/1", "HAKO_LLVM_SCRIPT_BUILDER_STRICT");
|
||||
if strict && strict != "0" && strict != "false" { print("UNSUPPORTED: binop_add (stub)"); return -1 }
|
||||
return 0
|
||||
}
|
||||
ret(fn_handle, val){
|
||||
local strict = call("env.local.get/1", "HAKO_LLVM_SCRIPT_BUILDER_STRICT");
|
||||
if strict && strict != "0" && strict != "false" { print("UNSUPPORTED: ret (stub)"); return -1 }
|
||||
return 0
|
||||
}
|
||||
|
||||
// v1 programs (JSON emitters) — behavior: return JSON string for AOT facade
|
||||
program_compare_branch_ret0(lhs, rhs, opk){
|
||||
local op = opk ? opk : ">"
|
||||
local b0 = "{\"id\":0,\"instructions\":[" +
|
||||
"{\"op\":\"const\",\"dst\":1,\"value\":{\"type\":\"i64\",\"value\":" + lhs + "}}," +
|
||||
"{\"op\":\"const\",\"dst\":2,\"value\":{\"type\":\"i64\",\"value\":" + rhs + "}}," +
|
||||
"{\"op\":\"compare\",\"dst\":3,\"operation\":\"" + op + "\",\"lhs\":1,\"rhs\":2}," +
|
||||
"{\"op\":\"branch\",\"cond\":3,\"then\":1,\"else\":2}] }"
|
||||
local b1 = "{\"id\":1,\"instructions\":[" +
|
||||
"{\"op\":\"const\",\"dst\":4,\"value\":{\"type\":\"i64\",\"value\":0}}," +
|
||||
"{\"op\":\"ret\",\"value\":4}] }"
|
||||
local b2 = "{\"id\":2,\"instructions\":[" +
|
||||
"{\"op\":\"const\",\"dst\":5,\"value\":{\"type\":\"i64\",\"value\":0}}," +
|
||||
"{\"op\":\"ret\",\"value\":5}] }"
|
||||
return "{ \"version\": 0, \"functions\": [ { \"name\": \"main\", \"params\": [], \"blocks\": [" + b0 + "," + b1 + "," + b2 + "] } ] }"
|
||||
}
|
||||
|
||||
program_phi_if_ret0(val_then, val_else){
|
||||
local b0 = "{\"id\":0,\"instructions\":[" +
|
||||
"{\"op\":\"const\",\"dst\":1,\"value\":{\"type\":\"i64\",\"value\":1}}," +
|
||||
"{\"op\":\"compare\",\"dst\":2,\"operation\":\"==\",\"lhs\":1,\"rhs\":1}," +
|
||||
"{\"op\":\"branch\",\"cond\":2,\"then\":1,\"else\":2}] }"
|
||||
local b1 = "{\"id\":1,\"instructions\":[" +
|
||||
"{\"op\":\"const\",\"dst\":3,\"value\":{\"type\":\"i64\",\"value\":" + val_then + "}}," +
|
||||
"{\"op\":\"jump\",\"target\":3}] }"
|
||||
local b2 = "{\"id\":2,\"instructions\":[" +
|
||||
"{\"op\":\"const\",\"dst\":4,\"value\":{\"type\":\"i64\",\"value\":" + val_else + "}}," +
|
||||
"{\"op\":\"jump\",\"target\":3}] }"
|
||||
local b3 = "{\"id\":3,\"instructions\":[" +
|
||||
"{\"op\":\"phi\",\"dst\":5,\"type\":\"i64\",\"incoming\":[{\"block\":1,\"value\":3},{\"block\":2,\"value\":4}]}," +
|
||||
"{\"op\":\"const\",\"dst\":6,\"value\":{\"type\":\"i64\",\"value\":0}}," +
|
||||
"{\"op\":\"ret\",\"value\":6}] }"
|
||||
return "{ \"version\": 0, \"functions\": [ { \"name\": \"main\", \"params\": [], \"blocks\": [" + b0 + "," + b1 + "," + b2 + "," + b3 + "] } ] }"
|
||||
}
|
||||
|
||||
// v2 extern calls (console.*) — return JSON for AOT facade
|
||||
program_call_console_log_ret0(){
|
||||
// const s="hello"; mir_call Extern(env.console.log) s; ret 0
|
||||
return "{ \"version\": 0, \"functions\": [ { \"name\": \"main\", \"params\": [], \"blocks\": [ { \"id\": 0, \"instructions\": [" +
|
||||
"{\\\"op\\\":\\\"const\\\",\\\"dst\\\":1,\\\"value\\\":{\\\"type\\\":\\\"string\\\",\\\"value\\\":\\\"hello\\\"}}," +
|
||||
"{\\\"op\\\":\\\"mir_call\\\",\\\"dst\\\":2,\\\"mir_call\\\":{\\\"callee\\\":{\\\"type\\\":\\\"Extern\\\",\\\"name\\\":\\\"env.console.log\\\"},\\\"args\\\":[1],\\\"effects\\\":[]}}," +
|
||||
"{\\\"op\\\":\\\"const\\\",\\\"dst\\\":3,\\\"value\\\":{\\\"type\\\":\\\"i64\\\",\\\"value\\\":0}}," +
|
||||
"{\\\"op\\\":\\\"ret\\\",\\\"value\\\":3}] } ] } ] }"
|
||||
}
|
||||
program_call_console_warn_ret0(){
|
||||
return "{ \"version\": 0, \"functions\": [ { \"name\": \"main\", \"params\": [], \"blocks\": [ { \"id\": 0, \"instructions\": [" +
|
||||
"{\\\"op\\\":\\\"const\\\",\\\"dst\\\":1,\\\"value\\\":{\\\"type\\\":\\\"string\\\",\\\"value\\\":\\\"warn-message\\\"}}," +
|
||||
"{\\\"op\\\":\\\"mir_call\\\",\\\"dst\\\":2,\\\"mir_call\\\":{\\\"callee\\\":{\\\"type\\\":\\\"Extern\\\",\\\"name\\\":\\\"env.console.warn\\\"},\\\"args\\\":[1],\\\"effects\\\":[]}}," +
|
||||
"{\\\"op\\\":\\\"const\\\",\\\"dst\\\":3,\\\"value\\\":{\\\"type\\\":\\\"i64\\\",\\\"value\\\":0}}," +
|
||||
"{\\\"op\\\":\\\"ret\\\",\\\"value\\\":3}] } ] } ] }"
|
||||
}
|
||||
program_call_console_error_ret0(){
|
||||
return "{ \"version\": 0, \"functions\": [ { \"name\": \"main\", \"params\": [], \"blocks\": [ { \"id\": 0, \"instructions\": [" +
|
||||
"{\\\"op\\\":\\\"const\\\",\\\"dst\\\":1,\\\"value\\\":{\\\"type\\\":\\\"string\\\",\\\"value\\\":\\\"error-message\\\"}}," +
|
||||
"{\\\"op\\\":\\\"mir_call\\\",\\\"dst\\\":2,\\\"mir_call\\\":{\\\"callee\\\":{\\\"type\\\":\\\"Extern\\\",\\\"name\\\":\\\"env.console.error\\\"},\\\"args\\\":[1],\\\"effects\\\":[]}}," +
|
||||
"{\\\"op\\\":\\\"const\\\",\\\"dst\\\":3,\\\"value\\\":{\\\"type\\\":\\\"i64\\\",\\\"value\\\":0}}," +
|
||||
"{\\\"op\\\":\\\"ret\\\",\\\"value\\\":3}] } ] } ] }"
|
||||
}
|
||||
// env.mem.alloc/free roundtrip; return 0
|
||||
program_call_mem_alloc_free_ret0(size){
|
||||
local sz = size ? size : 16
|
||||
return "{ \"version\": 0, \"functions\": [ { \"name\": \"main\", \"params\": [], \"blocks\": [ { \"id\": 0, \"instructions\": [" +
|
||||
"{\\\"op\\\":\\\"const\\\",\\\"dst\\\":1,\\\"value\\\":{\\\"type\\\":\\\"i64\\\",\\\"value\\\":" + sz + "}}," +
|
||||
"{\\\"op\\\":\\\"mir_call\\\",\\\"dst\\\":2,\\\"mir_call\\\":{\\\"callee\\\":{\\\"type\\\":\\\"Extern\\\",\\\"name\\\":\\\"env.mem.alloc\\\"},\\\"args\\\":[1],\\\"effects\\\":[]}}," +
|
||||
"{\\\"op\\\":\\\"mir_call\\\",\\\"dst\\\":3,\\\"mir_call\\\":{\\\"callee\\\":{\\\"type\\\":\\\"Extern\\\",\\\"name\\\":\\\"env.mem.free\\\"},\\\"args\\\":[2],\\\"effects\\\":[]}}," +
|
||||
"{\\\"op\\\":\\\"const\\\",\\\"dst\\\":4,\\\"value\\\":{\\\"type\\\":\\\"i64\\\",\\\"value\\\":0}}," +
|
||||
"{\\\"op\\\":\\\"ret\\\",\\\"value\\\":4}] } ] } ] }"
|
||||
}
|
||||
// env.local.get (value unused); return 0
|
||||
program_call_env_local_get_ret0(key){
|
||||
local k = key ? key : "SMOKES_ENV_LOCAL_GET"
|
||||
return "{ \"version\": 0, \"functions\": [ { \"name\": \"main\", \"params\": [], \"blocks\": [ { \"id\": 0, \"instructions\": [" +
|
||||
"{\\\"op\\\":\\\"const\\\",\\\"dst\\\":1,\\\"value\\\":{\\\"type\\\":\\\"string\\\",\\\"value\\\":\\\"" + k + "\\\"}}," +
|
||||
"{\\\"op\\\":\\\"mir_call\\\",\\\"dst\\\":2,\\\"mir_call\\\":{\\\"callee\\\":{\\\"type\\\":\\\"Extern\\\",\\\"name\\\":\\\"env.local.get\\\"},\\\"args\\\":[1],\\\"effects\\\":[]}}," +
|
||||
"{\\\"op\\\":\\\"const\\\",\\\"dst\\\":3,\\\"value\\\":{\\\"type\\\":\\\"i64\\\",\\\"value\\\":0}}," +
|
||||
"{\\\"op\\\":\\\"ret\\\",\\\"value\\\":3}] } ] } ] }"
|
||||
}
|
||||
// v2 extern calls (time.now_ms / JSON.stringify)
|
||||
// Call env.time.now_ms() and return 0 (exe exit code stable)
|
||||
program_call_time_now_ms_ret0(){
|
||||
return "{ \"version\": 0, \"functions\": [ { \"name\": \"main\", \"params\": [], \"blocks\": [ { \"id\": 0, \"instructions\": [" +
|
||||
"{\\\"op\\\":\\\"mir_call\\\",\\\"dst\\\":2,\\\"mir_call\\\":{\\\"callee\\\":{\\\"type\\\":\\\"Extern\\\",\\\"name\\\":\\\"env.time.now_ms\\\"},\\\"args\\\":[],\\\"effects\\\":[]}}," +
|
||||
"{\\\"op\\\":\\\"const\\\",\\\"dst\\\":3,\\\"value\\\":{\\\"type\\\":\\\"i64\\\",\\\"value\\\":0}}," +
|
||||
"{\\\"op\\\":\\\"ret\\\",\\\"value\\\":3}] } ] } ] }"
|
||||
}
|
||||
// Call JSON.stringify(any) via nyash.json.stringify_h and return 0
|
||||
program_call_json_stringify_ret0(){
|
||||
return "{ \"version\": 0, \"functions\": [ { \"name\": \"main\", \"params\": [], \"blocks\": [ { \"id\": 0, \"instructions\": [" +
|
||||
"{\\\"op\\\":\\\"const\\\",\\\"dst\\\":1,\\\"value\\\":{\\\"type\\\":\\\"i64\\\",\\\"value\\\":42}}," +
|
||||
"{\\\"op\\\":\\\"mir_call\\\",\\\"dst\\\":2,\\\"mir_call\\\":{\\\"callee\\\":{\\\"type\\\":\\\"Extern\\\",\\\"name\\\":\\\"nyash.json.stringify_h\\\"},\\\"args\\\":[1],\\\"effects\\\":[]}}," +
|
||||
"{\\\"op\\\":\\\"const\\\",\\\"dst\\\":3,\\\"value\\\":{\\\"type\\\":\\\"i64\\\",\\\"value\\\":0}}," +
|
||||
"{\\\"op\\\":\\\"ret\\\",\\\"value\\\":3}] } ] } ] }"
|
||||
}
|
||||
}
|
||||
9
lang/src/llvm_ir/boxes/emit.hako
Normal file
9
lang/src/llvm_ir/boxes/emit.hako
Normal file
@ -0,0 +1,9 @@
|
||||
// LLVMEmitBox — オブジェクト出力(当面は委譲予定・MVPはFail‑Fast stub)
|
||||
static box LLVMEmitBox {
|
||||
write_object(mod_handle, path){
|
||||
// まだスクリプト内で IR→obj を完結させない方針。委譲前提のためFail‑Fast。
|
||||
print("UNSUPPORTED: write_object (delegate to AotBox/libhako_aot)");
|
||||
return -1
|
||||
}
|
||||
}
|
||||
|
||||
10
lang/src/llvm_ir/boxes/function.hako
Normal file
10
lang/src/llvm_ir/boxes/function.hako
Normal file
@ -0,0 +1,10 @@
|
||||
// LLVMFunctionBox — 関数定義と基本ブロック操作(MVPは形のみ)
|
||||
static box LLVMFunctionBox {
|
||||
append_block(fn_handle, name){
|
||||
return 1
|
||||
}
|
||||
set_insert_point(fn_handle, bb_handle){
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
21
lang/src/llvm_ir/boxes/module.hako
Normal file
21
lang/src/llvm_ir/boxes/module.hako
Normal file
@ -0,0 +1,21 @@
|
||||
// LLVMModuleBox — IR 構築の起点(MVPは形のみ)
|
||||
static box LLVMModuleBox {
|
||||
new(name, triple, dl){
|
||||
// Gate: opt‑in のみ
|
||||
local on = call("env.local.get/1", "HAKO_LLVM_SCRIPT_BUILDER");
|
||||
if !on || on == "0" || on == "false" { return -1 }
|
||||
// For MVP, just return a dummy handle (=1)
|
||||
return 1
|
||||
}
|
||||
set_target_triple(handle, triple){
|
||||
return 0
|
||||
}
|
||||
set_data_layout(handle, dl){
|
||||
return 0
|
||||
}
|
||||
add_function(handle, name, ret_ty, args_array){
|
||||
// Return a dummy function handle (=1)
|
||||
return 1
|
||||
}
|
||||
}
|
||||
|
||||
10
lang/src/llvm_ir/boxes/types.hako
Normal file
10
lang/src/llvm_ir/boxes/types.hako
Normal file
@ -0,0 +1,10 @@
|
||||
// LLVMTypesBox — 代表的なプリミティブ型のクエリ(v0)
|
||||
static box LLVMTypesBox {
|
||||
i1(){ return "i1" }
|
||||
i8(){ return "i8" }
|
||||
i32(){ return "i32" }
|
||||
i64(){ return "i64" }
|
||||
f64(){ return "f64" }
|
||||
ptr(ty){ return ty + "*" }
|
||||
}
|
||||
|
||||
44
lang/src/llvm_ir/boxes/v0_builder.hako
Normal file
44
lang/src/llvm_ir/boxes/v0_builder.hako
Normal file
@ -0,0 +1,44 @@
|
||||
// LLVMV0BuilderBox — v0: 最小 MIR(JSON v0) を直接生成する軽量ビルダ(依存レス)
|
||||
// 目的: スモークでの AOT 経路確認を最小依存で実現する。
|
||||
|
||||
static box LLVMV0BuilderBox {
|
||||
_q(s){ return "\"" + s + "\"" }
|
||||
_i(n){ return "" + n }
|
||||
_inst_const(dst, val){
|
||||
return "{\"op\":\"const\",\"dst\":" + me._i(dst) + ",\"value\":{\"type\":\"i64\",\"value\":" + me._i(val) + "}}"
|
||||
}
|
||||
_inst_ret(val){ return "{\"op\":\"ret\",\"value\":" + me._i(val) + "}" }
|
||||
_map_binop_kind(opk){
|
||||
if opk == "+" { return "Add" }
|
||||
if opk == "-" { return "Sub" }
|
||||
if opk == "*" { return "Mul" }
|
||||
if opk == "/" { return "Div" }
|
||||
if opk == "%" { return "Mod" }
|
||||
return opk
|
||||
}
|
||||
_inst_binop(kind, lhs, rhs, dst){
|
||||
return "{\"op\":\"binop\",\"op_kind\":" + me._q(kind) + ",\"lhs\":" + me._i(lhs) + ",\"rhs\":" + me._i(rhs) + ",\"dst\":" + me._i(dst) + "}"
|
||||
}
|
||||
_wrap_fn(body_json){
|
||||
return "{ \"version\": 0, \"functions\": [ { \"name\": \"main\", \"params\": [], \"blocks\": [ { \"id\": 0, \"instructions\": [" + body_json + "] } ] } ] }"
|
||||
}
|
||||
|
||||
// return 0(v0代表)
|
||||
ret0(){
|
||||
local body = me._inst_const(1, 0) + "," + me._inst_ret(1)
|
||||
return me._wrap_fn(body)
|
||||
}
|
||||
|
||||
// return <v>
|
||||
ret_i64(v){
|
||||
local body = me._inst_const(1, v) + "," + me._inst_ret(1)
|
||||
return me._wrap_fn(body)
|
||||
}
|
||||
|
||||
// (<lhs> <op> <rhs>) → return (op: +|-|*|/|%)
|
||||
binop_i64(lhs, rhs, opk){
|
||||
local kind = me._map_binop_kind(opk)
|
||||
local body = me._inst_const(1, lhs) + "," + me._inst_const(2, rhs) + "," + me._inst_binop(kind, 1, 2, 3) + "," + me._inst_ret(3)
|
||||
return me._wrap_fn(body)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user