summaryrefslogtreecommitdiff
path: root/lib/Target/ARM/MCTargetDesc/ARMTargetStreamer.cpp
blob: fdc0ed7d67f154230ef1858e7eb78b8474dc227a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
//===- ARMTargetStreamer.cpp - ARMTargetStreamer class --*- C++ -*---------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the ARMTargetStreamer class.
//
//===----------------------------------------------------------------------===//
#include "llvm/ADT/MapVector.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCStreamer.h"

using namespace llvm;

namespace {
// A class to keep track of assembler-generated constant pools that are use to
// implement the ldr-pseudo.
class ConstantPool {
  typedef SmallVector<std::pair<MCSymbol *, const MCExpr *>, 4> EntryVecTy;
  EntryVecTy Entries;

public:
  // Initialize a new empty constant pool
  ConstantPool() {}

  // Add a new entry to the constant pool in the next slot.
  // \param Value is the new entry to put in the constant pool.
  //
  // \returns a MCExpr that references the newly inserted value
  const MCExpr *addEntry(const MCExpr *Value, MCContext &Context);

  // Emit the contents of the constant pool using the provided streamer.
  void emitEntries(MCStreamer &Streamer);

  // Return true if the constant pool is empty
  bool empty();
};
}

namespace llvm {
class AssemblerConstantPools {
  // Map type used to keep track of per-Section constant pools used by the
  // ldr-pseudo opcode. The map associates a section to its constant pool. The
  // constant pool is a vector of (label, value) pairs. When the ldr
  // pseudo is parsed we insert a new (label, value) pair into the constant pool
  // for the current section and add MCSymbolRefExpr to the new label as
  // an opcode to the ldr. After we have parsed all the user input we
  // output the (label, value) pairs in each constant pool at the end of the
  // section.
  //
  // We use the MapVector for the map type to ensure stable iteration of
  // the sections at the end of the parse. We need to iterate over the
  // sections in a stable order to ensure that we have print the
  // constant pools in a deterministic order when printing an assembly
  // file.
  typedef MapVector<const MCSection *, ConstantPool> ConstantPoolMapTy;
  ConstantPoolMapTy ConstantPools;

public:
  AssemblerConstantPools() {}
  ~AssemblerConstantPools() {}

  void emitAll(MCStreamer &Streamer);
  void emitForCurrentSection(MCStreamer &Streamer);
  const MCExpr *addEntry(MCStreamer &Streamer, const MCExpr *Expr);

private:
  ConstantPool *getConstantPool(const MCSection *Section);
  ConstantPool &getOrCreateConstantPool(const MCSection *Section);
};
}

//
// ConstantPool implementation
//
// Emit the contents of the constant pool using the provided streamer.
void ConstantPool::emitEntries(MCStreamer &Streamer) {
  if (Entries.empty())
    return;
  Streamer.EmitCodeAlignment(4); // align to 4-byte address
  Streamer.EmitDataRegion(MCDR_DataRegion);
  for (EntryVecTy::const_iterator I = Entries.begin(), E = Entries.end();
       I != E; ++I) {
    Streamer.EmitLabel(I->first);
    Streamer.EmitValue(I->second, 4);
  }
  Streamer.EmitDataRegion(MCDR_DataRegionEnd);
  Entries.clear();
}

const MCExpr *ConstantPool::addEntry(const MCExpr *Value, MCContext &Context) {
  MCSymbol *CPEntryLabel = Context.CreateTempSymbol();

  Entries.push_back(std::make_pair(CPEntryLabel, Value));
  return MCSymbolRefExpr::Create(CPEntryLabel, Context);
}

bool ConstantPool::empty() { return Entries.empty(); }

//
// AssemblerConstantPools implementation
//
ConstantPool *
AssemblerConstantPools::getConstantPool(const MCSection *Section) {
  ConstantPoolMapTy::iterator CP = ConstantPools.find(Section);
  if (CP == ConstantPools.end())
    return 0;

  return &CP->second;
}

ConstantPool &
AssemblerConstantPools::getOrCreateConstantPool(const MCSection *Section) {
  return ConstantPools[Section];
}

static void emitConstantPool(MCStreamer &Streamer, const MCSection *Section,
                             ConstantPool &CP) {
  if (!CP.empty()) {
    Streamer.SwitchSection(Section);
    CP.emitEntries(Streamer);
  }
}

