ARMTargetStreamer.cpp revision dce4a407a24b04eebc6a376f8e62b41aaa7b071f
1//===- ARMTargetStreamer.cpp - ARMTargetStreamer class --*- 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 ARMTargetStreamer class.
11//
12//===----------------------------------------------------------------------===//
13#include "llvm/ADT/MapVector.h"
14#include "llvm/MC/MCContext.h"
15#include "llvm/MC/MCExpr.h"
16#include "llvm/MC/MCStreamer.h"
17
18using namespace llvm;
19
20namespace {
21// A class to keep track of assembler-generated constant pools that are use to
22// implement the ldr-pseudo.
23class ConstantPool {
24  typedef SmallVector<std::pair<MCSymbol *, const MCExpr *>, 4> EntryVecTy;
25  EntryVecTy Entries;
26
27public:
28  // Initialize a new empty constant pool
29  ConstantPool() {}
30
31  // Add a new entry to the constant pool in the next slot.
32  // \param Value is the new entry to put in the constant pool.
33  //
34  // \returns a MCExpr that references the newly inserted value
35  const MCExpr *addEntry(const MCExpr *Value, MCContext &Context);
36
37  // Emit the contents of the constant pool using the provided streamer.
38  void emitEntries(MCStreamer &Streamer);
39
40  // Return true if the constant pool is empty
41  bool empty();
42};
43}
44
45namespace llvm {
46class AssemblerConstantPools {
47  // Map type used to keep track of per-Section constant pools used by the
48  // ldr-pseudo opcode. The map associates a section to its constant pool. The
49  // constant pool is a vector of (label, value) pairs. When the ldr
50  // pseudo is parsed we insert a new (label, value) pair into the constant pool
51  // for the current section and add MCSymbolRefExpr to the new label as
52  // an opcode to the ldr. After we have parsed all the user input we
53  // output the (label, value) pairs in each constant pool at the end of the
54  // section.
55  //
56  // We use the MapVector for the map type to ensure stable iteration of
57  // the sections at the end of the parse. We need to iterate over the
58  // sections in a stable order to ensure that we have print the
59  // constant pools in a deterministic order when printing an assembly
60  // file.
61  typedef MapVector<const MCSection *, ConstantPool> ConstantPoolMapTy;
62  ConstantPoolMapTy ConstantPools;
63
64public:
65  AssemblerConstantPools() {}
66  ~AssemblerConstantPools() {}
67
68  void emitAll(MCStreamer &Streamer);
69  void emitForCurrentSection(MCStreamer &Streamer);
70  const MCExpr *addEntry(MCStreamer &Streamer, const MCExpr *Expr);
71
72private:
73  ConstantPool *getConstantPool(const MCSection *Section);
74  ConstantPool &getOrCreateConstantPool(const MCSection *Section);
75};
76}
77
78//
79// ConstantPool implementation
80//
81// Emit the contents of the constant pool using the provided streamer.
82void ConstantPool::emitEntries(MCStreamer &Streamer) {
83  if (Entries.empty())
84    return;
85  Streamer.EmitCodeAlignment(4); // align to 4-byte address
86  Streamer.EmitDataRegion(MCDR_DataRegion);
87  for (EntryVecTy::const_iterator I = Entries.begin(), E = Entries.end();
88       I != E; ++I) {
89    Streamer.EmitLabel(I->first);
90    Streamer.EmitValue(I->second, 4);
91  }
92  Streamer.EmitDataRegion(MCDR_DataRegionEnd);
93  Entries.clear();
94}
95
96const MCExpr *ConstantPool::addEntry(const MCExpr *Value, MCContext &Context) {
97  MCSymbol *CPEntryLabel = Context.CreateTempSymbol();
98
99  Entries.push_back(std::make_pair(CPEntryLabel, Value));
100  return MCSymbolRefExpr::Create(CPEntryLabel, Context);
101}
102
103bool ConstantPool::empty() { return Entries.empty(); }
104
105//
106// AssemblerConstantPools implementation
107//
108ConstantPool *
109AssemblerConstantPools::getConstantPool(const MCSection *Section) {
110  ConstantPoolMapTy::iterator CP = ConstantPools.find(Section);
111  if (CP == ConstantPools.end())
112    return nullptr;
113
114  return &CP->second;
115}
116
117ConstantPool &
118AssemblerConstantPools::getOrCreateConstantPool(const MCSection *Section) {
119  return ConstantPools[Section];
120}
121
122static void emitConstantPool(MCStreamer &Streamer, const MCSection *Section,
123                             ConstantPool &CP) {
124  if (!CP.empty()) {
125    Streamer.SwitchSection(Section);
126    CP.emitEntries(Streamer);
127  }
128}
129
130void AssemblerConstantPools::emitAll(MCStreamer &Streamer) {
131  // Dump contents of assembler constant pools.
132  for (ConstantPoolMapTy::iterator CPI = ConstantPools.begin(),
133                                   CPE = ConstantPools.end();
134       CPI != CPE; ++CPI) {
135    const MCSection *Section = CPI->first;
136    ConstantPool &CP = CPI->second;
137
138    emitConstantPool(Streamer, Section, CP);
139  }
140}
141
142void AssemblerConstantPools::emitForCurrentSection(MCStreamer &Streamer) {
143  const MCSection *Section = Streamer.getCurrentSection().first;
144  if (ConstantPool *CP = getConstantPool(Section)) {
145    emitConstantPool(Streamer, Section, *CP);
146  }
147}
148
149const MCExpr *AssemblerConstantPools::addEntry(MCStreamer &Streamer,
150                                               const MCExpr *Expr) {
151  const MCSection *Section = Streamer.getCurrentSection().first;
152  return getOrCreateConstantPool(Section).addEntry(Expr, Streamer.getContext());
153}
154
155//
156// ARMTargetStreamer Implemenation
157//
158ARMTargetStreamer::ARMTargetStreamer(MCStreamer &S)
159    : MCTargetStreamer(S), ConstantPools(new AssemblerConstantPools()) {}
160
161ARMTargetStreamer::~ARMTargetStreamer() {}
162
163// The constant pool handling is shared by all ARMTargetStreamer
164// implementations.
165const MCExpr *ARMTargetStreamer::addConstantPoolEntry(const MCExpr *Expr) {
166  return ConstantPools->addEntry(Streamer, Expr);
167}
168
169void ARMTargetStreamer::emitCurrentConstantPool() {
170  ConstantPools->emitForCurrentSection(Streamer);
171}
172
173// finish() - write out any non-empty assembler constant pools.
174void ARMTargetStreamer::finish() { ConstantPools->emitAll(Streamer); }
175
176// The remaining callbacks should be handled separately by each
177// streamer.
178void ARMTargetStreamer::emitFnStart() {
179  llvm_unreachable("unimplemented");
180}
181void ARMTargetStreamer::emitFnEnd() {
182  llvm_unreachable("unimplemented");
183}
184void ARMTargetStreamer::emitCantUnwind() {
185  llvm_unreachable("unimplemented");
186}
187void ARMTargetStreamer::emitPersonality(const MCSymbol *Personality) {
188  llvm_unreachable("unimplemented");
189}
190void ARMTargetStreamer::emitPersonalityIndex(unsigned Index) {
191  llvm_unreachable("unimplemented");
192}
193void ARMTargetStreamer::emitHandlerData() {
194  llvm_unreachable("unimplemented");
195}
196void ARMTargetStreamer::emitSetFP(unsigned FpReg, unsigned SpReg,
197                                       int64_t Offset) {
198  llvm_unreachable("unimplemented");
199}
200void ARMTargetStreamer::emitMovSP(unsigned Reg, int64_t Offset) {
201  llvm_unreachable("unimplemented");
202}
203void ARMTargetStreamer::emitPad(int64_t Offset) {
204  llvm_unreachable("unimplemented");
205}
206void
207ARMTargetStreamer::emitRegSave(const SmallVectorImpl<unsigned> &RegList,
208                                    bool isVector) {
209  llvm_unreachable("unimplemented");
210}
211void ARMTargetStreamer::emitUnwindRaw(
212    int64_t StackOffset, const SmallVectorImpl<uint8_t> &Opcodes) {
213  llvm_unreachable("unimplemented");
214}
215void ARMTargetStreamer::switchVendor(StringRef Vendor) {
216  llvm_unreachable("unimplemented");
217}
218void ARMTargetStreamer::emitAttribute(unsigned Attribute, unsigned Value) {
219  llvm_unreachable("unimplemented");
220}
221void ARMTargetStreamer::emitTextAttribute(unsigned Attribute,
222                                               StringRef String) {
223  llvm_unreachable("unimplemented");
224}
225void ARMTargetStreamer::emitIntTextAttribute(unsigned Attribute,
226                                                  unsigned IntValue,
227                                                  StringRef StringValue) {
228  llvm_unreachable("unimplemented");
229}
230void ARMTargetStreamer::emitArch(unsigned Arch) {
231  llvm_unreachable("unimplemented");
232}
233void ARMTargetStreamer::emitObjectArch(unsigned Arch) {
234  llvm_unreachable("unimplemented");
235}
236void ARMTargetStreamer::emitFPU(unsigned FPU) {
237  llvm_unreachable("unimplemented");
238}
239void ARMTargetStreamer::finishAttributeSection() {
240  llvm_unreachable("unimplemented");
241}
242void ARMTargetStreamer::emitInst(uint32_t Inst, char Suffix) {
243  llvm_unreachable("unimplemented");
244}
245void ARMTargetStreamer::AnnotateTLSDescriptorSequence(
246    const MCSymbolRefExpr *SRE) {
247  llvm_unreachable("unimplemented");
248}
249
250void ARMTargetStreamer::emitThumbSet(MCSymbol *Symbol, const MCExpr *Value) {
251  llvm_unreachable("unimplemented");
252}
253