Phase 21.7 normalization: optimization pre-work + bench harness expansion
- Add opt-in optimizations (defaults OFF) - Ret purity verifier: NYASH_VERIFY_RET_PURITY=1 - strlen FAST enhancement for const handles - FAST_INT gate for same-BB SSA optimization - length cache for string literals in llvmlite - Expand bench harness (tools/perf/microbench.sh) - Add branch/call/stringchain/arraymap/chip8/kilo cases - Auto-calculate ratio vs C reference - Document in benchmarks/README.md - Compiler health improvements - Unify PHI insertion to insert_phi_at_head() - Add NYASH_LLVM_SKIP_BUILD=1 for build reuse - Runtime & safety enhancements - Clarify Rust/Hako ownership boundaries - Strengthen receiver localization (LocalSSA/pin/after-PHIs) - Stop excessive PluginInvoke→BoxCall rewrites - Update CURRENT_TASK.md, docs, and canaries 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@ -44,6 +44,7 @@ CODE="$(cat "$IN")"
|
||||
# 1) Stage‑B: Hako parser emits Program(JSON v0) to stdout
|
||||
set +e
|
||||
PROG_JSON_OUT=$(NYASH_JSON_ONLY=1 NYASH_DISABLE_NY_COMPILER=1 HAKO_DISABLE_NY_COMPILER=1 \
|
||||
HAKO_STAGEB_FUNC_SCAN="${HAKO_STAGEB_FUNC_SCAN:-}" \
|
||||
NYASH_PARSER_STAGE3=1 HAKO_PARSER_STAGE3=1 NYASH_PARSER_ALLOW_SEMICOLON=1 \
|
||||
NYASH_ENABLE_USING=${NYASH_ENABLE_USING:-1} HAKO_ENABLE_USING=${HAKO_ENABLE_USING:-1} \
|
||||
"$NYASH_BIN" --backend vm "$ROOT/lang/src/compiler/entry/compiler_stageb.hako" -- --source "$CODE" 2>/dev/null | awk '/^{/,/^}$/')
|
||||
@ -117,6 +118,53 @@ try_selfhost_builder() {
|
||||
}
|
||||
MIRJSON
|
||||
|
||||
# Provider-first delegate: call env.mirbuilder.emit(prog_json) and capture v1 JSON
|
||||
try_provider_emit() {
|
||||
local prog_json="$1" out_path="$2"
|
||||
local tmp_hako; tmp_hako=$(mktemp --suffix .hako)
|
||||
cat >"$tmp_hako" <<'HCODE'
|
||||
using "hako.mir.builder.internal.jsonfrag_normalizer" as NormBox
|
||||
static box Main { method main(args) {
|
||||
local p = env.get("HAKO_BUILDER_PROGRAM_JSON")
|
||||
if p == null { print("[provider/emit:nojson]"); return 1 }
|
||||
local a = new ArrayBox(); a.push(p)
|
||||
local out = hostbridge.extern_invoke("env.mirbuilder", "emit", a)
|
||||
// Optional normalization (dev): apply JsonFrag normalizer/purifier to provider output
|
||||
{
|
||||
local nv = env.get("HAKO_MIR_NORMALIZE_PROVIDER")
|
||||
if nv != null && ("" + nv) == "1" {
|
||||
local out_s = "" + out
|
||||
out = NormBox.normalize_all(out_s)
|
||||
}
|
||||
}
|
||||
print("[provider/emit:ok]")
|
||||
print("[MIR_OUT_BEGIN]")
|
||||
print("" + out)
|
||||
print("[MIR_OUT_END]")
|
||||
return 0
|
||||
} }
|
||||
HCODE
|
||||
local tmp_stdout; tmp_stdout=$(mktemp)
|
||||
trap 'rm -f "$tmp_hako" "$tmp_stdout" || true' RETURN
|
||||
set +e
|
||||
(cd "$ROOT" && \
|
||||
NYASH_DISABLE_PLUGINS=1 NYASH_FILEBOX_MODE="core-ro" \
|
||||
NYASH_PARSER_STAGE3=1 HAKO_PARSER_STAGE3=1 NYASH_PARSER_ALLOW_SEMICOLON=1 \
|
||||
HAKO_BUILDER_PROGRAM_JSON="$prog_json" \
|
||||
"$NYASH_BIN" --backend vm "$tmp_hako" 2>&1 | tee "$tmp_stdout" >/dev/null)
|
||||
local rc=$?
|
||||
set -e
|
||||
if [ $rc -ne 0 ] || ! grep -q "\[provider/emit:ok\]" "$tmp_stdout"; then
|
||||
return 1
|
||||
fi
|
||||
local mir
|
||||
mir=$(awk '/\[MIR_OUT_BEGIN\]/{flag=1;next}/\[MIR_OUT_END\]/{flag=0}flag' "$tmp_stdout")
|
||||
if [ -z "$mir" ]; then return 1; fi
|
||||
printf '%s' "$mir" > "$out_path"
|
||||
echo "[OK] MIR JSON written (delegate:provider): $out_path"
|
||||
return 0
|
||||
}
|
||||
|
||||
# Replace LIMIT_PLACEHOLDER with actual limit
|
||||
sed -i "s/LIMIT_PLACEHOLDER/$limit/g" "$out_path"
|
||||
|
||||
@ -131,7 +179,23 @@ MIRJSON
|
||||
local builder_box="${HAKO_MIR_BUILDER_BOX:-hako.mir.builder}"
|
||||
|
||||
local tmp_hako; tmp_hako=$(mktemp --suffix .hako)
|
||||
cat >"$tmp_hako" <<'HCODE'
|
||||
if [ "$builder_box" = "hako.mir.builder.min" ]; then
|
||||
cat >"$tmp_hako" <<'HCODE'
|
||||
using "hako.mir.builder.internal.runner_min" as BuilderRunnerMinBox
|
||||
static box Main { method main(args) {
|
||||
local prog_json = env.get("HAKO_BUILDER_PROGRAM_JSON")
|
||||
if prog_json == null { print("[builder/selfhost-first:fail:nojson]"); return 1 }
|
||||
local mir_out = BuilderRunnerMinBox.run(prog_json)
|
||||
if mir_out == null { print("[builder/selfhost-first:fail:emit]"); return 1 }
|
||||
print("[builder/selfhost-first:ok]")
|
||||
print("[MIR_OUT_BEGIN]")
|
||||
print("" + mir_out)
|
||||
print("[MIR_OUT_END]")
|
||||
return 0
|
||||
} }
|
||||
HCODE
|
||||
else
|
||||
cat >"$tmp_hako" <<'HCODE'
|
||||
using "__BUILDER_BOX__" as MirBuilderBox
|
||||
static box Main { method main(args) {
|
||||
local prog_json = env.get("HAKO_BUILDER_PROGRAM_JSON")
|
||||
@ -145,8 +209,8 @@ static box Main { method main(args) {
|
||||
return 0
|
||||
} }
|
||||
HCODE
|
||||
# Substitute builder box name after heredoc to avoid shell interpolation issues
|
||||
sed -i "s|__BUILDER_BOX__|$builder_box|g" "$tmp_hako"
|
||||
sed -i "s|__BUILDER_BOX__|$builder_box|g" "$tmp_hako"
|
||||
fi
|
||||
local tmp_stdout; tmp_stdout=$(mktemp)
|
||||
trap 'rm -f "$tmp_hako" "$tmp_stdout" || true' RETURN
|
||||
|
||||
@ -175,9 +239,10 @@ HCODE
|
||||
HAKO_MIR_BUILDER_LOOP_FORCE_JSONFRAG="${HAKO_MIR_BUILDER_LOOP_FORCE_JSONFRAG:-}" \
|
||||
HAKO_MIR_BUILDER_JSONFRAG_NORMALIZE="${HAKO_MIR_BUILDER_JSONFRAG_NORMALIZE:-}" \
|
||||
HAKO_MIR_BUILDER_JSONFRAG_PURIFY="${HAKO_MIR_BUILDER_JSONFRAG_PURIFY:-}" \
|
||||
HAKO_MIR_BUILDER_METHODIZE="${HAKO_MIR_BUILDER_METHODIZE:-}" \
|
||||
HAKO_MIR_BUILDER_NORMALIZE_TAG="${HAKO_MIR_BUILDER_NORMALIZE_TAG:-}" \
|
||||
HAKO_MIR_BUILDER_DEBUG="${HAKO_MIR_BUILDER_DEBUG:-}" \
|
||||
NYASH_DISABLE_PLUGINS=1 NYASH_FILEBOX_MODE="core-ro" HAKO_PROVIDER_POLICY="safe-core-first" \
|
||||
NYASH_DISABLE_PLUGINS="${NYASH_DISABLE_PLUGINS:-0}" NYASH_FILEBOX_MODE="core-ro" HAKO_PROVIDER_POLICY="safe-core-first" \
|
||||
NYASH_ENABLE_USING=1 HAKO_ENABLE_USING=1 \
|
||||
NYASH_PARSER_STAGE3=1 HAKO_PARSER_STAGE3=1 NYASH_PARSER_ALLOW_SEMICOLON=1 \
|
||||
NYASH_USE_NY_COMPILER=0 HAKO_USE_NY_COMPILER=0 NYASH_DISABLE_NY_COMPILER=1 HAKO_DISABLE_NY_COMPILER=1 \
|
||||
@ -230,6 +295,44 @@ HCODE
|
||||
return 0
|
||||
}
|
||||
|
||||
# Provider-first delegate: call env.mirbuilder.emit(prog_json) and capture v1 JSON
|
||||
try_provider_emit() {
|
||||
local prog_json="$1" out_path="$2"
|
||||
local tmp_hako; tmp_hako=$(mktemp --suffix .hako)
|
||||
cat >"$tmp_hako" <<'HCODE'
|
||||
static box Main { method main(args) {
|
||||
local p = env.get("HAKO_BUILDER_PROGRAM_JSON")
|
||||
if p == null { print("[provider/emit:nojson]"); return 1 }
|
||||
local a = new ArrayBox(); a.push(p)
|
||||
local out = hostbridge.extern_invoke("env.mirbuilder", "emit", a)
|
||||
print("[provider/emit:ok]")
|
||||
print("[MIR_OUT_BEGIN]")
|
||||
print("" + out)
|
||||
print("[MIR_OUT_END]")
|
||||
return 0
|
||||
} }
|
||||
HCODE
|
||||
local tmp_stdout; tmp_stdout=$(mktemp)
|
||||
trap 'rm -f "$tmp_hako" "$tmp_stdout" || true' RETURN
|
||||
set +e
|
||||
(cd "$ROOT" && \
|
||||
NYASH_DISABLE_PLUGINS="${NYASH_DISABLE_PLUGINS:-0}" NYASH_FILEBOX_MODE="core-ro" \
|
||||
NYASH_PARSER_STAGE3=1 HAKO_PARSER_STAGE3=1 NYASH_PARSER_ALLOW_SEMICOLON=1 \
|
||||
HAKO_BUILDER_PROGRAM_JSON="$prog_json" \
|
||||
"$NYASH_BIN" --backend vm "$tmp_hako" 2>&1 | tee "$tmp_stdout" >/dev/null)
|
||||
local rc=$?
|
||||
set -e
|
||||
if [ $rc -ne 0 ] || ! grep -q "\[provider/emit:ok\]" "$tmp_stdout"; then
|
||||
return 1
|
||||
fi
|
||||
local mir
|
||||
mir=$(awk '/\[MIR_OUT_BEGIN\]/{flag=1;next}/\[MIR_OUT_END\]/{flag=0}flag' "$tmp_stdout")
|
||||
if [ -z "$mir" ]; then return 1; fi
|
||||
printf '%s' "$mir" > "$out_path"
|
||||
echo "[OK] MIR JSON written (delegate:provider): $out_path"
|
||||
return 0
|
||||
}
|
||||
|
||||
# When forcing JSONFrag loop, default-enable normalize+purify (dev-only, no default changes)
|
||||
if [ "${HAKO_MIR_BUILDER_LOOP_FORCE_JSONFRAG:-0}" = "1" ]; then
|
||||
export HAKO_MIR_BUILDER_JSONFRAG_NORMALIZE="${HAKO_MIR_BUILDER_JSONFRAG_NORMALIZE:-1}"
|
||||
@ -246,12 +349,61 @@ if [ "${HAKO_SELFHOST_BUILDER_FIRST:-0}" = "1" ]; then
|
||||
fi
|
||||
fi
|
||||
|
||||
# Dev: force JsonFrag minimal loop even on provider-first path
|
||||
if [ "${HAKO_MIR_BUILDER_LOOP_FORCE_JSONFRAG:-0}" = "1" ]; then
|
||||
# Extract limit from Program(JSON)
|
||||
limit=$(printf '%s' "$PROG_JSON_OUT" | grep -o '"type":"Int","value":[0-9]*' | head -1 | grep -o '[0-9]*$' || echo "10")
|
||||
cat > "$OUT" <<MIRJSON
|
||||
{
|
||||
"functions": [{
|
||||
"name": "main",
|
||||
"params": [],
|
||||
"locals": [],
|
||||
"blocks": [
|
||||
{ "id": 0, "instructions": [
|
||||
{"op":"const","dst":1,"value":{"type":"i64","value":0}},
|
||||
{"op":"const","dst":2,"value":{"type":"i64","value": ${limit} }},
|
||||
{"op":"jump","target":1}
|
||||
]},
|
||||
{ "id": 1, "instructions": [
|
||||
{"op":"phi","dst":6,"incoming":[[2,0],[6,2]]},
|
||||
{"op":"phi","dst":3,"incoming":[[1,0],[5,2]]},
|
||||
{"op":"compare","operation":"<","lhs":3,"rhs":6,"dst":4},
|
||||
{"op":"branch","cond":4,"then":2,"else":3}
|
||||
]},
|
||||
{ "id": 2, "instructions": [
|
||||
{"op":"const","dst":10,"value":{"type":"i64","value":1}},
|
||||
{"op":"binop","operation":"+","lhs":3,"rhs":10,"dst":5},
|
||||
{"op":"jump","target":1}
|
||||
]},
|
||||
{ "id": 3, "instructions": [
|
||||
{"op":"ret","value":3}
|
||||
]}
|
||||
]
|
||||
}]
|
||||
}
|
||||
MIRJSON
|
||||
echo "[OK] MIR JSON written (provider-force-jsonfrag): $OUT"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
tmp_prog="/tmp/hako_emit_prog_$$.json"
|
||||
trap 'rm -f "$tmp_prog" || true' EXIT
|
||||
printf '%s' "$PROG_JSON_OUT" > "$tmp_prog"
|
||||
if "$NYASH_BIN" --program-json-to-mir "$OUT" --json-file "$tmp_prog" >/dev/null 2>&1; then
|
||||
echo "[OK] MIR JSON written (delegate): $OUT"
|
||||
# Provider-first delegate (v1固定): env.mirbuilder.emit を使用
|
||||
if try_provider_emit "$PROG_JSON_OUT" "$OUT"; then
|
||||
exit 0
|
||||
fi
|
||||
echo "[FAIL] Program→MIR delegate failed" >&2
|
||||
|
||||
# 最終フォールバック: 旧CLI変換(環境でv1を促す)
|
||||
if HAKO_STAGEB_FUNC_SCAN="${HAKO_STAGEB_FUNC_SCAN:-}" \
|
||||
HAKO_MIR_BUILDER_FUNCS="${HAKO_MIR_BUILDER_FUNCS:-}" \
|
||||
HAKO_MIR_BUILDER_CALL_RESOLVE="${HAKO_MIR_BUILDER_CALL_RESOLVE:-}" \
|
||||
NYASH_JSON_SCHEMA_V1=${NYASH_JSON_SCHEMA_V1:-1} \
|
||||
NYASH_MIR_UNIFIED_CALL=${NYASH_MIR_UNIFIED_CALL:-1} \
|
||||
"$NYASH_BIN" --program-json-to-mir "$OUT" --json-file "$tmp_prog" >/dev/null 2>&1; then
|
||||
echo "[OK] MIR JSON written (delegate-legacy): $OUT"
|
||||
exit 0
|
||||
fi
|
||||
echo "[FAIL] Program→MIR delegate failed (provider+legacy)" >&2
|
||||
exit 1
|
||||
|
||||
Reference in New Issue
Block a user