]>
Commit | Line | Data |
---|---|---|
970d7e83 | 1 | //===- lib/MC/MCELFStreamer.cpp - ELF Object Output -----------------------===// |
223e47cc LB |
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 assembles .s files and emits ELF .o object files. | |
11 | // | |
12 | //===----------------------------------------------------------------------===// | |
13 | ||
970d7e83 | 14 | #include "llvm/MC/MCELFStreamer.h" |
1a4d82fc | 15 | #include "llvm/ADT/STLExtras.h" |
223e47cc | 16 | #include "llvm/ADT/SmallPtrSet.h" |
1a4d82fc | 17 | #include "llvm/MC/MCAsmBackend.h" |
85aaf69f | 18 | #include "llvm/MC/MCAsmInfo.h" |
223e47cc LB |
19 | #include "llvm/MC/MCAssembler.h" |
20 | #include "llvm/MC/MCCodeEmitter.h" | |
21 | #include "llvm/MC/MCContext.h" | |
970d7e83 | 22 | #include "llvm/MC/MCELF.h" |
223e47cc LB |
23 | #include "llvm/MC/MCELFSymbolFlags.h" |
24 | #include "llvm/MC/MCExpr.h" | |
25 | #include "llvm/MC/MCInst.h" | |
1a4d82fc | 26 | #include "llvm/MC/MCObjectFileInfo.h" |
223e47cc LB |
27 | #include "llvm/MC/MCObjectStreamer.h" |
28 | #include "llvm/MC/MCSection.h" | |
970d7e83 | 29 | #include "llvm/MC/MCSectionELF.h" |
223e47cc LB |
30 | #include "llvm/MC/MCSymbol.h" |
31 | #include "llvm/MC/MCValue.h" | |
223e47cc LB |
32 | #include "llvm/Support/Debug.h" |
33 | #include "llvm/Support/ELF.h" | |
34 | #include "llvm/Support/ErrorHandling.h" | |
35 | #include "llvm/Support/raw_ostream.h" | |
36 | ||
37 | using namespace llvm; | |
38 | ||
970d7e83 LB |
39 | MCELFStreamer::~MCELFStreamer() { |
40 | } | |
223e47cc | 41 | |
85aaf69f | 42 | void MCELFStreamer::InitSections(bool NoExecStack) { |
223e47cc LB |
43 | // This emulates the same behavior of GNU as. This makes it easier |
44 | // to compare the output as the major sections are in the same order. | |
85aaf69f SL |
45 | MCContext &Ctx = getContext(); |
46 | SwitchSection(Ctx.getObjectFileInfo()->getTextSection()); | |
1a4d82fc JJ |
47 | EmitCodeAlignment(4); |
48 | ||
85aaf69f | 49 | SwitchSection(Ctx.getObjectFileInfo()->getDataSection()); |
1a4d82fc JJ |
50 | EmitCodeAlignment(4); |
51 | ||
85aaf69f | 52 | SwitchSection(Ctx.getObjectFileInfo()->getBSSSection()); |
1a4d82fc JJ |
53 | EmitCodeAlignment(4); |
54 | ||
85aaf69f SL |
55 | SwitchSection(Ctx.getObjectFileInfo()->getTextSection()); |
56 | ||
57 | if (NoExecStack) | |
58 | SwitchSection(Ctx.getAsmInfo()->getNonexecutableStackSection(Ctx)); | |
223e47cc LB |
59 | } |
60 | ||
61 | void MCELFStreamer::EmitLabel(MCSymbol *Symbol) { | |
62 | assert(Symbol->isUndefined() && "Cannot define a symbol twice!"); | |
63 | ||
64 | MCObjectStreamer::EmitLabel(Symbol); | |
65 | ||
66 | const MCSectionELF &Section = | |
67 | static_cast<const MCSectionELF&>(Symbol->getSection()); | |
68 | MCSymbolData &SD = getAssembler().getSymbolData(*Symbol); | |
69 | if (Section.getFlags() & ELF::SHF_TLS) | |
70 | MCELF::SetType(SD, ELF::STT_TLS); | |
71 | } | |
72 | ||
73 | void MCELFStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) { | |
1a4d82fc JJ |
74 | // Let the target do whatever target specific stuff it needs to do. |
75 | getAssembler().getBackend().handleAssemblerFlag(Flag); | |
76 | // Do any generic stuff we need to do. | |
223e47cc LB |
77 | switch (Flag) { |
78 | case MCAF_SyntaxUnified: return; // no-op here. | |
79 | case MCAF_Code16: return; // Change parsing mode; no-op here. | |
80 | case MCAF_Code32: return; // Change parsing mode; no-op here. | |
81 | case MCAF_Code64: return; // Change parsing mode; no-op here. | |
82 | case MCAF_SubsectionsViaSymbols: | |
83 | getAssembler().setSubsectionsViaSymbols(true); | |
84 | return; | |
85 | } | |
86 | ||
87 | llvm_unreachable("invalid assembler flag!"); | |
88 | } | |
89 | ||
1a4d82fc JJ |
90 | void MCELFStreamer::ChangeSection(const MCSection *Section, |
91 | const MCExpr *Subsection) { | |
970d7e83 LB |
92 | MCSectionData *CurSection = getCurrentSectionData(); |
93 | if (CurSection && CurSection->isBundleLocked()) | |
94 | report_fatal_error("Unterminated .bundle_lock when changing a section"); | |
85aaf69f SL |
95 | |
96 | MCAssembler &Asm = getAssembler(); | |
97 | auto *SectionELF = static_cast<const MCSectionELF *>(Section); | |
98 | const MCSymbol *Grp = SectionELF->getGroup(); | |
223e47cc | 99 | if (Grp) |
85aaf69f SL |
100 | Asm.getOrCreateSymbolData(*Grp); |
101 | ||
1a4d82fc | 102 | this->MCObjectStreamer::ChangeSection(Section, Subsection); |
85aaf69f SL |
103 | MCSymbol *SectionSymbol = getContext().getOrCreateSectionSymbol(*SectionELF); |
104 | if (SectionSymbol->isUndefined()) { | |
105 | EmitLabel(SectionSymbol); | |
106 | MCELF::SetType(Asm.getSymbolData(*SectionSymbol), ELF::STT_SECTION); | |
107 | } | |
223e47cc LB |
108 | } |
109 | ||
110 | void MCELFStreamer::EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) { | |
111 | getAssembler().getOrCreateSymbolData(*Symbol); | |
1a4d82fc JJ |
112 | const MCExpr *Value = MCSymbolRefExpr::Create( |
113 | Symbol, MCSymbolRefExpr::VK_WEAKREF, getContext()); | |
223e47cc LB |
114 | Alias->setVariableValue(Value); |
115 | } | |
116 | ||
1a4d82fc JJ |
117 | // When GNU as encounters more than one .type declaration for an object it seems |
118 | // to use a mechanism similar to the one below to decide which type is actually | |
119 | // used in the object file. The greater of T1 and T2 is selected based on the | |
120 | // following ordering: | |
121 | // STT_NOTYPE < STT_OBJECT < STT_FUNC < STT_GNU_IFUNC < STT_TLS < anything else | |
122 | // If neither T1 < T2 nor T2 < T1 according to this ordering, use T2 (the user | |
123 | // provided type). | |
124 | static unsigned CombineSymbolTypes(unsigned T1, unsigned T2) { | |
125 | unsigned TypeOrdering[] = {ELF::STT_NOTYPE, ELF::STT_OBJECT, ELF::STT_FUNC, | |
126 | ELF::STT_GNU_IFUNC, ELF::STT_TLS}; | |
127 | for (unsigned i = 0; i != array_lengthof(TypeOrdering); ++i) { | |
128 | if (T1 == TypeOrdering[i]) | |
129 | return T2; | |
130 | if (T2 == TypeOrdering[i]) | |
131 | return T1; | |
132 | } | |
133 | ||
134 | return T2; | |
135 | } | |
136 | ||
137 | bool MCELFStreamer::EmitSymbolAttribute(MCSymbol *Symbol, | |
138 | MCSymbolAttr Attribute) { | |
223e47cc LB |
139 | // Indirect symbols are handled differently, to match how 'as' handles |
140 | // them. This makes writing matching .o files easier. | |
141 | if (Attribute == MCSA_IndirectSymbol) { | |
142 | // Note that we intentionally cannot use the symbol data here; this is | |
143 | // important for matching the string table that 'as' generates. | |
144 | IndirectSymbolData ISD; | |
145 | ISD.Symbol = Symbol; | |
146 | ISD.SectionData = getCurrentSectionData(); | |
147 | getAssembler().getIndirectSymbols().push_back(ISD); | |
1a4d82fc | 148 | return true; |
223e47cc LB |
149 | } |
150 | ||
151 | // Adding a symbol attribute always introduces the symbol, note that an | |
152 | // important side effect of calling getOrCreateSymbolData here is to register | |
153 | // the symbol with the assembler. | |
154 | MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol); | |
155 | ||
156 | // The implementation of symbol attributes is designed to match 'as', but it | |
157 | // leaves much to desired. It doesn't really make sense to arbitrarily add and | |
158 | // remove flags, but 'as' allows this (in particular, see .desc). | |
159 | // | |
160 | // In the future it might be worth trying to make these operations more well | |
161 | // defined. | |
162 | switch (Attribute) { | |
163 | case MCSA_LazyReference: | |
164 | case MCSA_Reference: | |
165 | case MCSA_SymbolResolver: | |
166 | case MCSA_PrivateExtern: | |
167 | case MCSA_WeakDefinition: | |
168 | case MCSA_WeakDefAutoPrivate: | |
169 | case MCSA_Invalid: | |
170 | case MCSA_IndirectSymbol: | |
1a4d82fc | 171 | return false; |
223e47cc LB |
172 | |
173 | case MCSA_NoDeadStrip: | |
174 | case MCSA_ELF_TypeGnuUniqueObject: | |
175 | // Ignore for now. | |
176 | break; | |
177 | ||
178 | case MCSA_Global: | |
179 | MCELF::SetBinding(SD, ELF::STB_GLOBAL); | |
180 | SD.setExternal(true); | |
181 | BindingExplicitlySet.insert(Symbol); | |
182 | break; | |
183 | ||
184 | case MCSA_WeakReference: | |
185 | case MCSA_Weak: | |
186 | MCELF::SetBinding(SD, ELF::STB_WEAK); | |
187 | SD.setExternal(true); | |
188 | BindingExplicitlySet.insert(Symbol); | |
189 | break; | |
190 | ||
191 | case MCSA_Local: | |
192 | MCELF::SetBinding(SD, ELF::STB_LOCAL); | |
193 | SD.setExternal(false); | |
194 | BindingExplicitlySet.insert(Symbol); | |
195 | break; | |
196 | ||
197 | case MCSA_ELF_TypeFunction: | |
1a4d82fc JJ |
198 | MCELF::SetType(SD, CombineSymbolTypes(MCELF::GetType(SD), |
199 | ELF::STT_FUNC)); | |
223e47cc LB |
200 | break; |
201 | ||
202 | case MCSA_ELF_TypeIndFunction: | |
1a4d82fc JJ |
203 | MCELF::SetType(SD, CombineSymbolTypes(MCELF::GetType(SD), |
204 | ELF::STT_GNU_IFUNC)); | |
223e47cc LB |
205 | break; |
206 | ||
207 | case MCSA_ELF_TypeObject: | |
1a4d82fc JJ |
208 | MCELF::SetType(SD, CombineSymbolTypes(MCELF::GetType(SD), |
209 | ELF::STT_OBJECT)); | |
223e47cc LB |
210 | break; |
211 | ||
212 | case MCSA_ELF_TypeTLS: | |
1a4d82fc JJ |
213 | MCELF::SetType(SD, CombineSymbolTypes(MCELF::GetType(SD), |
214 | ELF::STT_TLS)); | |
223e47cc LB |
215 | break; |
216 | ||
217 | case MCSA_ELF_TypeCommon: | |
1a4d82fc JJ |
218 | // TODO: Emit these as a common symbol. |
219 | MCELF::SetType(SD, CombineSymbolTypes(MCELF::GetType(SD), | |
220 | ELF::STT_OBJECT)); | |
223e47cc LB |
221 | break; |
222 | ||
223 | case MCSA_ELF_TypeNoType: | |
1a4d82fc JJ |
224 | MCELF::SetType(SD, CombineSymbolTypes(MCELF::GetType(SD), |
225 | ELF::STT_NOTYPE)); | |
223e47cc LB |
226 | break; |
227 | ||
228 | case MCSA_Protected: | |
229 | MCELF::SetVisibility(SD, ELF::STV_PROTECTED); | |
230 | break; | |
231 | ||
232 | case MCSA_Hidden: | |
233 | MCELF::SetVisibility(SD, ELF::STV_HIDDEN); | |
234 | break; | |
235 | ||
236 | case MCSA_Internal: | |
237 | MCELF::SetVisibility(SD, ELF::STV_INTERNAL); | |
238 | break; | |
239 | } | |
1a4d82fc JJ |
240 | |
241 | return true; | |
223e47cc LB |
242 | } |
243 | ||
244 | void MCELFStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, | |
245 | unsigned ByteAlignment) { | |
246 | MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol); | |
247 | ||
248 | if (!BindingExplicitlySet.count(Symbol)) { | |
249 | MCELF::SetBinding(SD, ELF::STB_GLOBAL); | |
250 | SD.setExternal(true); | |
251 | } | |
252 | ||
253 | MCELF::SetType(SD, ELF::STT_OBJECT); | |
254 | ||
255 | if (MCELF::GetBinding(SD) == ELF_STB_Local) { | |
256 | const MCSection *Section = getAssembler().getContext().getELFSection(".bss", | |
257 | ELF::SHT_NOBITS, | |
258 | ELF::SHF_WRITE | | |
259 | ELF::SHF_ALLOC, | |
260 | SectionKind::getBSS()); | |
1a4d82fc JJ |
261 | |
262 | AssignSection(Symbol, Section); | |
223e47cc LB |
263 | |
264 | struct LocalCommon L = {&SD, Size, ByteAlignment}; | |
265 | LocalCommons.push_back(L); | |
266 | } else { | |
267 | SD.setCommon(Size, ByteAlignment); | |
268 | } | |
269 | ||
270 | SD.setSize(MCConstantExpr::Create(Size, getContext())); | |
271 | } | |
272 | ||
970d7e83 LB |
273 | void MCELFStreamer::EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) { |
274 | MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol); | |
275 | SD.setSize(Value); | |
276 | } | |
277 | ||
223e47cc LB |
278 | void MCELFStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, |
279 | unsigned ByteAlignment) { | |
280 | // FIXME: Should this be caught and done earlier? | |
281 | MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol); | |
282 | MCELF::SetBinding(SD, ELF::STB_LOCAL); | |
283 | SD.setExternal(false); | |
284 | BindingExplicitlySet.insert(Symbol); | |
285 | EmitCommonSymbol(Symbol, Size, ByteAlignment); | |
286 | } | |
287 | ||
223e47cc | 288 | void MCELFStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size, |
1a4d82fc | 289 | const SMLoc &Loc) { |
970d7e83 LB |
290 | if (getCurrentSectionData()->isBundleLocked()) |
291 | report_fatal_error("Emitting values inside a locked bundle is forbidden"); | |
223e47cc | 292 | fixSymbolsInTLSFixups(Value); |
1a4d82fc | 293 | MCObjectStreamer::EmitValueImpl(Value, Size, Loc); |
223e47cc LB |
294 | } |
295 | ||
970d7e83 LB |
296 | void MCELFStreamer::EmitValueToAlignment(unsigned ByteAlignment, |
297 | int64_t Value, | |
298 | unsigned ValueSize, | |
299 | unsigned MaxBytesToEmit) { | |
300 | if (getCurrentSectionData()->isBundleLocked()) | |
301 | report_fatal_error("Emitting values inside a locked bundle is forbidden"); | |
302 | MCObjectStreamer::EmitValueToAlignment(ByteAlignment, Value, | |
303 | ValueSize, MaxBytesToEmit); | |
304 | } | |
305 | ||
1a4d82fc JJ |
306 | // Add a symbol for the file name of this module. They start after the |
307 | // null symbol and don't count as normal symbol, i.e. a non-STT_FILE symbol | |
308 | // with the same name may appear. | |
223e47cc | 309 | void MCELFStreamer::EmitFileDirective(StringRef Filename) { |
1a4d82fc JJ |
310 | getAssembler().addFileName(Filename); |
311 | } | |
223e47cc | 312 | |
1a4d82fc JJ |
313 | void MCELFStreamer::EmitIdent(StringRef IdentString) { |
314 | const MCSection *Comment = getAssembler().getContext().getELFSection( | |
315 | ".comment", ELF::SHT_PROGBITS, ELF::SHF_MERGE | ELF::SHF_STRINGS, | |
316 | SectionKind::getReadOnly(), 1, ""); | |
317 | PushSection(); | |
318 | SwitchSection(Comment); | |
319 | if (!SeenIdent) { | |
320 | EmitIntValue(0, 1); | |
321 | SeenIdent = true; | |
322 | } | |
323 | EmitBytes(IdentString); | |
324 | EmitIntValue(0, 1); | |
325 | PopSection(); | |
223e47cc LB |
326 | } |
327 | ||
1a4d82fc | 328 | void MCELFStreamer::fixSymbolsInTLSFixups(const MCExpr *expr) { |
223e47cc | 329 | switch (expr->getKind()) { |
970d7e83 LB |
330 | case MCExpr::Target: |
331 | cast<MCTargetExpr>(expr)->fixELFSymbolsInTLSFixups(getAssembler()); | |
332 | break; | |
223e47cc LB |
333 | case MCExpr::Constant: |
334 | break; | |
335 | ||
336 | case MCExpr::Binary: { | |
337 | const MCBinaryExpr *be = cast<MCBinaryExpr>(expr); | |
338 | fixSymbolsInTLSFixups(be->getLHS()); | |
339 | fixSymbolsInTLSFixups(be->getRHS()); | |
340 | break; | |
341 | } | |
342 | ||
343 | case MCExpr::SymbolRef: { | |
344 | const MCSymbolRefExpr &symRef = *cast<MCSymbolRefExpr>(expr); | |
345 | switch (symRef.getKind()) { | |
346 | default: | |
347 | return; | |
348 | case MCSymbolRefExpr::VK_GOTTPOFF: | |
349 | case MCSymbolRefExpr::VK_INDNTPOFF: | |
350 | case MCSymbolRefExpr::VK_NTPOFF: | |
351 | case MCSymbolRefExpr::VK_GOTNTPOFF: | |
352 | case MCSymbolRefExpr::VK_TLSGD: | |
353 | case MCSymbolRefExpr::VK_TLSLD: | |
354 | case MCSymbolRefExpr::VK_TLSLDM: | |
355 | case MCSymbolRefExpr::VK_TPOFF: | |
356 | case MCSymbolRefExpr::VK_DTPOFF: | |
223e47cc LB |
357 | case MCSymbolRefExpr::VK_Mips_TLSGD: |
358 | case MCSymbolRefExpr::VK_Mips_GOTTPREL: | |
359 | case MCSymbolRefExpr::VK_Mips_TPREL_HI: | |
360 | case MCSymbolRefExpr::VK_Mips_TPREL_LO: | |
1a4d82fc JJ |
361 | case MCSymbolRefExpr::VK_PPC_DTPMOD: |
362 | case MCSymbolRefExpr::VK_PPC_TPREL: | |
363 | case MCSymbolRefExpr::VK_PPC_TPREL_LO: | |
364 | case MCSymbolRefExpr::VK_PPC_TPREL_HI: | |
365 | case MCSymbolRefExpr::VK_PPC_TPREL_HA: | |
366 | case MCSymbolRefExpr::VK_PPC_TPREL_HIGHER: | |
367 | case MCSymbolRefExpr::VK_PPC_TPREL_HIGHERA: | |
368 | case MCSymbolRefExpr::VK_PPC_TPREL_HIGHEST: | |
369 | case MCSymbolRefExpr::VK_PPC_TPREL_HIGHESTA: | |
370 | case MCSymbolRefExpr::VK_PPC_DTPREL: | |
371 | case MCSymbolRefExpr::VK_PPC_DTPREL_LO: | |
372 | case MCSymbolRefExpr::VK_PPC_DTPREL_HI: | |
373 | case MCSymbolRefExpr::VK_PPC_DTPREL_HA: | |
374 | case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHER: | |
375 | case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHERA: | |
376 | case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHEST: | |
377 | case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHESTA: | |
378 | case MCSymbolRefExpr::VK_PPC_GOT_TPREL: | |
379 | case MCSymbolRefExpr::VK_PPC_GOT_TPREL_LO: | |
380 | case MCSymbolRefExpr::VK_PPC_GOT_TPREL_HI: | |
381 | case MCSymbolRefExpr::VK_PPC_GOT_TPREL_HA: | |
382 | case MCSymbolRefExpr::VK_PPC_GOT_DTPREL: | |
383 | case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_LO: | |
384 | case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_HI: | |
385 | case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_HA: | |
970d7e83 | 386 | case MCSymbolRefExpr::VK_PPC_TLS: |
1a4d82fc JJ |
387 | case MCSymbolRefExpr::VK_PPC_GOT_TLSGD: |
388 | case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_LO: | |
389 | case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_HI: | |
390 | case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_HA: | |
970d7e83 | 391 | case MCSymbolRefExpr::VK_PPC_TLSGD: |
1a4d82fc JJ |
392 | case MCSymbolRefExpr::VK_PPC_GOT_TLSLD: |
393 | case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_LO: | |
394 | case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_HI: | |
395 | case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_HA: | |
970d7e83 | 396 | case MCSymbolRefExpr::VK_PPC_TLSLD: |
223e47cc LB |
397 | break; |
398 | } | |
399 | MCSymbolData &SD = getAssembler().getOrCreateSymbolData(symRef.getSymbol()); | |
400 | MCELF::SetType(SD, ELF::STT_TLS); | |
401 | break; | |
402 | } | |
403 | ||
404 | case MCExpr::Unary: | |
405 | fixSymbolsInTLSFixups(cast<MCUnaryExpr>(expr)->getSubExpr()); | |
406 | break; | |
407 | } | |
408 | } | |
409 | ||
1a4d82fc JJ |
410 | void MCELFStreamer::EmitInstToFragment(const MCInst &Inst, |
411 | const MCSubtargetInfo &STI) { | |
412 | this->MCObjectStreamer::EmitInstToFragment(Inst, STI); | |
970d7e83 | 413 | MCRelaxableFragment &F = *cast<MCRelaxableFragment>(getCurrentFragment()); |
223e47cc LB |
414 | |
415 | for (unsigned i = 0, e = F.getFixups().size(); i != e; ++i) | |
416 | fixSymbolsInTLSFixups(F.getFixups()[i].getValue()); | |
417 | } | |
418 | ||
1a4d82fc JJ |
419 | void MCELFStreamer::EmitInstToData(const MCInst &Inst, |
420 | const MCSubtargetInfo &STI) { | |
970d7e83 | 421 | MCAssembler &Assembler = getAssembler(); |
223e47cc LB |
422 | SmallVector<MCFixup, 4> Fixups; |
423 | SmallString<256> Code; | |
424 | raw_svector_ostream VecOS(Code); | |
1a4d82fc | 425 | Assembler.getEmitter().EncodeInstruction(Inst, VecOS, Fixups, STI); |
223e47cc LB |
426 | VecOS.flush(); |
427 | ||
428 | for (unsigned i = 0, e = Fixups.size(); i != e; ++i) | |
429 | fixSymbolsInTLSFixups(Fixups[i].getValue()); | |
430 | ||
970d7e83 LB |
431 | // There are several possibilities here: |
432 | // | |
433 | // If bundling is disabled, append the encoded instruction to the current data | |
434 | // fragment (or create a new such fragment if the current fragment is not a | |
435 | // data fragment). | |
436 | // | |
437 | // If bundling is enabled: | |
438 | // - If we're not in a bundle-locked group, emit the instruction into a | |
439 | // fragment of its own. If there are no fixups registered for the | |
440 | // instruction, emit a MCCompactEncodedInstFragment. Otherwise, emit a | |
441 | // MCDataFragment. | |
442 | // - If we're in a bundle-locked group, append the instruction to the current | |
443 | // data fragment because we want all the instructions in a group to get into | |
444 | // the same fragment. Be careful not to do that for the first instruction in | |
445 | // the group, though. | |
446 | MCDataFragment *DF; | |
447 | ||
448 | if (Assembler.isBundlingEnabled()) { | |
449 | MCSectionData *SD = getCurrentSectionData(); | |
450 | if (SD->isBundleLocked() && !SD->isBundleGroupBeforeFirstInst()) | |
451 | // If we are bundle-locked, we re-use the current fragment. | |
452 | // The bundle-locking directive ensures this is a new data fragment. | |
453 | DF = cast<MCDataFragment>(getCurrentFragment()); | |
454 | else if (!SD->isBundleLocked() && Fixups.size() == 0) { | |
455 | // Optimize memory usage by emitting the instruction to a | |
456 | // MCCompactEncodedInstFragment when not in a bundle-locked group and | |
457 | // there are no fixups registered. | |
1a4d82fc JJ |
458 | MCCompactEncodedInstFragment *CEIF = new MCCompactEncodedInstFragment(); |
459 | insert(CEIF); | |
970d7e83 LB |
460 | CEIF->getContents().append(Code.begin(), Code.end()); |
461 | return; | |
462 | } else { | |
1a4d82fc JJ |
463 | DF = new MCDataFragment(); |
464 | insert(DF); | |
85aaf69f SL |
465 | } |
466 | if (SD->getBundleLockState() == MCSectionData::BundleLockedAlignToEnd) { | |
467 | // If this fragment is for a group marked "align_to_end", set a flag | |
468 | // in the fragment. This can happen after the fragment has already been | |
469 | // created if there are nested bundle_align groups and an inner one | |
470 | // is the one marked align_to_end. | |
471 | DF->setAlignToBundleEnd(true); | |
970d7e83 LB |
472 | } |
473 | ||
474 | // We're now emitting an instruction in a bundle group, so this flag has | |
475 | // to be turned off. | |
476 | SD->setBundleGroupBeforeFirstInst(false); | |
477 | } else { | |
478 | DF = getOrCreateDataFragment(); | |
479 | } | |
480 | ||
223e47cc LB |
481 | // Add the fixups and data. |
482 | for (unsigned i = 0, e = Fixups.size(); i != e; ++i) { | |
483 | Fixups[i].setOffset(Fixups[i].getOffset() + DF->getContents().size()); | |
970d7e83 | 484 | DF->getFixups().push_back(Fixups[i]); |
223e47cc | 485 | } |
970d7e83 | 486 | DF->setHasInstructions(true); |
223e47cc LB |
487 | DF->getContents().append(Code.begin(), Code.end()); |
488 | } | |
489 | ||
970d7e83 LB |
490 | void MCELFStreamer::EmitBundleAlignMode(unsigned AlignPow2) { |
491 | assert(AlignPow2 <= 30 && "Invalid bundle alignment"); | |
492 | MCAssembler &Assembler = getAssembler(); | |
85aaf69f SL |
493 | if (AlignPow2 > 0 && (Assembler.getBundleAlignSize() == 0 || |
494 | Assembler.getBundleAlignSize() == 1U << AlignPow2)) | |
495 | Assembler.setBundleAlignSize(1U << AlignPow2); | |
970d7e83 | 496 | else |
85aaf69f | 497 | report_fatal_error(".bundle_align_mode cannot be changed once set"); |
970d7e83 LB |
498 | } |
499 | ||
500 | void MCELFStreamer::EmitBundleLock(bool AlignToEnd) { | |
501 | MCSectionData *SD = getCurrentSectionData(); | |
502 | ||
503 | // Sanity checks | |
504 | // | |
505 | if (!getAssembler().isBundlingEnabled()) | |
506 | report_fatal_error(".bundle_lock forbidden when bundling is disabled"); | |
85aaf69f SL |
507 | |
508 | if (!SD->isBundleLocked()) | |
509 | SD->setBundleGroupBeforeFirstInst(true); | |
970d7e83 LB |
510 | |
511 | SD->setBundleLockState(AlignToEnd ? MCSectionData::BundleLockedAlignToEnd : | |
512 | MCSectionData::BundleLocked); | |
970d7e83 LB |
513 | } |
514 | ||
515 | void MCELFStreamer::EmitBundleUnlock() { | |
516 | MCSectionData *SD = getCurrentSectionData(); | |
517 | ||
518 | // Sanity checks | |
519 | if (!getAssembler().isBundlingEnabled()) | |
520 | report_fatal_error(".bundle_unlock forbidden when bundling is disabled"); | |
521 | else if (!SD->isBundleLocked()) | |
522 | report_fatal_error(".bundle_unlock without matching lock"); | |
523 | else if (SD->isBundleGroupBeforeFirstInst()) | |
524 | report_fatal_error("Empty bundle-locked group is forbidden"); | |
525 | ||
526 | SD->setBundleLockState(MCSectionData::NotBundleLocked); | |
527 | } | |
528 | ||
1a4d82fc | 529 | void MCELFStreamer::Flush() { |
223e47cc LB |
530 | for (std::vector<LocalCommon>::const_iterator i = LocalCommons.begin(), |
531 | e = LocalCommons.end(); | |
532 | i != e; ++i) { | |
533 | MCSymbolData *SD = i->SD; | |
534 | uint64_t Size = i->Size; | |
535 | unsigned ByteAlignment = i->ByteAlignment; | |
536 | const MCSymbol &Symbol = SD->getSymbol(); | |
537 | const MCSection &Section = Symbol.getSection(); | |
538 | ||
539 | MCSectionData &SectData = getAssembler().getOrCreateSectionData(Section); | |
540 | new MCAlignFragment(ByteAlignment, 0, 1, ByteAlignment, &SectData); | |
541 | ||
542 | MCFragment *F = new MCFillFragment(0, 0, Size, &SectData); | |
543 | SD->setFragment(F); | |
544 | ||
545 | // Update the maximum alignment of the section if necessary. | |
546 | if (ByteAlignment > SectData.getAlignment()) | |
547 | SectData.setAlignment(ByteAlignment); | |
548 | } | |
549 | ||
1a4d82fc | 550 | LocalCommons.clear(); |
223e47cc | 551 | } |
1a4d82fc JJ |
552 | |
553 | void MCELFStreamer::FinishImpl() { | |
554 | EmitFrames(nullptr); | |
555 | ||
556 | Flush(); | |
557 | ||
558 | this->MCObjectStreamer::FinishImpl(); | |
970d7e83 | 559 | } |
223e47cc LB |
560 | |
561 | MCStreamer *llvm::createELFStreamer(MCContext &Context, MCAsmBackend &MAB, | |
562 | raw_ostream &OS, MCCodeEmitter *CE, | |
85aaf69f | 563 | bool RelaxAll) { |
223e47cc LB |
564 | MCELFStreamer *S = new MCELFStreamer(Context, MAB, OS, CE); |
565 | if (RelaxAll) | |
566 | S->getAssembler().setRelaxAll(true); | |
223e47cc LB |
567 | return S; |
568 | } | |
970d7e83 LB |
569 | |
570 | void MCELFStreamer::EmitThumbFunc(MCSymbol *Func) { | |
571 | llvm_unreachable("Generic ELF doesn't support this directive"); | |
572 | } | |
573 | ||
970d7e83 LB |
574 | void MCELFStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) { |
575 | llvm_unreachable("ELF doesn't support this directive"); | |
576 | } | |
577 | ||
578 | void MCELFStreamer::BeginCOFFSymbolDef(const MCSymbol *Symbol) { | |
579 | llvm_unreachable("ELF doesn't support this directive"); | |
580 | } | |
581 | ||
582 | void MCELFStreamer::EmitCOFFSymbolStorageClass(int StorageClass) { | |
583 | llvm_unreachable("ELF doesn't support this directive"); | |
584 | } | |
585 | ||
586 | void MCELFStreamer::EmitCOFFSymbolType(int Type) { | |
587 | llvm_unreachable("ELF doesn't support this directive"); | |
588 | } | |
589 | ||
590 | void MCELFStreamer::EndCOFFSymbolDef() { | |
591 | llvm_unreachable("ELF doesn't support this directive"); | |
592 | } | |
593 | ||
594 | void MCELFStreamer::EmitZerofill(const MCSection *Section, MCSymbol *Symbol, | |
595 | uint64_t Size, unsigned ByteAlignment) { | |
596 | llvm_unreachable("ELF doesn't support this directive"); | |
597 | } | |
598 | ||
599 | void MCELFStreamer::EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol, | |
600 | uint64_t Size, unsigned ByteAlignment) { | |
601 | llvm_unreachable("ELF doesn't support this directive"); | |
602 | } |