在C代码中使用memcpy并使用wasm目标进行编译时出现llvm-link错误

时间:2018-07-19 18:49:27

标签: clang llvm webassembly

我试图通过clang将两个* .c文件编译为LLVM位代码,使用llvm-link将它们链接在一起,并从中制作一个* .wasm文件。我通过https://github.com/yurydelendik/wasmception

提供的Makefile在计算机上构建了LLVM。

这很好,直到我在C代码中使用memcpy为止。然后llvm-link停止并显示错误:

Intrinsic has incorrect argument type!
void (i8*, i8*, i32, i1)* @llvm.memcpy.p0i8.p0i8.i32

以下是重现此问题的最小示例:

one.c

#define EXPORT __attribute__((visibility("default")))
#include <string.h>

char* some_str();

EXPORT void do_something() {
  char* cpy_src = some_str();
  char other_str[15];
  memcpy(other_str, cpy_src, strlen(cpy_src));
}

two.c

char* some_str() {
  return "Hello World";
}

执行以下命令:

$ clang --target=wasm32-unknown-unknown-wasm --sysroot=../wasmception/sysroot -S -emit-llvm -nostartfiles -fvisibility=hidden one.c -o one.bc
[...]
$ clang --target=wasm32-unknown-unknown-wasm --sysroot=../wasmception/sysroot -S -emit-llvm -nostartfiles -fvisibility=hidden two.c -o two.bc
[...]

请注意,没有进行任何优化,因为这将消除此处不必要的memcpy调用。正如我所说的,这是脱离上下文显示错误的最小示例。

$ llvm-link one.bc two.bc -o res.bc -v
Loading 'one.bc'
Linking in 'one.bc'
Loading 'two.bc'
Linking in 'two.bc'
Intrinsic has incorrect argument type!
void (i8*, i8*, i32, i1)* @llvm.memcpy.p0i8.p0i8.i32
llvm-link: error: linked module is broken!

当我在示例文件中注释掉memcpy调用时,错误消失了。当然,这不是我正在从事的实际项目中的选择。

我做错什么了吗?通常在WebAssembly上下文中使用memcpy是一个坏主意吗?这可能是LLVM / Clang中的错误吗?

1 个答案:

答案 0 :(得分:3)

通读这些github问题,似乎memcpy内在函数当前不受WASM后端支持:

https://github.com/WebAssembly/design/issues/236
https://github.com/WebAssembly/design/issues/1003

作为一种解决方法,您可以指示clang使用-fno-builtin禁用内部扩展,以便生成的代码将调用实际的memcpy函数。