@@ -68,6 +68,9 @@ class IRBuilder : public IRBuilderBase {
68
68
#endif
69
69
{}
70
70
71
+ // / Defined below.
72
+ class SavedInsertionPointRAII ;
73
+
71
74
// / Determines if the current location is apparently reachable. The
72
75
// / invariant we maintain is that the insertion point of the builder
73
76
// / always points within a block unless the current location is
@@ -345,6 +348,72 @@ class IRBuilder : public IRBuilderBase {
345
348
}
346
349
return result;
347
350
}
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
+ }
348
417
};
349
418
350
419
} // end namespace irgen
0 commit comments