]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/vet: improve asmdecl parameter handling
authorJosh Bleecher Snyder <josharian@gmail.com>
Sun, 10 Jul 2016 00:10:57 +0000 (17:10 -0700)
committerJosh Bleecher Snyder <josharian@gmail.com>
Mon, 22 Aug 2016 15:42:06 +0000 (15:42 +0000)
The asmdecl check had hand-rolled code that
calculated the size and offset of parameters
based only on the AST.
It included a list of known named types.

This CL changes asmdecl to use go/types instead.
This allows us to easily handle named types.
It also adds support for structs, arrays,
and complex parameters.

It improves the default names given to unnamed
parameters. Previously, all anonymous arguments were
called "unnamed", and the first anonymous return
argument was called "ret".
Anonymous arguments are now called arg, arg1, arg2,
etc., depending on the index in the argument list.
Return arguments are ret, ret1, ret2.

This CL also fixes a bug in the printing of
composite data type sizes.

Updates #11041

Change-Id: I1085116a26fe6199480b680eff659eb9ab31769b
Reviewed-on: https://go-review.googlesource.com/27150
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Rob Pike <r@golang.org>
src/cmd/vet/asmdecl.go
src/cmd/vet/testdata/asm.go
src/cmd/vet/testdata/asm1.s
src/runtime/sys_darwin_arm.s
src/runtime/sys_plan9_arm.s

