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