How to do type checking with the LLVM C++ API?

夙愿已清 提交于 2019-12-13 04:18:13

问题


I've just started learning the LLVM C++ API, and I'm a bit confused about how to do type checking. There's an example my instructor has provided to me about storing a variable in stack memory as follows:

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

I understand this, but in the next part it talks about type checking before assigning a value to a variable. 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()

I am utterly confused at why this needs to be done for type checking. I've read the documentation and getPointerTo returns a PointerType object. So my first question is, the Type object of Alloca is IntegerType, so why are we creating an object of PointerType? This seems completely out of left field to me.

The second question I have is, why are we then comparing this PointerType object with the Alloca Type object which is an IntegerType object? Is there some sort of == operator overloading? Because I was searching through the documentation and I couldn't find any.


回答1:


You appear to be following this tutorial. Your question is missing some valuable context which I reproduce below:

For example the following code uses the LLVM API to create an alloca instruction to store integers (LLVM type i32) on the stack. This storage space is used to store values and to load values from the memory locations on the stack.

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");

You should then store this pointer into the symbol table for the identifier NAME. You can access the pointer to the type TYPE using Alloca->getType() when you want to assign a value to this location.

So Alloca->getType() is providing you a PointerType object representing "pointer to i32," in particular a pointer to the location in the stack that was allocated for the i32. But rvalue is an i32, not a pointer to i32. Even so, we can still use Alloca->getType() to compare the type of the lvalue (i32) to something, namely the type of rvalue:

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();

We first obtain the type of rvalue. We can't compare it directly to the type of lvalue, because we only have the type "pointer to type of lvalue". So what we have to do is convert the type object obtained from rvalue to "pointer to type of rvalue"—that is, we convert it from i32 to a *i32.

In other words, how do we check that rvalue has type i32 if all we have to compare it to is the type *i32? The answer is, we just promote rvalue's type to a pointer type, i.e. take its i32 and make it a pointer *i32.

At this point ptrTy contains the type "pointer to type of rvalue", while we also know that Alloca->getType() gives us the type "pointer to type of lvalue." In order to assign the rvalue to lvalue, we check that these two types coincide:

And check that the type of the Alloca location for lvalue has the same type:

ptrTy == Alloca->getType()

The expression above is the conditional; it is true if the types are the same and false otherwise. Assuming it's true, you assign the values like so:

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


来源:https://stackoverflow.com/questions/56842706/how-to-do-type-checking-with-the-llvm-c-api

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!