]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/asm: require NOSPLIT for ABIInternal asm functions
authorThan McIntosh <thanm@google.com>
Tue, 13 Apr 2021 17:46:52 +0000 (13:46 -0400)
committerThan McIntosh <thanm@google.com>
Wed, 14 Apr 2021 16:59:08 +0000 (16:59 +0000)
Change the assembler to enforce the requirement that ABIInternal
functions need to be NOSPLIT. At the moment all of the assembly
routines in the runtime that are defined as ABIInternal also
happen to be NOSPLIT, but this CL makes it mandatory.

Updates #40724.

Change-Id: Ief80d22de1782edb44b798fcde9aab8a93548722
Reviewed-on: https://go-review.googlesource.com/c/go/+/309789
Trust: Than McIntosh <thanm@google.com>
Run-TryBot: Than McIntosh <thanm@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Austin Clements <austin@google.com>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
src/cmd/asm/internal/asm/asm.go
src/cmd/asm/internal/asm/pseudo_test.go

index 340f18892479158d9bd719f5b13b949f79fb91a1..cf0d1550f99f0e3d6f014b1b4782553692348bb2 100644 (file)
@@ -134,6 +134,14 @@ func (p *Parser) asmText(operands [][]lex.Token) {
                next++
        }
 
+       // Issue an error if we see a function defined as ABIInternal
+       // without NOSPLIT. In ABIInternal, obj needs to know the function
+       // signature in order to construct the morestack path, so this
+       // currently isn't supported for asm functions.
+       if nameAddr.Sym.ABI() == obj.ABIInternal && flag&obj.NOSPLIT == 0 {
+               p.errorf("TEXT %q: ABIInternal requires NOSPLIT", name)
+       }
+
        // Next operand is the frame and arg size.
        // Bizarre syntax: $frameSize-argSize is two words, not subtraction.
        // Both frameSize and argSize must be simple integers; only frameSize
index 622ee25ce7159bca3951e7f8da7f617e1169ec2c..fe6ffa60740f8a939da0beaadc40e73796b51474 100644 (file)
@@ -25,11 +25,13 @@ func tokenize(s string) [][]lex.Token {
 
 func TestErroneous(t *testing.T) {
 
-       tests := []struct {
+       type errtest struct {
                pseudo   string
                operands string
                expected string
-       }{
+       }
+
+       nonRuntimeTests := []errtest{
                {"TEXT", "", "expect two or three operands for TEXT"},
                {"TEXT", "%", "expect two or three operands for TEXT"},
                {"TEXT", "1, 1", "TEXT symbol \"<erroneous symbol>\" must be a symbol(SB)"},
@@ -58,23 +60,44 @@ func TestErroneous(t *testing.T) {
                {"PCDATA", "1", "expect two operands for PCDATA"},
        }
 
+       runtimeTests := []errtest{
+               {"TEXT", "foo<ABIInternal>(SB),0", "TEXT \"foo\": ABIInternal requires NOSPLIT"},
+       }
+
+       testcats := []struct {
+               compilingRuntime bool
+               tests            []errtest
+       }{
+               {
+                       compilingRuntime: false,
+                       tests:            nonRuntimeTests,
+               },
+               {
+                       compilingRuntime: true,
+                       tests:            runtimeTests,
+               },
+       }
+
        // Note these errors should be independent of the architecture.
        // Just run the test with amd64.
        parser := newParser("amd64")
        var buf bytes.Buffer
        parser.errorWriter = &buf
 
-       for _, test := range tests {
-               parser.errorCount = 0
-               parser.lineNum++
-               if !parser.pseudo(test.pseudo, tokenize(test.operands)) {
-                       t.Fatalf("Wrong pseudo-instruction: %s", test.pseudo)
-               }
-               errorLine := buf.String()
-               if test.expected != errorLine {
-                       t.Errorf("Unexpected error %q; expected %q", errorLine, test.expected)
+       for _, cat := range testcats {
+               for _, test := range cat.tests {
+                       parser.compilingRuntime = cat.compilingRuntime
+                       parser.errorCount = 0
+                       parser.lineNum++
+                       if !parser.pseudo(test.pseudo, tokenize(test.operands)) {
+                               t.Fatalf("Wrong pseudo-instruction: %s", test.pseudo)
+                       }
+                       errorLine := buf.String()
+                       if test.expected != errorLine {
+                               t.Errorf("Unexpected error %q; expected %q", errorLine, test.expected)
+                       }
+                       buf.Reset()
                }
-               buf.Reset()
        }
 
 }