mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
[dev.simd] 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. Change-Id: I49897ea0c6500a29eac89b597d75c0eb3e9b6706 Reviewed-on: https://go-review.googlesource.com/c/go/+/680897 Reviewed-by: Cherry Mui <cherryyz@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
This commit is contained in:
parent
b2e8ddba3c
commit
dfa6c74263
1 changed files with 96 additions and 74 deletions
|
|
@ -73,16 +73,14 @@ var regNamesAMD64 = []string{
|
||||||
"X15",
|
"X15",
|
||||||
}
|
}
|
||||||
|
|
||||||
var out io.Writer
|
var arches = map[string]func(g *gen){
|
||||||
|
|
||||||
var arches = map[string]func(){
|
|
||||||
"386": gen386,
|
"386": gen386,
|
||||||
"amd64": genAMD64,
|
"amd64": genAMD64,
|
||||||
"arm": genARM,
|
"arm": genARM,
|
||||||
"arm64": genARM64,
|
"arm64": genARM64,
|
||||||
"loong64": genLoong64,
|
"loong64": genLoong64,
|
||||||
"mips64x": func() { genMIPS(true) },
|
"mips64x": func(g *gen) { genMIPS(g, true) },
|
||||||
"mipsx": func() { genMIPS(false) },
|
"mipsx": func(g *gen) { genMIPS(g, false) },
|
||||||
"ppc64x": genPPC64,
|
"ppc64x": genPPC64,
|
||||||
"riscv64": genRISCV64,
|
"riscv64": genRISCV64,
|
||||||
"s390x": genS390X,
|
"s390x": genS390X,
|
||||||
|
|
@ -93,53 +91,58 @@ var beLe = map[string]bool{"mips64x": true, "mipsx": true, "ppc64x": true}
|
||||||
func main() {
|
func main() {
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
if flag.NArg() > 0 {
|
if flag.NArg() > 0 {
|
||||||
out = os.Stdout
|
|
||||||
for _, arch := range flag.Args() {
|
for _, arch := range flag.Args() {
|
||||||
gen, ok := arches[arch]
|
genFn, ok := arches[arch]
|
||||||
if !ok {
|
if !ok {
|
||||||
log.Fatalf("unknown arch %s", arch)
|
log.Fatalf("unknown arch %s", arch)
|
||||||
}
|
}
|
||||||
header(arch)
|
g := gen{os.Stdout, arch}
|
||||||
gen()
|
g.asmHeader()
|
||||||
|
genFn(&g)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
for arch, gen := range arches {
|
for arch, genFn := range arches {
|
||||||
f, err := os.Create(fmt.Sprintf("preempt_%s.s", arch))
|
f, err := os.Create(fmt.Sprintf("preempt_%s.s", arch))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
out = f
|
g := gen{f, arch}
|
||||||
header(arch)
|
g.asmHeader()
|
||||||
gen()
|
genFn(&g)
|
||||||
if err := f.Close(); err != nil {
|
if err := f.Close(); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func header(arch string) {
|
type gen struct {
|
||||||
fmt.Fprintf(out, "// Code generated by mkpreempt.go; DO NOT EDIT.\n\n")
|
w io.Writer
|
||||||
if beLe[arch] {
|
goarch string
|
||||||
base := arch[:len(arch)-1]
|
|
||||||
fmt.Fprintf(out, "//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(out, "#include \"textflag.h\"\n\n")
|
|
||||||
fmt.Fprintf(out, "TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0\n")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func p(f string, args ...any) {
|
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(g.w, "#include \"go_asm.h\"\n")
|
||||||
|
if g.goarch == "amd64" {
|
||||||
|
fmt.Fprintf(g.w, "#include \"asm_amd64.h\"\n")
|
||||||
|
}
|
||||||
|
fmt.Fprintf(g.w, "#include \"textflag.h\"\n\n")
|
||||||
|
fmt.Fprintf(g.w, "TEXT ·asyncPreempt(SB),NOSPLIT|NOFRAME,$0-0\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *gen) p(f string, args ...any) {
|
||||||
fmted := fmt.Sprintf(f, args...)
|
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) {
|
func (g *gen) label(l string) {
|
||||||
fmt.Fprintf(out, "%s\n", l)
|
fmt.Fprintf(g.w, "%s\n", l)
|
||||||
}
|
}
|
||||||
|
|
||||||
type layout struct {
|
type layout struct {
|
||||||
|
|
@ -176,28 +179,30 @@ func (l *layout) addSpecial(save, restore string, size int) {
|
||||||
l.stack += size
|
l.stack += size
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *layout) save() {
|
func (l *layout) save(g *gen) {
|
||||||
for _, reg := range l.regs {
|
for _, reg := range l.regs {
|
||||||
if reg.save != "" {
|
if reg.save != "" {
|
||||||
p(reg.save, reg.pos)
|
g.p(reg.save, reg.pos)
|
||||||
} else {
|
} 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-- {
|
for i := len(l.regs) - 1; i >= 0; i-- {
|
||||||
reg := l.regs[i]
|
reg := l.regs[i]
|
||||||
if reg.restore != "" {
|
if reg.restore != "" {
|
||||||
p(reg.restore, reg.pos)
|
g.p(reg.restore, reg.pos)
|
||||||
} else {
|
} 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")
|
p("PUSHFL")
|
||||||
// Save general purpose registers.
|
// Save general purpose registers.
|
||||||
var l = layout{sp: "SP"}
|
var l = layout{sp: "SP"}
|
||||||
|
|
@ -218,22 +223,24 @@ func gen386() {
|
||||||
|
|
||||||
p("ADJSP $%d", lSSE.stack)
|
p("ADJSP $%d", lSSE.stack)
|
||||||
p("NOP SP")
|
p("NOP SP")
|
||||||
l.save()
|
l.save(g)
|
||||||
p("#ifndef %s", softfloat)
|
p("#ifndef %s", softfloat)
|
||||||
lSSE.save()
|
lSSE.save(g)
|
||||||
p("#endif")
|
p("#endif")
|
||||||
p("CALL ·asyncPreempt2(SB)")
|
p("CALL ·asyncPreempt2(SB)")
|
||||||
p("#ifndef %s", softfloat)
|
p("#ifndef %s", softfloat)
|
||||||
lSSE.restore()
|
lSSE.restore(g)
|
||||||
p("#endif")
|
p("#endif")
|
||||||
l.restore()
|
l.restore(g)
|
||||||
p("ADJSP $%d", -lSSE.stack)
|
p("ADJSP $%d", -lSSE.stack)
|
||||||
|
|
||||||
p("POPFL")
|
p("POPFL")
|
||||||
p("RET")
|
p("RET")
|
||||||
}
|
}
|
||||||
|
|
||||||
func genAMD64() {
|
func genAMD64(g *gen) {
|
||||||
|
p := g.p
|
||||||
|
|
||||||
// Assign stack offsets.
|
// Assign stack offsets.
|
||||||
var l = layout{sp: "SP"}
|
var l = layout{sp: "SP"}
|
||||||
for _, reg := range regNamesAMD64 {
|
for _, reg := range regNamesAMD64 {
|
||||||
|
|
@ -262,19 +269,21 @@ func genAMD64() {
|
||||||
p("// But vet doesn't know ADJSP, so suppress vet stack checking")
|
p("// But vet doesn't know ADJSP, so suppress vet stack checking")
|
||||||
p("NOP SP")
|
p("NOP SP")
|
||||||
|
|
||||||
l.save()
|
l.save(g)
|
||||||
|
|
||||||
lSSE.save()
|
lSSE.save(g)
|
||||||
p("CALL ·asyncPreempt2(SB)")
|
p("CALL ·asyncPreempt2(SB)")
|
||||||
lSSE.restore()
|
lSSE.restore(g)
|
||||||
l.restore()
|
l.restore(g)
|
||||||
p("ADJSP $%d", -lSSE.stack)
|
p("ADJSP $%d", -lSSE.stack)
|
||||||
p("POPFQ")
|
p("POPFQ")
|
||||||
p("POPQ BP")
|
p("POPQ BP")
|
||||||
p("RET")
|
p("RET")
|
||||||
}
|
}
|
||||||
|
|
||||||
func genARM() {
|
func genARM(g *gen) {
|
||||||
|
p := g.p
|
||||||
|
|
||||||
// Add integer registers R0-R12.
|
// Add integer registers R0-R12.
|
||||||
// R13 (SP), R14 (LR), R15 (PC) are special and not saved here.
|
// R13 (SP), R14 (LR), R15 (PC) are special and not saved here.
|
||||||
var l = layout{sp: "R13", stack: 4} // add LR slot
|
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
|
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.
|
p("MOVB ·goarmsoftfp(SB), R0\nCMP $0, R0\nBNE nofp") // test goarmsoftfp, and skip FP registers if goarmsoftfp!=0.
|
||||||
lfp.save()
|
lfp.save(g)
|
||||||
label("nofp:")
|
g.label("nofp:")
|
||||||
p("CALL ·asyncPreempt2(SB)")
|
p("CALL ·asyncPreempt2(SB)")
|
||||||
p("MOVB ·goarmsoftfp(SB), R0\nCMP $0, R0\nBNE nofp2") // test goarmsoftfp, and skip FP registers if goarmsoftfp!=0.
|
p("MOVB ·goarmsoftfp(SB), R0\nCMP $0, R0\nBNE nofp2") // test goarmsoftfp, and skip FP registers if goarmsoftfp!=0.
|
||||||
lfp.restore()
|
lfp.restore(g)
|
||||||
label("nofp2:")
|
g.label("nofp2:")
|
||||||
l.restore()
|
l.restore(g)
|
||||||
|
|
||||||
p("MOVW %d(R13), R14", lfp.stack) // sigctxt.pushCall pushes LR on stack, restore it
|
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("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
|
p("UNDEF") // shouldn't get here
|
||||||
}
|
}
|
||||||
|
|
||||||
func genARM64() {
|
func genARM64(g *gen) {
|
||||||
|
p := g.p
|
||||||
// Add integer registers R0-R26
|
// Add integer registers R0-R26
|
||||||
// R27 (REGTMP), R28 (g), R29 (FP), R30 (LR), R31 (SP) are special
|
// R27 (REGTMP), R28 (g), R29 (FP), R30 (LR), R31 (SP) are special
|
||||||
// and not saved here.
|
// and not saved here.
|
||||||
|
|
@ -362,9 +372,9 @@ func genARM64() {
|
||||||
p("MOVD R30, (RSP)")
|
p("MOVD R30, (RSP)")
|
||||||
p("#endif")
|
p("#endif")
|
||||||
|
|
||||||
l.save()
|
l.save(g)
|
||||||
p("CALL ·asyncPreempt2(SB)")
|
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 %d(RSP), R30", l.stack) // sigctxt.pushCall has pushed LR (at interrupt) on stack, restore it
|
||||||
p("MOVD -8(RSP), R29") // restore frame pointer
|
p("MOVD -8(RSP), R29") // restore frame pointer
|
||||||
|
|
@ -373,7 +383,9 @@ func genARM64() {
|
||||||
p("RET (R27)")
|
p("RET (R27)")
|
||||||
}
|
}
|
||||||
|
|
||||||
func genMIPS(_64bit bool) {
|
func genMIPS(g *gen, _64bit bool) {
|
||||||
|
p := g.p
|
||||||
|
|
||||||
mov := "MOVW"
|
mov := "MOVW"
|
||||||
movf := "MOVF"
|
movf := "MOVF"
|
||||||
add := "ADD"
|
add := "ADD"
|
||||||
|
|
@ -428,15 +440,15 @@ func genMIPS(_64bit bool) {
|
||||||
p(mov+" R31, -%d(R29)", lfp.stack)
|
p(mov+" R31, -%d(R29)", lfp.stack)
|
||||||
p(sub+" $%d, R29", lfp.stack)
|
p(sub+" $%d, R29", lfp.stack)
|
||||||
|
|
||||||
l.save()
|
l.save(g)
|
||||||
p("#ifndef %s", softfloat)
|
p("#ifndef %s", softfloat)
|
||||||
lfp.save()
|
lfp.save(g)
|
||||||
p("#endif")
|
p("#endif")
|
||||||
p("CALL ·asyncPreempt2(SB)")
|
p("CALL ·asyncPreempt2(SB)")
|
||||||
p("#ifndef %s", softfloat)
|
p("#ifndef %s", softfloat)
|
||||||
lfp.restore()
|
lfp.restore(g)
|
||||||
p("#endif")
|
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+" %d(R29), R31", lfp.stack) // sigctxt.pushCall has pushed LR (at interrupt) on stack, restore it
|
||||||
p(mov + " (R29), R23") // load PC to REGTMP
|
p(mov + " (R29), R23") // load PC to REGTMP
|
||||||
|
|
@ -444,7 +456,9 @@ func genMIPS(_64bit bool) {
|
||||||
p("JMP (R23)")
|
p("JMP (R23)")
|
||||||
}
|
}
|
||||||
|
|
||||||
func genLoong64() {
|
func genLoong64(g *gen) {
|
||||||
|
p := g.p
|
||||||
|
|
||||||
mov := "MOVV"
|
mov := "MOVV"
|
||||||
movf := "MOVD"
|
movf := "MOVD"
|
||||||
add := "ADDV"
|
add := "ADDV"
|
||||||
|
|
@ -478,9 +492,9 @@ func genLoong64() {
|
||||||
p(mov+" R1, -%d(R3)", l.stack)
|
p(mov+" R1, -%d(R3)", l.stack)
|
||||||
p(sub+" $%d, R3", l.stack)
|
p(sub+" $%d, R3", l.stack)
|
||||||
|
|
||||||
l.save()
|
l.save(g)
|
||||||
p("CALL ·asyncPreempt2(SB)")
|
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+" %d(R3), R1", l.stack) // sigctxt.pushCall has pushed LR (at interrupt) on stack, restore it
|
||||||
p(mov + " (R3), R30") // load PC to REGTMP
|
p(mov + " (R3), R30") // load PC to REGTMP
|
||||||
|
|
@ -488,7 +502,9 @@ func genLoong64() {
|
||||||
p("JMP (R30)")
|
p("JMP (R30)")
|
||||||
}
|
}
|
||||||
|
|
||||||
func genPPC64() {
|
func genPPC64(g *gen) {
|
||||||
|
p := g.p
|
||||||
|
|
||||||
// Add integer registers R3-R29
|
// Add integer registers R3-R29
|
||||||
// R0 (zero), R1 (SP), R30 (g) are special and not saved here.
|
// 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.
|
// 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("MOVD LR, R31")
|
||||||
p("MOVDU R31, -%d(R1)", l.stack) // allocate frame, save PC of interrupted instruction (in LR)
|
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)")
|
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 %d(R1), R31", l.stack) // sigctxt.pushCall has pushed LR, R2, R12 (at interrupt) on stack, restore them
|
||||||
p("MOVD R31, LR")
|
p("MOVD R31, LR")
|
||||||
|
|
@ -543,7 +559,9 @@ func genPPC64() {
|
||||||
p("JMP (CTR)")
|
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.
|
// X0 (zero), X1 (LR), X2 (SP), X3 (GP), X4 (TP), X27 (g), X31 (TMP) are special.
|
||||||
var l = layout{sp: "X2", stack: 8}
|
var l = layout{sp: "X2", stack: 8}
|
||||||
|
|
||||||
|
|
@ -564,16 +582,18 @@ func genRISCV64() {
|
||||||
|
|
||||||
p("MOV X1, -%d(X2)", l.stack)
|
p("MOV X1, -%d(X2)", l.stack)
|
||||||
p("SUB $%d, X2", l.stack)
|
p("SUB $%d, X2", l.stack)
|
||||||
l.save()
|
l.save(g)
|
||||||
p("CALL ·asyncPreempt2(SB)")
|
p("CALL ·asyncPreempt2(SB)")
|
||||||
l.restore()
|
l.restore(g)
|
||||||
p("MOV %d(X2), X1", l.stack)
|
p("MOV %d(X2), X1", l.stack)
|
||||||
p("MOV (X2), X31")
|
p("MOV (X2), X31")
|
||||||
p("ADD $%d, X2", l.stack+8)
|
p("ADD $%d, X2", l.stack+8)
|
||||||
p("JMP (X31)")
|
p("JMP (X31)")
|
||||||
}
|
}
|
||||||
|
|
||||||
func genS390X() {
|
func genS390X(g *gen) {
|
||||||
|
p := g.p
|
||||||
|
|
||||||
// Add integer registers R0-R12
|
// Add integer registers R0-R12
|
||||||
// R13 (g), R14 (LR), R15 (SP) are special, and not saved here.
|
// R13 (g), R14 (LR), R15 (SP) are special, and not saved here.
|
||||||
// Saving R10 (REGTMP) is not necessary, but it is saved anyway.
|
// Saving R10 (REGTMP) is not necessary, but it is saved anyway.
|
||||||
|
|
@ -594,9 +614,9 @@ func genS390X() {
|
||||||
p("ADD $-%d, R15", l.stack)
|
p("ADD $-%d, R15", l.stack)
|
||||||
p("MOVW R10, 8(R15)") // save flags
|
p("MOVW R10, 8(R15)") // save flags
|
||||||
|
|
||||||
l.save()
|
l.save(g)
|
||||||
p("CALL ·asyncPreempt2(SB)")
|
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("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)
|
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)")
|
p("JMP (R10)")
|
||||||
}
|
}
|
||||||
|
|
||||||
func genWasm() {
|
func genWasm(g *gen) {
|
||||||
|
p := g.p
|
||||||
p("// No async preemption on wasm")
|
p("// No async preemption on wasm")
|
||||||
p("UNDEF")
|
p("UNDEF")
|
||||||
}
|
}
|
||||||
|
|
||||||
func notImplemented() {
|
func notImplemented(g *gen) {
|
||||||
|
p := g.p
|
||||||
p("// Not implemented yet")
|
p("// Not implemented yet")
|
||||||
p("JMP ·abort(SB)")
|
p("JMP ·abort(SB)")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue