[英]LLVM: Why do I get segfaults when building calls?
我正在使用LLVM的C API。 我想我必須使用LLVMBuildCall
錯誤,因為我對它做的大部分調用LLVMBuildCall
錯誤的。 我發布了一個最小的例子,下面發生了這種情況。 但我有其他例子,我使用更復雜的LLVMBuildCall
調用,它不會段錯誤。
代碼有點長,但大部分是樣板; 也許去評論// Here's the function type we'll use
。 這是段錯誤的調用LLVMBuildCall(builder, f, params, PARAM_COUNT, "call")
。 這是代碼:
#include <stdio.h>
#include <llvm-c/Analysis.h>
#include <llvm-c/Core.h>
#include <llvm-c/Target.h>
#include <llvm-c/TargetMachine.h>
int
main() {
// a lot of setup...
LLVMInitializeNativeTarget();
LLVMInitializeNativeAsmPrinter();
char* triple = LLVMGetDefaultTargetTriple();
char* error;
LLVMTargetRef target_ref;
if (LLVMGetTargetFromTriple(triple, &target_ref, &error)) {
printf("Error: %s\n", error);
return 1;
}
LLVMTargetMachineRef tm_ref = LLVMCreateTargetMachine(
target_ref,
triple,
"",
"",
LLVMCodeGenLevelDefault,
LLVMRelocStatic,
LLVMCodeModelJITDefault);
LLVMDisposeMessage(triple);
LLVMContextRef context = LLVMContextCreate();
LLVMModuleRef module = LLVMModuleCreateWithNameInContext("module_name", context);
LLVMBuilderRef builder = LLVMCreateBuilderInContext(context);
LLVMTypeRef i64t = LLVMInt64TypeInContext(context);
const int PARAM_COUNT = 1;
LLVMTypeRef param_types[PARAM_COUNT] = {
i64t,
};
// Here's the function type we'll use
LLVMTypeRef func_type = LLVMFunctionType(i64t, param_types, PARAM_COUNT, 0);
// start building it
LLVMValueRef func = LLVMAddFunction(module, "func1", func_type);
LLVMBasicBlockRef entry = LLVMAppendBasicBlockInContext(context, func, "entry");
LLVMPositionBuilderAtEnd(builder, entry);
LLVMValueRef c = LLVMConstInt(i64t, 0, 0);
// If I try to call, I get a seg fault
LLVMValueRef f = LLVMBuildBitCast(builder, c, func_type, "cast");
LLVMValueRef params[PARAM_COUNT];
for (int i = 0; i < PARAM_COUNT; i++) {
params[i] = LLVMGetParam(f, i);
}
LLVMValueRef call = LLVMBuildCall(builder, f, params, PARAM_COUNT, "call");
LLVMBuildRet(builder, call);
// but if I comment the above and uncomment this, it works fine
// LLVMBuildRet(builder, c);
LLVMVerifyModule(module, LLVMAbortProcessAction, &error);
LLVMDisposeMessage(error);
}
以及我如何運行它:
$ llvm-config --version
8.0.0
$ clang++ trash.cpp `llvm-config --cflags --ldflags` `llvm-config --libs` `llvm-config --system-libs`
$ ./a.out
Segmentation fault: 11
FWIW,當我運行valgrind的memcheck時,我得到了這個(有額外的東西被剪掉):
==58974== Invalid read of size 8
==58974== at 0x10084DA72: llvm::Use* llvm::copy<llvm::ArrayRef<llvm::Value*>&, llvm::Use*>(llvm::ArrayRef<llvm::Value*>&, llvm::Use*) (in ./a.out)
==58974== by 0x10084D9E2: llvm::CallInst::init(llvm::FunctionType*, llvm::Value*, llvm::ArrayRef<llvm::Value*>, llvm::ArrayRef<llvm::OperandBundleDefT<llvm::Value*> >, llvm::Twine const&) (in ./a.out)
==58974== by 0x100814CCA: llvm::CallInst::Create(llvm::FunctionType*, llvm::Value*, llvm::ArrayRef<llvm::Value*>, llvm::ArrayRef<llvm::OperandBundleDefT<llvm::Value*> >, llvm::Twine const&, llvm::Instruction*) (in ./a.out)
==58974== by 0x1008137FD: llvm::IRBuilder<llvm::ConstantFolder, llvm::IRBuilderDefaultInserter>::CreateCall(llvm::FunctionType*, llvm::Value*, llvm::ArrayRef<llvm::Value*>, llvm::Twine const&, llvm::MDNode*) (in ./a.out)
==58974== by 0x1008137B9: LLVMBuildCall (in ./a.out)
==58974== by 0x10000281A: main (trash.cpp:62)
==58974== Address 0x0 is not stack'd, malloc'd or (recently) free'd
所以我想有些東西正在訪問空指針。
還有一點信息:每20次運行中就有一次,這不是段錯誤。 所以我插入代碼來查找變量call
的LLVMTypeKind
,它是與f
的返回類型不同的LLVMTypeKind
。 我認為不應該這樣。
事實證明,我應該使用LLVMBuildBitCast
,而不是使用LLVMConstIntToPtr
。 LLVMBuildBitCast
的東西看起來像一個函數指針,但在某種程度上被破壞了。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.