Home | History | Annotate | Download | only in CodeGen
      1 //===-- CGBuilder.h - Choose IRBuilder implementation  ----------*- C++ -*-===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 
     10 #ifndef LLVM_CLANG_LIB_CODEGEN_CGBUILDER_H
     11 #define LLVM_CLANG_LIB_CODEGEN_CGBUILDER_H
     12 
     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 /// \brief This is an IRBuilder insertion helper that forwards to
     23 /// CodeGenFunction::InsertHelper, which adds necessary metadata to
     24 /// instructions.
     25 template <bool PreserveNames>
     26 class CGBuilderInserter
     27     : protected llvm::IRBuilderDefaultInserter<PreserveNames> {
     28 public:
     29   CGBuilderInserter() = default;
     30   explicit CGBuilderInserter(CodeGenFunction *CGF) : CGF(CGF) {}
     31 
     32 protected:
     33   /// \brief This forwards to CodeGenFunction::InsertHelper.
     34   void InsertHelper(llvm::Instruction *I, const llvm::Twine &Name,
     35                     llvm::BasicBlock *BB,
     36                     llvm::BasicBlock::iterator InsertPt) const;
     37 private:
     38   CodeGenFunction *CGF = nullptr;
     39 };
     40 
     41 // Don't preserve names on values in an optimized build.
     42 #ifdef NDEBUG
     43 #define PreserveNames false
     44 #else
     45 #define PreserveNames true
     46 #endif
     47 
     48 typedef CGBuilderInserter<PreserveNames> CGBuilderInserterTy;
     49 
     50 typedef llvm::IRBuilder<PreserveNames, llvm::ConstantFolder,
     51                         CGBuilderInserterTy> CGBuilderBaseTy;
     52 
     53 class CGBuilderTy : public CGBuilderBaseTy {
     54   /// Storing a reference to the type cache here makes it a lot easier
     55   /// to build natural-feeling, target-specific IR.
     56   const CodeGenTypeCache &TypeCache;
     57 public:
     58   CGBuilderTy(const CodeGenTypeCache &TypeCache, llvm::LLVMContext &C)
     59     : CGBuilderBaseTy(C), TypeCache(TypeCache) {}
     60   CGBuilderTy(const CodeGenTypeCache &TypeCache,
     61               llvm::LLVMContext &C, const llvm::ConstantFolder &F,
     62               const CGBuilderInserterTy &Inserter)
     63     : CGBuilderBaseTy(C, F, Inserter), TypeCache(TypeCache) {}
     64   CGBuilderTy(const CodeGenTypeCache &TypeCache, llvm::Instruction *I)
     65     : CGBuilderBaseTy(I), TypeCache(TypeCache) {}
     66   CGBuilderTy(const CodeGenTypeCache &TypeCache, llvm::BasicBlock *BB)
     67     : CGBuilderBaseTy(BB), TypeCache(TypeCache) {}
     68 
     69   llvm::ConstantInt *getSize(CharUnits N) {
     70     return llvm::ConstantInt::get(TypeCache.SizeTy, N.getQuantity());
     71   }
     72   llvm::ConstantInt *getSize(uint64_t N) {
     73     return llvm::ConstantInt::get(TypeCache.SizeTy, N);
     74   }
     75 
     76   // Note that we intentionally hide the CreateLoad APIs that don't
     77   // take an alignment.
     78   llvm::LoadInst *CreateLoad(Address Addr, const llvm::Twine &Name = "") {
     79     return CreateAlignedLoad(Addr.getPointer(),
     80                              Addr.getAlignment().getQuantity(),
     81                              Name);
     82   }
     83   llvm::LoadInst *CreateLoad(Address Addr, const char *Name) {
     84     // This overload is required to prevent string literals from
     85     // ending up in the IsVolatile overload.
     86     return CreateAlignedLoad(Addr.getPointer(),
     87                              Addr.getAlignment().getQuantity(),
     88                              Name);
     89   }
     90   llvm::LoadInst *CreateLoad(Address Addr, bool IsVolatile,
     91                              const llvm::Twine &Name = "") {
     92     return CreateAlignedLoad(Addr.getPointer(),
     93                              Addr.getAlignment().getQuantity(),
     94                              IsVolatile,
     95                              Name);
     96   }
     97 
     98   using CGBuilderBaseTy::CreateAlignedLoad;
     99   llvm::LoadInst *CreateAlignedLoad(llvm::Value *Addr, CharUnits Align,
    100                                     const llvm::Twine &Name = "") {
    101     return CreateAlignedLoad(Addr, Align.getQuantity(), Name);
    102   }
    103   llvm::LoadInst *CreateAlignedLoad(llvm::Value *Addr, CharUnits Align,
    104                                     const char *Name) {
    105     return CreateAlignedLoad(Addr, Align.getQuantity(), Name);
    106   }
    107   llvm::LoadInst *CreateAlignedLoad(llvm::Type *Ty, llvm::Value *Addr,
    108                                     CharUnits Align,
    109                                     const llvm::Twine &Name = "") {
    110     assert(Addr->getType()->getPointerElementType() == Ty);
    111     return CreateAlignedLoad(Addr, Align.getQuantity(), Name);
    112   }
    113   llvm::LoadInst *CreateAlignedLoad(llvm::Value *Addr, CharUnits Align,
    114                                     bool IsVolatile,
    115                                     const llvm::Twine &Name = "") {
    116     return CreateAlignedLoad(Addr, Align.getQuantity(), IsVolatile, Name);
    117   }
    118 
    119   // Note that we intentionally hide the CreateStore APIs that don't
    120   // take an alignment.
    121   llvm::StoreInst *CreateStore(llvm::Value *Val, Address Addr,
    122                                bool IsVolatile = false) {
    123     return CreateAlignedStore(Val, Addr.getPointer(),
    124                               Addr.getAlignment().getQuantity(), IsVolatile);
    125   }
    126 
    127   using CGBuilderBaseTy::CreateAlignedStore;
    128   llvm::StoreInst *CreateAlignedStore(llvm::Value *Val, llvm::Value *Addr,
    129                                       CharUnits Align, bool IsVolatile = false) {
    130     return CreateAlignedStore(Val, Addr, Align.getQuantity(), IsVolatile);
    131   }
    132 
    133   // FIXME: these "default-aligned" APIs should be removed,
    134   // but I don't feel like fixing all the builtin code right now.
    135   llvm::LoadInst *CreateDefaultAlignedLoad(llvm::Value *Addr,
    136                                            const llvm::Twine &Name = "") {
    137     return CGBuilderBaseTy::CreateLoad(Addr, false, Name);
    138   }
    139   llvm::LoadInst *CreateDefaultAlignedLoad(llvm::Value *Addr,
    140                                            const char *Name) {
    141     return CGBuilderBaseTy::CreateLoad(Addr, false, Name);
    142   }
    143   llvm::LoadInst *CreateDefaultAlignedLoad(llvm::Value *Addr, bool IsVolatile,
    144                                            const llvm::Twine &Name = "") {
    145     return CGBuilderBaseTy::CreateLoad(Addr, IsVolatile, Name);
    146   }
    147 
    148   llvm::StoreInst *CreateDefaultAlignedStore(llvm::Value *Val,
    149                                              llvm::Value *Addr,
    150                                              bool IsVolatile = false) {
    151     return CGBuilderBaseTy::CreateStore(Val, Addr, IsVolatile);
    152   }
    153 
    154   /// Emit a load from an i1 flag variable.
    155   llvm::LoadInst *CreateFlagLoad(llvm::Value *Addr,
    156                                  const llvm::Twine &Name = "") {
    157     assert(Addr->getType()->getPointerElementType() == getInt1Ty());
    158     return CreateAlignedLoad(getInt1Ty(), Addr, CharUnits::One(), Name);
    159   }
    160 
    161   /// Emit a store to an i1 flag variable.
    162   llvm::StoreInst *CreateFlagStore(bool Value, llvm::Value *Addr) {
    163     assert(Addr->getType()->getPointerElementType() == getInt1Ty());
    164     return CreateAlignedStore(getInt1(Value), Addr, CharUnits::One());
    165   }
    166 
    167   using CGBuilderBaseTy::CreateBitCast;
    168   Address CreateBitCast(Address Addr, llvm::Type *Ty,
    169                         const llvm::Twine &Name = "") {
    170     return Address(CreateBitCast(Addr.getPointer(), Ty, Name),
    171                    Addr.getAlignment());
    172   }
    173 
    174   /// Cast the element type of the given address to a different type,
    175   /// preserving information like the alignment and address space.
    176   Address CreateElementBitCast(Address Addr, llvm::Type *Ty,
    177                                const llvm::Twine &Name = "") {
    178     auto PtrTy = Ty->getPointerTo(Addr.getAddressSpace());
    179     return CreateBitCast(Addr, PtrTy, Name);
    180   }
    181 
    182   using CGBuilderBaseTy::CreatePointerBitCastOrAddrSpaceCast;
    183   Address CreatePointerBitCastOrAddrSpaceCast(Address Addr, llvm::Type *Ty,
    184                                               const llvm::Twine &Name = "") {
    185     llvm::Value *Ptr =
    186       CreatePointerBitCastOrAddrSpaceCast(Addr.getPointer(), Ty, Name);
    187     return Address(Ptr, Addr.getAlignment());
    188   }
    189 
    190   using CGBuilderBaseTy::CreateStructGEP;
    191   Address CreateStructGEP(Address Addr, unsigned Index, CharUnits Offset,
    192                           const llvm::Twine &Name = "") {
    193     return Address(CreateStructGEP(Addr.getElementType(),
    194                                    Addr.getPointer(), Index, Name),
    195                    Addr.getAlignment().alignmentAtOffset(Offset));
    196   }
    197 
    198   /// Given
    199   ///   %addr = [n x T]* ...
    200   /// produce
    201   ///   %name = getelementptr inbounds %addr, i64 0, i64 index
    202   /// where i64 is actually the target word size.
    203   ///
    204   /// This API assumes that drilling into an array like this is always
    205   /// an inbounds operation.
    206   ///
    207   /// \param EltSize - the size of the type T in bytes
    208   Address CreateConstArrayGEP(Address Addr, uint64_t Index, CharUnits EltSize,
    209                               const llvm::Twine &Name = "") {
    210     return Address(CreateInBoundsGEP(Addr.getPointer(),
    211                                      {getSize(CharUnits::Zero()),
    212                                       getSize(Index)},
    213                                      Name),
    214                    Addr.getAlignment().alignmentAtOffset(Index * EltSize));
    215   }
    216 
    217   /// Given
    218   ///   %addr = T* ...
    219   /// produce
    220   ///   %name = getelementptr inbounds %addr, i64 index
    221   /// where i64 is actually the target word size.
    222   ///
    223   /// \param EltSize - the size of the type T in bytes
    224   Address CreateConstInBoundsGEP(Address Addr, uint64_t Index,
    225                                  CharUnits EltSize,
    226                                  const llvm::Twine &Name = "") {
    227     return Address(CreateInBoundsGEP(Addr.getElementType(), Addr.getPointer(),
    228                                      getSize(Index), Name),
    229                    Addr.getAlignment().alignmentAtOffset(Index * EltSize));
    230   }
    231 
    232   /// Given
    233   ///   %addr = T* ...
    234   /// produce
    235   ///   %name = getelementptr inbounds %addr, i64 index
    236   /// where i64 is actually the target word size.
    237   ///
    238   /// \param EltSize - the size of the type T in bytes
    239   Address CreateConstGEP(Address Addr, uint64_t Index, CharUnits EltSize,
    240                          const llvm::Twine &Name = "") {
    241     return Address(CreateGEP(Addr.getElementType(), Addr.getPointer(),
    242                              getSize(Index), Name),
    243                    Addr.getAlignment().alignmentAtOffset(Index * EltSize));
    244   }
    245 
    246   /// Given a pointer to i8, adjust it by a given constant offset.
    247   Address CreateConstInBoundsByteGEP(Address Addr, CharUnits Offset,
    248                                      const llvm::Twine &Name = "") {
    249     assert(Addr.getElementType() == TypeCache.Int8Ty);
    250     return Address(CreateInBoundsGEP(Addr.getPointer(), getSize(Offset), Name),
    251                    Addr.getAlignment().alignmentAtOffset(Offset));
    252   }
    253   Address CreateConstByteGEP(Address Addr, CharUnits Offset,
    254                              const llvm::Twine &Name = "") {
    255     assert(Addr.getElementType() == TypeCache.Int8Ty);
    256     return Address(CreateGEP(Addr.getPointer(), getSize(Offset), Name),
    257                    Addr.getAlignment().alignmentAtOffset(Offset));
    258   }
    259 
    260   llvm::Value *CreateConstInBoundsByteGEP(llvm::Value *Ptr, CharUnits Offset,
    261                                           const llvm::Twine &Name = "") {
    262     assert(Ptr->getType()->getPointerElementType() == TypeCache.Int8Ty);
    263     return CreateInBoundsGEP(Ptr, getSize(Offset), Name);
    264   }
    265   llvm::Value *CreateConstByteGEP(llvm::Value *Ptr, CharUnits Offset,
    266                                   const llvm::Twine &Name = "") {
    267     assert(Ptr->getType()->getPointerElementType() == TypeCache.Int8Ty);
    268     return CreateGEP(Ptr, getSize(Offset), Name);
    269   }
    270 
    271   using CGBuilderBaseTy::CreateMemCpy;
    272   llvm::CallInst *CreateMemCpy(Address Dest, Address Src, llvm::Value *Size,
    273                                bool IsVolatile = false) {
    274     auto Align = std::min(Dest.getAlignment(), Src.getAlignment());
    275     return CreateMemCpy(Dest.getPointer(), Src.getPointer(), Size,
    276                         Align.getQuantity(), IsVolatile);
    277   }
    278   llvm::CallInst *CreateMemCpy(Address Dest, Address Src, uint64_t Size,
    279                                bool IsVolatile = false) {
    280     auto Align = std::min(Dest.getAlignment(), Src.getAlignment());
    281     return CreateMemCpy(Dest.getPointer(), Src.getPointer(), Size,
    282                         Align.getQuantity(), IsVolatile);
    283   }
    284 
    285   using CGBuilderBaseTy::CreateMemMove;
    286   llvm::CallInst *CreateMemMove(Address Dest, Address Src, llvm::Value *Size,
    287                                 bool IsVolatile = false) {
    288     auto Align = std::min(Dest.getAlignment(), Src.getAlignment());
    289     return CreateMemMove(Dest.getPointer(), Src.getPointer(), Size,
    290                          Align.getQuantity(), IsVolatile);
    291   }
    292 
    293   using CGBuilderBaseTy::CreateMemSet;
    294   llvm::CallInst *CreateMemSet(Address Dest, llvm::Value *Value,
    295                                llvm::Value *Size, bool IsVolatile = false) {
    296     return CreateMemSet(Dest.getPointer(), Value, Size,
    297                         Dest.getAlignment().getQuantity(), IsVolatile);
    298   }
    299 };
    300 
    301 #undef PreserveNames
    302 
    303 }  // end namespace CodeGen
    304 }  // end namespace clang
    305 
    306 #endif
    307