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 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 llvm::Value *CreateConstInBoundsByteGEP(llvm::Value *Ptr, CharUnits Offset, 248 const llvm::Twine &Name = "") { 249 assert(Ptr->getType()->getPointerElementType() == TypeCache.Int8Ty); 250 return CreateInBoundsGEP(Ptr, getSize(Offset), Name); 251 } 252 llvm::Value *CreateConstByteGEP(llvm::Value *Ptr, CharUnits Offset, 253 const llvm::Twine &Name = "") { 254 assert(Ptr->getType()->getPointerElementType() == TypeCache.Int8Ty); 255 return CreateGEP(Ptr, getSize(Offset), Name); 256 } 257 258 using CGBuilderBaseTy::CreateMemCpy; 259 llvm::CallInst *CreateMemCpy(Address Dest, Address Src, llvm::Value *Size, 260 bool IsVolatile = false) { 261 return CreateMemCpy(Dest.getPointer(), Dest.getAlignment().getQuantity(), 262 Src.getPointer(), Src.getAlignment().getQuantity(), 263 Size,IsVolatile); 264 } 265 llvm::CallInst *CreateMemCpy(Address Dest, Address Src, uint64_t Size, 266 bool IsVolatile = false) { 267 return CreateMemCpy(Dest.getPointer(), Dest.getAlignment().getQuantity(), 268 Src.getPointer(), Src.getAlignment().getQuantity(), 269 Size, IsVolatile); 270 } 271 272 using CGBuilderBaseTy::CreateMemMove; 273 llvm::CallInst *CreateMemMove(Address Dest, Address Src, llvm::Value *Size, 274 bool IsVolatile = false) { 275 return CreateMemMove(Dest.getPointer(), Dest.getAlignment().getQuantity(), 276 Src.getPointer(), Src.getAlignment().getQuantity(), 277 Size, IsVolatile); 278 } 279 280 using CGBuilderBaseTy::CreateMemSet; 281 llvm::CallInst *CreateMemSet(Address Dest, llvm::Value *Value, 282 llvm::Value *Size, bool IsVolatile = false) { 283 return CreateMemSet(Dest.getPointer(), Value, Size, 284 Dest.getAlignment().getQuantity(), IsVolatile); 285 } 286 }; 287 288 } // end namespace CodeGen 289 } // end namespace clang 290 291 #endif 292