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 /// 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; CGBuilderInserter(CodeGenFunction * CGF)29 explicit CGBuilderInserter(CodeGenFunction *CGF) : CGF(CGF) {} 30 31 protected: 32 /// 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: CGBuilderTy(const CodeGenTypeCache & TypeCache,llvm::LLVMContext & C)50 CGBuilderTy(const CodeGenTypeCache &TypeCache, llvm::LLVMContext &C) 51 : CGBuilderBaseTy(C), TypeCache(TypeCache) {} CGBuilderTy(const CodeGenTypeCache & TypeCache,llvm::LLVMContext & C,const llvm::ConstantFolder & F,const CGBuilderInserterTy & Inserter)52 CGBuilderTy(const CodeGenTypeCache &TypeCache, 53 llvm::LLVMContext &C, const llvm::ConstantFolder &F, 54 const CGBuilderInserterTy &Inserter) 55 : CGBuilderBaseTy(C, F, Inserter), TypeCache(TypeCache) {} CGBuilderTy(const CodeGenTypeCache & TypeCache,llvm::Instruction * I)56 CGBuilderTy(const CodeGenTypeCache &TypeCache, llvm::Instruction *I) 57 : CGBuilderBaseTy(I), TypeCache(TypeCache) {} CGBuilderTy(const CodeGenTypeCache & TypeCache,llvm::BasicBlock * BB)58 CGBuilderTy(const CodeGenTypeCache &TypeCache, llvm::BasicBlock *BB) 59 : CGBuilderBaseTy(BB), TypeCache(TypeCache) {} 60 getSize(CharUnits N)61 llvm::ConstantInt *getSize(CharUnits N) { 62 return llvm::ConstantInt::get(TypeCache.SizeTy, N.getQuantity()); 63 } getSize(uint64_t N)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 } CreateLoad(Address Addr,const char * Name)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 } CreateAlignedLoad(llvm::Value * Addr,CharUnits Align,const char * Name)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. CreateFlagStore(bool Value,llvm::Value * Addr)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 using CGBuilderBaseTy::CreateAddrSpaceCast; 149 Address CreateAddrSpaceCast(Address Addr, llvm::Type *Ty, 150 const llvm::Twine &Name = "") { 151 return Address(CreateAddrSpaceCast(Addr.getPointer(), Ty, Name), 152 Addr.getAlignment()); 153 } 154 155 /// Cast the element type of the given address to a different type, 156 /// preserving information like the alignment and address space. 157 Address CreateElementBitCast(Address Addr, llvm::Type *Ty, 158 const llvm::Twine &Name = "") { 159 auto PtrTy = Ty->getPointerTo(Addr.getAddressSpace()); 160 return CreateBitCast(Addr, PtrTy, Name); 161 } 162 163 using CGBuilderBaseTy::CreatePointerBitCastOrAddrSpaceCast; 164 Address CreatePointerBitCastOrAddrSpaceCast(Address Addr, llvm::Type *Ty, 165 const llvm::Twine &Name = "") { 166 llvm::Value *Ptr = 167 CreatePointerBitCastOrAddrSpaceCast(Addr.getPointer(), Ty, Name); 168 return Address(Ptr, Addr.getAlignment()); 169 } 170 171 using CGBuilderBaseTy::CreateStructGEP; 172 Address CreateStructGEP(Address Addr, unsigned Index, CharUnits Offset, 173 const llvm::Twine &Name = "") { 174 return Address(CreateStructGEP(Addr.getElementType(), 175 Addr.getPointer(), Index, Name), 176 Addr.getAlignment().alignmentAtOffset(Offset)); 177 } 178 Address CreateStructGEP(Address Addr, unsigned Index, 179 const llvm::StructLayout *Layout, 180 const llvm::Twine &Name = "") { 181 auto Offset = CharUnits::fromQuantity(Layout->getElementOffset(Index)); 182 return CreateStructGEP(Addr, Index, Offset, Name); 183 } 184 185 /// Given 186 /// %addr = [n x T]* ... 187 /// produce 188 /// %name = getelementptr inbounds %addr, i64 0, i64 index 189 /// where i64 is actually the target word size. 190 /// 191 /// This API assumes that drilling into an array like this is always 192 /// an inbounds operation. 193 /// 194 /// \param EltSize - the size of the type T in bytes 195 Address CreateConstArrayGEP(Address Addr, uint64_t Index, CharUnits EltSize, 196 const llvm::Twine &Name = "") { 197 return Address(CreateInBoundsGEP(Addr.getPointer(), 198 {getSize(CharUnits::Zero()), 199 getSize(Index)}, 200 Name), 201 Addr.getAlignment().alignmentAtOffset(Index * EltSize)); 202 } 203 204 /// Given 205 /// %addr = T* ... 206 /// produce 207 /// %name = getelementptr inbounds %addr, i64 index 208 /// where i64 is actually the target word size. 209 /// 210 /// \param EltSize - the size of the type T in bytes 211 Address CreateConstInBoundsGEP(Address Addr, uint64_t Index, 212 CharUnits EltSize, 213 const llvm::Twine &Name = "") { 214 return Address(CreateInBoundsGEP(Addr.getElementType(), Addr.getPointer(), 215 getSize(Index), Name), 216 Addr.getAlignment().alignmentAtOffset(Index * EltSize)); 217 } 218 219 /// Given 220 /// %addr = T* ... 221 /// produce 222 /// %name = getelementptr inbounds %addr, i64 index 223 /// where i64 is actually the target word size. 224 /// 225 /// \param EltSize - the size of the type T in bytes 226 Address CreateConstGEP(Address Addr, uint64_t Index, CharUnits EltSize, 227 const llvm::Twine &Name = "") { 228 return Address(CreateGEP(Addr.getElementType(), Addr.getPointer(), 229 getSize(Index), Name), 230 Addr.getAlignment().alignmentAtOffset(Index * EltSize)); 231 } 232 233 /// Given a pointer to i8, adjust it by a given constant offset. 234 Address CreateConstInBoundsByteGEP(Address Addr, CharUnits Offset, 235 const llvm::Twine &Name = "") { 236 assert(Addr.getElementType() == TypeCache.Int8Ty); 237 return Address(CreateInBoundsGEP(Addr.getPointer(), getSize(Offset), Name), 238 Addr.getAlignment().alignmentAtOffset(Offset)); 239 } 240 Address CreateConstByteGEP(Address Addr, CharUnits Offset, 241 const llvm::Twine &Name = "") { 242 assert(Addr.getElementType() == TypeCache.Int8Ty); 243 return Address(CreateGEP(Addr.getPointer(), getSize(Offset), Name), 244 Addr.getAlignment().alignmentAtOffset(Offset)); 245 } 246 247 using CGBuilderBaseTy::CreateConstInBoundsGEP2_32; 248 Address CreateConstInBoundsGEP2_32(Address Addr, unsigned Idx0, 249 unsigned Idx1, const llvm::DataLayout &DL, 250 const llvm::Twine &Name = "") { 251 auto *GEP = cast<llvm::GetElementPtrInst>(CreateConstInBoundsGEP2_32( 252 Addr.getElementType(), Addr.getPointer(), Idx0, Idx1, Name)); 253 llvm::APInt Offset( 254 DL.getIndexSizeInBits(Addr.getType()->getPointerAddressSpace()), 0, 255 /*IsSigned=*/true); 256 if (!GEP->accumulateConstantOffset(DL, Offset)) 257 llvm_unreachable("offset of GEP with constants is always computable"); 258 return Address(GEP, Addr.getAlignment().alignmentAtOffset( 259 CharUnits::fromQuantity(Offset.getSExtValue()))); 260 } 261 262 llvm::Value *CreateConstInBoundsByteGEP(llvm::Value *Ptr, CharUnits Offset, 263 const llvm::Twine &Name = "") { 264 assert(Ptr->getType()->getPointerElementType() == TypeCache.Int8Ty); 265 return CreateInBoundsGEP(Ptr, getSize(Offset), Name); 266 } 267 llvm::Value *CreateConstByteGEP(llvm::Value *Ptr, CharUnits Offset, 268 const llvm::Twine &Name = "") { 269 assert(Ptr->getType()->getPointerElementType() == TypeCache.Int8Ty); 270 return CreateGEP(Ptr, getSize(Offset), Name); 271 } 272 273 using CGBuilderBaseTy::CreateMemCpy; 274 llvm::CallInst *CreateMemCpy(Address Dest, Address Src, llvm::Value *Size, 275 bool IsVolatile = false) { 276 return CreateMemCpy(Dest.getPointer(), Dest.getAlignment().getQuantity(), 277 Src.getPointer(), Src.getAlignment().getQuantity(), 278 Size,IsVolatile); 279 } 280 llvm::CallInst *CreateMemCpy(Address Dest, Address Src, uint64_t Size, 281 bool IsVolatile = false) { 282 return CreateMemCpy(Dest.getPointer(), Dest.getAlignment().getQuantity(), 283 Src.getPointer(), Src.getAlignment().getQuantity(), 284 Size, IsVolatile); 285 } 286 287 using CGBuilderBaseTy::CreateMemMove; 288 llvm::CallInst *CreateMemMove(Address Dest, Address Src, llvm::Value *Size, 289 bool IsVolatile = false) { 290 return CreateMemMove(Dest.getPointer(), Dest.getAlignment().getQuantity(), 291 Src.getPointer(), Src.getAlignment().getQuantity(), 292 Size, IsVolatile); 293 } 294 295 using CGBuilderBaseTy::CreateMemSet; 296 llvm::CallInst *CreateMemSet(Address Dest, llvm::Value *Value, 297 llvm::Value *Size, bool IsVolatile = false) { 298 return CreateMemSet(Dest.getPointer(), Value, Size, 299 Dest.getAlignment().getQuantity(), IsVolatile); 300 } 301 }; 302 303 } // end namespace CodeGen 304 } // end namespace clang 305 306 #endif 307