void AssemblerConstantPools::emitAll(MCStreamer &Streamer) {
  // Dump contents of assembler constant pools.
  for (ConstantPoolMapTy::iterator CPI = ConstantPools.begin(),
                                   CPE = ConstantPools.end();
       CPI != CPE; ++CPI) {
    const MCSection *Section = CPI->first;
    ConstantPool &CP = CPI->second;

    emitConstantPool(Streamer, Section, CP);
  }
}

void AssemblerConstantPools::emitForCurrentSection(MCStreamer &Streamer) {
  const MCSection *Section = Streamer.getCurrentSection().first;
  if (ConstantPool *CP = getConstantPool(Section)) {
    emitConstantPool(Streamer, Section, *CP);
  }
}

const MCExpr *AssemblerConstantPools::addEntry(MCStreamer &Streamer,
                                               const MCExpr *Expr) {
  const MCSection *Section = Streamer.getCurrentSection().first;
  return getOrCreateConstantPool(Section).addEntry(Expr, Streamer.getContext());
}

//
// ARMTargetStreamer Implemenation
//
ARMTargetStreamer::ARMTargetStreamer(MCStreamer &S)
    : MCTargetStreamer(S), ConstantPools(new AssemblerConstantPools()) {}

ARMTargetStreamer::~ARMTargetStreamer() {}

// The constant pool handling is shared by all ARMTargetStreamer
// implementations.
const MCExpr *ARMTargetStreamer::addConstantPoolEntry(const MCExpr *Expr) {
  return ConstantPools->addEntry(Streamer, Expr);
}

void ARMTargetStreamer::emitCurrentConstantPool() {
  ConstantPools->emitForCurrentSection(Streamer);
}

// finish() - write out any non-empty assembler constant pools.
void ARMTargetStreamer::finish() { ConstantPools->emitAll(Streamer); }

// The remaining callbacks should be handled separately by each
// streamer.
void ARMTargetStreamer::emitFnStart() {
  llvm_unreachable("unimplemented");
}
void ARMTargetStreamer::emitFnEnd() {
  llvm_unreachable("unimplemented");
}
void ARMTargetStreamer::emitCantUnwind() {
  llvm_unreachable("unimplemented");
}
void ARMTargetStreamer::emitPersonality(const MCSymbol *Personality) {
  llvm_unreachable("unimplemented");
}
void ARMTargetStreamer::emitPersonalityIndex(unsigned Index) {
  llvm_unreachable("unimplemented");
}
void ARMTargetStreamer::emitHandlerData() {
  llvm_unreachable("unimplemented");
}
void ARMTargetStreamer::emitSetFP(unsigned FpReg, unsigned SpReg,
                                       int64_t Offset) {
  llvm_unreachable("unimplemented");
}
void ARMTargetStreamer::emitMovSP(unsigned Reg, int64_t Offset) {
  llvm_unreachable("unimplemented");
}
void ARMTargetStreamer::emitPad(int64_t Offset) {
  llvm_unreachable("unimplemented");
}
void
ARMTargetStreamer::emitRegSave(const SmallVectorImpl<unsigned> &RegList,
                                    bool isVector) {
  llvm_unreachable("unimplemented");
}
void ARMTargetStreamer::emitUnwindRaw(
    int64_t StackOffset, const SmallVectorImpl<uint8_t> &Opcodes) {
  llvm_unreachable("unimplemented");
}
void ARMTargetStreamer::switchVendor(StringRef Vendor) {
  llvm_unreachable("unimplemented");
}
void ARMTargetStreamer::emitAttribute(unsigned Attribute, unsigned Value) {
  llvm_unreachable("unimplemented");
}
void ARMTargetStreamer::emitTextAttribute(unsigned Attribute,
                                               StringRef String) {
  llvm_unreachable("unimplemented");
}
void ARMTargetStreamer::emitIntTextAttribute(unsigned Attribute,
                                                  unsigned IntValue,
                                                  StringRef StringValue) {
  llvm_unreachable("unimplemented");
}
void ARMTargetStreamer::emitArch(unsigned Arch) {
  llvm_unreachable("unimplemented");
}
void ARMTargetStreamer::emitObjectArch(unsigned Arch) {
  llvm_unreachable("unimplemented");
}
void ARMTargetStreamer::emitFPU(unsigned FPU) {
  llvm_unreachable("unimplemented");
}
void ARMTargetStreamer::finishAttributeSection() {
  llvm_unreachable("unimplemented");
}
void ARMTargetStreamer::emitInst(uint32_t Inst, char Suffix) {
  llvm_unreachable("unimplemented");
}
void ARMTargetStreamer::AnnotateTLSDescriptorSequence(
    const MCSymbolRefExpr *SRE) {
  llvm_unreachable("unimplemented");
}