Some more refactoring.
[oota-llvm.git] / lib / Target / ARM / ARMConstantPoolValue.cpp
1 //===- ARMConstantPoolValue.cpp - 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 #include "ARMConstantPoolValue.h"
15 #include "llvm/ADT/FoldingSet.h"
16 #include "llvm/Constant.h"
17 #include "llvm/Constants.h"
18 #include "llvm/GlobalValue.h"
19 #include "llvm/Type.h"
20 #include "llvm/CodeGen/MachineBasicBlock.h"
21 #include "llvm/Support/raw_ostream.h"
22 #include <cstdlib>
23 using namespace llvm;
24
25 //===----------------------------------------------------------------------===//
26 // ARMConstantPoolValue
27 //===----------------------------------------------------------------------===//
28
29 ARMConstantPoolValue::ARMConstantPoolValue(Type *Ty, unsigned id,
30                                            ARMCP::ARMCPKind kind,
31                                            unsigned char PCAdj,
32                                            ARMCP::ARMCPModifier modifier,
33                                            bool addCurrentAddress)
34   : MachineConstantPoolValue(Ty), S(NULL), LabelId(id), Kind(kind),
35     PCAdjust(PCAdj), Modifier(modifier),
36     AddCurrentAddress(addCurrentAddress) {}
37
38 ARMConstantPoolValue::ARMConstantPoolValue(const Constant *cval, unsigned id,
39                                            ARMCP::ARMCPKind K,
40                                            unsigned char PCAdj,
41                                            ARMCP::ARMCPModifier Modif,
42                                            bool AddCA)
43   : MachineConstantPoolValue((Type*)cval->getType()),
44     CVal(cval), S(NULL), LabelId(id), Kind(K), PCAdjust(PCAdj),
45     Modifier(Modif), AddCurrentAddress(AddCA) {}
46
47 ARMConstantPoolValue::ARMConstantPoolValue(LLVMContext &C,
48                                            const MachineBasicBlock *mbb,
49                                            unsigned id,
50                                            ARMCP::ARMCPKind K,
51                                            unsigned char PCAdj,
52                                            ARMCP::ARMCPModifier Modif,
53                                            bool AddCA)
54   : MachineConstantPoolValue((Type*)Type::getInt8PtrTy(C)),
55     CVal(NULL), MBB(mbb), S(NULL), LabelId(id), Kind(K), PCAdjust(PCAdj),
56     Modifier(Modif), AddCurrentAddress(AddCA) {}
57
58 ARMConstantPoolValue::ARMConstantPoolValue(LLVMContext &C,
59                                            const char *s, unsigned id,
60                                            unsigned char PCAdj,
61                                            ARMCP::ARMCPModifier Modif,
62                                            bool AddCA)
63   : MachineConstantPoolValue((Type*)Type::getInt32Ty(C)),
64     CVal(NULL), S(strdup(s)), LabelId(id), Kind(ARMCP::CPExtSymbol),
65     PCAdjust(PCAdj), Modifier(Modif), AddCurrentAddress(AddCA) {}
66
67 ARMConstantPoolValue::ARMConstantPoolValue(const GlobalValue *gv,
68                                            ARMCP::ARMCPModifier Modif)
69   : MachineConstantPoolValue((Type*)Type::getInt32Ty(gv->getContext())),
70     CVal(gv), S(NULL), LabelId(0), Kind(ARMCP::CPValue), PCAdjust(0),
71     Modifier(Modif), AddCurrentAddress(false) {}
72
73 const GlobalValue *ARMConstantPoolValue::getGV() const {
74   return dyn_cast_or_null<GlobalValue>(CVal);
75 }
76
77 const BlockAddress *ARMConstantPoolValue::getBlockAddress() const {
78   return dyn_cast_or_null<BlockAddress>(CVal);
79 }
80
81 const MachineBasicBlock *ARMConstantPoolValue::getMBB() const {
82   return MBB;
83 }
84
85 const char *ARMConstantPoolValue::getModifierText() const {
86   switch (Modifier) {
87   default: llvm_unreachable("Unknown modifier!");
88     // FIXME: Are these case sensitive? It'd be nice to lower-case all the
89     // strings if that's legal.
90   case ARMCP::no_modifier: return "none";
91   case ARMCP::TLSGD:       return "tlsgd";
92   case ARMCP::GOT:         return "GOT";
93   case ARMCP::GOTOFF:      return "GOTOFF";
94   case ARMCP::GOTTPOFF:    return "gottpoff";
95   case ARMCP::TPOFF:       return "tpoff";
96   }
97 }
98
99 static bool CPV_streq(const char *S1, const char *S2) {
100   if (S1 == S2)
101     return true;
102   if (S1 && S2 && strcmp(S1, S2) == 0)
103     return true;
104   return false;
105 }
106
107 int ARMConstantPoolValue::getExistingMachineCPValue(MachineConstantPool *CP,
108                                                     unsigned Alignment) {
109   unsigned AlignMask = Alignment - 1;
110   const std::vector<MachineConstantPoolEntry> Constants = CP->getConstants();
111   for (unsigned i = 0, e = Constants.size(); i != e; ++i) {
112     if (Constants[i].isMachineConstantPoolEntry() &&
113         (Constants[i].getAlignment() & AlignMask) == 0) {
114       ARMConstantPoolValue *CPV =
115         (ARMConstantPoolValue *)Constants[i].Val.MachineCPVal;
116       if (CPV->CVal == CVal &&
117           CPV->LabelId == LabelId &&
118           CPV->PCAdjust == PCAdjust &&
119           CPV_streq(CPV->S, S) &&
120           CPV->Modifier == Modifier)
121         return i;
122     }
123   }
124
125   return -1;
126 }
127
128 ARMConstantPoolValue::~ARMConstantPoolValue() {
129   free((void*)S);
130 }
131
132 void
133 ARMConstantPoolValue::addSelectionDAGCSEId(FoldingSetNodeID &ID) {
134   ID.AddPointer(CVal);
135   ID.AddPointer(S);
136   ID.AddInteger(LabelId);
137   ID.AddInteger(PCAdjust);
138 }
139
140 bool
141 ARMConstantPoolValue::hasSameValue(ARMConstantPoolValue *ACPV) {
142   if (ACPV->Kind == Kind &&
143       ACPV->CVal == CVal &&
144       ACPV->PCAdjust == PCAdjust &&
145       CPV_streq(ACPV->S, S) &&
146       ACPV->Modifier == Modifier) {
147     if (ACPV->LabelId == LabelId)
148       return true;
149     // Two PC relative constpool entries containing the same GV address or
150     // external symbols. FIXME: What about blockaddress?
151     if (Kind == ARMCP::CPValue || Kind == ARMCP::CPExtSymbol)
152       return true;
153   }
154   return false;
155 }
156
157 void ARMConstantPoolValue::dump() const {
158   errs() << "  " << *this;
159 }
160
161 void ARMConstantPoolValue::print(raw_ostream &O) const {
162   if (CVal)
163     O << CVal->getName();
164   else if (MBB)
165     O << "";
166   else
167     O << S;
168   if (Modifier) O << "(" << getModifierText() << ")";
169   if (PCAdjust != 0) {
170     O << "-(LPC" << LabelId << "+" << (unsigned)PCAdjust;
171     if (AddCurrentAddress) O << "-.";
172     O << ")";
173   }
174 }
175
176 //===----------------------------------------------------------------------===//
177 // ARMConstantPoolConstant
178 //===----------------------------------------------------------------------===//
179
180 ARMConstantPoolConstant::ARMConstantPoolConstant(Type *Ty,
181                                                  const Constant *C,
182                                                  unsigned ID,
183                                                  ARMCP::ARMCPKind Kind,
184                                                  unsigned char PCAdj,
185                                                  ARMCP::ARMCPModifier Modifier,
186                                                  bool AddCurrentAddress)
187   : ARMConstantPoolValue(Ty, ID, Kind, PCAdj, Modifier, AddCurrentAddress),
188     CVal(C) {}
189
190 ARMConstantPoolConstant::ARMConstantPoolConstant(const Constant *C,
191                                                  unsigned ID,
192                                                  ARMCP::ARMCPKind Kind,
193                                                  unsigned char PCAdj,
194                                                  ARMCP::ARMCPModifier Modifier,
195                                                  bool AddCurrentAddress)
196   : ARMConstantPoolValue((Type*)C->getType(), ID, Kind, PCAdj, Modifier,
197                          AddCurrentAddress),
198     CVal(C) {}
199
200 ARMConstantPoolConstant *
201 ARMConstantPoolConstant::Create(const Constant *C, unsigned ID) {
202   return new ARMConstantPoolConstant(C, ID, ARMCP::CPValue, 0,
203                                      ARMCP::no_modifier, false);
204 }
205
206 ARMConstantPoolConstant *
207 ARMConstantPoolConstant::Create(const GlobalValue *GV,
208                                 ARMCP::ARMCPModifier Modifier) {
209   return new ARMConstantPoolConstant((Type*)Type::getInt32Ty(GV->getContext()),
210                                      GV, 0, ARMCP::CPValue, 0,
211                                      Modifier, false);
212 }
213
214 ARMConstantPoolConstant *
215 ARMConstantPoolConstant::Create(const Constant *C, unsigned ID,
216                                 ARMCP::ARMCPKind Kind, unsigned char PCAdj) {
217   return new ARMConstantPoolConstant(C, ID, Kind, PCAdj,
218                                      ARMCP::no_modifier, false);
219 }
220
221 ARMConstantPoolConstant *
222 ARMConstantPoolConstant::Create(const Constant *C, unsigned ID,
223                                 ARMCP::ARMCPKind Kind, unsigned char PCAdj,
224                                 ARMCP::ARMCPModifier Modifier,
225                                 bool AddCurrentAddress) {
226   return new ARMConstantPoolConstant(C, ID, Kind, PCAdj, Modifier,
227                                      AddCurrentAddress);
228 }
229
230 const GlobalValue *ARMConstantPoolConstant::getGV() const {
231   return dyn_cast_or_null<GlobalValue>(CVal);
232 }
233
234 const BlockAddress *ARMConstantPoolConstant::getBlockAddress() const {
235   return dyn_cast_or_null<BlockAddress>(CVal);
236 }
237
238 int ARMConstantPoolConstant::getExistingMachineCPValue(MachineConstantPool *CP,
239                                                        unsigned Alignment) {
240   unsigned AlignMask = Alignment - 1;
241   const std::vector<MachineConstantPoolEntry> Constants = CP->getConstants();
242   for (unsigned i = 0, e = Constants.size(); i != e; ++i) {
243     if (Constants[i].isMachineConstantPoolEntry() &&
244         (Constants[i].getAlignment() & AlignMask) == 0) {
245       ARMConstantPoolValue *CPV =
246         (ARMConstantPoolValue *)Constants[i].Val.MachineCPVal;
247       ARMConstantPoolConstant *APC = dyn_cast<ARMConstantPoolConstant>(CPV);
248       if (!APC) continue;
249
250       if (APC->getGV() == this->CVal &&
251           APC->getLabelId() == this->getLabelId() &&
252           APC->getPCAdjustment() == this->getPCAdjustment() &&
253           CPV_streq(APC->getSymbol(), this->getSymbol()) &&
254           APC->getModifier() == this->getModifier())
255         return i;
256     }
257   }
258
259   return -1;
260 }
261
262 bool ARMConstantPoolConstant::hasSameValue(ARMConstantPoolValue *ACPV) {
263   const ARMConstantPoolConstant *ACPC = dyn_cast<ARMConstantPoolConstant>(ACPV);
264   return ACPC && ACPC->CVal == CVal && ARMConstantPoolValue::hasSameValue(ACPV);
265 }
266
267 void ARMConstantPoolConstant::addSelectionDAGCSEId(FoldingSetNodeID &ID) {
268   ID.AddPointer(CVal);
269   ARMConstantPoolValue::addSelectionDAGCSEId(ID);
270 }
271
272 void ARMConstantPoolConstant::print(raw_ostream &O) const {
273   O << CVal->getName();
274   ARMConstantPoolValue::print(O);
275 }