llvm - 将 GetElementPtrInst 与包含多个值的 ArrayRef 一起使用时出现段错误

标签 llvm llvm-c++-api

我正在尝试使用 LLVM 和 C++ 编写一个玩具编译器。但每当我尝试创建具有多个索引的 GetElementPtrInst 时,就会出现段错误。 有关此说明的文档对我没有帮助 ( API-Documentation Language-Documentation )

我的 llvm 版本是 3.1,这是在 Arch Linux 上。刚刚在另一台 Arch 机器上测试了它并得到了同样的错误。

我做错了什么吗?

这是一个小的工作程序来说明我的问题。它可以通过以下方式编译:

g++ -o segfault_example segfault_example.cpp -Wall -Wextra -pedantic \
    `llvm-config --libs core jit native --cxxflags --ldflags`
#include <llvm/Module.h>
#include <llvm/Constants.h>
#include <llvm/DerivedTypes.h>
#include <llvm/LLVMContext.h>
#include <llvm/Instructions.h>
#include <llvm/Analysis/Verifier.h>
#include <llvm/ADT/ArrayRef.h>
#include <string>
#include <iostream>

static llvm::LLVMContext& global = llvm::getGlobalContext();
static llvm::Type* int32ty = llvm::Type::getInt32Ty(global);

llvm::ConstantInt* getInt32(int n)
{
    return llvm::ConstantInt::get(llvm::Type::getInt32Ty(global), n);
}

int main()
{
    //setup everything for a minimal example
    llvm::Module* mainModule = new llvm::Module("main", global);

    llvm::FunctionType* ftype = llvm::FunctionType::get(int32ty, false);

    llvm::Function* mainFunction = llvm::Function::Create(
        ftype, llvm::GlobalValue::InternalLinkage, "main", mainModule);

    llvm::BasicBlock* bblock = llvm::BasicBlock::Create(
        global, "entry", mainFunction, 0);

    llvm::AllocaInst* mem = new llvm::AllocaInst(llvm::Type::getInt32PtrTy(global, 0x1000)
        , getInt32(0x1000), 0x1000, "mem", bblock);

    //tests
    //this works
    std::cout << "Testing with one element vector" << std::endl;
    std::vector<llvm::Value*> vect_1;
    vect_1.push_back(getInt32(0));
    llvm::GetElementPtrInst* gep1 =
        llvm::GetElementPtrInst::CreateInBounds(mem, llvm::ArrayRef<llvm::Value*>(vect_1)
        , "retval", bblock);
    std::cout << "done" << std::endl;

    //this works too, but I can't find this signature in the documentation
    std::cout << "Testing with Value* instead of ArrayRef" << std::endl;
        llvm::GetElementPtrInst::CreateInBounds(mem, getInt32(0), "retval", bblock);
    std::cout << "done" << std::endl;

    //this segfaults
    std::cout << "Filling two element vector" << std::endl;
    std::vector<llvm::Value*> vect_2;
    vect_2.push_back(getInt32(0));
    vect_2.push_back(getInt32(1));
    std::cout << "Testing with two element vector" << std::endl;
    //segfault
    llvm::GetElementPtrInst* gep2 =
        llvm::GetElementPtrInst::CreateInBounds(mem, llvm::ArrayRef<llvm::Value*>(vect_2)
        , "retval", bblock);
    std::cout << "done" << std::endl;

    mainModule->dump();
    llvm::verifyFunction(*mainFunction);
}

最佳答案

发现错误。我会尝试解释原因和我的解决方案,但解释可能是错误的。

mem 的类型错误。 (就我而言)需要使用 new llvm::AllocaInst(llvm::ArrayType::get(int32ty, 100), "mem", bblock); 声明。创建两个间接级别 ( explanation why there are two indirections )。以前的类型只有一个间接寻址,因此使用 GetElementPtrInst 和两元素向量取消引用它不起作用。

我在玩 llvm in the browser 时注意到了这一点并发出 LLVM C++ Api 代码。

您可以在命令行上为 C 示例文件创建 C++ Api 代码,如下所示:

clang -c -emit-llvm -o ex.bf example.c
llc -march=cpp -o ex.cpp ex.bf

关于llvm - 将 GetElementPtrInst 与包含多个值的 ArrayRef 一起使用时出现段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11186052/

相关文章:

c++ - 如何在LLVM上提取完整的函数信息?

llvm - 通过LLVM API直接生成机器代码

c++ - 在哪里可以找到哪些 C++ API 对应于哪些 llvm 命令?

xcode - 使用已弃用的方法时在 Xcode 中显示自定义警告

c++ - LLVM 别名分析器奇怪的结果

LLVM。如何根据名称访问结构字段?

c++ - 使用 clang 共享库中的额外模块名称符号

llvm 内联 channel 不起作用

c++ - LLVM IR 代码生成段错误仅在方法声明具有参数时退出

gdb - clang 3.1 在 Ubuntu 12.04 上构建的二进制文件无法使用 gdb 进行调试