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