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