Home | History | Annotate | Line # | Download | only in CodeGen
      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 "llvm/IR/DataLayout.h"
     13 #include "llvm/IR/IRBuilder.h"
     14 #include "Address.h"
     15 #include "CodeGenTypeCache.h"
     16 
     17 namespace clang {
     18 namespace CodeGen {
     19 
     20 class CodeGenFunction;
     21 
     22 /// This is an IRBuilder insertion helper that forwards to
     23 /// CodeGenFunction::InsertHelper, which adds necessary metadata to
     24 /// instructions.
     25 class CGBuilderInserter final : public llvm::IRBuilderDefaultInserter {
     26 public:
     27   CGBuilderInserter() = default;
     28   explicit CGBuilderInserter(CodeGenFunction *CGF) : CGF(CGF) {}
     29 
     30   /// This forwards to CodeGenFunction::InsertHelper.
     31   void InsertHelper(llvm::Instruction *I, const llvm::Twine &Name,
     32                     llvm::BasicBlock *BB,
     33                     llvm::BasicBlock::iterator InsertPt) const override;
     34 private:
     35   CodeGenFunction *CGF = nullptr;
     36 };
     37 
     38 typedef CGBuilderInserter CGBuilderInserterTy;
     39 
     40 typedef llvm::IRBuilder<llvm::ConstantFolder, CGBuilderInserterTy>
     41     CGBuilderBaseTy;
     42 
     43 class CGBuilderTy : public CGBuilderBaseTy {
     44   /// Storing a reference to the type cache here makes it a lot easier
     45   /// to build natural-feeling, target-specific IR.
     46   const CodeGenTypeCache &TypeCache;
     47 public:
     48   CGBuilderTy(const CodeGenTypeCache &TypeCache, llvm::LLVMContext &C)
     49     : CGBuilderBaseTy(C), TypeCache(TypeCache) {}
     50   CGBuilderTy(const CodeGenTypeCache &TypeCache,
     51               llvm::LLVMContext &C, const llvm::ConstantFolder &F,
     52               const CGBuilderInserterTy &Inserter)
     53     : CGBuilderBaseTy(C, F, Inserter), TypeCache(TypeCache) {}
     54   CGBuilderTy(const CodeGenTypeCache &TypeCache, llvm::Instruction *I)
     55     : CGBuilderBaseTy(I), TypeCache(TypeCache) {}
     56   CGBuilderTy(const CodeGenTypeCache &TypeCache, llvm::BasicBlock *BB)
     57     : CGBuilderBaseTy(BB), TypeCache(TypeCache) {}
     58 
     59   llvm::ConstantInt *getSize(CharUnits N) {
     60     return llvm::ConstantInt::get(TypeCache.SizeTy, N.getQuantity());
     61   }
     62   llvm::ConstantInt *getSize(uint64_t N) {
     63     return llvm::ConstantInt::get(TypeCache.SizeTy, N);
     64   }
     65 
     66   // Note that we intentionally hide the CreateLoad APIs that don't
     67   // take an alignment.
     68   llvm::LoadInst *CreateLoad(Address Addr, const llvm::Twine &Name = "") {
     69     return CreateAlignedLoad(Addr.getElementType(), Addr.getPointer(),
     70                              Addr.getAlignment().getAsAlign(), Name);
     71   }
     72   llvm::LoadInst *CreateLoad(Address Addr, const char *Name) {
     73     // This overload is required to prevent string literals from
     74     // ending up in the IsVolatile overload.
     75     return CreateAlignedLoad(Addr.getElementType(), Addr.getPointer(),
     76                              Addr.getAlignment().getAsAlign(), Name);
     77   }
     78   llvm::LoadInst *CreateLoad(Address Addr, bool IsVolatile,
     79                              const llvm::Twine &Name = "") {
     80     return CreateAlignedLoad(Addr.getElementType(), Addr.getPointer(),
     81                              Addr.getAlignment().getAsAlign(), IsVolatile,
     82                              Name);
     83   }
     84 
     85   using CGBuilderBaseTy::CreateAlignedLoad;
     86   llvm::LoadInst *CreateAlignedLoad(llvm::Type *Ty, llvm::Value *Addr,
     87                                     CharUnits Align,
     88                                     const llvm::Twine &Name = "") {
     89     assert(Addr->getType()->getPointerElementType() == Ty);
     90     return CreateAlignedLoad(Ty, Addr, Align.getAsAlign(), Name);
     91   }
     92 
     93   // Note that we intentionally hide the CreateStore APIs that don't
     94   // take an alignment.
     95   llvm::StoreInst *CreateStore(llvm::Value *Val, Address Addr,
     96                                bool IsVolatile = false) {
     97     return CreateAlignedStore(Val, Addr.getPointer(),
     98                               Addr.getAlignment().getAsAlign(), IsVolatile);
     99   }
    100 
    101   using CGBuilderBaseTy::CreateAlignedStore;
    102   llvm::StoreInst *CreateAlignedStore(llvm::Value *Val, llvm::Value *Addr,
    103                                       CharUnits Align, bool IsVolatile = false) {
    104     return CreateAlignedStore(Val, Addr, Align.getAsAlign(), IsVolatile);
    105   }
    106 
    107   // FIXME: these "default-aligned" APIs should be removed,
    108   // but I don't feel like fixing all the builtin code right now.
    109   llvm::StoreInst *CreateDefaultAlignedStore(llvm::Value *Val,
    110                                              llvm::Value *Addr,
    111                                              bool IsVolatile = false) {
    112     return CGBuilderBaseTy::CreateStore(Val, Addr, IsVolatile);
    113   }
    114 
    115   /// Emit a load from an i1 flag variable.
    116   llvm::LoadInst *CreateFlagLoad(llvm::Value *Addr,
    117                                  const llvm::Twine &Name = "") {
    118     assert(Addr->getType()->getPointerElementType() == getInt1Ty());
    119     return CreateAlignedLoad(getInt1Ty(), Addr, CharUnits::One(), Name);
    120   }
    121 
    122   /// Emit a store to an i1 flag variable.
    123   llvm::StoreInst *CreateFlagStore(bool Value, llvm::Value *Addr) {
    124     assert(Addr->getType()->getPointerElementType() == getInt1Ty());
    125     return CreateAlignedStore(getInt1(Value), Addr, CharUnits::One());
    126   }
    127 
    128   // Temporarily use old signature; clang will be updated to an Address overload
    129   // in a subsequent patch.
    130   llvm::AtomicCmpXchgInst *
    131   CreateAtomicCmpXchg(llvm::Value *Ptr, llvm::Value *Cmp, llvm::Value *New,
    132                       llvm::AtomicOrdering SuccessOrdering,
    133                       llvm::AtomicOrdering FailureOrdering,
    134                       llvm::SyncScope::ID SSID = llvm::SyncScope::System) {
    135     return CGBuilderBaseTy::CreateAtomicCmpXchg(
    136         Ptr, Cmp, New, llvm::MaybeAlign(), SuccessOrdering, FailureOrdering,
    137         SSID);
    138   }
    139 
    140   // Temporarily use old signature; clang will be updated to an Address overload
    141   // in a subsequent patch.
    142   llvm::AtomicRMWInst *
    143   CreateAtomicRMW(llvm::AtomicRMWInst::BinOp Op, llvm::Value *Ptr,
    144                   llvm::Value *Val, llvm::AtomicOrdering Ordering,
    145                   llvm::SyncScope::ID SSID = llvm::SyncScope::System) {
    146     return CGBuilderBaseTy::CreateAtomicRMW(Op, Ptr, Val, llvm::MaybeAlign(),
    147                                             Ordering, SSID);
    148   }
    149 
    150   using CGBuilderBaseTy::CreateBitCast;
    151   Address CreateBitCast(Address Addr, llvm::Type *Ty,
    152                         const llvm::Twine &Name = "") {
    153     return Address(CreateBitCast(Addr.getPointer(), Ty, Name),
    154                    Addr.getAlignment());
    155   }
    156 
    157   using CGBuilderBaseTy::CreateAddrSpaceCast;
    158   Address CreateAddrSpaceCast(Address Addr, llvm::Type *Ty,
    159                               const llvm::Twine &Name = "") {
    160     return Address(CreateAddrSpaceCast(Addr.getPointer(), Ty, Name),
    161                    Addr.getAlignment());
    162   }
    163 
    164   /// Cast the element type of the given address to a different type,
    165   /// preserving information like the alignment and address space.
    166   Address CreateElementBitCast(Address Addr, llvm::Type *Ty,
    167                                const llvm::Twine &Name = "") {
    168     auto PtrTy = Ty->getPointerTo(Addr.getAddressSpace());
    169     return CreateBitCast(Addr, PtrTy, Name);
    170   }
    171 
    172   using CGBuilderBaseTy::CreatePointerBitCastOrAddrSpaceCast;
    173   Address CreatePointerBitCastOrAddrSpaceCast(Address Addr, llvm::Type *Ty,
    174                                               const llvm::Twine &Name = "") {
    175     llvm::Value *Ptr =
    176       CreatePointerBitCastOrAddrSpaceCast(Addr.getPointer(), Ty, Name);
    177     return Address(Ptr, Addr.getAlignment());
    178   }
    179 
    180   /// Given
    181   ///   %addr = {T1, T2...}* ...
    182   /// produce
    183   ///   %name = getelementptr inbounds %addr, i32 0, i32 index
    184   ///
    185   /// This API assumes that drilling into a struct like this is always an
    186   /// inbounds operation.
    187   using CGBuilderBaseTy::CreateStructGEP;
    188   Address CreateStructGEP(Address Addr, unsigned Index,
    189                           const llvm::Twine &Name = "") {
    190     llvm::StructType *ElTy = cast<llvm::StructType>(Addr.getElementType());
    191     const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout();
    192     const llvm::StructLayout *Layout = DL.getStructLayout(ElTy);
    193     auto Offset = CharUnits::fromQuantity(Layout->getElementOffset(Index));
    194 
    195     return Address(CreateStructGEP(Addr.getElementType(),
    196                                    Addr.getPointer(), Index, Name),
    197                    Addr.getAlignment().alignmentAtOffset(Offset));
    198   }
    199 
    200   /// Given
    201   ///   %addr = [n x T]* ...
    202   /// produce
    203   ///   %name = getelementptr inbounds %addr, i64 0, i64 index
    204   /// where i64 is actually the target word size.
    205   ///
    206   /// This API assumes that drilling into an array like this is always
    207   /// an inbounds operation.
    208   Address CreateConstArrayGEP(Address Addr, uint64_t Index,
    209                               const llvm::Twine &Name = "") {
    210     llvm::ArrayType *ElTy = cast<llvm::ArrayType>(Addr.getElementType());
    211     const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout();
    212     CharUnits EltSize =
    213         CharUnits::fromQuantity(DL.getTypeAllocSize(ElTy->getElementType()));
    214 
    215     return Address(
    216         CreateInBoundsGEP(Addr.getElementType(), Addr.getPointer(),
    217                           {getSize(CharUnits::Zero()), getSize(Index)}, Name),
    218         Addr.getAlignment().alignmentAtOffset(Index * EltSize));
    219   }
    220 
    221   /// Given
    222   ///   %addr = T* ...
    223   /// produce
    224   ///   %name = getelementptr inbounds %addr, i64 index
    225   /// where i64 is actually the target word size.
    226   Address CreateConstInBoundsGEP(Address Addr, uint64_t Index,
    227                                  const llvm::Twine &Name = "") {
    228     llvm::Type *ElTy = Addr.getElementType();
    229     const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout();
    230     CharUnits EltSize = CharUnits::fromQuantity(DL.getTypeAllocSize(ElTy));
    231 
    232     return Address(CreateInBoundsGEP(Addr.getElementType(), Addr.getPointer(),
    233                                      getSize(Index), Name),
    234                    Addr.getAlignment().alignmentAtOffset(Index * EltSize));
    235   }
    236 
    237   /// Given
    238   ///   %addr = T* ...
    239   /// produce
    240   ///   %name = getelementptr inbounds %addr, i64 index
    241   /// where i64 is actually the target word size.
    242   Address CreateConstGEP(Address Addr, uint64_t Index,
    243                          const llvm::Twine &Name = "") {
    244     const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout();
    245     CharUnits EltSize =
    246         CharUnits::fromQuantity(DL.getTypeAllocSize(Addr.getElementType()));
    247 
    248     return Address(CreateGEP(Addr.getElementType(), Addr.getPointer(),
    249                              getSize(Index), Name),
    250                    Addr.getAlignment().alignmentAtOffset(Index * EltSize));
    251   }
    252 
    253   /// Given a pointer to i8, adjust it by a given constant offset.
    254   Address CreateConstInBoundsByteGEP(Address Addr, CharUnits Offset,
    255                                      const llvm::Twine &Name = "") {
    256     assert(Addr.getElementType() == TypeCache.Int8Ty);
    257     return Address(CreateInBoundsGEP(Addr.getElementType(), Addr.getPointer(),
    258                                      getSize(Offset), Name),
    259                    Addr.getAlignment().alignmentAtOffset(Offset));
    260   }
    261   Address CreateConstByteGEP(Address Addr, CharUnits Offset,
    262                              const llvm::Twine &Name = "") {
    263     assert(Addr.getElementType() == TypeCache.Int8Ty);
    264     return Address(CreateGEP(Addr.getPointer(), getSize(Offset), Name),
    265                    Addr.getAlignment().alignmentAtOffset(Offset));
    266   }
    267 
    268   using CGBuilderBaseTy::CreateConstInBoundsGEP2_32;
    269   Address CreateConstInBoundsGEP2_32(Address Addr, unsigned Idx0, unsigned Idx1,
    270                                      const llvm::Twine &Name = "") {
    271     const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout();
    272 
    273     auto *GEP = cast<llvm::GetElementPtrInst>(CreateConstInBoundsGEP2_32(
    274         Addr.getElementType(), Addr.getPointer(), Idx0, Idx1, Name));
    275     llvm::APInt Offset(
    276         DL.getIndexSizeInBits(Addr.getType()->getPointerAddressSpace()), 0,
    277         /*isSigned=*/true);
    278     if (!GEP->accumulateConstantOffset(DL, Offset))
    279       llvm_unreachable("offset of GEP with constants is always computable");
    280     return Address(GEP, Addr.getAlignment().alignmentAtOffset(
    281                             CharUnits::fromQuantity(Offset.getSExtValue())));
    282   }
    283 
    284   using CGBuilderBaseTy::CreateMemCpy;
    285   llvm::CallInst *CreateMemCpy(Address Dest, Address Src, llvm::Value *Size,
    286                                bool IsVolatile = false) {
    287     return CreateMemCpy(Dest.getPointer(), Dest.getAlignment().getAsAlign(),
    288                         Src.getPointer(), Src.getAlignment().getAsAlign(), Size,
    289                         IsVolatile);
    290   }
    291   llvm::CallInst *CreateMemCpy(Address Dest, Address Src, uint64_t Size,
    292                                bool IsVolatile = false) {
    293     return CreateMemCpy(Dest.getPointer(), Dest.getAlignment().getAsAlign(),
    294                         Src.getPointer(), Src.getAlignment().getAsAlign(), Size,
    295                         IsVolatile);
    296   }
    297 
    298   using CGBuilderBaseTy::CreateMemCpyInline;
    299   llvm::CallInst *CreateMemCpyInline(Address Dest, Address Src, uint64_t Size) {
    300     return CreateMemCpyInline(
    301         Dest.getPointer(), Dest.getAlignment().getAsAlign(), Src.getPointer(),
    302         Src.getAlignment().getAsAlign(), getInt64(Size));
    303   }
    304 
    305   using CGBuilderBaseTy::CreateMemMove;
    306   llvm::CallInst *CreateMemMove(Address Dest, Address Src, llvm::Value *Size,
    307                                 bool IsVolatile = false) {
    308     return CreateMemMove(Dest.getPointer(), Dest.getAlignment().getAsAlign(),
    309                          Src.getPointer(), Src.getAlignment().getAsAlign(),
    310                          Size, IsVolatile);
    311   }
    312 
    313   using CGBuilderBaseTy::CreateMemSet;
    314   llvm::CallInst *CreateMemSet(Address Dest, llvm::Value *Value,
    315                                llvm::Value *Size, bool IsVolatile = false) {
    316     return CreateMemSet(Dest.getPointer(), Value, Size,
    317                         Dest.getAlignment().getAsAlign(), IsVolatile);
    318   }
    319 
    320   using CGBuilderBaseTy::CreatePreserveStructAccessIndex;
    321   Address CreatePreserveStructAccessIndex(Address Addr,
    322                                           unsigned Index,
    323                                           unsigned FieldIndex,
    324                                           llvm::MDNode *DbgInfo) {
    325     llvm::StructType *ElTy = cast<llvm::StructType>(Addr.getElementType());
    326     const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout();
    327     const llvm::StructLayout *Layout = DL.getStructLayout(ElTy);
    328     auto Offset = CharUnits::fromQuantity(Layout->getElementOffset(Index));
    329 
    330     return Address(CreatePreserveStructAccessIndex(ElTy, Addr.getPointer(),
    331                                                    Index, FieldIndex, DbgInfo),
    332                    Addr.getAlignment().alignmentAtOffset(Offset));
    333   }
    334 };
    335 
    336 }  // end namespace CodeGen
    337 }  // end namespace clang
    338 
    339 #endif
    340