Than McIntosh | 9cff07b | 2017-05-18 14:24:02 -0400 | [diff] [blame] | 1 | //===-- go-llvm-cabi-irbuilders.h - IR builder helper classes -------------===// |
| 2 | // |
| 3 | // The LLVM Compiler Infrastructure |
| 4 | // |
| 5 | // This file is distributed under the University of Illinois Open Source |
| 6 | // License. See LICENSE.TXT for details. |
| 7 | // |
| 8 | //===----------------------------------------------------------------------===// |
| 9 | // |
| 10 | // Assorted helper classes for IR building. |
| 11 | // |
| 12 | //===----------------------------------------------------------------------===// |
| 13 | |
| 14 | #ifndef LLVMGOFRONTEND_GO_LLVM_IRBUILDER_H |
| 15 | #define LLVMGOFRONTEND_GO_LLVM_IRBUILDER_H |
| 16 | |
| 17 | #include "go-llvm-bexpression.h" |
| 18 | |
| 19 | #include "llvm/IR/IRBuilder.h" |
| 20 | |
| 21 | class NameGen; |
| 22 | |
| 23 | // Generic "no insert" builder |
| 24 | typedef llvm::IRBuilder<> LIRBuilder; |
| 25 | |
Than McIntosh | bcbffd7 | 2017-06-02 09:17:23 -0400 | [diff] [blame] | 26 | // Insertion helper for Bexpressions; inserts any instructions |
| 27 | // created by IRBuilder into the specified Bexpression's inst list. |
| 28 | |
Than McIntosh | 9cff07b | 2017-05-18 14:24:02 -0400 | [diff] [blame] | 29 | class BexprInserter { |
| 30 | public: |
| 31 | BexprInserter() : expr_(nullptr) { } |
| 32 | void setDest(Bexpression *expr) { assert(!expr_); expr_ = expr; } |
| 33 | |
| 34 | void InsertHelper(llvm::Instruction *I, const llvm::Twine &Name, |
| 35 | llvm::BasicBlock *BB, |
| 36 | llvm::BasicBlock::iterator InsertPt) const { |
| 37 | assert(expr_); |
| 38 | expr_->appendInstruction(I); |
| 39 | I->setName(Name); |
| 40 | } |
| 41 | |
| 42 | private: |
| 43 | mutable Bexpression *expr_; |
| 44 | }; |
| 45 | |
| 46 | // Builder that appends to a specified Bexpression |
| 47 | |
| 48 | class BexprLIRBuilder : |
| 49 | public llvm::IRBuilder<llvm::ConstantFolder, BexprInserter> { |
| 50 | typedef llvm::IRBuilder<llvm::ConstantFolder, BexprInserter> IRBuilderBase; |
| 51 | public: |
| 52 | BexprLIRBuilder(llvm::LLVMContext &context, Bexpression *expr) : |
| 53 | IRBuilderBase(context, llvm::ConstantFolder()) { |
| 54 | setDest(expr); |
| 55 | } |
| 56 | }; |
| 57 | |
Than McIntosh | bcbffd7 | 2017-06-02 09:17:23 -0400 | [diff] [blame] | 58 | // Similar to the above, but adds to a Binstructions object. |
| 59 | |
Than McIntosh | 9cff07b | 2017-05-18 14:24:02 -0400 | [diff] [blame] | 60 | class BinstructionsInserter { |
| 61 | public: |
| 62 | BinstructionsInserter() : insns_(nullptr) { } |
| 63 | void setDest(Binstructions *insns) { assert(!insns_); insns_ = insns; } |
| 64 | |
| 65 | void InsertHelper(llvm::Instruction *I, const llvm::Twine &Name, |
| 66 | llvm::BasicBlock *BB, |
| 67 | llvm::BasicBlock::iterator InsertPt) const { |
| 68 | assert(insns_); |
| 69 | insns_->appendInstruction(I); |
| 70 | I->setName(Name); |
| 71 | } |
| 72 | |
| 73 | private: |
| 74 | mutable Binstructions *insns_; |
| 75 | }; |
| 76 | |
| 77 | // Builder that appends to a specified Binstructions object |
| 78 | |
| 79 | class BinstructionsLIRBuilder : |
| 80 | public llvm::IRBuilder<llvm::ConstantFolder, BinstructionsInserter> { |
| 81 | typedef llvm::IRBuilder<llvm::ConstantFolder, |
| 82 | BinstructionsInserter> IRBuilderBase; |
| 83 | public: |
| 84 | BinstructionsLIRBuilder(llvm::LLVMContext &context, Binstructions *insns) : |
| 85 | IRBuilderBase(context, llvm::ConstantFolder()) { |
| 86 | setDest(insns); |
| 87 | } |
| 88 | }; |
| 89 | |
Than McIntosh | bcbffd7 | 2017-06-02 09:17:23 -0400 | [diff] [blame] | 90 | // Some of the methods in the LLVM IRBuilder class (ex: CreateMemCpy) |
| 91 | // assume that you are appending to an existing basic block (which is |
| 92 | // typically not what we want to do in many cases in the bridge code). |
| 93 | // Furthermore it is required that the block in question be already |
| 94 | // parented within an llvm::Function (the IRBuilder code relies on |
| 95 | // being able to call getParent() to trace back up to the enclosing |
| 96 | // context). |
Than McIntosh | 9cff07b | 2017-05-18 14:24:02 -0400 | [diff] [blame] | 97 | // |
Than McIntosh | bcbffd7 | 2017-06-02 09:17:23 -0400 | [diff] [blame] | 98 | // This builder works around this issue by creating a dummy basic |
| 99 | // block to capture any instructions generated, then when the builder |
| 100 | // is destroyed it detaches the instructions from the block so that |
| 101 | // they can be returned in a list. A dummy function has to be passed in |
| 102 | // as well in order to host the dummy BB, however the dummy block will |
| 103 | // be detached in the destructor. |
Than McIntosh | 9cff07b | 2017-05-18 14:24:02 -0400 | [diff] [blame] | 104 | |
| 105 | class BlockLIRBuilder : public LIRBuilder { |
| 106 | public: |
Than McIntosh | bcbffd7 | 2017-06-02 09:17:23 -0400 | [diff] [blame] | 107 | BlockLIRBuilder(llvm::Function *dummyFcn, NameGen *namegen); |
| 108 | ~BlockLIRBuilder(); |
Than McIntosh | 9cff07b | 2017-05-18 14:24:02 -0400 | [diff] [blame] | 109 | |
| 110 | // Return the instructions generated by this builder. Note that |
| 111 | // this detaches them from the dummy block we emitted them into, |
| 112 | // hence is not intended to be invoked more than once. |
| 113 | std::vector<llvm::Instruction*> instructions(); |
| 114 | |
| 115 | private: |
| 116 | std::unique_ptr<llvm::BasicBlock> dummyBlock_; |
| 117 | NameGen *namegen_; |
| 118 | }; |
| 119 | |
| 120 | #endif // LLVMGOFRONTEND_GO_LLVM_IRBUILDER_H |