1 //===- lib/MC/MCObjectStreamer.cpp - Object File MCStreamer Interface -----===//
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 #include "llvm/MC/MCObjectStreamer.h"
11 #include "llvm/ADT/STLExtras.h"
12 #include "llvm/MC/MCAsmBackend.h"
13 #include "llvm/MC/MCAssembler.h"
14 #include "llvm/MC/MCCodeEmitter.h"
15 #include "llvm/MC/MCCodeView.h"
16 #include "llvm/MC/MCContext.h"
17 #include "llvm/MC/MCDwarf.h"
18 #include "llvm/MC/MCExpr.h"
19 #include "llvm/MC/MCObjectWriter.h"
20 #include "llvm/MC/MCSection.h"
21 #include "llvm/MC/MCSymbol.h"
22 #include "llvm/Support/ErrorHandling.h"
23 #include "llvm/Support/SourceMgr.h"
24 using namespace llvm;
25
MCObjectStreamer(MCContext & Context,std::unique_ptr<MCAsmBackend> TAB,std::unique_ptr<MCObjectWriter> OW,std::unique_ptr<MCCodeEmitter> Emitter)26 MCObjectStreamer::MCObjectStreamer(MCContext &Context,
27 std::unique_ptr<MCAsmBackend> TAB,
28 std::unique_ptr<MCObjectWriter> OW,
29 std::unique_ptr<MCCodeEmitter> Emitter)
30 : MCStreamer(Context),
31 Assembler(llvm::make_unique<MCAssembler>(
32 Context, std::move(TAB), std::move(Emitter), std::move(OW))),
33 EmitEHFrame(true), EmitDebugFrame(false) {}
34
~MCObjectStreamer()35 MCObjectStreamer::~MCObjectStreamer() {}
36
37 // AssemblerPtr is used for evaluation of expressions and causes
38 // difference between asm and object outputs. Return nullptr to in
39 // inline asm mode to limit divergence to assembly inputs.
getAssemblerPtr()40 MCAssembler *MCObjectStreamer::getAssemblerPtr() {
41 if (getUseAssemblerInfoForParsing())
42 return Assembler.get();
43 return nullptr;
44 }
45
flushPendingLabels(MCFragment * F,uint64_t FOffset)46 void MCObjectStreamer::flushPendingLabels(MCFragment *F, uint64_t FOffset) {
47 if (PendingLabels.empty())
48 return;
49 if (!F) {
50 F = new MCDataFragment();
51 MCSection *CurSection = getCurrentSectionOnly();
52 CurSection->getFragmentList().insert(CurInsertionPoint, F);
53 F->setParent(CurSection);
54 }
55 for (MCSymbol *Sym : PendingLabels) {
56 Sym->setFragment(F);
57 Sym->setOffset(FOffset);
58 }
59 PendingLabels.clear();
60 }
61
62 // When fixup's offset is a forward declared label, e.g.:
63 //
64 // .reloc 1f, R_MIPS_JALR, foo
65 // 1: nop
66 //
67 // postpone adding it to Fixups vector until the label is defined and its offset
68 // is known.
resolvePendingFixups()69 void MCObjectStreamer::resolvePendingFixups() {
70 for (PendingMCFixup &PendingFixup : PendingFixups) {
71 if (!PendingFixup.Sym || PendingFixup.Sym->isUndefined ()) {
72 getContext().reportError(PendingFixup.Fixup.getLoc(),
73 "unresolved relocation offset");
74 continue;
75 }
76 flushPendingLabels(PendingFixup.DF, PendingFixup.DF->getContents().size());
77 PendingFixup.Fixup.setOffset(PendingFixup.Sym->getOffset());
78 PendingFixup.DF->getFixups().push_back(PendingFixup.Fixup);
79 }
80 PendingFixups.clear();
81 }
82
83 // As a compile-time optimization, avoid allocating and evaluating an MCExpr
84 // tree for (Hi - Lo) when Hi and Lo are offsets into the same fragment.
85 static Optional<uint64_t>
absoluteSymbolDiff(MCAssembler & Asm,const MCSymbol * Hi,const MCSymbol * Lo)86 absoluteSymbolDiff(MCAssembler &Asm, const MCSymbol *Hi, const MCSymbol *Lo) {
87 assert(Hi && Lo);
88 if (Asm.getBackendPtr()->requiresDiffExpressionRelocations())
89 return None;
90
91 if (!Hi->getFragment() || Hi->getFragment() != Lo->getFragment() ||
92 Hi->isVariable() || Lo->isVariable())
93 return None;
94
95 return Hi->getOffset() - Lo->getOffset();
96 }
97
emitAbsoluteSymbolDiff(const MCSymbol * Hi,const MCSymbol * Lo,unsigned Size)98 void MCObjectStreamer::emitAbsoluteSymbolDiff(const MCSymbol *Hi,
99 const MCSymbol *Lo,
100 unsigned Size) {
101 if (Optional<uint64_t> Diff = absoluteSymbolDiff(getAssembler(), Hi, Lo)) {
102 EmitIntValue(*Diff, Size);
103 return;
104 }
105 MCStreamer::emitAbsoluteSymbolDiff(Hi, Lo, Size);
106 }
107
emitAbsoluteSymbolDiffAsULEB128(const MCSymbol * Hi,const MCSymbol * Lo)108 void MCObjectStreamer::emitAbsoluteSymbolDiffAsULEB128(const MCSymbol *Hi,
109 const MCSymbol *Lo) {
110 if (Optional<uint64_t> Diff = absoluteSymbolDiff(getAssembler(), Hi, Lo)) {
111 EmitULEB128IntValue(*Diff);
112 return;
113 }
114 MCStreamer::emitAbsoluteSymbolDiffAsULEB128(Hi, Lo);
115 }
116
reset()117 void MCObjectStreamer::reset() {
118 if (Assembler)
119 Assembler->reset();
120 CurInsertionPoint = MCSection::iterator();
121 EmitEHFrame = true;
122 EmitDebugFrame = false;
123 PendingLabels.clear();
124 MCStreamer::reset();
125 }
126
EmitFrames(MCAsmBackend * MAB)127 void MCObjectStreamer::EmitFrames(MCAsmBackend *MAB) {
128 if (!getNumFrameInfos())
129 return;
130
131 if (EmitEHFrame)
132 MCDwarfFrameEmitter::Emit(*this, MAB, true);
133
134 if (EmitDebugFrame)
135 MCDwarfFrameEmitter::Emit(*this, MAB, false);
136 }
137
getCurrentFragment() const138 MCFragment *MCObjectStreamer::getCurrentFragment() const {
139 assert(getCurrentSectionOnly() && "No current section!");
140
141 if (CurInsertionPoint != getCurrentSectionOnly()->getFragmentList().begin())
142 return &*std::prev(CurInsertionPoint);
143
144 return nullptr;
145 }
146
CanReuseDataFragment(const MCDataFragment & F,const MCAssembler & Assembler,const MCSubtargetInfo * STI)147 static bool CanReuseDataFragment(const MCDataFragment &F,
148 const MCAssembler &Assembler,
149 const MCSubtargetInfo *STI) {
150 if (!F.hasInstructions())
151 return true;
152 // When bundling is enabled, we don't want to add data to a fragment that
153 // already has instructions (see MCELFStreamer::EmitInstToData for details)
154 if (Assembler.isBundlingEnabled())
155 return Assembler.getRelaxAll();
156 // If the subtarget is changed mid fragment we start a new fragment to record
157 // the new STI.
158 return !STI || F.getSubtargetInfo() == STI;
159 }
160
161 MCDataFragment *
getOrCreateDataFragment(const MCSubtargetInfo * STI)162 MCObjectStreamer::getOrCreateDataFragment(const MCSubtargetInfo *STI) {
163 MCDataFragment *F = dyn_cast_or_null<MCDataFragment>(getCurrentFragment());
164 if (!F || !CanReuseDataFragment(*F, *Assembler, STI)) {
165 F = new MCDataFragment();
166 insert(F);
167 }
168 return F;
169 }
170
getOrCreatePaddingFragment()171 MCPaddingFragment *MCObjectStreamer::getOrCreatePaddingFragment() {
172 MCPaddingFragment *F =
173 dyn_cast_or_null<MCPaddingFragment>(getCurrentFragment());
174 if (!F) {
175 F = new MCPaddingFragment();
176 insert(F);
177 }
178 return F;
179 }
180
visitUsedSymbol(const MCSymbol & Sym)181 void MCObjectStreamer::visitUsedSymbol(const MCSymbol &Sym) {
182 Assembler->registerSymbol(Sym);
183 }
184
EmitCFISections(bool EH,bool Debug)185 void MCObjectStreamer::EmitCFISections(bool EH, bool Debug) {
186 MCStreamer::EmitCFISections(EH, Debug);
187 EmitEHFrame = EH;
188 EmitDebugFrame = Debug;
189 }
190
EmitValueImpl(const MCExpr * Value,unsigned Size,SMLoc Loc)191 void MCObjectStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size,
192 SMLoc Loc) {
193 MCStreamer::EmitValueImpl(Value, Size, Loc);
194 MCDataFragment *DF = getOrCreateDataFragment();
195 flushPendingLabels(DF, DF->getContents().size());
196
197 MCDwarfLineEntry::Make(this, getCurrentSectionOnly());
198
199 // Avoid fixups when possible.
200 int64_t AbsValue;
201 if (Value->evaluateAsAbsolute(AbsValue, getAssemblerPtr())) {
202 if (!isUIntN(8 * Size, AbsValue) && !isIntN(8 * Size, AbsValue)) {
203 getContext().reportError(
204 Loc, "value evaluated as " + Twine(AbsValue) + " is out of range.");
205 return;
206 }
207 EmitIntValue(AbsValue, Size);
208 return;
209 }
210 DF->getFixups().push_back(
211 MCFixup::create(DF->getContents().size(), Value,
212 MCFixup::getKindForSize(Size, false), Loc));
213 DF->getContents().resize(DF->getContents().size() + Size, 0);
214 }
215
EmitCFILabel()216 MCSymbol *MCObjectStreamer::EmitCFILabel() {
217 MCSymbol *Label = getContext().createTempSymbol("cfi", true);
218 EmitLabel(Label);
219 return Label;
220 }
221
EmitCFIStartProcImpl(MCDwarfFrameInfo & Frame)222 void MCObjectStreamer::EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame) {
223 // We need to create a local symbol to avoid relocations.
224 Frame.Begin = getContext().createTempSymbol();
225 EmitLabel(Frame.Begin);
226 }
227
EmitCFIEndProcImpl(MCDwarfFrameInfo & Frame)228 void MCObjectStreamer::EmitCFIEndProcImpl(MCDwarfFrameInfo &Frame) {
229 Frame.End = getContext().createTempSymbol();
230 EmitLabel(Frame.End);
231 }
232
EmitLabel(MCSymbol * Symbol,SMLoc Loc)233 void MCObjectStreamer::EmitLabel(MCSymbol *Symbol, SMLoc Loc) {
234 MCStreamer::EmitLabel(Symbol, Loc);
235
236 getAssembler().registerSymbol(*Symbol);
237
238 // If there is a current fragment, mark the symbol as pointing into it.
239 // Otherwise queue the label and set its fragment pointer when we emit the
240 // next fragment.
241 auto *F = dyn_cast_or_null<MCDataFragment>(getCurrentFragment());
242 if (F && !(getAssembler().isBundlingEnabled() &&
243 getAssembler().getRelaxAll())) {
244 Symbol->setFragment(F);
245 Symbol->setOffset(F->getContents().size());
246 } else {
247 PendingLabels.push_back(Symbol);
248 }
249 }
250
EmitLabel(MCSymbol * Symbol,SMLoc Loc,MCFragment * F)251 void MCObjectStreamer::EmitLabel(MCSymbol *Symbol, SMLoc Loc, MCFragment *F) {
252 MCStreamer::EmitLabel(Symbol, Loc);
253 getAssembler().registerSymbol(*Symbol);
254 auto *DF = dyn_cast_or_null<MCDataFragment>(F);
255 if (DF)
256 Symbol->setFragment(F);
257 else
258 PendingLabels.push_back(Symbol);
259 }
260
EmitULEB128Value(const MCExpr * Value)261 void MCObjectStreamer::EmitULEB128Value(const MCExpr *Value) {
262 int64_t IntValue;
263 if (Value->evaluateAsAbsolute(IntValue, getAssemblerPtr())) {
264 EmitULEB128IntValue(IntValue);
265 return;
266 }
267 insert(new MCLEBFragment(*Value, false));
268 }
269
EmitSLEB128Value(const MCExpr * Value)270 void MCObjectStreamer::EmitSLEB128Value(const MCExpr *Value) {
271 int64_t IntValue;
272 if (Value->evaluateAsAbsolute(IntValue, getAssemblerPtr())) {
273 EmitSLEB128IntValue(IntValue);
274 return;
275 }
276 insert(new MCLEBFragment(*Value, true));
277 }
278
EmitWeakReference(MCSymbol * Alias,const MCSymbol * Symbol)279 void MCObjectStreamer::EmitWeakReference(MCSymbol *Alias,
280 const MCSymbol *Symbol) {
281 report_fatal_error("This file format doesn't support weak aliases.");
282 }
283
ChangeSection(MCSection * Section,const MCExpr * Subsection)284 void MCObjectStreamer::ChangeSection(MCSection *Section,
285 const MCExpr *Subsection) {
286 changeSectionImpl(Section, Subsection);
287 }
288
changeSectionImpl(MCSection * Section,const MCExpr * Subsection)289 bool MCObjectStreamer::changeSectionImpl(MCSection *Section,
290 const MCExpr *Subsection) {
291 assert(Section && "Cannot switch to a null section!");
292 flushPendingLabels(nullptr);
293 getContext().clearDwarfLocSeen();
294
295 bool Created = getAssembler().registerSection(*Section);
296
297 int64_t IntSubsection = 0;
298 if (Subsection &&
299 !Subsection->evaluateAsAbsolute(IntSubsection, getAssemblerPtr()))
300 report_fatal_error("Cannot evaluate subsection number");
301 if (IntSubsection < 0 || IntSubsection > 8192)
302 report_fatal_error("Subsection number out of range");
303 CurInsertionPoint =
304 Section->getSubsectionInsertionPoint(unsigned(IntSubsection));
305 return Created;
306 }
307
EmitAssignment(MCSymbol * Symbol,const MCExpr * Value)308 void MCObjectStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) {
309 getAssembler().registerSymbol(*Symbol);
310 MCStreamer::EmitAssignment(Symbol, Value);
311 }
312
mayHaveInstructions(MCSection & Sec) const313 bool MCObjectStreamer::mayHaveInstructions(MCSection &Sec) const {
314 return Sec.hasInstructions();
315 }
316
EmitInstruction(const MCInst & Inst,const MCSubtargetInfo & STI,bool)317 void MCObjectStreamer::EmitInstruction(const MCInst &Inst,
318 const MCSubtargetInfo &STI, bool) {
319 getAssembler().getBackend().handleCodePaddingInstructionBegin(Inst);
320 EmitInstructionImpl(Inst, STI);
321 getAssembler().getBackend().handleCodePaddingInstructionEnd(Inst);
322 }
323
EmitInstructionImpl(const MCInst & Inst,const MCSubtargetInfo & STI)324 void MCObjectStreamer::EmitInstructionImpl(const MCInst &Inst,
325 const MCSubtargetInfo &STI) {
326 MCStreamer::EmitInstruction(Inst, STI);
327
328 MCSection *Sec = getCurrentSectionOnly();
329 Sec->setHasInstructions(true);
330
331 // Now that a machine instruction has been assembled into this section, make
332 // a line entry for any .loc directive that has been seen.
333 MCDwarfLineEntry::Make(this, getCurrentSectionOnly());
334
335 // If this instruction doesn't need relaxation, just emit it as data.
336 MCAssembler &Assembler = getAssembler();
337 if (!Assembler.getBackend().mayNeedRelaxation(Inst, STI)) {
338 EmitInstToData(Inst, STI);
339 return;
340 }
341
342 // Otherwise, relax and emit it as data if either:
343 // - The RelaxAll flag was passed
344 // - Bundling is enabled and this instruction is inside a bundle-locked
345 // group. We want to emit all such instructions into the same data
346 // fragment.
347 if (Assembler.getRelaxAll() ||
348 (Assembler.isBundlingEnabled() && Sec->isBundleLocked())) {
349 MCInst Relaxed;
350 getAssembler().getBackend().relaxInstruction(Inst, STI, Relaxed);
351 while (getAssembler().getBackend().mayNeedRelaxation(Relaxed, STI))
352 getAssembler().getBackend().relaxInstruction(Relaxed, STI, Relaxed);
353 EmitInstToData(Relaxed, STI);
354 return;
355 }
356
357 // Otherwise emit to a separate fragment.
358 EmitInstToFragment(Inst, STI);
359 }
360
EmitInstToFragment(const MCInst & Inst,const MCSubtargetInfo & STI)361 void MCObjectStreamer::EmitInstToFragment(const MCInst &Inst,
362 const MCSubtargetInfo &STI) {
363 if (getAssembler().getRelaxAll() && getAssembler().isBundlingEnabled())
364 llvm_unreachable("All instructions should have already been relaxed");
365
366 // Always create a new, separate fragment here, because its size can change
367 // during relaxation.
368 MCRelaxableFragment *IF = new MCRelaxableFragment(Inst, STI);
369 insert(IF);
370
371 SmallString<128> Code;
372 raw_svector_ostream VecOS(Code);
373 getAssembler().getEmitter().encodeInstruction(Inst, VecOS, IF->getFixups(),
374 STI);
375 IF->getContents().append(Code.begin(), Code.end());
376 }
377
378 #ifndef NDEBUG
379 static const char *const BundlingNotImplementedMsg =
380 "Aligned bundling is not implemented for this object format";
381 #endif
382
EmitBundleAlignMode(unsigned AlignPow2)383 void MCObjectStreamer::EmitBundleAlignMode(unsigned AlignPow2) {
384 llvm_unreachable(BundlingNotImplementedMsg);
385 }
386
EmitBundleLock(bool AlignToEnd)387 void MCObjectStreamer::EmitBundleLock(bool AlignToEnd) {
388 llvm_unreachable(BundlingNotImplementedMsg);
389 }
390
EmitBundleUnlock()391 void MCObjectStreamer::EmitBundleUnlock() {
392 llvm_unreachable(BundlingNotImplementedMsg);
393 }
394
EmitDwarfLocDirective(unsigned FileNo,unsigned Line,unsigned Column,unsigned Flags,unsigned Isa,unsigned Discriminator,StringRef FileName)395 void MCObjectStreamer::EmitDwarfLocDirective(unsigned FileNo, unsigned Line,
396 unsigned Column, unsigned Flags,
397 unsigned Isa,
398 unsigned Discriminator,
399 StringRef FileName) {
400 // In case we see two .loc directives in a row, make sure the
401 // first one gets a line entry.
402 MCDwarfLineEntry::Make(this, getCurrentSectionOnly());
403
404 this->MCStreamer::EmitDwarfLocDirective(FileNo, Line, Column, Flags,
405 Isa, Discriminator, FileName);
406 }
407
buildSymbolDiff(MCObjectStreamer & OS,const MCSymbol * A,const MCSymbol * B)408 static const MCExpr *buildSymbolDiff(MCObjectStreamer &OS, const MCSymbol *A,
409 const MCSymbol *B) {
410 MCContext &Context = OS.getContext();
411 MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None;
412 const MCExpr *ARef = MCSymbolRefExpr::create(A, Variant, Context);
413 const MCExpr *BRef = MCSymbolRefExpr::create(B, Variant, Context);
414 const MCExpr *AddrDelta =
415 MCBinaryExpr::create(MCBinaryExpr::Sub, ARef, BRef, Context);
416 return AddrDelta;
417 }
418
emitDwarfSetLineAddr(MCObjectStreamer & OS,MCDwarfLineTableParams Params,int64_t LineDelta,const MCSymbol * Label,int PointerSize)419 static void emitDwarfSetLineAddr(MCObjectStreamer &OS,
420 MCDwarfLineTableParams Params,
421 int64_t LineDelta, const MCSymbol *Label,
422 int PointerSize) {
423 // emit the sequence to set the address
424 OS.EmitIntValue(dwarf::DW_LNS_extended_op, 1);
425 OS.EmitULEB128IntValue(PointerSize + 1);
426 OS.EmitIntValue(dwarf::DW_LNE_set_address, 1);
427 OS.EmitSymbolValue(Label, PointerSize);
428
429 // emit the sequence for the LineDelta (from 1) and a zero address delta.
430 MCDwarfLineAddr::Emit(&OS, Params, LineDelta, 0);
431 }
432
EmitDwarfAdvanceLineAddr(int64_t LineDelta,const MCSymbol * LastLabel,const MCSymbol * Label,unsigned PointerSize)433 void MCObjectStreamer::EmitDwarfAdvanceLineAddr(int64_t LineDelta,
434 const MCSymbol *LastLabel,
435 const MCSymbol *Label,
436 unsigned PointerSize) {
437 if (!LastLabel) {
438 emitDwarfSetLineAddr(*this, Assembler->getDWARFLinetableParams(), LineDelta,
439 Label, PointerSize);
440 return;
441 }
442 const MCExpr *AddrDelta = buildSymbolDiff(*this, Label, LastLabel);
443 int64_t Res;
444 if (AddrDelta->evaluateAsAbsolute(Res, getAssemblerPtr())) {
445 MCDwarfLineAddr::Emit(this, Assembler->getDWARFLinetableParams(), LineDelta,
446 Res);
447 return;
448 }
449 insert(new MCDwarfLineAddrFragment(LineDelta, *AddrDelta));
450 }
451
EmitDwarfAdvanceFrameAddr(const MCSymbol * LastLabel,const MCSymbol * Label)452 void MCObjectStreamer::EmitDwarfAdvanceFrameAddr(const MCSymbol *LastLabel,
453 const MCSymbol *Label) {
454 const MCExpr *AddrDelta = buildSymbolDiff(*this, Label, LastLabel);
455 int64_t Res;
456 if (AddrDelta->evaluateAsAbsolute(Res, getAssemblerPtr())) {
457 MCDwarfFrameEmitter::EmitAdvanceLoc(*this, Res);
458 return;
459 }
460 insert(new MCDwarfCallFrameFragment(*AddrDelta));
461 }
462
EmitCVLocDirective(unsigned FunctionId,unsigned FileNo,unsigned Line,unsigned Column,bool PrologueEnd,bool IsStmt,StringRef FileName,SMLoc Loc)463 void MCObjectStreamer::EmitCVLocDirective(unsigned FunctionId, unsigned FileNo,
464 unsigned Line, unsigned Column,
465 bool PrologueEnd, bool IsStmt,
466 StringRef FileName, SMLoc Loc) {
467 // Validate the directive.
468 if (!checkCVLocSection(FunctionId, FileNo, Loc))
469 return;
470
471 // Emit a label at the current position and record it in the CodeViewContext.
472 MCSymbol *LineSym = getContext().createTempSymbol();
473 EmitLabel(LineSym);
474 getContext().getCVContext().recordCVLoc(getContext(), LineSym, FunctionId,
475 FileNo, Line, Column, PrologueEnd,
476 IsStmt);
477 }
478
EmitCVLinetableDirective(unsigned FunctionId,const MCSymbol * Begin,const MCSymbol * End)479 void MCObjectStreamer::EmitCVLinetableDirective(unsigned FunctionId,
480 const MCSymbol *Begin,
481 const MCSymbol *End) {
482 getContext().getCVContext().emitLineTableForFunction(*this, FunctionId, Begin,
483 End);
484 this->MCStreamer::EmitCVLinetableDirective(FunctionId, Begin, End);
485 }
486
EmitCVInlineLinetableDirective(unsigned PrimaryFunctionId,unsigned SourceFileId,unsigned SourceLineNum,const MCSymbol * FnStartSym,const MCSymbol * FnEndSym)487 void MCObjectStreamer::EmitCVInlineLinetableDirective(
488 unsigned PrimaryFunctionId, unsigned SourceFileId, unsigned SourceLineNum,
489 const MCSymbol *FnStartSym, const MCSymbol *FnEndSym) {
490 getContext().getCVContext().emitInlineLineTableForFunction(
491 *this, PrimaryFunctionId, SourceFileId, SourceLineNum, FnStartSym,
492 FnEndSym);
493 this->MCStreamer::EmitCVInlineLinetableDirective(
494 PrimaryFunctionId, SourceFileId, SourceLineNum, FnStartSym, FnEndSym);
495 }
496
EmitCVDefRangeDirective(ArrayRef<std::pair<const MCSymbol *,const MCSymbol * >> Ranges,StringRef FixedSizePortion)497 void MCObjectStreamer::EmitCVDefRangeDirective(
498 ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
499 StringRef FixedSizePortion) {
500 MCFragment *Frag =
501 getContext().getCVContext().emitDefRange(*this, Ranges, FixedSizePortion);
502 // Attach labels that were pending before we created the defrange fragment to
503 // the beginning of the new fragment.
504 flushPendingLabels(Frag, 0);
505 this->MCStreamer::EmitCVDefRangeDirective(Ranges, FixedSizePortion);
506 }
507
EmitCVStringTableDirective()508 void MCObjectStreamer::EmitCVStringTableDirective() {
509 getContext().getCVContext().emitStringTable(*this);
510 }
EmitCVFileChecksumsDirective()511 void MCObjectStreamer::EmitCVFileChecksumsDirective() {
512 getContext().getCVContext().emitFileChecksums(*this);
513 }
514
EmitCVFileChecksumOffsetDirective(unsigned FileNo)515 void MCObjectStreamer::EmitCVFileChecksumOffsetDirective(unsigned FileNo) {
516 getContext().getCVContext().emitFileChecksumOffset(*this, FileNo);
517 }
518
EmitBytes(StringRef Data)519 void MCObjectStreamer::EmitBytes(StringRef Data) {
520 MCDwarfLineEntry::Make(this, getCurrentSectionOnly());
521 MCDataFragment *DF = getOrCreateDataFragment();
522 flushPendingLabels(DF, DF->getContents().size());
523 DF->getContents().append(Data.begin(), Data.end());
524
525 // EmitBytes might not cover all possible ways we emit data (or could be used
526 // to emit executable code in some cases), but is the best method we have
527 // right now for checking this.
528 MCSection *Sec = getCurrentSectionOnly();
529 Sec->setHasData(true);
530 }
531
EmitValueToAlignment(unsigned ByteAlignment,int64_t Value,unsigned ValueSize,unsigned MaxBytesToEmit)532 void MCObjectStreamer::EmitValueToAlignment(unsigned ByteAlignment,
533 int64_t Value,
534 unsigned ValueSize,
535 unsigned MaxBytesToEmit) {
536 if (MaxBytesToEmit == 0)
537 MaxBytesToEmit = ByteAlignment;
538 insert(new MCAlignFragment(ByteAlignment, Value, ValueSize, MaxBytesToEmit));
539
540 // Update the maximum alignment on the current section if necessary.
541 MCSection *CurSec = getCurrentSectionOnly();
542 if (ByteAlignment > CurSec->getAlignment())
543 CurSec->setAlignment(ByteAlignment);
544 }
545
EmitCodeAlignment(unsigned ByteAlignment,unsigned MaxBytesToEmit)546 void MCObjectStreamer::EmitCodeAlignment(unsigned ByteAlignment,
547 unsigned MaxBytesToEmit) {
548 EmitValueToAlignment(ByteAlignment, 0, 1, MaxBytesToEmit);
549 cast<MCAlignFragment>(getCurrentFragment())->setEmitNops(true);
550 }
551
emitValueToOffset(const MCExpr * Offset,unsigned char Value,SMLoc Loc)552 void MCObjectStreamer::emitValueToOffset(const MCExpr *Offset,
553 unsigned char Value,
554 SMLoc Loc) {
555 insert(new MCOrgFragment(*Offset, Value, Loc));
556 }
557
EmitCodePaddingBasicBlockStart(const MCCodePaddingContext & Context)558 void MCObjectStreamer::EmitCodePaddingBasicBlockStart(
559 const MCCodePaddingContext &Context) {
560 getAssembler().getBackend().handleCodePaddingBasicBlockStart(this, Context);
561 }
562
EmitCodePaddingBasicBlockEnd(const MCCodePaddingContext & Context)563 void MCObjectStreamer::EmitCodePaddingBasicBlockEnd(
564 const MCCodePaddingContext &Context) {
565 getAssembler().getBackend().handleCodePaddingBasicBlockEnd(Context);
566 }
567
568 // Associate DTPRel32 fixup with data and resize data area
EmitDTPRel32Value(const MCExpr * Value)569 void MCObjectStreamer::EmitDTPRel32Value(const MCExpr *Value) {
570 MCDataFragment *DF = getOrCreateDataFragment();
571 flushPendingLabels(DF, DF->getContents().size());
572
573 DF->getFixups().push_back(MCFixup::create(DF->getContents().size(),
574 Value, FK_DTPRel_4));
575 DF->getContents().resize(DF->getContents().size() + 4, 0);
576 }
577
578 // Associate DTPRel64 fixup with data and resize data area
EmitDTPRel64Value(const MCExpr * Value)579 void MCObjectStreamer::EmitDTPRel64Value(const MCExpr *Value) {
580 MCDataFragment *DF = getOrCreateDataFragment();
581 flushPendingLabels(DF, DF->getContents().size());
582
583 DF->getFixups().push_back(MCFixup::create(DF->getContents().size(),
584 Value, FK_DTPRel_8));
585 DF->getContents().resize(DF->getContents().size() + 8, 0);
586 }
587
588 // Associate TPRel32 fixup with data and resize data area
EmitTPRel32Value(const MCExpr * Value)589 void MCObjectStreamer::EmitTPRel32Value(const MCExpr *Value) {
590 MCDataFragment *DF = getOrCreateDataFragment();
591 flushPendingLabels(DF, DF->getContents().size());
592
593 DF->getFixups().push_back(MCFixup::create(DF->getContents().size(),
594 Value, FK_TPRel_4));
595 DF->getContents().resize(DF->getContents().size() + 4, 0);
596 }
597
598 // Associate TPRel64 fixup with data and resize data area
EmitTPRel64Value(const MCExpr * Value)599 void MCObjectStreamer::EmitTPRel64Value(const MCExpr *Value) {
600 MCDataFragment *DF = getOrCreateDataFragment();
601 flushPendingLabels(DF, DF->getContents().size());
602
603 DF->getFixups().push_back(MCFixup::create(DF->getContents().size(),
604 Value, FK_TPRel_8));
605 DF->getContents().resize(DF->getContents().size() + 8, 0);
606 }
607
608 // Associate GPRel32 fixup with data and resize data area
EmitGPRel32Value(const MCExpr * Value)609 void MCObjectStreamer::EmitGPRel32Value(const MCExpr *Value) {
610 MCDataFragment *DF = getOrCreateDataFragment();
611 flushPendingLabels(DF, DF->getContents().size());
612
613 DF->getFixups().push_back(
614 MCFixup::create(DF->getContents().size(), Value, FK_GPRel_4));
615 DF->getContents().resize(DF->getContents().size() + 4, 0);
616 }
617
618 // Associate GPRel64 fixup with data and resize data area
EmitGPRel64Value(const MCExpr * Value)619 void MCObjectStreamer::EmitGPRel64Value(const MCExpr *Value) {
620 MCDataFragment *DF = getOrCreateDataFragment();
621 flushPendingLabels(DF, DF->getContents().size());
622
623 DF->getFixups().push_back(
624 MCFixup::create(DF->getContents().size(), Value, FK_GPRel_4));
625 DF->getContents().resize(DF->getContents().size() + 8, 0);
626 }
627
EmitRelocDirective(const MCExpr & Offset,StringRef Name,const MCExpr * Expr,SMLoc Loc,const MCSubtargetInfo & STI)628 bool MCObjectStreamer::EmitRelocDirective(const MCExpr &Offset, StringRef Name,
629 const MCExpr *Expr, SMLoc Loc,
630 const MCSubtargetInfo &STI) {
631 Optional<MCFixupKind> MaybeKind = Assembler->getBackend().getFixupKind(Name);
632 if (!MaybeKind.hasValue())
633 return true;
634
635 MCFixupKind Kind = *MaybeKind;
636
637 if (Expr == nullptr)
638 Expr =
639 MCSymbolRefExpr::create(getContext().createTempSymbol(), getContext());
640
641 MCDataFragment *DF = getOrCreateDataFragment(&STI);
642 flushPendingLabels(DF, DF->getContents().size());
643
644 int64_t OffsetValue;
645 if (Offset.evaluateAsAbsolute(OffsetValue)) {
646 if (OffsetValue < 0)
647 llvm_unreachable(".reloc offset is negative");
648 DF->getFixups().push_back(MCFixup::create(OffsetValue, Expr, Kind, Loc));
649 return false;
650 }
651
652 if (Offset.getKind() != llvm::MCExpr::SymbolRef)
653 llvm_unreachable(".reloc offset is not absolute nor a label");
654
655 const MCSymbolRefExpr &SRE = cast<MCSymbolRefExpr>(Offset);
656 if (SRE.getSymbol().isDefined()) {
657 DF->getFixups().push_back(MCFixup::create(SRE.getSymbol().getOffset(),
658 Expr, Kind, Loc));
659 return false;
660 }
661
662 PendingFixups.emplace_back(&SRE.getSymbol(), DF,
663 MCFixup::create(-1, Expr, Kind, Loc));
664 return false;
665 }
666
emitFill(const MCExpr & NumBytes,uint64_t FillValue,SMLoc Loc)667 void MCObjectStreamer::emitFill(const MCExpr &NumBytes, uint64_t FillValue,
668 SMLoc Loc) {
669 MCDataFragment *DF = getOrCreateDataFragment();
670 flushPendingLabels(DF, DF->getContents().size());
671
672 assert(getCurrentSectionOnly() && "need a section");
673 insert(new MCFillFragment(FillValue, 1, NumBytes, Loc));
674 }
675
emitFill(const MCExpr & NumValues,int64_t Size,int64_t Expr,SMLoc Loc)676 void MCObjectStreamer::emitFill(const MCExpr &NumValues, int64_t Size,
677 int64_t Expr, SMLoc Loc) {
678 int64_t IntNumValues;
679 // Do additional checking now if we can resolve the value.
680 if (NumValues.evaluateAsAbsolute(IntNumValues, getAssemblerPtr())) {
681 if (IntNumValues < 0) {
682 getContext().getSourceManager()->PrintMessage(
683 Loc, SourceMgr::DK_Warning,
684 "'.fill' directive with negative repeat count has no effect");
685 return;
686 }
687 // Emit now if we can for better errors.
688 int64_t NonZeroSize = Size > 4 ? 4 : Size;
689 Expr &= ~0ULL >> (64 - NonZeroSize * 8);
690 for (uint64_t i = 0, e = IntNumValues; i != e; ++i) {
691 EmitIntValue(Expr, NonZeroSize);
692 if (NonZeroSize < Size)
693 EmitIntValue(0, Size - NonZeroSize);
694 }
695 return;
696 }
697
698 // Otherwise emit as fragment.
699 MCDataFragment *DF = getOrCreateDataFragment();
700 flushPendingLabels(DF, DF->getContents().size());
701
702 assert(getCurrentSectionOnly() && "need a section");
703 insert(new MCFillFragment(Expr, Size, NumValues, Loc));
704 }
705
EmitFileDirective(StringRef Filename)706 void MCObjectStreamer::EmitFileDirective(StringRef Filename) {
707 getAssembler().addFileName(Filename);
708 }
709
EmitAddrsig()710 void MCObjectStreamer::EmitAddrsig() {
711 getAssembler().getWriter().emitAddrsigSection();
712 }
713
EmitAddrsigSym(const MCSymbol * Sym)714 void MCObjectStreamer::EmitAddrsigSym(const MCSymbol *Sym) {
715 getAssembler().registerSymbol(*Sym);
716 getAssembler().getWriter().addAddrsigSymbol(Sym);
717 }
718
FinishImpl()719 void MCObjectStreamer::FinishImpl() {
720 getContext().RemapDebugPaths();
721
722 // If we are generating dwarf for assembly source files dump out the sections.
723 if (getContext().getGenDwarfForAssembly())
724 MCGenDwarfInfo::Emit(this);
725
726 // Dump out the dwarf file & directory tables and line tables.
727 MCDwarfLineTable::Emit(this, getAssembler().getDWARFLinetableParams());
728
729 flushPendingLabels();
730 resolvePendingFixups();
731 getAssembler().Finish();
732 }
733