From f93504bfd6358d2275b9b9d1e6199259cfe56061 Mon Sep 17 00:00:00 2001 From: Guoqi Chen Date: Thu, 23 Apr 2026 17:27:16 +0800 Subject: [PATCH 1/8] cmd/internal/obj/loong64: add FRINT{F,D} instructions Go asm syntax: FRINTF FJ, FD FRINTD FJ, FD Equivalent platform assembler syntax: frint.s fd, fd frint.d fd, fd Change-Id: If26c1c26764ac1be6fc7e706a65e1dbbda094805 Reviewed-on: https://go-review.googlesource.com/c/go/+/771020 Reviewed-by: Meidan Li Reviewed-by: Junyang Shao Reviewed-by: Dmitri Shuralyov LUCI-TryBot-Result: golang-scoped@luci-project-accounts.iam.gserviceaccount.com --- src/cmd/asm/internal/asm/testdata/loong64enc1.s | 4 ++++ src/cmd/internal/obj/loong64/anames.go | 2 ++ src/cmd/internal/obj/loong64/asm.go | 2 ++ src/cmd/internal/obj/loong64/inst.go | 4 ++++ src/cmd/internal/obj/loong64/instOp.go | 2 ++ 5 files changed, 14 insertions(+) diff --git a/src/cmd/asm/internal/asm/testdata/loong64enc1.s b/src/cmd/asm/internal/asm/testdata/loong64enc1.s index 98d8ba7a674b9b..955ba630714681 100644 --- a/src/cmd/asm/internal/asm/testdata/loong64enc1.s +++ b/src/cmd/asm/internal/asm/testdata/loong64enc1.s @@ -395,6 +395,10 @@ lable2: FTINTVF F0, F1 // 01241b01 FTINTVD F0, F1 // 01281b01 + // FRINT{F,D} instructions + FRINTF F0, F1 // 01441e01 + FRINTD F0, F1 // 01481e01 + FMAXAF F4, F5, F6 // a6900c01 FMAXAF F4, F5 // a5900c01 FMAXAD F4, F5, F6 // a6100d01 diff --git a/src/cmd/internal/obj/loong64/anames.go b/src/cmd/internal/obj/loong64/anames.go index 71623ba5fbe7b0..d99c2562676404 100644 --- a/src/cmd/internal/obj/loong64/anames.go +++ b/src/cmd/internal/obj/loong64/anames.go @@ -269,6 +269,8 @@ var Anames = []string{ "FTINTRNEWD", "FTINTRNEVF", "FTINTRNEVD", + "FRINTF", + "FRINTD", "FSEL", "VMOVQ", "XVMOVQ", diff --git a/src/cmd/internal/obj/loong64/asm.go b/src/cmd/internal/obj/loong64/asm.go index 1616d3be506f21..c3ec81cc92d0f5 100644 --- a/src/cmd/internal/obj/loong64/asm.go +++ b/src/cmd/internal/obj/loong64/asm.go @@ -1332,6 +1332,8 @@ func buildop(ctxt *obj.Link) { opset(AFTINTWD, r0) opset(AFTINTVF, r0) opset(AFTINTVD, r0) + opset(AFRINTF, r0) + opset(AFRINTD, r0) opset(ANEGF, r0) opset(ANEGD, r0) opset(AABSD, r0) diff --git a/src/cmd/internal/obj/loong64/inst.go b/src/cmd/internal/obj/loong64/inst.go index 37a3df7cfcc9a1..f59406eeef4dfa 100644 --- a/src/cmd/internal/obj/loong64/inst.go +++ b/src/cmd/internal/obj/loong64/inst.go @@ -355,6 +355,10 @@ const ( AFTINTRNEVF AFTINTRNEVD + // 3.2.3.4 + AFRINTF + AFRINTD + // 3.2.4.2 AFSEL diff --git a/src/cmd/internal/obj/loong64/instOp.go b/src/cmd/internal/obj/loong64/instOp.go index c99c79a2073f23..8d9bb7bbceee0c 100644 --- a/src/cmd/internal/obj/loong64/instOp.go +++ b/src/cmd/internal/obj/loong64/instOp.go @@ -588,6 +588,8 @@ var oprr = map[obj.As]uint32{ AFTINTVF: 0x46c9 << 10, // ftint.l.s AMOVDV: 0x46ca << 10, // ftint.l.d AFTINTVD: 0x46ca << 10, // ftint.l.d + AFRINTF: 0x4791 << 10, // frint.s + AFRINTD: 0x4792 << 10, // frint.d AMOVDF: 0x4646 << 10, // fcvt.s.d AMOVFD: 0x4649 << 10, // fcvt.d.s AABSF: 0x4501 << 10, // fabs.s From 8329d313073470f7ce5d97ce223da8849eb06f11 Mon Sep 17 00:00:00 2001 From: Guoqi Chen Date: Tue, 19 May 2026 20:33:39 +0800 Subject: [PATCH 2/8] runtime/loong64: use ABIInternal convention in cgocallbackg This change follows from CL 765581 and CL 768780. As expected, the program panics when an unpinned pointed is passed from Go to C. The stack trace showing an autogenerated frame by the linker. # cat -n main.c 1 #include 2 #include "parse.h" 3 4 int main(void) { 5 GoMap m = GoFoo(); 6 (void)m; 7 return 0; 8 } # cat -n callbackErr.go 1 package main 2 3 import ( 4 "C" 5 ) 6 7 //export GoFoo 8 func GoFoo() map[int]int { 9 return map[int]int{0: 1,} 10 } 11 12 func main() { 13 } # go build -buildmode=c-shared -o callbackErr.so callbackErr.go # gcc -o main main.c callbackErr.so -Wl,-rpath,'$ORIGIN' # ./main [...] goroutine 17 [running, locked to thread]: panic({0x7ffff3811460?, 0x3bbf919e000?}) /usr/lib/go-1.26/src/runtime/panic.go:879 +0x160 runtime.cgoCheckArg(0x7ffff38126e0, 0x3bbf9192000, 0x0?, 0x0, 0x1) /usr/lib/go-1.26/src/runtime/cgocall.go:659 +0x4c4 runtime.cgoCheckResult({0x7ffff38126e0, 0x3bbf9192000}) /usr/lib/go-1.26/src/runtime/cgocall.go:829 +0x50 _cgoexp_f011903c6073_GoFoo(0x7ffffb8059e8) /home/chenguoqi/temp/callbackErr.go:8 +0x80 runtime.cgocallbackg1(0x7ffff376e570, 0x7ffffb8059e8, 0x0) /usr/lib/go-1.26/src/runtime/cgocall.go:466 +0x29c runtime.cgocallbackg(0x7ffff376e570, 0x7ffffb8059e8, 0x0) /usr/lib/go-1.26/src/runtime/cgocall.go:362 +0x108 runtime.cgocallbackg(0x7ffff376e570, 0x7ffffb8059e8, 0x0) :1 +0x1c runtime.cgocallback(0x0, 0x0, 0x0) /usr/lib/go-1.26/src/runtime/asm_loong64.s:662 +0x9c runtime.goexit({}) /usr/lib/go-1.26/src/runtime/asm_loong64.s:752 +0x4 Aborted ./main Load the cgocallbackg arguments into the registers expected by ABIInternal. [...] goroutine 17 [running, locked to thread]: panic({0x7ffff0356d78?, 0x5eae29a9e000?}) /home/chenguoqi/golang/go-upstream/src/runtime/panic.go:878 +0x160 runtime.cgoCheckArg(0x7ffff0351598, 0x5eae29a92000, 0x0?, 0x0, 0x1) /home/chenguoqi/golang/go-upstream/src/runtime/cgocall.go:667 +0x4a4 runtime.cgoCheckResult({0x7ffff0351598, 0x5eae29a92000}) /home/chenguoqi/golang/go-upstream/src/runtime/cgocall.go:837 +0x50 _cgoexp_f011903c6073_GoFoo(0x7ffffb817928) /home/chenguoqi/temp/callbackErr.go:8 +0x80 runtime.cgocallbackg1(0x7ffff02ae500, 0x7ffffb817928, 0x0) /home/chenguoqi/golang/go-upstream/src/runtime/cgocall.go:474 +0x2b0 runtime.cgocallbackg(0x7ffff02ae500, 0x7ffffb817928, 0x0) /home/chenguoqi/golang/go-upstream/src/runtime/cgocall.go:362 +0x104 runtime.cgocallback(0x0, 0x0, 0x0) /home/chenguoqi/golang/go-upstream/src/runtime/asm_loong64.s:667 +0x94 runtime.goexit({}) /home/chenguoqi/golang/go-upstream/src/runtime/asm_loong64.s:747 +0x4 Aborted ./main Change-Id: I8d5693fa582f8692b8f9cb022b82917943eaf30e Reviewed-on: https://go-review.googlesource.com/c/go/+/779740 Reviewed-by: Dmitri Shuralyov Reviewed-by: Meidan Li Reviewed-by: Junyang Shao LUCI-TryBot-Result: golang-scoped@luci-project-accounts.iam.gserviceaccount.com --- src/runtime/asm_loong64.s | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/src/runtime/asm_loong64.s b/src/runtime/asm_loong64.s index b810b5d604a04f..a41433c446ec57 100644 --- a/src/runtime/asm_loong64.s +++ b/src/runtime/asm_loong64.s @@ -656,20 +656,19 @@ havem: MOVV m_curg(R12), g JAL runtime·save_g(SB) MOVV (g_sched+gobuf_sp)(g), R13 // prepare stack as R13 - MOVV (g_sched+gobuf_pc)(g), R4 - MOVV R4, -(24+8)(R13) // "saved LR"; must match frame size - MOVV fn+0(FP), R5 - MOVV frame+8(FP), R6 - MOVV ctxt+16(FP), R7 - MOVV $-(24+8)(R13), R3 - MOVV R5, 8(R3) - MOVV R6, 16(R3) - MOVV R7, 24(R3) - JAL runtime·cgocallbackg(SB) + MOVV (g_sched+gobuf_pc)(g), R7 + MOVV R7, -(24+8)(R13) // "saved LR"; must match frame size + + MOVV fn+0(FP), R4 + MOVV frame+8(FP), R5 + MOVV ctxt+16(FP), R6 + SUBV $(24+8), R13 // Allocate the same frame size on the g stack + MOVV R13, R3 // switch stack + JAL runtime·cgocallbackg(SB) // Restore g->sched (== m->curg->sched) from saved values. - MOVV 0(R3), R4 - MOVV R4, (g_sched+gobuf_pc)(g) + MOVV 0(R3), R7 + MOVV R7, (g_sched+gobuf_pc)(g) MOVV $(24+8)(R3), R13 // must match frame size MOVV R13, (g_sched+gobuf_sp)(g) From b12ed667d9b68802d3c5d3b969bed01ab4131b1e Mon Sep 17 00:00:00 2001 From: Filippo Valsorda Date: Tue, 19 May 2026 20:37:41 +0200 Subject: [PATCH 3/8] crypto/ecdsa: test hash size restrictions Change-Id: I44a74a75d89abbf8f59fe6bfc21471e56a6a6964 Reviewed-on: https://go-review.googlesource.com/c/go/+/780000 LUCI-TryBot-Result: golang-scoped@luci-project-accounts.iam.gserviceaccount.com Auto-Submit: Filippo Valsorda Reviewed-by: Roland Shoemaker Reviewed-by: David Chase --- src/crypto/ecdsa/ecdsa_test.go | 109 +++++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) diff --git a/src/crypto/ecdsa/ecdsa_test.go b/src/crypto/ecdsa/ecdsa_test.go index 29645dc277dab1..5ca1b1694dfa5f 100644 --- a/src/crypto/ecdsa/ecdsa_test.go +++ b/src/crypto/ecdsa/ecdsa_test.go @@ -108,6 +108,81 @@ func TestSignAndVerifyASN1(t *testing.T) { testAllCurves(t, testSignAndVerifyASN1) } +func TestEmptyHashRejection(t *testing.T) { + testAllCurves(t, testEmptyHashRejection) +} + +func testEmptyHashRejection(t *testing.T, c elliptic.Curve) { + priv, err := GenerateKey(c, rand.Reader) + if err != nil { + t.Fatal(err) + } + + t.Run("SignASN1", func(t *testing.T) { + _, err := SignASN1(rand.Reader, priv, nil) + if err == nil { + t.Fatal("SignASN1 with nil hash should fail") + } + if !strings.Contains(err.Error(), "cannot be empty") { + t.Errorf("unexpected error: %v", err) + } + + _, err = SignASN1(rand.Reader, priv, []byte{}) + if err == nil { + t.Fatal("SignASN1 with empty hash should fail") + } + if !strings.Contains(err.Error(), "cannot be empty") { + t.Errorf("unexpected error: %v", err) + } + }) + + t.Run("Sign", func(t *testing.T) { + _, err := priv.Sign(rand.Reader, nil, nil) + if err == nil { + t.Fatal("Sign with nil hash should fail") + } + if !strings.Contains(err.Error(), "cannot be empty") { + t.Errorf("unexpected error: %v", err) + } + + _, err = priv.Sign(rand.Reader, []byte{}, nil) + if err == nil { + t.Fatal("Sign with empty hash should fail") + } + if !strings.Contains(err.Error(), "cannot be empty") { + t.Errorf("unexpected error: %v", err) + } + }) + + t.Run("SignDeterministic", func(t *testing.T) { + if _, err := priv.Sign(nil, nil, nil); err == nil { + t.Error("deterministic Sign with nil hash should fail") + } + if _, err := priv.Sign(nil, []byte{}, nil); err == nil { + t.Error("deterministic Sign with empty hash should fail") + } + }) + + t.Run("VerifyASN1", func(t *testing.T) { + // Create a valid signature first + hash := []byte("test hash") + sig, err := SignASN1(rand.Reader, priv, hash) + if err != nil { + t.Fatal(err) + } + + // Verify with nil hash should return false + if VerifyASN1(&priv.PublicKey, nil, sig) { + t.Error("VerifyASN1 with nil hash should return false") + } + + // Verify with empty hash should return false + if VerifyASN1(&priv.PublicKey, []byte{}, sig) { + t.Error("VerifyASN1 with empty hash should return false") + } + }) +} + func testSignAndVerifyASN1(t *testing.T, c elliptic.Curve) { priv, _ := GenerateKey(c, rand.Reader) @@ -128,6 +203,40 @@ func testSignAndVerifyASN1(t *testing.T, c elliptic.Curve) { } } +func TestSignHashLength(t *testing.T) { + testAllCurves(t, testSignHashLength) +} + +func testSignHashLength(t *testing.T, c elliptic.Curve) { + priv, err := GenerateKey(c, rand.Reader) + if err != nil { + t.Fatal(err) + } + + digest := sha256.Sum256([]byte("message")) + + // opts == nil is allowed and skips the length check. + if _, err := priv.Sign(rand.Reader, digest[:], nil); err != nil { + t.Errorf("Sign with nil opts: %v", err) + } + + // opts != nil with matching hash length succeeds. + if _, err := priv.Sign(rand.Reader, digest[:], crypto.SHA256); err != nil { + t.Errorf("Sign with matching hash: %v", err) + } + + // opts != nil with mismatched hash length fails. + if _, err := priv.Sign(rand.Reader, digest[:], crypto.SHA384); err == nil { + t.Error("Sign with mismatched hash length should fail") + } + if _, err := priv.Sign(rand.Reader, digest[:len(digest)-1], crypto.SHA256); err == nil { + t.Error("Sign with short digest should fail") + } + if _, err := priv.Sign(rand.Reader, nil, crypto.SHA256); err == nil { + t.Error("Sign with empty digest should fail") + } +} + func TestNonceSafety(t *testing.T) { testAllCurves(t, testNonceSafety) } From 2760c3f5a3afe3465fd757ad4809b09bcfe11db3 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Tue, 19 May 2026 14:07:55 -0700 Subject: [PATCH 4/8] go/types: use mustParse helper to simplify tests where possible Note: types2 either deosn't have these tests or is already using a short form. Change-Id: I729282e9ff574010490604814134756df5824f4b Reviewed-on: https://go-review.googlesource.com/c/go/+/780100 LUCI-TryBot-Result: golang-scoped@luci-project-accounts.iam.gserviceaccount.com Auto-Submit: Robert Griesemer Reviewed-by: Robert Griesemer Reviewed-by: David Chase --- src/go/types/alias_test.go | 11 ++--------- src/go/types/api_test.go | 13 ++++++------- src/go/types/eval_test.go | 5 +---- src/go/types/example_test.go | 6 +----- src/go/types/hash_test.go | 6 +----- src/go/types/methodset_test.go | 12 +++--------- 6 files changed, 14 insertions(+), 39 deletions(-) diff --git a/src/go/types/alias_test.go b/src/go/types/alias_test.go index e0c52fbe78372d..760d66b05047ae 100644 --- a/src/go/types/alias_test.go +++ b/src/go/types/alias_test.go @@ -6,7 +6,6 @@ package types_test import ( "go/ast" - "go/parser" "go/token" "go/types" "testing" @@ -28,10 +27,7 @@ type B struct { type A[T any] struct{}` fset := token.NewFileSet() - file, err := parser.ParseFile(fset, "p.go", src, parser.ParseComments) - if err != nil { - t.Fatalf("could not parse: %v", err) - } + file := mustParse(fset, src) conf := types.Config{} pkg, err := conf.Check(file.Name.Name, fset, []*ast.File{file}, &types.Info{}) @@ -59,10 +55,7 @@ func TestPartialTypeCheckUndeclaredAliasPanic(t *testing.T) { type A = B // undeclared` fset := token.NewFileSet() - file, err := parser.ParseFile(fset, "p.go", src, parser.ParseComments|parser.SkipObjectResolution) - if err != nil { - t.Fatalf("could not parse: %v", err) - } + file := mustParse(fset, src) conf := types.Config{} // no error handler, panic pkg, _ := conf.Check(file.Name.Name, fset, []*ast.File{file}, &types.Info{}) diff --git a/src/go/types/api_test.go b/src/go/types/api_test.go index e8e4f502313b5b..c3fa46dc4545b9 100644 --- a/src/go/types/api_test.go +++ b/src/go/types/api_test.go @@ -3055,7 +3055,7 @@ type C = int // to compute which file it is "in" based on syntax position. func TestVersionIssue69477(t *testing.T) { fset := token.NewFileSet() - f, _ := parser.ParseFile(fset, "a.go", "package p; const k = 123", parser.SkipObjectResolution) + f := mustParse(fset, "package p; const k = 123") // Set an invalid Pos on the BasicLit. ast.Inspect(f, func(n ast.Node) bool { @@ -3085,10 +3085,10 @@ func TestVersionIssue69477(t *testing.T) { // The Checker now holds the effective version in a state variable. func TestVersionWithoutPos(t *testing.T) { fset := token.NewFileSet() - f, _ := parser.ParseFile(fset, "a.go", "//go:build go1.22\n\npackage p; var _ int", parser.SkipObjectResolution) + f := mustParse(fset, "//go:build go1.22\n\npackage p; var _ int") // Splice in a decl from another file. Its pos will be wrong. - f2, _ := parser.ParseFile(fset, "a.go", "package q; func _(s func(func() bool)) { for range s {} }", parser.SkipObjectResolution) + f2 := mustParse(fset, "package q; func _(s func(func() bool)) { for range s {} }") f.Decls[0] = f2.Decls[0] // Type check. The checker will consult the effective @@ -3107,7 +3107,7 @@ func TestVersionWithoutPos(t *testing.T) { func TestVarKind(t *testing.T) { fset := token.NewFileSet() - f, _ := parser.ParseFile(fset, "a.go", `package p + f := mustParse(fset, `package p var global int @@ -3121,8 +3121,7 @@ func (recv T) f(param int) (result int) { _ = local3 } return local2 -} -`, parser.SkipObjectResolution) +}`) pkg := NewPackage("p", "p") info := &Info{Defs: make(map[*ast.Ident]Object)} @@ -3160,7 +3159,7 @@ type B []byte var _ = f[B] ` fset := token.NewFileSet() - f, _ := parser.ParseFile(fset, "p.go", src, parser.SkipObjectResolution) + f := mustParse(fset, src) pkg := NewPackage("p", "p") info := &Info{Types: make(map[ast.Expr]TypeAndValue)} diff --git a/src/go/types/eval_test.go b/src/go/types/eval_test.go index 2e0624e65ee2b9..24c3e2eb09718d 100644 --- a/src/go/types/eval_test.go +++ b/src/go/types/eval_test.go @@ -241,10 +241,7 @@ func f(a int, s string) S { }` fset := token.NewFileSet() - f, err := parser.ParseFile(fset, "p", src, parser.ParseComments|parser.SkipObjectResolution) - if err != nil { - t.Fatal(err) - } + f := mustParse(fset, src) conf := Config{Importer: defaultImporter(fset)} pkg, err := conf.Check("p", fset, []*ast.File{f}, nil) diff --git a/src/go/types/example_test.go b/src/go/types/example_test.go index cec01457355148..044687f53769a5 100644 --- a/src/go/types/example_test.go +++ b/src/go/types/example_test.go @@ -19,7 +19,6 @@ import ( "fmt" "go/ast" "go/format" - "go/parser" "go/token" "go/types" "log" @@ -117,10 +116,7 @@ type S struct { I; m int } type I interface { m() byte } ` fset := token.NewFileSet() - f, err := parser.ParseFile(fset, "celsius.go", input, parser.SkipObjectResolution) - if err != nil { - log.Fatal(err) - } + f := mustParse(fset, input) // Type-check a package consisting of this file. // Type information for the imported packages diff --git a/src/go/types/hash_test.go b/src/go/types/hash_test.go index 4b040d26472146..88e0ae8a242105 100644 --- a/src/go/types/hash_test.go +++ b/src/go/types/hash_test.go @@ -8,7 +8,6 @@ package types_test import ( "go/ast" - "go/parser" "go/token" "go/types" "hash/maphash" @@ -95,10 +94,7 @@ type Tagged2 struct { F int "tag2" } ` fset := token.NewFileSet() - file, err := parser.ParseFile(fset, "p.go", src, parser.SkipObjectResolution) - if err != nil { - t.Fatal(err) - } + file := mustParse(fset, src) var conf types.Config pkg, err := conf.Check("", fset, []*ast.File{file}, nil) diff --git a/src/go/types/methodset_test.go b/src/go/types/methodset_test.go index d0ec1f1d881a6e..43893194b9eb99 100644 --- a/src/go/types/methodset_test.go +++ b/src/go/types/methodset_test.go @@ -10,7 +10,6 @@ import ( "testing" "go/ast" - "go/parser" "go/token" . "go/types" ) @@ -144,10 +143,8 @@ type Instance = *Tree[int] ` fset := token.NewFileSet() - f, err := parser.ParseFile(fset, "foo.go", src, parser.SkipObjectResolution) - if err != nil { - panic(err) - } + f := mustParse(fset, src) + pkg := NewPackage("pkg", f.Name.Name) if err := NewChecker(nil, fset, pkg, nil).Files([]*ast.File{f}); err != nil { panic(err) @@ -165,10 +162,7 @@ func (T) m() {} // expected error: invalid receiver type ` fset := token.NewFileSet() - f, err := parser.ParseFile(fset, "p.go", src, parser.SkipObjectResolution) - if err != nil { - t.Fatal(err) - } + f := mustParse(fset, src) var conf Config pkg, err := conf.Check("p", fset, []*ast.File{f}, nil) From 37bce6617fb957b4d0c16cc10b269cb5b5975892 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Tue, 19 May 2026 14:34:18 -0700 Subject: [PATCH 5/8] types2, go/types: add missing alias test to types2, simplify go/types test Change-Id: I4d3377e704d718a1914135a444b9df59f84af179 Reviewed-on: https://go-review.googlesource.com/c/go/+/780120 Reviewed-by: Robert Griesemer Auto-Submit: Robert Griesemer Reviewed-by: David Chase LUCI-TryBot-Result: golang-scoped@luci-project-accounts.iam.gserviceaccount.com --- src/cmd/compile/internal/types2/alias_test.go | 61 +++++++++++++++++++ src/go/types/alias_test.go | 25 ++------ 2 files changed, 67 insertions(+), 19 deletions(-) create mode 100644 src/cmd/compile/internal/types2/alias_test.go diff --git a/src/cmd/compile/internal/types2/alias_test.go b/src/cmd/compile/internal/types2/alias_test.go new file mode 100644 index 00000000000000..7e108e179c325c --- /dev/null +++ b/src/cmd/compile/internal/types2/alias_test.go @@ -0,0 +1,61 @@ +// Copyright 2026 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package types2_test + +import ( + "cmd/compile/internal/types2" + "testing" +) + +func TestIssue74181(t *testing.T) { + src := `package p + +type AB = A[B] + +type _ struct { + _ AB +} + +type B struct { + f *AB +} + +type A[T any] struct{} +` + + pkg := mustTypecheck(src, nil, nil) + b := pkg.Scope().Lookup("B").Type() + if n, ok := b.(*types2.Named); ok { + if s, ok := n.Underlying().(*types2.Struct); ok { + got := s.Field(0).Type() + want := types2.NewPointer(pkg.Scope().Lookup("AB").Type()) + if !types2.Identical(got, want) { + t.Errorf("wrong type for f: got %v, want %v", got, want) + } + return + } + } + t.Errorf("unexpected type for B: %v", b) +} + +func TestPartialTypeCheckUndeclaredAliasPanic(t *testing.T) { + src := `package p + +type A = B // undeclared +` + + pkg, _ := typecheck(src, nil, nil) // don't panic on error + a := pkg.Scope().Lookup("A").Type() + if alias, ok := a.(*types2.Alias); ok { + got := alias.Rhs() + want := types2.Typ[types2.Invalid] + + if !types2.Identical(got, want) { + t.Errorf("wrong type for B: got %v, want %v", got, want) + } + return + } + t.Errorf("unexpected type for A: %v", a) +} diff --git a/src/go/types/alias_test.go b/src/go/types/alias_test.go index 760d66b05047ae..f8b54df905b11b 100644 --- a/src/go/types/alias_test.go +++ b/src/go/types/alias_test.go @@ -5,8 +5,6 @@ package types_test import ( - "go/ast" - "go/token" "go/types" "testing" ) @@ -24,17 +22,10 @@ type B struct { f *AB } -type A[T any] struct{}` - - fset := token.NewFileSet() - file := mustParse(fset, src) - - conf := types.Config{} - pkg, err := conf.Check(file.Name.Name, fset, []*ast.File{file}, &types.Info{}) - if err != nil { - t.Fatalf("could not type check: %v", err) - } +type A[T any] struct{} +` + pkg := mustTypecheck(src, nil, nil) b := pkg.Scope().Lookup("B").Type() if n, ok := b.(*types.Named); ok { if s, ok := n.Underlying().(*types.Struct); ok { @@ -52,15 +43,11 @@ type A[T any] struct{}` func TestPartialTypeCheckUndeclaredAliasPanic(t *testing.T) { src := `package p -type A = B // undeclared` +type A = B // undeclared +` - fset := token.NewFileSet() - file := mustParse(fset, src) - - conf := types.Config{} // no error handler, panic - pkg, _ := conf.Check(file.Name.Name, fset, []*ast.File{file}, &types.Info{}) + pkg, _ := typecheck(src, nil, nil) // don't panic on error a := pkg.Scope().Lookup("A").Type() - if alias, ok := a.(*types.Alias); ok { got := alias.Rhs() want := types.Typ[types.Invalid] From 8494d25c4cc090a84d82d88a9ddbed21e0c32c8c Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Tue, 19 May 2026 09:28:23 -0700 Subject: [PATCH 6/8] os/signal: make NotifyContext Cause match context.Canceled Fixes #77639 Change-Id: I90e5d6f68c02749ac6e407f1c3565312efafb033 Reviewed-on: https://go-review.googlesource.com/c/go/+/779860 Reviewed-by: David Chase LUCI-TryBot-Result: golang-scoped@luci-project-accounts.iam.gserviceaccount.com Reviewed-by: Damien Neil Reviewed-by: Florian Lehner Auto-Submit: Ian Lance Taylor --- src/os/signal/signal.go | 7 +++++++ src/os/signal/signal_test.go | 22 ++++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/src/os/signal/signal.go b/src/os/signal/signal.go index e5e4816ffeccd8..b19366f5af56dd 100644 --- a/src/os/signal/signal.go +++ b/src/os/signal/signal.go @@ -354,3 +354,10 @@ type signalError string func (s signalError) Error() string { return string(s) } + +func (s signalError) Is(target error) bool { + if target == context.Canceled { + return true + } + return false +} diff --git a/src/os/signal/signal_test.go b/src/os/signal/signal_test.go index 8a3ba0e847546b..693e40c90aee50 100644 --- a/src/os/signal/signal_test.go +++ b/src/os/signal/signal_test.go @@ -924,3 +924,25 @@ func TestSignalTrace(t *testing.T) { close(quit) <-done } + +// #77639. +func TestNotifyContextCause(t *testing.T) { + ctx, stop := NotifyContext(t.Context(), syscall.SIGINT) + defer stop() + syscall.Kill(syscall.Getpid(), syscall.SIGINT) + <-ctx.Done() + + err := ctx.Err() + if err == nil { + t.Error("ctx.Err returned nil") + } else if !errors.Is(err, context.Canceled) { + t.Errorf("error %v is not context.Canceled", err) + } + + err = context.Cause(ctx) + if err == nil { + t.Error("context.Cause returned nil") + } else if !errors.Is(err, context.Canceled) { + t.Errorf("cause %v is not context.Canceled", err) + } +} From 45f1313c189bc51de0484c76fa77efc424c6b969 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Tue, 19 May 2026 14:45:27 -0700 Subject: [PATCH 7/8] go/types: generate alias_test.go from respective types2 source Change-Id: Ia5be3eea95583ed2b32f568f7689d414205c5d21 Reviewed-on: https://go-review.googlesource.com/c/go/+/780101 Reviewed-by: Robert Griesemer Auto-Submit: Robert Griesemer LUCI-TryBot-Result: golang-scoped@luci-project-accounts.iam.gserviceaccount.com Reviewed-by: David Chase --- src/go/types/alias_test.go | 5 ++++- src/go/types/generate_test.go | 4 ++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/go/types/alias_test.go b/src/go/types/alias_test.go index f8b54df905b11b..8648c6a569cb24 100644 --- a/src/go/types/alias_test.go +++ b/src/go/types/alias_test.go @@ -1,4 +1,7 @@ -// Copyright 2025 The Go Authors. All rights reserved. +// Code generated by "go test -run=Generate -write=all"; DO NOT EDIT. +// Source: ../../cmd/compile/internal/types2/alias_test.go + +// Copyright 2026 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. diff --git a/src/go/types/generate_test.go b/src/go/types/generate_test.go index 7e090c909bf559..1761059359d57e 100644 --- a/src/go/types/generate_test.go +++ b/src/go/types/generate_test.go @@ -101,6 +101,10 @@ type action func(in *ast.File) var filemap = map[string]action{ "alias.go": fixTokenPos, + "alias_test.go": func(f *ast.File) { + renameImportPath(f, `"cmd/compile/internal/types2"->"go/types"`) + renameIdents(f, "types2->types") + }, "assignments.go": func(f *ast.File) { renameImportPath(f, `"cmd/compile/internal/syntax"->"go/ast"`) renameSelectorExprs(f, "syntax.Name->ast.Ident", "ident.Value->ident.Name", "ast.Pos->token.Pos") // must happen before renaming identifiers From 47f26133bd6f63ea659ce28bfdb7761de96964d0 Mon Sep 17 00:00:00 2001 From: Guoqi Chen Date: Thu, 16 Apr 2026 09:31:07 +0800 Subject: [PATCH 8/8] cmd/internal/obj/loong64: add ll.acq.{w,d}, sc.rel.{w,d}, sc.q instruction Go asm syntax: LLACQW (RJ), RD LLACQV (RJ), RD SCRELW RD, (RJ) SCRELV RD, (RJ) SCQ RD, RK, (RJ) Equivalent platform assembler syntax: ll.acq.w rd, rj ll.acq.d rd, rj sc.rel.w rd, rj sc.rel.d rd, rj sc.q rd, rk, rj To ensure semantic consistency of instruction suffixes, equivalent instructions LLW and SCW for LL and SC have been added. Change-Id: I01a13e76c5b00c14e8774de51bf0680ab76a46e3 Reviewed-on: https://go-review.googlesource.com/c/go/+/768900 Reviewed-by: Meidan Li LUCI-TryBot-Result: golang-scoped@luci-project-accounts.iam.gserviceaccount.com Reviewed-by: David Chase Reviewed-by: Keith Randall --- .../asm/internal/asm/testdata/loong64enc1.s | 16 ++++++--- .../asm/internal/asm/testdata/loong64error.s | 3 +- src/cmd/internal/obj/loong64/anames.go | 15 +++++--- src/cmd/internal/obj/loong64/asm.go | 36 +++++++++++++++++-- src/cmd/internal/obj/loong64/inst.go | 17 +++++---- src/cmd/internal/obj/loong64/instOp.go | 7 ++++ src/internal/cpu/cpu.go | 18 +++++----- src/internal/cpu/cpu_loong64.go | 10 ++++-- 8 files changed, 94 insertions(+), 28 deletions(-) diff --git a/src/cmd/asm/internal/asm/testdata/loong64enc1.s b/src/cmd/asm/internal/asm/testdata/loong64enc1.s index 955ba630714681..fa433d53e12134 100644 --- a/src/cmd/asm/internal/asm/testdata/loong64enc1.s +++ b/src/cmd/asm/internal/asm/testdata/loong64enc1.s @@ -97,8 +97,6 @@ lable2: MOVV R4, 1(R5) // a404c029 MOVB R4, 1(R5) // a4040029 MOVBU R4, 1(R5) // a4040029 - SC R4, 4096(R5) // a4001021 - SCV R4, 4096(R5) // a4001023 MOVW y+8(FP), R4 // 64408028 MOVWU y+8(FP), R4 // 6440802a MOVV y+8(FP), R4 // 6440c028 @@ -109,8 +107,6 @@ lable2: MOVV 1(R5), R4 // a404c028 MOVB 1(R5), R4 // a4040028 MOVBU 1(R5), R4 // a404002a - LL 4096(R5), R4 // a4001020 - LLV 4096(R5), R4 // a4001022 MOVW $4(R4), R5 // 8510c002 MOVV $4(R4), R5 // 8510c002 MOVW $-1, R4 // 04fcff02 @@ -354,6 +350,18 @@ lable2: AMMAXDBVU R14, (R13), R12 // acb97038 AMMINDBWU R14, (R13), R12 // ac397138 AMMINDBVU R14, (R13), R12 // acb97138 + LL 4096(R5), R4 // a4001020 + LLW 4096(R5), R4 // a4001020 + LLV 4096(R5), R4 // a4001022 + LLACQW (R5), R4 // a4805738 + LLACQV (R5), R4 // a4885738 + SC R4, 4096(R5) // a4001021 + SCW R4, 4096(R5) // a4001021 + SCV R4, 4096(R5) // a4001023 + SCQ R4, R5, (R6) // c4145738 + SCRELW R4, (R6) // c4845738 + SCRELV R4, (R6) // c48c5738 + FMADDF F2, F14, F9, F16 // 30391108 FMADDD F11, F20, F23, F12 // ecd22508 diff --git a/src/cmd/asm/internal/asm/testdata/loong64error.s b/src/cmd/asm/internal/asm/testdata/loong64error.s index 1bc0ddea557192..25ef3a85a46738 100644 --- a/src/cmd/asm/internal/asm/testdata/loong64error.s +++ b/src/cmd/asm/internal/asm/testdata/loong64error.s @@ -8,7 +8,8 @@ TEXT errors(SB),$0 ADDV16 $1, R4, R5 // ERROR "the constant must be a multiple of 65536." ADDV16 $65535, R4, R5 // ERROR "the constant must be a multiple of 65536." SC R4, 1(R5) // ERROR "offset must be a multiple of 4." + SCW R4, 1(R5) // ERROR "offset must be a multiple of 4." SCV R4, 1(R5) // ERROR "offset must be a multiple of 4." LL 1(R5), R4 // ERROR "offset must be a multiple of 4." + LLW 1(R5), R4 // ERROR "offset must be a multiple of 4." LLV 1(R5), R4 // ERROR "offset must be a multiple of 4." - diff --git a/src/cmd/internal/obj/loong64/anames.go b/src/cmd/internal/obj/loong64/anames.go index d99c2562676404..0244a8f9e58811 100644 --- a/src/cmd/internal/obj/loong64/anames.go +++ b/src/cmd/internal/obj/loong64/anames.go @@ -43,8 +43,6 @@ var Anames = []string{ "DIVU", "DIVW", "DIVWU", - "LL", - "LLV", "LUI", "MOVB", "MOVBU", @@ -77,8 +75,6 @@ var Anames = []string{ "REMU", "REMWU", "RFE", - "SC", - "SCV", "SGT", "SGTU", "SLL", @@ -181,6 +177,17 @@ var Anames = []string{ "AMMAXDBVU", "AMMINDBWU", "AMMINDBVU", + "LL", + "LLW", + "LLV", + "SC", + "SCW", + "SCV", + "SCQ", + "LLACQW", + "LLACQV", + "SCRELW", + "SCRELV", "EXTWB", "EXTWH", "CLOW", diff --git a/src/cmd/internal/obj/loong64/asm.go b/src/cmd/internal/obj/loong64/asm.go index c3ec81cc92d0f5..2ed2f23d11090a 100644 --- a/src/cmd/internal/obj/loong64/asm.go +++ b/src/cmd/internal/obj/loong64/asm.go @@ -247,7 +247,7 @@ var optab = []Optab{ {AVMOVQ, C_SOREG_12, C_NONE, C_NONE, C_VREG, C_NONE, 8, 4, REGZERO, 0}, {AVMOVQ, C_VREG, C_NONE, C_NONE, C_ROFF, C_NONE, 20, 4, 0, 0}, {AVMOVQ, C_ROFF, C_NONE, C_NONE, C_VREG, C_NONE, 21, 4, 0, 0}, - {AVMOVQ, C_SOREG_12, C_NONE, C_NONE, C_ARNG, C_NONE, 46, 4, 0, 0}, // vldrepl.{b/h/w/d} + {AVMOVQ, C_SOREG_12, C_NONE, C_NONE, C_ARNG, C_NONE, 42, 4, 0, 0}, // vldrepl.{b/h/w/d} // moving data between registers {AVMOVQ, C_VREG, C_NONE, C_NONE, C_VREG, C_NONE, 1, 4, 0, 0}, {AVMOVQ, C_REG, C_NONE, C_NONE, C_ELEM, C_NONE, 39, 4, 0, 0}, // vinsgr2vr.{b/h/w/d} @@ -262,7 +262,7 @@ var optab = []Optab{ {AXVMOVQ, C_SAUTO, C_NONE, C_NONE, C_XREG, C_NONE, 8, 4, REGZERO, 0}, {AXVMOVQ, C_XREG, C_NONE, C_NONE, C_ROFF, C_NONE, 20, 4, 0, 0}, {AXVMOVQ, C_ROFF, C_NONE, C_NONE, C_XREG, C_NONE, 21, 4, 0, 0}, - {AXVMOVQ, C_SOREG_12, C_NONE, C_NONE, C_ARNG, C_NONE, 46, 4, 0, 0}, // xvldrepl.{b/h/w/d} + {AXVMOVQ, C_SOREG_12, C_NONE, C_NONE, C_ARNG, C_NONE, 42, 4, 0, 0}, // xvldrepl.{b/h/w/d} // moving data between registers {AXVMOVQ, C_XREG, C_NONE, C_NONE, C_XREG, C_NONE, 1, 4, 0, 0}, {AXVMOVQ, C_REG, C_NONE, C_NONE, C_ELEM, C_NONE, 39, 4, 0, 0}, // vinsgr2vr.{b/h/w/d} @@ -310,6 +310,10 @@ var optab = []Optab{ {AAMSWAPW, C_REG, C_NONE, C_NONE, C_ZOREG, C_REG, 66, 4, 0, 0}, + {ASCQ, C_REG, C_REG, C_NONE, C_ZOREG, C_NONE, 45, 4, 0, 0}, + {ALLACQW, C_ZOREG, C_NONE, C_NONE, C_REG, C_NONE, 46, 4, 0, 0}, + {ASCRELW, C_REG, C_NONE, C_NONE, C_ZOREG, C_NONE, 46, 4, 0, 0}, + {ASYSCALL, C_NONE, C_NONE, C_NONE, C_NONE, C_NONE, 5, 4, 0, 0}, {ASYSCALL, C_U15CON, C_NONE, C_NONE, C_NONE, C_NONE, 5, 4, 0, 0}, @@ -1430,8 +1434,10 @@ func buildop(ctxt *obj.Link) { case AMOVWP: opset(AMOVVP, r0) opset(ASC, r0) + opset(ASCW, r0) opset(ASCV, r0) opset(ALL, r0) + opset(ALLW, r0) opset(ALLV, r0) case ASLL: @@ -1515,6 +1521,7 @@ func buildop(ctxt *obj.Link) { APRELDX, AFSEL, AADDV16, + ASCQ, obj.ANOP, obj.ATEXT, obj.AFUNCDATA, @@ -1573,6 +1580,12 @@ func buildop(ctxt *obj.Link) { opset(i, r0) } + case ALLACQW: + opset(ALLACQV, r0) + + case ASCRELW: + opset(ASCRELV, r0) + // vseq.b vd, vj, vk // vseqi.b vd, vj, si5 case AVSEQB: @@ -2724,7 +2737,7 @@ func (c *ctxt0) asmout(p *obj.Prog, o *Optab, out []uint32) { rd := uint32(p.To.Reg & EXT_REG_MASK) o1 = v | (rj << 5) | rd - case 46: // vmov offset(vj), vd. + case 42: // vmov offset(vj), vd. v, _ := c.specialLsxMovInst(p.As, p.From.Reg, p.To.Reg, true) if v == 0 { c.ctxt.Diag("illegal arng type combination: %v\n", p) @@ -2756,6 +2769,23 @@ func (c *ctxt0) asmout(p *obj.Prog, o *Optab, out []uint32) { } } + case 45: + // sc.q rd, rk, (rj) + o1 = OP_RRR(c.oprrr(p.As), uint32(p.Reg), uint32(p.To.Reg), uint32(p.From.Reg)) + + case 46: + // ll.acq.{w/d} (rj), rd + rj := uint32(p.From.Reg) + rd := uint32(p.To.Reg) + + switch p.As { + case ASCRELW, ASCRELV: + rj = uint32(p.To.Reg) + rd = uint32(p.From.Reg) + } + + o1 = OP_RR(c.oprr(p.As), rj, rd) + case 47: // preld offset(Rbase), $hint offs := c.regoff(&p.From) hint := p.GetFrom3().Offset diff --git a/src/cmd/internal/obj/loong64/inst.go b/src/cmd/internal/obj/loong64/inst.go index f59406eeef4dfa..3e9cd0c7dc4dba 100644 --- a/src/cmd/internal/obj/loong64/inst.go +++ b/src/cmd/internal/obj/loong64/inst.go @@ -55,9 +55,6 @@ const ( ADIVW ADIVWU - ALL - ALLV - ALUI AMOVB @@ -99,9 +96,6 @@ const ( ARFE - ASC - ASCV - ASGT ASGTU @@ -228,6 +222,17 @@ const ( AAMMAXDBVU AAMMINDBWU AAMMINDBVU + ALL + ALLW + ALLV + ASC + ASCW + ASCV + ASCQ + ALLACQW + ALLACQV + ASCRELW + ASCRELV // 2.2.3.1 AEXTWB diff --git a/src/cmd/internal/obj/loong64/instOp.go b/src/cmd/internal/obj/loong64/instOp.go index 8d9bb7bbceee0c..c2fa45ae573494 100644 --- a/src/cmd/internal/obj/loong64/instOp.go +++ b/src/cmd/internal/obj/loong64/instOp.go @@ -36,6 +36,7 @@ var oprrr = map[obj.As]uint32{ ASGTU: 0x25 << 15, // sltu AMASKEQZ: 0x26 << 15, // maskeqz AMASKNEZ: 0x27 << 15, // masknez + ASCQ: 0x070AE << 15, // sc.q ANOR: 0x28 << 15, // nor AAND: 0x29 << 15, // and AOR: 0x2a << 15, // or @@ -568,6 +569,10 @@ var oprr = map[obj.As]uint32{ ARDTIMELW: 0x18 << 10, // rdtimel.w ARDTIMEHW: 0x19 << 10, // rdtimeh.w ARDTIMED: 0x1a << 10, // rdtime.d + ALLACQW: 0x0E15E0 << 10, // ll.acq.w + ASCRELW: 0x0E15E1 << 10, // sc.rel.w + ALLACQV: 0x0E15E2 << 10, // ll.acq.d + ASCRELV: 0x0E15E3 << 10, // sc.rel.d ATRUNCFV: 0x46a9 << 10, // ftintrz.l.s ATRUNCDV: 0x46aa << 10, // ftintrz.l.d ATRUNCFW: 0x46a1 << 10, // ftintrz.w.s @@ -760,7 +765,9 @@ var opirr = map[obj.As]uint32{ -AMOVD: 0x0ae << 22, // fld.d AMOVD: 0x0af << 22, // fst.d -ALL: 0x020 << 24, // ll.w + -ALLW: 0x020 << 24, // ll.w ASC: 0x021 << 24, // sc.w + ASCW: 0x021 << 24, // sc.w -ALLV: 0x022 << 24, // ll.d ASCV: 0x023 << 24, // sc.d -AMOVWP: 0x24 << 24, // ldptr.w diff --git a/src/internal/cpu/cpu.go b/src/internal/cpu/cpu.go index cf10e36b2d6ede..a2d5524acd4674 100644 --- a/src/internal/cpu/cpu.go +++ b/src/internal/cpu/cpu.go @@ -92,14 +92,16 @@ var ARM64 struct { // The booleans in Loong64 contain the correspondingly named cpu feature bit. // The struct is padded to avoid false sharing. var Loong64 struct { - _ CacheLinePad - HasLSX bool // support 128-bit vector extension - HasLASX bool // support 256-bit vector extension - HasCRC32 bool // support CRC instruction - HasLAMCAS bool // support AMCAS[_DB].{B/H/W/D} - HasLAM_BH bool // support AM{SWAP/ADD}[_DB].{B/H} instruction - HasDBAR_HINTS bool // supports finer-grained DBAR hints - _ CacheLinePad + _ CacheLinePad + HasLSX bool // support 128-bit vector extension + HasLASX bool // support 256-bit vector extension + HasCRC32 bool // support CRC instruction + HasLAMCAS bool // support AMCAS[_DB].{B/H/W/D} + HasLAM_BH bool // support AM{SWAP/ADD}[_DB].{B/H} instruction + HasLLACQ_SCREL bool // support LLACQ.{W/D}、SCREL.{W/D} instruction + HasSCQ bool // support SC.Q instruction + HasDBAR_HINTS bool // supports finer-grained DBAR hints + _ CacheLinePad } var MIPS64X struct { diff --git a/src/internal/cpu/cpu_loong64.go b/src/internal/cpu/cpu_loong64.go index 520c1157ab050f..501e90de45e35d 100644 --- a/src/internal/cpu/cpu_loong64.go +++ b/src/internal/cpu/cpu_loong64.go @@ -17,8 +17,10 @@ const ( cpucfg1_CRC32 = 1 << 25 // CPUCFG2 bits - cpucfg2_LAM_BH = 1 << 27 - cpucfg2_LAMCAS = 1 << 28 + cpucfg2_LAM_BH = 1 << 27 + cpucfg2_LAMCAS = 1 << 28 + cpucfg2_LLACQ_SCREL = 1 << 29 + cpucfg2_SCQ = 1 << 30 // CPUCFG3 bits cpucfg3_DBAR_HINTS = 1 << 17 @@ -34,6 +36,8 @@ func doinit() { {Name: "crc32", Feature: &Loong64.HasCRC32}, {Name: "lamcas", Feature: &Loong64.HasLAMCAS}, {Name: "lam_bh", Feature: &Loong64.HasLAM_BH}, + {Name: "llacq_screl", Feature: &Loong64.HasLLACQ_SCREL}, + {Name: "scq", Feature: &Loong64.HasSCQ}, {Name: "dbar_hints", Feature: &Loong64.HasDBAR_HINTS}, } @@ -51,6 +55,8 @@ func doinit() { Loong64.HasCRC32 = cfgIsSet(cfg1, cpucfg1_CRC32) Loong64.HasLAMCAS = cfgIsSet(cfg2, cpucfg2_LAMCAS) Loong64.HasLAM_BH = cfgIsSet(cfg2, cpucfg2_LAM_BH) + Loong64.HasLLACQ_SCREL = cfgIsSet(cfg2, cpucfg2_LLACQ_SCREL) + Loong64.HasSCQ = cfgIsSet(cfg2, cpucfg2_SCQ) Loong64.HasDBAR_HINTS = cfgIsSet(cfg3, cpucfg3_DBAR_HINTS) osInit()