blob: 6e8a62cd2e8c8e7a895eaed596333a6631ccfe81 [file] [log] [blame]
David Peixottob9b73622014-02-04 17:22:40 +00001//===- 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"
David Peixottob9b73622014-02-04 17:22:40 +000014#include "llvm/MC/MCContext.h"
Chandler Carruth442f7842014-03-04 10:07:28 +000015#include "llvm/MC/MCExpr.h"
16#include "llvm/MC/MCStreamer.h"
David Peixottob9b73622014-02-04 17:22:40 +000017
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())
Craig Topper062a2ba2014-04-25 05:30:21 +0000112 return nullptr;
David Peixottob9b73622014-02-04 17:22:40 +0000113
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}