From 427275cb2353b90cd2bb991ec0dfc3627bd54130 Mon Sep 17 00:00:00 2001 From: hiroki23 <33798+hiroki23@users.noreply.github.com> Date: Fri, 28 Aug 2026 15:09:48 +0900 Subject: [PATCH 1/3] feat: connect Gate 1 source differential corpus --- .github/workflows/gate-zero.yml | 34 ++- TYPE_RB_REVISION | 2 +- corpus/gate1/division-by-zero/go.mod | 4 + corpus/gate1/division-by-zero/src/main.trb | 7 + corpus/gate1/division-by-zero/trbconfig.jsonc | 8 + corpus/gate1/integer-kernel/go.mod | 4 + corpus/gate1/integer-kernel/src/main.trb | 22 ++ corpus/gate1/integer-kernel/trbconfig.jsonc | 8 + corpus/gate1/integer-overflow/go.mod | 4 + corpus/gate1/integer-overflow/src/main.trb | 8 + corpus/gate1/integer-overflow/trbconfig.jsonc | 8 + corpus/gate1/integer-power-overflow/go.mod | 4 + .../gate1/integer-power-overflow/src/main.trb | 6 + .../integer-power-overflow/trbconfig.jsonc | 8 + corpus/gate1/negative-integer-exponent/go.mod | 4 + .../negative-integer-exponent/src/main.trb | 7 + .../negative-integer-exponent/trbconfig.jsonc | 8 + corpus/gate1/scalar-control-flow/go.mod | 4 + corpus/gate1/scalar-control-flow/src/main.trb | 46 +++ .../gate1/scalar-control-flow/trbconfig.jsonc | 8 + corpus/gate1/static-output/go.mod | 4 + corpus/gate1/static-output/src/main.trb | 4 + corpus/gate1/static-output/trbconfig.jsonc | 8 + .../gate1/unsupported-dynamic-output/go.mod | 4 + .../unsupported-dynamic-output/src/main.trb | 4 + .../trbconfig.jsonc | 8 + docs/gate-1-qbe.md | 10 +- src/gate1_differential_test.trb | 190 +++++++++++++ src/gate1_driver.trb | 68 +++++ src/gate1_mir.trb | 1 + src/gate1_snapshot.trb | 3 + src/gate1_test.trb | 28 +- src/gate1_toolchain.trb | 13 + src/qbe.trb | 177 ++++++++++-- tools/gate1-benchmark/go.mod | 4 + tools/gate1-benchmark/src/main.trb | 261 ++++++++++++++++++ tools/gate1-benchmark/trbconfig.jsonc | 8 + 37 files changed, 951 insertions(+), 48 deletions(-) create mode 100644 corpus/gate1/division-by-zero/go.mod create mode 100644 corpus/gate1/division-by-zero/src/main.trb create mode 100644 corpus/gate1/division-by-zero/trbconfig.jsonc create mode 100644 corpus/gate1/integer-kernel/go.mod create mode 100644 corpus/gate1/integer-kernel/src/main.trb create mode 100644 corpus/gate1/integer-kernel/trbconfig.jsonc create mode 100644 corpus/gate1/integer-overflow/go.mod create mode 100644 corpus/gate1/integer-overflow/src/main.trb create mode 100644 corpus/gate1/integer-overflow/trbconfig.jsonc create mode 100644 corpus/gate1/integer-power-overflow/go.mod create mode 100644 corpus/gate1/integer-power-overflow/src/main.trb create mode 100644 corpus/gate1/integer-power-overflow/trbconfig.jsonc create mode 100644 corpus/gate1/negative-integer-exponent/go.mod create mode 100644 corpus/gate1/negative-integer-exponent/src/main.trb create mode 100644 corpus/gate1/negative-integer-exponent/trbconfig.jsonc create mode 100644 corpus/gate1/scalar-control-flow/go.mod create mode 100644 corpus/gate1/scalar-control-flow/src/main.trb create mode 100644 corpus/gate1/scalar-control-flow/trbconfig.jsonc create mode 100644 corpus/gate1/static-output/go.mod create mode 100644 corpus/gate1/static-output/src/main.trb create mode 100644 corpus/gate1/static-output/trbconfig.jsonc create mode 100644 corpus/gate1/unsupported-dynamic-output/go.mod create mode 100644 corpus/gate1/unsupported-dynamic-output/src/main.trb create mode 100644 corpus/gate1/unsupported-dynamic-output/trbconfig.jsonc create mode 100644 src/gate1_differential_test.trb create mode 100644 src/gate1_driver.trb create mode 100644 tools/gate1-benchmark/go.mod create mode 100644 tools/gate1-benchmark/src/main.trb create mode 100644 tools/gate1-benchmark/trbconfig.jsonc diff --git a/.github/workflows/gate-zero.yml b/.github/workflows/gate-zero.yml index 1ce8caa0..0f1efd3b 100644 --- a/.github/workflows/gate-zero.yml +++ b/.github/workflows/gate-zero.yml @@ -1,4 +1,4 @@ -name: Gate 0 +name: Native gates on: pull_request: @@ -11,7 +11,7 @@ permissions: jobs: verify: - runs-on: ubuntu-latest + runs-on: macos-14 steps: - name: Check out TypeRB Native uses: actions/checkout@v5 @@ -20,7 +20,7 @@ jobs: uses: actions/checkout@v5 with: repository: type-rb/type-rb - ref: 30b5f5206680a39a02966d1579f76de55760a349 + ref: fc4c511a4ebed28cc83fbca56af0d31fb481010c path: .type-rb - name: Set up Go for the bootstrap compiler @@ -32,13 +32,31 @@ jobs: - name: Verify the compiler revision pin run: test "$(cat TYPE_RB_REVISION)" = "$(git -C .type-rb rev-parse HEAD)" + - name: Build the pinned TypeRB compiler + working-directory: .type-rb + run: go build -o "$RUNNER_TEMP/trb" ./cmd/trb + + - name: Build pinned QBE 1.3 + run: | + curl -L https://c9x.me/compile/release/qbe-1.3.tar.xz -o "$RUNNER_TEMP/qbe-1.3.tar.xz" + echo "d587905d620dc5e1d2bfa7c2cc642b9b837aa89a3188c6e37b53d756cf66e320 $RUNNER_TEMP/qbe-1.3.tar.xz" | shasum -a 256 -c - + tar -C "$RUNNER_TEMP" -xf "$RUNNER_TEMP/qbe-1.3.tar.xz" + make -C "$RUNNER_TEMP/qbe-1.3" + - name: Verify formatting - run: .type-rb/trb fmt --check . + run: "$RUNNER_TEMP/trb" fmt --check . - name: Check TypeRB sources - run: .type-rb/trb check - - - name: Run Gate 0 tests and fixtures + run: | + "$RUNNER_TEMP/trb" check + "$RUNNER_TEMP/trb" check --config tools/gate1-benchmark/trbconfig.jsonc + for config in corpus/gate1/*/trbconfig.jsonc; do + "$RUNNER_TEMP/trb" check --config "$config" + done + + - name: Run gate tests, fixtures, and source differential corpus env: TYPE_RB_NATIVE_ROOT: ${{ github.workspace }} - run: .type-rb/trb test + TYPE_RB_NATIVE_REFERENCE_TRB: ${{ runner.temp }}/trb + TYPE_RB_NATIVE_QBE: ${{ runner.temp }}/qbe-1.3/qbe + run: "$RUNNER_TEMP/trb" test diff --git a/TYPE_RB_REVISION b/TYPE_RB_REVISION index 13edaf02..74f7dc60 100644 --- a/TYPE_RB_REVISION +++ b/TYPE_RB_REVISION @@ -1 +1 @@ -30b5f5206680a39a02966d1579f76de55760a349 +fc4c511a4ebed28cc83fbca56af0d31fb481010c diff --git a/corpus/gate1/division-by-zero/go.mod b/corpus/gate1/division-by-zero/go.mod new file mode 100644 index 00000000..f76c0bc5 --- /dev/null +++ b/corpus/gate1/division-by-zero/go.mod @@ -0,0 +1,4 @@ +// Generated from trbconfig.jsonc by trb. +module github.com/type-rb/type-rb-native/corpus/gate1/division-by-zero + +go 1.27 diff --git a/corpus/gate1/division-by-zero/src/main.trb b/corpus/gate1/division-by-zero/src/main.trb new file mode 100644 index 00000000..cd1028cd --- /dev/null +++ b/corpus/gate1/division-by-zero/src/main.trb @@ -0,0 +1,7 @@ +def main() + zero := 0 + if 1 / zero == 0 + return + end + return +end diff --git a/corpus/gate1/division-by-zero/trbconfig.jsonc b/corpus/gate1/division-by-zero/trbconfig.jsonc new file mode 100644 index 00000000..8f04750c --- /dev/null +++ b/corpus/gate1/division-by-zero/trbconfig.jsonc @@ -0,0 +1,8 @@ +{ + "name": "gate1-division-by-zero", + "mode": "go", + "sourceDir": "src", + "go": { + "module": "github.com/type-rb/type-rb-native/corpus/gate1/division-by-zero" + } +} diff --git a/corpus/gate1/integer-kernel/go.mod b/corpus/gate1/integer-kernel/go.mod new file mode 100644 index 00000000..7a1a6155 --- /dev/null +++ b/corpus/gate1/integer-kernel/go.mod @@ -0,0 +1,4 @@ +// Generated from trbconfig.jsonc by trb. +module github.com/type-rb/type-rb-native/corpus/gate1/integer-kernel + +go 1.27 diff --git a/corpus/gate1/integer-kernel/src/main.trb b/corpus/gate1/integer-kernel/src/main.trb new file mode 100644 index 00000000..e23d9a3e --- /dev/null +++ b/corpus/gate1/integer-kernel/src/main.trb @@ -0,0 +1,22 @@ +def kernel(iterations: Integer): Integer + mut index := 0 + mut total := 0 + while index < iterations + total += (index % 97) * 3 + total -= index % 31 + if total > 1000000 + total /= 2 + end + index += 1 + end + return total +end + +def main() + if kernel(5000000) > 0 + puts("gate1-integer-kernel") + return + end + puts("gate1-integer-kernel-failed") + return +end diff --git a/corpus/gate1/integer-kernel/trbconfig.jsonc b/corpus/gate1/integer-kernel/trbconfig.jsonc new file mode 100644 index 00000000..2e17b17f --- /dev/null +++ b/corpus/gate1/integer-kernel/trbconfig.jsonc @@ -0,0 +1,8 @@ +{ + "name": "gate1-integer-kernel", + "mode": "go", + "sourceDir": "src", + "go": { + "module": "github.com/type-rb/type-rb-native/corpus/gate1/integer-kernel" + } +} diff --git a/corpus/gate1/integer-overflow/go.mod b/corpus/gate1/integer-overflow/go.mod new file mode 100644 index 00000000..93d6d495 --- /dev/null +++ b/corpus/gate1/integer-overflow/go.mod @@ -0,0 +1,4 @@ +// Generated from trbconfig.jsonc by trb. +module github.com/type-rb/type-rb-native/corpus/gate1/integer-overflow + +go 1.27 diff --git a/corpus/gate1/integer-overflow/src/main.trb b/corpus/gate1/integer-overflow/src/main.trb new file mode 100644 index 00000000..8ff189b5 --- /dev/null +++ b/corpus/gate1/integer-overflow/src/main.trb @@ -0,0 +1,8 @@ +def main() + mut value := 9007199254740991 + value += 1 + if value == 0 + return + end + return +end diff --git a/corpus/gate1/integer-overflow/trbconfig.jsonc b/corpus/gate1/integer-overflow/trbconfig.jsonc new file mode 100644 index 00000000..2a2b4237 --- /dev/null +++ b/corpus/gate1/integer-overflow/trbconfig.jsonc @@ -0,0 +1,8 @@ +{ + "name": "gate1-integer-overflow", + "mode": "go", + "sourceDir": "src", + "go": { + "module": "github.com/type-rb/type-rb-native/corpus/gate1/integer-overflow" + } +} diff --git a/corpus/gate1/integer-power-overflow/go.mod b/corpus/gate1/integer-power-overflow/go.mod new file mode 100644 index 00000000..0a80b386 --- /dev/null +++ b/corpus/gate1/integer-power-overflow/go.mod @@ -0,0 +1,4 @@ +// Generated from trbconfig.jsonc by trb. +module github.com/type-rb/type-rb-native/corpus/gate1/integer-power-overflow + +go 1.27 diff --git a/corpus/gate1/integer-power-overflow/src/main.trb b/corpus/gate1/integer-power-overflow/src/main.trb new file mode 100644 index 00000000..10d70161 --- /dev/null +++ b/corpus/gate1/integer-power-overflow/src/main.trb @@ -0,0 +1,6 @@ +def main() + if 2 ** 53 == 0 + return + end + return +end diff --git a/corpus/gate1/integer-power-overflow/trbconfig.jsonc b/corpus/gate1/integer-power-overflow/trbconfig.jsonc new file mode 100644 index 00000000..7ea8b3ea --- /dev/null +++ b/corpus/gate1/integer-power-overflow/trbconfig.jsonc @@ -0,0 +1,8 @@ +{ + "name": "gate1-integer-power-overflow", + "mode": "go", + "sourceDir": "src", + "go": { + "module": "github.com/type-rb/type-rb-native/corpus/gate1/integer-power-overflow" + } +} diff --git a/corpus/gate1/negative-integer-exponent/go.mod b/corpus/gate1/negative-integer-exponent/go.mod new file mode 100644 index 00000000..b78f9a8b --- /dev/null +++ b/corpus/gate1/negative-integer-exponent/go.mod @@ -0,0 +1,4 @@ +// Generated from trbconfig.jsonc by trb. +module github.com/type-rb/type-rb-native/corpus/gate1/negative-integer-exponent + +go 1.27 diff --git a/corpus/gate1/negative-integer-exponent/src/main.trb b/corpus/gate1/negative-integer-exponent/src/main.trb new file mode 100644 index 00000000..b16c5683 --- /dev/null +++ b/corpus/gate1/negative-integer-exponent/src/main.trb @@ -0,0 +1,7 @@ +def main() + exponent :=- 1 + if 2 ** exponent == 0 + return + end + return +end diff --git a/corpus/gate1/negative-integer-exponent/trbconfig.jsonc b/corpus/gate1/negative-integer-exponent/trbconfig.jsonc new file mode 100644 index 00000000..649679c0 --- /dev/null +++ b/corpus/gate1/negative-integer-exponent/trbconfig.jsonc @@ -0,0 +1,8 @@ +{ + "name": "gate1-negative-integer-exponent", + "mode": "go", + "sourceDir": "src", + "go": { + "module": "github.com/type-rb/type-rb-native/corpus/gate1/negative-integer-exponent" + } +} diff --git a/corpus/gate1/scalar-control-flow/go.mod b/corpus/gate1/scalar-control-flow/go.mod new file mode 100644 index 00000000..c82e25f2 --- /dev/null +++ b/corpus/gate1/scalar-control-flow/go.mod @@ -0,0 +1,4 @@ +// Generated from trbconfig.jsonc by trb. +module github.com/type-rb/type-rb-native/corpus/gate1/scalar-control-flow + +go 1.27 diff --git a/corpus/gate1/scalar-control-flow/src/main.trb b/corpus/gate1/scalar-control-flow/src/main.trb new file mode 100644 index 00000000..2964d64e --- /dev/null +++ b/corpus/gate1/scalar-control-flow/src/main.trb @@ -0,0 +1,46 @@ +def sum_to(limit: Integer): Integer + mut index := 0 + mut total := 0 + while index < limit + index += 1 + total += index + end + return total +end + +def reduce(mut value: Integer): Integer + while value > 3 + if value % 2 == 0 + value /= 2 + else + value -= 1 + end + end + return value +end + +def scale(value: Float): Float + return value * 1.5 +end + +def main() + total := sum_to(100) + if total == 5050 + if reduce(42) == 2 + if - 7 / 3 == - 2 + if - 7 % 3 == - 1 + if !false + if scale(2.0) == 3.0 + if 3 ** 4 == 81 + puts("gate1-scalar-control-flow") + return + end + end + end + end + end + end + end + puts("gate1-scalar-control-flow-failed") + return +end diff --git a/corpus/gate1/scalar-control-flow/trbconfig.jsonc b/corpus/gate1/scalar-control-flow/trbconfig.jsonc new file mode 100644 index 00000000..79276afb --- /dev/null +++ b/corpus/gate1/scalar-control-flow/trbconfig.jsonc @@ -0,0 +1,8 @@ +{ + "name": "gate1-scalar-control-flow", + "mode": "go", + "sourceDir": "src", + "go": { + "module": "github.com/type-rb/type-rb-native/corpus/gate1/scalar-control-flow" + } +} diff --git a/corpus/gate1/static-output/go.mod b/corpus/gate1/static-output/go.mod new file mode 100644 index 00000000..fd3aebdf --- /dev/null +++ b/corpus/gate1/static-output/go.mod @@ -0,0 +1,4 @@ +// Generated from trbconfig.jsonc by trb. +module github.com/type-rb/type-rb-native/corpus/gate1/static-output + +go 1.27 diff --git a/corpus/gate1/static-output/src/main.trb b/corpus/gate1/static-output/src/main.trb new file mode 100644 index 00000000..3508c35d --- /dev/null +++ b/corpus/gate1/static-output/src/main.trb @@ -0,0 +1,4 @@ +def main() + puts("gate1-static-output") + return +end diff --git a/corpus/gate1/static-output/trbconfig.jsonc b/corpus/gate1/static-output/trbconfig.jsonc new file mode 100644 index 00000000..cef066c4 --- /dev/null +++ b/corpus/gate1/static-output/trbconfig.jsonc @@ -0,0 +1,8 @@ +{ + "name": "gate1-static-output", + "mode": "go", + "sourceDir": "src", + "go": { + "module": "github.com/type-rb/type-rb-native/corpus/gate1/static-output" + } +} diff --git a/corpus/gate1/unsupported-dynamic-output/go.mod b/corpus/gate1/unsupported-dynamic-output/go.mod new file mode 100644 index 00000000..91042b8e --- /dev/null +++ b/corpus/gate1/unsupported-dynamic-output/go.mod @@ -0,0 +1,4 @@ +// Generated from trbconfig.jsonc by trb. +module github.com/type-rb/type-rb-native/corpus/gate1/unsupported-dynamic-output + +go 1.27 diff --git a/corpus/gate1/unsupported-dynamic-output/src/main.trb b/corpus/gate1/unsupported-dynamic-output/src/main.trb new file mode 100644 index 00000000..00cfa9bc --- /dev/null +++ b/corpus/gate1/unsupported-dynamic-output/src/main.trb @@ -0,0 +1,4 @@ +def main() + puts(42) + return +end diff --git a/corpus/gate1/unsupported-dynamic-output/trbconfig.jsonc b/corpus/gate1/unsupported-dynamic-output/trbconfig.jsonc new file mode 100644 index 00000000..205ada28 --- /dev/null +++ b/corpus/gate1/unsupported-dynamic-output/trbconfig.jsonc @@ -0,0 +1,8 @@ +{ + "name": "gate1-unsupported-dynamic-output", + "mode": "go", + "sourceDir": "src", + "go": { + "module": "github.com/type-rb/type-rb-native/corpus/gate1/unsupported-dynamic-output" + } +} diff --git a/docs/gate-1-qbe.md b/docs/gate-1-qbe.md index 2edbbef7..91b62f00 100644 --- a/docs/gate-1-qbe.md +++ b/docs/gate-1-qbe.md @@ -48,7 +48,7 @@ contract. Supported instructions are: - `boolean_literal`, `integer_literal`, and `float_literal`; -- `integer_binary` with `add`, `subtract`, `multiply`, `divide`, or `remainder`; +- `integer_binary` with `add`, `subtract`, `multiply`, `divide`, `remainder`, or `power`; - `float_binary` with `add`, `subtract`, `multiply`, or `divide`; - `integer_compare` and `float_compare` with the six ordered comparison names; - `boolean_not`; @@ -63,10 +63,10 @@ and the decoder applies resource limits before code generation. Portable Integer values remain within `-9007199254740991` through `9007199254740991`. Arithmetic is checked before an out-of-range result can be -observed. Divide-by-zero, remainder-by-zero, and range failures write a fixed -diagnostic to standard error and exit with status 70 in this temporary runtime. -The exact failure text remains experimental until the source-connected -differential corpus establishes the reference behavior. +observed. The source-connected differential corpus runs the optimized Go +baseline with `GOTRACEBACK=none`; range and division-by-zero failures then +match its exact standard error and status 2. This process envelope remains an +internal Gate 1 convention rather than a promoted language guarantee. Boolean values use QBE words, Integer values use QBE longs, and Float values use QBE doubles. Non-entry block parameters are lowered through typed stack diff --git a/src/gate1_differential_test.trb b/src/gate1_differential_test.trb new file mode 100644 index 00000000..e7b0ab8a --- /dev/null +++ b/src/gate1_differential_test.trb @@ -0,0 +1,190 @@ +import { decode_gate1_snapshot } from gate1_snapshot +import { build_gate1_executable } from gate1_toolchain +import { create_directory } from trb/std/filesystem +import { environment, run } from trb/std/process +import { Result } from trb/std/result +import { describe, expect, test } from trb/std/test + +record Gate1Observation + status: Integer + stdout: String + stderr: String +end + +record Gate1DifferentialPair + reference: Gate1Observation + native: Gate1Observation +end + +record Gate1DifferentialExpectation + name: String + stdout: String + stderr: String + status: Integer +end + +def _gate1_observe(command: String): Result + case run("/usr/bin/env", ["GOTRACEBACK=none", command]) + when Result::Ok(process) + return Result::Ok( + Gate1Observation.new( + status: process.status, + stdout: process.stdout, + stderr: process.stderr, + ) + ) + when Result::Err(error) + return Result::Err(error.operation + ": " + error.message) + end +end + +def _gate1_differential_case(name: String): Result + root := environment("TYPE_RB_NATIVE_ROOT") + reference_trb := environment("TYPE_RB_NATIVE_REFERENCE_TRB") + qbe := environment("TYPE_RB_NATIVE_QBE") + if root == nil + return Result::Err("TYPE_RB_NATIVE_ROOT is unavailable") + end + if reference_trb == nil + return Result::Err("TYPE_RB_NATIVE_REFERENCE_TRB is unavailable") + end + if qbe == nil + return Result::Err("Gate 1 differential environment is incomplete") + end + config := root + "/corpus/gate1/" + name + "/trbconfig.jsonc" + workspace := "/tmp/type-rb-native-gate1-differential-" + name + case create_directory(workspace) + when Result::Ok(_unit) + when Result::Err(_error) + end + snapshot_process := case run(reference_trb, ["compiler", "native-snapshot", "--config", config]) + when Result::Ok(process) + process + when Result::Err(error) + return Result::Err("snapshot: " + error.operation + ": " + error.message) + end + if !snapshot_process.success + return Result::Err("snapshot: " + snapshot_process.stderr) + end + native_module := case decode_gate1_snapshot(snapshot_process.stdout) + when Result::Ok(value) + value + when Result::Err(diagnostic) + return Result::Err( + "decode: " + diagnostic.code + " " + diagnostic.path + ": " + diagnostic.message + ) + end + native_output := workspace + "/native" + case build_gate1_executable(native_module, qbe, "/usr/bin/cc", workspace, native_output) + when Result::Ok(_report) + when Result::Err(error) + return Result::Err("native-build: " + error.phase + ": " + error.message) + end + reference_output := workspace + "/reference" + reference_build := case run( + reference_trb, + ["build", "--compile", "--config", config, "--outfile", reference_output], + ) + when Result::Ok(process) + process + when Result::Err(error) + return Result::Err("reference-build: " + error.operation + ": " + error.message) + end + if !reference_build.success + return Result::Err("reference-build: " + reference_build.stderr) + end + reference_observation := try _gate1_observe(reference_output) + native_observation := try _gate1_observe(native_output) + return Result::Ok( + Gate1DifferentialPair.new(reference: reference_observation, native: native_observation) + ) +end + +describe("Gate 1 source-connected differential corpus") do + test("matches optimized Go output and process failure behavior") do + if environment("TYPE_RB_NATIVE_REFERENCE_TRB") == nil || environment("TYPE_RB_NATIVE_QBE") == nil + expect(true).to_be_true() + else + expectations: Array := [ + Gate1DifferentialExpectation.new( + name: "static-output", + stdout: "gate1-static-output\n", + stderr: "", + status: 0, + ), + Gate1DifferentialExpectation.new( + name: "scalar-control-flow", + stdout: "gate1-scalar-control-flow\n", + stderr: "", + status: 0, + ), + Gate1DifferentialExpectation.new( + name: "integer-kernel", + stdout: "gate1-integer-kernel\n", + stderr: "", + status: 0, + ), + Gate1DifferentialExpectation.new( + name: "integer-overflow", + stdout: "", + stderr: "panic: Integer is outside the portable range\n", + status: 2, + ), + Gate1DifferentialExpectation.new( + name: "integer-power-overflow", + stdout: "", + stderr: "panic: Integer is outside the portable range\n", + status: 2, + ), + Gate1DifferentialExpectation.new( + name: "negative-integer-exponent", + stdout: "", + stderr: "panic: negative Integer exponent\n", + status: 2, + ), + Gate1DifferentialExpectation.new( + name: "division-by-zero", + stdout: "", + stderr: "panic: division by zero\n", + status: 2, + ), + ] + mut index := 0 + while index < expectations.size() + expected := expectations[index] + case _gate1_differential_case(expected.name) + when Result::Ok(pair) + expect(pair.reference).to_equal(pair.native) + expect(pair.native.status).to_equal(expected.status) + expect(pair.native.stdout).to_equal(expected.stdout) + expect(pair.native.stderr).to_equal(expected.stderr) + when Result::Err(error) + puts(error) + expect(false).to_be_true() + end + index += 1 + end + end + end + + test("rejects unsupported source explicitly at the producer boundary") do + root := environment("TYPE_RB_NATIVE_ROOT") + reference_trb := environment("TYPE_RB_NATIVE_REFERENCE_TRB") + if root == nil + expect(true).to_be_true() + else + if reference_trb == nil + expect(true).to_be_true() + else + config := root + "/corpus/gate1/unsupported-dynamic-output/trbconfig.jsonc" + case run(reference_trb, ["compiler", "native-snapshot", "--config", config]) + when Result::Ok(process) + expect(process.success).to_be_false() + expect(process.stderr.include?("native snapshot v2 does not support dynamic puts() output")).to_be_true() + when Result::Err(_error) + expect(false).to_be_true() + end + end + end + end +end diff --git a/src/gate1_driver.trb b/src/gate1_driver.trb new file mode 100644 index 00000000..43a6c40d --- /dev/null +++ b/src/gate1_driver.trb @@ -0,0 +1,68 @@ +import { decode_gate1_snapshot } from gate1_snapshot +import { build_gate1_executable } from gate1_toolchain +import { write_text } from trb/std/filesystem +import { argv, run } from trb/std/process +import { Result } from trb/std/result +import { Instant } from trb/std/time + +def _gate1_driver_usage(): String + return "usage: type-rb-native REFERENCE_TRB CONFIG QBE CC WORKSPACE OUTPUT" +end + +def main() + arguments := argv() + if arguments.size() != 6 + puts(_gate1_driver_usage()) + return + end + snapshot_started := Instant.now() + snapshot_process := case run( + arguments[0], + ["compiler", "native-snapshot", "--config", arguments[1]], + ) + when Result::Ok(result) + result + when Result::Err(error) + puts("snapshot: " + error.operation + ": " + error.message) + return + end + snapshot_seconds := Instant.now().duration_since(snapshot_started).total_seconds() + if !snapshot_process.success + puts("snapshot: reference compiler rejected the source") + puts(snapshot_process.stderr) + return + end + snapshot_path := arguments[4] + "/snapshot.json" + case write_text(snapshot_path, snapshot_process.stdout) + when Result::Ok(_unit) + when Result::Err(error) + puts("snapshot: " + error.operation + ": " + error.message) + return + end + decode_started := Instant.now() + native_module := case decode_gate1_snapshot(snapshot_process.stdout) + when Result::Ok(value) + value + when Result::Err(diagnostic) + puts("decode: " + diagnostic.code + " " + diagnostic.path + ": " + diagnostic.message) + return + end + decode_seconds := Instant.now().duration_since(decode_started).total_seconds() + case build_gate1_executable( + native_module, + arguments[2], + arguments[3], + arguments[4], + arguments[5], + ) + when Result::Ok(report) + puts("gate1-phase,snapshot," + snapshot_seconds.to_s()) + puts("gate1-phase,decode," + decode_seconds.to_s()) + puts("gate1-phase,emit," + report.emit_seconds.to_s()) + puts("gate1-phase,qbe," + report.qbe_seconds.to_s()) + puts("gate1-phase,link," + report.link_seconds.to_s()) + when Result::Err(error) + puts("build: " + error.phase + ": " + error.message) + end + return +end diff --git a/src/gate1_mir.trb b/src/gate1_mir.trb index 192e4512..9a9cda73 100644 --- a/src/gate1_mir.trb +++ b/src/gate1_mir.trb @@ -16,6 +16,7 @@ enum IntegerBinaryOperator Multiply Divide Remainder + Power end enum FloatBinaryOperator diff --git a/src/gate1_snapshot.trb b/src/gate1_snapshot.trb index 8ded490d..d8a4f52b 100644 --- a/src/gate1_snapshot.trb +++ b/src/gate1_snapshot.trb @@ -415,6 +415,9 @@ def _gate1_integer_operator(name: String, path: String): Result::Ok(IntegerBinaryOperator::Remainder) end + if name == "power" + return Result::Ok(IntegerBinaryOperator::Power) + end return Result::Err( boundary_diagnostic("TRBN0003", path, "unsupported Gate 1 Integer operator") ) diff --git a/src/gate1_test.trb b/src/gate1_test.trb index 00bc6eb9..433a6951 100644 --- a/src/gate1_test.trb +++ b/src/gate1_test.trb @@ -230,13 +230,13 @@ def _gate1_arithmetic_module(overflow: Boolean): Gate1Module mut instructions: Array := [] if overflow instructions = [ - Gate1Instruction::IntegerLiteral("maximum", 9007199254740991, _gate1_origin(20)), Gate1Instruction::IntegerLiteral("two", 2, _gate1_origin(20)), + Gate1Instruction::IntegerLiteral("fifty_three", 53, _gate1_origin(20)), Gate1Instruction::IntegerBinary( "overflow", - IntegerBinaryOperator::Multiply, - "maximum", + IntegerBinaryOperator::Power, "two", + "fifty_three", _gate1_origin(20), ), Gate1Instruction::WriteStatic("unreachable\n", _gate1_origin(20)), @@ -248,7 +248,7 @@ def _gate1_arithmetic_module(overflow: Boolean): Gate1Module Gate1Instruction::IntegerLiteral("forty_one", 41, _gate1_origin(20)), Gate1Instruction::IntegerLiteral("negative_seven", - 7, _gate1_origin(20)), Gate1Instruction::IntegerLiteral("negative_five", - 5, _gate1_origin(20)), - Gate1Instruction::IntegerLiteral("expected", 77, _gate1_origin(20)), + Gate1Instruction::IntegerLiteral("expected", 104, _gate1_origin(20)), Gate1Instruction::IntegerBinary( "difference", IntegerBinaryOperator::Subtract, @@ -298,10 +298,24 @@ def _gate1_arithmetic_module(overflow: Boolean): Gate1Module "negative_product", _gate1_origin(20), ), + Gate1Instruction::IntegerBinary( + "power", + IntegerBinaryOperator::Power, + "three", + "three", + _gate1_origin(20), + ), + Gate1Instruction::IntegerBinary( + "complete", + IntegerBinaryOperator::Add, + "combined", + "power", + _gate1_origin(20), + ), Gate1Instruction::IntegerCompare( "matches", ComparisonOperator::Equal, - "combined", + "complete", "expected", _gate1_origin(20), ), @@ -547,9 +561,9 @@ describe("Gate 1 scalar QBE path") do when Result::Ok(report) case run(report.output_path, []) when Result::Ok(process_result) - expect(process_result.status).to_equal(70) + expect(process_result.status).to_equal(2) expect(process_result.stdout).to_equal("") - expect(process_result.stderr).to_equal("TypeRB Integer arithmetic error\n") + expect(process_result.stderr).to_equal("panic: Integer is outside the portable range\n") when Result::Err(_error) expect(false).to_be_true() end diff --git a/src/gate1_toolchain.trb b/src/gate1_toolchain.trb index 7e8081ad..8a661b77 100644 --- a/src/gate1_toolchain.trb +++ b/src/gate1_toolchain.trb @@ -3,6 +3,7 @@ import { emit_qbe } from qbe import { write_text } from trb/std/filesystem import { run } from trb/std/process import { Result } from trb/std/result +import { Instant } from trb/std/time record Gate1BuildError phase: String @@ -16,6 +17,9 @@ record Gate1BuildReport qbe_ir_path: String assembly_path: String output_path: String + emit_seconds: Float + qbe_seconds: Float + link_seconds: Float end def build_gate1_executable( @@ -25,6 +29,7 @@ def build_gate1_executable( workspace: String, output_path: String, ): Result + emit_started := Instant.now() qbe_source := case emit_qbe(native_module) when Result::Ok(source) source @@ -36,6 +41,7 @@ def build_gate1_executable( ) ) end + emit_seconds := Instant.now().duration_since(emit_started).total_seconds() qbe_ir_path := workspace + "/module.ssa" assembly_path := workspace + "/module.s" case write_text(qbe_ir_path, qbe_source) @@ -45,6 +51,7 @@ def build_gate1_executable( Gate1BuildError.new(phase: "write-qbe", message: error.operation + ": " + error.message) ) end + qbe_started := Instant.now() qbe_result := case run(qbe_command, ["-t", "arm64_apple", qbe_ir_path]) when Result::Ok(process_result) process_result @@ -53,6 +60,7 @@ def build_gate1_executable( Gate1BuildError.new(phase: "qbe", message: error.operation + ": " + error.message) ) end + qbe_seconds := Instant.now().duration_since(qbe_started).total_seconds() if !qbe_result.success return Result::Err( Gate1BuildError.new( @@ -71,6 +79,7 @@ def build_gate1_executable( Gate1BuildError.new(phase: "write-assembly", message: error.operation + ": " + error.message) ) end + link_started := Instant.now() cc_result := case run(cc_command, [assembly_path, "-Wl,-dead_strip", "-o", output_path]) when Result::Ok(process_result) process_result @@ -79,6 +88,7 @@ def build_gate1_executable( Gate1BuildError.new(phase: "link", message: error.operation + ": " + error.message) ) end + link_seconds := Instant.now().duration_since(link_started).total_seconds() if !cc_result.success return Result::Err( Gate1BuildError.new( @@ -95,6 +105,9 @@ def build_gate1_executable( qbe_ir_path: qbe_ir_path, assembly_path: assembly_path, output_path: output_path, + emit_seconds: emit_seconds, + qbe_seconds: qbe_seconds, + link_seconds: link_seconds, ) ) end diff --git a/src/qbe.trb b/src/qbe.trb index 594941a8..d4ef5153 100644 --- a/src/qbe.trb +++ b/src/qbe.trb @@ -71,7 +71,9 @@ def _qbe_collect_static_data(native_module: Gate1Module): Array end def _qbe_emit_static_data(static_data: Array, mut writer: StringBuilder) - _qbe_line(writer, "data $trbn_arithmetic_error = { b 84 121 112 101 82 66 32 73 110 116 101 103 101 114 32 97 114 105 116 104 109 101 116 105 99 32 101 114 114 111 114 10 }") + _qbe_line(writer, "data $trbn_integer_range_error = { b 112 97 110 105 99 58 32 73 110 116 101 103 101 114 32 105 115 32 111 117 116 115 105 100 101 32 116 104 101 32 112 111 114 116 97 98 108 101 32 114 97 110 103 101 10 }") + _qbe_line(writer, "data $trbn_division_error = { b 112 97 110 105 99 58 32 100 105 118 105 115 105 111 110 32 98 121 32 122 101 114 111 10 }") + _qbe_line(writer, "data $trbn_negative_exponent_error = { b 112 97 110 105 99 58 32 110 101 103 97 116 105 118 101 32 73 110 116 101 103 101 114 32 101 120 112 111 110 101 110 116 10 }") mut index := 0 while index < static_data.size() item := static_data[index] @@ -94,10 +96,24 @@ def _qbe_emit_static_data(static_data: Array, mut writer: StringB end def _qbe_emit_runtime(mut writer: StringBuilder) - _qbe_line(writer, "function $trbn_arithmetic_fail() {") + _qbe_line(writer, "function $trbn_integer_range_fail() {") _qbe_line(writer, "@start") - _qbe_line(writer, "\tcall $write(w 2, l $trbn_arithmetic_error, l 32)") - _qbe_line(writer, "\tcall $exit(w 70)") + _qbe_line(writer, "\tcall $write(w 2, l $trbn_integer_range_error, l 45)") + _qbe_line(writer, "\tcall $exit(w 2)") + _qbe_line(writer, "\thlt") + _qbe_line(writer, "}") + _qbe_line(writer, "") + _qbe_line(writer, "function $trbn_division_fail() {") + _qbe_line(writer, "@start") + _qbe_line(writer, "\tcall $write(w 2, l $trbn_division_error, l 24)") + _qbe_line(writer, "\tcall $exit(w 2)") + _qbe_line(writer, "\thlt") + _qbe_line(writer, "}") + _qbe_line(writer, "") + _qbe_line(writer, "function $trbn_negative_exponent_fail() {") + _qbe_line(writer, "@start") + _qbe_line(writer, "\tcall $write(w 2, l $trbn_negative_exponent_error, l 33)") + _qbe_line(writer, "\tcall $exit(w 2)") _qbe_line(writer, "\thlt") _qbe_line(writer, "}") _qbe_line(writer, "") @@ -106,6 +122,7 @@ def _qbe_emit_runtime(mut writer: StringBuilder) _qbe_emit_checked_multiply(writer) _qbe_emit_checked_divide(writer) _qbe_emit_checked_remainder(writer) + _qbe_emit_checked_power(writer) return end @@ -119,7 +136,7 @@ def _qbe_emit_checked_add(mut writer: StringBuilder) _qbe_line(writer, "\t%too_low =w csltl %result, -9007199254740991") _qbe_line(writer, "\tjnz %too_low, @fail, @ok") _qbe_line(writer, "@fail") - _qbe_line(writer, "\tcall $trbn_arithmetic_fail()") + _qbe_line(writer, "\tcall $trbn_integer_range_fail()") _qbe_line(writer, "\thlt") _qbe_line(writer, "@ok") _qbe_line(writer, "\tret %result") @@ -138,7 +155,7 @@ def _qbe_emit_checked_subtract(mut writer: StringBuilder) _qbe_line(writer, "\t%too_low =w csltl %result, -9007199254740991") _qbe_line(writer, "\tjnz %too_low, @fail, @ok") _qbe_line(writer, "@fail") - _qbe_line(writer, "\tcall $trbn_arithmetic_fail()") + _qbe_line(writer, "\tcall $trbn_integer_range_fail()") _qbe_line(writer, "\thlt") _qbe_line(writer, "@ok") _qbe_line(writer, "\tret %result") @@ -189,7 +206,7 @@ def _qbe_emit_checked_multiply(mut writer: StringBuilder) _qbe_line(writer, "@zero") _qbe_line(writer, "\tret 0") _qbe_line(writer, "@fail") - _qbe_line(writer, "\tcall $trbn_arithmetic_fail()") + _qbe_line(writer, "\tcall $trbn_integer_range_fail()") _qbe_line(writer, "\thlt") _qbe_line(writer, "}") _qbe_line(writer, "") @@ -202,7 +219,7 @@ def _qbe_emit_checked_divide(mut writer: StringBuilder) _qbe_line(writer, "\t%zero =w ceql %right, 0") _qbe_line(writer, "\tjnz %zero, @fail, @ok") _qbe_line(writer, "@fail") - _qbe_line(writer, "\tcall $trbn_arithmetic_fail()") + _qbe_line(writer, "\tcall $trbn_division_fail()") _qbe_line(writer, "\thlt") _qbe_line(writer, "@ok") _qbe_line(writer, "\t%result =l div %left, %right") @@ -218,7 +235,7 @@ def _qbe_emit_checked_remainder(mut writer: StringBuilder) _qbe_line(writer, "\t%zero =w ceql %right, 0") _qbe_line(writer, "\tjnz %zero, @fail, @ok") _qbe_line(writer, "@fail") - _qbe_line(writer, "\tcall $trbn_arithmetic_fail()") + _qbe_line(writer, "\tcall $trbn_division_fail()") _qbe_line(writer, "\thlt") _qbe_line(writer, "@ok") _qbe_line(writer, "\t%result =l rem %left, %right") @@ -228,6 +245,55 @@ def _qbe_emit_checked_remainder(mut writer: StringBuilder) return end +def _qbe_emit_checked_power(mut writer: StringBuilder) + _qbe_line(writer, "function l $trbn_ipow(l %base, l %exponent) {") + _qbe_line(writer, "@start") + _qbe_line(writer, "\t%negative =w csltl %exponent, 0") + _qbe_line(writer, "\tjnz %negative, @negative, @initialize") + _qbe_line(writer, "@negative") + _qbe_line(writer, "\tcall $trbn_negative_exponent_fail()") + _qbe_line(writer, "\thlt") + _qbe_line(writer, "@initialize") + _qbe_line(writer, "\t%result_slot =l alloc8 8") + _qbe_line(writer, "\t%factor_slot =l alloc8 8") + _qbe_line(writer, "\t%exponent_slot =l alloc8 8") + _qbe_line(writer, "\tstorel 1, %result_slot") + _qbe_line(writer, "\tstorel %base, %factor_slot") + _qbe_line(writer, "\tstorel %exponent, %exponent_slot") + _qbe_line(writer, "\tjmp @loop") + _qbe_line(writer, "@loop") + _qbe_line(writer, "\t%remaining =l loadl %exponent_slot") + _qbe_line(writer, "\t%done =w ceql %remaining, 0") + _qbe_line(writer, "\tjnz %done, @finish, @test_bit") + _qbe_line(writer, "@test_bit") + _qbe_line(writer, "\t%bit =l and %remaining, 1") + _qbe_line(writer, "\t%odd =w ceql %bit, 1") + _qbe_line(writer, "\tjnz %odd, @multiply_result, @advance") + _qbe_line(writer, "@multiply_result") + _qbe_line(writer, "\t%current_result =l loadl %result_slot") + _qbe_line(writer, "\t%current_factor =l loadl %factor_slot") + _qbe_line(writer, "\t%product =l call $trbn_imul(l %current_result, l %current_factor)") + _qbe_line(writer, "\tstorel %product, %result_slot") + _qbe_line(writer, "\tjmp @advance") + _qbe_line(writer, "@advance") + _qbe_line(writer, "\t%remaining_for_advance =l loadl %exponent_slot") + _qbe_line(writer, "\t%next_exponent =l div %remaining_for_advance, 2") + _qbe_line(writer, "\tstorel %next_exponent, %exponent_slot") + _qbe_line(writer, "\t%finished =w ceql %next_exponent, 0") + _qbe_line(writer, "\tjnz %finished, @finish, @square_factor") + _qbe_line(writer, "@square_factor") + _qbe_line(writer, "\t%factor =l loadl %factor_slot") + _qbe_line(writer, "\t%squared =l call $trbn_imul(l %factor, l %factor)") + _qbe_line(writer, "\tstorel %squared, %factor_slot") + _qbe_line(writer, "\tjmp @loop") + _qbe_line(writer, "@finish") + _qbe_line(writer, "\t%result =l loadl %result_slot") + _qbe_line(writer, "\tret %result") + _qbe_line(writer, "}") + _qbe_line(writer, "") + return +end + def _qbe_emit_function( native_module: Gate1Module, function: Gate1Function, @@ -438,9 +504,14 @@ def _qbe_emit_instruction( _qbe_line(writer, "\t" + values.fetch(result) + " =d copy d_" + value.to_s()) when Gate1Instruction::IntegerBinary(result, operator, left, right, origin) _qbe_emit_origin(native_module, origin, writer) - _qbe_line(writer, - "\t" + values.fetch(result) + " =l call " + _qbe_integer_operator(operator) + - "(l " + values.fetch(left) + ", l " + values.fetch(right) + ")" + _qbe_emit_integer_binary( + operator, + values.fetch(result), + values.fetch(left), + values.fetch(right), + block_index, + instruction_index, + writer, ) when Gate1Instruction::FloatBinary(result, operator, left, right, origin) _qbe_emit_origin(native_module, origin, writer) @@ -491,6 +562,73 @@ def _qbe_emit_instruction( return end +def _qbe_emit_integer_binary( + operator: IntegerBinaryOperator, + result: String, + left: String, + right: String, + block_index: Integer, + instruction_index: Integer, + mut writer: StringBuilder, + ) + prefix := "@integer_" + block_index.to_s() + "_" + instruction_index.to_s() + "_" + case operator + when IntegerBinaryOperator::Add + _qbe_line(writer, "\t" + result + " =l add " + left + ", " + right) + _qbe_emit_inline_range_check(result, prefix, writer) + when IntegerBinaryOperator::Subtract + _qbe_line(writer, "\t" + result + " =l sub " + left + ", " + right) + _qbe_emit_inline_range_check(result, prefix, writer) + when IntegerBinaryOperator::Multiply + _qbe_line(writer, "\t" + result + " =l call $trbn_imul(l " + left + ", l " + right + ")") + when IntegerBinaryOperator::Divide + _qbe_emit_inline_division(result, left, right, "div", prefix, writer) + when IntegerBinaryOperator::Remainder + _qbe_emit_inline_division(result, left, right, "rem", prefix, writer) + when IntegerBinaryOperator::Power + _qbe_line(writer, "\t" + result + " =l call $trbn_ipow(l " + left + ", l " + right + ")") + end + return +end + +def _qbe_emit_inline_range_check(value: String, prefix: String, mut writer: StringBuilder) + check_low := prefix + "check_low" + fail := prefix + "fail" + ok := prefix + "ok" + temporary_prefix := prefix.replace_all("@", "%") + _qbe_line(writer, "\t" + temporary_prefix + "too_high =w csgtl " + value + ", 9007199254740991") + _qbe_line(writer, "\tjnz " + temporary_prefix + "too_high, " + fail + ", " + check_low) + _qbe_line(writer, check_low) + _qbe_line(writer, "\t" + temporary_prefix + "too_low =w csltl " + value + ", -9007199254740991") + _qbe_line(writer, "\tjnz " + temporary_prefix + "too_low, " + fail + ", " + ok) + _qbe_line(writer, fail) + _qbe_line(writer, "\tcall $trbn_integer_range_fail()") + _qbe_line(writer, "\thlt") + _qbe_line(writer, ok) + return +end + +def _qbe_emit_inline_division( + result: String, + left: String, + right: String, + operation: String, + prefix: String, + mut writer: StringBuilder, + ) + fail := prefix + "fail" + ok := prefix + "ok" + zero := prefix.replace_all("@", "%") + "zero" + _qbe_line(writer, "\t" + zero + " =w ceql " + right + ", 0") + _qbe_line(writer, "\tjnz " + zero + ", " + fail + ", " + ok) + _qbe_line(writer, fail) + _qbe_line(writer, "\tcall $trbn_division_fail()") + _qbe_line(writer, "\thlt") + _qbe_line(writer, ok) + _qbe_line(writer, "\t" + result + " =l " + operation + " " + left + ", " + right) + return +end + def _qbe_emit_terminator( native_module: Gate1Module, function: Gate1Function, @@ -567,21 +705,6 @@ def _qbe_emit_origin(native_module: Gate1Module, origin: SourceOrigin, mut write return end -def _qbe_integer_operator(operator: IntegerBinaryOperator): String - case operator - when IntegerBinaryOperator::Add - return "$trbn_iadd" - when IntegerBinaryOperator::Subtract - return "$trbn_isub" - when IntegerBinaryOperator::Multiply - return "$trbn_imul" - when IntegerBinaryOperator::Divide - return "$trbn_idiv" - when IntegerBinaryOperator::Remainder - return "$trbn_irem" - end -end - def _qbe_float_operator(operator: FloatBinaryOperator): String case operator when FloatBinaryOperator::Add diff --git a/tools/gate1-benchmark/go.mod b/tools/gate1-benchmark/go.mod new file mode 100644 index 00000000..98d6d15a --- /dev/null +++ b/tools/gate1-benchmark/go.mod @@ -0,0 +1,4 @@ +// Generated from trbconfig.jsonc by trb. +module github.com/type-rb/type-rb-native/tools/gate1-benchmark + +go 1.27 diff --git a/tools/gate1-benchmark/src/main.trb b/tools/gate1-benchmark/src/main.trb new file mode 100644 index 00000000..507149cb --- /dev/null +++ b/tools/gate1-benchmark/src/main.trb @@ -0,0 +1,261 @@ +import { create_directory, write_text } from trb/std/filesystem +import { argv, run } from trb/std/process +import { Result } from trb/std/result +import trb/std/string_builder +import { Instant } from trb/std/time + +record TimedProcess + seconds: Float + status: Integer + stdout: String + stderr: String +end + +def measure_process(command: String, arguments: Array): Result + started := Instant.now() + case run(command, arguments) + when Result::Ok(process) + return Result::Ok( + TimedProcess.new( + seconds: Instant.now().duration_since(started).total_seconds(), + status: process.status, + stdout: process.stdout, + stderr: process.stderr, + ) + ) + when Result::Err(error) + return Result::Err(error.operation + ": " + error.message) + end +end + +def append_measurement( + mut output: StringBuilder, + metric: String, + case_name: String, + candidate: String, + iteration: Integer, + value: String, + status: Integer, + ) + output.append( + metric + "," + case_name + "," + candidate + "," + iteration.to_s() + "," + value + "," + status.to_s() + "\n" + ) + return +end + +def append_native_phases( + mut output: StringBuilder, + case_name: String, + iteration: Integer, + stdout: String, + ) + lines := stdout.split("\n") + mut index := 0 + while index < lines.size() + line := lines[index] + if line.start_with?("gate1-phase,") + fields := line.split(",") + if fields.size() == 3 + append_measurement(output, "build-" + fields[1], case_name, "native", iteration, fields[2], 0) + end + end + index += 1 + end + return +end + +def record_size( + mut output: StringBuilder, + case_name: String, + candidate: String, + kind: String, + path: String, + ): Result + measurement := try measure_process("/usr/bin/stat", ["-f", "%z", path]) + if measurement.status != 0 + return Result::Err("stat " + path + ": " + measurement.stderr) + end + append_measurement(output, kind, case_name, candidate, 0, measurement.stdout.strip(), 0) + return Result::Ok(true) +end + +def benchmark_case( + mut output: StringBuilder, + root: String, + reference_trb: String, + native_driver: String, + qbe: String, + cc: String, + workspace_root: String, + case_name: String, + build_repetitions: Integer, + runtime_repetitions: Integer, + ): Result + config := root + "/corpus/gate1/" + case_name + "/trbconfig.jsonc" + workspace := workspace_root + "/" + case_name + native_workspace := workspace + "/native-workspace" + go_cache := workspace + "/go-cache" + go_size_cache := workspace + "/go-size-cache" + case create_directory(native_workspace) + when Result::Ok(_unit) + when Result::Err(error) + return Result::Err(error.operation + ": " + error.message) + end + native_output := workspace + "/native" + reference_output := workspace + "/reference" + reference_size_output := workspace + "/reference-size" + mut iteration := 0 + while iteration < build_repetitions + if iteration % 2 == 0 + native_build := try measure_process( + native_driver, + [reference_trb, config, qbe, cc, native_workspace, native_output], + ) + append_measurement(output, "build-total", case_name, "native", iteration, native_build.seconds.to_s(), native_build.status) + append_native_phases(output, case_name, iteration, native_build.stdout) + reference_build := try measure_process( + "/usr/bin/env", + ["GOCACHE=" + go_cache, reference_trb, "build", "--compile", "--config", config, "--outfile", reference_output], + ) + append_measurement(output, "build-total", case_name, "go", iteration, reference_build.seconds.to_s(), reference_build.status) + else + reference_build := try measure_process( + "/usr/bin/env", + ["GOCACHE=" + go_cache, reference_trb, "build", "--compile", "--config", config, "--outfile", reference_output], + ) + append_measurement(output, "build-total", case_name, "go", iteration, reference_build.seconds.to_s(), reference_build.status) + native_build := try measure_process( + native_driver, + [reference_trb, config, qbe, cc, native_workspace, native_output], + ) + append_measurement(output, "build-total", case_name, "native", iteration, native_build.seconds.to_s(), native_build.status) + append_native_phases(output, case_name, iteration, native_build.stdout) + end + reference_size_build := try measure_process( + "/usr/bin/env", + [ + "GOCACHE=" + go_size_cache, + "GOFLAGS=-ldflags=-s -w", + reference_trb, + "build", + "--compile", + "--config", + config, + "--outfile", + reference_size_output, + ], + ) + append_measurement( + output, + "build-total", + case_name, + "go-size", + iteration, + reference_size_build.seconds.to_s(), + reference_size_build.status, + ) + iteration += 1 + end + native_stripped := native_output + ".stripped" + reference_stripped := reference_output + ".stripped" + reference_size_stripped := reference_size_output + ".stripped" + native_strip := try measure_process("/usr/bin/strip", ["-x", "-o", native_stripped, native_output]) + if native_strip.status != 0 + return Result::Err("strip native: " + native_strip.stderr) + end + reference_strip := try measure_process("/usr/bin/strip", ["-x", "-o", reference_stripped, reference_output]) + if reference_strip.status != 0 + return Result::Err("strip go: " + reference_strip.stderr) + end + reference_size_strip := try measure_process( + "/usr/bin/strip", + ["-x", "-o", reference_size_stripped, reference_size_output], + ) + if reference_size_strip.status != 0 + return Result::Err("strip size-optimized go: " + reference_size_strip.stderr) + end + try record_size(output, case_name, "native", "size-raw", native_output) + try record_size(output, case_name, "go", "size-raw", reference_output) + try record_size(output, case_name, "go-size", "size-raw", reference_size_output) + try record_size(output, case_name, "native", "size-stripped", native_stripped) + try record_size(output, case_name, "go", "size-stripped", reference_stripped) + try record_size(output, case_name, "go-size", "size-stripped", reference_size_stripped) + iteration = 0 + while iteration < 3 + try measure_process(native_output, []) + try measure_process(reference_output, []) + try measure_process(reference_size_output, []) + iteration += 1 + end + iteration = 0 + while iteration < runtime_repetitions + if iteration % 2 == 0 + native_run := try measure_process(native_output, []) + append_measurement(output, "runtime", case_name, "native", iteration, native_run.seconds.to_s(), native_run.status) + reference_run := try measure_process(reference_output, []) + append_measurement(output, "runtime", case_name, "go", iteration, reference_run.seconds.to_s(), reference_run.status) + else + reference_run := try measure_process(reference_output, []) + append_measurement(output, "runtime", case_name, "go", iteration, reference_run.seconds.to_s(), reference_run.status) + native_run := try measure_process(native_output, []) + append_measurement(output, "runtime", case_name, "native", iteration, native_run.seconds.to_s(), native_run.status) + end + reference_size_run := try measure_process(reference_size_output, []) + append_measurement( + output, + "runtime", + case_name, + "go-size", + iteration, + reference_size_run.seconds.to_s(), + reference_size_run.status, + ) + iteration += 1 + end + return Result::Ok(true) +end + +def main() + arguments := argv() + if arguments.size() != 9 + puts("usage: gate1-benchmark ROOT REFERENCE_TRB NATIVE_DRIVER QBE CC WORKSPACE BUILD_REPETITIONS RUNTIME_REPETITIONS OUTPUT") + return + end + case create_directory(arguments[5]) + when Result::Ok(_unit) + when Result::Err(error) + puts(error.operation + ": " + error.message) + return + end + mut output := string_builder.new() + output.append("metric,case,candidate,iteration,value,status\n") + case_names := ["static-output", "scalar-control-flow", "integer-kernel"] + mut index := 0 + while index < case_names.size() + case benchmark_case( + output, + arguments[0], + arguments[1], + arguments[2], + arguments[3], + arguments[4], + arguments[5], + case_names[index], + arguments[6].to_i(), + arguments[7].to_i(), + ) + when Result::Ok(_value) + when Result::Err(error) + puts(error) + return + end + index += 1 + end + case write_text(arguments[8], output.to_s()) + when Result::Ok(_unit) + puts(arguments[8]) + when Result::Err(error) + puts(error.operation + ": " + error.message) + end + return +end diff --git a/tools/gate1-benchmark/trbconfig.jsonc b/tools/gate1-benchmark/trbconfig.jsonc new file mode 100644 index 00000000..744036cd --- /dev/null +++ b/tools/gate1-benchmark/trbconfig.jsonc @@ -0,0 +1,8 @@ +{ + "name": "type-rb-native-gate1-benchmark", + "mode": "go", + "sourceDir": "src", + "go": { + "module": "github.com/type-rb/type-rb-native/tools/gate1-benchmark" + } +} From d751d60466a0bf78a1368088689955fa384201bc Mon Sep 17 00:00:00 2001 From: hiroki23 <33798+hiroki23@users.noreply.github.com> Date: Fri, 28 Aug 2026 15:12:43 +0900 Subject: [PATCH 2/3] feat: record Gate 1 peak memory --- tools/gate1-benchmark/src/main.trb | 61 ++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/tools/gate1-benchmark/src/main.trb b/tools/gate1-benchmark/src/main.trb index 507149cb..a5bf2d8e 100644 --- a/tools/gate1-benchmark/src/main.trb +++ b/tools/gate1-benchmark/src/main.trb @@ -79,6 +79,36 @@ def record_size( return Result::Ok(true) end +def measure_peak_rss(command: String, arguments: Array): Result + mut time_arguments := ["-l", command] + mut index := 0 + while index < arguments.size() + time_arguments.push(arguments[index]) + index += 1 + end + measurement := try measure_process("/usr/bin/time", time_arguments) + if measurement.status != 0 + return Result::Err("time " + command + ": " + measurement.stderr) + end + lines := measurement.stderr.split("\n") + index = 0 + while index < lines.size() + line := lines[index] + if line.include?("maximum resident set size") + fields := line.strip().split(" ") + mut field_index := 0 + while field_index < fields.size() + if !fields[field_index].empty?() + return Result::Ok(fields[field_index]) + end + field_index += 1 + end + end + index += 1 + end + return Result::Err("time did not report maximum resident set size for " + command) +end + def benchmark_case( mut output: StringBuilder, root: String, @@ -156,6 +186,31 @@ def benchmark_case( ) iteration += 1 end + native_build_rss := try measure_peak_rss( + native_driver, + [reference_trb, config, qbe, cc, native_workspace, native_output], + ) + append_measurement(output, "build-peak-rss", case_name, "native", 0, native_build_rss, 0) + reference_build_rss := try measure_peak_rss( + "/usr/bin/env", + ["GOCACHE=" + go_cache, reference_trb, "build", "--compile", "--config", config, "--outfile", reference_output], + ) + append_measurement(output, "build-peak-rss", case_name, "go", 0, reference_build_rss, 0) + reference_size_build_rss := try measure_peak_rss( + "/usr/bin/env", + [ + "GOCACHE=" + go_size_cache, + "GOFLAGS=-ldflags=-s -w", + reference_trb, + "build", + "--compile", + "--config", + config, + "--outfile", + reference_size_output, + ], + ) + append_measurement(output, "build-peak-rss", case_name, "go-size", 0, reference_size_build_rss, 0) native_stripped := native_output + ".stripped" reference_stripped := reference_output + ".stripped" reference_size_stripped := reference_size_output + ".stripped" @@ -180,6 +235,12 @@ def benchmark_case( try record_size(output, case_name, "native", "size-stripped", native_stripped) try record_size(output, case_name, "go", "size-stripped", reference_stripped) try record_size(output, case_name, "go-size", "size-stripped", reference_size_stripped) + native_runtime_rss := try measure_peak_rss(native_output, []) + append_measurement(output, "runtime-peak-rss", case_name, "native", 0, native_runtime_rss, 0) + reference_runtime_rss := try measure_peak_rss(reference_output, []) + append_measurement(output, "runtime-peak-rss", case_name, "go", 0, reference_runtime_rss, 0) + reference_size_runtime_rss := try measure_peak_rss(reference_size_output, []) + append_measurement(output, "runtime-peak-rss", case_name, "go-size", 0, reference_size_runtime_rss, 0) iteration = 0 while iteration < 3 try measure_process(native_output, []) From 9d1bf4b27dc9049964a015559c30ae967f39cc83 Mon Sep 17 00:00:00 2001 From: hiroki23 <33798+hiroki23@users.noreply.github.com> Date: Fri, 28 Aug 2026 15:18:54 +0900 Subject: [PATCH 3/3] docs: record Gate 1 QBE result --- .github/workflows/gate-zero.yml | 6 +- README.md | 24 +- docs/gate-1-qbe.md | 4 + .../README.md | 162 ++++ .../2026-08-28-gate1-qbe-darwin-arm64/raw.csv | 727 ++++++++++++++++++ 5 files changed, 913 insertions(+), 10 deletions(-) create mode 100644 results/2026-08-28-gate1-qbe-darwin-arm64/README.md create mode 100644 results/2026-08-28-gate1-qbe-darwin-arm64/raw.csv diff --git a/.github/workflows/gate-zero.yml b/.github/workflows/gate-zero.yml index 0f1efd3b..84f8c575 100644 --- a/.github/workflows/gate-zero.yml +++ b/.github/workflows/gate-zero.yml @@ -44,7 +44,8 @@ jobs: make -C "$RUNNER_TEMP/qbe-1.3" - name: Verify formatting - run: "$RUNNER_TEMP/trb" fmt --check . + run: | + "$RUNNER_TEMP/trb" fmt --check . - name: Check TypeRB sources run: | @@ -59,4 +60,5 @@ jobs: TYPE_RB_NATIVE_ROOT: ${{ github.workspace }} TYPE_RB_NATIVE_REFERENCE_TRB: ${{ runner.temp }}/trb TYPE_RB_NATIVE_QBE: ${{ runner.temp }}/qbe-1.3/qbe - run: "$RUNNER_TEMP/trb" test + run: | + "$RUNNER_TEMP/trb" test diff --git a/README.md b/README.md index 88a028ef..b75a1314 100644 --- a/README.md +++ b/README.md @@ -36,14 +36,21 @@ Gate 0 implements the experimental boundary in TypeRB: strict decoding of versioned, data-only bootstrap snapshots, lowering to Native MIR, MIR verification, deterministic diagnostics, and source-origin preservation. -Gate 1 is active. Its first vertical slice decodes snapshot v2, verifies a -heap-free scalar MIR, emits QBE IL from TypeRB code, and builds a working -`darwin/arm64` executable with pinned QBE 1.3 and the system linker. The current -subset includes functions, direct calls, block parameters, branches, loops, -Boolean, portable Integer, binary64 Float, static UTF-8 output, and deterministic -arithmetic failure. It provides no production runtime, stable ABI, stable -artifact format, or compatibility guarantee. Records and tagged values are -deferred to Gate 2. +Gate 1 is complete at its experimental checkpoint. A pinned, process-based +reference producer now connects real TypeRB source to snapshot v2, verified +heap-free scalar MIR, TypeRB-authored QBE emission, and working `darwin/arm64` +executables. The differential corpus covers functions, direct calls, block +parameters, branches, loops, Boolean, portable Integer including checked power, +binary64 Float, static UTF-8 output, and deterministic arithmetic failure. + +On the recorded Apple M2 Pro run, native warm build time improved by 30.5% to +36.3%, stripped executable size improved by 96.85%, and the worst runtime result +was a 16.0% regression, within the pre-registered 25% bound. See the +[Gate 1 result](results/2026-08-28-gate1-qbe-darwin-arm64/README.md). Development +stops before Gate 2 for maintainer review. The result does not select QBE for +production or measure the final self-hosted compiler. The current path provides +no production runtime, stable ABI, stable artifact format, or compatibility +guarantee. Records and tagged values remain deferred to Gate 2. ## Intended boundary @@ -137,6 +144,7 @@ repository. - [Architecture](docs/architecture.md) - [Experiment plan](docs/experiment-plan.md) - [Gate 1 QBE vertical slice](docs/gate-1-qbe.md) +- [Gate 1 QBE Darwin arm64 result](results/2026-08-28-gate1-qbe-darwin-arm64/README.md) - [Decision 0001: Experimental native toolchain boundary](docs/decisions/0001-experimental-native-toolchain.md) - [Decision 0002: TypeRB-owned self-hosting](docs/decisions/0002-typerb-owned-self-hosting.md) - [Decision 0003: Gate 1 QBE and Darwin arm64 profile](docs/decisions/0003-gate-1-qbe-target.md) diff --git a/docs/gate-1-qbe.md b/docs/gate-1-qbe.md index 91b62f00..c410bae7 100644 --- a/docs/gate-1-qbe.md +++ b/docs/gate-1-qbe.md @@ -5,6 +5,10 @@ correct native executable cheaply enough to justify connecting it to the reference frontend. It is an experimental checkpoint, not a supported TypeRB target or a measurement of the final self-hosted compiler. +The source-connected differential corpus and provisional measurements are +complete. Gate 1 passes; see the +[recorded result](../results/2026-08-28-gate1-qbe-darwin-arm64/README.md). + ## Current pipeline ```text diff --git a/results/2026-08-28-gate1-qbe-darwin-arm64/README.md b/results/2026-08-28-gate1-qbe-darwin-arm64/README.md new file mode 100644 index 00000000..4dc14f2d --- /dev/null +++ b/results/2026-08-28-gate1-qbe-darwin-arm64/README.md @@ -0,0 +1,162 @@ +# Gate 1 QBE Darwin arm64 Results + +Gate 1 passes its pre-registered continuation criteria on this provisional, +heap-free corpus. This is evidence for continuing the experiment, not evidence +that QBE is the production backend or that the final self-hosted compiler has +the same performance. + +## Revisions and environment + +- TypeRB reference compiler: `fc4c511a4ebed28cc83fbca56af0d31fb481010c` +- measured TypeRB Native implementation: `d751d60466a0bf78a1368088689955fa384201bc` +- QBE: release 1.3, commit `c0818978acec60ebb6167fade60fb7012cbf20ca` +- QBE archive SHA-256: + `d587905d620dc5e1d2bfa7c2cc642b9b837aa89a3188c6e37b53d756cf66e320` +- target profile: `darwin-arm64-v0` / QBE `arm64_apple` +- machine: Apple M2 Pro, 32 GiB RAM +- operating system: macOS 26.6.2 (25G83), arm64 +- Go: 1.27.0 darwin/arm64 +- C toolchain: Apple clang 21.0.0, target `arm64-apple-darwin25.6.0` + +The committed [`raw.csv`](raw.csv) contains 726 measurements and no nonzero +measurement status. + +## Method + +The TypeRB-authored benchmark executable measured three successful projects: +static output, scalar calls/control flow, and a five-million-iteration checked +Integer kernel. The correctness suite separately covers range failure, +division by zero, Integer power overflow, negative Integer exponent, and an +explicitly unsupported dynamic-output source. + +For each successful project the harness recorded: + +- 10 complete application builds for the native, ordinary Go, and + size-optimized Go paths; +- native snapshot, decode/lower, emit, QBE, and link phase times; +- raw and stripped executable sizes; +- one warm peak-RSS observation for build and runtime; and +- 50 runtime observations after three unrecorded warmups. + +Iteration 0 used an empty, per-project Go build cache. Later iterations reused +that cache. The native path has no application code cache. The workspace began +absent, but operating-system filesystem and page caches were not flushed. The +native and ordinary Go build order alternated; the size-optimized Go build ran +third. Runtime order alternated between native and ordinary Go, followed by the +size-optimized Go executable. + +The ordinary baseline command was `trb build --compile`. The size baseline used +the same command with `GOFLAGS=-ldflags=-s -w`. Native application builds used +the TypeRB-authored driver, the process-based snapshot producer in the pinned +reference compiler, QBE 1.3, and `/usr/bin/cc`. + +The exact top-level commands were: + +```sh +# Run from the pinned TypeRB checkout. +GOCACHE=/tmp/type-rb-go-cache go build \ + -o /tmp/type-rb-reference-trb-fc4c511 ./cmd/trb + +# Run from the TypeRB Native worktree. +GOCACHE=/tmp/type-rb-go-cache /Users/fujita-h/trb/type-rb/trb \ + build --compile --outfile /tmp/type-rb-native-driver-d751d60 +GOCACHE=/tmp/type-rb-go-cache /Users/fujita-h/trb/type-rb/trb \ + build --compile --config tools/gate1-benchmark/trbconfig.jsonc \ + --outfile /tmp/type-rb-native-benchmark-d751d60 + +/tmp/type-rb-native-benchmark-d751d60 \ + /Users/fujita-h/trb/worktrees/type-rb-native/gate-one-differential \ + /tmp/type-rb-reference-trb-fc4c511 \ + /tmp/type-rb-native-driver-d751d60 \ + /tmp/qbe-1.3/qbe /usr/bin/cc \ + /tmp/type-rb-native-gate1-benchmark-d751d60 \ + 10 50 \ + /Users/fujita-h/trb/worktrees/type-rb-native/gate-one-differential/results/2026-08-28-gate1-qbe-darwin-arm64/raw.csv +``` + +## Primary results + +Times are medians in seconds. Warm build excludes iteration 0. Each percentage +compares native with the stronger applicable Go result in that row. + +| Project | Native warm build | Best Go warm build | Build delta | Native runtime | Best Go runtime | Runtime delta | +| --- | ---: | ---: | ---: | ---: | ---: | ---: | +| static-output | 0.112686 | 0.176782 | -36.3% | 0.0064065 | 0.0075675 | -15.3% | +| scalar-control-flow | 0.108581 | 0.169988 | -36.1% | 0.0067520 | 0.0074730 | -9.6% | +| integer-kernel | 0.116422 | 0.167608 | -30.5% | 0.0223165 | 0.0192430 | +16.0% | + +The kernel regression remains within the registered 25% non-inferiority bound +and below the 2x catastrophic limit. Process launch noise dominates the two +small runtime cases, so they are startup observations rather than throughput +claims. + +| Project | Native stripped | Best size-optimized Go | Size delta | +| --- | ---: | ---: | ---: | +| static-output | 50,032 B | 1,587,714 B | -96.85% | +| scalar-control-flow | 50,032 B | 1,587,730 B | -96.85% | +| integer-kernel | 50,032 B | 1,587,730 B | -96.85% | + +The size-optimized Go value is the smaller `-s -w` output before a subsequent +`strip -x`; on this toolchain that second operation added a small amount of +Mach-O metadata. + +## Build phases and memory + +Warm native phase medians are milliseconds: + +| Project | Snapshot | Decode/lower | Emit | QBE | Link | Total | +| --- | ---: | ---: | ---: | ---: | ---: | ---: | +| static-output | 15.489 | 0.189 | 0.039 | 6.958 | 75.293 | 112.686 | +| scalar-control-flow | 16.065 | 1.086 | 0.159 | 7.949 | 73.561 | 108.581 | +| integer-kernel | 16.143 | 0.577 | 0.100 | 7.809 | 76.057 | 116.422 | + +The unassigned difference includes process startup, data-only serialization, +file writes, and benchmark observation overhead. The system assembler/linker +is the largest recorded native phase. + +Peak RSS is one warm observation, in bytes: + +| Project | Native build | Best Go build | Native runtime | Best Go runtime | +| --- | ---: | ---: | ---: | ---: | +| static-output | 35,749,888 | 60,358,656 | 1,376,256 | 4,030,464 | +| scalar-control-flow | 35,569,664 | 59,342,848 | 1,359,872 | 3,932,160 | +| integer-kernel | 35,684,352 | 59,686,912 | 1,376,256 | 4,128,768 | + +## Toolchain and dynamic dependencies + +Required application-build components measured locally: + +| Component | Bytes | Role | +| --- | ---: | --- | +| pinned reference `trb` | 37,071,922 | temporary snapshot producer and Go baseline compiler | +| TypeRB-authored native driver | 5,250,050 | snapshot validation, MIR, QBE emission, and tool orchestration | +| QBE executable | 403,424 | native backend sidecar | +| Go 1.27 root | 283,246,592 | required only by the Go application-build baseline | + +The provisional native application-build path totals 42,725,396 bytes +(40.75 MiB) before system tools. The Go path totals 320,318,514 bytes +(305.48 MiB) before system libraries. The benchmark executable is measurement +infrastructure and is not included. The native compiler driver itself was +bootstrapped through Go for Gate 1; this is not a measurement of the final +self-hosted compiler distribution. + +Both paths use system-supplied components. Native builds require +`/usr/bin/cc`, the Apple assembler/linker, and the SDK. Generated native +executables dynamically load only `/usr/lib/libSystem.B.dylib` in this corpus. +The Go size baseline loads `libSystem.B.dylib` and `libresolv.9.dylib`. + +## Gate evaluation + +- Differential correctness: pass for all supported corpus programs, including + exact stdout, stderr, and process status. +- Unsupported input: pass; dynamic output fails explicitly at the snapshot + producer. +- Minimum primary improvement: pass. Warm end-to-end build improves by + 30.5% to 36.3%, and executable size improves by 96.85%. +- Other primary outcomes: pass. The worst runtime result is a 16.0% regression, + within the 25% bound. +- Catastrophic regression: none in the final measurements. +- TinyGo calibration: omitted. TinyGo was not installed, is not a Gate 1 + deliverable, and the QBE result already resolves the continuation decision. + +Gate 1 therefore passes. Development stops before Gate 2 for maintainer review. diff --git a/results/2026-08-28-gate1-qbe-darwin-arm64/raw.csv b/results/2026-08-28-gate1-qbe-darwin-arm64/raw.csv new file mode 100644 index 00000000..66727d09 --- /dev/null +++ b/results/2026-08-28-gate1-qbe-darwin-arm64/raw.csv @@ -0,0 +1,727 @@ +metric,case,candidate,iteration,value,status +build-total,static-output,native,0,0.8034,0 +build-snapshot,static-output,native,0,0.094766,0 +build-decode,static-output,native,0,0.000671,0 +build-emit,static-output,native,0,0.000089,0 +build-qbe,static-output,native,0,0.013249,0 +build-link,static-output,native,0,0.220307,0 +build-total,static-output,go,0,2.93194,0 +build-total,static-output,go-size,0,2.924494,0 +build-total,static-output,go,1,0.188576,0 +build-total,static-output,native,1,0.107512,0 +build-snapshot,static-output,native,1,0.015489,0 +build-decode,static-output,native,1,0.000175,0 +build-emit,static-output,native,1,0.00006,0 +build-qbe,static-output,native,1,0.007094,0 +build-link,static-output,native,1,0.075113,0 +build-total,static-output,go-size,1,0.179942,0 +build-total,static-output,native,2,0.120176,0 +build-snapshot,static-output,native,2,0.021043,0 +build-decode,static-output,native,2,0.000189,0 +build-emit,static-output,native,2,0.000038,0 +build-qbe,static-output,native,2,0.010721,0 +build-link,static-output,native,2,0.07522,0 +build-total,static-output,go,2,0.202906,0 +build-total,static-output,go-size,2,0.176782,0 +build-total,static-output,go,3,0.178318,0 +build-total,static-output,native,3,0.106017,0 +build-snapshot,static-output,native,3,0.014799,0 +build-decode,static-output,native,3,0.000171,0 +build-emit,static-output,native,3,0.000043,0 +build-qbe,static-output,native,3,0.0068,0 +build-link,static-output,native,3,0.07594,0 +build-total,static-output,go-size,3,0.173204,0 +build-total,static-output,native,4,0.113271,0 +build-snapshot,static-output,native,4,0.014415,0 +build-decode,static-output,native,4,0.000185,0 +build-emit,static-output,native,4,0.000042,0 +build-qbe,static-output,native,4,0.006591,0 +build-link,static-output,native,4,0.083615,0 +build-total,static-output,go,4,0.173821,0 +build-total,static-output,go-size,4,0.158232,0 +build-total,static-output,go,5,0.186484,0 +build-total,static-output,native,5,0.105744,0 +build-snapshot,static-output,native,5,0.015077,0 +build-decode,static-output,native,5,0.000168,0 +build-emit,static-output,native,5,0.000039,0 +build-qbe,static-output,native,5,0.006826,0 +build-link,static-output,native,5,0.075293,0 +build-total,static-output,go-size,5,0.184001,0 +build-total,static-output,native,6,0.105563,0 +build-snapshot,static-output,native,6,0.014538,0 +build-decode,static-output,native,6,0.00019,0 +build-emit,static-output,native,6,0.000038,0 +build-qbe,static-output,native,6,0.007095,0 +build-link,static-output,native,6,0.074073,0 +build-total,static-output,go,6,0.519302,0 +build-total,static-output,go-size,6,0.215903,0 +build-total,static-output,go,7,0.206526,0 +build-total,static-output,native,7,0.118391,0 +build-snapshot,static-output,native,7,0.018944,0 +build-decode,static-output,native,7,0.000229,0 +build-emit,static-output,native,7,0.000035,0 +build-qbe,static-output,native,7,0.007076,0 +build-link,static-output,native,7,0.075177,0 +build-total,static-output,go-size,7,0.175897,0 +build-total,static-output,native,8,0.120531,0 +build-snapshot,static-output,native,8,0.019759,0 +build-decode,static-output,native,8,0.000205,0 +build-emit,static-output,native,8,0.000038,0 +build-qbe,static-output,native,8,0.006958,0 +build-link,static-output,native,8,0.08063,0 +build-total,static-output,go,8,0.179697,0 +build-total,static-output,go-size,8,0.244717,0 +build-total,static-output,go,9,0.215304,0 +build-total,static-output,native,9,0.112686,0 +build-snapshot,static-output,native,9,0.016241,0 +build-decode,static-output,native,9,0.000205,0 +build-emit,static-output,native,9,0.000046,0 +build-qbe,static-output,native,9,0.006642,0 +build-link,static-output,native,9,0.080547,0 +build-total,static-output,go-size,9,0.154534,0 +build-peak-rss,static-output,native,0,35749888,0 +build-peak-rss,static-output,go,0,68616192,0 +build-peak-rss,static-output,go-size,0,60358656,0 +size-raw,static-output,native,0,50440,0 +size-raw,static-output,go,0,2429714,0 +size-raw,static-output,go-size,0,1587714,0 +size-stripped,static-output,native,0,50032,0 +size-stripped,static-output,go,0,2330800,0 +size-stripped,static-output,go-size,0,1587768,0 +runtime-peak-rss,static-output,native,0,1376256,0 +runtime-peak-rss,static-output,go,0,4112384,0 +runtime-peak-rss,static-output,go-size,0,4030464,0 +runtime,static-output,native,0,0.005472,0 +runtime,static-output,go,0,0.007228,0 +runtime,static-output,go-size,0,0.007423,0 +runtime,static-output,go,1,0.007588,0 +runtime,static-output,native,1,0.006014,0 +runtime,static-output,go-size,1,0.007318,0 +runtime,static-output,native,2,0.006327,0 +runtime,static-output,go,2,0.007433,0 +runtime,static-output,go-size,2,0.007698,0 +runtime,static-output,go,3,0.008347,0 +runtime,static-output,native,3,0.00687,0 +runtime,static-output,go-size,3,0.008083,0 +runtime,static-output,native,4,0.007061,0 +runtime,static-output,go,4,0.007916,0 +runtime,static-output,go-size,4,0.008376,0 +runtime,static-output,go,5,0.008629,0 +runtime,static-output,native,5,0.008178,0 +runtime,static-output,go-size,5,0.007736,0 +runtime,static-output,native,6,0.006069,0 +runtime,static-output,go,6,0.007697,0 +runtime,static-output,go-size,6,0.007337,0 +runtime,static-output,go,7,0.007976,0 +runtime,static-output,native,7,0.006583,0 +runtime,static-output,go-size,7,0.00803,0 +runtime,static-output,native,8,0.006415,0 +runtime,static-output,go,8,0.00718,0 +runtime,static-output,go-size,8,0.007673,0 +runtime,static-output,go,9,0.007411,0 +runtime,static-output,native,9,0.005841,0 +runtime,static-output,go-size,9,0.007416,0 +runtime,static-output,native,10,0.006398,0 +runtime,static-output,go,10,0.007565,0 +runtime,static-output,go-size,10,0.007082,0 +runtime,static-output,go,11,0.007733,0 +runtime,static-output,native,11,0.005918,0 +runtime,static-output,go-size,11,0.006497,0 +runtime,static-output,native,12,0.005627,0 +runtime,static-output,go,12,0.007119,0 +runtime,static-output,go-size,12,0.006916,0 +runtime,static-output,go,13,0.006715,0 +runtime,static-output,native,13,0.006116,0 +runtime,static-output,go-size,13,0.006612,0 +runtime,static-output,native,14,0.006063,0 +runtime,static-output,go,14,0.010319,0 +runtime,static-output,go-size,14,0.00713,0 +runtime,static-output,go,15,0.006935,0 +runtime,static-output,native,15,0.005681,0 +runtime,static-output,go-size,15,0.006854,0 +runtime,static-output,native,16,0.006416,0 +runtime,static-output,go,16,0.006797,0 +runtime,static-output,go-size,16,0.009615,0 +runtime,static-output,go,17,0.010565,0 +runtime,static-output,native,17,0.008176,0 +runtime,static-output,go-size,17,0.007246,0 +runtime,static-output,native,18,0.006229,0 +runtime,static-output,go,18,0.010492,0 +runtime,static-output,go-size,18,0.01094,0 +runtime,static-output,go,19,0.00945,0 +runtime,static-output,native,19,0.005976,0 +runtime,static-output,go-size,19,0.007363,0 +runtime,static-output,native,20,0.009863,0 +runtime,static-output,go,20,0.00744,0 +runtime,static-output,go-size,20,0.007042,0 +runtime,static-output,go,21,0.011175,0 +runtime,static-output,native,21,0.00685,0 +runtime,static-output,go-size,21,0.011228,0 +runtime,static-output,native,22,0.006,0 +runtime,static-output,go,22,0.007607,0 +runtime,static-output,go-size,22,0.011684,0 +runtime,static-output,go,23,0.008249,0 +runtime,static-output,native,23,0.008196,0 +runtime,static-output,go-size,23,0.010808,0 +runtime,static-output,native,24,0.005867,0 +runtime,static-output,go,24,0.010284,0 +runtime,static-output,go-size,24,0.007809,0 +runtime,static-output,go,25,0.011311,0 +runtime,static-output,native,25,0.006807,0 +runtime,static-output,go-size,25,0.010796,0 +runtime,static-output,native,26,0.009763,0 +runtime,static-output,go,26,0.010605,0 +runtime,static-output,go-size,26,0.00734,0 +runtime,static-output,go,27,0.007341,0 +runtime,static-output,native,27,0.008798,0 +runtime,static-output,go-size,27,0.007438,0 +runtime,static-output,native,28,0.005792,0 +runtime,static-output,go,28,0.011433,0 +runtime,static-output,go-size,28,0.008091,0 +runtime,static-output,go,29,0.011877,0 +runtime,static-output,native,29,0.006547,0 +runtime,static-output,go-size,29,0.007256,0 +runtime,static-output,native,30,0.009535,0 +runtime,static-output,go,30,0.008222,0 +runtime,static-output,go-size,30,0.006944,0 +runtime,static-output,go,31,0.008164,0 +runtime,static-output,native,31,0.006509,0 +runtime,static-output,go-size,31,0.007203,0 +runtime,static-output,native,32,0.005753,0 +runtime,static-output,go,32,0.007309,0 +runtime,static-output,go-size,32,0.006736,0 +runtime,static-output,go,33,0.011429,0 +runtime,static-output,native,33,0.006366,0 +runtime,static-output,go-size,33,0.007512,0 +runtime,static-output,native,34,0.009737,0 +runtime,static-output,go,34,0.007121,0 +runtime,static-output,go-size,34,0.012491,0 +runtime,static-output,go,35,0.00757,0 +runtime,static-output,native,35,0.006712,0 +runtime,static-output,go-size,35,0.007355,0 +runtime,static-output,native,36,0.00617,0 +runtime,static-output,go,36,0.007068,0 +runtime,static-output,go-size,36,0.007242,0 +runtime,static-output,go,37,0.006767,0 +runtime,static-output,native,37,0.005359,0 +runtime,static-output,go-size,37,0.007758,0 +runtime,static-output,native,38,0.008825,0 +runtime,static-output,go,38,0.006769,0 +runtime,static-output,go-size,38,0.010739,0 +runtime,static-output,go,39,0.009365,0 +runtime,static-output,native,39,0.009484,0 +runtime,static-output,go-size,39,0.007839,0 +runtime,static-output,native,40,0.011149,0 +runtime,static-output,go,40,0.007888,0 +runtime,static-output,go-size,40,0.007388,0 +runtime,static-output,go,41,0.010232,0 +runtime,static-output,native,41,0.006081,0 +runtime,static-output,go-size,41,0.010415,0 +runtime,static-output,native,42,0.005868,0 +runtime,static-output,go,42,0.007063,0 +runtime,static-output,go-size,42,0.011264,0 +runtime,static-output,go,43,0.009685,0 +runtime,static-output,native,43,0.009728,0 +runtime,static-output,go-size,43,0.010663,0 +runtime,static-output,native,44,0.007634,0 +runtime,static-output,go,44,0.012787,0 +runtime,static-output,go-size,44,0.011332,0 +runtime,static-output,go,45,0.007956,0 +runtime,static-output,native,45,0.008653,0 +runtime,static-output,go-size,45,0.007754,0 +runtime,static-output,native,46,0.006351,0 +runtime,static-output,go,46,0.01146,0 +runtime,static-output,go-size,46,0.007623,0 +runtime,static-output,go,47,0.011398,0 +runtime,static-output,native,47,0.006051,0 +runtime,static-output,go-size,47,0.007194,0 +runtime,static-output,native,48,0.010481,0 +runtime,static-output,go,48,0.00732,0 +runtime,static-output,go-size,48,0.012104,0 +runtime,static-output,go,49,0.007603,0 +runtime,static-output,native,49,0.006305,0 +runtime,static-output,go-size,49,0.007419,0 +build-total,scalar-control-flow,native,0,0.138999,0 +build-snapshot,scalar-control-flow,native,0,0.022017,0 +build-decode,scalar-control-flow,native,0,0.001191,0 +build-emit,scalar-control-flow,native,0,0.000177,0 +build-qbe,scalar-control-flow,native,0,0.012438,0 +build-link,scalar-control-flow,native,0,0.094201,0 +build-total,scalar-control-flow,go,0,2.526536,0 +build-total,scalar-control-flow,go-size,0,2.444575,0 +build-total,scalar-control-flow,go,1,0.199326,0 +build-total,scalar-control-flow,native,1,0.12656,0 +build-snapshot,scalar-control-flow,native,1,0.019068,0 +build-decode,scalar-control-flow,native,1,0.001116,0 +build-emit,scalar-control-flow,native,1,0.000162,0 +build-qbe,scalar-control-flow,native,1,0.007949,0 +build-link,scalar-control-flow,native,1,0.080289,0 +build-total,scalar-control-flow,go-size,1,0.195445,0 +build-total,scalar-control-flow,native,2,0.108581,0 +build-snapshot,scalar-control-flow,native,2,0.018689,0 +build-decode,scalar-control-flow,native,2,0.00109,0 +build-emit,scalar-control-flow,native,2,0.000151,0 +build-qbe,scalar-control-flow,native,2,0.007833,0 +build-link,scalar-control-flow,native,2,0.069127,0 +build-total,scalar-control-flow,go,2,0.177351,0 +build-total,scalar-control-flow,go-size,2,0.183835,0 +build-total,scalar-control-flow,go,3,0.171075,0 +build-total,scalar-control-flow,native,3,0.119252,0 +build-snapshot,scalar-control-flow,native,3,0.015487,0 +build-decode,scalar-control-flow,native,3,0.001072,0 +build-emit,scalar-control-flow,native,3,0.000159,0 +build-qbe,scalar-control-flow,native,3,0.011702,0 +build-link,scalar-control-flow,native,3,0.078778,0 +build-total,scalar-control-flow,go-size,3,0.155477,0 +build-total,scalar-control-flow,native,4,0.103145,0 +build-snapshot,scalar-control-flow,native,4,0.016208,0 +build-decode,scalar-control-flow,native,4,0.001033,0 +build-emit,scalar-control-flow,native,4,0.000152,0 +build-qbe,scalar-control-flow,native,4,0.007846,0 +build-link,scalar-control-flow,native,4,0.070067,0 +build-total,scalar-control-flow,go,4,0.184431,0 +build-total,scalar-control-flow,go-size,4,0.169014,0 +build-total,scalar-control-flow,go,5,0.204588,0 +build-total,scalar-control-flow,native,5,0.104399,0 +build-snapshot,scalar-control-flow,native,5,0.015737,0 +build-decode,scalar-control-flow,native,5,0.001032,0 +build-emit,scalar-control-flow,native,5,0.000152,0 +build-qbe,scalar-control-flow,native,5,0.008507,0 +build-link,scalar-control-flow,native,5,0.070923,0 +build-total,scalar-control-flow,go-size,5,0.157429,0 +build-total,scalar-control-flow,native,6,0.106152,0 +build-snapshot,scalar-control-flow,native,6,0.016065,0 +build-decode,scalar-control-flow,native,6,0.001032,0 +build-emit,scalar-control-flow,native,6,0.000152,0 +build-qbe,scalar-control-flow,native,6,0.009601,0 +build-link,scalar-control-flow,native,6,0.070726,0 +build-total,scalar-control-flow,go,6,0.208997,0 +build-total,scalar-control-flow,go-size,6,0.169988,0 +build-total,scalar-control-flow,go,7,0.179584,0 +build-total,scalar-control-flow,native,7,0.106702,0 +build-snapshot,scalar-control-flow,native,7,0.015447,0 +build-decode,scalar-control-flow,native,7,0.001086,0 +build-emit,scalar-control-flow,native,7,0.000169,0 +build-qbe,scalar-control-flow,native,7,0.007986,0 +build-link,scalar-control-flow,native,7,0.073561,0 +build-total,scalar-control-flow,go-size,7,0.184011,0 +build-total,scalar-control-flow,native,8,0.122422,0 +build-snapshot,scalar-control-flow,native,8,0.015355,0 +build-decode,scalar-control-flow,native,8,0.001211,0 +build-emit,scalar-control-flow,native,8,0.000163,0 +build-qbe,scalar-control-flow,native,8,0.007779,0 +build-link,scalar-control-flow,native,8,0.086648,0 +build-total,scalar-control-flow,go,8,0.204004,0 +build-total,scalar-control-flow,go-size,8,0.161552,0 +build-total,scalar-control-flow,go,9,0.190945,0 +build-total,scalar-control-flow,native,9,0.125966,0 +build-snapshot,scalar-control-flow,native,9,0.01726,0 +build-decode,scalar-control-flow,native,9,0.001225,0 +build-emit,scalar-control-flow,native,9,0.000189,0 +build-qbe,scalar-control-flow,native,9,0.007449,0 +build-link,scalar-control-flow,native,9,0.0868,0 +build-total,scalar-control-flow,go-size,9,0.192884,0 +build-peak-rss,scalar-control-flow,native,0,35569664,0 +build-peak-rss,scalar-control-flow,go,0,70336512,0 +build-peak-rss,scalar-control-flow,go-size,0,59342848,0 +size-raw,scalar-control-flow,native,0,50552,0 +size-raw,scalar-control-flow,go,0,2429794,0 +size-raw,scalar-control-flow,go-size,0,1587730,0 +size-stripped,scalar-control-flow,native,0,50032,0 +size-stripped,scalar-control-flow,go,0,2330816,0 +size-stripped,scalar-control-flow,go-size,0,1587784,0 +runtime-peak-rss,scalar-control-flow,native,0,1359872,0 +runtime-peak-rss,scalar-control-flow,go,0,4161536,0 +runtime-peak-rss,scalar-control-flow,go-size,0,3932160,0 +runtime,scalar-control-flow,native,0,0.008059,0 +runtime,scalar-control-flow,go,0,0.008951,0 +runtime,scalar-control-flow,go-size,0,0.009137,0 +runtime,scalar-control-flow,go,1,0.012246,0 +runtime,scalar-control-flow,native,1,0.007789,0 +runtime,scalar-control-flow,go-size,1,0.01165,0 +runtime,scalar-control-flow,native,2,0.007286,0 +runtime,scalar-control-flow,go,2,0.009522,0 +runtime,scalar-control-flow,go-size,2,0.011587,0 +runtime,scalar-control-flow,go,3,0.013877,0 +runtime,scalar-control-flow,native,3,0.007045,0 +runtime,scalar-control-flow,go-size,3,0.007563,0 +runtime,scalar-control-flow,native,4,0.009538,0 +runtime,scalar-control-flow,go,4,0.009137,0 +runtime,scalar-control-flow,go-size,4,0.01227,0 +runtime,scalar-control-flow,go,5,0.008201,0 +runtime,scalar-control-flow,native,5,0.010201,0 +runtime,scalar-control-flow,go-size,5,0.008931,0 +runtime,scalar-control-flow,native,6,0.009272,0 +runtime,scalar-control-flow,go,6,0.009277,0 +runtime,scalar-control-flow,go-size,6,0.008674,0 +runtime,scalar-control-flow,go,7,0.01218,0 +runtime,scalar-control-flow,native,7,0.006996,0 +runtime,scalar-control-flow,go-size,7,0.010116,0 +runtime,scalar-control-flow,native,8,0.00663,0 +runtime,scalar-control-flow,go,8,0.009383,0 +runtime,scalar-control-flow,go-size,8,0.007158,0 +runtime,scalar-control-flow,go,9,0.006863,0 +runtime,scalar-control-flow,native,9,0.009328,0 +runtime,scalar-control-flow,go-size,9,0.00708,0 +runtime,scalar-control-flow,native,10,0.005841,0 +runtime,scalar-control-flow,go,10,0.00907,0 +runtime,scalar-control-flow,go-size,10,0.006776,0 +runtime,scalar-control-flow,go,11,0.006775,0 +runtime,scalar-control-flow,native,11,0.005855,0 +runtime,scalar-control-flow,go-size,11,0.011357,0 +runtime,scalar-control-flow,native,12,0.006005,0 +runtime,scalar-control-flow,go,12,0.007031,0 +runtime,scalar-control-flow,go-size,12,0.011462,0 +runtime,scalar-control-flow,go,13,0.010354,0 +runtime,scalar-control-flow,native,13,0.008515,0 +runtime,scalar-control-flow,go-size,13,0.006773,0 +runtime,scalar-control-flow,native,14,0.005412,0 +runtime,scalar-control-flow,go,14,0.007107,0 +runtime,scalar-control-flow,go-size,14,0.012129,0 +runtime,scalar-control-flow,go,15,0.00658,0 +runtime,scalar-control-flow,native,15,0.005798,0 +runtime,scalar-control-flow,go-size,15,0.00672,0 +runtime,scalar-control-flow,native,16,0.005573,0 +runtime,scalar-control-flow,go,16,0.008097,0 +runtime,scalar-control-flow,go-size,16,0.010497,0 +runtime,scalar-control-flow,go,17,0.006754,0 +runtime,scalar-control-flow,native,17,0.008566,0 +runtime,scalar-control-flow,go-size,17,0.006394,0 +runtime,scalar-control-flow,native,18,0.005382,0 +runtime,scalar-control-flow,go,18,0.009434,0 +runtime,scalar-control-flow,go-size,18,0.006119,0 +runtime,scalar-control-flow,go,19,0.005998,0 +runtime,scalar-control-flow,native,19,0.009803,0 +runtime,scalar-control-flow,go-size,19,0.006755,0 +runtime,scalar-control-flow,native,20,0.006132,0 +runtime,scalar-control-flow,go,20,0.011312,0 +runtime,scalar-control-flow,go-size,20,0.006559,0 +runtime,scalar-control-flow,go,21,0.006757,0 +runtime,scalar-control-flow,native,21,0.009829,0 +runtime,scalar-control-flow,go-size,21,0.006415,0 +runtime,scalar-control-flow,native,22,0.006125,0 +runtime,scalar-control-flow,go,22,0.011138,0 +runtime,scalar-control-flow,go-size,22,0.010118,0 +runtime,scalar-control-flow,go,23,0.007885,0 +runtime,scalar-control-flow,native,23,0.010248,0 +runtime,scalar-control-flow,go-size,23,0.006881,0 +runtime,scalar-control-flow,native,24,0.005549,0 +runtime,scalar-control-flow,go,24,0.011193,0 +runtime,scalar-control-flow,go-size,24,0.006638,0 +runtime,scalar-control-flow,go,25,0.011428,0 +runtime,scalar-control-flow,native,25,0.006431,0 +runtime,scalar-control-flow,go-size,25,0.008309,0 +runtime,scalar-control-flow,native,26,0.010547,0 +runtime,scalar-control-flow,go,26,0.006975,0 +runtime,scalar-control-flow,go-size,26,0.011735,0 +runtime,scalar-control-flow,go,27,0.007575,0 +runtime,scalar-control-flow,native,27,0.00598,0 +runtime,scalar-control-flow,go-size,27,0.007164,0 +runtime,scalar-control-flow,native,28,0.00628,0 +runtime,scalar-control-flow,go,28,0.00713,0 +runtime,scalar-control-flow,go-size,28,0.01109,0 +runtime,scalar-control-flow,go,29,0.007632,0 +runtime,scalar-control-flow,native,29,0.008283,0 +runtime,scalar-control-flow,go-size,29,0.009822,0 +runtime,scalar-control-flow,native,30,0.006294,0 +runtime,scalar-control-flow,go,30,0.010153,0 +runtime,scalar-control-flow,go-size,30,0.007091,0 +runtime,scalar-control-flow,go,31,0.008695,0 +runtime,scalar-control-flow,native,31,0.012494,0 +runtime,scalar-control-flow,go-size,31,0.009044,0 +runtime,scalar-control-flow,native,32,0.009943,0 +runtime,scalar-control-flow,go,32,0.007636,0 +runtime,scalar-control-flow,go-size,32,0.011277,0 +runtime,scalar-control-flow,go,33,0.007074,0 +runtime,scalar-control-flow,native,33,0.006478,0 +runtime,scalar-control-flow,go-size,33,0.007284,0 +runtime,scalar-control-flow,native,34,0.006217,0 +runtime,scalar-control-flow,go,34,0.007351,0 +runtime,scalar-control-flow,go-size,34,0.007088,0 +runtime,scalar-control-flow,go,35,0.007089,0 +runtime,scalar-control-flow,native,35,0.006981,0 +runtime,scalar-control-flow,go-size,35,0.006854,0 +runtime,scalar-control-flow,native,36,0.006874,0 +runtime,scalar-control-flow,go,36,0.006963,0 +runtime,scalar-control-flow,go-size,36,0.006891,0 +runtime,scalar-control-flow,go,37,0.006566,0 +runtime,scalar-control-flow,native,37,0.005847,0 +runtime,scalar-control-flow,go-size,37,0.010612,0 +runtime,scalar-control-flow,native,38,0.006322,0 +runtime,scalar-control-flow,go,38,0.007316,0 +runtime,scalar-control-flow,go-size,38,0.006555,0 +runtime,scalar-control-flow,go,39,0.007471,0 +runtime,scalar-control-flow,native,39,0.007932,0 +runtime,scalar-control-flow,go-size,39,0.006535,0 +runtime,scalar-control-flow,native,40,0.006138,0 +runtime,scalar-control-flow,go,40,0.006791,0 +runtime,scalar-control-flow,go-size,40,0.006707,0 +runtime,scalar-control-flow,go,41,0.007019,0 +runtime,scalar-control-flow,native,41,0.005323,0 +runtime,scalar-control-flow,go-size,41,0.00883,0 +runtime,scalar-control-flow,native,42,0.005534,0 +runtime,scalar-control-flow,go,42,0.006516,0 +runtime,scalar-control-flow,go-size,42,0.006886,0 +runtime,scalar-control-flow,go,43,0.006513,0 +runtime,scalar-control-flow,native,43,0.005059,0 +runtime,scalar-control-flow,go-size,43,0.006575,0 +runtime,scalar-control-flow,native,44,0.005652,0 +runtime,scalar-control-flow,go,44,0.006269,0 +runtime,scalar-control-flow,go-size,44,0.007383,0 +runtime,scalar-control-flow,go,45,0.007273,0 +runtime,scalar-control-flow,native,45,0.020874,0 +runtime,scalar-control-flow,go-size,45,0.01783,0 +runtime,scalar-control-flow,native,46,0.013621,0 +runtime,scalar-control-flow,go,46,0.015589,0 +runtime,scalar-control-flow,go-size,46,0.012425,0 +runtime,scalar-control-flow,go,47,0.010753,0 +runtime,scalar-control-flow,native,47,0.007232,0 +runtime,scalar-control-flow,go-size,47,0.011783,0 +runtime,scalar-control-flow,native,48,0.007142,0 +runtime,scalar-control-flow,go,48,0.007427,0 +runtime,scalar-control-flow,go-size,48,0.007589,0 +runtime,scalar-control-flow,go,49,0.006849,0 +runtime,scalar-control-flow,native,49,0.005729,0 +runtime,scalar-control-flow,go-size,49,0.007053,0 +build-total,integer-kernel,native,0,0.120683,0 +build-snapshot,integer-kernel,native,0,0.018597,0 +build-decode,integer-kernel,native,0,0.000564,0 +build-emit,integer-kernel,native,0,0.000093,0 +build-qbe,integer-kernel,native,0,0.010813,0 +build-link,integer-kernel,native,0,0.082955,0 +build-total,integer-kernel,go,0,2.543558,0 +build-total,integer-kernel,go-size,0,2.471917,0 +build-total,integer-kernel,go,1,0.198357,0 +build-total,integer-kernel,native,1,0.121813,0 +build-snapshot,integer-kernel,native,1,0.019462,0 +build-decode,integer-kernel,native,1,0.000632,0 +build-emit,integer-kernel,native,1,0.000107,0 +build-qbe,integer-kernel,native,1,0.007762,0 +build-link,integer-kernel,native,1,0.079424,0 +build-total,integer-kernel,go-size,1,0.167608,0 +build-total,integer-kernel,native,2,0.121088,0 +build-snapshot,integer-kernel,native,2,0.020127,0 +build-decode,integer-kernel,native,2,0.000545,0 +build-emit,integer-kernel,native,2,0.000097,0 +build-qbe,integer-kernel,native,2,0.009097,0 +build-link,integer-kernel,native,2,0.078813,0 +build-total,integer-kernel,go,2,0.278624,0 +build-total,integer-kernel,go-size,2,0.162406,0 +build-total,integer-kernel,go,3,0.179647,0 +build-total,integer-kernel,native,3,0.120729,0 +build-snapshot,integer-kernel,native,3,0.019293,0 +build-decode,integer-kernel,native,3,0.000587,0 +build-emit,integer-kernel,native,3,0.00009,0 +build-qbe,integer-kernel,native,3,0.011687,0 +build-link,integer-kernel,native,3,0.076585,0 +build-total,integer-kernel,go-size,3,0.156558,0 +build-total,integer-kernel,native,4,0.106029,0 +build-snapshot,integer-kernel,native,4,0.016143,0 +build-decode,integer-kernel,native,4,0.000577,0 +build-emit,integer-kernel,native,4,0.000115,0 +build-qbe,integer-kernel,native,4,0.007506,0 +build-link,integer-kernel,native,4,0.073216,0 +build-total,integer-kernel,go,4,0.191927,0 +build-total,integer-kernel,go-size,4,0.16824,0 +build-total,integer-kernel,go,5,0.201671,0 +build-total,integer-kernel,native,5,0.100643,0 +build-snapshot,integer-kernel,native,5,0.014302,0 +build-decode,integer-kernel,native,5,0.000533,0 +build-emit,integer-kernel,native,5,0.00009,0 +build-qbe,integer-kernel,native,5,0.007199,0 +build-link,integer-kernel,native,5,0.070405,0 +build-total,integer-kernel,go-size,5,0.153944,0 +build-total,integer-kernel,native,6,0.105961,0 +build-snapshot,integer-kernel,native,6,0.014716,0 +build-decode,integer-kernel,native,6,0.000529,0 +build-emit,integer-kernel,native,6,0.000111,0 +build-qbe,integer-kernel,native,6,0.007809,0 +build-link,integer-kernel,native,6,0.073953,0 +build-total,integer-kernel,go,6,0.199411,0 +build-total,integer-kernel,go-size,6,0.17007,0 +build-total,integer-kernel,go,7,0.173883,0 +build-total,integer-kernel,native,7,0.116422,0 +build-snapshot,integer-kernel,native,7,0.015564,0 +build-decode,integer-kernel,native,7,0.00053,0 +build-emit,integer-kernel,native,7,0.000092,0 +build-qbe,integer-kernel,native,7,0.012067,0 +build-link,integer-kernel,native,7,0.075237,0 +build-total,integer-kernel,go-size,7,0.183954,0 +build-total,integer-kernel,native,8,0.119528,0 +build-snapshot,integer-kernel,native,8,0.019314,0 +build-decode,integer-kernel,native,8,0.000589,0 +build-emit,integer-kernel,native,8,0.0001,0 +build-qbe,integer-kernel,native,8,0.010732,0 +build-link,integer-kernel,native,8,0.076057,0 +build-total,integer-kernel,go,8,0.200006,0 +build-total,integer-kernel,go-size,8,0.160816,0 +build-total,integer-kernel,go,9,0.181278,0 +build-total,integer-kernel,native,9,0.114093,0 +build-snapshot,integer-kernel,native,9,0.015659,0 +build-decode,integer-kernel,native,9,0.000663,0 +build-emit,integer-kernel,native,9,0.000103,0 +build-qbe,integer-kernel,native,9,0.00741,0 +build-link,integer-kernel,native,9,0.081721,0 +build-total,integer-kernel,go-size,9,0.176752,0 +build-peak-rss,integer-kernel,native,0,35684352,0 +build-peak-rss,integer-kernel,go,0,69320704,0 +build-peak-rss,integer-kernel,go-size,0,59686912,0 +size-raw,integer-kernel,native,0,50504,0 +size-raw,integer-kernel,go,0,2429746,0 +size-raw,integer-kernel,go-size,0,1587730,0 +size-stripped,integer-kernel,native,0,50032,0 +size-stripped,integer-kernel,go,0,2330816,0 +size-stripped,integer-kernel,go-size,0,1587784,0 +runtime-peak-rss,integer-kernel,native,0,1376256,0 +runtime-peak-rss,integer-kernel,go,0,4128768,0 +runtime-peak-rss,integer-kernel,go-size,0,4177920,0 +runtime,integer-kernel,native,0,0.018426,0 +runtime,integer-kernel,go,0,0.01508,0 +runtime,integer-kernel,go-size,0,0.015177,0 +runtime,integer-kernel,go,1,0.015349,0 +runtime,integer-kernel,native,1,0.018766,0 +runtime,integer-kernel,go-size,1,0.020115,0 +runtime,integer-kernel,native,2,0.022654,0 +runtime,integer-kernel,go,2,0.019879,0 +runtime,integer-kernel,go-size,2,0.020164,0 +runtime,integer-kernel,go,3,0.018498,0 +runtime,integer-kernel,native,3,0.022148,0 +runtime,integer-kernel,go-size,3,0.015864,0 +runtime,integer-kernel,native,4,0.021642,0 +runtime,integer-kernel,go,4,0.017346,0 +runtime,integer-kernel,go-size,4,0.014944,0 +runtime,integer-kernel,go,5,0.016093,0 +runtime,integer-kernel,native,5,0.022948,0 +runtime,integer-kernel,go-size,5,0.020511,0 +runtime,integer-kernel,native,6,0.021965,0 +runtime,integer-kernel,go,6,0.015071,0 +runtime,integer-kernel,go-size,6,0.020137,0 +runtime,integer-kernel,go,7,0.01925,0 +runtime,integer-kernel,native,7,0.022632,0 +runtime,integer-kernel,go-size,7,0.018459,0 +runtime,integer-kernel,native,8,0.018898,0 +runtime,integer-kernel,go,8,0.015429,0 +runtime,integer-kernel,go-size,8,0.020188,0 +runtime,integer-kernel,go,9,0.016054,0 +runtime,integer-kernel,native,9,0.019219,0 +runtime,integer-kernel,go-size,9,0.019262,0 +runtime,integer-kernel,native,10,0.022689,0 +runtime,integer-kernel,go,10,0.019133,0 +runtime,integer-kernel,go-size,10,0.015037,0 +runtime,integer-kernel,go,11,0.018608,0 +runtime,integer-kernel,native,11,0.019353,0 +runtime,integer-kernel,go-size,11,0.01962,0 +runtime,integer-kernel,native,12,0.02297,0 +runtime,integer-kernel,go,12,0.018995,0 +runtime,integer-kernel,go-size,12,0.014912,0 +runtime,integer-kernel,go,13,0.018118,0 +runtime,integer-kernel,native,13,0.022137,0 +runtime,integer-kernel,go-size,13,0.019042,0 +runtime,integer-kernel,native,14,0.022834,0 +runtime,integer-kernel,go,14,0.0162,0 +runtime,integer-kernel,go-size,14,0.01975,0 +runtime,integer-kernel,go,15,0.019422,0 +runtime,integer-kernel,native,15,0.024573,0 +runtime,integer-kernel,go-size,15,0.019315,0 +runtime,integer-kernel,native,16,0.021915,0 +runtime,integer-kernel,go,16,0.021524,0 +runtime,integer-kernel,go-size,16,0.015938,0 +runtime,integer-kernel,go,17,0.019616,0 +runtime,integer-kernel,native,17,0.020061,0 +runtime,integer-kernel,go-size,17,0.016842,0 +runtime,integer-kernel,native,18,0.0229,0 +runtime,integer-kernel,go,18,0.020606,0 +runtime,integer-kernel,go-size,18,0.019715,0 +runtime,integer-kernel,go,19,0.020629,0 +runtime,integer-kernel,native,19,0.023494,0 +runtime,integer-kernel,go-size,19,0.019628,0 +runtime,integer-kernel,native,20,0.024136,0 +runtime,integer-kernel,go,20,0.0197,0 +runtime,integer-kernel,go-size,20,0.020358,0 +runtime,integer-kernel,go,21,0.024778,0 +runtime,integer-kernel,native,21,0.022876,0 +runtime,integer-kernel,go-size,21,0.020009,0 +runtime,integer-kernel,native,22,0.022317,0 +runtime,integer-kernel,go,22,0.020829,0 +runtime,integer-kernel,go-size,22,0.020248,0 +runtime,integer-kernel,go,23,0.01997,0 +runtime,integer-kernel,native,23,0.023649,0 +runtime,integer-kernel,go-size,23,0.018882,0 +runtime,integer-kernel,native,24,0.022507,0 +runtime,integer-kernel,go,24,0.01937,0 +runtime,integer-kernel,go-size,24,0.020954,0 +runtime,integer-kernel,go,25,0.019013,0 +runtime,integer-kernel,native,25,0.022316,0 +runtime,integer-kernel,go-size,25,0.019025,0 +runtime,integer-kernel,native,26,0.022319,0 +runtime,integer-kernel,go,26,0.02465,0 +runtime,integer-kernel,go-size,26,0.022855,0 +runtime,integer-kernel,go,27,0.018837,0 +runtime,integer-kernel,native,27,0.02187,0 +runtime,integer-kernel,go-size,27,0.023254,0 +runtime,integer-kernel,native,28,0.02537,0 +runtime,integer-kernel,go,28,0.020962,0 +runtime,integer-kernel,go-size,28,0.019853,0 +runtime,integer-kernel,go,29,0.019603,0 +runtime,integer-kernel,native,29,0.021777,0 +runtime,integer-kernel,go-size,29,0.019107,0 +runtime,integer-kernel,native,30,0.025886,0 +runtime,integer-kernel,go,30,0.023139,0 +runtime,integer-kernel,go-size,30,0.01884,0 +runtime,integer-kernel,go,31,0.018475,0 +runtime,integer-kernel,native,31,0.022115,0 +runtime,integer-kernel,go-size,31,0.01864,0 +runtime,integer-kernel,native,32,0.021703,0 +runtime,integer-kernel,go,32,0.019089,0 +runtime,integer-kernel,go-size,32,0.019014,0 +runtime,integer-kernel,go,33,0.018813,0 +runtime,integer-kernel,native,33,0.021705,0 +runtime,integer-kernel,go-size,33,0.018513,0 +runtime,integer-kernel,native,34,0.022802,0 +runtime,integer-kernel,go,34,0.019733,0 +runtime,integer-kernel,go-size,34,0.023324,0 +runtime,integer-kernel,go,35,0.020457,0 +runtime,integer-kernel,native,35,0.027923,0 +runtime,integer-kernel,go-size,35,0.019138,0 +runtime,integer-kernel,native,36,0.021976,0 +runtime,integer-kernel,go,36,0.021746,0 +runtime,integer-kernel,go-size,36,0.023714,0 +runtime,integer-kernel,go,37,0.021565,0 +runtime,integer-kernel,native,37,0.022639,0 +runtime,integer-kernel,go-size,37,0.019513,0 +runtime,integer-kernel,native,38,0.023814,0 +runtime,integer-kernel,go,38,0.021313,0 +runtime,integer-kernel,go-size,38,0.019314,0 +runtime,integer-kernel,go,39,0.02097,0 +runtime,integer-kernel,native,39,0.021806,0 +runtime,integer-kernel,go-size,39,0.018947,0 +runtime,integer-kernel,native,40,0.022169,0 +runtime,integer-kernel,go,40,0.018419,0 +runtime,integer-kernel,go-size,40,0.019334,0 +runtime,integer-kernel,go,41,0.018911,0 +runtime,integer-kernel,native,41,0.02391,0 +runtime,integer-kernel,go-size,41,0.018618,0 +runtime,integer-kernel,native,42,0.023535,0 +runtime,integer-kernel,go,42,0.019592,0 +runtime,integer-kernel,go-size,42,0.021356,0 +runtime,integer-kernel,go,43,0.019355,0 +runtime,integer-kernel,native,43,0.021572,0 +runtime,integer-kernel,go-size,43,0.019224,0 +runtime,integer-kernel,native,44,0.027986,0 +runtime,integer-kernel,go,44,0.020936,0 +runtime,integer-kernel,go-size,44,0.019099,0 +runtime,integer-kernel,go,45,0.024302,0 +runtime,integer-kernel,native,45,0.022401,0 +runtime,integer-kernel,go-size,45,0.018977,0 +runtime,integer-kernel,native,46,0.021817,0 +runtime,integer-kernel,go,46,0.019,0 +runtime,integer-kernel,go-size,46,0.019179,0 +runtime,integer-kernel,go,47,0.018972,0 +runtime,integer-kernel,native,47,0.021915,0 +runtime,integer-kernel,go-size,47,0.018987,0 +runtime,integer-kernel,native,48,0.021927,0 +runtime,integer-kernel,go,48,0.01878,0 +runtime,integer-kernel,go-size,48,0.019124,0 +runtime,integer-kernel,go,49,0.019034,0 +runtime,integer-kernel,native,49,0.022229,0 +runtime,integer-kernel,go-size,49,0.019817,0