gpt4 book ai didi

c - LLVM:为什么在构建调用时会出现段错误?

转载 作者:行者123 更新时间:2023-12-04 17:36:49 26 4
gpt4 key购买 nike

我正在使用 LLVM 的 C API。我想我必须使用 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 次运行中就有一次,这不是段错误。所以我插入了代码来查找 LLVMTypeKind变量 call , 这是一个不同的 LLVMTypeKind来自 f 的返回类型.我认为不应该。

最佳答案

事实证明,与其使用 LLVMBuildBitCast,不如使用 LLVMConstIntToPtr。从 LLVMBuildBitCast 出来的东西看起来像一个函数指针,但在某种程度上已经损坏。

关于c - LLVM:为什么在构建调用时会出现段错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56391122/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com