// If the value was stack-assigned, returns the single
// abiStep describing that translation, and nil otherwise.
func (a *abiSeq) addArg(t *rtype) *abiStep {
+ // We'll always be adding a new value, so do that first.
pStart := len(a.steps)
a.valueStart = append(a.valueStart, pStart)
if t.size == 0 {
a.stackBytes = align(a.stackBytes, uintptr(t.align))
return nil
}
+ // Hold a copy of "a" so that we can roll back if
+ // register assignment fails.
+ aOld := *a
if !a.regAssign(t, 0) {
- a.steps = a.steps[:pStart]
+ // Register assignment failed. Roll back any changes
+ // and stack-assign.
+ *a = aOld
a.stackAssign(t.size, uintptr(t.align))
return &a.steps[len(a.steps)-1]
}
passStruct13,
pass2Struct1,
passEmptyStruct,
+ passStruct10AndSmall,
} {
fn := reflect.ValueOf(fn)
t.Run(runtime.FuncForPC(fn.Pointer()).Name(), func(t *testing.T) {
return a, b, c
}
+// This test case forces a large argument to the stack followed by more
+// in-register arguments.
+//go:registerparams
+//go:noinline
+func passStruct10AndSmall(a Struct10, b byte, c uint) (Struct10, byte, uint) {
+ return a, b, c
+}
+
// Struct1 is a simple integer-only aggregate struct.
type Struct1 struct {
A, B, C uint