Go没有链接我的汇编:未定义的外部函数。

huangapple go评论85阅读模式
英文:

Go isn't linking my assembly: undefined external function

问题

我正在尝试编写一些SIMD代码,主要是为了学习目的。我知道Go可以链接汇编代码,但我无法使其正常工作。

这是我能做的最简单的示例(逐元素向量乘法):

vec_amd64.s(注意:实际文件在RET下面有一个空白行,否则会导致错误)

// 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
    // 也尝试过 ret+32,因为我在某些地方看到过这样的写法
    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)

    // 在编译成功之前,这里只是一个占位符
    if res != res2 {
        t.Fatalf("Expected %v; got %v", res, res2)
    }
}

当我尝试运行go test时,我得到以下错误:

# testmain
simd.TestMul: 调用外部函数 simd.mul
simd.TestMul: 未定义: simd.mul

go env命令报告我的GOHOSTARCHamd64,我的Go版本为1.3。为了确认不是架构引起的问题,我找到了另一个使用汇编的包,并删除了除_amd64.s文件以外的所有汇编文件,测试运行正常。

我还尝试将其更改为导出标识符,以防止出现奇怪的问题,但没有成功。我认为我几乎按照math/big等包中的模板进行了操作,所以希望我漏掉的是一些简单明显的东西。

我知道Go至少尝试使用汇编,因为如果我在.s文件中引入语法错误,构建工具会报错。

编辑:

明确一下,go build可以编译通过,但go test会导致出现错误。

英文:

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.

答案1

得分: 96

你正在使用错误的点符号。将

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

改为

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

一切都会正常工作。

英文:

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.

huangapple
  • 本文由 发表于 2014年8月23日 18:30:01
  • 转载请务必保留本文链接:https://go.coder-hub.com/25460967.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定