问题
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 oflvalue
from the symbol table. You can check the type ofrvalue
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