xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/ARM/ARMConstantPoolValue.h (revision e25152834cdf3b353892835a4f3b157e066a8ed4)
10b57cec5SDimitry Andric //===- ARMConstantPoolValue.h - ARM constantpool value ----------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file implements the ARM specific constantpool value class.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #ifndef LLVM_LIB_TARGET_ARM_ARMCONSTANTPOOLVALUE_H
140b57cec5SDimitry Andric #define LLVM_LIB_TARGET_ARM_ARMCONSTANTPOOLVALUE_H
150b57cec5SDimitry Andric 
160b57cec5SDimitry Andric #include "llvm/ADT/SmallPtrSet.h"
170b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
180b57cec5SDimitry Andric #include "llvm/ADT/iterator_range.h"
190b57cec5SDimitry Andric #include "llvm/CodeGen/MachineConstantPool.h"
200b57cec5SDimitry Andric #include "llvm/Support/Casting.h"
210b57cec5SDimitry Andric #include <string>
220b57cec5SDimitry Andric #include <vector>
230b57cec5SDimitry Andric 
240b57cec5SDimitry Andric namespace llvm {
250b57cec5SDimitry Andric 
260b57cec5SDimitry Andric class BlockAddress;
270b57cec5SDimitry Andric class Constant;
280b57cec5SDimitry Andric class GlobalValue;
290b57cec5SDimitry Andric class GlobalVariable;
300b57cec5SDimitry Andric class LLVMContext;
310b57cec5SDimitry Andric class MachineBasicBlock;
320b57cec5SDimitry Andric class raw_ostream;
330b57cec5SDimitry Andric class Type;
340b57cec5SDimitry Andric 
350b57cec5SDimitry Andric namespace ARMCP {
360b57cec5SDimitry Andric 
370b57cec5SDimitry Andric   enum ARMCPKind {
380b57cec5SDimitry Andric     CPValue,
390b57cec5SDimitry Andric     CPExtSymbol,
400b57cec5SDimitry Andric     CPBlockAddress,
410b57cec5SDimitry Andric     CPLSDA,
420b57cec5SDimitry Andric     CPMachineBasicBlock,
430b57cec5SDimitry Andric     CPPromotedGlobal
440b57cec5SDimitry Andric   };
450b57cec5SDimitry Andric 
460b57cec5SDimitry Andric   enum ARMCPModifier {
470b57cec5SDimitry Andric     no_modifier, /// None
480b57cec5SDimitry Andric     TLSGD,       /// Thread Local Storage (General Dynamic Mode)
490b57cec5SDimitry Andric     GOT_PREL,    /// Global Offset Table, PC Relative
500b57cec5SDimitry Andric     GOTTPOFF,    /// Global Offset Table, Thread Pointer Offset
510b57cec5SDimitry Andric     TPOFF,       /// Thread Pointer Offset
520b57cec5SDimitry Andric     SECREL,      /// Section Relative (Windows TLS)
530b57cec5SDimitry Andric     SBREL,       /// Static Base Relative (RWPI)
540b57cec5SDimitry Andric   };
550b57cec5SDimitry Andric 
560b57cec5SDimitry Andric } // end namespace ARMCP
570b57cec5SDimitry Andric 
580b57cec5SDimitry Andric /// ARMConstantPoolValue - ARM specific constantpool value. This is used to
590b57cec5SDimitry Andric /// represent PC-relative displacement between the address of the load
600b57cec5SDimitry Andric /// instruction and the constant being loaded, i.e. (&GV-(LPIC+8)).
610b57cec5SDimitry Andric class ARMConstantPoolValue : public MachineConstantPoolValue {
620b57cec5SDimitry Andric   unsigned LabelId;        // Label id of the load.
630b57cec5SDimitry Andric   ARMCP::ARMCPKind Kind;   // Kind of constant.
640b57cec5SDimitry Andric   unsigned char PCAdjust;  // Extra adjustment if constantpool is pc-relative.
650b57cec5SDimitry Andric                            // 8 for ARM, 4 for Thumb.
660b57cec5SDimitry Andric   ARMCP::ARMCPModifier Modifier;   // GV modifier i.e. (&GV(modifier)-(LPIC+8))
670b57cec5SDimitry Andric   bool AddCurrentAddress;
680b57cec5SDimitry Andric 
690b57cec5SDimitry Andric protected:
700b57cec5SDimitry Andric   ARMConstantPoolValue(Type *Ty, unsigned id, ARMCP::ARMCPKind Kind,
710b57cec5SDimitry Andric                        unsigned char PCAdj, ARMCP::ARMCPModifier Modifier,
720b57cec5SDimitry Andric                        bool AddCurrentAddress);
730b57cec5SDimitry Andric 
740b57cec5SDimitry Andric   ARMConstantPoolValue(LLVMContext &C, unsigned id, ARMCP::ARMCPKind Kind,
750b57cec5SDimitry Andric                        unsigned char PCAdj, ARMCP::ARMCPModifier Modifier,
760b57cec5SDimitry Andric                        bool AddCurrentAddress);
770b57cec5SDimitry Andric 
780b57cec5SDimitry Andric   template <typename Derived>
getExistingMachineCPValueImpl(MachineConstantPool * CP,Align Alignment)79*5ffd83dbSDimitry Andric   int getExistingMachineCPValueImpl(MachineConstantPool *CP, Align Alignment) {
800b57cec5SDimitry Andric     const std::vector<MachineConstantPoolEntry> &Constants = CP->getConstants();
810b57cec5SDimitry Andric     for (unsigned i = 0, e = Constants.size(); i != e; ++i) {
820b57cec5SDimitry Andric       if (Constants[i].isMachineConstantPoolEntry() &&
83*5ffd83dbSDimitry Andric           Constants[i].getAlign() >= Alignment) {
840b57cec5SDimitry Andric         auto *CPV =
850b57cec5SDimitry Andric           static_cast<ARMConstantPoolValue*>(Constants[i].Val.MachineCPVal);
860b57cec5SDimitry Andric         if (Derived *APC = dyn_cast<Derived>(CPV))
870b57cec5SDimitry Andric           if (cast<Derived>(this)->equals(APC))
880b57cec5SDimitry Andric             return i;
890b57cec5SDimitry Andric       }
900b57cec5SDimitry Andric     }
910b57cec5SDimitry Andric 
920b57cec5SDimitry Andric     return -1;
930b57cec5SDimitry Andric   }
940b57cec5SDimitry Andric 
950b57cec5SDimitry Andric public:
960b57cec5SDimitry Andric   ~ARMConstantPoolValue() override;
970b57cec5SDimitry Andric 
getModifier()980b57cec5SDimitry Andric   ARMCP::ARMCPModifier getModifier() const { return Modifier; }
990b57cec5SDimitry Andric   StringRef getModifierText() const;
hasModifier()1000b57cec5SDimitry Andric   bool hasModifier() const { return Modifier != ARMCP::no_modifier; }
1010b57cec5SDimitry Andric 
mustAddCurrentAddress()1020b57cec5SDimitry Andric   bool mustAddCurrentAddress() const { return AddCurrentAddress; }
1030b57cec5SDimitry Andric 
getLabelId()1040b57cec5SDimitry Andric   unsigned getLabelId() const { return LabelId; }
getPCAdjustment()1050b57cec5SDimitry Andric   unsigned char getPCAdjustment() const { return PCAdjust; }
1060b57cec5SDimitry Andric 
isGlobalValue()1070b57cec5SDimitry Andric   bool isGlobalValue() const { return Kind == ARMCP::CPValue; }
isExtSymbol()1080b57cec5SDimitry Andric   bool isExtSymbol() const { return Kind == ARMCP::CPExtSymbol; }
isBlockAddress()1090b57cec5SDimitry Andric   bool isBlockAddress() const { return Kind == ARMCP::CPBlockAddress; }
isLSDA()1100b57cec5SDimitry Andric   bool isLSDA() const { return Kind == ARMCP::CPLSDA; }
isMachineBasicBlock()1110b57cec5SDimitry Andric   bool isMachineBasicBlock() const{ return Kind == ARMCP::CPMachineBasicBlock; }
isPromotedGlobal()1120b57cec5SDimitry Andric   bool isPromotedGlobal() const{ return Kind == ARMCP::CPPromotedGlobal; }
1130b57cec5SDimitry Andric 
1140b57cec5SDimitry Andric   int getExistingMachineCPValue(MachineConstantPool *CP,
115*5ffd83dbSDimitry Andric                                 Align Alignment) override;
1160b57cec5SDimitry Andric 
1170b57cec5SDimitry Andric   void addSelectionDAGCSEId(FoldingSetNodeID &ID) override;
1180b57cec5SDimitry Andric 
1190b57cec5SDimitry Andric   /// hasSameValue - Return true if this ARM constpool value can share the same
1200b57cec5SDimitry Andric   /// constantpool entry as another ARM constpool value.
1210b57cec5SDimitry Andric   virtual bool hasSameValue(ARMConstantPoolValue *ACPV);
1220b57cec5SDimitry Andric 
equals(const ARMConstantPoolValue * A)1230b57cec5SDimitry Andric   bool equals(const ARMConstantPoolValue *A) const {
1240b57cec5SDimitry Andric     return this->LabelId == A->LabelId &&
1250b57cec5SDimitry Andric       this->PCAdjust == A->PCAdjust &&
1260b57cec5SDimitry Andric       this->Modifier == A->Modifier;
1270b57cec5SDimitry Andric   }
1280b57cec5SDimitry Andric 
1290b57cec5SDimitry Andric   void print(raw_ostream &O) const override;
print(raw_ostream * O)1300b57cec5SDimitry Andric   void print(raw_ostream *O) const { if (O) print(*O); }
1310b57cec5SDimitry Andric   void dump() const;
1320b57cec5SDimitry Andric };
1330b57cec5SDimitry Andric 
1340b57cec5SDimitry Andric inline raw_ostream &operator<<(raw_ostream &O, const ARMConstantPoolValue &V) {
1350b57cec5SDimitry Andric   V.print(O);
1360b57cec5SDimitry Andric   return O;
1370b57cec5SDimitry Andric }
1380b57cec5SDimitry Andric 
1390b57cec5SDimitry Andric /// ARMConstantPoolConstant - ARM-specific constant pool values for Constants,
1400b57cec5SDimitry Andric /// Functions, and BlockAddresses.
1410b57cec5SDimitry Andric class ARMConstantPoolConstant : public ARMConstantPoolValue {
1420b57cec5SDimitry Andric   const Constant *CVal;         // Constant being loaded.
1430b57cec5SDimitry Andric   SmallPtrSet<const GlobalVariable*, 1> GVars;
1440b57cec5SDimitry Andric 
1450b57cec5SDimitry Andric   ARMConstantPoolConstant(const Constant *C,
1460b57cec5SDimitry Andric                           unsigned ID,
1470b57cec5SDimitry Andric                           ARMCP::ARMCPKind Kind,
1480b57cec5SDimitry Andric                           unsigned char PCAdj,
1490b57cec5SDimitry Andric                           ARMCP::ARMCPModifier Modifier,
1500b57cec5SDimitry Andric                           bool AddCurrentAddress);
1510b57cec5SDimitry Andric   ARMConstantPoolConstant(Type *Ty, const Constant *C,
1520b57cec5SDimitry Andric                           unsigned ID,
1530b57cec5SDimitry Andric                           ARMCP::ARMCPKind Kind,
1540b57cec5SDimitry Andric                           unsigned char PCAdj,
1550b57cec5SDimitry Andric                           ARMCP::ARMCPModifier Modifier,
1560b57cec5SDimitry Andric                           bool AddCurrentAddress);
1570b57cec5SDimitry Andric   ARMConstantPoolConstant(const GlobalVariable *GV, const Constant *Init);
1580b57cec5SDimitry Andric 
1590b57cec5SDimitry Andric public:
1600b57cec5SDimitry Andric   static ARMConstantPoolConstant *Create(const Constant *C, unsigned ID);
1610b57cec5SDimitry Andric   static ARMConstantPoolConstant *Create(const GlobalValue *GV,
1620b57cec5SDimitry Andric                                          ARMCP::ARMCPModifier Modifier);
1630b57cec5SDimitry Andric   static ARMConstantPoolConstant *Create(const GlobalVariable *GV,
1640b57cec5SDimitry Andric                                          const Constant *Initializer);
1650b57cec5SDimitry Andric   static ARMConstantPoolConstant *Create(const Constant *C, unsigned ID,
1660b57cec5SDimitry Andric                                          ARMCP::ARMCPKind Kind,
1670b57cec5SDimitry Andric                                          unsigned char PCAdj);
1680b57cec5SDimitry Andric   static ARMConstantPoolConstant *Create(const Constant *C, unsigned ID,
1690b57cec5SDimitry Andric                                          ARMCP::ARMCPKind Kind,
1700b57cec5SDimitry Andric                                          unsigned char PCAdj,
1710b57cec5SDimitry Andric                                          ARMCP::ARMCPModifier Modifier,
1720b57cec5SDimitry Andric                                          bool AddCurrentAddress);
1730b57cec5SDimitry Andric 
1740b57cec5SDimitry Andric   const GlobalValue *getGV() const;
1750b57cec5SDimitry Andric   const BlockAddress *getBlockAddress() const;
1760b57cec5SDimitry Andric 
1770b57cec5SDimitry Andric   using promoted_iterator = SmallPtrSet<const GlobalVariable *, 1>::iterator;
1780b57cec5SDimitry Andric 
promotedGlobals()1790b57cec5SDimitry Andric   iterator_range<promoted_iterator> promotedGlobals() {
1800b57cec5SDimitry Andric     return iterator_range<promoted_iterator>(GVars.begin(), GVars.end());
1810b57cec5SDimitry Andric   }
1820b57cec5SDimitry Andric 
getPromotedGlobalInit()1830b57cec5SDimitry Andric   const Constant *getPromotedGlobalInit() const {
1840b57cec5SDimitry Andric     return CVal;
1850b57cec5SDimitry Andric   }
1860b57cec5SDimitry Andric 
1870b57cec5SDimitry Andric   int getExistingMachineCPValue(MachineConstantPool *CP,
188*5ffd83dbSDimitry Andric                                 Align Alignment) override;
1890b57cec5SDimitry Andric 
1900b57cec5SDimitry Andric   /// hasSameValue - Return true if this ARM constpool value can share the same
1910b57cec5SDimitry Andric   /// constantpool entry as another ARM constpool value.
1920b57cec5SDimitry Andric   bool hasSameValue(ARMConstantPoolValue *ACPV) override;
1930b57cec5SDimitry Andric 
1940b57cec5SDimitry Andric   void addSelectionDAGCSEId(FoldingSetNodeID &ID) override;
1950b57cec5SDimitry Andric 
1960b57cec5SDimitry Andric   void print(raw_ostream &O) const override;
1970b57cec5SDimitry Andric 
classof(const ARMConstantPoolValue * APV)1980b57cec5SDimitry Andric   static bool classof(const ARMConstantPoolValue *APV) {
1990b57cec5SDimitry Andric     return APV->isGlobalValue() || APV->isBlockAddress() || APV->isLSDA() ||
2000b57cec5SDimitry Andric            APV->isPromotedGlobal();
2010b57cec5SDimitry Andric   }
2020b57cec5SDimitry Andric 
equals(const ARMConstantPoolConstant * A)2030b57cec5SDimitry Andric   bool equals(const ARMConstantPoolConstant *A) const {
2040b57cec5SDimitry Andric     return CVal == A->CVal && ARMConstantPoolValue::equals(A);
2050b57cec5SDimitry Andric   }
2060b57cec5SDimitry Andric };
2070b57cec5SDimitry Andric 
2080b57cec5SDimitry Andric /// ARMConstantPoolSymbol - ARM-specific constantpool values for external
2090b57cec5SDimitry Andric /// symbols.
2100b57cec5SDimitry Andric class ARMConstantPoolSymbol : public ARMConstantPoolValue {
2110b57cec5SDimitry Andric   const std::string S;          // ExtSymbol being loaded.
2120b57cec5SDimitry Andric 
2130b57cec5SDimitry Andric   ARMConstantPoolSymbol(LLVMContext &C, StringRef s, unsigned id,
2140b57cec5SDimitry Andric                         unsigned char PCAdj, ARMCP::ARMCPModifier Modifier,
2150b57cec5SDimitry Andric                         bool AddCurrentAddress);
2160b57cec5SDimitry Andric 
2170b57cec5SDimitry Andric public:
2180b57cec5SDimitry Andric   static ARMConstantPoolSymbol *Create(LLVMContext &C, StringRef s, unsigned ID,
2190b57cec5SDimitry Andric                                        unsigned char PCAdj);
2200b57cec5SDimitry Andric 
getSymbol()2210b57cec5SDimitry Andric   StringRef getSymbol() const { return S; }
2220b57cec5SDimitry Andric 
2230b57cec5SDimitry Andric   int getExistingMachineCPValue(MachineConstantPool *CP,
224*5ffd83dbSDimitry Andric                                 Align Alignment) override;
2250b57cec5SDimitry Andric 
2260b57cec5SDimitry Andric   void addSelectionDAGCSEId(FoldingSetNodeID &ID) override;
2270b57cec5SDimitry Andric 
2280b57cec5SDimitry Andric   /// hasSameValue - Return true if this ARM constpool value can share the same
2290b57cec5SDimitry Andric   /// constantpool entry as another ARM constpool value.
2300b57cec5SDimitry Andric   bool hasSameValue(ARMConstantPoolValue *ACPV) override;
2310b57cec5SDimitry Andric 
2320b57cec5SDimitry Andric   void print(raw_ostream &O) const override;
2330b57cec5SDimitry Andric 
classof(const ARMConstantPoolValue * ACPV)2340b57cec5SDimitry Andric   static bool classof(const ARMConstantPoolValue *ACPV) {
2350b57cec5SDimitry Andric     return ACPV->isExtSymbol();
2360b57cec5SDimitry Andric   }
2370b57cec5SDimitry Andric 
equals(const ARMConstantPoolSymbol * A)2380b57cec5SDimitry Andric   bool equals(const ARMConstantPoolSymbol *A) const {
2390b57cec5SDimitry Andric     return S == A->S && ARMConstantPoolValue::equals(A);
2400b57cec5SDimitry Andric   }
2410b57cec5SDimitry Andric };
2420b57cec5SDimitry Andric 
2430b57cec5SDimitry Andric /// ARMConstantPoolMBB - ARM-specific constantpool value of a machine basic
2440b57cec5SDimitry Andric /// block.
2450b57cec5SDimitry Andric class ARMConstantPoolMBB : public ARMConstantPoolValue {
2460b57cec5SDimitry Andric   const MachineBasicBlock *MBB; // Machine basic block.
2470b57cec5SDimitry Andric 
2480b57cec5SDimitry Andric   ARMConstantPoolMBB(LLVMContext &C, const MachineBasicBlock *mbb, unsigned id,
2490b57cec5SDimitry Andric                      unsigned char PCAdj, ARMCP::ARMCPModifier Modifier,
2500b57cec5SDimitry Andric                      bool AddCurrentAddress);
2510b57cec5SDimitry Andric 
2520b57cec5SDimitry Andric public:
2530b57cec5SDimitry Andric   static ARMConstantPoolMBB *Create(LLVMContext &C,
2540b57cec5SDimitry Andric                                     const MachineBasicBlock *mbb,
2550b57cec5SDimitry Andric                                     unsigned ID, unsigned char PCAdj);
2560b57cec5SDimitry Andric 
getMBB()2570b57cec5SDimitry Andric   const MachineBasicBlock *getMBB() const { return MBB; }
2580b57cec5SDimitry Andric 
2590b57cec5SDimitry Andric   int getExistingMachineCPValue(MachineConstantPool *CP,
260*5ffd83dbSDimitry Andric                                 Align Alignment) override;
2610b57cec5SDimitry Andric 
2620b57cec5SDimitry Andric   void addSelectionDAGCSEId(FoldingSetNodeID &ID) override;
2630b57cec5SDimitry Andric 
2640b57cec5SDimitry Andric   /// hasSameValue - Return true if this ARM constpool value can share the same
2650b57cec5SDimitry Andric   /// constantpool entry as another ARM constpool value.
2660b57cec5SDimitry Andric   bool hasSameValue(ARMConstantPoolValue *ACPV) override;
2670b57cec5SDimitry Andric 
2680b57cec5SDimitry Andric   void print(raw_ostream &O) const override;
2690b57cec5SDimitry Andric 
classof(const ARMConstantPoolValue * ACPV)2700b57cec5SDimitry Andric   static bool classof(const ARMConstantPoolValue *ACPV) {
2710b57cec5SDimitry Andric     return ACPV->isMachineBasicBlock();
2720b57cec5SDimitry Andric   }
2730b57cec5SDimitry Andric 
equals(const ARMConstantPoolMBB * A)2740b57cec5SDimitry Andric   bool equals(const ARMConstantPoolMBB *A) const {
2750b57cec5SDimitry Andric     return MBB == A->MBB && ARMConstantPoolValue::equals(A);
2760b57cec5SDimitry Andric   }
2770b57cec5SDimitry Andric };
2780b57cec5SDimitry Andric 
2790b57cec5SDimitry Andric } // end namespace llvm
2800b57cec5SDimitry Andric 
2810b57cec5SDimitry Andric #endif // LLVM_LIB_TARGET_ARM_ARMCONSTANTPOOLVALUE_H
282