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