@@ -615,6 +615,96 @@ class OpBuilder : public Builder {
615615 Block::iterator insertPoint;
616616};
617617
618+ // / ImplicitLocOpBuilder maintains a 'current location', allowing use of the
619+ // / create<> method without specifying the location. It is otherwise the same
620+ // / as OpBuilder.
621+ class ImplicitLocOpBuilder : public mlir ::OpBuilder {
622+ public:
623+ // / OpBuilder has a bunch of convenience constructors - we support them all
624+ // / with the additional Location.
625+ template <typename ... T>
626+ ImplicitLocOpBuilder (Location loc, T &&...operands)
627+ : OpBuilder(std::forward<T>(operands)...), curLoc(loc) {}
628+
629+ // / Create a builder and set the insertion point to before the first operation
630+ // / in the block but still inside the block.
631+ static ImplicitLocOpBuilder atBlockBegin (Location loc, Block *block,
632+ Listener *listener = nullptr ) {
633+ return ImplicitLocOpBuilder (loc, block, block->begin (), listener);
634+ }
635+
636+ // / Create a builder and set the insertion point to after the last operation
637+ // / in the block but still inside the block.
638+ static ImplicitLocOpBuilder atBlockEnd (Location loc, Block *block,
639+ Listener *listener = nullptr ) {
640+ return ImplicitLocOpBuilder (loc, block, block->end (), listener);
641+ }
642+
643+ // / Create a builder and set the insertion point to before the block
644+ // / terminator.
645+ static ImplicitLocOpBuilder atBlockTerminator (Location loc, Block *block,
646+ Listener *listener = nullptr ) {
647+ auto *terminator = block->getTerminator ();
648+ assert (terminator != nullptr && " the block has no terminator" );
649+ return ImplicitLocOpBuilder (loc, block, Block::iterator (terminator),
650+ listener);
651+ }
652+
653+ // / Accessors for the implied location.
654+ Location getLoc () const { return curLoc; }
655+ void setLoc (Location loc) { curLoc = loc; }
656+
657+ // We allow clients to use the explicit-loc version of create as well.
658+ using OpBuilder::create;
659+ using OpBuilder::createOrFold;
660+
661+ // / Create an operation of specific op type at the current insertion point and
662+ // / location.
663+ template <typename OpTy, typename ... Args>
664+ OpTy create (Args &&...args) {
665+ return OpBuilder::create<OpTy>(curLoc, std::forward<Args>(args)...);
666+ }
667+
668+ // / Create an operation of specific op type at the current insertion point,
669+ // / and immediately try to fold it. This functions populates 'results' with
670+ // / the results after folding the operation.
671+ template <typename OpTy, typename ... Args>
672+ void createOrFold (llvm::SmallVectorImpl<Value> &results, Args &&...args) {
673+ OpBuilder::createOrFold<OpTy>(results, curLoc, std::forward<Args>(args)...);
674+ }
675+
676+ // / Overload to create or fold a single result operation.
677+ template <typename OpTy, typename ... Args>
678+ std::enable_if_t <OpTy::template hasTrait<mlir::OpTrait::OneResult>(), Value>
679+ createOrFold (Args &&...args) {
680+ return OpBuilder::createOrFold<OpTy>(curLoc, std::forward<Args>(args)...);
681+ }
682+
683+ // / Overload to create or fold a zero result operation.
684+ template <typename OpTy, typename ... Args>
685+ std::enable_if_t <OpTy::template hasTrait<mlir::OpTrait::ZeroResults>(), OpTy>
686+ createOrFold (Args &&...args) {
687+ return OpBuilder::createOrFold<OpTy>(curLoc, std::forward<Args>(args)...);
688+ }
689+
690+ // / This builder can also be used to emit diagnostics to the current location.
691+ mlir::InFlightDiagnostic
692+ emitError (const llvm::Twine &message = llvm::Twine()) {
693+ return mlir::emitError (curLoc, message);
694+ }
695+ mlir::InFlightDiagnostic
696+ emitWarning (const llvm::Twine &message = llvm::Twine()) {
697+ return mlir::emitWarning (curLoc, message);
698+ }
699+ mlir::InFlightDiagnostic
700+ emitRemark (const llvm::Twine &message = llvm::Twine()) {
701+ return mlir::emitRemark (curLoc, message);
702+ }
703+
704+ private:
705+ Location curLoc;
706+ };
707+
618708} // namespace mlir
619709
620710#endif
0 commit comments