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 llvm::LoadInst *CreateAlignedLoad(llvm::Value *Addr, CharUnits Align, 106 bool IsVolatile, 107 const llvm::Twine &Name = "") { 108 return CreateAlignedLoad(Addr, Align.getQuantity(), IsVolatile, Name); 109 } 110 111 // Note that we intentionally hide the CreateStore APIs that don't 112 // take an alignment. 113 llvm::StoreInst *CreateStore(llvm::Value *Val, Address Addr, 114 bool IsVolatile = false) { 115 return CreateAlignedStore(Val, Addr.getPointer(), 116 Addr.getAlignment().getQuantity(), IsVolatile); 117 } 118 119 using CGBuilderBaseTy::CreateAlignedStore; 120 llvm::StoreInst *CreateAlignedStore(llvm::Value *Val, llvm::Value *Addr, 121 CharUnits Align, bool IsVolatile = false) { 122 return CreateAlignedStore(Val, Addr, Align.getQuantity(), IsVolatile); 123 } 124 125 // FIXME: these "default-aligned" APIs should be removed, 126 // but I don't feel like fixing all the builtin code right now. 127 llvm::LoadInst *CreateDefaultAlignedLoad(llvm::Value *Addr, 128 const llvm::Twine &Name = "") { 129 return CGBuilderBaseTy::CreateLoad(Addr, false, Name); 130 } 131 llvm::LoadInst *CreateDefaultAlignedLoad(llvm::Value *Addr, 132 const char *Name) { 133 return CGBuilderBaseTy::CreateLoad(Addr, false, Name); 134 } 135 llvm::LoadInst *CreateDefaultAlignedLoad(llvm::Value *Addr, bool IsVolatile, 136 const llvm::Twine &Name = "") { 137 return CGBuilderBaseTy::CreateLoad(Addr, IsVolatile, Name); 138 } 139 140 llvm::StoreInst *CreateDefaultAlignedStore(llvm::Value *Val, 141 llvm::Value *Addr, 142 bool IsVolatile = false) { 143 return CGBuilderBaseTy::CreateStore(Val, Addr, IsVolatile); 144 } 145 146 /// Emit a load from an i1 flag variable. 147 llvm::LoadInst *CreateFlagLoad(llvm::Value *Addr, 148 const llvm::Twine &Name = "") { 149 assert(Addr->getType()->getPointerElementType() == getInt1Ty()); 150 return CreateAlignedLoad(getInt1Ty(), Addr, CharUnits::One(), Name); 151 } 152 153 /// Emit a store to an i1 flag variable. 154 llvm::StoreInst *CreateFlagStore(bool Value, llvm::Value *Addr) { 155 assert(Addr->getType()->getPointerElementType() == getInt1Ty()); 156 return CreateAlignedStore(getInt1(Value), Addr, CharUnits::One()); 157 } 158 159 using CGBuilderBaseTy::CreateBitCast; 160 Address CreateBitCast(Address Addr, llvm::Type *Ty, 161 const llvm::Twine &Name = "") { 162 return Address(CreateBitCast(Addr.getPointer(), Ty, Name), 163 Addr.getAlignment()); 164 } 165 166 /// Cast the element type of the given address to a different type, 167 /// preserving information like the alignment and address space. 168 Address CreateElementBitCast(Address Addr, llvm::Type *Ty, 169 const llvm::Twine &Name = "") { 170 auto PtrTy = Ty->getPointerTo(Addr.getAddressSpace()); 171 return CreateBitCast(Addr, PtrTy, Name); 172 } 173 174 using CGBuilderBaseTy::CreatePointerBitCastOrAddrSpaceCast; 175 Address CreatePointerBitCastOrAddrSpaceCast(Address Addr, llvm::Type *Ty, 176 const llvm::Twine &Name = "") { 177 llvm::Value *Ptr = 178 CreatePointerBitCastOrAddrSpaceCast(Addr.getPointer(), Ty, Name); 179 return Address(Ptr, Addr.getAlignment()); 180 } 181 182 using CGBuilderBaseTy::CreateStructGEP; 183 Address CreateStructGEP(Address Addr, unsigned Index, CharUnits Offset, 184 const llvm::Twine &Name = "") { 185 return Address(CreateStructGEP(Addr.getElementType(), 186 Addr.getPointer(), Index, Name), 187 Addr.getAlignment().alignmentAtOffset(Offset)); 188 } 189 Address CreateStructGEP(Address Addr, unsigned Index, 190 const llvm::StructLayout *Layout, 191 const llvm::Twine &Name = "") { 192 auto Offset = CharUnits::fromQuantity(Layout->getElementOffset(Index)); 193 return CreateStructGEP(Addr, Index, Offset, Name); 194 } 195 196 /// Given 197 /// %addr = [n x T]* ... 198 /// produce 199 /// %name = getelementptr inbounds %addr, i64 0, i64 index 200 /// where i64 is actually the target word size. 201 /// 202 /// This API assumes that drilling into an array like this is always 203 /// an inbounds operation. 204 /// 205 /// \param EltSize - the size of the type T in bytes 206 Address CreateConstArrayGEP(Address Addr, uint64_t Index, CharUnits EltSize, 207 const llvm::Twine &Name = "") { 208 return Address(CreateInBoundsGEP(Addr.getPointer(), 209 {getSize(CharUnits::Zero()), 210 getSize(Index)}, 211 Name), 212 Addr.getAlignment().alignmentAtOffset(Index * EltSize)); 213 } 214 215 /// Given 216 /// %addr = T* ... 217 /// produce 218 /// %name = getelementptr inbounds %addr, i64 index 219 /// where i64 is actually the target word size. 220 /// 221 /// \param EltSize - the size of the type T in bytes 222 Address CreateConstInBoundsGEP(Address Addr, uint64_t Index, 223 CharUnits EltSize, 224 const llvm::Twine &Name = "") { 225 return Address(CreateInBoundsGEP(Addr.getElementType(), Addr.getPointer(), 226 getSize(Index), Name), 227 Addr.getAlignment().alignmentAtOffset(Index * EltSize)); 228 } 229 230 /// Given 231 /// %addr = T* ... 232 /// produce 233 /// %name = getelementptr inbounds %addr, i64 index 234 /// where i64 is actually the target word size. 235 /// 236 /// \param EltSize - the size of the type T in bytes 237 Address CreateConstGEP(Address Addr, uint64_t Index, CharUnits EltSize, 238 const llvm::Twine &Name = "") { 239 return Address(CreateGEP(Addr.getElementType(), Addr.getPointer(), 240 getSize(Index), Name), 241 Addr.getAlignment().alignmentAtOffset(Index * EltSize)); 242 } 243 244 /// Given a pointer to i8, adjust it by a given constant offset. 245 Address CreateConstInBoundsByteGEP(Address Addr, CharUnits Offset, 246 const llvm::Twine &Name = "") { 247 assert(Addr.getElementType() == TypeCache.Int8Ty); 248 return Address(CreateInBoundsGEP(Addr.getPointer(), getSize(Offset), Name), 249 Addr.getAlignment().alignmentAtOffset(Offset)); 250 } 251 Address CreateConstByteGEP(Address Addr, CharUnits Offset, 252 const llvm::Twine &Name = "") { 253 assert(Addr.getElementType() == TypeCache.Int8Ty); 254 return Address(CreateGEP(Addr.getPointer(), getSize(Offset), Name), 255 Addr.getAlignment().alignmentAtOffset(Offset)); 256 } 257 258 llvm::Value *CreateConstInBoundsByteGEP(llvm::Value *Ptr, CharUnits Offset, 259 const llvm::Twine &Name = "") { 260 assert(Ptr->getType()->getPointerElementType() == TypeCache.Int8Ty); 261 return CreateInBoundsGEP(Ptr, getSize(Offset), Name); 262 } 263 llvm::Value *CreateConstByteGEP(llvm::Value *Ptr, CharUnits Offset, 264 const llvm::Twine &Name = "") { 265 assert(Ptr->getType()->getPointerElementType() == TypeCache.Int8Ty); 266 return CreateGEP(Ptr, getSize(Offset), Name); 267 } 268 269 using CGBuilderBaseTy::CreateMemCpy; 270 llvm::CallInst *CreateMemCpy(Address Dest, Address Src, llvm::Value *Size, 271 bool IsVolatile = false) { 272 auto Align = std::min(Dest.getAlignment(), Src.getAlignment()); 273 return CreateMemCpy(Dest.getPointer(), Src.getPointer(), Size, 274 Align.getQuantity(), IsVolatile); 275 } 276 llvm::CallInst *CreateMemCpy(Address Dest, Address Src, uint64_t Size, 277 bool IsVolatile = false) { 278 auto Align = std::min(Dest.getAlignment(), Src.getAlignment()); 279 return CreateMemCpy(Dest.getPointer(), Src.getPointer(), Size, 280 Align.getQuantity(), IsVolatile); 281 } 282 283 using CGBuilderBaseTy::CreateMemMove; 284 llvm::CallInst *CreateMemMove(Address Dest, Address Src, llvm::Value *Size, 285 bool IsVolatile = false) { 286 auto Align = std::min(Dest.getAlignment(), Src.getAlignment()); 287 return CreateMemMove(Dest.getPointer(), Src.getPointer(), Size, 288 Align.getQuantity(), IsVolatile); 289 } 290 291 using CGBuilderBaseTy::CreateMemSet; 292 llvm::CallInst *CreateMemSet(Address Dest, llvm::Value *Value, 293 llvm::Value *Size, bool IsVolatile = false) { 294 return CreateMemSet(Dest.getPointer(), Value, Size, 295 Dest.getAlignment().getQuantity(), IsVolatile); 296 } 297 }; 298 299 } // end namespace CodeGen 300 } // end namespace clang 301 302 #endif 303