Basic
IRBuilder 是用于帮助生成 LLVM IR 的类。 一个 module 和一个 LLVM context 是一一对应的关系。
IR Builder 在 module, function, basic block 中跟踪下一行指令的插入位置 ( 插入点 )。
它还可以插入对应 C 标准库函数的调用, 创建全局变量或函数,以及内联汇编代码。
要注意 IR Builder 不是线程安全的。 在多线程生成代码时, 每个线程都要分配独立的 context, module 和 IR Builder。
IRBuilderBase
这个类代码量有点大, 头文件中声明就用了 2000 多行...
属性
protected:
BasicBlock *BB;
BasicBlock::iterator InsertPt;
LLVMContext &Context;
const IRBuilderFolder &Folder;
const IRBuilderDefaultInserter &Inserter;
MDNode *DefaultFPMathTag;
FastMathFlags FMF;
bool IsFPConstrained = false;
fp::ExceptionBehavior DefaultConstrainedExcept = fp::ebStrict;
RoundingMode DefaultConstrainedRounding = RoundingMode::Dynamic;
ArrayRef<OperandBundleDef> DefaultOperandBundles;
private:
SmallVector<std::pair<unsigned, MDNode *>, 2> MetadataToCopy;
方法
可以分为以下几种:
- 构造函数
- 元属性相关
- 插入点相关
- debug 定位信息相关
- 生成 全局变量 的方法
- 生成 类型 的方法
- 生成 常量 的方法
- 生成 Intrinsic 的方法
- 生成 向量操作 的方法
- 生成 控制指令 的方法
- 生成 二元操作 的方法
- 生成 内存指令 的方法
- 生成 类型转换操作 的方法
- 生成比较指令的方法
- 生成其它指令的方法
插入点相关
/// Clear the insertion point: created instructions will not be
/// inserted into a block.
void ClearInsertionPoint() {
BB = nullptr;
InsertPt = BasicBlock::iterator();
}
BasicBlock *GetInsertBlock() const { return BB; }
BasicBlock::iterator GetInsertPoint() const { return InsertPt; }
还有一系列 SetInsertPoint 的变体和重载
/// This specifies that created instructions should be appended to the
/// end of the specified block.
void SetInsertPoint(BasicBlock *TheBB) {
BB = TheBB;
InsertPt = BB->end();
}
/// This specifies that created instructions should be inserted before
/// the specified instruction.
void SetInsertPoint(Instruction *I) {
BB = I->getParent();
InsertPt = I->getIterator();
assert(InsertPt != BB->end() && "Can't read debug loc from end()");
SetCurrentDebugLocation(I->getStableDebugLoc());
}
/// This specifies that created instructions should be inserted at the
/// specified point.
void SetInsertPoint(BasicBlock *TheBB, BasicBlock::iterator IP) {
BB = TheBB;
InsertPt = IP;
if (IP != TheBB->end())
SetCurrentDebugLocation(IP->getStableDebugLoc());
}
/// This specifies that created instructions should be inserted at
/// the specified point, but also requires that \p IP is dereferencable.
void SetInsertPoint(BasicBlock::iterator IP) {
BB = IP->getParent();
InsertPt = IP;
SetCurrentDebugLocation(IP->getStableDebugLoc());
}
/// This specifies that created instructions should inserted at the beginning
/// end of the specified function, but after already existing static alloca
/// instructions that are at the start.
void SetInsertPointPastAllocas(Function *F) {
BB = &F->getEntryBlock();
InsertPt = BB->getFirstNonPHIOrDbgOrAlloca();
}
/// Returns the current insert point.
InsertPoint saveIP() const {
return InsertPoint(GetInsertBlock(), GetInsertPoint());
}
/// Returns the current insert point, clearing it in the process.
InsertPoint saveAndClearIP() {
InsertPoint IP(GetInsertBlock(), GetInsertPoint());
ClearInsertionPoint();
return IP;
}
/// Sets the current insert point to a previously-saved location.
void restoreIP(InsertPoint IP) {
if (IP.isSet())
SetInsertPoint(IP.getBlock(), IP.getPoint());
else
ClearInsertionPoint();
}
Insert
可以看出泛泛的三种插入情况: 指令, 常量, 变量。 所有的插入操作, 都是以这 3 种 insert 为基础操作的。
/// Insert and return the specified instruction.
template<typename InstTy>
InstTy *Insert(InstTy *I, const Twine &Name = "") const {
Inserter.InsertHelper(I, Name, BB, InsertPt);
AddMetadataToInst(I);
return I;
}
/// No-op overload to handle constants.
Constant *Insert(Constant *C, const Twine& = "") const {
return C;
}
Value *Insert(Value *V, const Twine &Name = "") const {
if (Instruction *I = dyn_cast<Instruction>(V))
return Insert(I, Name);
assert(isa<Constant>(V));
return V;
}
IRBuilder
类声明
template <typename FolderTy = ConstantFolder,
typename InserterTy = IRBuilderDefaultInserter>
class IRBuilder : public IRBuilderBase {...}
继承了 IRBuilderBase
属性 ( 不包含父类的属性)
private:
FolderTy Folder;
InserterTy Inserter;