我正在尝试使用llvm编写类似c语言的编译器用于教育目的。
到目前为止,它进展顺利,但我经常遇到缺乏实际使用文档的问题。我发现的例子相当薄,clang有点过于复杂,因为它包含了c ++中所有可能的特性。
当为变量声明生成代码并初始化它时,我使用具有已知类型的AllocaInst,因为该语言是强类型的。另一方面,我也有用于初始化右手表达式的代码生成,我目前还不知道所需的类型。
分配如下:
llvm::AllocaInst *alloc = new llvm::AllocaInst(generateType(varDecl->getType()), varDecl->identifier().c_str(), block);
然后我在右侧生成表达式,对于一个简单的整数,我最终调用它:llvm::ConstantInt::get(llvm::Type::getInt32Ty(m_context), decExpr->value(), block);
我的问题是,当我调用store指令时,如果变量是在8位上声明并且表达式的值使用32位类型(即使它可能适合8位),我可能会遇到问题:{{ 1}}
我的第一个想法是检查类型和转换,但这对于一个适合的值来说似乎是多余的。另一个想法是在生成右手表达式时传递一个类型提示,并使用该类型生成我的常量整数,但这似乎是一个黑客,我试图避免这些。
我的问题是:处理这个问题最合理的方法是什么?我目前还不知道任何论坛/ IRC频道可以帮助处于类似情况的人,所以我们将不胜感激。
答案 0 :(得分:-1)
LLVM will require your L-value and R-value types to match so you need to be explicit about whether it's e.g. i8 or i32 in each assignment case.
Assuming you don't want the compiler to generate code that may silently truncate the value (risk losing data without emitting a warning), you'll need to ensure the L-value is at least as wide as the R-value requires.
If on the other hand the L-value is wider than the R-value, you'll need to extend the R-value before storing it.
One tip is to use LLVM's casting op-codes for scalars, e.g:
Instruction::CastOps cop = CastInst::getCastOpcode( srcValue, srcSigned, dstLlvmType, dstSigned );
Value* newSrcVal = builder->CreateCast( cop, srcValue, dstLlvmType, "" );