I'm trying to write some SIMD mostly for learning purposes. I know Go can link assembly, but I can't get it to work correctly.
Here's the most minimal example I can make (element-wise vector multiplication):
vec_amd64.s (note: the actual file has a whitespace line under RET
since it causes errors otherwise)
// func mul(v1, v2 Vec4) Vec4
TEXT .mul(SB),4,$0-48
MOVUPS v1+0(FP), X0
MOVUPS v2+16(FP), X1
MULPS X1, X0
// also tried ret+32 since I've seen some places do that
MOVUPS X0, toReturn+32(FP)
RET
vec.go
package simd
type Vec4 [4]float32
func (v1 Vec4) Mul(v2 Vec4) Vec4 {
return Vec4{v1[0] * v2[0], v1[1] * v2[1], v1[2] * v2[2], v1[3] * v2[3]}
}
func mul(v1, v2 Vec4) Vec4
simd_test.go
package simd
import (
"testing"
)
func TestMul(t *testing.T) {
v1 := Vec4{1, 2, 3, 4}
v2 := Vec4{5, 6, 7, 8}
res := v1.Mul(v2)
res2 := mul(v1, v2)
// Placeholder until I get it to compile
if res != res2 {
t.Fatalf("Expected %v; got %v", res, res2)
}
}
When I try to run go test
I get the error:
# testmain
simd.TestMul: call to external function simd.mul
simd.TestMul: undefined: simd.mul
The go env
command reports my GOHOSTARCH
to be amd64
and my Go version to be 1.3. To confirm it wasn't the architecture causing the problem, I found another package that uses assembly and deleted all the assembly files except the _amd64.s
one and its tests ran fine.
I also tried changing it to an exported identifier in case that was causing weirdness, but no dice. I think I pretty closely followed the template in packages like math/big
, so hopefully it's something simple and obvious that I'm missing.
I know that Go is at least trying to use the assembly because if I introduce a syntax error to the .s file the build tool will complain about it.
Edit:
To be clear, go build
will compile cleanly, but go test
causes the error to appear.