index bd336cb662f15e4d242ef8881d482fb181fb8c40..17172ed71daffe409bce1a40cda8c25b361e87a5 100644 (file)
@@ -12,6 +12,7 @@ import (
        "go/ast"
        "go/build"
        "go/token"
+       "go/types"
        "regexp"
        "strconv"
        "strings"
@@ -25,16 +26,17 @@ type asmKind int
 const (
        asmString asmKind = 100 + iota
        asmSlice
+       asmArray
        asmInterface
        asmEmptyInterface
+       asmStruct
+       asmComplex
 )
 
 // An asmArch describes assembly parameters for an architecture
 type asmArch struct {
        name      string
-       ptrSize   int
-       intSize   int
-       maxAlign  int
+       sizes     *types.StdSizes
        bigEndian bool
        stack     string
        lr        bool
@@ -58,16 +60,23 @@ type asmVar struct {
        inner []*asmVar
 }
 
+// Common architecture word sizes and alignments.
 var (
-       asmArch386      = asmArch{"386", 4, 4, 4, false, "SP", false}
-       asmArchArm      = asmArch{"arm", 4, 4, 4, false, "R13", true}
-       asmArchArm64    = asmArch{"arm64", 8, 8, 8, false, "RSP", true}
-       asmArchAmd64    = asmArch{"amd64", 8, 8, 8, false, "SP", false}
-       asmArchAmd64p32 = asmArch{"amd64p32", 4, 4, 8, false, "SP", false}
-       asmArchMips64   = asmArch{"mips64", 8, 8, 8, true, "R29", true}
-       asmArchMips64LE = asmArch{"mips64", 8, 8, 8, false, "R29", true}
-       asmArchPpc64    = asmArch{"ppc64", 8, 8, 8, true, "R1", true}
-       asmArchPpc64LE  = asmArch{"ppc64le", 8, 8, 8, false, "R1", true}
+       size44 = &types.StdSizes{WordSize: 4, MaxAlign: 4}
+       size48 = &types.StdSizes{WordSize: 4, MaxAlign: 8}
+       size88 = &types.StdSizes{WordSize: 8, MaxAlign: 8}
+)
+
+var (
+       asmArch386      = asmArch{"386", size44, false, "SP", false}
+       asmArchArm      = asmArch{"arm", size44, false, "R13", true}
+       asmArchArm64    = asmArch{"arm64", size88, false, "RSP", true}
+       asmArchAmd64    = asmArch{"amd64", size88, false, "SP", false}
+       asmArchAmd64p32 = asmArch{"amd64p32", size48, false, "SP", false}
+       asmArchMips64   = asmArch{"mips64", size88, true, "R29", true}
+       asmArchMips64LE = asmArch{"mips64", size88, false, "R29", true}
+       asmArchPpc64    = asmArch{"ppc64", size88, true, "R1", true}
+       asmArchPpc64LE  = asmArch{"ppc64le", size88, false, "R1", true}
 
        arches = []*asmArch{
                &asmArch386,
@@ -82,6 +91,10 @@ var (
        }
 )
 
+func (a *asmArch) intSize() int  { return int(a.sizes.WordSize) }
+func (a *asmArch) ptrSize() int  { return int(a.sizes.WordSize) }
+func (a *asmArch) maxAlign() int { return int(a.sizes.MaxAlign) }
+
 var (
        re           = regexp.MustCompile
        asmPlusBuild = re(`//\s+\+build\s+([^\n]+)`)
@@ -201,10 +214,10 @@ Files:
                                        }
                                }
                                localSize, _ = strconv.Atoi(m[3])
-                               localSize += archDef.intSize
+                               localSize += archDef.intSize()
                                if archDef.lr {
                                        // Account for caller's saved LR
-                                       localSize += archDef.intSize
+                                       localSize += archDef.intSize()
                                }
                                argSize, _ = strconv.Atoi(m[4])
                                if fn == nil && !strings.Contains(fnName, "<>") {
@@ -310,199 +323,179 @@ Files:
        }
 }
 
+func asmKindForType(t types.Type, size int) asmKind {
+       switch t := t.Underlying().(type) {
+       case *types.Basic:
+               switch t.Kind() {
+               case types.String:
+                       return asmString
+               case types.Complex64, types.Complex128:
+                       return asmComplex
+               }
+               return asmKind(size)
+       case *types.Pointer, *types.Chan, *types.Map, *types.Signature:
+               return asmKind(size)
+       case *types.Struct:
+               return asmStruct
+       case *types.Interface:
+               if t.Empty() {
+                       return asmEmptyInterface
+               }
+               return asmInterface
+       case *types.Array:
+               return asmArray
+       case *types.Slice:
+               return asmSlice
+       }
+       panic("unreachable")
+}
+
+// A component is an assembly-addressable component of a composite type,
+// or a composite type itself.
+type component struct {
+       size   int
+       offset int
+       kind   asmKind
+       typ    string
+       suffix string // Such as _base for string base, _0_lo for lo half of first element of [1]uint64 on 32 bit machine.
+       outer  string // The suffix for immediately containing composite type.
+}
+
+func newComponent(suffix string, kind asmKind, typ string, offset, size int, outer string) component {
+       return component{suffix: suffix, kind: kind, typ: typ, offset: offset, size: size, outer: outer}
+}
+
+// componentsOfType generates a list of components of type t.
+// For example, given string, the components are the string itself, the base, and the length.
+func componentsOfType(arch *asmArch, t types.Type) []component {
+       return appendComponentsRecursive(arch, t, nil, "", 0)
+}
+
+// appendComponentsRecursive implements componentsOfType.
+// Recursion is required to correct handle structs and arrays,
+// which can contain arbitrary other types.
+func appendComponentsRecursive(arch *asmArch, t types.Type, cc []component, suffix string, off int) []component {
+       s := t.String()
+       size := int(arch.sizes.Sizeof(t))
+       kind := asmKindForType(t, size)
+       cc = append(cc, newComponent(suffix, kind, s, off, size, suffix))
+
+       switch kind {
+       case 8:
+               if arch.ptrSize() == 4 {
+                       w1, w2 := "lo", "hi"
+                       if arch.bigEndian {
+                               w1, w2 = w2, w1
+                       }
+                       cc = append(cc, newComponent(suffix+"_"+w1, 4, "half "+s, off, 4, suffix))
+                       cc = append(cc, newComponent(suffix+"_"+w2, 4, "half "+s, off+4, 4, suffix))
+               }
+
+       case asmEmptyInterface:
+               cc = append(cc, newComponent(suffix+"_type", asmKind(arch.ptrSize()), "interface type", off, arch.ptrSize(), suffix))
+               cc = append(cc, newComponent(suffix+"_data", asmKind(arch.ptrSize()), "interface data", off+arch.ptrSize(), arch.ptrSize(), suffix))
+
+       case asmInterface:
+               cc = append(cc, newComponent(suffix+"_itable", asmKind(arch.ptrSize()), "interface itable", off, arch.ptrSize(), suffix))
+               cc = append(cc, newComponent(suffix+"_data", asmKind(arch.ptrSize()), "interface data", off+arch.ptrSize(), arch.ptrSize(), suffix))
+
+       case asmSlice:
+               cc = append(cc, newComponent(suffix+"_base", asmKind(arch.ptrSize()), "slice base", off, arch.ptrSize(), suffix))
+               cc = append(cc, newComponent(suffix+"_len", asmKind(arch.intSize()), "slice len", off+arch.ptrSize(), arch.intSize(), suffix))
+               cc = append(cc, newComponent(suffix+"_cap", asmKind(arch.intSize()), "slice cap", off+arch.ptrSize()+arch.intSize(), arch.intSize(), suffix))
+
+       case asmString:
+               cc = append(cc, newComponent(suffix+"_base", asmKind(arch.ptrSize()), "string base", off, arch.ptrSize(), suffix))
+               cc = append(cc, newComponent(suffix+"_len", asmKind(arch.intSize()), "string len", off+arch.ptrSize(), arch.intSize(), suffix))
+
+       case asmComplex:
+               fsize := size / 2
+               cc = append(cc, newComponent(suffix+"_real", asmKind(fsize), fmt.Sprintf("real(complex%d)", size*8), off, fsize, suffix))
+               cc = append(cc, newComponent(suffix+"_imag", asmKind(fsize), fmt.Sprintf("imag(complex%d)", size*8), off+fsize, fsize, suffix))
+
+       case asmStruct:
+               tu := t.Underlying().(*types.Struct)
+               fields := make([]*types.Var, tu.NumFields())
+               for i := 0; i < tu.NumFields(); i++ {
+                       fields[i] = tu.Field(i)
+               }
+               offsets := arch.sizes.Offsetsof(fields)
+               for i, f := range fields {
+                       cc = appendComponentsRecursive(arch, f.Type(), cc, suffix+"_"+f.Name(), off+int(offsets[i]))
+               }
+
+       case asmArray:
+               tu := t.Underlying().(*types.Array)
+               elem := tu.Elem()
+               // Calculate offset of each element array.
+               fields := []*types.Var{
+                       types.NewVar(token.NoPos, nil, "fake0", elem),
+                       types.NewVar(token.NoPos, nil, "fake1", elem),
+               }
+               offsets := arch.sizes.Offsetsof(fields)
+               elemoff := int(offsets[1])
+               for i := 0; i < int(tu.Len()); i++ {
+                       cc = appendComponentsRecursive(arch, elem, cc, suffix+"_"+strconv.Itoa(i), i*elemoff)
+               }
+       }
+
+       return cc
+}
+
 // asmParseDecl parses a function decl for expected assembly variables.
 func (f *File) asmParseDecl(decl *ast.FuncDecl) map[string]*asmFunc {
        var (
                arch   *asmArch
                fn     *asmFunc
                offset int
-               failed bool
        )
 
-       addVar := func(outer string, v asmVar) {
-               if vo := fn.vars[outer]; vo != nil {
-                       vo.inner = append(vo.inner, &v)
-               }
-               fn.vars[v.name] = &v
-               for i := 0; i < v.size; i++ {
-                       fn.varByOffset[v.off+i] = &v
-               }
-       }
-
-       addParams := func(list []*ast.Field) {
-               for i, fld := range list {
-                       // Determine alignment, size, and kind of type in declaration.
-                       var align, size int
-                       var kind asmKind
-                       names := fld.Names
-                       typ := f.gofmt(fld.Type)
-                       switch t := fld.Type.(type) {
-                       default:
-                               switch typ {
-                               default:
-                                       f.Warnf(fld.Type.Pos(), "unknown assembly argument type %s", typ)
-                                       failed = true
-                                       return
-                               case "int8", "uint8", "byte", "bool":
-                                       size = 1
-                               case "int16", "uint16":
-                                       size = 2
-                               case "int32", "uint32", "float32":
-                                       size = 4
-                               case "int64", "uint64", "float64":
-                                       align = arch.maxAlign
-                                       size = 8
-                               case "int", "uint":
-                                       size = arch.intSize
-                               case "uintptr", "iword", "Word", "Errno", "unsafe.Pointer":
-                                       size = arch.ptrSize
-                               case "string", "ErrorString":
-                                       size = arch.ptrSize * 2
-                                       align = arch.ptrSize
-                                       kind = asmString
-                               }
-                       case *ast.ChanType, *ast.FuncType, *ast.MapType, *ast.StarExpr:
-                               size = arch.ptrSize
-                       case *ast.InterfaceType:
-                               align = arch.ptrSize
-                               size = 2 * arch.ptrSize
-                               if len(t.Methods.List) > 0 {
-                                       kind = asmInterface
-                               } else {
-                                       kind = asmEmptyInterface
-                               }
-                       case *ast.ArrayType:
-                               if t.Len == nil {
-                                       size = arch.ptrSize + 2*arch.intSize
-                                       align = arch.ptrSize
-                                       kind = asmSlice
-                                       break
-                               }
-                               f.Warnf(fld.Type.Pos(), "unsupported assembly argument type %s", typ)
-                               failed = true
-                       case *ast.StructType:
-                               f.Warnf(fld.Type.Pos(), "unsupported assembly argument type %s", typ)
-                               failed = true
-                       }
-                       if align == 0 {
-                               align = size
-                       }
-                       if kind == 0 {
-                               kind = asmKind(size)
-                       }
+       // addParams adds asmVars for each of the parameters in list.
+       // isret indicates whether the list are the arguments or the return values.
+       addParams := func(list []*ast.Field, isret bool) {
+               argnum := 0
+               for _, fld := range list {
+                       t := f.pkg.types[fld.Type].Type
+                       align := int(arch.sizes.Alignof(t))
+                       size := int(arch.sizes.Sizeof(t))
                        offset += -offset & (align - 1)
+                       cc := componentsOfType(arch, t)
 
-                       // Create variable for each name being declared with this type.
+                       // names is the list of names with this type.
+                       names := fld.Names
                        if len(names) == 0 {
-                               name := "unnamed"
-                               if decl.Type.Results != nil && len(decl.Type.Results.List) > 0 && &list[0] == &decl.Type.Results.List[0] && i == 0 {
-                                       // Assume assembly will refer to single unnamed result as r.
+                               // Anonymous args will be called arg, arg1, arg2, ...
+                               // Similarly so for return values: ret, ret1, ret2, ...
+                               name := "arg"
+                               if isret {
                                        name = "ret"
                                }
-                               names = []*ast.Ident{{Name: name}}
+                               if argnum > 0 {
+                                       name += strconv.Itoa(argnum)
+                               }
+                               names = []*ast.Ident{ast.NewIdent(name)}
                        }
+                       argnum += len(names)
+
+                       // Create variable for each name.
                        for _, id := range names {
                                name := id.Name
-                               addVar("", asmVar{
-                                       name: name,
-                                       kind: kind,
-                                       typ:  typ,
-                                       off:  offset,
-                                       size: size,
-                               })
-                               switch kind {
-                               case 8:
-                                       if arch.ptrSize == 4 {
-                                               w1, w2 := "lo", "hi"
-                                               if arch.bigEndian {
-                                                       w1, w2 = w2, w1
-                                               }
-                                               addVar(name, asmVar{
-                                                       name: name + "_" + w1,
-                                                       kind: 4,
-                                                       typ:  "half " + typ,
-                                                       off:  offset,
-                                                       size: 4,
-                                               })
-                                               addVar(name, asmVar{
-                                                       name: name + "_" + w2,
-                                                       kind: 4,
-                                                       typ:  "half " + typ,
-                                                       off:  offset + 4,
-                                                       size: 4,
-                                               })
+                               for _, c := range cc {
+                                       outer := name + c.outer
+                                       v := asmVar{
+                                               name: name + c.suffix,
+                                               kind: c.kind,
+                                               typ:  c.typ,
+                                               off:  offset + c.offset,
+                                               size: c.size,
+                                       }
+                                       if vo := fn.vars[outer]; vo != nil {
+                                               vo.inner = append(vo.inner, &v)
+                                       }
+                                       fn.vars[v.name] = &v
+                                       for i := 0; i < v.size; i++ {
+                                               fn.varByOffset[v.off+i] = &v
                                        }
-
-                               case asmEmptyInterface:
-                                       addVar(name, asmVar{
-                                               name: name + "_type",
-                                               kind: asmKind(arch.ptrSize),
-                                               typ:  "interface type",
-                                               off:  offset,
-                                               size: arch.ptrSize,
-                                       })
-                                       addVar(name, asmVar{
-                                               name: name + "_data",
-                                               kind: asmKind(arch.ptrSize),
-                                               typ:  "interface data",
-                                               off:  offset + arch.ptrSize,
-                                               size: arch.ptrSize,
-                                       })
-
-                               case asmInterface:
-                                       addVar(name, asmVar{
-                                               name: name + "_itable",
-                                               kind: asmKind(arch.ptrSize),
-                                               typ:  "interface itable",
-                                               off:  offset,
-                                               size: arch.ptrSize,
-                                       })
-                                       addVar(name, asmVar{
-                                               name: name + "_data",
-                                               kind: asmKind(arch.ptrSize),
-                                               typ:  "interface data",
-                                               off:  offset + arch.ptrSize,
-                                               size: arch.ptrSize,
-                                       })
-
-                               case asmSlice:
-                                       addVar(name, asmVar{
-                                               name: name + "_base",
-                                               kind: asmKind(arch.ptrSize),
-                                               typ:  "slice base",
-                                               off:  offset,
-                                               size: arch.ptrSize,
-                                       })
-                                       addVar(name, asmVar{
-                                               name: name + "_len",
-                                               kind: asmKind(arch.intSize),
-                                               typ:  "slice len",
-                                               off:  offset + arch.ptrSize,
-                                               size: arch.intSize,
-                                       })
-                                       addVar(name, asmVar{
-                                               name: name + "_cap",
-                                               kind: asmKind(arch.intSize),
-                                               typ:  "slice cap",
-                                               off:  offset + arch.ptrSize + arch.intSize,
-                                               size: arch.intSize,
-                                       })
-
-                               case asmString:
-                                       addVar(name, asmVar{
-                                               name: name + "_base",
-                                               kind: asmKind(arch.ptrSize),
-                                               typ:  "string base",
-                                               off:  offset,
-                                               size: arch.ptrSize,
-                                       })
-                                       addVar(name, asmVar{
-                                               name: name + "_len",
-                                               kind: asmKind(arch.intSize),
-                                               typ:  "string len",
-                                               off:  offset + arch.ptrSize,
-                                               size: arch.intSize,
-                                       })
                                }
                                offset += size
                        }
@@ -517,18 +510,15 @@ func (f *File) asmParseDecl(decl *ast.FuncDecl) map[string]*asmFunc {
                        varByOffset: make(map[int]*asmVar),
                }
                offset = 0
-               addParams(decl.Type.Params.List)
+               addParams(decl.Type.Params.List, false)
                if decl.Type.Results != nil && len(decl.Type.Results.List) > 0 {
-                       offset += -offset & (arch.maxAlign - 1)
-                       addParams(decl.Type.Results.List)
+                       offset += -offset & (arch.maxAlign() - 1)
+                       addParams(decl.Type.Results.List, true)
                }
                fn.size = offset
                m[arch.name] = fn
        }
 
-       if failed {
-               return nil
-       }
        return m
 }
 
@@ -649,11 +639,13 @@ func asmCheckVar(badf func(string, ...interface{}), fn *asmFunc, line, expr stri
        }
 
        vk := v.kind
+       vs := v.size
        vt := v.typ
        switch vk {
        case asmInterface, asmEmptyInterface, asmString, asmSlice:
                // allow reference to first word (pointer)
                vk = v.inner[0].kind
+               vs = v.inner[0].size
                vt = v.inner[0].typ
        }
 
@@ -687,6 +679,6 @@ func asmCheckVar(badf func(string, ...interface{}), fn *asmFunc, line, expr stri
                                fmt.Fprintf(&inner, "%s+%d(FP)", vi.name, vi.off)
                        }
                }
-               badf("invalid %s of %s; %s is %d-byte value%s", op, expr, vt, vk, inner.String())
+               badf("invalid %s of %s; %s is %d-byte value%s", op, expr, vt, vs, inner.String())
        }
 }
index 81947102ec83f6663a60271786f700caceacd554..3f9275c008bc87bc0e5e9302899837de400dd290 100644 (file)
@@ -8,6 +8,12 @@
 
 package testdata
 
+type S struct {
+       i int32
+       b bool
+       s string
+}
+
 func arg1(x int8, y uint8)
 func arg2(x int16, y uint16)
 func arg4(x int32, y uint32)
@@ -19,6 +25,9 @@ func argslice(x, y []string)
 func argiface(x interface{}, y interface {
        m()
 })
+func argcomplex(x complex64, y complex128)
+func argstruct(x S, y struct{})
+func argarray(x [2]S)
 func returnint() int
 func returnbyte(x int) byte
 func returnnamed(x byte) (r1 int, r2 int16, r3 string, r4 byte)
index 2c6f13b137c1cd24e2622db4226f5906f3edec34..bc8cbc2e798bef5fd393d0c2c23811842498682d 100644 (file)
@@ -221,6 +221,49 @@ TEXT ·argiface(SB),0,$0-32
        MOVQ    y_data+24(FP), AX
        RET
 
+TEXT ·argcomplex(SB),0,$24 // ERROR "wrong argument size 0; expected \$\.\.\.-24"
+       MOVSS   x+0(FP), X0 // ERROR "invalid MOVSS of x\+0\(FP\); complex64 is 8-byte value containing x_real\+0\(FP\) and x_imag\+4\(FP\)"
+       MOVSD   x+0(FP), X0 // ERROR "invalid MOVSD of x\+0\(FP\); complex64 is 8-byte value containing x_real\+0\(FP\) and x_imag\+4\(FP\)"
+       MOVSS   x_real+0(FP), X0
+       MOVSD   x_real+0(FP), X0 // ERROR "invalid MOVSD of x_real\+0\(FP\); real\(complex64\) is 4-byte value"
+       MOVSS   x_real+4(FP), X0 // ERROR "invalid offset x_real\+4\(FP\); expected x_real\+0\(FP\)"
+       MOVSS   x_imag+4(FP), X0
+       MOVSD   x_imag+4(FP), X0 // ERROR "invalid MOVSD of x_imag\+4\(FP\); imag\(complex64\) is 4-byte value"
+       MOVSS   x_imag+8(FP), X0 // ERROR "invalid offset x_imag\+8\(FP\); expected x_imag\+4\(FP\)"
+       MOVSD   y+8(FP), X0 // ERROR "invalid MOVSD of y\+8\(FP\); complex128 is 16-byte value containing y_real\+8\(FP\) and y_imag\+16\(FP\)"
+       MOVSS   y_real+8(FP), X0 // ERROR "invalid MOVSS of y_real\+8\(FP\); real\(complex128\) is 8-byte value"
+       MOVSD   y_real+8(FP), X0
+       MOVSS   y_real+16(FP), X0 // ERROR "invalid offset y_real\+16\(FP\); expected y_real\+8\(FP\)"
+       MOVSS   y_imag+16(FP), X0 // ERROR "invalid MOVSS of y_imag\+16\(FP\); imag\(complex128\) is 8-byte value"
+       MOVSD   y_imag+16(FP), X0
+       MOVSS   y_imag+24(FP), X0 // ERROR "invalid offset y_imag\+24\(FP\); expected y_imag\+16\(FP\)"
+       RET
+
+TEXT ·argstruct(SB),0,$64 // ERROR "wrong argument size 0; expected \$\.\.\.-24"
+       MOVQ    x+0(FP), AX // ERROR "invalid MOVQ of x\+0\(FP\); testdata.S is 24-byte value"
+       MOVQ    x_i+0(FP), AX // ERROR "invalid MOVQ of x_i\+0\(FP\); int32 is 4-byte value"
+       MOVQ    x_b+0(FP), AX // ERROR "invalid offset x_b\+0\(FP\); expected x_b\+4\(FP\)"
+       MOVQ    x_s+8(FP), AX
+       MOVQ    x_s_base+8(FP), AX
+       MOVQ    x_s+16(FP), AX // ERROR "invalid offset x_s\+16\(FP\); expected x_s\+8\(FP\), x_s_base\+8\(FP\), or x_s_len\+16\(FP\)"
+       MOVQ    x_s_len+16(FP), AX
+       RET
+
+TEXT ·argarray(SB),0,$64 // ERROR "wrong argument size 0; expected \$\.\.\.-48"
+       MOVQ    x+0(FP), AX // ERROR "invalid MOVQ of x\+0\(FP\); \[2\]testdata.S is 48-byte value"
+       MOVQ    x_0_i+0(FP), AX // ERROR "invalid MOVQ of x_0_i\+0\(FP\); int32 is 4-byte value"
+       MOVQ    x_0_b+0(FP), AX // ERROR "invalid offset x_0_b\+0\(FP\); expected x_0_b\+4\(FP\)"
+       MOVQ    x_0_s+8(FP), AX
+       MOVQ    x_0_s_base+8(FP), AX
+       MOVQ    x_0_s+16(FP), AX // ERROR "invalid offset x_0_s\+16\(FP\); expected x_0_s\+8\(FP\), x_0_s_base\+8\(FP\), or x_0_s_len\+16\(FP\)"
+       MOVQ    x_0_s_len+16(FP), AX
+       MOVB    foo+25(FP), AX // ERROR "unknown variable foo; offset 25 is x_1_i\+24\(FP\)"
+       MOVQ    x_1_s+32(FP), AX
+       MOVQ    x_1_s_base+32(FP), AX
+       MOVQ    x_1_s+40(FP), AX // ERROR "invalid offset x_1_s\+40\(FP\); expected x_1_s\+32\(FP\), x_1_s_base\+32\(FP\), or x_1_s_len\+40\(FP\)"
+       MOVQ    x_1_s_len+40(FP), AX
+       RET
+
 TEXT ·returnint(SB),0,$0-8
        MOVB    AX, ret+0(FP) // ERROR "invalid MOVB of ret\+0\(FP\); int is 8-byte value"
        MOVW    AX, ret+0(FP) // ERROR "invalid MOVW of ret\+0\(FP\); int is 8-byte value"
index 52f6a94d46300f3ac855bb5f693d0c4c31e1f396..985ff502459e91b748940b262c8e80ac266c0f1f 100644 (file)
@@ -106,7 +106,7 @@ TEXT runtime·raiseproc(SB),NOSPLIT,$24
        MOVW    $SYS_getpid, R12
        SWI     $0x80
        // arg 1 pid already in R0 from getpid
-       MOVW    unnamed+0(FP), R1       // arg 2 - signal
+       MOVW    arg+0(FP), R1   // arg 2 - signal
        MOVW    $1, R2  // arg 3 - posix
        MOVW    $SYS_kill, R12
        SWI $0x80
index 6dee611fbdacc56c56da72ea2263922fa5f52ce1..bc7a90b4d97b81255fd2659037498d67b2032567 100644 (file)
@@ -131,7 +131,7 @@ TEXT runtime·plan9_tsemacquire(SB),NOSPLIT,$0-12
 TEXT runtime·nsec(SB),NOSPLIT,$-4-12
        MOVW    $SYS_NSEC, R0
        SWI     0
-       MOVW    unnamed+0(FP), R1
+       MOVW    arg+0(FP), R1
        MOVW    0(R1), R0
        MOVW    R0, ret_lo+4(FP)
        MOVW    4(R1), R0