Find file History
mmcloughlin operand: include '+0' in named symbol references
Intended to address an asmdecl error.

  [amd64] Butterfly: use of unnamed argument 0(FP); offset 0 is x0+0(FP)

Updates #24
Latest commit 475a241 Jan 13, 2019
Type Name Latest commit message Commit time
Failed to load latest commit information.
stub.go doc: README for args example Jan 1, 2019


Demonstrates how to reference function parameters in avo.


Use Param() to reference arguments by name. The Load() function can be used to load the argument into a register (this will select the correct MOV instruction for you). Likewise Store and ReturnIndex can be used to write the return value. The following function will return its second argument.

	TEXT("Second", NOSPLIT, "func(x, y int32) int32")
	y := Load(Param("y"), GP32())
	Store(y, ReturnIndex(0))

This avo code will generate the following assembly. Note that parameter references are named to conform to asmdecl rules enforced by go vet.

// func Second(x int32, y int32) int32
TEXT ·Second(SB), NOSPLIT, $0-12
	MOVL y+4(FP), AX
	MOVL AX, ret+8(FP)

Primitive types can be loaded as above. Other types consist of sub-components which must be loaded into registers independently; for example strings, slices, arrays, structs and complex values.

Strings and Slices

Strings and slices actually consist of multiple components under the hood: see reflect.StringHeader and reflect.SliceHeader. The following avo code allows you to load the string length.

	TEXT("StringLen", NOSPLIT, "func(s string) int")
	strlen := Load(Param("s").Len(), GP64())
	Store(strlen, ReturnIndex(0))

The same code would work for a slice argument. Likewise Param(...).Base() and Param(...).Cap() will load the base pointer and capacity (slice only).

Array Indexing

Arrays can be indexed with the Index() method. For example, the following returns the third element of the passed array.

	TEXT("ArrayThree", NOSPLIT, "func(a [7]uint64) uint64")
	a3 := Load(Param("a").Index(3), GP64())
	Store(a3, ReturnIndex(0))

Struct Fields

Struct fields can be accessed with the Field() method. Note that this requires the package to be specified, so that avo can parse the type definition. In this example we specify the package with the line:


This package contains the struct definition:

type Struct struct {
	Byte       byte
	Int8       int8
	Uint16     uint16
	Int32      int32
	Uint64     uint64
	Float32    float32
	Float64    float64
	String     string
	Slice      []Sub
	Array      [5]Sub
	Complex64  complex64
	Complex128 complex128

The following function will return the Float64 field from this struct.

	TEXT("FieldFloat64", NOSPLIT, "func(s Struct) float64")
	f64 := Load(Param("s").Field("Float64"), XMM())
	Store(f64, ReturnIndex(0))

Complex Values

Complex types complex{64,128} are actually just pairs of float{32,64} values. These can be accessed with the Real() and Imag() methods. For example the following function returns the imaginary part of the Complex64 struct field.

	TEXT("FieldComplex64Imag", NOSPLIT, "func(s Struct) float32")
	c64i := Load(Param("s").Field("Complex64").Imag(), XMM())
	Store(c64i, ReturnIndex(0))

Nested Data Structures

The above methods may be composed to reference arbitrarily nested data structures. For example, the following returns s.Array[2].B[2].

	TEXT("FieldArrayTwoBTwo", NOSPLIT, "func(s Struct) byte")
	b2 := Load(Param("s").Field("Array").Index(2).Field("B").Index(2), GP8())
	Store(b2, ReturnIndex(0))