|
| 1 | +//===- Context.h ------------------------------------------------*- C++ -*-===// |
| 2 | +// |
| 3 | +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| 4 | +// See https://llvm.org/LICENSE.txt for license information. |
| 5 | +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| 6 | +// |
| 7 | +//===----------------------------------------------------------------------===// |
| 8 | + |
| 9 | +#ifndef LLVM_SANDBOXIR_CONTEXT_H |
| 10 | +#define LLVM_SANDBOXIR_CONTEXT_H |
| 11 | + |
| 12 | +#include "llvm/IR/LLVMContext.h" |
| 13 | +#include "llvm/SandboxIR/Tracker.h" |
| 14 | +#include "llvm/SandboxIR/Type.h" |
| 15 | + |
| 16 | +namespace llvm::sandboxir { |
| 17 | + |
| 18 | +class Module; |
| 19 | +class Value; |
| 20 | +class Argument; |
| 21 | + |
| 22 | +class Context { |
| 23 | +protected: |
| 24 | + LLVMContext &LLVMCtx; |
| 25 | + friend class Type; // For LLVMCtx. |
| 26 | + friend class PointerType; // For LLVMCtx. |
| 27 | + friend class CmpInst; // For LLVMCtx. TODO: cleanup when sandboxir::VectorType |
| 28 | + // is complete |
| 29 | + friend class IntegerType; // For LLVMCtx. |
| 30 | + friend class StructType; // For LLVMCtx. |
| 31 | + friend class ::llvm::TargetExtType; // For LLVMCtx. |
| 32 | + friend class Region; // For LLVMCtx. |
| 33 | + |
| 34 | + Tracker IRTracker; |
| 35 | + |
| 36 | + /// Maps LLVM Value to the corresponding sandboxir::Value. Owns all |
| 37 | + /// SandboxIR objects. |
| 38 | + DenseMap<llvm::Value *, std::unique_ptr<Value>> LLVMValueToValueMap; |
| 39 | + |
| 40 | + /// Maps an LLVM Module to the corresponding sandboxir::Module. |
| 41 | + DenseMap<llvm::Module *, std::unique_ptr<Module>> LLVMModuleToModuleMap; |
| 42 | + |
| 43 | + /// Type has a protected destructor to prohibit the user from managing the |
| 44 | + /// lifetime of the Type objects. Context is friend of Type, and this custom |
| 45 | + /// deleter can destroy Type. |
| 46 | + struct TypeDeleter { |
| 47 | + void operator()(Type *Ty) { delete Ty; } |
| 48 | + }; |
| 49 | + /// Maps LLVM Type to the corresonding sandboxir::Type. Owns all Sandbox IR |
| 50 | + /// Type objects. |
| 51 | + DenseMap<llvm::Type *, std::unique_ptr<Type, TypeDeleter>> LLVMTypeToTypeMap; |
| 52 | + |
| 53 | + /// Remove \p V from the maps and returns the unique_ptr. |
| 54 | + std::unique_ptr<Value> detachLLVMValue(llvm::Value *V); |
| 55 | + /// Remove \p SBV from all SandboxIR maps and stop owning it. This effectively |
| 56 | + /// detaches \p V from the underlying IR. |
| 57 | + std::unique_ptr<Value> detach(Value *V); |
| 58 | + friend class Instruction; // For detach(). |
| 59 | + /// Take ownership of VPtr and store it in `LLVMValueToValueMap`. |
| 60 | + Value *registerValue(std::unique_ptr<Value> &&VPtr); |
| 61 | + friend class EraseFromParent; // For registerValue(). |
| 62 | + /// This is the actual function that creates sandboxir values for \p V, |
| 63 | + /// and among others handles all instruction types. |
| 64 | + Value *getOrCreateValueInternal(llvm::Value *V, llvm::User *U = nullptr); |
| 65 | + /// Get or create a sandboxir::Argument for an existing LLVM IR \p LLVMArg. |
| 66 | + Argument *getOrCreateArgument(llvm::Argument *LLVMArg); |
| 67 | + /// Get or create a sandboxir::Value for an existing LLVM IR \p LLVMV. |
| 68 | + Value *getOrCreateValue(llvm::Value *LLVMV) { |
| 69 | + return getOrCreateValueInternal(LLVMV, 0); |
| 70 | + } |
| 71 | + /// Get or create a sandboxir::Constant from an existing LLVM IR \p LLVMC. |
| 72 | + Constant *getOrCreateConstant(llvm::Constant *LLVMC) { |
| 73 | + return cast<Constant>(getOrCreateValueInternal(LLVMC, 0)); |
| 74 | + } |
| 75 | + // Friends for getOrCreateConstant(). |
| 76 | +#define DEF_CONST(ID, CLASS) friend class CLASS; |
| 77 | +#include "llvm/SandboxIR/SandboxIRValues.def" |
| 78 | + |
| 79 | + /// Create a sandboxir::BasicBlock for an existing LLVM IR \p BB. This will |
| 80 | + /// also create all contents of the block. |
| 81 | + BasicBlock *createBasicBlock(llvm::BasicBlock *BB); |
| 82 | + friend class BasicBlock; // For getOrCreateValue(). |
| 83 | + |
| 84 | + IRBuilder<ConstantFolder> LLVMIRBuilder; |
| 85 | + auto &getLLVMIRBuilder() { return LLVMIRBuilder; } |
| 86 | + |
| 87 | + VAArgInst *createVAArgInst(llvm::VAArgInst *SI); |
| 88 | + friend VAArgInst; // For createVAArgInst() |
| 89 | + FreezeInst *createFreezeInst(llvm::FreezeInst *SI); |
| 90 | + friend FreezeInst; // For createFreezeInst() |
| 91 | + FenceInst *createFenceInst(llvm::FenceInst *SI); |
| 92 | + friend FenceInst; // For createFenceInst() |
| 93 | + SelectInst *createSelectInst(llvm::SelectInst *SI); |
| 94 | + friend SelectInst; // For createSelectInst() |
| 95 | + InsertElementInst *createInsertElementInst(llvm::InsertElementInst *IEI); |
| 96 | + friend InsertElementInst; // For createInsertElementInst() |
| 97 | + ExtractElementInst *createExtractElementInst(llvm::ExtractElementInst *EEI); |
| 98 | + friend ExtractElementInst; // For createExtractElementInst() |
| 99 | + ShuffleVectorInst *createShuffleVectorInst(llvm::ShuffleVectorInst *SVI); |
| 100 | + friend ShuffleVectorInst; // For createShuffleVectorInst() |
| 101 | + ExtractValueInst *createExtractValueInst(llvm::ExtractValueInst *IVI); |
| 102 | + friend ExtractValueInst; // For createExtractValueInst() |
| 103 | + InsertValueInst *createInsertValueInst(llvm::InsertValueInst *IVI); |
| 104 | + friend InsertValueInst; // For createInsertValueInst() |
| 105 | + BranchInst *createBranchInst(llvm::BranchInst *I); |
| 106 | + friend BranchInst; // For createBranchInst() |
| 107 | + LoadInst *createLoadInst(llvm::LoadInst *LI); |
| 108 | + friend LoadInst; // For createLoadInst() |
| 109 | + StoreInst *createStoreInst(llvm::StoreInst *SI); |
| 110 | + friend StoreInst; // For createStoreInst() |
| 111 | + ReturnInst *createReturnInst(llvm::ReturnInst *I); |
| 112 | + friend ReturnInst; // For createReturnInst() |
| 113 | + CallInst *createCallInst(llvm::CallInst *I); |
| 114 | + friend CallInst; // For createCallInst() |
| 115 | + InvokeInst *createInvokeInst(llvm::InvokeInst *I); |
| 116 | + friend InvokeInst; // For createInvokeInst() |
| 117 | + CallBrInst *createCallBrInst(llvm::CallBrInst *I); |
| 118 | + friend CallBrInst; // For createCallBrInst() |
| 119 | + LandingPadInst *createLandingPadInst(llvm::LandingPadInst *I); |
| 120 | + friend LandingPadInst; // For createLandingPadInst() |
| 121 | + CatchPadInst *createCatchPadInst(llvm::CatchPadInst *I); |
| 122 | + friend CatchPadInst; // For createCatchPadInst() |
| 123 | + CleanupPadInst *createCleanupPadInst(llvm::CleanupPadInst *I); |
| 124 | + friend CleanupPadInst; // For createCleanupPadInst() |
| 125 | + CatchReturnInst *createCatchReturnInst(llvm::CatchReturnInst *I); |
| 126 | + friend CatchReturnInst; // For createCatchReturnInst() |
| 127 | + CleanupReturnInst *createCleanupReturnInst(llvm::CleanupReturnInst *I); |
| 128 | + friend CleanupReturnInst; // For createCleanupReturnInst() |
| 129 | + GetElementPtrInst *createGetElementPtrInst(llvm::GetElementPtrInst *I); |
| 130 | + friend GetElementPtrInst; // For createGetElementPtrInst() |
| 131 | + CatchSwitchInst *createCatchSwitchInst(llvm::CatchSwitchInst *I); |
| 132 | + friend CatchSwitchInst; // For createCatchSwitchInst() |
| 133 | + ResumeInst *createResumeInst(llvm::ResumeInst *I); |
| 134 | + friend ResumeInst; // For createResumeInst() |
| 135 | + SwitchInst *createSwitchInst(llvm::SwitchInst *I); |
| 136 | + friend SwitchInst; // For createSwitchInst() |
| 137 | + UnaryOperator *createUnaryOperator(llvm::UnaryOperator *I); |
| 138 | + friend UnaryOperator; // For createUnaryOperator() |
| 139 | + BinaryOperator *createBinaryOperator(llvm::BinaryOperator *I); |
| 140 | + friend BinaryOperator; // For createBinaryOperator() |
| 141 | + AtomicRMWInst *createAtomicRMWInst(llvm::AtomicRMWInst *I); |
| 142 | + friend AtomicRMWInst; // For createAtomicRMWInst() |
| 143 | + AtomicCmpXchgInst *createAtomicCmpXchgInst(llvm::AtomicCmpXchgInst *I); |
| 144 | + friend AtomicCmpXchgInst; // For createAtomicCmpXchgInst() |
| 145 | + AllocaInst *createAllocaInst(llvm::AllocaInst *I); |
| 146 | + friend AllocaInst; // For createAllocaInst() |
| 147 | + CastInst *createCastInst(llvm::CastInst *I); |
| 148 | + friend CastInst; // For createCastInst() |
| 149 | + PHINode *createPHINode(llvm::PHINode *I); |
| 150 | + friend PHINode; // For createPHINode() |
| 151 | + UnreachableInst *createUnreachableInst(llvm::UnreachableInst *UI); |
| 152 | + friend UnreachableInst; // For createUnreachableInst() |
| 153 | + CmpInst *createCmpInst(llvm::CmpInst *I); |
| 154 | + friend CmpInst; // For createCmpInst() |
| 155 | + ICmpInst *createICmpInst(llvm::ICmpInst *I); |
| 156 | + friend ICmpInst; // For createICmpInst() |
| 157 | + FCmpInst *createFCmpInst(llvm::FCmpInst *I); |
| 158 | + friend FCmpInst; // For createFCmpInst() |
| 159 | + |
| 160 | +public: |
| 161 | + Context(LLVMContext &LLVMCtx) |
| 162 | + : LLVMCtx(LLVMCtx), IRTracker(*this), |
| 163 | + LLVMIRBuilder(LLVMCtx, ConstantFolder()) {} |
| 164 | + |
| 165 | + Tracker &getTracker() { return IRTracker; } |
| 166 | + /// Convenience function for `getTracker().save()` |
| 167 | + void save() { IRTracker.save(); } |
| 168 | + /// Convenience function for `getTracker().revert()` |
| 169 | + void revert() { IRTracker.revert(); } |
| 170 | + /// Convenience function for `getTracker().accept()` |
| 171 | + void accept() { IRTracker.accept(); } |
| 172 | + |
| 173 | + sandboxir::Value *getValue(llvm::Value *V) const; |
| 174 | + const sandboxir::Value *getValue(const llvm::Value *V) const { |
| 175 | + return getValue(const_cast<llvm::Value *>(V)); |
| 176 | + } |
| 177 | + |
| 178 | + Module *getModule(llvm::Module *LLVMM) const; |
| 179 | + |
| 180 | + Module *getOrCreateModule(llvm::Module *LLVMM); |
| 181 | + |
| 182 | + Type *getType(llvm::Type *LLVMTy) { |
| 183 | + if (LLVMTy == nullptr) |
| 184 | + return nullptr; |
| 185 | + auto Pair = LLVMTypeToTypeMap.insert({LLVMTy, nullptr}); |
| 186 | + auto It = Pair.first; |
| 187 | + if (Pair.second) |
| 188 | + It->second = std::unique_ptr<Type, TypeDeleter>(new Type(LLVMTy, *this)); |
| 189 | + return It->second.get(); |
| 190 | + } |
| 191 | + |
| 192 | + /// Create a sandboxir::Function for an existing LLVM IR \p F, including all |
| 193 | + /// blocks and instructions. |
| 194 | + /// This is the main API function for creating Sandbox IR. |
| 195 | + /// Note: this will not fully populate its parent module. The only globals |
| 196 | + /// that will be available are those used within the function. |
| 197 | + Function *createFunction(llvm::Function *F); |
| 198 | + |
| 199 | + /// Create a sandboxir::Module corresponding to \p LLVMM. |
| 200 | + Module *createModule(llvm::Module *LLVMM); |
| 201 | + |
| 202 | + /// \Returns the number of values registered with Context. |
| 203 | + size_t getNumValues() const { return LLVMValueToValueMap.size(); } |
| 204 | +}; |
| 205 | + |
| 206 | +} // namespace llvm::sandboxir |
| 207 | + |
| 208 | +#endif // LLVM_SANDBOXIR_CONTEXT_H |
0 commit comments