从概念上讲,我想做的事情非常简单。我使用与Alloca technique described in the Kaleidoscope example配对的mem2reg来减少手动创建Phi节点的需要。
我已经实现了我的自定义语言的几个方面,但是我遇到了以通用方式实现后递增/递减的问题。
我的AST节点PostIncrDecrNode
包含一个表示++
或--
的标记和一个表达式AST节点,该节点被编码为返回llvm::Value*
,就像Kaleidoscope示例一样。我已经注意到我可能需要返回llvm::Value*
以外的其他东西,因为我的语言非常安全,我需要知道诸如整数类型的符号之类的东西,但现在我觉得我可能还需要跟踪llvm::AllocaInst
。
一个简单的示例情况是这样的代码:
int myfunction(int i)
{
return i++;
}
我的调试AST打印如下所示:
- CompilationUnit:test.str
- FunctionDeclarationNode
- IdentifierNode:int
- IdentifierNode:myfunction
- FunctionParameterNode
- IdentifierNode:int
- IdentifierNode:i
- BlockNode
- ReturnNode
- PostIncrDecrNode
- IdentifierNode:i
最后两行是相关部分,因为我有一个PostIncrDecrNode
,其中包含IdentifierNode
,代码如下:
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;
}
第SharedSymbolEntry entry = context.getSymbolInScopeByName(*value);
行使用shared_ptr
的{{1}} std::String
'值'成员(又称变量名称)来查找我的IdentifierNode
(只是一个包装器类型,用于在上下文堆栈中存储语言特定信息以及SharedSymbolEntry
llvm::Value*
),该堆栈由函数参数或变量AST节点填充入口块分配。
问题是,llvm::AllocaInst*
无法访问alloca,只能访问负载PostIncrDecrNode
中返回的llvm::Value*
。
LLVM中是否有任何方法可以解析rtn = builder->CreateLoad(val, value->c_str());
中的llvm::AllocaInst*
以便在存储指令中使用它(存储指令需要一个指针,在这种情况下我只有整数值) )?
我遇到了一些类似的问题,但我不确定他们是否回答了我的问题。 最后一个似乎暗示这可能根本不可能,所以我很好奇别人如何解决这个问题。
答案 0 :(得分:1)
当您返回llvm::Value*
时(在您的情况下,它是LoadInst*
),您可以使用LLVM RTTI系统将llvm:Value*
强制转换为llvm::LoadInst*
,如下所示:
Value* val = someFunction(...);
if (llvm::LoadInst* I = dyn_cast<llvm::LoadInst>(val)
{
// do something with the load instruction I
}
else // not a load instruction
如果有llvm::LoadInst*
,您可以使用getPointerOperand()轻松访问加载发生的地址。
现在,您可以尝试将指针操作数强制转换回AllocaInst*
,如上例所示。如果成功,则会有AllocaInst
,当它失效时,它就是其他内容(例如GetElementPtrInst
)。