From: Austin Clements Date: Thu, 12 Jun 2025 22:37:01 +0000 (-0400) Subject: runtime: eliminate global state in mkpreempt.go X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=cef381ba60e129e407ea5e5c1191e6ed571cf956;p=gostls13.git runtime: eliminate global state in mkpreempt.go We're going to start writing two files, so having a single global file we're writing will be a problem. This has no effect on the generated code. This is a cherry-pick of CL 680897 from the dev.simd branch. Change-Id: I49897ea0c6500a29eac89b597d75c0eb3e9b6706 Reviewed-on: https://go-review.googlesource.com/c/go/+/693395 Auto-Submit: Austin Clements Reviewed-by: Cherry Mui LUCI-TryBot-Result: Go LUCI --- diff --git a/src/runtime/mkpreempt.go b/src/runtime/mkpreempt.go index 6a9cf77a43..ec900a23d2 100644 --- a/src/runtime/mkpreempt.go +++ b/src/runtime/mkpreempt.go @@ -73,16 +73,14 @@ var regNamesAMD64 = []string{ "X15", } -var out io.Writer - -var arches = map[string]func(){ +var arches = map[string]func(g *gen){ "386": gen386, "amd64": genAMD64, "arm": genARM, "arm64": genARM64, "loong64": genLoong64, - "mips64x": func() { genMIPS(true) }, - "mipsx": func() { genMIPS(false) }, + "mips64x": func(g *gen) { genMIPS(g, true) }, + "mipsx": func(g *gen) { genMIPS(g, false) }, "ppc64x": genPPC64, "riscv64": genRISCV64, "s390x": genS390X, @@ -93,53 +91,58 @@ var beLe = map[string]bool{"mips64x": true, "mipsx": true, "ppc64x": true} func main() { flag.Parse() if flag.NArg() > 0 { - out = os.Stdout for _, arch := range flag.Args() { - gen, ok := arches[arch] + genFn, ok := arches[arch] if !ok { log.Fatalf("unknown arch %s", arch) } - header(arch) - gen() + g := gen{os.Stdout, arch} + g.asmHeader() + genFn(&g) } return } - for arch, gen := range arches { + for arch, genFn := range arches { f, err := os.Create(fmt.Sprintf("preempt_%s.s", arch)) if err != nil { log.Fatal(err) } - out = f - header(arch) - gen() + g := gen{f, arch} + g.asmHeader() + genFn(&g) if err := f.Close(); err != nil { log.Fatal(err) } } } -func header(arch string) { - fmt.Fprintf(out, "// Code generated by mkpreempt.go; DO NOT EDIT.\n\n") - if beLe[arch] { - base := arch[:len(arch)-1] - fmt.Fprintf(out, "//go:build %s || %sle\n\n", base, base) +type gen struct { + w io.Writer + goarch string +} + +func (g *gen) asmHeader() { + fmt.Fprintf(g.w, "// Code generated by mkpreempt.go; DO NOT EDIT.\n\n") + if beLe[g.goarch] { + base := g.goarch[:len(g.goarch)-1] + fmt.Fprintf(g.w, "//go:build %s || %sle\n\n", base, base) } - fmt.Fprintf(out, "#include \"go_asm.h\"\n") - if arch == "amd64" { - fmt.Fprintf(out, "#include \"asm_amd64.h\"\n") + fmt.Fprintf(g.w, "#include \"go_asm.h\"\n") + if g.goarch == "amd64" { + fmt.Fprintf(g.w, "#include \"asm_amd64.h\"\n") } - fmt.Fprintf(out, "#include \"textflag.h\"\n\n") - fmt.Fprintf(out, "TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0\n") + fmt.Fprintf(g.w, "#include \"textflag.h\"\n\n") + fmt.Fprintf(g.w, "TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0\n") } -func p(f string, args ...any) { +func (g *gen) p(f string, args ...any) { fmted := fmt.Sprintf(f, args...) - fmt.Fprintf(out, "\t%s\n", strings.ReplaceAll(fmted, "\n", "\n\t")) + fmt.Fprintf(g.w, "\t%s\n", strings.ReplaceAll(fmted, "\n", "\n\t")) } -func label(l string) { - fmt.Fprintf(out, "%s\n", l) +func (g *gen) label(l string) { + fmt.Fprintf(g.w, "%s\n", l) } type layout struct { @@ -176,28 +179,30 @@ func (l *layout) addSpecial(save, restore string, size int) { l.stack += size } -func (l *layout) save() { +func (l *layout) save(g *gen) { for _, reg := range l.regs { if reg.save != "" { - p(reg.save, reg.pos) + g.p(reg.save, reg.pos) } else { - p("%s %s, %d(%s)", reg.saveOp, reg.reg, reg.pos, l.sp) + g.p("%s %s, %d(%s)", reg.saveOp, reg.reg, reg.pos, l.sp) } } } -func (l *layout) restore() { +func (l *layout) restore(g *gen) { for i := len(l.regs) - 1; i >= 0; i-- { reg := l.regs[i] if reg.restore != "" { - p(reg.restore, reg.pos) + g.p(reg.restore, reg.pos) } else { - p("%s %d(%s), %s", reg.restoreOp, reg.pos, l.sp, reg.reg) + g.p("%s %d(%s), %s", reg.restoreOp, reg.pos, l.sp, reg.reg) } } } -func gen386() { +func gen386(g *gen) { + p := g.p + p("PUSHFL") // Save general purpose registers. var l = layout{sp: "SP"} @@ -218,22 +223,24 @@ func gen386() { p("ADJSP $%d", lSSE.stack) p("NOP SP") - l.save() + l.save(g) p("#ifndef %s", softfloat) - lSSE.save() + lSSE.save(g) p("#endif") p("CALL ·asyncPreempt2(SB)") p("#ifndef %s", softfloat) - lSSE.restore() + lSSE.restore(g) p("#endif") - l.restore() + l.restore(g) p("ADJSP $%d", -lSSE.stack) p("POPFL") p("RET") } -func genAMD64() { +func genAMD64(g *gen) { + p := g.p + // Assign stack offsets. var l = layout{sp: "SP"} for _, reg := range regNamesAMD64 { @@ -262,19 +269,21 @@ func genAMD64() { p("// But vet doesn't know ADJSP, so suppress vet stack checking") p("NOP SP") - l.save() + l.save(g) - lSSE.save() + lSSE.save(g) p("CALL ·asyncPreempt2(SB)") - lSSE.restore() - l.restore() + lSSE.restore(g) + l.restore(g) p("ADJSP $%d", -lSSE.stack) p("POPFQ") p("POPQ BP") p("RET") } -func genARM() { +func genARM(g *gen) { + p := g.p + // Add integer registers R0-R12. // R13 (SP), R14 (LR), R15 (PC) are special and not saved here. var l = layout{sp: "R13", stack: 4} // add LR slot @@ -303,22 +312,23 @@ func genARM() { } p("MOVW.W R14, -%d(R13)", lfp.stack) // allocate frame, save LR - l.save() + l.save(g) p("MOVB ·goarmsoftfp(SB), R0\nCMP $0, R0\nBNE nofp") // test goarmsoftfp, and skip FP registers if goarmsoftfp!=0. - lfp.save() - label("nofp:") + lfp.save(g) + g.label("nofp:") p("CALL ·asyncPreempt2(SB)") p("MOVB ·goarmsoftfp(SB), R0\nCMP $0, R0\nBNE nofp2") // test goarmsoftfp, and skip FP registers if goarmsoftfp!=0. - lfp.restore() - label("nofp2:") - l.restore() + lfp.restore(g) + g.label("nofp2:") + l.restore(g) p("MOVW %d(R13), R14", lfp.stack) // sigctxt.pushCall pushes LR on stack, restore it p("MOVW.P %d(R13), R15", lfp.stack+4) // load PC, pop frame (including the space pushed by sigctxt.pushCall) p("UNDEF") // shouldn't get here } -func genARM64() { +func genARM64(g *gen) { + p := g.p // Add integer registers R0-R26 // R27 (REGTMP), R28 (g), R29 (FP), R30 (LR), R31 (SP) are special // and not saved here. @@ -362,9 +372,9 @@ func genARM64() { p("MOVD R30, (RSP)") p("#endif") - l.save() + l.save(g) p("CALL ·asyncPreempt2(SB)") - l.restore() + l.restore(g) p("MOVD %d(RSP), R30", l.stack) // sigctxt.pushCall has pushed LR (at interrupt) on stack, restore it p("MOVD -8(RSP), R29") // restore frame pointer @@ -373,7 +383,9 @@ func genARM64() { p("RET (R27)") } -func genMIPS(_64bit bool) { +func genMIPS(g *gen, _64bit bool) { + p := g.p + mov := "MOVW" movf := "MOVF" add := "ADD" @@ -428,15 +440,15 @@ func genMIPS(_64bit bool) { p(mov+" R31, -%d(R29)", lfp.stack) p(sub+" $%d, R29", lfp.stack) - l.save() + l.save(g) p("#ifndef %s", softfloat) - lfp.save() + lfp.save(g) p("#endif") p("CALL ·asyncPreempt2(SB)") p("#ifndef %s", softfloat) - lfp.restore() + lfp.restore(g) p("#endif") - l.restore() + l.restore(g) p(mov+" %d(R29), R31", lfp.stack) // sigctxt.pushCall has pushed LR (at interrupt) on stack, restore it p(mov + " (R29), R23") // load PC to REGTMP @@ -444,7 +456,9 @@ func genMIPS(_64bit bool) { p("JMP (R23)") } -func genLoong64() { +func genLoong64(g *gen) { + p := g.p + mov := "MOVV" movf := "MOVD" add := "ADDV" @@ -478,9 +492,9 @@ func genLoong64() { p(mov+" R1, -%d(R3)", l.stack) p(sub+" $%d, R3", l.stack) - l.save() + l.save(g) p("CALL ·asyncPreempt2(SB)") - l.restore() + l.restore(g) p(mov+" %d(R3), R1", l.stack) // sigctxt.pushCall has pushed LR (at interrupt) on stack, restore it p(mov + " (R3), R30") // load PC to REGTMP @@ -488,7 +502,9 @@ func genLoong64() { p("JMP (R30)") } -func genPPC64() { +func genPPC64(g *gen) { + p := g.p + // Add integer registers R3-R29 // R0 (zero), R1 (SP), R30 (g) are special and not saved here. // R2 (TOC pointer in PIC mode), R12 (function entry address in PIC mode) have been saved in sigctxt.pushCall. @@ -528,9 +544,9 @@ func genPPC64() { p("MOVD LR, R31") p("MOVDU R31, -%d(R1)", l.stack) // allocate frame, save PC of interrupted instruction (in LR) - l.save() + l.save(g) p("CALL ·asyncPreempt2(SB)") - l.restore() + l.restore(g) p("MOVD %d(R1), R31", l.stack) // sigctxt.pushCall has pushed LR, R2, R12 (at interrupt) on stack, restore them p("MOVD R31, LR") @@ -543,7 +559,9 @@ func genPPC64() { p("JMP (CTR)") } -func genRISCV64() { +func genRISCV64(g *gen) { + p := g.p + // X0 (zero), X1 (LR), X2 (SP), X3 (GP), X4 (TP), X27 (g), X31 (TMP) are special. var l = layout{sp: "X2", stack: 8} @@ -564,16 +582,18 @@ func genRISCV64() { p("MOV X1, -%d(X2)", l.stack) p("SUB $%d, X2", l.stack) - l.save() + l.save(g) p("CALL ·asyncPreempt2(SB)") - l.restore() + l.restore(g) p("MOV %d(X2), X1", l.stack) p("MOV (X2), X31") p("ADD $%d, X2", l.stack+8) p("JMP (X31)") } -func genS390X() { +func genS390X(g *gen) { + p := g.p + // Add integer registers R0-R12 // R13 (g), R14 (LR), R15 (SP) are special, and not saved here. // Saving R10 (REGTMP) is not necessary, but it is saved anyway. @@ -594,9 +614,9 @@ func genS390X() { p("ADD $-%d, R15", l.stack) p("MOVW R10, 8(R15)") // save flags - l.save() + l.save(g) p("CALL ·asyncPreempt2(SB)") - l.restore() + l.restore(g) p("MOVD %d(R15), R14", l.stack) // sigctxt.pushCall has pushed LR (at interrupt) on stack, restore it p("ADD $%d, R15", l.stack+8) // pop frame (including the space pushed by sigctxt.pushCall) @@ -606,12 +626,14 @@ func genS390X() { p("JMP (R10)") } -func genWasm() { +func genWasm(g *gen) { + p := g.p p("// No async preemption on wasm") p("UNDEF") } -func notImplemented() { +func notImplemented(g *gen) { + p := g.p p("// Not implemented yet") p("JMP ·abort(SB)") }