doc: README for args example
Also started a README in the root examples directory. Updates #14
This commit is contained in:
6
examples/README.md
Normal file
6
examples/README.md
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
# Examples
|
||||||
|
|
||||||
|
Feature demonstrations:
|
||||||
|
|
||||||
|
* **[add](add):** Add two numbers. The "Hello World!" of `avo`.
|
||||||
|
* **[args](args):** Loading function arguments.
|
||||||
117
examples/args/README.md
Normal file
117
examples/args/README.md
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
# args
|
||||||
|
|
||||||
|
Demonstrates how to reference function parameters in `avo`.
|
||||||
|
|
||||||
|
## Basics
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
[embedmd]:# (asm.go go /.*TEXT.*Second/ /RET.*/)
|
||||||
|
```go
|
||||||
|
TEXT("Second", "func(x, y int32) int32")
|
||||||
|
y := Load(Param("y"), GP32v())
|
||||||
|
Store(y, ReturnIndex(0))
|
||||||
|
RET()
|
||||||
|
```
|
||||||
|
|
||||||
|
This `avo` code will generate the following assembly. Note that parameter references are named to conform to [`asmdecl`](https://godoc.org/golang.org/x/tools/go/analysis/passes/asmdecl) rules enforced by `go vet`.
|
||||||
|
|
||||||
|
[embedmd]:# (args.s s /.*func Second/ /RET/)
|
||||||
|
```s
|
||||||
|
// func Second(x int32, y int32) int32
|
||||||
|
TEXT ·Second(SB), $0-12
|
||||||
|
MOVL y+4(FP), AX
|
||||||
|
MOVL AX, ret+8(FP)
|
||||||
|
RET
|
||||||
|
```
|
||||||
|
|
||||||
|
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`](https://golang.org/pkg/reflect/#StringHeader) and [`reflect.SliceHeader`](https://golang.org/pkg/reflect/#SliceHeader). The following `avo` code allows you to load the string length.
|
||||||
|
|
||||||
|
[embedmd]:# (asm.go go /.*TEXT.*StringLen/ /RET.*/)
|
||||||
|
```go
|
||||||
|
TEXT("StringLen", "func(s string) int")
|
||||||
|
strlen := Load(Param("s").Len(), GP64v())
|
||||||
|
Store(strlen, ReturnIndex(0))
|
||||||
|
RET()
|
||||||
|
```
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
[embedmd]:# (asm.go go /.*TEXT.*ArrayThree/ /RET.*/)
|
||||||
|
```go
|
||||||
|
TEXT("ArrayThree", "func(a [7]uint64) uint64")
|
||||||
|
a3 := Load(Param("a").Index(3), GP64v())
|
||||||
|
Store(a3, ReturnIndex(0))
|
||||||
|
RET()
|
||||||
|
```
|
||||||
|
|
||||||
|
## 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:
|
||||||
|
|
||||||
|
[embedmd]:# (asm.go go /.*Package\(.*/)
|
||||||
|
```go
|
||||||
|
Package("github.com/mmcloughlin/avo/examples/args")
|
||||||
|
```
|
||||||
|
|
||||||
|
This package contains the struct definition:
|
||||||
|
|
||||||
|
[embedmd]:# (args.go go /type Struct/ /^}/)
|
||||||
|
```go
|
||||||
|
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.
|
||||||
|
|
||||||
|
[embedmd]:# (asm.go go /.*TEXT.*FieldFloat64/ /RET.*/)
|
||||||
|
```go
|
||||||
|
TEXT("FieldFloat64", "func(s Struct) float64")
|
||||||
|
f64 := Load(Param("s").Field("Float64"), Xv())
|
||||||
|
Store(f64, ReturnIndex(0))
|
||||||
|
RET()
|
||||||
|
```
|
||||||
|
|
||||||
|
## 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.
|
||||||
|
|
||||||
|
[embedmd]:# (asm.go go /.*TEXT.*FieldComplex64Imag/ /RET.*/)
|
||||||
|
```go
|
||||||
|
TEXT("FieldComplex64Imag", "func(s Struct) float32")
|
||||||
|
c64i := Load(Param("s").Field("Complex64").Imag(), Xv())
|
||||||
|
Store(c64i, ReturnIndex(0))
|
||||||
|
RET()
|
||||||
|
```
|
||||||
|
|
||||||
|
## 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]`.
|
||||||
|
|
||||||
|
[embedmd]:# (asm.go go /.*TEXT.*FieldArrayTwoBTwo/ /RET.*/)
|
||||||
|
```go
|
||||||
|
TEXT("FieldArrayTwoBTwo", "func(s Struct) byte")
|
||||||
|
b2 := Load(Param("s").Field("Array").Index(2).Field("B").Index(2), GP8v())
|
||||||
|
Store(b2, ReturnIndex(0))
|
||||||
|
RET()
|
||||||
|
```
|
||||||
@@ -1,5 +1,11 @@
|
|||||||
// Code generated by command: go run asm.go -out args.s -stubs stub.go. DO NOT EDIT.
|
// Code generated by command: go run asm.go -out args.s -stubs stub.go. DO NOT EDIT.
|
||||||
|
|
||||||
|
// func Second(x int32, y int32) int32
|
||||||
|
TEXT ·Second(SB), $0-12
|
||||||
|
MOVL y+4(FP), AX
|
||||||
|
MOVL AX, ret+8(FP)
|
||||||
|
RET
|
||||||
|
|
||||||
// func StringLen(s string) int
|
// func StringLen(s string) int
|
||||||
TEXT ·StringLen(SB), $0-24
|
TEXT ·StringLen(SB), $0-24
|
||||||
MOVQ s_len+8(FP), AX
|
MOVQ s_len+8(FP), AX
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ func TestFunctionsEqual(t *testing.T) {
|
|||||||
cases := []struct {
|
cases := []struct {
|
||||||
f, g interface{}
|
f, g interface{}
|
||||||
}{
|
}{
|
||||||
|
{Second, func(x, y int32) int32 { return y }},
|
||||||
{StringLen, func(s string) int { return len(s) }},
|
{StringLen, func(s string) int { return len(s) }},
|
||||||
{SliceLen, func(s []int) int { return len(s) }},
|
{SliceLen, func(s []int) int { return len(s) }},
|
||||||
{SliceCap, func(s []int) int { return cap(s) }},
|
{SliceCap, func(s []int) int { return cap(s) }},
|
||||||
|
|||||||
@@ -9,6 +9,11 @@ import (
|
|||||||
func main() {
|
func main() {
|
||||||
Package("github.com/mmcloughlin/avo/examples/args")
|
Package("github.com/mmcloughlin/avo/examples/args")
|
||||||
|
|
||||||
|
TEXT("Second", "func(x, y int32) int32")
|
||||||
|
y := Load(Param("y"), GP32v())
|
||||||
|
Store(y, ReturnIndex(0))
|
||||||
|
RET()
|
||||||
|
|
||||||
TEXT("StringLen", "func(s string) int")
|
TEXT("StringLen", "func(s string) int")
|
||||||
strlen := Load(Param("s").Len(), GP64v())
|
strlen := Load(Param("s").Len(), GP64v())
|
||||||
Store(strlen, ReturnIndex(0))
|
Store(strlen, ReturnIndex(0))
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
package args
|
package args
|
||||||
|
|
||||||
|
func Second(x int32, y int32) int32
|
||||||
|
|
||||||
func StringLen(s string) int
|
func StringLen(s string) int
|
||||||
|
|
||||||
func SliceLen(s []int) int
|
func SliceLen(s []int) int
|
||||||
|
|||||||
Reference in New Issue
Block a user