Conceptually what I would like to do is pretty simple. I am using the Alloca technique described in the Kaleidoscope example paired with mem2reg to reduce the need to manually create Phi nodes.
I have implemented several aspects of my custom language, but I have ran into a problem with implementing post increment/decrement in a generic way.
My AST node PostIncrDecrNode
contains a token to denote ++
or --
and an expression AST node that is codegened to return an llvm::Value*
much like the Kaleidoscope example. I have already noticed that I will likely need to return something other then an llvm::Value*
as my language is very type safe and I need to know things such as signedness of integral types, but now I feel that I may also need to keep track of the llvm::AllocaInst
.
A simple example situation is code like this:
int myfunction(int i)
{
return i++;
}
My debug AST print looks like this:
- CompilationUnit:test.str
- FunctionDeclarationNode
- IdentifierNode:int
- IdentifierNode:myfunction
- FunctionParameterNode
- IdentifierNode:int
- IdentifierNode:i
- BlockNode
- ReturnNode
- PostIncrDecrNode
- IdentifierNode:i
The last two lines are the relevant part here as I have a PostIncrDecrNode
that contains an IdentifierNode
that will be codegened like this:
Value* IdentifierNode::codeGenInternal(CodeGenContext& context)
{
Value* rtn = NULL;
SharedSymbolEntry entry = context.getSymbolInScopeByName(*value);
Value* val = entry ? entry->llvmVal : NULL;
if(val)
{
IRBuilder<>* builder = context.getIRBuilder();
rtn = builder->CreateLoad(val, value->c_str());
}
else
{
context.handleCodeGenError(*this, "Unknown variable name: " + Twine(value->c_str()));
}
return rtn;
}
The line SharedSymbolEntry entry = context.getSymbolInScopeByName(*value);
uses the stored shared_ptr
to std::String
'value' member of the IdentifierNode
(aka the variable name) to look up my SharedSymbolEntry
(just a wrapper type to store language specific information along with the llvm::Value*
which is the llvm::AllocaInst*
) in the context stack which is populated with entry block allocas by function parameters or variable AST nodes.
The problem is that the PostIncrDecrNode
doesn't have access to the alloca, only the returned llvm::Value*
from the load rtn = builder->CreateLoad(val, value->c_str());
.
Is there any way in LLVM to resolve the llvm::AllocaInst*
from the llvm::Value*
in order to use it in a store instruction (the store instruction needs a pointer and I only have the integral value in this case)?
I ran into a few similar questions, but I'm not sure if they answer my question. The last one seems to suggest that this may not be possible at all so I would be curious how others have solved this problem.
When you are returning a llvm::Value*
(in your case it is a LoadInst*
) you can cast the llvm:Value*
to llvm::LoadInst*
using the the LLVM RTTI system like this:
Value* val = someFunction(...);
if (llvm::LoadInst* I = dyn_cast<llvm::LoadInst>(val)
{
// do something with the load instruction I
}
else // not a load instruction
When have your llvm::LoadInst*
you can easily access the address where the load has happened with getPointerOperand().
Now you can try to cast the pointer operand back to an AllocaInst*
as in the example above. If it succeeds you have your AllocaInst
, when it failes it is something else (e.g. a GetElementPtrInst
).