Path: blob/main/contrib/llvm-project/clang/lib/CodeGen/CGBuilder.h
35233 views
//===-- CGBuilder.h - Choose IRBuilder implementation ----------*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#ifndef LLVM_CLANG_LIB_CODEGEN_CGBUILDER_H9#define LLVM_CLANG_LIB_CODEGEN_CGBUILDER_H1011#include "Address.h"12#include "CGValue.h"13#include "CodeGenTypeCache.h"14#include "llvm/Analysis/Utils/Local.h"15#include "llvm/IR/DataLayout.h"16#include "llvm/IR/IRBuilder.h"17#include "llvm/IR/Type.h"1819namespace clang {20namespace CodeGen {2122class CGBuilderTy;23class CodeGenFunction;2425/// This is an IRBuilder insertion helper that forwards to26/// CodeGenFunction::InsertHelper, which adds necessary metadata to27/// instructions.28class CGBuilderInserter final : public llvm::IRBuilderDefaultInserter {29friend CGBuilderTy;3031public:32CGBuilderInserter() = default;33explicit CGBuilderInserter(CodeGenFunction *CGF) : CGF(CGF) {}3435/// This forwards to CodeGenFunction::InsertHelper.36void InsertHelper(llvm::Instruction *I, const llvm::Twine &Name,37llvm::BasicBlock::iterator InsertPt) const override;3839private:40CodeGenFunction *CGF = nullptr;41};4243typedef CGBuilderInserter CGBuilderInserterTy;4445typedef llvm::IRBuilder<llvm::ConstantFolder, CGBuilderInserterTy>46CGBuilderBaseTy;4748class CGBuilderTy : public CGBuilderBaseTy {49friend class Address;5051/// Storing a reference to the type cache here makes it a lot easier52/// to build natural-feeling, target-specific IR.53const CodeGenTypeCache &TypeCache;5455CodeGenFunction *getCGF() const { return getInserter().CGF; }5657llvm::Value *emitRawPointerFromAddress(Address Addr) const {58return Addr.getBasePointer();59}6061template <bool IsInBounds>62Address createConstGEP2_32(Address Addr, unsigned Idx0, unsigned Idx1,63const llvm::Twine &Name) {64const llvm::DataLayout &DL = BB->getDataLayout();65llvm::GetElementPtrInst *GEP;66if (IsInBounds)67GEP = cast<llvm::GetElementPtrInst>(CreateConstInBoundsGEP2_32(68Addr.getElementType(), emitRawPointerFromAddress(Addr), Idx0, Idx1,69Name));70else71GEP = cast<llvm::GetElementPtrInst>(CreateConstGEP2_32(72Addr.getElementType(), emitRawPointerFromAddress(Addr), Idx0, Idx1,73Name));74llvm::APInt Offset(75DL.getIndexSizeInBits(Addr.getType()->getPointerAddressSpace()), 0,76/*isSigned=*/true);77if (!GEP->accumulateConstantOffset(DL, Offset))78llvm_unreachable("offset of GEP with constants is always computable");79return Address(GEP, GEP->getResultElementType(),80Addr.getAlignment().alignmentAtOffset(81CharUnits::fromQuantity(Offset.getSExtValue())),82IsInBounds ? Addr.isKnownNonNull() : NotKnownNonNull);83}8485public:86CGBuilderTy(const CodeGenTypeCache &TypeCache, llvm::LLVMContext &C)87: CGBuilderBaseTy(C), TypeCache(TypeCache) {}88CGBuilderTy(const CodeGenTypeCache &TypeCache, llvm::LLVMContext &C,89const llvm::ConstantFolder &F,90const CGBuilderInserterTy &Inserter)91: CGBuilderBaseTy(C, F, Inserter), TypeCache(TypeCache) {}92CGBuilderTy(const CodeGenTypeCache &TypeCache, llvm::Instruction *I)93: CGBuilderBaseTy(I), TypeCache(TypeCache) {}94CGBuilderTy(const CodeGenTypeCache &TypeCache, llvm::BasicBlock *BB)95: CGBuilderBaseTy(BB), TypeCache(TypeCache) {}9697llvm::ConstantInt *getSize(CharUnits N) {98return llvm::ConstantInt::get(TypeCache.SizeTy, N.getQuantity());99}100llvm::ConstantInt *getSize(uint64_t N) {101return llvm::ConstantInt::get(TypeCache.SizeTy, N);102}103104// Note that we intentionally hide the CreateLoad APIs that don't105// take an alignment.106llvm::LoadInst *CreateLoad(Address Addr, const llvm::Twine &Name = "") {107return CreateAlignedLoad(Addr.getElementType(),108emitRawPointerFromAddress(Addr),109Addr.getAlignment().getAsAlign(), Name);110}111llvm::LoadInst *CreateLoad(Address Addr, const char *Name) {112// This overload is required to prevent string literals from113// ending up in the IsVolatile overload.114return CreateAlignedLoad(Addr.getElementType(),115emitRawPointerFromAddress(Addr),116Addr.getAlignment().getAsAlign(), Name);117}118llvm::LoadInst *CreateLoad(Address Addr, bool IsVolatile,119const llvm::Twine &Name = "") {120return CreateAlignedLoad(121Addr.getElementType(), emitRawPointerFromAddress(Addr),122Addr.getAlignment().getAsAlign(), IsVolatile, Name);123}124125using CGBuilderBaseTy::CreateAlignedLoad;126llvm::LoadInst *CreateAlignedLoad(llvm::Type *Ty, llvm::Value *Addr,127CharUnits Align,128const llvm::Twine &Name = "") {129return CreateAlignedLoad(Ty, Addr, Align.getAsAlign(), Name);130}131132// Note that we intentionally hide the CreateStore APIs that don't133// take an alignment.134llvm::StoreInst *CreateStore(llvm::Value *Val, Address Addr,135bool IsVolatile = false) {136return CreateAlignedStore(Val, emitRawPointerFromAddress(Addr),137Addr.getAlignment().getAsAlign(), IsVolatile);138}139140using CGBuilderBaseTy::CreateAlignedStore;141llvm::StoreInst *CreateAlignedStore(llvm::Value *Val, llvm::Value *Addr,142CharUnits Align,143bool IsVolatile = false) {144return CreateAlignedStore(Val, Addr, Align.getAsAlign(), IsVolatile);145}146147// FIXME: these "default-aligned" APIs should be removed,148// but I don't feel like fixing all the builtin code right now.149llvm::StoreInst *CreateDefaultAlignedStore(llvm::Value *Val,150llvm::Value *Addr,151bool IsVolatile = false) {152return CGBuilderBaseTy::CreateStore(Val, Addr, IsVolatile);153}154155/// Emit a load from an i1 flag variable.156llvm::LoadInst *CreateFlagLoad(llvm::Value *Addr,157const llvm::Twine &Name = "") {158return CreateAlignedLoad(getInt1Ty(), Addr, CharUnits::One(), Name);159}160161/// Emit a store to an i1 flag variable.162llvm::StoreInst *CreateFlagStore(bool Value, llvm::Value *Addr) {163return CreateAlignedStore(getInt1(Value), Addr, CharUnits::One());164}165166llvm::AtomicCmpXchgInst *167CreateAtomicCmpXchg(Address Addr, llvm::Value *Cmp, llvm::Value *New,168llvm::AtomicOrdering SuccessOrdering,169llvm::AtomicOrdering FailureOrdering,170llvm::SyncScope::ID SSID = llvm::SyncScope::System) {171return CGBuilderBaseTy::CreateAtomicCmpXchg(172Addr.emitRawPointer(*getCGF()), Cmp, New,173Addr.getAlignment().getAsAlign(), SuccessOrdering, FailureOrdering,174SSID);175}176177llvm::AtomicRMWInst *178CreateAtomicRMW(llvm::AtomicRMWInst::BinOp Op, Address Addr, llvm::Value *Val,179llvm::AtomicOrdering Ordering,180llvm::SyncScope::ID SSID = llvm::SyncScope::System) {181return CGBuilderBaseTy::CreateAtomicRMW(182Op, Addr.emitRawPointer(*getCGF()), Val,183Addr.getAlignment().getAsAlign(), Ordering, SSID);184}185186using CGBuilderBaseTy::CreateAddrSpaceCast;187Address CreateAddrSpaceCast(Address Addr, llvm::Type *Ty,188llvm::Type *ElementTy,189const llvm::Twine &Name = "") {190if (!Addr.hasOffset())191return Address(CreateAddrSpaceCast(Addr.getBasePointer(), Ty, Name),192ElementTy, Addr.getAlignment(), Addr.getPointerAuthInfo(),193/*Offset=*/nullptr, Addr.isKnownNonNull());194// Eagerly force a raw address if these is an offset.195return RawAddress(196CreateAddrSpaceCast(Addr.emitRawPointer(*getCGF()), Ty, Name),197ElementTy, Addr.getAlignment(), Addr.isKnownNonNull());198}199200using CGBuilderBaseTy::CreatePointerBitCastOrAddrSpaceCast;201Address CreatePointerBitCastOrAddrSpaceCast(Address Addr, llvm::Type *Ty,202llvm::Type *ElementTy,203const llvm::Twine &Name = "") {204if (Addr.getType()->getAddressSpace() == Ty->getPointerAddressSpace())205return Addr.withElementType(ElementTy);206return CreateAddrSpaceCast(Addr, Ty, ElementTy, Name);207}208209/// Given210/// %addr = {T1, T2...}* ...211/// produce212/// %name = getelementptr inbounds %addr, i32 0, i32 index213///214/// This API assumes that drilling into a struct like this is always an215/// inbounds operation.216using CGBuilderBaseTy::CreateStructGEP;217Address CreateStructGEP(Address Addr, unsigned Index,218const llvm::Twine &Name = "") {219llvm::StructType *ElTy = cast<llvm::StructType>(Addr.getElementType());220const llvm::DataLayout &DL = BB->getDataLayout();221const llvm::StructLayout *Layout = DL.getStructLayout(ElTy);222auto Offset = CharUnits::fromQuantity(Layout->getElementOffset(Index));223224return Address(CreateStructGEP(Addr.getElementType(), Addr.getBasePointer(),225Index, Name),226ElTy->getElementType(Index),227Addr.getAlignment().alignmentAtOffset(Offset),228Addr.isKnownNonNull());229}230231/// Given232/// %addr = [n x T]* ...233/// produce234/// %name = getelementptr inbounds %addr, i64 0, i64 index235/// where i64 is actually the target word size.236///237/// This API assumes that drilling into an array like this is always238/// an inbounds operation.239Address CreateConstArrayGEP(Address Addr, uint64_t Index,240const llvm::Twine &Name = "") {241llvm::ArrayType *ElTy = cast<llvm::ArrayType>(Addr.getElementType());242const llvm::DataLayout &DL = BB->getDataLayout();243CharUnits EltSize =244CharUnits::fromQuantity(DL.getTypeAllocSize(ElTy->getElementType()));245246return Address(247CreateInBoundsGEP(Addr.getElementType(), Addr.getBasePointer(),248{getSize(CharUnits::Zero()), getSize(Index)}, Name),249ElTy->getElementType(),250Addr.getAlignment().alignmentAtOffset(Index * EltSize),251Addr.isKnownNonNull());252}253254/// Given255/// %addr = T* ...256/// produce257/// %name = getelementptr inbounds %addr, i64 index258/// where i64 is actually the target word size.259Address CreateConstInBoundsGEP(Address Addr, uint64_t Index,260const llvm::Twine &Name = "") {261llvm::Type *ElTy = Addr.getElementType();262const llvm::DataLayout &DL = BB->getDataLayout();263CharUnits EltSize = CharUnits::fromQuantity(DL.getTypeAllocSize(ElTy));264265return Address(266CreateInBoundsGEP(ElTy, Addr.getBasePointer(), getSize(Index), Name),267ElTy, Addr.getAlignment().alignmentAtOffset(Index * EltSize),268Addr.isKnownNonNull());269}270271/// Given272/// %addr = T* ...273/// produce274/// %name = getelementptr inbounds %addr, i64 index275/// where i64 is actually the target word size.276Address CreateConstGEP(Address Addr, uint64_t Index,277const llvm::Twine &Name = "") {278llvm::Type *ElTy = Addr.getElementType();279const llvm::DataLayout &DL = BB->getDataLayout();280CharUnits EltSize = CharUnits::fromQuantity(DL.getTypeAllocSize(ElTy));281282return Address(CreateGEP(ElTy, Addr.getBasePointer(), getSize(Index), Name),283Addr.getElementType(),284Addr.getAlignment().alignmentAtOffset(Index * EltSize));285}286287/// Create GEP with single dynamic index. The address alignment is reduced288/// according to the element size.289using CGBuilderBaseTy::CreateGEP;290Address CreateGEP(CodeGenFunction &CGF, Address Addr, llvm::Value *Index,291const llvm::Twine &Name = "") {292const llvm::DataLayout &DL = BB->getDataLayout();293CharUnits EltSize =294CharUnits::fromQuantity(DL.getTypeAllocSize(Addr.getElementType()));295296return Address(297CreateGEP(Addr.getElementType(), Addr.emitRawPointer(CGF), Index, Name),298Addr.getElementType(),299Addr.getAlignment().alignmentOfArrayElement(EltSize));300}301302/// Given a pointer to i8, adjust it by a given constant offset.303Address CreateConstInBoundsByteGEP(Address Addr, CharUnits Offset,304const llvm::Twine &Name = "") {305assert(Addr.getElementType() == TypeCache.Int8Ty);306return Address(307CreateInBoundsGEP(Addr.getElementType(), Addr.getBasePointer(),308getSize(Offset), Name),309Addr.getElementType(), Addr.getAlignment().alignmentAtOffset(Offset),310Addr.isKnownNonNull());311}312313Address CreateConstByteGEP(Address Addr, CharUnits Offset,314const llvm::Twine &Name = "") {315assert(Addr.getElementType() == TypeCache.Int8Ty);316return Address(CreateGEP(Addr.getElementType(), Addr.getBasePointer(),317getSize(Offset), Name),318Addr.getElementType(),319Addr.getAlignment().alignmentAtOffset(Offset));320}321322using CGBuilderBaseTy::CreateConstInBoundsGEP2_32;323Address CreateConstInBoundsGEP2_32(Address Addr, unsigned Idx0, unsigned Idx1,324const llvm::Twine &Name = "") {325return createConstGEP2_32<true>(Addr, Idx0, Idx1, Name);326}327328using CGBuilderBaseTy::CreateConstGEP2_32;329Address CreateConstGEP2_32(Address Addr, unsigned Idx0, unsigned Idx1,330const llvm::Twine &Name = "") {331return createConstGEP2_32<false>(Addr, Idx0, Idx1, Name);332}333334Address CreateGEP(Address Addr, ArrayRef<llvm::Value *> IdxList,335llvm::Type *ElementType, CharUnits Align,336const Twine &Name = "") {337llvm::Value *Ptr = emitRawPointerFromAddress(Addr);338return RawAddress(CreateGEP(Addr.getElementType(), Ptr, IdxList, Name),339ElementType, Align);340}341342using CGBuilderBaseTy::CreateInBoundsGEP;343Address CreateInBoundsGEP(Address Addr, ArrayRef<llvm::Value *> IdxList,344llvm::Type *ElementType, CharUnits Align,345const Twine &Name = "") {346return RawAddress(CreateInBoundsGEP(Addr.getElementType(),347emitRawPointerFromAddress(Addr),348IdxList, Name),349ElementType, Align, Addr.isKnownNonNull());350}351352using CGBuilderBaseTy::CreateIsNull;353llvm::Value *CreateIsNull(Address Addr, const Twine &Name = "") {354if (!Addr.hasOffset())355return CreateIsNull(Addr.getBasePointer(), Name);356// The pointer isn't null if Addr has an offset since offsets can always357// be applied inbound.358return llvm::ConstantInt::getFalse(Context);359}360361using CGBuilderBaseTy::CreateMemCpy;362llvm::CallInst *CreateMemCpy(Address Dest, Address Src, llvm::Value *Size,363bool IsVolatile = false) {364llvm::Value *DestPtr = emitRawPointerFromAddress(Dest);365llvm::Value *SrcPtr = emitRawPointerFromAddress(Src);366return CreateMemCpy(DestPtr, Dest.getAlignment().getAsAlign(), SrcPtr,367Src.getAlignment().getAsAlign(), Size, IsVolatile);368}369llvm::CallInst *CreateMemCpy(Address Dest, Address Src, uint64_t Size,370bool IsVolatile = false) {371llvm::Value *DestPtr = emitRawPointerFromAddress(Dest);372llvm::Value *SrcPtr = emitRawPointerFromAddress(Src);373return CreateMemCpy(DestPtr, Dest.getAlignment().getAsAlign(), SrcPtr,374Src.getAlignment().getAsAlign(), Size, IsVolatile);375}376377using CGBuilderBaseTy::CreateMemCpyInline;378llvm::CallInst *CreateMemCpyInline(Address Dest, Address Src, uint64_t Size) {379llvm::Value *DestPtr = emitRawPointerFromAddress(Dest);380llvm::Value *SrcPtr = emitRawPointerFromAddress(Src);381return CreateMemCpyInline(DestPtr, Dest.getAlignment().getAsAlign(), SrcPtr,382Src.getAlignment().getAsAlign(), getInt64(Size));383}384385using CGBuilderBaseTy::CreateMemMove;386llvm::CallInst *CreateMemMove(Address Dest, Address Src, llvm::Value *Size,387bool IsVolatile = false) {388llvm::Value *DestPtr = emitRawPointerFromAddress(Dest);389llvm::Value *SrcPtr = emitRawPointerFromAddress(Src);390return CreateMemMove(DestPtr, Dest.getAlignment().getAsAlign(), SrcPtr,391Src.getAlignment().getAsAlign(), Size, IsVolatile);392}393394using CGBuilderBaseTy::CreateMemSet;395llvm::CallInst *CreateMemSet(Address Dest, llvm::Value *Value,396llvm::Value *Size, bool IsVolatile = false) {397return CreateMemSet(emitRawPointerFromAddress(Dest), Value, Size,398Dest.getAlignment().getAsAlign(), IsVolatile);399}400401using CGBuilderBaseTy::CreateMemSetInline;402llvm::CallInst *CreateMemSetInline(Address Dest, llvm::Value *Value,403uint64_t Size) {404return CreateMemSetInline(emitRawPointerFromAddress(Dest),405Dest.getAlignment().getAsAlign(), Value,406getInt64(Size));407}408409using CGBuilderBaseTy::CreatePreserveStructAccessIndex;410Address CreatePreserveStructAccessIndex(Address Addr, unsigned Index,411unsigned FieldIndex,412llvm::MDNode *DbgInfo) {413llvm::StructType *ElTy = cast<llvm::StructType>(Addr.getElementType());414const llvm::DataLayout &DL = BB->getDataLayout();415const llvm::StructLayout *Layout = DL.getStructLayout(ElTy);416auto Offset = CharUnits::fromQuantity(Layout->getElementOffset(Index));417418return Address(419CreatePreserveStructAccessIndex(ElTy, emitRawPointerFromAddress(Addr),420Index, FieldIndex, DbgInfo),421ElTy->getElementType(Index),422Addr.getAlignment().alignmentAtOffset(Offset));423}424425using CGBuilderBaseTy::CreatePreserveUnionAccessIndex;426Address CreatePreserveUnionAccessIndex(Address Addr, unsigned FieldIndex,427llvm::MDNode *DbgInfo) {428Addr.replaceBasePointer(CreatePreserveUnionAccessIndex(429Addr.getBasePointer(), FieldIndex, DbgInfo));430return Addr;431}432433using CGBuilderBaseTy::CreateLaunderInvariantGroup;434Address CreateLaunderInvariantGroup(Address Addr) {435Addr.replaceBasePointer(CreateLaunderInvariantGroup(Addr.getBasePointer()));436return Addr;437}438439using CGBuilderBaseTy::CreateStripInvariantGroup;440Address CreateStripInvariantGroup(Address Addr) {441Addr.replaceBasePointer(CreateStripInvariantGroup(Addr.getBasePointer()));442return Addr;443}444};445446} // end namespace CodeGen447} // end namespace clang448449#endif450451452