1327952Sdim//===- ARMConstantPoolValue.cpp - ARM constantpool value ------------------===//
2193323Sed//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6193323Sed//
7193323Sed//===----------------------------------------------------------------------===//
8193323Sed//
9193323Sed// This file implements the ARM specific constantpool value class.
10193323Sed//
11193323Sed//===----------------------------------------------------------------------===//
12193323Sed
13193323Sed#include "ARMConstantPoolValue.h"
14193323Sed#include "llvm/ADT/FoldingSet.h"
15226633Sdim#include "llvm/CodeGen/MachineBasicBlock.h"
16341825Sdim#include "llvm/Config/llvm-config.h"
17249423Sdim#include "llvm/IR/Constant.h"
18249423Sdim#include "llvm/IR/Constants.h"
19249423Sdim#include "llvm/IR/GlobalValue.h"
20360784Sdim#include "llvm/IR/GlobalVariable.h"
21249423Sdim#include "llvm/IR/Type.h"
22321369Sdim#include "llvm/Support/Casting.h"
23321369Sdim#include "llvm/Support/Compiler.h"
24321369Sdim#include "llvm/Support/ErrorHandling.h"
25193323Sed#include "llvm/Support/raw_ostream.h"
26321369Sdim
27193323Sedusing namespace llvm;
28193323Sed
29226633Sdim//===----------------------------------------------------------------------===//
30226633Sdim// ARMConstantPoolValue
31226633Sdim//===----------------------------------------------------------------------===//
32226633Sdim
33226633SdimARMConstantPoolValue::ARMConstantPoolValue(Type *Ty, unsigned id,
34226633Sdim                                           ARMCP::ARMCPKind kind,
35193323Sed                                           unsigned char PCAdj,
36226633Sdim                                           ARMCP::ARMCPModifier modifier,
37226633Sdim                                           bool addCurrentAddress)
38226633Sdim  : MachineConstantPoolValue(Ty), LabelId(id), Kind(kind),
39226633Sdim    PCAdjust(PCAdj), Modifier(modifier),
40226633Sdim    AddCurrentAddress(addCurrentAddress) {}
41193323Sed
42226633SdimARMConstantPoolValue::ARMConstantPoolValue(LLVMContext &C, unsigned id,
43226633Sdim                                           ARMCP::ARMCPKind kind,
44193323Sed                                           unsigned char PCAdj,
45226633Sdim                                           ARMCP::ARMCPModifier modifier,
46226633Sdim                                           bool addCurrentAddress)
47226633Sdim  : MachineConstantPoolValue((Type*)Type::getInt32Ty(C)),
48226633Sdim    LabelId(id), Kind(kind), PCAdjust(PCAdj), Modifier(modifier),
49226633Sdim    AddCurrentAddress(addCurrentAddress) {}
50193323Sed
51321369SdimARMConstantPoolValue::~ARMConstantPoolValue() = default;
52193323Sed
53314564SdimStringRef ARMConstantPoolValue::getModifierText() const {
54226633Sdim  switch (Modifier) {
55226633Sdim    // FIXME: Are these case sensitive? It'd be nice to lower-case all the
56226633Sdim    // strings if that's legal.
57309124Sdim  case ARMCP::no_modifier:
58309124Sdim    return "none";
59309124Sdim  case ARMCP::TLSGD:
60309124Sdim    return "tlsgd";
61309124Sdim  case ARMCP::GOT_PREL:
62309124Sdim    return "GOT_PREL";
63309124Sdim  case ARMCP::GOTTPOFF:
64309124Sdim    return "gottpoff";
65309124Sdim  case ARMCP::TPOFF:
66309124Sdim    return "tpoff";
67314564Sdim  case ARMCP::SBREL:
68314564Sdim    return "SBREL";
69309124Sdim  case ARMCP::SECREL:
70309124Sdim    return "secrel32";
71226633Sdim  }
72234353Sdim  llvm_unreachable("Unknown modifier!");
73226633Sdim}
74226633Sdim
75226633Sdimint ARMConstantPoolValue::getExistingMachineCPValue(MachineConstantPool *CP,
76226633Sdim                                                    unsigned Alignment) {
77234353Sdim  llvm_unreachable("Shouldn't be calling this directly!");
78226633Sdim}
79226633Sdim
80226633Sdimvoid
81226633SdimARMConstantPoolValue::addSelectionDAGCSEId(FoldingSetNodeID &ID) {
82226633Sdim  ID.AddInteger(LabelId);
83226633Sdim  ID.AddInteger(PCAdjust);
84226633Sdim}
85226633Sdim
86226633Sdimbool
87226633SdimARMConstantPoolValue::hasSameValue(ARMConstantPoolValue *ACPV) {
88226633Sdim  if (ACPV->Kind == Kind &&
89226633Sdim      ACPV->PCAdjust == PCAdjust &&
90309124Sdim      ACPV->Modifier == Modifier &&
91309124Sdim      ACPV->LabelId == LabelId &&
92309124Sdim      ACPV->AddCurrentAddress == AddCurrentAddress) {
93226633Sdim    // Two PC relative constpool entries containing the same GV address or
94226633Sdim    // external symbols. FIXME: What about blockaddress?
95226633Sdim    if (Kind == ARMCP::CPValue || Kind == ARMCP::CPExtSymbol)
96226633Sdim      return true;
97226633Sdim  }
98226633Sdim  return false;
99226633Sdim}
100226633Sdim
101321369Sdim#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
102309124SdimLLVM_DUMP_METHOD void ARMConstantPoolValue::dump() const {
103226633Sdim  errs() << "  " << *this;
104226633Sdim}
105321369Sdim#endif
106226633Sdim
107226633Sdimvoid ARMConstantPoolValue::print(raw_ostream &O) const {
108226633Sdim  if (Modifier) O << "(" << getModifierText() << ")";
109226633Sdim  if (PCAdjust != 0) {
110226633Sdim    O << "-(LPC" << LabelId << "+" << (unsigned)PCAdjust;
111226633Sdim    if (AddCurrentAddress) O << "-.";
112226633Sdim    O << ")";
113226633Sdim  }
114226633Sdim}
115226633Sdim
116226633Sdim//===----------------------------------------------------------------------===//
117226633Sdim// ARMConstantPoolConstant
118226633Sdim//===----------------------------------------------------------------------===//
119226633Sdim
120226633SdimARMConstantPoolConstant::ARMConstantPoolConstant(Type *Ty,
121226633Sdim                                                 const Constant *C,
122226633Sdim                                                 unsigned ID,
123226633Sdim                                                 ARMCP::ARMCPKind Kind,
124226633Sdim                                                 unsigned char PCAdj,
125226633Sdim                                                 ARMCP::ARMCPModifier Modifier,
126226633Sdim                                                 bool AddCurrentAddress)
127226633Sdim  : ARMConstantPoolValue(Ty, ID, Kind, PCAdj, Modifier, AddCurrentAddress),
128226633Sdim    CVal(C) {}
129226633Sdim
130226633SdimARMConstantPoolConstant::ARMConstantPoolConstant(const Constant *C,
131226633Sdim                                                 unsigned ID,
132226633Sdim                                                 ARMCP::ARMCPKind Kind,
133226633Sdim                                                 unsigned char PCAdj,
134226633Sdim                                                 ARMCP::ARMCPModifier Modifier,
135226633Sdim                                                 bool AddCurrentAddress)
136226633Sdim  : ARMConstantPoolValue((Type*)C->getType(), ID, Kind, PCAdj, Modifier,
137226633Sdim                         AddCurrentAddress),
138226633Sdim    CVal(C) {}
139226633Sdim
140314564SdimARMConstantPoolConstant::ARMConstantPoolConstant(const GlobalVariable *GV,
141314564Sdim                                                 const Constant *C)
142314564Sdim    : ARMConstantPoolValue((Type *)C->getType(), 0, ARMCP::CPPromotedGlobal, 0,
143327952Sdim                           ARMCP::no_modifier, false), CVal(C) {
144327952Sdim  GVars.insert(GV);
145327952Sdim}
146314564Sdim
147226633SdimARMConstantPoolConstant *
148226633SdimARMConstantPoolConstant::Create(const Constant *C, unsigned ID) {
149226633Sdim  return new ARMConstantPoolConstant(C, ID, ARMCP::CPValue, 0,
150226633Sdim                                     ARMCP::no_modifier, false);
151226633Sdim}
152226633Sdim
153226633SdimARMConstantPoolConstant *
154314564SdimARMConstantPoolConstant::Create(const GlobalVariable *GVar,
155314564Sdim                                const Constant *Initializer) {
156314564Sdim  return new ARMConstantPoolConstant(GVar, Initializer);
157314564Sdim}
158314564Sdim
159314564SdimARMConstantPoolConstant *
160226633SdimARMConstantPoolConstant::Create(const GlobalValue *GV,
161226633Sdim                                ARMCP::ARMCPModifier Modifier) {
162226633Sdim  return new ARMConstantPoolConstant((Type*)Type::getInt32Ty(GV->getContext()),
163226633Sdim                                     GV, 0, ARMCP::CPValue, 0,
164226633Sdim                                     Modifier, false);
165226633Sdim}
166226633Sdim
167226633SdimARMConstantPoolConstant *
168226633SdimARMConstantPoolConstant::Create(const Constant *C, unsigned ID,
169226633Sdim                                ARMCP::ARMCPKind Kind, unsigned char PCAdj) {
170226633Sdim  return new ARMConstantPoolConstant(C, ID, Kind, PCAdj,
171226633Sdim                                     ARMCP::no_modifier, false);
172226633Sdim}
173226633Sdim
174226633SdimARMConstantPoolConstant *
175226633SdimARMConstantPoolConstant::Create(const Constant *C, unsigned ID,
176226633Sdim                                ARMCP::ARMCPKind Kind, unsigned char PCAdj,
177226633Sdim                                ARMCP::ARMCPModifier Modifier,
178226633Sdim                                bool AddCurrentAddress) {
179226633Sdim  return new ARMConstantPoolConstant(C, ID, Kind, PCAdj, Modifier,
180226633Sdim                                     AddCurrentAddress);
181226633Sdim}
182226633Sdim
183226633Sdimconst GlobalValue *ARMConstantPoolConstant::getGV() const {
184198892Srdivacky  return dyn_cast_or_null<GlobalValue>(CVal);
185198892Srdivacky}
186198892Srdivacky
187226633Sdimconst BlockAddress *ARMConstantPoolConstant::getBlockAddress() const {
188198892Srdivacky  return dyn_cast_or_null<BlockAddress>(CVal);
189198892Srdivacky}
190198892Srdivacky
191226633Sdimint ARMConstantPoolConstant::getExistingMachineCPValue(MachineConstantPool *CP,
192226633Sdim                                                       unsigned Alignment) {
193327952Sdim  int index =
194327952Sdim    getExistingMachineCPValueImpl<ARMConstantPoolConstant>(CP, Alignment);
195327952Sdim  if (index != -1) {
196327952Sdim    auto *CPV = static_cast<ARMConstantPoolValue*>(
197327952Sdim        CP->getConstants()[index].Val.MachineCPVal);
198327952Sdim    auto *Constant = cast<ARMConstantPoolConstant>(CPV);
199327952Sdim    Constant->GVars.insert(GVars.begin(), GVars.end());
200327952Sdim  }
201327952Sdim  return index;
202226633Sdim}
203226633Sdim
204226633Sdimbool ARMConstantPoolConstant::hasSameValue(ARMConstantPoolValue *ACPV) {
205226633Sdim  const ARMConstantPoolConstant *ACPC = dyn_cast<ARMConstantPoolConstant>(ACPV);
206226633Sdim  return ACPC && ACPC->CVal == CVal && ARMConstantPoolValue::hasSameValue(ACPV);
207226633Sdim}
208226633Sdim
209226633Sdimvoid ARMConstantPoolConstant::addSelectionDAGCSEId(FoldingSetNodeID &ID) {
210226633Sdim  ID.AddPointer(CVal);
211327952Sdim  for (const auto *GV : GVars)
212327952Sdim    ID.AddPointer(GV);
213226633Sdim  ARMConstantPoolValue::addSelectionDAGCSEId(ID);
214226633Sdim}
215226633Sdim
216226633Sdimvoid ARMConstantPoolConstant::print(raw_ostream &O) const {
217226633Sdim  O << CVal->getName();
218226633Sdim  ARMConstantPoolValue::print(O);
219226633Sdim}
220226633Sdim
221226633Sdim//===----------------------------------------------------------------------===//
222226633Sdim// ARMConstantPoolSymbol
223226633Sdim//===----------------------------------------------------------------------===//
224226633Sdim
225314564SdimARMConstantPoolSymbol::ARMConstantPoolSymbol(LLVMContext &C, StringRef s,
226314564Sdim                                             unsigned id, unsigned char PCAdj,
227226633Sdim                                             ARMCP::ARMCPModifier Modifier,
228226633Sdim                                             bool AddCurrentAddress)
229314564Sdim    : ARMConstantPoolValue(C, id, ARMCP::CPExtSymbol, PCAdj, Modifier,
230314564Sdim                           AddCurrentAddress),
231314564Sdim      S(s) {}
232226633Sdim
233314564SdimARMConstantPoolSymbol *ARMConstantPoolSymbol::Create(LLVMContext &C,
234314564Sdim                                                     StringRef s, unsigned ID,
235314564Sdim                                                     unsigned char PCAdj) {
236226633Sdim  return new ARMConstantPoolSymbol(C, s, ID, PCAdj, ARMCP::no_modifier, false);
237226633Sdim}
238226633Sdim
239226633Sdimint ARMConstantPoolSymbol::getExistingMachineCPValue(MachineConstantPool *CP,
240226633Sdim                                                     unsigned Alignment) {
241261991Sdim  return getExistingMachineCPValueImpl<ARMConstantPoolSymbol>(CP, Alignment);
242193323Sed}
243193323Sed
244226633Sdimbool ARMConstantPoolSymbol::hasSameValue(ARMConstantPoolValue *ACPV) {
245226633Sdim  const ARMConstantPoolSymbol *ACPS = dyn_cast<ARMConstantPoolSymbol>(ACPV);
246249423Sdim  return ACPS && ACPS->S == S && ARMConstantPoolValue::hasSameValue(ACPV);
247198090Srdivacky}
248198090Srdivacky
249226633Sdimvoid ARMConstantPoolSymbol::addSelectionDAGCSEId(FoldingSetNodeID &ID) {
250249423Sdim  ID.AddString(S);
251226633Sdim  ARMConstantPoolValue::addSelectionDAGCSEId(ID);
252193323Sed}
253193323Sed
254226633Sdimvoid ARMConstantPoolSymbol::print(raw_ostream &O) const {
255226633Sdim  O << S;
256226633Sdim  ARMConstantPoolValue::print(O);
257199481Srdivacky}
258199481Srdivacky
259226633Sdim//===----------------------------------------------------------------------===//
260226633Sdim// ARMConstantPoolMBB
261226633Sdim//===----------------------------------------------------------------------===//
262226633Sdim
263226633SdimARMConstantPoolMBB::ARMConstantPoolMBB(LLVMContext &C,
264226633Sdim                                       const MachineBasicBlock *mbb,
265226633Sdim                                       unsigned id, unsigned char PCAdj,
266226633Sdim                                       ARMCP::ARMCPModifier Modifier,
267226633Sdim                                       bool AddCurrentAddress)
268226633Sdim  : ARMConstantPoolValue(C, id, ARMCP::CPMachineBasicBlock, PCAdj,
269226633Sdim                         Modifier, AddCurrentAddress),
270226633Sdim    MBB(mbb) {}
271226633Sdim
272226633SdimARMConstantPoolMBB *ARMConstantPoolMBB::Create(LLVMContext &C,
273226633Sdim                                               const MachineBasicBlock *mbb,
274226633Sdim                                               unsigned ID,
275226633Sdim                                               unsigned char PCAdj) {
276226633Sdim  return new ARMConstantPoolMBB(C, mbb, ID, PCAdj, ARMCP::no_modifier, false);
277193323Sed}
278193323Sed
279226633Sdimint ARMConstantPoolMBB::getExistingMachineCPValue(MachineConstantPool *CP,
280226633Sdim                                                  unsigned Alignment) {
281261991Sdim  return getExistingMachineCPValueImpl<ARMConstantPoolMBB>(CP, Alignment);
282193323Sed}
283226633Sdim
284226633Sdimbool ARMConstantPoolMBB::hasSameValue(ARMConstantPoolValue *ACPV) {
285226633Sdim  const ARMConstantPoolMBB *ACPMBB = dyn_cast<ARMConstantPoolMBB>(ACPV);
286226633Sdim  return ACPMBB && ACPMBB->MBB == MBB &&
287226633Sdim    ARMConstantPoolValue::hasSameValue(ACPV);
288226633Sdim}
289226633Sdim
290226633Sdimvoid ARMConstantPoolMBB::addSelectionDAGCSEId(FoldingSetNodeID &ID) {
291226633Sdim  ID.AddPointer(MBB);
292226633Sdim  ARMConstantPoolValue::addSelectionDAGCSEId(ID);
293226633Sdim}
294226633Sdim
295226633Sdimvoid ARMConstantPoolMBB::print(raw_ostream &O) const {
296327952Sdim  O << printMBBReference(*MBB);
297226633Sdim  ARMConstantPoolValue::print(O);
298226633Sdim}
299