我试图通过clang
将两个* .c文件编译为LLVM位代码,使用llvm-link
将它们链接在一起,并从中制作一个* .wasm文件。我通过https://github.com/yurydelendik/wasmception
这很好,直到我在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中的错误吗?
答案 0 :(得分:3)
通读这些github问题,似乎memcpy
内在函数当前不受WASM后端支持:
https://github.com/WebAssembly/design/issues/236
https://github.com/WebAssembly/design/issues/1003
作为一种解决方法,您可以指示clang使用-fno-builtin
禁用内部扩展,以便生成的代码将调用实际的memcpy
函数。