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