brintos

brintos / llvm-project-archived public Read only

0
0
Text · 19.0 KiB · 090f75d Raw
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