1//===- lib/MC/MCObjectStreamer.cpp - Object File MCStreamer Interface -----===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "llvm/MC/MCObjectStreamer.h"
10#include "llvm/MC/MCAsmBackend.h"
11#include "llvm/MC/MCAsmInfo.h"
12#include "llvm/MC/MCAssembler.h"
13#include "llvm/MC/MCCodeEmitter.h"
14#include "llvm/MC/MCCodeView.h"
15#include "llvm/MC/MCContext.h"
16#include "llvm/MC/MCDwarf.h"
17#include "llvm/MC/MCExpr.h"
18#include "llvm/MC/MCLFIRewriter.h"
19#include "llvm/MC/MCObjectFileInfo.h"
20#include "llvm/MC/MCObjectWriter.h"
21#include "llvm/MC/MCSFrame.h"
22#include "llvm/MC/MCSection.h"
23#include "llvm/MC/MCSymbol.h"
24#include "llvm/Support/ErrorHandling.h"
25#include "llvm/Support/SourceMgr.h"
26using namespace llvm;
27
28MCObjectStreamer::MCObjectStreamer(MCContext &Context,
29 std::unique_ptr<MCAsmBackend> TAB,
30 std::unique_ptr<MCObjectWriter> OW,
31 std::unique_ptr<MCCodeEmitter> Emitter)
32 : MCStreamer(Context),
33 Assembler(std::make_unique<MCAssembler>(
34 args&: Context, args: std::move(TAB), args: std::move(Emitter), args: std::move(OW))),
35 EmitEHFrame(true), EmitDebugFrame(false), EmitSFrame(false) {
36 assert(Assembler->getBackendPtr() && Assembler->getEmitterPtr());
37 IsObj = true;
38 setAllowAutoPadding(Assembler->getBackend().allowAutoPadding());
39 if (Context.getTargetOptions().MCRelaxAll)
40 Assembler->setRelaxAll(true);
41}
42
43MCObjectStreamer::~MCObjectStreamer() = default;
44
45MCAssembler *MCObjectStreamer::getAssemblerPtr() {
46 if (getUseAssemblerInfoForParsing())
47 return Assembler.get();
48 return nullptr;
49}
50
51constexpr size_t FragBlockSize = 16384;
52// Ensure the new fragment can at least store a few bytes.
53constexpr size_t NewFragHeadroom = 8;
54
55static_assert(NewFragHeadroom >= alignof(MCFragment));
56static_assert(FragBlockSize >= sizeof(MCFragment) + NewFragHeadroom);
57
58MCFragment *MCObjectStreamer::allocFragSpace(size_t Headroom) {
59 auto Size = std::max(a: FragBlockSize, b: sizeof(MCFragment) + Headroom);
60 FragSpace = Size - sizeof(MCFragment);
61 auto Block = std::unique_ptr<uint8_t[]>(new uint8_t[Size]);
62 auto *F = reinterpret_cast<MCFragment *>(Block.get());
63 FragStorage.push_back(Elt: std::move(Block));
64 return F;
65}
66
67void MCObjectStreamer::newFragment() {
68 MCFragment *F;
69 if (LLVM_LIKELY(sizeof(MCFragment) + NewFragHeadroom <= FragSpace)) {
70 auto End = reinterpret_cast<size_t>(getCurFragEnd());
71 F = reinterpret_cast<MCFragment *>(
72 alignToPowerOf2(Value: End, Align: alignof(MCFragment)));
73 FragSpace -= size_t(F) - End + sizeof(MCFragment);
74 } else {
75 F = allocFragSpace(Headroom: 0);
76 }
77 new (F) MCFragment();
78 addFragment(F);
79}
80
81void MCObjectStreamer::ensureHeadroom(size_t Headroom) {
82 if (Headroom <= FragSpace)
83 return;
84 auto *F = allocFragSpace(Headroom);
85 new (F) MCFragment();
86 addFragment(F);
87}
88
89void MCObjectStreamer::addSpecialFragment(MCFragment *Frag) {
90 assert(Frag->getKind() != MCFragment::FT_Data &&
91 "Frag should have a variable-size tail");
92 // Frag is not connected to FragSpace. Before modifying CurFrag with
93 // addFragment(Frag), allocate an empty fragment to maintain FragSpace
94 // connectivity, potentially reusing CurFrag's associated space.
95 MCFragment *F;
96 if (LLVM_LIKELY(sizeof(MCFragment) + NewFragHeadroom <= FragSpace)) {
97 auto End = reinterpret_cast<size_t>(getCurFragEnd());
98 F = reinterpret_cast<MCFragment *>(
99 alignToPowerOf2(Value: End, Align: alignof(MCFragment)));
100 FragSpace -= size_t(F) - End + sizeof(MCFragment);
101 } else {
102 F = allocFragSpace(Headroom: 0);
103 }
104 new (F) MCFragment();
105
106 addFragment(F: Frag);
107 addFragment(F);
108}
109
110void MCObjectStreamer::appendContents(ArrayRef<char> Contents) {
111 ensureHeadroom(Headroom: Contents.size());
112 assert(FragSpace >= Contents.size());
113 // As this is performance-sensitive code, explicitly use std::memcpy.
114 // Optimization of std::copy to memmove is unreliable.
115 if (!Contents.empty())
116 std::memcpy(dest: getCurFragEnd(), src: Contents.begin(), n: Contents.size());
117 CurFrag->FixedSize += Contents.size();
118 FragSpace -= Contents.size();
119}
120
121void MCObjectStreamer::appendContents(size_t Num, uint8_t Elt) {
122 ensureHeadroom(Headroom: Num);
123 MutableArrayRef<uint8_t> Data(getCurFragEnd(), Num);
124 llvm::fill(Range&: Data, Value&: Elt);
125 CurFrag->FixedSize += Num;
126 FragSpace -= Num;
127}
128
129void MCObjectStreamer::addFixup(const MCExpr *Value, MCFixupKind Kind) {
130 CurFrag->addFixup(Fixup: MCFixup::create(Offset: getCurFragSize(), Value, Kind));
131}
132
133// As a compile-time optimization, avoid allocating and evaluating an MCExpr
134// tree for (Hi - Lo) when Hi and Lo are offsets into the same fragment's fixed
135// part.
136static std::optional<uint64_t> absoluteSymbolDiff(const MCSymbol *Hi,
137 const MCSymbol *Lo) {
138 assert(Hi && Lo);
139 if (Lo == Hi)
140 return 0;
141 if (Hi->isVariable() || Lo->isVariable())
142 return std::nullopt;
143 auto *LoF = Lo->getFragment();
144 if (!LoF || Hi->getFragment() != LoF || LoF->isLinkerRelaxable())
145 return std::nullopt;
146 // If either symbol resides in the variable part, bail out.
147 auto Fixed = LoF->getFixedSize();
148 if (Lo->getOffset() > Fixed || Hi->getOffset() > Fixed)
149 return std::nullopt;
150
151 return Hi->getOffset() - Lo->getOffset();
152}
153
154void MCObjectStreamer::emitAbsoluteSymbolDiff(const MCSymbol *Hi,
155 const MCSymbol *Lo,
156 unsigned Size) {
157 if (std::optional<uint64_t> Diff = absoluteSymbolDiff(Hi, Lo))
158 emitIntValue(Value: *Diff, Size);
159 else
160 MCStreamer::emitAbsoluteSymbolDiff(Hi, Lo, Size);
161}
162
163void MCObjectStreamer::emitAbsoluteSymbolDiffAsULEB128(const MCSymbol *Hi,
164 const MCSymbol *Lo) {
165 if (std::optional<uint64_t> Diff = absoluteSymbolDiff(Hi, Lo))
166 emitULEB128IntValue(Value: *Diff);
167 else
168 MCStreamer::emitAbsoluteSymbolDiffAsULEB128(Hi, Lo);
169}
170
171void MCObjectStreamer::reset() {
172 if (Assembler) {
173 Assembler->reset();
174 Assembler->setRelaxAll(getContext().getTargetOptions().MCRelaxAll);
175 }
176 EmitEHFrame = true;
177 EmitDebugFrame = false;
178 BundleLocked = false;
179 FragStorage.clear();
180 FragSpace = 0;
181 SpecialFragAllocator.Reset();
182 MCStreamer::reset();
183}
184
185void MCObjectStreamer::generateCompactUnwindEncodings() {
186 auto &Backend = getAssembler().getBackend();
187 for (auto &FI : DwarfFrameInfos)
188 FI.CompactUnwindEncoding =
189 Backend.generateCompactUnwindEncoding(FI: &FI, Ctxt: &getContext());
190}
191
192void MCObjectStreamer::emitFrames() {
193 if (!getNumFrameInfos())
194 return;
195
196 if (EmitEHFrame)
197 MCDwarfFrameEmitter::emit(streamer&: *this, isEH: true);
198 if (EmitDebugFrame)
199 MCDwarfFrameEmitter::emit(streamer&: *this, isEH: false);
200
201 if (EmitSFrame || getContext().getTargetOptions().EmitSFrameUnwind)
202 MCSFrameEmitter::emit(Streamer&: *this);
203}
204
205void MCObjectStreamer::visitUsedSymbol(const MCSymbol &Sym) {
206 Assembler->registerSymbol(Symbol: Sym);
207}
208
209void MCObjectStreamer::emitCFISections(bool EH, bool Debug, bool SFrame) {
210 MCStreamer::emitCFISections(EH, Debug, SFrame);
211 EmitEHFrame = EH;
212 EmitDebugFrame = Debug;
213 EmitSFrame = SFrame;
214}
215
216void MCObjectStreamer::emitValueImpl(const MCExpr *Value, unsigned Size,
217 SMLoc Loc) {
218 MCStreamer::emitValueImpl(Value, Size, Loc);
219
220 MCDwarfLineEntry::make(MCOS: this, Section: getCurrentSectionOnly());
221
222 // Avoid fixups when possible.
223 int64_t AbsValue;
224 if (Value->evaluateAsAbsolute(Res&: AbsValue, Asm: getAssemblerPtr())) {
225 if (!isUIntN(N: 8 * Size, x: AbsValue) && !isIntN(N: 8 * Size, x: AbsValue)) {
226 getContext().reportError(
227 L: Loc, Msg: "value evaluated as " + Twine(AbsValue) + " is out of range.");
228 return;
229 }
230 emitIntValue(Value: AbsValue, Size);
231 return;
232 }
233 ensureHeadroom(Headroom: Size);
234 addFixup(Value, Kind: MCFixup::getDataKindForSize(Size));
235 appendContents(Num: Size, Elt: 0);
236}
237
238MCSymbol *MCObjectStreamer::emitCFILabel() {
239 MCSymbol *Label = getContext().createTempSymbol(Name: "cfi");
240 emitLabel(Symbol: Label);
241 return Label;
242}
243
244void MCObjectStreamer::emitCFIStartProcImpl(MCDwarfFrameInfo &Frame) {
245 // We need to create a local symbol to avoid relocations.
246 Frame.Begin = getContext().createTempSymbol();
247 emitLabel(Symbol: Frame.Begin);
248}
249
250void MCObjectStreamer::emitCFIEndProcImpl(MCDwarfFrameInfo &Frame) {
251 Frame.End = getContext().createTempSymbol();
252 emitLabel(Symbol: Frame.End);
253}
254
255void MCObjectStreamer::emitLabel(MCSymbol *Symbol, SMLoc Loc) {
256 MCStreamer::emitLabel(Symbol, Loc);
257 // If Symbol is a non-redefiniable variable, emitLabel has reported an error.
258 // Bail out.
259 if (Symbol->isVariable())
260 return;
261
262 getAssembler().registerSymbol(Symbol: *Symbol);
263
264 // Set the fragment and offset. This function might be called by
265 // changeSection, when the section stack top hasn't been changed to the new
266 // section.
267 MCFragment *F = CurFrag;
268 Symbol->setFragment(F);
269 Symbol->setOffset(F->getFixedSize());
270
271 emitPendingAssignments(Symbol);
272}
273
274void MCObjectStreamer::emitPendingAssignments(MCSymbol *Symbol) {
275 auto Assignments = pendingAssignments.find(Val: Symbol);
276 if (Assignments == pendingAssignments.end())
277 return;
278
279 // emitAssignment can recursively re-enter emitPendingAssignments for
280 // other symbols, so move the list out and erase before iterating.
281 SmallVector<PendingAssignment, 1> Pending = std::move(Assignments->second);
282 pendingAssignments.erase(I: Assignments);
283 for (const PendingAssignment &A : Pending)
284 emitAssignment(Symbol: A.Symbol, Value: A.Value);
285}
286
287// Emit a label at a previously emitted fragment/offset position. This must be
288// within the currently-active section.
289void MCObjectStreamer::emitLabelAtPos(MCSymbol *Symbol, SMLoc Loc,
290 MCFragment &F, uint64_t Offset) {
291 assert(F.getParent() == getCurrentSectionOnly());
292 MCStreamer::emitLabel(Symbol, Loc);
293 getAssembler().registerSymbol(Symbol: *Symbol);
294 Symbol->setFragment(&F);
295 Symbol->setOffset(Offset);
296}
297
298void MCObjectStreamer::emitULEB128Value(const MCExpr *Value) {
299 int64_t IntValue;
300 if (Value->evaluateAsAbsolute(Res&: IntValue, Asm: getAssembler())) {
301 emitULEB128IntValue(Value: IntValue);
302 return;
303 }
304 auto *F = getCurrentFragment();
305 F->makeLEB(IsSigned: false, Value);
306 newFragment();
307}
308
309void MCObjectStreamer::emitSLEB128Value(const MCExpr *Value) {
310 int64_t IntValue;
311 if (Value->evaluateAsAbsolute(Res&: IntValue, Asm: getAssembler())) {
312 emitSLEB128IntValue(Value: IntValue);
313 return;
314 }
315 auto *F = getCurrentFragment();
316 F->makeLEB(IsSigned: true, Value);
317 newFragment();
318}
319
320void MCObjectStreamer::emitWeakReference(MCSymbol *Alias,
321 const MCSymbol *Target) {
322 reportFatalUsageError(reason: "this file format doesn't support weak aliases");
323}
324
325void MCObjectStreamer::changeSection(MCSection *Section, uint32_t Subsection) {
326 assert(Section && "Cannot switch to a null section!");
327 getContext().clearDwarfLocSeen();
328
329 // Register the section and create an initial fragment for subsection 0
330 // if `Subsection` is non-zero.
331 bool NewSec = getAssembler().registerSection(Section&: *Section);
332 MCFragment *F0 = nullptr;
333 if (NewSec && Subsection) {
334 changeSection(Section, Subsection: 0);
335 F0 = CurFrag;
336 }
337
338 // To maintain connectivity between CurFrag and FragSpace when CurFrag is
339 // modified, allocate an empty fragment and append it to the fragment list.
340 // (Subsections[I].second.Tail is not connected to FragSpace.)
341 MCFragment *F;
342 if (LLVM_LIKELY(sizeof(MCFragment) + NewFragHeadroom <= FragSpace)) {
343 auto End = reinterpret_cast<size_t>(getCurFragEnd());
344 F = reinterpret_cast<MCFragment *>(
345 alignToPowerOf2(Value: End, Align: alignof(MCFragment)));
346 FragSpace -= size_t(F) - End + sizeof(MCFragment);
347 } else {
348 F = allocFragSpace(Headroom: 0);
349 }
350 new (F) MCFragment();
351 F->setParent(Section);
352
353 auto &Subsections = Section->Subsections;
354 size_t I = 0, E = Subsections.size();
355 while (I != E && Subsections[I].first < Subsection)
356 ++I;
357 // If the subsection number is not in the sorted Subsections list, create a
358 // new fragment list.
359 if (I == E || Subsections[I].first != Subsection) {
360 Subsections.insert(I: Subsections.begin() + I,
361 Elt: {Subsection, MCSection::FragList{.Head: F, .Tail: F}});
362 Section->CurFragList = &Subsections[I].second;
363 CurFrag = F;
364 } else {
365 Section->CurFragList = &Subsections[I].second;
366 CurFrag = Subsections[I].second.Tail;
367 // Ensure CurFrag is associated with FragSpace.
368 addFragment(F);
369 }
370
371 // Define the section symbol at subsection 0's initial fragment if required.
372 if (!NewSec)
373 return;
374 if (auto *Sym = Section->getBeginSymbol()) {
375 Sym->setFragment(Subsection ? F0 : CurFrag);
376 getAssembler().registerSymbol(Symbol: *Sym);
377 }
378}
379
380void MCObjectStreamer::emitAssignment(MCSymbol *Symbol, const MCExpr *Value) {
381 getAssembler().registerSymbol(Symbol: *Symbol);
382 MCStreamer::emitAssignment(Symbol, Value);
383 emitPendingAssignments(Symbol);
384}
385
386void MCObjectStreamer::emitConditionalAssignment(MCSymbol *Symbol,
387 const MCExpr *Value) {
388 const MCSymbol *Target = &cast<MCSymbolRefExpr>(Val: *Value).getSymbol();
389
390 // If the symbol already exists, emit the assignment. Otherwise, emit it
391 // later only if the symbol is also emitted.
392 if (Target->isRegistered())
393 emitAssignment(Symbol, Value);
394 else
395 pendingAssignments[Target].push_back(Elt: {.Symbol: Symbol, .Value: Value});
396}
397
398bool MCObjectStreamer::mayHaveInstructions(MCSection &Sec) const {
399 return Sec.hasInstructions();
400}
401
402void MCObjectStreamer::emitInstruction(const MCInst &Inst,
403 const MCSubtargetInfo &STI) {
404 if (LFIRewriter && LFIRewriter->rewriteInst(Inst, Out&: *this, STI))
405 return;
406
407 MCStreamer::emitInstruction(Inst, STI);
408
409 MCSection *Sec = getCurrentSectionOnly();
410 Sec->setHasInstructions(true);
411
412 // Now that a machine instruction has been assembled into this section, make
413 // a line entry for any .loc directive that has been seen.
414 MCDwarfLineEntry::make(MCOS: this, Section: getCurrentSectionOnly());
415
416 // If this instruction doesn't need relaxation, just emit it as data.
417 MCAssembler &Assembler = getAssembler();
418 MCAsmBackend &Backend = Assembler.getBackend();
419
420 auto relaxToFixpoint = [&](MCInst I) {
421 while (Backend.mayNeedRelaxation(Opcode: I.getOpcode(), Operands: I.getOperands(), STI))
422 Backend.relaxInstruction(Inst&: I, STI);
423 return I;
424 };
425
426 // Bundling emits one relaxable fragment per instruction so that finishLayout
427 // can fold padding into instruction encodings.
428 if (Assembler.isBundlingEnabled()) {
429 if (BundleLocked || Assembler.getRelaxAll())
430 emitInstToFragment(Inst: relaxToFixpoint(Inst), STI);
431 else
432 emitInstToFragment(Inst, STI);
433 return;
434 }
435
436 if (!(Backend.mayNeedRelaxation(Opcode: Inst.getOpcode(), Operands: Inst.getOperands(), STI) ||
437 Backend.allowEnhancedRelaxation())) {
438 emitInstToData(Inst, STI);
439 return;
440 }
441
442 // Otherwise, relax and emit it as data if RelaxAll is specified.
443 if (Assembler.getRelaxAll()) {
444 emitInstToData(Inst: relaxToFixpoint(Inst), STI);
445 return;
446 }
447
448 emitInstToFragment(Inst, STI);
449}
450
451void MCObjectStreamer::emitInstToData(const MCInst &Inst,
452 const MCSubtargetInfo &STI) {
453 MCFragment *F = getCurrentFragment();
454
455 // Append the instruction to the data fragment.
456 size_t CodeOffset = getCurFragSize();
457 SmallString<16> Content;
458 SmallVector<MCFixup, 1> Fixups;
459 getAssembler().getEmitter().encodeInstruction(Inst, CB&: Content, Fixups, STI);
460 appendContents(Contents: Content);
461 if (CurFrag != F) {
462 F = CurFrag;
463 CodeOffset = 0;
464 }
465 F->setHasInstructions(STI);
466
467 if (Fixups.empty())
468 return;
469 bool MarkedLinkerRelaxable = false;
470 for (auto &Fixup : Fixups) {
471 Fixup.setOffset(Fixup.getOffset() + CodeOffset);
472 if (!Fixup.isLinkerRelaxable() || MarkedLinkerRelaxable)
473 continue;
474 MarkedLinkerRelaxable = true;
475 // Set the fragment's order within the subsection for use by
476 // MCAssembler::relaxAlign.
477 auto *Sec = F->getParent();
478 if (!Sec->isLinkerRelaxable())
479 Sec->setFirstLinkerRelaxable(F->getLayoutOrder());
480 // Do not add data after a linker-relaxable instruction. The difference
481 // between a new label and a label at or before the linker-relaxable
482 // instruction cannot be resolved at assemble-time.
483 F->setLinkerRelaxable();
484 newFragment();
485 }
486 F->appendFixups(Fixups);
487}
488
489void MCObjectStreamer::emitInstToFragment(const MCInst &Inst,
490 const MCSubtargetInfo &STI) {
491 auto *F = getCurrentFragment();
492 SmallVector<char, 16> Data;
493 SmallVector<MCFixup, 1> Fixups;
494 getAssembler().getEmitter().encodeInstruction(Inst, CB&: Data, Fixups, STI);
495
496 F->Kind = MCFragment::FT_Relaxable;
497 F->setHasInstructions(STI);
498
499 F->setVarContents(Data);
500 F->setInst(Inst);
501
502 bool MarkedLinkerRelaxable = false;
503 for (auto &Fixup : Fixups) {
504 if (!Fixup.isLinkerRelaxable() || MarkedLinkerRelaxable)
505 continue;
506 MarkedLinkerRelaxable = true;
507 auto *Sec = F->getParent();
508 if (!Sec->isLinkerRelaxable())
509 Sec->setFirstLinkerRelaxable(F->getLayoutOrder());
510 F->setLinkerRelaxable();
511 }
512 F->setVarFixups(Fixups);
513
514 newFragment();
515}
516
517void MCObjectStreamer::emitDwarfLocDirective(unsigned FileNo, unsigned Line,
518 unsigned Column, unsigned Flags,
519 unsigned Isa,
520 unsigned Discriminator,
521 StringRef FileName,
522 StringRef Comment) {
523 // In case we see two .loc directives in a row, make sure the
524 // first one gets a line entry.
525 MCDwarfLineEntry::make(MCOS: this, Section: getCurrentSectionOnly());
526
527 this->MCStreamer::emitDwarfLocDirective(FileNo, Line, Column, Flags, Isa,
528 Discriminator, FileName, Comment);
529}
530
531static const MCExpr *buildSymbolDiff(MCObjectStreamer &OS, const MCSymbol *A,
532 const MCSymbol *B, SMLoc Loc) {
533 MCContext &Context = OS.getContext();
534 const MCExpr *ARef = MCSymbolRefExpr::create(Symbol: A, Ctx&: Context);
535 const MCExpr *BRef = MCSymbolRefExpr::create(Symbol: B, Ctx&: Context);
536 const MCExpr *AddrDelta =
537 MCBinaryExpr::create(Op: MCBinaryExpr::Sub, LHS: ARef, RHS: BRef, Ctx&: Context, Loc);
538 return AddrDelta;
539}
540
541static void emitDwarfSetLineAddr(MCObjectStreamer &OS,
542 MCDwarfLineTableParams Params,
543 int64_t LineDelta, const MCSymbol *Label,
544 int PointerSize) {
545 // emit the sequence to set the address
546 OS.emitIntValue(Value: dwarf::DW_LNS_extended_op, Size: 1);
547 OS.emitULEB128IntValue(Value: PointerSize + 1);
548 OS.emitIntValue(Value: dwarf::DW_LNE_set_address, Size: 1);
549 OS.emitSymbolValue(Sym: Label, Size: PointerSize);
550
551 // emit the sequence for the LineDelta (from 1) and a zero address delta.
552 MCDwarfLineAddr::Emit(MCOS: &OS, Params, LineDelta, AddrDelta: 0);
553}
554
555void MCObjectStreamer::emitDwarfAdvanceLineAddr(int64_t LineDelta,
556 const MCSymbol *LastLabel,
557 const MCSymbol *Label,
558 unsigned PointerSize) {
559 if (!LastLabel) {
560 emitDwarfSetLineAddr(OS&: *this, Params: Assembler->getDWARFLinetableParams(), LineDelta,
561 Label, PointerSize);
562 return;
563 }
564
565 // If the two labels are within the same fragment, then the address-offset is
566 // already a fixed constant and is not relaxable. Emit the advance-line-addr
567 // data immediately to save time and memory.
568 if (auto OptAddrDelta = absoluteSymbolDiff(Hi: Label, Lo: LastLabel)) {
569 SmallString<16> Tmp;
570 MCDwarfLineAddr::encode(Context&: getContext(), Params: Assembler->getDWARFLinetableParams(),
571 LineDelta, AddrDelta: *OptAddrDelta, OS&: Tmp);
572 emitBytes(Data: Tmp);
573 return;
574 }
575
576 auto *F = getCurrentFragment();
577 F->Kind = MCFragment::FT_Dwarf;
578 F->setDwarfAddrDelta(buildSymbolDiff(OS&: *this, A: Label, B: LastLabel, Loc: SMLoc()));
579 F->setDwarfLineDelta(LineDelta);
580 newFragment();
581}
582
583void MCObjectStreamer::emitDwarfLineEndEntry(MCSection *Section,
584 MCSymbol *LastLabel,
585 MCSymbol *EndLabel) {
586 // Emit a DW_LNE_end_sequence into the line table. When EndLabel is null, it
587 // means we should emit the entry for the end of the section and therefore we
588 // use the section end label for the reference label. After having the
589 // appropriate reference label, we emit the address delta and use INT64_MAX as
590 // the line delta which is the signal that this is actually a
591 // DW_LNE_end_sequence.
592 if (!EndLabel)
593 EndLabel = endSection(Section);
594
595 // Switch back the dwarf line section, in case endSection had to switch the
596 // section.
597 MCContext &Ctx = getContext();
598 switchSection(Section: Ctx.getObjectFileInfo()->getDwarfLineSection());
599
600 const MCAsmInfo &AsmInfo = Ctx.getAsmInfo();
601 emitDwarfAdvanceLineAddr(INT64_MAX, LastLabel, Label: EndLabel,
602 PointerSize: AsmInfo.getCodePointerSize());
603}
604
605void MCObjectStreamer::emitDwarfAdvanceFrameAddr(const MCSymbol *LastLabel,
606 const MCSymbol *Label,
607 SMLoc Loc) {
608 auto *F = getCurrentFragment();
609 F->Kind = MCFragment::FT_DwarfFrame;
610 F->setDwarfAddrDelta(buildSymbolDiff(OS&: *this, A: Label, B: LastLabel, Loc));
611 newFragment();
612}
613
614void MCObjectStreamer::emitSFrameCalculateFuncOffset(const MCSymbol *FuncBase,
615 const MCSymbol *FREBegin,
616 MCFragment *FDEFrag,
617 SMLoc Loc) {
618 assert(FuncBase && "No function base address");
619 assert(FREBegin && "FRE doesn't describe a location");
620 auto *F = getCurrentFragment();
621 F->Kind = MCFragment::FT_SFrame;
622 F->setSFrameAddrDelta(buildSymbolDiff(OS&: *this, A: FREBegin, B: FuncBase, Loc));
623 F->setSFrameFDE(FDEFrag);
624 newFragment();
625}
626
627void MCObjectStreamer::emitCVLocDirective(unsigned FunctionId, unsigned FileNo,
628 unsigned Line, unsigned Column,
629 bool PrologueEnd, bool IsStmt,
630 StringRef FileName, SMLoc Loc) {
631 // Validate the directive.
632 if (!checkCVLocSection(FuncId: FunctionId, Loc))
633 return;
634
635 // Emit a label at the current position and record it in the CodeViewContext.
636 MCSymbol *LineSym = getContext().createTempSymbol();
637 emitLabel(Symbol: LineSym);
638 getContext().getCVContext().recordCVLoc(Ctx&: getContext(), Label: LineSym, FunctionId,
639 FileNo, Line, Column, PrologueEnd,
640 IsStmt);
641}
642
643void MCObjectStreamer::emitCVLinetableDirective(unsigned FunctionId,
644 const MCSymbol *Begin,
645 const MCSymbol *End) {
646 getContext().getCVContext().emitLineTableForFunction(OS&: *this, FuncId: FunctionId, FuncBegin: Begin,
647 FuncEnd: End);
648 this->MCStreamer::emitCVLinetableDirective(FunctionId, FnStart: Begin, FnEnd: End);
649}
650
651void MCObjectStreamer::emitCVInlineLinetableDirective(
652 unsigned PrimaryFunctionId, unsigned SourceFileId, unsigned SourceLineNum,
653 const MCSymbol *FnStartSym, const MCSymbol *FnEndSym) {
654 getContext().getCVContext().emitInlineLineTableForFunction(
655 OS&: *this, PrimaryFunctionId, SourceFileId, SourceLineNum, FnStartSym,
656 FnEndSym);
657 this->MCStreamer::emitCVInlineLinetableDirective(
658 PrimaryFunctionId, SourceFileId, SourceLineNum, FnStartSym, FnEndSym);
659}
660
661void MCObjectStreamer::emitCVDefRangeDirective(
662 ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
663 StringRef FixedSizePortion) {
664 getContext().getCVContext().emitDefRange(OS&: *this, Ranges, FixedSizePortion);
665 // Attach labels that were pending before we created the defrange fragment to
666 // the beginning of the new fragment.
667 this->MCStreamer::emitCVDefRangeDirective(Ranges, FixedSizePortion);
668}
669
670void MCObjectStreamer::emitCVStringTableDirective() {
671 getContext().getCVContext().emitStringTable(OS&: *this);
672}
673void MCObjectStreamer::emitCVFileChecksumsDirective() {
674 getContext().getCVContext().emitFileChecksums(OS&: *this);
675}
676
677void MCObjectStreamer::emitCVFileChecksumOffsetDirective(unsigned FileNo) {
678 getContext().getCVContext().emitFileChecksumOffset(OS&: *this, FileNo);
679}
680
681void MCObjectStreamer::emitBytes(StringRef Data) {
682 MCDwarfLineEntry::make(MCOS: this, Section: getCurrentSectionOnly());
683 appendContents(Contents: ArrayRef(Data.data(), Data.size()));
684}
685
686void MCObjectStreamer::emitValueToAlignment(Align Alignment, int64_t Fill,
687 uint8_t FillLen,
688 unsigned MaxBytesToEmit) {
689 if (MaxBytesToEmit == 0)
690 MaxBytesToEmit = Alignment.value();
691 MCFragment *F = getCurrentFragment();
692 F->makeAlign(Alignment, Fill, FillLen, MaxBytesToEmit);
693 newFragment();
694
695 // Update the maximum alignment on the current section if necessary.
696 F->getParent()->ensureMinAlignment(MinAlignment: Alignment);
697}
698
699void MCObjectStreamer::emitCodeAlignment(Align Alignment,
700 const MCSubtargetInfo &STI,
701 unsigned MaxBytesToEmit) {
702 auto *F = getCurrentFragment();
703 emitValueToAlignment(Alignment, Fill: 0, FillLen: 1, MaxBytesToEmit);
704 F->u.align.EmitNops = true;
705 F->STI = &STI;
706}
707
708void MCObjectStreamer::emitPrefAlign(Align Alignment, const MCSymbol &End,
709 bool EmitNops, uint8_t Fill,
710 const MCSubtargetInfo &STI) {
711 auto *F = getCurrentFragment();
712 F->makePrefAlign(PrefAlign: Alignment, End, EmitNops, Fill);
713 if (EmitNops)
714 F->STI = &STI;
715 newFragment();
716}
717
718void MCObjectStreamer::emitValueToOffset(const MCExpr *Offset,
719 unsigned char Value,
720 SMLoc Loc) {
721 newSpecialFragment<MCOrgFragment>(args: *Offset, args&: Value, args&: Loc);
722}
723
724void MCObjectStreamer::emitRelocDirective(const MCExpr &Offset, StringRef Name,
725 const MCExpr *Expr, SMLoc Loc) {
726 std::optional<MCFixupKind> MaybeKind =
727 Assembler->getBackend().getFixupKind(Name);
728 if (!MaybeKind) {
729 getContext().reportError(L: Loc, Msg: "unknown relocation name");
730 return;
731 }
732
733 MCFixupKind Kind = *MaybeKind;
734 if (Expr)
735 visitUsedExpr(Expr: *Expr);
736 else
737 Expr =
738 MCSymbolRefExpr::create(Symbol: getContext().createTempSymbol(), Ctx&: getContext());
739
740 auto *O = &Offset;
741 int64_t Val;
742 if (Offset.evaluateAsAbsolute(Res&: Val, Asm: nullptr)) {
743 auto *SecSym = getCurrentSectionOnly()->getBeginSymbol();
744 O = MCBinaryExpr::createAdd(LHS: MCSymbolRefExpr::create(Symbol: SecSym, Ctx&: getContext()),
745 RHS: O, Ctx&: getContext(), Loc);
746 }
747 getAssembler().addRelocDirective(RD: {.Offset: *O, .Expr: Expr, .Kind: Kind});
748}
749
750void MCObjectStreamer::emitFill(const MCExpr &NumBytes, uint64_t FillValue,
751 SMLoc Loc) {
752 assert(getCurrentSectionOnly() && "need a section");
753 newSpecialFragment<MCFillFragment>(args&: FillValue, args: 1, args: NumBytes, args&: Loc);
754}
755
756void MCObjectStreamer::emitFill(const MCExpr &NumValues, int64_t Size,
757 int64_t Expr, SMLoc Loc) {
758 int64_t IntNumValues;
759 // Do additional checking now if we can resolve the value.
760 if (NumValues.evaluateAsAbsolute(Res&: IntNumValues, Asm: getAssembler()) &&
761 IntNumValues < 0) {
762 getContext().getSourceManager()->PrintMessage(
763 Loc, Kind: SourceMgr::DK_Warning,
764 Msg: "'.fill' directive with negative repeat count has no effect");
765 return;
766 }
767
768 assert(getCurrentSectionOnly() && "need a section");
769 newSpecialFragment<MCFillFragment>(args&: Expr, args&: Size, args: NumValues, args&: Loc);
770}
771
772void MCObjectStreamer::emitNops(int64_t NumBytes, int64_t ControlledNopLength,
773 SMLoc Loc, const MCSubtargetInfo &STI) {
774 assert(getCurrentSectionOnly() && "need a section");
775 newSpecialFragment<MCNopsFragment>(args&: NumBytes, args&: ControlledNopLength, args&: Loc, args: STI);
776}
777
778void MCObjectStreamer::emitFileDirective(StringRef Filename) {
779 MCAssembler &Asm = getAssembler();
780 Asm.getWriter().addFileName(FileName: Filename);
781}
782
783void MCObjectStreamer::emitFileDirective(StringRef Filename,
784 StringRef CompilerVersion,
785 StringRef TimeStamp,
786 StringRef Description) {
787 MCObjectWriter &W = getAssembler().getWriter();
788 W.addFileName(FileName: Filename);
789 if (CompilerVersion.size())
790 W.setCompilerVersion(CompilerVersion);
791 // TODO: add TimeStamp and Description to .file symbol table entry
792 // with the integrated assembler.
793}
794
795void MCObjectStreamer::emitAddrsig() {
796 getAssembler().getWriter().emitAddrsigSection();
797}
798
799void MCObjectStreamer::emitAddrsigSym(const MCSymbol *Sym) {
800 getAssembler().getWriter().addAddrsigSymbol(Sym);
801}
802
803void MCObjectStreamer::finishImpl() {
804 getContext().RemapDebugPaths();
805
806 // If we are generating dwarf for assembly source files dump out the sections.
807 if (getContext().getGenDwarfForAssembly())
808 MCGenDwarfInfo::Emit(MCOS: this);
809
810 // Dump out the dwarf file & directory tables and line tables.
811 MCDwarfLineTable::emit(MCOS: this, Params: getAssembler().getDWARFLinetableParams());
812
813 // Emit pseudo probes for the current module.
814 MCPseudoProbeTable::emit(MCOS: this);
815
816 getAssembler().Finish();
817}
818