82

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.

peterSO
  • 158,998
  • 31
  • 281
  • 276
Linear
  • 21,074
  • 4
  • 59
  • 70
  • `go build` finished cleanly, `go test` fails. – Linear Aug 23 '14 at 11:22
  • 1
    How do you compile? You didn't answer the question. – fuz Aug 23 '14 at 11:29
  • I'm afraid I don't understand the question then. I compile using the `go` build tool. If there's an extra step that needs to be in there for assembly that very well may be the answer to my question, but if you're getting at something else I'm not sure what it is. – Linear Aug 23 '14 at 11:29
  • 1
    What commands did you enter from which directory relative to you source files? *I compile using the `go` build tool.* is very vague. It could mean anything. – fuz Aug 23 '14 at 11:31
  • I ran `go test` from `$GOPATH/src/simd`, which is the source directory. – Linear Aug 23 '14 at 11:32
  • The Go tool is rather simple and straightforward, I'm not sure what you're getting at. I'm not using advanced flags like coverage profiles or gcflags if that's what you're asking. – Linear Aug 23 '14 at 11:35
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/59853/discussion-between-fuzxxl-and-jsor). – fuz Aug 23 '14 at 11:40
  • 1
    There is a difference between calling `go build` and `go build foo.go`, etc. It might also be possible that you have funky settings in your `$GOPATH`, etc. The more you write about *what exactly* you did, the easier it is to help you. The best thing is to post transcripts of shell sessions instead of prosa. – fuz Aug 23 '14 at 11:42
  • Also, the `go` tool is not simple. It exposes all parts of the go build system through various subcommands and options. Any part of the Go building process can be fine-tuned with custom `go` commands. – fuz Aug 23 '14 at 11:43
  • 12
    The Go language really seems to have a fetish for the mid-dot character. Related: [Slashes and dots in function names and prototypes?](http://stackoverflow.com/questions/13475908/slashes-and-dots-in-function-names-and-prototypes) – Cody Gray - on strike Aug 23 '14 at 13:28

1 Answers1

96

You are using the wrong dot. instead of

TEXT .mul(SB),4,$0-48

write

TEXT ·mul(SB),4,$0-48

and everything works just fine.

fuz
  • 88,405
  • 25
  • 200
  • 352
  • 11
    Well THAT was subtle, I did not notice that it was a mid-dot. Thanks. – Linear Aug 23 '14 at 11:43
  • 2
    It surprises many people. I didn't see it either on first glance. – fuz Aug 23 '14 at 11:44
  • 13
    How do people type that on an american QWERTY keyboard? Or is this not a common use-case, where you could just google the symbol as necessary? – Seiyria Aug 23 '14 at 15:31
  • 9
    [Like this](https://en.wikipedia.org/wiki/Interpunct#Keyboard_input). OSes that don't suck (i.e. not Windows) map unused layers of the QWERTY layout so that characters like the interpunct can be entered. – fuz Aug 23 '14 at 15:36
  • 7
    @FUZxxl FYI Alt-0183 (using the number-pad) still works for Windows. Not quite as nice, and usually difficult on laptops, but it works. – Intermernet Aug 24 '14 at 02:58
  • 4
    On linux (Ubuntu, at least) if you have the [compose key](http://en.wikipedia.org/wiki/Compose_key) enabled: `` `^` `.` = `·` – Izkata Aug 25 '14 at 19:41