| //===-- go-llvm-cabi-irbuilders.h - IR builder helper classes -------------===// |
| // |
| // Copyright 2018 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // Assorted helper classes for IR building. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef LLVMGOFRONTEND_GO_LLVM_IRBUILDER_H |
| #define LLVMGOFRONTEND_GO_LLVM_IRBUILDER_H |
| |
| #include "go-llvm-bexpression.h" |
| |
| #include "llvm/IR/IRBuilder.h" |
| |
| class NameGen; |
| |
| // Generic "no insert" builder |
| typedef llvm::IRBuilder<> LIRBuilder; |
| |
| // Insertion helper for Bexpressions; inserts any instructions |
| // created by IRBuilder into the specified Bexpression's inst list. |
| |
| class BexprInserter : public llvm::IRBuilderDefaultInserter { |
| public: |
| BexprInserter() : expr_(nullptr) { } |
| void setDest(Bexpression *expr) { assert(!expr_); expr_ = expr; } |
| |
| void InsertHelper(llvm::Instruction *I, const llvm::Twine &Name, |
| llvm::BasicBlock *BB, |
| llvm::BasicBlock::iterator InsertPt) const { |
| assert(expr_); |
| expr_->appendInstruction(I); |
| I->setName(Name); |
| } |
| |
| private: |
| mutable Bexpression *expr_; |
| }; |
| |
| // Builder that appends to a specified Bexpression |
| |
| class BexprLIRBuilder : |
| public llvm::IRBuilder<llvm::ConstantFolder, BexprInserter> { |
| typedef llvm::IRBuilder<llvm::ConstantFolder, BexprInserter> IRBuilderB; |
| public: |
| BexprLIRBuilder(llvm::LLVMContext &context, Bexpression *expr) : |
| IRBuilderB(context, llvm::ConstantFolder()) { |
| getInserter().setDest(expr); |
| } |
| }; |
| |
| // Many of the methods in the LLVM IRBuilder class (ex: CreateMemCpy) |
| // assume that you are appending to an existing basic block (which is |
| // typically not what we want to do in many cases in the bridge code). |
| // Furthermore it is required that the block in question be already |
| // parented within an llvm::Function (the IRBuilder code relies on |
| // being able to call getParent() to trace back up to the enclosing |
| // context). |
| // |
| // This builder works around this issue by creating a dummy basic |
| // block to capture any instructions generated, then when the builder |
| // is destroyed it detaches the instructions from the block so that |
| // they can be returned in a list. A dummy function has to be passed in |
| // as well in order to host the dummy BB, however the dummy block will |
| // be detached in the destructor. |
| |
| class BlockLIRBuilder : public LIRBuilder { |
| public: |
| BlockLIRBuilder(llvm::Function *dummyFcn, NameGen *namegen); |
| ~BlockLIRBuilder(); |
| |
| // Return the instructions generated by this builder. Note that |
| // this detaches them from the dummy block we emitted them into, |
| // hence is not intended to be invoked more than once. |
| std::vector<llvm::Instruction*> instructions(); |
| |
| private: |
| std::unique_ptr<llvm::BasicBlock> dummyBlock_; |
| NameGen *namegen_; |
| }; |
| |
| #endif // LLVMGOFRONTEND_GO_LLVM_IRBUILDER_H |