Files
avo/examples/fnv1a
Michael McLoughlin f295bde84c pass: ensure frame pointer register is saved (#174)
Currently `avo` uses `BP` as a standard general-purpose register. However, `BP` is used for the frame pointer and should be callee-save. Under some circumstances, the Go assembler will do this automatically, but not always. At the moment `avo` can produce code that clobbers the `BP` register. Since Go 1.16 this code will also fail a new `go vet` check.

This PR provides a (currently sub-optimal) fix for the issue. It introduces an `EnsureBasePointerCalleeSaved` pass which will check if the base pointer is written to by a function, and if so will artificially ensure that the function has a non-zero frame size. This will trigger the Go assembler to automatically save and restore the BP register.

In addition, we update the `asmdecl` tool to `asmvet`, which includes the `framepointer` vet check.

Updates #156
2021-04-18 18:37:56 -07:00
..
2019-01-06 20:04:51 -08:00
2019-01-13 10:12:52 -08:00
2018-12-27 23:09:44 -08:00

fnv1a

FNV-1a in avo.

const (
	OffsetBasis = 0xcbf29ce484222325
	Prime       = 0x100000001b3
)

func main() {
	TEXT("Hash64", NOSPLIT, "func(data []byte) uint64")
	Doc("Hash64 computes the FNV-1a hash of data.")
	ptr := Load(Param("data").Base(), GP64())
	n := Load(Param("data").Len(), GP64())

	h := RAX
	MOVQ(Imm(OffsetBasis), h)
	p := GP64()
	MOVQ(Imm(Prime), p)

	Label("loop")
	CMPQ(n, Imm(0))
	JE(LabelRef("done"))
	b := GP64()
	MOVBQZX(Mem{Base: ptr}, b)
	XORQ(b, h)
	MULQ(p)
	INCQ(ptr)
	DECQ(n)

	JMP(LabelRef("loop"))
	Label("done")
	Store(h, ReturnIndex(0))
	RET()
	Generate()
}