1 //===-- CGBuilder.h - Choose IRBuilder implementation ----------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #ifndef LLVM_CLANG_LIB_CODEGEN_CGBUILDER_H 10 #define LLVM_CLANG_LIB_CODEGEN_CGBUILDER_H 11 12 #include "Address.h" 13 #include "CGValue.h" 14 #include "CodeGenTypeCache.h" 15 #include "llvm/Analysis/Utils/Local.h" 16 #include "llvm/IR/DataLayout.h" 17 #include "llvm/IR/IRBuilder.h" 18 #include "llvm/IR/Type.h" 19 20 namespace clang { 21 namespace CodeGen { 22 23 class CGBuilderTy; 24 class CodeGenFunction; 25 26 /// This is an IRBuilder insertion helper that forwards to 27 /// CodeGenFunction::InsertHelper, which adds necessary metadata to 28 /// instructions. 29 class CGBuilderInserter final : public llvm::IRBuilderDefaultInserter { 30 friend CGBuilderTy; 31 32 public: 33 CGBuilderInserter() = default; CGBuilderInserter(CodeGenFunction * CGF)34 explicit CGBuilderInserter(CodeGenFunction *CGF) : CGF(CGF) {} 35 36 /// This forwards to CodeGenFunction::InsertHelper. 37 void InsertHelper(llvm::Instruction *I, const llvm::Twine &Name, 38 llvm::BasicBlock::iterator InsertPt) const override; 39 40 private: 41 CodeGenFunction *CGF = nullptr; 42 }; 43 44 typedef CGBuilderInserter CGBuilderInserterTy; 45 46 typedef llvm::IRBuilder<llvm::ConstantFolder, CGBuilderInserterTy> 47 CGBuilderBaseTy; 48 49 class CGBuilderTy : public CGBuilderBaseTy { 50 friend class Address; 51 52 /// Storing a reference to the type cache here makes it a lot easier 53 /// to build natural-feeling, target-specific IR. 54 const CodeGenTypeCache &TypeCache; 55 getCGF()56 CodeGenFunction *getCGF() const { return getInserter().CGF; } 57 emitRawPointerFromAddress(Address Addr)58 llvm::Value *emitRawPointerFromAddress(Address Addr) const { 59 return Addr.getBasePointer(); 60 } 61 62 template <bool IsInBounds> createConstGEP2_32(Address Addr,unsigned Idx0,unsigned Idx1,const llvm::Twine & Name)63 Address createConstGEP2_32(Address Addr, unsigned Idx0, unsigned Idx1, 64 const llvm::Twine &Name) { 65 const llvm::DataLayout &DL = BB->getDataLayout(); 66 llvm::GetElementPtrInst *GEP; 67 if (IsInBounds) 68 GEP = cast<llvm::GetElementPtrInst>(CreateConstInBoundsGEP2_32( 69 Addr.getElementType(), emitRawPointerFromAddress(Addr), Idx0, Idx1, 70 Name)); 71 else 72 GEP = cast<llvm::GetElementPtrInst>(CreateConstGEP2_32( 73 Addr.getElementType(), emitRawPointerFromAddress(Addr), Idx0, Idx1, 74 Name)); 75 llvm::APInt Offset( 76 DL.getIndexSizeInBits(Addr.getType()->getPointerAddressSpace()), 0, 77 /*isSigned=*/true); 78 if (!GEP->accumulateConstantOffset(DL, Offset)) 79 llvm_unreachable("offset of GEP with constants is always computable"); 80 return Address(GEP, GEP->getResultElementType(), 81 Addr.getAlignment().alignmentAtOffset( 82 CharUnits::fromQuantity(Offset.getSExtValue())), 83 IsInBounds ? Addr.isKnownNonNull() : NotKnownNonNull); 84 } 85 86 public: CGBuilderTy(const CodeGenTypeCache & TypeCache,llvm::LLVMContext & C)87 CGBuilderTy(const CodeGenTypeCache &TypeCache, llvm::LLVMContext &C) 88 : CGBuilderBaseTy(C), TypeCache(TypeCache) {} CGBuilderTy(const CodeGenTypeCache & TypeCache,llvm::LLVMContext & C,const llvm::ConstantFolder & F,const CGBuilderInserterTy & Inserter)89 CGBuilderTy(const CodeGenTypeCache &TypeCache, llvm::LLVMContext &C, 90 const llvm::ConstantFolder &F, 91 const CGBuilderInserterTy &Inserter) 92 : CGBuilderBaseTy(C, F, Inserter), TypeCache(TypeCache) {} CGBuilderTy(const CodeGenTypeCache & TypeCache,llvm::Instruction * I)93 CGBuilderTy(const CodeGenTypeCache &TypeCache, llvm::Instruction *I) 94 : CGBuilderBaseTy(I), TypeCache(TypeCache) {} CGBuilderTy(const CodeGenTypeCache & TypeCache,llvm::BasicBlock * BB)95 CGBuilderTy(const CodeGenTypeCache &TypeCache, llvm::BasicBlock *BB) 96 : CGBuilderBaseTy(BB), TypeCache(TypeCache) {} 97 getSize(CharUnits N)98 llvm::ConstantInt *getSize(CharUnits N) { 99 return llvm::ConstantInt::get(TypeCache.SizeTy, N.getQuantity()); 100 } getSize(uint64_t N)101 llvm::ConstantInt *getSize(uint64_t N) { 102 return llvm::ConstantInt::get(TypeCache.SizeTy, N); 103 } 104 105 // Note that we intentionally hide the CreateLoad APIs that don't 106 // take an alignment. 107 llvm::LoadInst *CreateLoad(Address Addr, const llvm::Twine &Name = "") { 108 return CreateAlignedLoad(Addr.getElementType(), 109 emitRawPointerFromAddress(Addr), 110 Addr.getAlignment().getAsAlign(), Name); 111 } CreateLoad(Address Addr,const char * Name)112 llvm::LoadInst *CreateLoad(Address Addr, const char *Name) { 113 // This overload is required to prevent string literals from 114 // ending up in the IsVolatile overload. 115 return CreateAlignedLoad(Addr.getElementType(), 116 emitRawPointerFromAddress(Addr), 117 Addr.getAlignment().getAsAlign(), Name); 118 } 119 llvm::LoadInst *CreateLoad(Address Addr, bool IsVolatile, 120 const llvm::Twine &Name = "") { 121 return CreateAlignedLoad( 122 Addr.getElementType(), emitRawPointerFromAddress(Addr), 123 Addr.getAlignment().getAsAlign(), IsVolatile, Name); 124 } 125 126 using CGBuilderBaseTy::CreateAlignedLoad; 127 llvm::LoadInst *CreateAlignedLoad(llvm::Type *Ty, llvm::Value *Addr, 128 CharUnits Align, 129 const llvm::Twine &Name = "") { 130 return CreateAlignedLoad(Ty, Addr, Align.getAsAlign(), Name); 131 } 132 133 // Note that we intentionally hide the CreateStore APIs that don't 134 // take an alignment. 135 llvm::StoreInst *CreateStore(llvm::Value *Val, Address Addr, 136 bool IsVolatile = false) { 137 return CreateAlignedStore(Val, emitRawPointerFromAddress(Addr), 138 Addr.getAlignment().getAsAlign(), IsVolatile); 139 } 140 141 using CGBuilderBaseTy::CreateAlignedStore; 142 llvm::StoreInst *CreateAlignedStore(llvm::Value *Val, llvm::Value *Addr, 143 CharUnits Align, 144 bool IsVolatile = false) { 145 return CreateAlignedStore(Val, Addr, Align.getAsAlign(), IsVolatile); 146 } 147 148 // FIXME: these "default-aligned" APIs should be removed, 149 // but I don't feel like fixing all the builtin code right now. 150 llvm::StoreInst *CreateDefaultAlignedStore(llvm::Value *Val, 151 llvm::Value *Addr, 152 bool IsVolatile = false) { 153 return CGBuilderBaseTy::CreateStore(Val, Addr, IsVolatile); 154 } 155 156 /// Emit a load from an i1 flag variable. 157 llvm::LoadInst *CreateFlagLoad(llvm::Value *Addr, 158 const llvm::Twine &Name = "") { 159 return CreateAlignedLoad(getInt1Ty(), Addr, CharUnits::One(), Name); 160 } 161 162 /// Emit a store to an i1 flag variable. CreateFlagStore(bool Value,llvm::Value * Addr)163 llvm::StoreInst *CreateFlagStore(bool Value, llvm::Value *Addr) { 164 return CreateAlignedStore(getInt1(Value), Addr, CharUnits::One()); 165 } 166 167 llvm::AtomicCmpXchgInst * 168 CreateAtomicCmpXchg(Address Addr, llvm::Value *Cmp, llvm::Value *New, 169 llvm::AtomicOrdering SuccessOrdering, 170 llvm::AtomicOrdering FailureOrdering, 171 llvm::SyncScope::ID SSID = llvm::SyncScope::System) { 172 return CGBuilderBaseTy::CreateAtomicCmpXchg( 173 Addr.emitRawPointer(*getCGF()), Cmp, New, 174 Addr.getAlignment().getAsAlign(), SuccessOrdering, FailureOrdering, 175 SSID); 176 } 177 178 llvm::AtomicRMWInst * 179 CreateAtomicRMW(llvm::AtomicRMWInst::BinOp Op, Address Addr, llvm::Value *Val, 180 llvm::AtomicOrdering Ordering, 181 llvm::SyncScope::ID SSID = llvm::SyncScope::System) { 182 return CGBuilderBaseTy::CreateAtomicRMW( 183 Op, Addr.emitRawPointer(*getCGF()), Val, 184 Addr.getAlignment().getAsAlign(), Ordering, SSID); 185 } 186 187 using CGBuilderBaseTy::CreateAddrSpaceCast; 188 Address CreateAddrSpaceCast(Address Addr, llvm::Type *Ty, 189 llvm::Type *ElementTy, 190 const llvm::Twine &Name = "") { 191 if (!Addr.hasOffset()) 192 return Address(CreateAddrSpaceCast(Addr.getBasePointer(), Ty, Name), 193 ElementTy, Addr.getAlignment(), Addr.getPointerAuthInfo(), 194 /*Offset=*/nullptr, Addr.isKnownNonNull()); 195 // Eagerly force a raw address if these is an offset. 196 return RawAddress( 197 CreateAddrSpaceCast(Addr.emitRawPointer(*getCGF()), Ty, Name), 198 ElementTy, Addr.getAlignment(), Addr.isKnownNonNull()); 199 } 200 201 using CGBuilderBaseTy::CreatePointerBitCastOrAddrSpaceCast; 202 Address CreatePointerBitCastOrAddrSpaceCast(Address Addr, llvm::Type *Ty, 203 llvm::Type *ElementTy, 204 const llvm::Twine &Name = "") { 205 if (Addr.getType()->getAddressSpace() == Ty->getPointerAddressSpace()) 206 return Addr.withElementType(ElementTy); 207 return CreateAddrSpaceCast(Addr, Ty, ElementTy, Name); 208 } 209 210 /// Given 211 /// %addr = {T1, T2...}* ... 212 /// produce 213 /// %name = getelementptr inbounds %addr, i32 0, i32 index 214 /// 215 /// This API assumes that drilling into a struct like this is always an 216 /// inbounds operation. 217 using CGBuilderBaseTy::CreateStructGEP; 218 Address CreateStructGEP(Address Addr, unsigned Index, 219 const llvm::Twine &Name = "") { 220 llvm::StructType *ElTy = cast<llvm::StructType>(Addr.getElementType()); 221 const llvm::DataLayout &DL = BB->getDataLayout(); 222 const llvm::StructLayout *Layout = DL.getStructLayout(ElTy); 223 auto Offset = CharUnits::fromQuantity(Layout->getElementOffset(Index)); 224 225 return Address(CreateStructGEP(Addr.getElementType(), Addr.getBasePointer(), 226 Index, Name), 227 ElTy->getElementType(Index), 228 Addr.getAlignment().alignmentAtOffset(Offset), 229 Addr.isKnownNonNull()); 230 } 231 232 /// Given 233 /// %addr = [n x T]* ... 234 /// produce 235 /// %name = getelementptr inbounds %addr, i64 0, i64 index 236 /// where i64 is actually the target word size. 237 /// 238 /// This API assumes that drilling into an array like this is always 239 /// an inbounds operation. 240 Address CreateConstArrayGEP(Address Addr, uint64_t Index, 241 const llvm::Twine &Name = "") { 242 llvm::ArrayType *ElTy = cast<llvm::ArrayType>(Addr.getElementType()); 243 const llvm::DataLayout &DL = BB->getDataLayout(); 244 CharUnits EltSize = 245 CharUnits::fromQuantity(DL.getTypeAllocSize(ElTy->getElementType())); 246 247 return Address( 248 CreateInBoundsGEP(Addr.getElementType(), Addr.getBasePointer(), 249 {getSize(CharUnits::Zero()), getSize(Index)}, Name), 250 ElTy->getElementType(), 251 Addr.getAlignment().alignmentAtOffset(Index * EltSize), 252 Addr.isKnownNonNull()); 253 } 254 255 /// Given 256 /// %addr = T* ... 257 /// produce 258 /// %name = getelementptr inbounds %addr, i64 index 259 /// where i64 is actually the target word size. 260 Address CreateConstInBoundsGEP(Address Addr, uint64_t Index, 261 const llvm::Twine &Name = "") { 262 llvm::Type *ElTy = Addr.getElementType(); 263 const llvm::DataLayout &DL = BB->getDataLayout(); 264 CharUnits EltSize = CharUnits::fromQuantity(DL.getTypeAllocSize(ElTy)); 265 266 return Address( 267 CreateInBoundsGEP(ElTy, Addr.getBasePointer(), getSize(Index), Name), 268 ElTy, Addr.getAlignment().alignmentAtOffset(Index * EltSize), 269 Addr.isKnownNonNull()); 270 } 271 272 /// Given 273 /// %addr = T* ... 274 /// produce 275 /// %name = getelementptr inbounds %addr, i64 index 276 /// where i64 is actually the target word size. 277 Address CreateConstGEP(Address Addr, uint64_t Index, 278 const llvm::Twine &Name = "") { 279 llvm::Type *ElTy = Addr.getElementType(); 280 const llvm::DataLayout &DL = BB->getDataLayout(); 281 CharUnits EltSize = CharUnits::fromQuantity(DL.getTypeAllocSize(ElTy)); 282 283 return Address(CreateGEP(ElTy, Addr.getBasePointer(), getSize(Index), Name), 284 Addr.getElementType(), 285 Addr.getAlignment().alignmentAtOffset(Index * EltSize)); 286 } 287 288 /// Create GEP with single dynamic index. The address alignment is reduced 289 /// according to the element size. 290 using CGBuilderBaseTy::CreateGEP; 291 Address CreateGEP(CodeGenFunction &CGF, Address Addr, llvm::Value *Index, 292 const llvm::Twine &Name = "") { 293 const llvm::DataLayout &DL = BB->getDataLayout(); 294 CharUnits EltSize = 295 CharUnits::fromQuantity(DL.getTypeAllocSize(Addr.getElementType())); 296 297 return Address( 298 CreateGEP(Addr.getElementType(), Addr.emitRawPointer(CGF), Index, Name), 299 Addr.getElementType(), 300 Addr.getAlignment().alignmentOfArrayElement(EltSize)); 301 } 302 303 /// Given a pointer to i8, adjust it by a given constant offset. 304 Address CreateConstInBoundsByteGEP(Address Addr, CharUnits Offset, 305 const llvm::Twine &Name = "") { 306 assert(Addr.getElementType() == TypeCache.Int8Ty); 307 return Address( 308 CreateInBoundsGEP(Addr.getElementType(), Addr.getBasePointer(), 309 getSize(Offset), Name), 310 Addr.getElementType(), Addr.getAlignment().alignmentAtOffset(Offset), 311 Addr.isKnownNonNull()); 312 } 313 314 Address CreateConstByteGEP(Address Addr, CharUnits Offset, 315 const llvm::Twine &Name = "") { 316 assert(Addr.getElementType() == TypeCache.Int8Ty); 317 return Address(CreateGEP(Addr.getElementType(), Addr.getBasePointer(), 318 getSize(Offset), Name), 319 Addr.getElementType(), 320 Addr.getAlignment().alignmentAtOffset(Offset)); 321 } 322 323 using CGBuilderBaseTy::CreateConstInBoundsGEP2_32; 324 Address CreateConstInBoundsGEP2_32(Address Addr, unsigned Idx0, unsigned Idx1, 325 const llvm::Twine &Name = "") { 326 return createConstGEP2_32<true>(Addr, Idx0, Idx1, Name); 327 } 328 329 using CGBuilderBaseTy::CreateConstGEP2_32; 330 Address CreateConstGEP2_32(Address Addr, unsigned Idx0, unsigned Idx1, 331 const llvm::Twine &Name = "") { 332 return createConstGEP2_32<false>(Addr, Idx0, Idx1, Name); 333 } 334 335 Address CreateGEP(Address Addr, ArrayRef<llvm::Value *> IdxList, 336 llvm::Type *ElementType, CharUnits Align, 337 const Twine &Name = "") { 338 llvm::Value *Ptr = emitRawPointerFromAddress(Addr); 339 return RawAddress(CreateGEP(Addr.getElementType(), Ptr, IdxList, Name), 340 ElementType, Align); 341 } 342 343 using CGBuilderBaseTy::CreateInBoundsGEP; 344 Address CreateInBoundsGEP(Address Addr, ArrayRef<llvm::Value *> IdxList, 345 llvm::Type *ElementType, CharUnits Align, 346 const Twine &Name = "") { 347 return RawAddress(CreateInBoundsGEP(Addr.getElementType(), 348 emitRawPointerFromAddress(Addr), 349 IdxList, Name), 350 ElementType, Align, Addr.isKnownNonNull()); 351 } 352 353 using CGBuilderBaseTy::CreateIsNull; 354 llvm::Value *CreateIsNull(Address Addr, const Twine &Name = "") { 355 if (!Addr.hasOffset()) 356 return CreateIsNull(Addr.getBasePointer(), Name); 357 // The pointer isn't null if Addr has an offset since offsets can always 358 // be applied inbound. 359 return llvm::ConstantInt::getFalse(Context); 360 } 361 362 using CGBuilderBaseTy::CreateMemCpy; 363 llvm::CallInst *CreateMemCpy(Address Dest, Address Src, llvm::Value *Size, 364 bool IsVolatile = false) { 365 llvm::Value *DestPtr = emitRawPointerFromAddress(Dest); 366 llvm::Value *SrcPtr = emitRawPointerFromAddress(Src); 367 return CreateMemCpy(DestPtr, Dest.getAlignment().getAsAlign(), SrcPtr, 368 Src.getAlignment().getAsAlign(), Size, IsVolatile); 369 } 370 llvm::CallInst *CreateMemCpy(Address Dest, Address Src, uint64_t Size, 371 bool IsVolatile = false) { 372 llvm::Value *DestPtr = emitRawPointerFromAddress(Dest); 373 llvm::Value *SrcPtr = emitRawPointerFromAddress(Src); 374 return CreateMemCpy(DestPtr, Dest.getAlignment().getAsAlign(), SrcPtr, 375 Src.getAlignment().getAsAlign(), Size, IsVolatile); 376 } 377 378 using CGBuilderBaseTy::CreateMemCpyInline; CreateMemCpyInline(Address Dest,Address Src,uint64_t Size)379 llvm::CallInst *CreateMemCpyInline(Address Dest, Address Src, uint64_t Size) { 380 llvm::Value *DestPtr = emitRawPointerFromAddress(Dest); 381 llvm::Value *SrcPtr = emitRawPointerFromAddress(Src); 382 return CreateMemCpyInline(DestPtr, Dest.getAlignment().getAsAlign(), SrcPtr, 383 Src.getAlignment().getAsAlign(), getInt64(Size)); 384 } 385 386 using CGBuilderBaseTy::CreateMemMove; 387 llvm::CallInst *CreateMemMove(Address Dest, Address Src, llvm::Value *Size, 388 bool IsVolatile = false) { 389 llvm::Value *DestPtr = emitRawPointerFromAddress(Dest); 390 llvm::Value *SrcPtr = emitRawPointerFromAddress(Src); 391 return CreateMemMove(DestPtr, Dest.getAlignment().getAsAlign(), SrcPtr, 392 Src.getAlignment().getAsAlign(), Size, IsVolatile); 393 } 394 395 using CGBuilderBaseTy::CreateMemSet; 396 llvm::CallInst *CreateMemSet(Address Dest, llvm::Value *Value, 397 llvm::Value *Size, bool IsVolatile = false) { 398 return CreateMemSet(emitRawPointerFromAddress(Dest), Value, Size, 399 Dest.getAlignment().getAsAlign(), IsVolatile); 400 } 401 402 using CGBuilderBaseTy::CreateMemSetInline; CreateMemSetInline(Address Dest,llvm::Value * Value,uint64_t Size)403 llvm::CallInst *CreateMemSetInline(Address Dest, llvm::Value *Value, 404 uint64_t Size) { 405 return CreateMemSetInline(emitRawPointerFromAddress(Dest), 406 Dest.getAlignment().getAsAlign(), Value, 407 getInt64(Size)); 408 } 409 410 using CGBuilderBaseTy::CreatePreserveStructAccessIndex; CreatePreserveStructAccessIndex(Address Addr,unsigned Index,unsigned FieldIndex,llvm::MDNode * DbgInfo)411 Address CreatePreserveStructAccessIndex(Address Addr, unsigned Index, 412 unsigned FieldIndex, 413 llvm::MDNode *DbgInfo) { 414 llvm::StructType *ElTy = cast<llvm::StructType>(Addr.getElementType()); 415 const llvm::DataLayout &DL = BB->getDataLayout(); 416 const llvm::StructLayout *Layout = DL.getStructLayout(ElTy); 417 auto Offset = CharUnits::fromQuantity(Layout->getElementOffset(Index)); 418 419 return Address( 420 CreatePreserveStructAccessIndex(ElTy, emitRawPointerFromAddress(Addr), 421 Index, FieldIndex, DbgInfo), 422 ElTy->getElementType(Index), 423 Addr.getAlignment().alignmentAtOffset(Offset)); 424 } 425 426 using CGBuilderBaseTy::CreatePreserveUnionAccessIndex; CreatePreserveUnionAccessIndex(Address Addr,unsigned FieldIndex,llvm::MDNode * DbgInfo)427 Address CreatePreserveUnionAccessIndex(Address Addr, unsigned FieldIndex, 428 llvm::MDNode *DbgInfo) { 429 Addr.replaceBasePointer(CreatePreserveUnionAccessIndex( 430 Addr.getBasePointer(), FieldIndex, DbgInfo)); 431 return Addr; 432 } 433 434 using CGBuilderBaseTy::CreateLaunderInvariantGroup; CreateLaunderInvariantGroup(Address Addr)435 Address CreateLaunderInvariantGroup(Address Addr) { 436 Addr.replaceBasePointer(CreateLaunderInvariantGroup(Addr.getBasePointer())); 437 return Addr; 438 } 439 440 using CGBuilderBaseTy::CreateStripInvariantGroup; CreateStripInvariantGroup(Address Addr)441 Address CreateStripInvariantGroup(Address Addr) { 442 Addr.replaceBasePointer(CreateStripInvariantGroup(Addr.getBasePointer())); 443 return Addr; 444 } 445 }; 446 447 } // end namespace CodeGen 448 } // end namespace clang 449 450 #endif 451