1 //===-- CGBuilder.h - Choose IRBuilder implementation ----------*- C++ -*-===// 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 #ifndef LLVM_CLANG_LIB_CODEGEN_CGBUILDER_H 11 #define LLVM_CLANG_LIB_CODEGEN_CGBUILDER_H 12 13 #include "llvm/IR/DataLayout.h" 14 #include "llvm/IR/IRBuilder.h" 15 #include "Address.h" 16 #include "CodeGenTypeCache.h" 17 18 namespace clang { 19 namespace CodeGen { 20 21 class CodeGenFunction; 22 23 /// \brief This is an IRBuilder insertion helper that forwards to 24 /// CodeGenFunction::InsertHelper, which adds necessary metadata to 25 /// instructions. 26 class CGBuilderInserter : protected llvm::IRBuilderDefaultInserter { 27 public: 28 CGBuilderInserter() = default; 29 explicit CGBuilderInserter(CodeGenFunction *CGF) : CGF(CGF) {} 30 31 protected: 32 /// \brief This forwards to CodeGenFunction::InsertHelper. 33 void InsertHelper(llvm::Instruction *I, const llvm::Twine &Name, 34 llvm::BasicBlock *BB, 35 llvm::BasicBlock::iterator InsertPt) const; 36 private: 37 CodeGenFunction *CGF = nullptr; 38 }; 39 40 typedef CGBuilderInserter CGBuilderInserterTy; 41 42 typedef llvm::IRBuilder<llvm::ConstantFolder, CGBuilderInserterTy> 43 CGBuilderBaseTy; 44 45 class CGBuilderTy : public CGBuilderBaseTy { 46 /// Storing a reference to the type cache here makes it a lot easier 47 /// to build natural-feeling, target-specific IR. 48 const CodeGenTypeCache &TypeCache; 49 public: 50 CGBuilderTy(const CodeGenTypeCache &TypeCache, llvm::LLVMContext &C) 51 : CGBuilderBaseTy(C), TypeCache(TypeCache) {} 52 CGBuilderTy(const CodeGenTypeCache &TypeCache, 53 llvm::LLVMContext &C, const llvm::ConstantFolder &F, 54 const CGBuilderInserterTy &Inserter) 55 : CGBuilderBaseTy(C, F, Inserter), TypeCache(TypeCache) {} 56 CGBuilderTy(const CodeGenTypeCache &TypeCache, llvm::Instruction *I) 57 : CGBuilderBaseTy(I), TypeCache(TypeCache) {} 58 CGBuilderTy(const CodeGenTypeCache &TypeCache, llvm::BasicBlock *BB) 59 : CGBuilderBaseTy(BB), TypeCache(TypeCache) {} 60 61 llvm::ConstantInt *getSize(CharUnits N) { 62 return llvm::ConstantInt::get(TypeCache.SizeTy, N.getQuantity()); 63 } 64 llvm::ConstantInt *getSize(uint64_t N) { 65 return llvm::ConstantInt::get(TypeCache.SizeTy, N); 66 } 67 68 // Note that we intentionally hide the CreateLoad APIs that don't 69 // take an alignment. 70 llvm::LoadInst *CreateLoad(Address Addr, const llvm::Twine &Name = "") { 71 return CreateAlignedLoad(Addr.getPointer(), 72 Addr.getAlignment().getQuantity(), 73 Name); 74 } 75 llvm::LoadInst *CreateLoad(Address Addr, const char *Name) { 76 // This overload is required to prevent string literals from 77 // ending up in the IsVolatile overload. 78 return CreateAlignedLoad(Addr.getPointer(), 79 Addr.getAlignment().getQuantity(), 80 Name); 81 } 82 llvm::LoadInst *CreateLoad(Address Addr, bool IsVolatile, 83 const llvm::Twine &Name = "") { 84 return CreateAlignedLoad(Addr.getPointer(), 85 Addr.getAlignment().getQuantity(), 86 IsVolatile, 87 Name); 88 } 89 90 using CGBuilderBaseTy::CreateAlignedLoad; 91 llvm::LoadInst *CreateAlignedLoad(llvm::Value *Addr, CharUnits Align, 92 const llvm::Twine &Name = "") { 93 return CreateAlignedLoad(Addr, Align.getQuantity(), Name); 94 } 95 llvm::LoadInst *CreateAlignedLoad(llvm::Value *Addr, CharUnits Align, 96 const char *Name) { 97 return CreateAlignedLoad(Addr, Align.getQuantity(), Name); 98 } 99 llvm::LoadInst *CreateAlignedLoad(llvm::Type *Ty, llvm::Value *Addr, 100 CharUnits Align, 101 const llvm::Twine &Name = "") { 102 assert(Addr->getType()->getPointerElementType() == Ty); 103 return CreateAlignedLoad(Addr, Align.getQuantity(), Name); 104 } 105 106 // Note that we intentionally hide the CreateStore APIs that don't 107 // take an alignment. 108 llvm::StoreInst *CreateStore(llvm::Value *Val, Address Addr, 109 bool IsVolatile = false) { 110 return CreateAlignedStore(Val, Addr.getPointer(), 111 Addr.getAlignment().getQuantity(), IsVolatile); 112 } 113 114 using CGBuilderBaseTy::CreateAlignedStore; 115 llvm::StoreInst *CreateAlignedStore(llvm::Value *Val, llvm::Value *Addr, 116 CharUnits Align, bool IsVolatile = false) { 117 return CreateAlignedStore(Val, Addr, Align.getQuantity(), IsVolatile); 118 } 119 120 // FIXME: these "default-aligned" APIs should be removed, 121 // but I don't feel like fixing all the builtin code right now. 122 llvm::StoreInst *CreateDefaultAlignedStore(llvm::Value *Val, 123 llvm::Value *Addr, 124 bool IsVolatile = false) { 125 return CGBuilderBaseTy::CreateStore(Val, Addr, IsVolatile); 126 } 127 128 /// Emit a load from an i1 flag variable. 129 llvm::LoadInst *CreateFlagLoad(llvm::Value *Addr, 130 const llvm::Twine &Name = "") { 131 assert(Addr->getType()->getPointerElementType() == getInt1Ty()); 132 return CreateAlignedLoad(getInt1Ty(), Addr, CharUnits::One(), Name); 133 } 134 135 /// Emit a store to an i1 flag variable. 136 llvm::StoreInst *CreateFlagStore(bool Value, llvm::Value *Addr) { 137 assert(Addr->getType()->getPointerElementType() == getInt1Ty()); 138 return CreateAlignedStore(getInt1(Value), Addr, CharUnits::One()); 139 } 140 141 using CGBuilderBaseTy::CreateBitCast; 142 Address CreateBitCast(Address Addr, llvm::Type *Ty, 143 const llvm::Twine &Name = "") { 144 return Address(CreateBitCast(Addr.getPointer(), Ty, Name), 145 Addr.getAlignment()); 146 } 147 148 /// Cast the element type of the given address to a different type, 149 /// preserving information like the alignment and address space. 150 Address CreateElementBitCast(Address Addr, llvm::Type *Ty, 151 const llvm::Twine &Name = "") { 152 auto PtrTy = Ty->getPointerTo(Addr.getAddressSpace()); 153 return CreateBitCast(Addr, PtrTy, Name); 154 } 155 156 using CGBuilderBaseTy::CreatePointerBitCastOrAddrSpaceCast; 157 Address CreatePointerBitCastOrAddrSpaceCast(Address Addr, llvm::Type *Ty, 158 const llvm::Twine &Name = "") { 159 llvm::Value *Ptr = 160 CreatePointerBitCastOrAddrSpaceCast(Addr.getPointer(), Ty, Name); 161 return Address(Ptr, Addr.getAlignment()); 162 } 163 164 using CGBuilderBaseTy::CreateStructGEP; 165 Address CreateStructGEP(Address Addr, unsigned Index, CharUnits Offset, 166 const llvm::Twine &Name = "") { 167 return Address(CreateStructGEP(Addr.getElementType(), 168 Addr.getPointer(), Index, Name), 169 Addr.getAlignment().alignmentAtOffset(Offset)); 170 } 171 Address CreateStructGEP(Address Addr, unsigned Index, 172 const llvm::StructLayout *Layout, 173 const llvm::Twine &Name = "") { 174 auto Offset = CharUnits::fromQuantity(Layout->getElementOffset(Index)); 175 return CreateStructGEP(Addr, Index, Offset, Name); 176 } 177 178 /// Given 179 /// %addr = [n x T]* ... 180 /// produce 181 /// %name = getelementptr inbounds %addr, i64 0, i64 index 182 /// where i64 is actually the target word size. 183 /// 184 /// This API assumes that drilling into an array like this is always 185 /// an inbounds operation. 186 /// 187 /// \param EltSize - the size of the type T in bytes 188 Address CreateConstArrayGEP(Address Addr, uint64_t Index, CharUnits EltSize, 189 const llvm::Twine &Name = "") { 190 return Address(CreateInBoundsGEP(Addr.getPointer(), 191 {getSize(CharUnits::Zero()), 192 getSize(Index)}, 193 Name), 194 Addr.getAlignment().alignmentAtOffset(Index * EltSize)); 195 } 196 197 /// Given 198 /// %addr = T* ... 199 /// produce 200 /// %name = getelementptr inbounds %addr, i64 index 201 /// where i64 is actually the target word size. 202 /// 203 /// \param EltSize - the size of the type T in bytes 204 Address CreateConstInBoundsGEP(Address Addr, uint64_t Index, 205 CharUnits EltSize, 206 const llvm::Twine &Name = "") { 207 return Address(CreateInBoundsGEP(Addr.getElementType(), Addr.getPointer(), 208 getSize(Index), Name), 209 Addr.getAlignment().alignmentAtOffset(Index * EltSize)); 210 } 211 212 /// Given 213 /// %addr = T* ... 214 /// produce 215 /// %name = getelementptr inbounds %addr, i64 index 216 /// where i64 is actually the target word size. 217 /// 218 /// \param EltSize - the size of the type T in bytes 219 Address CreateConstGEP(Address Addr, uint64_t Index, CharUnits EltSize, 220 const llvm::Twine &Name = "") { 221 return Address(CreateGEP(Addr.getElementType(), Addr.getPointer(), 222 getSize(Index), Name), 223 Addr.getAlignment().alignmentAtOffset(Index * EltSize)); 224 } 225 226 /// Given a pointer to i8, adjust it by a given constant offset. 227 Address CreateConstInBoundsByteGEP(Address Addr, CharUnits Offset, 228 const llvm::Twine &Name = "") { 229 assert(Addr.getElementType() == TypeCache.Int8Ty); 230 return Address(CreateInBoundsGEP(Addr.getPointer(), getSize(Offset), Name), 231 Addr.getAlignment().alignmentAtOffset(Offset)); 232 } 233 Address CreateConstByteGEP(Address Addr, CharUnits Offset, 234 const llvm::Twine &Name = "") { 235 assert(Addr.getElementType() == TypeCache.Int8Ty); 236 return Address(CreateGEP(Addr.getPointer(), getSize(Offset), Name), 237 Addr.getAlignment().alignmentAtOffset(Offset)); 238 } 239 240 llvm::Value *CreateConstInBoundsByteGEP(llvm::Value *Ptr, CharUnits Offset, 241 const llvm::Twine &Name = "") { 242 assert(Ptr->getType()->getPointerElementType() == TypeCache.Int8Ty); 243 return CreateInBoundsGEP(Ptr, getSize(Offset), Name); 244 } 245 llvm::Value *CreateConstByteGEP(llvm::Value *Ptr, CharUnits Offset, 246 const llvm::Twine &Name = "") { 247 assert(Ptr->getType()->getPointerElementType() == TypeCache.Int8Ty); 248 return CreateGEP(Ptr, getSize(Offset), Name); 249 } 250 251 using CGBuilderBaseTy::CreateMemCpy; 252 llvm::CallInst *CreateMemCpy(Address Dest, Address Src, llvm::Value *Size, 253 bool IsVolatile = false) { 254 auto Align = std::min(Dest.getAlignment(), Src.getAlignment()); 255 return CreateMemCpy(Dest.getPointer(), Src.getPointer(), Size, 256 Align.getQuantity(), IsVolatile); 257 } 258 llvm::CallInst *CreateMemCpy(Address Dest, Address Src, uint64_t Size, 259 bool IsVolatile = false) { 260 auto Align = std::min(Dest.getAlignment(), Src.getAlignment()); 261 return CreateMemCpy(Dest.getPointer(), Src.getPointer(), Size, 262 Align.getQuantity(), IsVolatile); 263 } 264 265 using CGBuilderBaseTy::CreateMemMove; 266 llvm::CallInst *CreateMemMove(Address Dest, Address Src, llvm::Value *Size, 267 bool IsVolatile = false) { 268 auto Align = std::min(Dest.getAlignment(), Src.getAlignment()); 269 return CreateMemMove(Dest.getPointer(), Src.getPointer(), Size, 270 Align.getQuantity(), IsVolatile); 271 } 272 273 using CGBuilderBaseTy::CreateMemSet; 274 llvm::CallInst *CreateMemSet(Address Dest, llvm::Value *Value, 275 llvm::Value *Size, bool IsVolatile = false) { 276 return CreateMemSet(Dest.getPointer(), Value, Size, 277 Dest.getAlignment().getQuantity(), IsVolatile); 278 } 279 }; 280 281 } // end namespace CodeGen 282 } // end namespace clang 283 284 #endif 285