Home | History | Annotate | Line # | Download | only in ARM
      1 //===- ARMConstantPoolValue.h - ARM constantpool value ----------*- 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 // This file implements the ARM specific constantpool value class.
     10 //
     11 //===----------------------------------------------------------------------===//
     12 
     13 #ifndef LLVM_LIB_TARGET_ARM_ARMCONSTANTPOOLVALUE_H
     14 #define LLVM_LIB_TARGET_ARM_ARMCONSTANTPOOLVALUE_H
     15 
     16 #include "llvm/ADT/SmallPtrSet.h"
     17 #include "llvm/ADT/StringRef.h"
     18 #include "llvm/ADT/iterator_range.h"
     19 #include "llvm/CodeGen/MachineConstantPool.h"
     20 #include "llvm/Support/Casting.h"
     21 #include <string>
     22 #include <vector>
     23 
     24 namespace llvm {
     25 
     26 class BlockAddress;
     27 class Constant;
     28 class GlobalValue;
     29 class GlobalVariable;
     30 class LLVMContext;
     31 class MachineBasicBlock;
     32 class raw_ostream;
     33 class Type;
     34 
     35 namespace ARMCP {
     36 
     37   enum ARMCPKind {
     38     CPValue,
     39     CPExtSymbol,
     40     CPBlockAddress,
     41     CPLSDA,
     42     CPMachineBasicBlock,
     43     CPPromotedGlobal
     44   };
     45 
     46   enum ARMCPModifier {
     47     no_modifier, /// None
     48     TLSGD,       /// Thread Local Storage (General Dynamic Mode)
     49     GOT_PREL,    /// Global Offset Table, PC Relative
     50     GOTTPOFF,    /// Global Offset Table, Thread Pointer Offset
     51     TPOFF,       /// Thread Pointer Offset
     52     SECREL,      /// Section Relative (Windows TLS)
     53     SBREL,       /// Static Base Relative (RWPI)
     54   };
     55 
     56 } // end namespace ARMCP
     57 
     58 /// ARMConstantPoolValue - ARM specific constantpool value. This is used to
     59 /// represent PC-relative displacement between the address of the load
     60 /// instruction and the constant being loaded, i.e. (&GV-(LPIC+8)).
     61 class ARMConstantPoolValue : public MachineConstantPoolValue {
     62   unsigned LabelId;        // Label id of the load.
     63   ARMCP::ARMCPKind Kind;   // Kind of constant.
     64   unsigned char PCAdjust;  // Extra adjustment if constantpool is pc-relative.
     65                            // 8 for ARM, 4 for Thumb.
     66   ARMCP::ARMCPModifier Modifier;   // GV modifier i.e. (&GV(modifier)-(LPIC+8))
     67   bool AddCurrentAddress;
     68 
     69 protected:
     70   ARMConstantPoolValue(Type *Ty, unsigned id, ARMCP::ARMCPKind Kind,
     71                        unsigned char PCAdj, ARMCP::ARMCPModifier Modifier,
     72                        bool AddCurrentAddress);
     73 
     74   ARMConstantPoolValue(LLVMContext &C, unsigned id, ARMCP::ARMCPKind Kind,
     75                        unsigned char PCAdj, ARMCP::ARMCPModifier Modifier,
     76                        bool AddCurrentAddress);
     77 
     78   template <typename Derived>
     79   int getExistingMachineCPValueImpl(MachineConstantPool *CP, Align Alignment) {
     80     const std::vector<MachineConstantPoolEntry> &Constants = CP->getConstants();
     81     for (unsigned i = 0, e = Constants.size(); i != e; ++i) {
     82       if (Constants[i].isMachineConstantPoolEntry() &&
     83           Constants[i].getAlign() >= Alignment) {
     84         auto *CPV =
     85           static_cast<ARMConstantPoolValue*>(Constants[i].Val.MachineCPVal);
     86         if (Derived *APC = dyn_cast<Derived>(CPV))
     87           if (cast<Derived>(this)->equals(APC))
     88             return i;
     89       }
     90     }
     91 
     92     return -1;
     93   }
     94 
     95 public:
     96   ~ARMConstantPoolValue() override;
     97 
     98   ARMCP::ARMCPModifier getModifier() const { return Modifier; }
     99   StringRef getModifierText() const;
    100   bool hasModifier() const { return Modifier != ARMCP::no_modifier; }
    101 
    102   bool mustAddCurrentAddress() const { return AddCurrentAddress; }
    103 
    104   unsigned getLabelId() const { return LabelId; }
    105   unsigned char getPCAdjustment() const { return PCAdjust; }
    106 
    107   bool isGlobalValue() const { return Kind == ARMCP::CPValue; }
    108   bool isExtSymbol() const { return Kind == ARMCP::CPExtSymbol; }
    109   bool isBlockAddress() const { return Kind == ARMCP::CPBlockAddress; }
    110   bool isLSDA() const { return Kind == ARMCP::CPLSDA; }
    111   bool isMachineBasicBlock() const{ return Kind == ARMCP::CPMachineBasicBlock; }
    112   bool isPromotedGlobal() const{ return Kind == ARMCP::CPPromotedGlobal; }
    113 
    114   int getExistingMachineCPValue(MachineConstantPool *CP,
    115                                 Align Alignment) override;
    116 
    117   void addSelectionDAGCSEId(FoldingSetNodeID &ID) override;
    118 
    119   /// hasSameValue - Return true if this ARM constpool value can share the same
    120   /// constantpool entry as another ARM constpool value.
    121   virtual bool hasSameValue(ARMConstantPoolValue *ACPV);
    122 
    123   bool equals(const ARMConstantPoolValue *A) const {
    124     return this->LabelId == A->LabelId &&
    125       this->PCAdjust == A->PCAdjust &&
    126       this->Modifier == A->Modifier;
    127   }
    128 
    129   void print(raw_ostream &O) const override;
    130   void print(raw_ostream *O) const { if (O) print(*O); }
    131   void dump() const;
    132 };
    133 
    134 inline raw_ostream &operator<<(raw_ostream &O, const ARMConstantPoolValue &V) {
    135   V.print(O);
    136   return O;
    137 }
    138 
    139 /// ARMConstantPoolConstant - ARM-specific constant pool values for Constants,
    140 /// Functions, and BlockAddresses.
    141 class ARMConstantPoolConstant : public ARMConstantPoolValue {
    142   const Constant *CVal;         // Constant being loaded.
    143   SmallPtrSet<const GlobalVariable*, 1> GVars;
    144 
    145   ARMConstantPoolConstant(const Constant *C,
    146                           unsigned ID,
    147                           ARMCP::ARMCPKind Kind,
    148                           unsigned char PCAdj,
    149                           ARMCP::ARMCPModifier Modifier,
    150                           bool AddCurrentAddress);
    151   ARMConstantPoolConstant(Type *Ty, const Constant *C,
    152                           unsigned ID,
    153                           ARMCP::ARMCPKind Kind,
    154                           unsigned char PCAdj,
    155                           ARMCP::ARMCPModifier Modifier,
    156                           bool AddCurrentAddress);
    157   ARMConstantPoolConstant(const GlobalVariable *GV, const Constant *Init);
    158 
    159 public:
    160   static ARMConstantPoolConstant *Create(const Constant *C, unsigned ID);
    161   static ARMConstantPoolConstant *Create(const GlobalValue *GV,
    162                                          ARMCP::ARMCPModifier Modifier);
    163   static ARMConstantPoolConstant *Create(const GlobalVariable *GV,
    164                                          const Constant *Initializer);
    165   static ARMConstantPoolConstant *Create(const Constant *C, unsigned ID,
    166                                          ARMCP::ARMCPKind Kind,
    167                                          unsigned char PCAdj);
    168   static ARMConstantPoolConstant *Create(const Constant *C, unsigned ID,
    169                                          ARMCP::ARMCPKind Kind,
    170                                          unsigned char PCAdj,
    171                                          ARMCP::ARMCPModifier Modifier,
    172                                          bool AddCurrentAddress);
    173 
    174   const GlobalValue *getGV() const;
    175   const BlockAddress *getBlockAddress() const;
    176 
    177   using promoted_iterator = SmallPtrSet<const GlobalVariable *, 1>::iterator;
    178 
    179   iterator_range<promoted_iterator> promotedGlobals() {
    180     return iterator_range<promoted_iterator>(GVars.begin(), GVars.end());
    181   }
    182 
    183   const Constant *getPromotedGlobalInit() const {
    184     return CVal;
    185   }
    186 
    187   int getExistingMachineCPValue(MachineConstantPool *CP,
    188                                 Align Alignment) override;
    189 
    190   /// hasSameValue - Return true if this ARM constpool value can share the same
    191   /// constantpool entry as another ARM constpool value.
    192   bool hasSameValue(ARMConstantPoolValue *ACPV) override;
    193 
    194   void addSelectionDAGCSEId(FoldingSetNodeID &ID) override;
    195 
    196   void print(raw_ostream &O) const override;
    197 
    198   static bool classof(const ARMConstantPoolValue *APV) {
    199     return APV->isGlobalValue() || APV->isBlockAddress() || APV->isLSDA() ||
    200            APV->isPromotedGlobal();
    201   }
    202 
    203   bool equals(const ARMConstantPoolConstant *A) const {
    204     return CVal == A->CVal && ARMConstantPoolValue::equals(A);
    205   }
    206 };
    207 
    208 /// ARMConstantPoolSymbol - ARM-specific constantpool values for external
    209 /// symbols.
    210 class ARMConstantPoolSymbol : public ARMConstantPoolValue {
    211   const std::string S;          // ExtSymbol being loaded.
    212 
    213   ARMConstantPoolSymbol(LLVMContext &C, StringRef s, unsigned id,
    214                         unsigned char PCAdj, ARMCP::ARMCPModifier Modifier,
    215                         bool AddCurrentAddress);
    216 
    217 public:
    218   static ARMConstantPoolSymbol *Create(LLVMContext &C, StringRef s, unsigned ID,
    219                                        unsigned char PCAdj);
    220 
    221   StringRef getSymbol() const { return S; }
    222 
    223   int getExistingMachineCPValue(MachineConstantPool *CP,
    224                                 Align Alignment) override;
    225 
    226   void addSelectionDAGCSEId(FoldingSetNodeID &ID) override;
    227 
    228   /// hasSameValue - Return true if this ARM constpool value can share the same
    229   /// constantpool entry as another ARM constpool value.
    230   bool hasSameValue(ARMConstantPoolValue *ACPV) override;
    231 
    232   void print(raw_ostream &O) const override;
    233 
    234   static bool classof(const ARMConstantPoolValue *ACPV) {
    235     return ACPV->isExtSymbol();
    236   }
    237 
    238   bool equals(const ARMConstantPoolSymbol *A) const {
    239     return S == A->S && ARMConstantPoolValue::equals(A);
    240   }
    241 };
    242 
    243 /// ARMConstantPoolMBB - ARM-specific constantpool value of a machine basic
    244 /// block.
    245 class ARMConstantPoolMBB : public ARMConstantPoolValue {
    246   const MachineBasicBlock *MBB; // Machine basic block.
    247 
    248   ARMConstantPoolMBB(LLVMContext &C, const MachineBasicBlock *mbb, unsigned id,
    249                      unsigned char PCAdj, ARMCP::ARMCPModifier Modifier,
    250                      bool AddCurrentAddress);
    251 
    252 public:
    253   static ARMConstantPoolMBB *Create(LLVMContext &C,
    254                                     const MachineBasicBlock *mbb,
    255                                     unsigned ID, unsigned char PCAdj);
    256 
    257   const MachineBasicBlock *getMBB() const { return MBB; }
    258 
    259   int getExistingMachineCPValue(MachineConstantPool *CP,
    260                                 Align Alignment) override;
    261 
    262   void addSelectionDAGCSEId(FoldingSetNodeID &ID) override;
    263 
    264   /// hasSameValue - Return true if this ARM constpool value can share the same
    265   /// constantpool entry as another ARM constpool value.
    266   bool hasSameValue(ARMConstantPoolValue *ACPV) override;
    267 
    268   void print(raw_ostream &O) const override;
    269 
    270   static bool classof(const ARMConstantPoolValue *ACPV) {
    271     return ACPV->isMachineBasicBlock();
    272   }
    273 
    274   bool equals(const ARMConstantPoolMBB *A) const {
    275     return MBB == A->MBB && ARMConstantPoolValue::equals(A);
    276   }
    277 };
    278 
    279 } // end namespace llvm
    280 
    281 #endif // LLVM_LIB_TARGET_ARM_ARMCONSTANTPOOLVALUE_H
    282