mirror of
https://github.com/hanzoai/wasm2go.git
synced 2026-10-30 15:06:48 +00:00
* gcasm: fix cross-chunk symbol gaps in the direct-call path Follow-ups to the direct cross-chunk asm calls change (#61): - The direct-asm resolvers (CalleeSymbol / MemHelperSymbol) trimmed calleeSig's leading "·" and let asmgen's goAsmSymbol re-derive the CALL operand. A spelled remote symbol ("github·com∕...∕p2·Fn0") has no ASCII "." for goAsmSymbol to split on, so it was re-wrapped as a current-package reference ("CALL ·github·com∕...(SB)") that can never link — any direct-asm-retained function making a resolved cross-chunk call produced an undefined symbol at consumer link time. The resolver contract now carries the exact plan 9 operand (without the "(SB)" suffix) and asmgen emits it verbatim. - plan9AsmPathSafe accepted digit-leading import paths ("4d63.com/...", "0xacab.org/..."), but the plan 9 asm lexer accepts digits only after the first identifier rune, so the spelled CALL would fail to assemble. The predicate now requires a letter or "_" at position 0. - That predicate existed as two byte-for-byte copies (codegen's isPlan9AsmSafe, gcasm's plan9AsmPathSafe) under a comment claiming an import cycle prevents sharing; no such cycle exists. Both packages now consult one exported asmgen.Plan9AsmPathSafe, so the linkname alias shape and the direct-CALL / gcasmABI0Keep anchor gates can never disagree. - buildPkg now verifies every captured fn leaves the emission loop either with a TEXT body or registered as a pure-Go fallback. A future degrade path that forgets fallbackNames would otherwise surface only as a link error in the consumer build, with no Build-time diagnostic; it is a Build error naming the fn now. The new cg_crosscall_directasm fixture keeps every op native (no rotl/rotr, which lower to helper CALLs the direct-asm emitter's ForbidCalls refuses) so the retained functions actually emit via asmgen; its regression test fails against the pre-fix resolvers with the mangled current-package spelling in the emitted bundle. Co-Authored-By: Claude Fable 5 <[email protected]> * asmgen: restructure the first-rune check as a switch to satisfy staticcheck golangci-lint's staticcheck (QF1001) flagged the negated compound condition in Plan9AsmPathSafe; the positive-switch form matches the per-byte loop below it. No behavior change. Co-Authored-By: Claude Fable 5 <[email protected]> --------- Co-authored-by: Claude Fable 5 <[email protected]>
61 lines
2.1 KiB
Go
61 lines
2.1 KiB
Go
package asmgen
|
||
|
||
import "testing"
|
||
|
||
// TestPlan9AsmPathSafe pins the shared safety predicate that decides
|
||
// whether an import path can be embedded verbatim into a plan 9 asm
|
||
// symbol operand (mapping "/" → "∕" and "." → "·") or whether the
|
||
// generators must fall back to per-chunk Go-body wrappers because
|
||
// some byte of the path has no plan 9 identifier substitute.
|
||
func TestPlan9AsmPathSafe(t *testing.T) {
|
||
cases := []struct {
|
||
path string
|
||
want bool
|
||
}{
|
||
// Single-name stdlib-style paths: safe.
|
||
{"runtime", true},
|
||
{"syscall", true},
|
||
// Nested paths with letters / digits / underscores: safe.
|
||
{"internal/runtime/atomic", true},
|
||
{"a/b/c", true},
|
||
{"foo_bar/baz", true},
|
||
{"_x/y", true},
|
||
{"gentest/pkg", true},
|
||
// Domain-style paths: dots are remapped to U+00B7, still safe.
|
||
{"github.com/foo/bar", true},
|
||
{"github.com/goccy/wasm2go/internal", true},
|
||
{"x.y.z/pkg", true},
|
||
{"example.org/x_y/v2", true},
|
||
// Digits are identifier runes only AFTER the first rune: a
|
||
// digit-leading host would put a digit at position 0 of the
|
||
// spelled operand, which the asm lexer scans as a number, not
|
||
// an identifier. Real Go module hosts like this exist.
|
||
{"4d63.com/mymod/pkg", false},
|
||
{"0xacab.org/x", false},
|
||
// ...while a digit anywhere later in the path is fine.
|
||
{"h4d63.com/mymod/pkg", true},
|
||
{"example.org/0user/pkg", true},
|
||
// Hyphen has no identifier-rune substitute — unsafe. This is
|
||
// what makes any module path containing a "-" fall back to
|
||
// the per-chunk Go-body wrappers.
|
||
{"github.com/example/foo-bar", false},
|
||
{"github.com/goccy/some-hyphen/pkg", false},
|
||
{"a-b", false},
|
||
// Other punctuation that can legally appear in module paths
|
||
// but breaks plan 9 asm identifier scanning.
|
||
{"a+b", false},
|
||
{"host.tld/a+b", false},
|
||
{"a~b", false},
|
||
{"foo bar", false},
|
||
{"host.tld/sp ace", false},
|
||
// Empty path: treated as unsafe so the caller skips the
|
||
// optimization rather than emitting "·" alone.
|
||
{"", false},
|
||
}
|
||
for _, c := range cases {
|
||
if got := Plan9AsmPathSafe(c.path); got != c.want {
|
||
t.Errorf("Plan9AsmPathSafe(%q) = %v, want %v", c.path, got, c.want)
|
||
}
|
||
}
|
||
}
|