我一直试图通过 LLVM 让 .NET CIL 在多个平台上运行(我对 GPU 特别感兴趣)。我使用Mono.Compiler将 CIL 转换为 LLVM。
我无法让 AMDGCN 正常工作。对于一个简单的添加功能,我得到以下翻译后的 IR:
; ModuleID = 'bitout.bc'
source_filename = "llvmmodule_1"
define i32 @llvmmodule_1_AddMethod(i32, i32) {
entry:
%A0 = alloca i32
store i32 %0, i32* %A0
%A1 = alloca i32
store i32 %1, i32* %A1
%T0 = load i32, i32* %A0
%T1 = load i32, i32* %A1
%T2 = add i32 %T0, %T1
ret i32 %T2
}
我试过直接通过 libLLVM 的 TargetMachineEmitTo{File, MemoryBuffer} 以及间接通过 llc 发出它。
直接发射会产生一个 SIGSEGV:
Thread 1 "mono" received signal SIGSEGV, Segmentation fault.
0x00007fffeddadb1a in llvm::AMDGPUInstPrinter::getRegisterName(unsigned int) () from /usr/lib/libLLVM.so
这似乎是由于上述函数中的(负)缓冲区溢出(据我从 gdb 得知)。
llc 在 amdgcn 和 r600 上都失败了:
Allocation instruction pointer not in the stack address space!
%A0 = alloca i32
Allocation instruction pointer not in the stack address space!
%A1 = alloca i32
否则,llc 对于所有其他平台(wasm64 除外)都可以正常编译。
经过一番挖掘,我一直想知道这是否可能是因为没有在 alloca 中指定地址空间(尽管在AMDGPU 的 LLVM 指南中并没有真正解释这一点);所以我得到了翻译后的 IR 的副本并更改了地址空间。事实证明,如果分配在私有地址空间中,llc 会编译它——我猜它是作为堆栈空间工作的。但是我觉得很奇怪,尽管全局地址空间和区域地址空间都不起作用 - 我不应该能够在全局内存中分配空间吗?我在这里想念什么?
同样,我找不到创建采用地址空间的 alloca 指令的方法(BuildAlloca 不采用地址空间作为参数,我找不到任何提及替代方案的文档或示例)。
如果重要的话,我在 ArchLinux 上使用默认的 libLLVM(此时,llvm 8.0.1)。