Skip to content

Commit 5a90f5c

Browse files
committed
[irgen] Implement irgen::IRBuilder::SavedInsertionPointRAII.
This is ported from the SavedInsertionPointRAII at the SIL level. I thought that I needed this to accomplish some of my recent work, but I was wrong. Still seemed useful enough to upstream it.
1 parent 781a90c commit 5a90f5c

File tree

1 file changed

+69
-0
lines changed

1 file changed

+69
-0
lines changed

lib/IRGen/IRBuilder.h

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,9 @@ class IRBuilder : public IRBuilderBase {
6868
#endif
6969
{}
7070

71+
/// Defined below.
72+
class SavedInsertionPointRAII;
73+
7174
/// Determines if the current location is apparently reachable. The
7275
/// invariant we maintain is that the insertion point of the builder
7376
/// always points within a block unless the current location is
@@ -345,6 +348,72 @@ class IRBuilder : public IRBuilderBase {
345348
}
346349
return result;
347350
}
351+
352+
bool insertingAtEndOfBlock() const {
353+
assert(hasValidIP() && "Must have insertion point to ask about it");
354+
return InsertPt == BB->end();
355+
}
356+
};
357+
358+
/// Given a Builder as input to its constructor, this class resets the Builder
359+
/// so it has the same insertion point at end of scope.
360+
class IRBuilder::SavedInsertionPointRAII {
361+
IRBuilder &builder;
362+
PointerUnion<llvm::Instruction *, llvm::BasicBlock *> savedInsertionPoint;
363+
364+
public:
365+
/// Constructor that saves a Builder's insertion point without changing the
366+
/// builder's underlying insertion point.
367+
SavedInsertionPointRAII(IRBuilder &inputBuilder)
368+
: builder(inputBuilder), savedInsertionPoint() {
369+
// If our builder does not have a valid insertion point, just put nullptr
370+
// into SavedIP.
371+
if (!builder.hasValidIP()) {
372+
savedInsertionPoint = static_cast<llvm::BasicBlock *>(nullptr);
373+
return;
374+
}
375+
376+
// If we are inserting into the end of the block, stash the insertion block.
377+
if (builder.insertingAtEndOfBlock()) {
378+
savedInsertionPoint = builder.GetInsertBlock();
379+
return;
380+
}
381+
382+
// Otherwise, stash the instruction.
383+
auto *i = &*builder.GetInsertPoint();
384+
savedInsertionPoint = i;
385+
}
386+
387+
SavedInsertionPointRAII(IRBuilder &b, llvm::Instruction *newInsertionPoint)
388+
: SavedInsertionPointRAII(b) {
389+
builder.SetInsertPoint(newInsertionPoint);
390+
}
391+
392+
SavedInsertionPointRAII(IRBuilder &b, llvm::BasicBlock *block,
393+
llvm::BasicBlock::iterator iter)
394+
: SavedInsertionPointRAII(b) {
395+
builder.SetInsertPoint(block, iter);
396+
}
397+
398+
SavedInsertionPointRAII(IRBuilder &b, llvm::BasicBlock *insertionBlock)
399+
: SavedInsertionPointRAII(b) {
400+
builder.SetInsertPoint(insertionBlock);
401+
}
402+
403+
SavedInsertionPointRAII(const SavedInsertionPointRAII &) = delete;
404+
SavedInsertionPointRAII &operator=(const SavedInsertionPointRAII &) = delete;
405+
SavedInsertionPointRAII(SavedInsertionPointRAII &&) = delete;
406+
SavedInsertionPointRAII &operator=(SavedInsertionPointRAII &&) = delete;
407+
408+
~SavedInsertionPointRAII() {
409+
if (savedInsertionPoint.isNull()) {
410+
builder.ClearInsertionPoint();
411+
} else if (savedInsertionPoint.is<llvm::Instruction *>()) {
412+
builder.SetInsertPoint(savedInsertionPoint.get<llvm::Instruction *>());
413+
} else {
414+
builder.SetInsertPoint(savedInsertionPoint.get<llvm::BasicBlock *>());
415+
}
416+
}
348417
};
349418

350419
} // end namespace irgen

0 commit comments

Comments
 (0)