1235633Sdim//===-- ARMConstantPoolValue.h - ARM constantpool value ---------*- C++ -*-===//
2193323Sed//
3193323Sed//                     The LLVM Compiler Infrastructure
4193323Sed//
5193323Sed// This file is distributed under the University of Illinois Open Source
6193323Sed// License. See LICENSE.TXT for details.
7193323Sed//
8193323Sed//===----------------------------------------------------------------------===//
9193323Sed//
10193323Sed// This file implements the ARM specific constantpool value class.
11193323Sed//
12193323Sed//===----------------------------------------------------------------------===//
13193323Sed
14193323Sed#ifndef LLVM_TARGET_ARM_CONSTANTPOOLVALUE_H
15193323Sed#define LLVM_TARGET_ARM_CONSTANTPOOLVALUE_H
16193323Sed
17193323Sed#include "llvm/CodeGen/MachineConstantPool.h"
18263509Sdim#include "llvm/Support/Casting.h"
19218893Sdim#include "llvm/Support/ErrorHandling.h"
20210299Sed#include <cstddef>
21193323Sed
22193323Sednamespace llvm {
23193323Sed
24226890Sdimclass BlockAddress;
25198892Srdivackyclass Constant;
26193323Sedclass GlobalValue;
27198090Srdivackyclass LLVMContext;
28226890Sdimclass MachineBasicBlock;
29193323Sed
30193323Sednamespace ARMCP {
31193323Sed  enum ARMCPKind {
32193323Sed    CPValue,
33198892Srdivacky    CPExtSymbol,
34198892Srdivacky    CPBlockAddress,
35226890Sdim    CPLSDA,
36226890Sdim    CPMachineBasicBlock
37193323Sed  };
38218893Sdim
39218893Sdim  enum ARMCPModifier {
40218893Sdim    no_modifier,
41218893Sdim    TLSGD,
42218893Sdim    GOT,
43218893Sdim    GOTOFF,
44218893Sdim    GOTTPOFF,
45218893Sdim    TPOFF
46218893Sdim  };
47193323Sed}
48193323Sed
49193323Sed/// ARMConstantPoolValue - ARM specific constantpool value. This is used to
50198892Srdivacky/// represent PC-relative displacement between the address of the load
51198892Srdivacky/// instruction and the constant being loaded, i.e. (&GV-(LPIC+8)).
52193323Sedclass ARMConstantPoolValue : public MachineConstantPoolValue {
53193323Sed  unsigned LabelId;        // Label id of the load.
54198892Srdivacky  ARMCP::ARMCPKind Kind;   // Kind of constant.
55198892Srdivacky  unsigned char PCAdjust;  // Extra adjustment if constantpool is pc-relative.
56193323Sed                           // 8 for ARM, 4 for Thumb.
57218893Sdim  ARMCP::ARMCPModifier Modifier;   // GV modifier i.e. (&GV(modifier)-(LPIC+8))
58193323Sed  bool AddCurrentAddress;
59193323Sed
60226890Sdimprotected:
61226890Sdim  ARMConstantPoolValue(Type *Ty, unsigned id, ARMCP::ARMCPKind Kind,
62226890Sdim                       unsigned char PCAdj, ARMCP::ARMCPModifier Modifier,
63226890Sdim                       bool AddCurrentAddress);
64226890Sdim
65226890Sdim  ARMConstantPoolValue(LLVMContext &C, unsigned id, ARMCP::ARMCPKind Kind,
66226890Sdim                       unsigned char PCAdj, ARMCP::ARMCPModifier Modifier,
67226890Sdim                       bool AddCurrentAddress);
68263509Sdim
69263509Sdim  template <typename Derived>
70263509Sdim  int getExistingMachineCPValueImpl(MachineConstantPool *CP,
71263509Sdim                                    unsigned Alignment) {
72263509Sdim    unsigned AlignMask = Alignment - 1;
73263509Sdim    const std::vector<MachineConstantPoolEntry> &Constants = CP->getConstants();
74263509Sdim    for (unsigned i = 0, e = Constants.size(); i != e; ++i) {
75263509Sdim      if (Constants[i].isMachineConstantPoolEntry() &&
76263509Sdim          (Constants[i].getAlignment() & AlignMask) == 0) {
77263509Sdim        ARMConstantPoolValue *CPV =
78263509Sdim            (ARMConstantPoolValue *)Constants[i].Val.MachineCPVal;
79263509Sdim        if (Derived *APC = dyn_cast<Derived>(CPV))
80263509Sdim          if (cast<Derived>(this)->equals(APC))
81263509Sdim            return i;
82263509Sdim      }
83263509Sdim    }
84263509Sdim
85263509Sdim    return -1;
86263509Sdim  }
87263509Sdim
88193323Sedpublic:
89226890Sdim  virtual ~ARMConstantPoolValue();
90193323Sed
91218893Sdim  ARMCP::ARMCPModifier getModifier() const { return Modifier; }
92226890Sdim  const char *getModifierText() const;
93218893Sdim  bool hasModifier() const { return Modifier != ARMCP::no_modifier; }
94226890Sdim
95193323Sed  bool mustAddCurrentAddress() const { return AddCurrentAddress; }
96226890Sdim
97193323Sed  unsigned getLabelId() const { return LabelId; }
98193323Sed  unsigned char getPCAdjustment() const { return PCAdjust; }
99226890Sdim
100198892Srdivacky  bool isGlobalValue() const { return Kind == ARMCP::CPValue; }
101198892Srdivacky  bool isExtSymbol() const { return Kind == ARMCP::CPExtSymbol; }
102226890Sdim  bool isBlockAddress() const { return Kind == ARMCP::CPBlockAddress; }
103226890Sdim  bool isLSDA() const { return Kind == ARMCP::CPLSDA; }
104226890Sdim  bool isMachineBasicBlock() const{ return Kind == ARMCP::CPMachineBasicBlock; }
105193323Sed
106218893Sdim  virtual unsigned getRelocationInfo() const { return 2; }
107198090Srdivacky
108193323Sed  virtual int getExistingMachineCPValue(MachineConstantPool *CP,
109193323Sed                                        unsigned Alignment);
110193323Sed
111226890Sdim  virtual void addSelectionDAGCSEId(FoldingSetNodeID &ID);
112193323Sed
113226890Sdim  /// hasSameValue - Return true if this ARM constpool value can share the same
114226890Sdim  /// constantpool entry as another ARM constpool value.
115226890Sdim  virtual bool hasSameValue(ARMConstantPoolValue *ACPV);
116199481Srdivacky
117226890Sdim  bool equals(const ARMConstantPoolValue *A) const {
118226890Sdim    return this->LabelId == A->LabelId &&
119226890Sdim      this->PCAdjust == A->PCAdjust &&
120226890Sdim      this->Modifier == A->Modifier;
121226890Sdim  }
122226890Sdim
123226890Sdim  virtual void print(raw_ostream &O) const;
124193323Sed  void print(raw_ostream *O) const { if (O) print(*O); }
125193323Sed  void dump() const;
126193323Sed};
127193323Sed
128193323Sedinline raw_ostream &operator<<(raw_ostream &O, const ARMConstantPoolValue &V) {
129193323Sed  V.print(O);
130193323Sed  return O;
131193323Sed}
132193323Sed
133226890Sdim/// ARMConstantPoolConstant - ARM-specific constant pool values for Constants,
134226890Sdim/// Functions, and BlockAddresses.
135226890Sdimclass ARMConstantPoolConstant : public ARMConstantPoolValue {
136226890Sdim  const Constant *CVal;         // Constant being loaded.
137226890Sdim
138226890Sdim  ARMConstantPoolConstant(const Constant *C,
139226890Sdim                          unsigned ID,
140226890Sdim                          ARMCP::ARMCPKind Kind,
141226890Sdim                          unsigned char PCAdj,
142226890Sdim                          ARMCP::ARMCPModifier Modifier,
143226890Sdim                          bool AddCurrentAddress);
144226890Sdim  ARMConstantPoolConstant(Type *Ty, const Constant *C,
145226890Sdim                          unsigned ID,
146226890Sdim                          ARMCP::ARMCPKind Kind,
147226890Sdim                          unsigned char PCAdj,
148226890Sdim                          ARMCP::ARMCPModifier Modifier,
149226890Sdim                          bool AddCurrentAddress);
150226890Sdim
151226890Sdimpublic:
152226890Sdim  static ARMConstantPoolConstant *Create(const Constant *C, unsigned ID);
153226890Sdim  static ARMConstantPoolConstant *Create(const GlobalValue *GV,
154226890Sdim                                         ARMCP::ARMCPModifier Modifier);
155226890Sdim  static ARMConstantPoolConstant *Create(const Constant *C, unsigned ID,
156226890Sdim                                         ARMCP::ARMCPKind Kind,
157226890Sdim                                         unsigned char PCAdj);
158226890Sdim  static ARMConstantPoolConstant *Create(const Constant *C, unsigned ID,
159226890Sdim                                         ARMCP::ARMCPKind Kind,
160226890Sdim                                         unsigned char PCAdj,
161226890Sdim                                         ARMCP::ARMCPModifier Modifier,
162226890Sdim                                         bool AddCurrentAddress);
163226890Sdim
164226890Sdim  const GlobalValue *getGV() const;
165226890Sdim  const BlockAddress *getBlockAddress() const;
166226890Sdim
167226890Sdim  virtual int getExistingMachineCPValue(MachineConstantPool *CP,
168226890Sdim                                        unsigned Alignment);
169226890Sdim
170226890Sdim  /// hasSameValue - Return true if this ARM constpool value can share the same
171226890Sdim  /// constantpool entry as another ARM constpool value.
172226890Sdim  virtual bool hasSameValue(ARMConstantPoolValue *ACPV);
173226890Sdim
174226890Sdim  virtual void addSelectionDAGCSEId(FoldingSetNodeID &ID);
175226890Sdim
176226890Sdim  virtual void print(raw_ostream &O) const;
177226890Sdim  static bool classof(const ARMConstantPoolValue *APV) {
178226890Sdim    return APV->isGlobalValue() || APV->isBlockAddress() || APV->isLSDA();
179226890Sdim  }
180263509Sdim
181263509Sdim  bool equals(const ARMConstantPoolConstant *A) const {
182263509Sdim    return CVal == A->CVal && ARMConstantPoolValue::equals(A);
183263509Sdim  }
184226890Sdim};
185226890Sdim
186226890Sdim/// ARMConstantPoolSymbol - ARM-specific constantpool values for external
187226890Sdim/// symbols.
188226890Sdimclass ARMConstantPoolSymbol : public ARMConstantPoolValue {
189252723Sdim  const std::string S;          // ExtSymbol being loaded.
190226890Sdim
191226890Sdim  ARMConstantPoolSymbol(LLVMContext &C, const char *s, unsigned id,
192226890Sdim                        unsigned char PCAdj, ARMCP::ARMCPModifier Modifier,
193226890Sdim                        bool AddCurrentAddress);
194226890Sdim
195226890Sdimpublic:
196226890Sdim  static ARMConstantPoolSymbol *Create(LLVMContext &C, const char *s,
197226890Sdim                                       unsigned ID, unsigned char PCAdj);
198226890Sdim
199252723Sdim  const char *getSymbol() const { return S.c_str(); }
200226890Sdim
201226890Sdim  virtual int getExistingMachineCPValue(MachineConstantPool *CP,
202226890Sdim                                        unsigned Alignment);
203226890Sdim
204226890Sdim  virtual void addSelectionDAGCSEId(FoldingSetNodeID &ID);
205226890Sdim
206226890Sdim  /// hasSameValue - Return true if this ARM constpool value can share the same
207226890Sdim  /// constantpool entry as another ARM constpool value.
208226890Sdim  virtual bool hasSameValue(ARMConstantPoolValue *ACPV);
209226890Sdim
210226890Sdim  virtual void print(raw_ostream &O) const;
211226890Sdim
212226890Sdim  static bool classof(const ARMConstantPoolValue *ACPV) {
213226890Sdim    return ACPV->isExtSymbol();
214226890Sdim  }
215263509Sdim
216263509Sdim  bool equals(const ARMConstantPoolSymbol *A) const {
217263509Sdim    return S == A->S && ARMConstantPoolValue::equals(A);
218263509Sdim  }
219226890Sdim};
220226890Sdim
221226890Sdim/// ARMConstantPoolMBB - ARM-specific constantpool value of a machine basic
222226890Sdim/// block.
223226890Sdimclass ARMConstantPoolMBB : public ARMConstantPoolValue {
224226890Sdim  const MachineBasicBlock *MBB; // Machine basic block.
225226890Sdim
226226890Sdim  ARMConstantPoolMBB(LLVMContext &C, const MachineBasicBlock *mbb, unsigned id,
227226890Sdim                     unsigned char PCAdj, ARMCP::ARMCPModifier Modifier,
228226890Sdim                     bool AddCurrentAddress);
229226890Sdim
230226890Sdimpublic:
231226890Sdim  static ARMConstantPoolMBB *Create(LLVMContext &C,
232226890Sdim                                    const MachineBasicBlock *mbb,
233226890Sdim                                    unsigned ID, unsigned char PCAdj);
234226890Sdim
235226890Sdim  const MachineBasicBlock *getMBB() const { return MBB; }
236226890Sdim
237226890Sdim  virtual int getExistingMachineCPValue(MachineConstantPool *CP,
238226890Sdim                                        unsigned Alignment);
239226890Sdim
240226890Sdim  virtual void addSelectionDAGCSEId(FoldingSetNodeID &ID);
241226890Sdim
242226890Sdim  /// hasSameValue - Return true if this ARM constpool value can share the same
243226890Sdim  /// constantpool entry as another ARM constpool value.
244226890Sdim  virtual bool hasSameValue(ARMConstantPoolValue *ACPV);
245226890Sdim
246226890Sdim  virtual void print(raw_ostream &O) const;
247226890Sdim
248226890Sdim  static bool classof(const ARMConstantPoolValue *ACPV) {
249226890Sdim    return ACPV->isMachineBasicBlock();
250226890Sdim  }
251263509Sdim
252263509Sdim  bool equals(const ARMConstantPoolMBB *A) const {
253263509Sdim    return MBB == A->MBB && ARMConstantPoolValue::equals(A);
254263509Sdim  }
255226890Sdim};
256226890Sdim
257193323Sed} // End llvm namespace
258193323Sed
259193323Sed#endif
260