【问题标题】:How to do type checking with the LLVM C++ API?如何使用 LLVM C++ API 进行类型检查?
【发布时间】:2019-07-01 21:30:50
【问题描述】:

我刚开始学习 LLVM C++ API,对如何进行类型检查有点困惑。我的导师向我提供了一个关于在堆栈内存中存储变量的示例,如下所示:

llvm::AllocaInst *Alloca;
Alloca = llvm::Builder.CreateAlloca(llvm::IntegerType::get(getGlobalContext(), 32), nullptr, "variable_name");

我明白这一点,但在下一部分中,它将讨论在为变量赋值之前进行类型检查。 To assign a value in a Decaf statement of the type lvalue = rvalue you should get the location of lvalue from the symbol table. You can check the type of rvalue using the following API call:

const llvm::PointerType *ptrTy = rvalue->getType()->getPointerTo();
ptrTy == Alloca->getType()

我完全不明白为什么要进行类型检查。我已阅读文档,getPointerTo 返回一个 PointerType 对象。所以我的第一个问题是,Alloca 的 Type 对象是 IntegerType,那我们为什么要创建 PointerType 的对象呢?这对我来说似乎完全超出了左领域。

我的第二个问题是,为什么我们要将此 PointerType 对象与作为 IntegerType 对象的 Alloca Type 对象进行比较?是否存在某种 == 运算符重载?因为我正在搜索文档,但找不到任何文档。

【问题讨论】:

    标签: llvm llvm-c++-api


    【解决方案1】:

    您似乎正在关注this tutorial。您的问题缺少我在下面复制的一些有价值的上下文:

    例如,以下代码使用 LLVM API 创建一个 alloca 指令以在堆栈上存储整数(LLVM 类型 i32)。此存储空间用于存储值并从堆栈上的内存位置加载值。

    llvm::AllocaInst *Alloca; 
    // unlike CreateEntryBlockAlloca the following will 
    // create the alloca instr at the current insertion point
    // rather than at the start of the block
    Alloca = llvm::Builder.CreateAlloca(llvm::IntegerType::get(getGlobalContext(), 32), nullptr, "variable_name");
    

    然后您应该将此指针存储到符号表中 标识符 NAME。您可以使用 TYPE 访问指针 Alloca->getType() 当你想给这个位置赋值时。

    所以Alloca->getType() 为您提供了一个表示“指向i32 的指针”的PointerType 对象,特别是指向堆栈中为i32 分配的位置的指针。但是rvaluei32,而不是指向i32 的指针。即便如此,我们仍然可以使用Alloca->getType() 来比较lvalue (i32) 的类型,即rvalue 的类型:

    lvalue = rvalue 类型的 Decaf 语句中赋值 应该从符号表中获取lvalue 的位置。你可以检查 rvalue 的类型使用以下 API 调用:

    const llvm::PointerType *ptrTy = rvalue->getType()->getPointerTo();
    

    我们首先获取rvalue的类型。我们不能直接将其与lvalue 的类型进行比较,因为我们只有“指向lvalue 类型的指针”类型。所以我们要做的就是将从rvalue得到的类型对象转换为“rvalue类型的指针”——也就是我们将i32转换为*i32

    换句话说,如果我们要比较的只是*i32 类型,我们如何检查rvalue 是否具有i32 类型?答案是,我们只是将rvalue 的类型提升为指针类型,即取其i32 并使其成为指针*i32

    此时ptrTy 包含类型“指向rvalue 类型的指针”,而我们也知道Alloca->getType() 为我们提供了类型“指向lvalue 类型的指针”。为了将rvalue 分配给lvalue,我们检查这两种类型是否一致:

    并检查左值的 Alloca 位置的类型是否相同 类型:

    ptrTy == Alloca->getType()
    

    上面的表达式是条件表达式;如果类型相同,则为 true,否则为 false。假设这是真的,您可以像这样分配值:

    llvm::Value *val = Builder.CreateStore(rvalue, Alloca)
    

    【讨论】:

    • 我真正感到困惑的是const llvm::PointerType *ptrTy = rvalue->getType()->getPointerTo();。我一直在阅读文档,getPointerTo 创建了一个 PointerType 对象,为什么我们需要这样做?为什么不直接使用返回 Type 对象本身的 getType() 呢?为什么要获取右值的 Type 对象,然后从中创建一个 PointerType 对象呢?同样在相等检查中,检查两个指针​​是否相等如何让我们知道类型相等?这是指针指向的两个不同的对象,那么我们为什么要比较它们呢?
    • 如果您要求 alloca 为 48 位整数提供足够的空间,则 alloca 会返回一个指向 48 位整数的指针。自然alloca的返回值是指针类型的。
    • @girbic 我更新了我的答案,以澄清为什么我们得到的是右值的指针类型,而不仅仅是右值的类型。总之,是因为我们有左值类型的指针类型,即*i32,而不是左值的类型i32
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-11-20
    • 1970-01-01
    • 2020-07-13
    • 2018-10-30
    • 1970-01-01
    • 1970-01-01
    • 2020-03-20
    相关资源
    最近更新 更多