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