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() && 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 if (getContext().getTargetOptions())
175 Assembler->setRelaxAll(getContext().getTargetOptions()->MCRelaxAll);
176 }
177 EmitEHFrame = true;
178 EmitDebugFrame = 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() &&
202 getContext().getTargetOptions()->EmitSFrameUnwind))
203 MCSFrameEmitter::emit(Streamer&: *this);
204}
205
206void MCObjectStreamer::visitUsedSymbol(const MCSymbol &Sym) {
207 Assembler->registerSymbol(Symbol: Sym);
208}
209
210void MCObjectStreamer::emitCFISections(bool EH, bool Debug, bool SFrame) {
211 MCStreamer::emitCFISections(EH, Debug, SFrame);
212 EmitEHFrame = EH;
213 EmitDebugFrame = Debug;
214 EmitSFrame = SFrame;
215}
216
217void MCObjectStreamer::emitValueImpl(const MCExpr *Value, unsigned Size,
218 SMLoc Loc) {
219 MCStreamer::emitValueImpl(Value, Size, Loc);
220
221 MCDwarfLineEntry::make(MCOS: this, Section: getCurrentSectionOnly());
222
223 // Avoid fixups when possible.
224 int64_t AbsValue;
225 if (Value->evaluateAsAbsolute(Res&: AbsValue, Asm: getAssemblerPtr())) {
226 if (!isUIntN(N: 8 * Size, x: AbsValue) && !isIntN(N: 8 * Size, x: AbsValue)) {
227 getContext().reportError(
228 L: Loc, Msg: "value evaluated as " + Twine(AbsValue) + " is out of range.");
229 return;
230 }
231 emitIntValue(Value: AbsValue, Size);
232 return;
233 }
234 ensureHeadroom(Headroom: Size);
235 addFixup(Value, Kind: MCFixup::getDataKindForSize(Size));
236 appendContents(Num: Size, Elt: 0);
237}
238
239MCSymbol *MCObjectStreamer::emitCFILabel() {
240 MCSymbol *Label = getContext().createTempSymbol(Name: "cfi");
241 emitLabel(Symbol: Label);
242 return Label;
243}
244
245void MCObjectStreamer::emitCFIStartProcImpl(MCDwarfFrameInfo &Frame) {
246 // We need to create a local symbol to avoid relocations.
247 Frame.Begin = getContext().createTempSymbol();
248 emitLabel(Symbol: Frame.Begin);
249}
250
251void MCObjectStreamer::emitCFIEndProcImpl(MCDwarfFrameInfo &Frame) {
252 Frame.End = getContext().createTempSymbol();
253 emitLabel(Symbol: Frame.End);
254}
255
256void MCObjectStreamer::emitLabel(MCSymbol *Symbol, SMLoc Loc) {
257 MCStreamer::emitLabel(Symbol, Loc);
258 // If Symbol is a non-redefiniable variable, emitLabel has reported an error.
259 // Bail out.
260 if (Symbol->isVariable())
261 return;
262
263 getAssembler().registerSymbol(Symbol: *Symbol);
264
265 // Set the fragment and offset. This function might be called by
266 // changeSection, when the section stack top hasn't been changed to the new
267 // section.
268 MCFragment *F = CurFrag;
269 Symbol->setFragment(F);
270 Symbol->setOffset(F->getFixedSize());
271
272 emitPendingAssignments(Symbol);
273}
274
275void MCObjectStreamer::emitPendingAssignments(MCSymbol *Symbol) {
276 auto Assignments = pendingAssignments.find(Val: Symbol);
277 if (Assignments != pendingAssignments.end()) {
278 for (const PendingAssignment &A : Assignments->second)
279 emitAssignment(Symbol: A.Symbol, Value: A.Value);
280
281 pendingAssignments.erase(I: Assignments);
282 }
283}
284
285// Emit a label at a previously emitted fragment/offset position. This must be
286// within the currently-active section.
287void MCObjectStreamer::emitLabelAtPos(MCSymbol *Symbol, SMLoc Loc,
288 MCFragment &F, uint64_t Offset) {
289 assert(F.getParent() == getCurrentSectionOnly());
290 MCStreamer::emitLabel(Symbol, Loc);
291 getAssembler().registerSymbol(Symbol: *Symbol);
292 Symbol->setFragment(&F);
293 Symbol->setOffset(Offset);
294}
295
296void MCObjectStreamer::emitULEB128Value(const MCExpr *Value) {
297 int64_t IntValue;
298 if (Value->evaluateAsAbsolute(Res&: IntValue, Asm: getAssembler())) {
299 emitULEB128IntValue(Value: IntValue);
300 return;
301 }
302 auto *F = getCurrentFragment();
303 F->makeLEB(IsSigned: false, Value);
304 newFragment();
305}
306
307void MCObjectStreamer::emitSLEB128Value(const MCExpr *Value) {
308 int64_t IntValue;
309 if (Value->evaluateAsAbsolute(Res&: IntValue, Asm: getAssembler())) {
310 emitSLEB128IntValue(Value: IntValue);
311 return;
312 }
313 auto *F = getCurrentFragment();
314 F->makeLEB(IsSigned: true, Value);
315 newFragment();
316}
317
318void MCObjectStreamer::emitWeakReference(MCSymbol *Alias,
319 const MCSymbol *Target) {
320 reportFatalUsageError(reason: "this file format doesn't support weak aliases");
321}
322
323void MCObjectStreamer::changeSection(MCSection *Section, uint32_t Subsection) {
324 assert(Section && "Cannot switch to a null section!");
325 getContext().clearDwarfLocSeen();
326
327 // Register the section and create an initial fragment for subsection 0
328 // if `Subsection` is non-zero.
329 bool NewSec = getAssembler().registerSection(Section&: *Section);
330 MCFragment *F0 = nullptr;
331 if (NewSec && Subsection) {
332 changeSection(Section, Subsection: 0);
333 F0 = CurFrag;
334 }
335
336 // To maintain connectivity between CurFrag and FragSpace when CurFrag is
337 // modified, allocate an empty fragment and append it to the fragment list.
338 // (Subsections[I].second.Tail is not connected to FragSpace.)
339 MCFragment *F;
340 if (LLVM_LIKELY(sizeof(MCFragment) + NewFragHeadroom <= FragSpace)) {
341 auto End = reinterpret_cast<size_t>(getCurFragEnd());
342 F = reinterpret_cast<MCFragment *>(
343 alignToPowerOf2(Value: End, Align: alignof(MCFragment)));
344 FragSpace -= size_t(F) - End + sizeof(MCFragment);
345 } else {
346 F = allocFragSpace(Headroom: 0);
347 }
348 new (F) MCFragment();
349 F->setParent(Section);
350
351 auto &Subsections = Section->Subsections;
352 size_t I = 0, E = Subsections.size();
353 while (I != E && Subsections[I].first < Subsection)
354 ++I;
355 // If the subsection number is not in the sorted Subsections list, create a
356 // new fragment list.
357 if (I == E || Subsections[I].first != Subsection) {
358 Subsections.insert(I: Subsections.begin() + I,
359 Elt: {Subsection, MCSection::FragList{.Head: F, .Tail: F}});
360 Section->CurFragList = &Subsections[I].second;
361 CurFrag = F;
362 } else {
363 Section->CurFragList = &Subsections[I].second;
364 CurFrag = Subsections[I].second.Tail;
365 // Ensure CurFrag is associated with FragSpace.
366 addFragment(F);
367 }
368
369 // Define the section symbol at subsection 0's initial fragment if required.
370 if (!NewSec)
371 return;
372 if (auto *Sym = Section->getBeginSymbol()) {
373 Sym->setFragment(Subsection ? F0 : CurFrag);
374 getAssembler().registerSymbol(Symbol: *Sym);
375 }
376}
377
378void MCObjectStreamer::emitAssignment(MCSymbol *Symbol, const MCExpr *Value) {
379 getAssembler().registerSymbol(Symbol: *Symbol);
380 MCStreamer::emitAssignment(Symbol, Value);
381 emitPendingAssignments(Symbol);
382}
383
384void MCObjectStreamer::emitConditionalAssignment(MCSymbol *Symbol,
385 const MCExpr *Value) {
386 const MCSymbol *Target = &cast<MCSymbolRefExpr>(Val: *Value).getSymbol();
387
388 // If the symbol already exists, emit the assignment. Otherwise, emit it
389 // later only if the symbol is also emitted.
390 if (Target->isRegistered())
391 emitAssignment(Symbol, Value);
392 else
393 pendingAssignments[Target].push_back(Elt: {.Symbol: Symbol, .Value: Value});
394}
395
396bool MCObjectStreamer::mayHaveInstructions(MCSection &Sec) const {
397 return Sec.hasInstructions();
398}
399
400void MCObjectStreamer::emitInstruction(const MCInst &Inst,
401 const MCSubtargetInfo &STI) {
402 if (LFIRewriter && LFIRewriter->rewriteInst(Inst, Out&: *this, STI))
403 return;
404
405 MCStreamer::emitInstruction(Inst, STI);
406
407 MCSection *Sec = getCurrentSectionOnly();
408 Sec->setHasInstructions(true);
409
410 // Now that a machine instruction has been assembled into this section, make
411 // a line entry for any .loc directive that has been seen.
412 MCDwarfLineEntry::make(MCOS: this, Section: getCurrentSectionOnly());
413
414 // If this instruction doesn't need relaxation, just emit it as data.
415 MCAssembler &Assembler = getAssembler();
416 MCAsmBackend &Backend = Assembler.getBackend();
417 if (!(Backend.mayNeedRelaxation(Opcode: Inst.getOpcode(), Operands: Inst.getOperands(), STI) ||
418 Backend.allowEnhancedRelaxation())) {
419 emitInstToData(Inst, STI);
420 return;
421 }
422
423 // Otherwise, relax and emit it as data if RelaxAll is specified.
424 if (Assembler.getRelaxAll()) {
425 MCInst Relaxed = Inst;
426 while (Backend.mayNeedRelaxation(Opcode: Relaxed.getOpcode(), Operands: Relaxed.getOperands(),
427 STI))
428 Backend.relaxInstruction(Inst&: Relaxed, STI);
429 emitInstToData(Inst: Relaxed, STI);
430 return;
431 }
432
433 emitInstToFragment(Inst, STI);
434}
435
436void MCObjectStreamer::emitInstToData(const MCInst &Inst,
437 const MCSubtargetInfo &STI) {
438 MCFragment *F = getCurrentFragment();
439
440 // Append the instruction to the data fragment.
441 size_t CodeOffset = getCurFragSize();
442 SmallString<16> Content;
443 SmallVector<MCFixup, 1> Fixups;
444 getAssembler().getEmitter().encodeInstruction(Inst, CB&: Content, Fixups, STI);
445 appendContents(Contents: Content);
446 if (CurFrag != F) {
447 F = CurFrag;
448 CodeOffset = 0;
449 }
450 F->setHasInstructions(STI);
451
452 if (Fixups.empty())
453 return;
454 bool MarkedLinkerRelaxable = false;
455 for (auto &Fixup : Fixups) {
456 Fixup.setOffset(Fixup.getOffset() + CodeOffset);
457 if (!Fixup.isLinkerRelaxable() || MarkedLinkerRelaxable)
458 continue;
459 MarkedLinkerRelaxable = true;
460 // Set the fragment's order within the subsection for use by
461 // MCAssembler::relaxAlign.
462 auto *Sec = F->getParent();
463 if (!Sec->isLinkerRelaxable())
464 Sec->setFirstLinkerRelaxable(F->getLayoutOrder());
465 // Do not add data after a linker-relaxable instruction. The difference
466 // between a new label and a label at or before the linker-relaxable
467 // instruction cannot be resolved at assemble-time.
468 F->setLinkerRelaxable();
469 newFragment();
470 }
471 F->appendFixups(Fixups);
472}
473
474void MCObjectStreamer::emitInstToFragment(const MCInst &Inst,
475 const MCSubtargetInfo &STI) {
476 auto *F = getCurrentFragment();
477 SmallVector<char, 16> Data;
478 SmallVector<MCFixup, 1> Fixups;
479 getAssembler().getEmitter().encodeInstruction(Inst, CB&: Data, Fixups, STI);
480
481 F->Kind = MCFragment::FT_Relaxable;
482 F->setHasInstructions(STI);
483
484 F->setVarContents(Data);
485 F->setInst(Inst);
486
487 bool MarkedLinkerRelaxable = false;
488 for (auto &Fixup : Fixups) {
489 if (!Fixup.isLinkerRelaxable() || MarkedLinkerRelaxable)
490 continue;
491 MarkedLinkerRelaxable = true;
492 auto *Sec = F->getParent();
493 if (!Sec->isLinkerRelaxable())
494 Sec->setFirstLinkerRelaxable(F->getLayoutOrder());
495 F->setLinkerRelaxable();
496 }
497 F->setVarFixups(Fixups);
498
499 newFragment();
500}
501
502void MCObjectStreamer::emitDwarfLocDirective(unsigned FileNo, unsigned Line,
503 unsigned Column, unsigned Flags,
504 unsigned Isa,
505 unsigned Discriminator,
506 StringRef FileName,
507 StringRef Comment) {
508 // In case we see two .loc directives in a row, make sure the
509 // first one gets a line entry.
510 MCDwarfLineEntry::make(MCOS: this, Section: getCurrentSectionOnly());
511
512 this->MCStreamer::emitDwarfLocDirective(FileNo, Line, Column, Flags, Isa,
513 Discriminator, FileName, Comment);
514}
515
516static const MCExpr *buildSymbolDiff(MCObjectStreamer &OS, const MCSymbol *A,
517 const MCSymbol *B, SMLoc Loc) {
518 MCContext &Context = OS.getContext();
519 const MCExpr *ARef = MCSymbolRefExpr::create(Symbol: A, Ctx&: Context);
520 const MCExpr *BRef = MCSymbolRefExpr::create(Symbol: B, Ctx&: Context);
521 const MCExpr *AddrDelta =
522 MCBinaryExpr::create(Op: MCBinaryExpr::Sub, LHS: ARef, RHS: BRef, Ctx&: Context, Loc);
523 return AddrDelta;
524}
525
526static void emitDwarfSetLineAddr(MCObjectStreamer &OS,
527 MCDwarfLineTableParams Params,
528 int64_t LineDelta, const MCSymbol *Label,
529 int PointerSize) {
530 // emit the sequence to set the address
531 OS.emitIntValue(Value: dwarf::DW_LNS_extended_op, Size: 1);
532 OS.emitULEB128IntValue(Value: PointerSize + 1);
533 OS.emitIntValue(Value: dwarf::DW_LNE_set_address, Size: 1);
534 OS.emitSymbolValue(Sym: Label, Size: PointerSize);
535
536 // emit the sequence for the LineDelta (from 1) and a zero address delta.
537 MCDwarfLineAddr::Emit(MCOS: &OS, Params, LineDelta, AddrDelta: 0);
538}
539
540void MCObjectStreamer::emitDwarfAdvanceLineAddr(int64_t LineDelta,
541 const MCSymbol *LastLabel,
542 const MCSymbol *Label,
543 unsigned PointerSize) {
544 if (!LastLabel) {
545 emitDwarfSetLineAddr(OS&: *this, Params: Assembler->getDWARFLinetableParams(), LineDelta,
546 Label, PointerSize);
547 return;
548 }
549
550 // If the two labels are within the same fragment, then the address-offset is
551 // already a fixed constant and is not relaxable. Emit the advance-line-addr
552 // data immediately to save time and memory.
553 if (auto OptAddrDelta = absoluteSymbolDiff(Hi: Label, Lo: LastLabel)) {
554 SmallString<16> Tmp;
555 MCDwarfLineAddr::encode(Context&: getContext(), Params: Assembler->getDWARFLinetableParams(),
556 LineDelta, AddrDelta: *OptAddrDelta, OS&: Tmp);
557 emitBytes(Data: Tmp);
558 return;
559 }
560
561 auto *F = getCurrentFragment();
562 F->Kind = MCFragment::FT_Dwarf;
563 F->setDwarfAddrDelta(buildSymbolDiff(OS&: *this, A: Label, B: LastLabel, Loc: SMLoc()));
564 F->setDwarfLineDelta(LineDelta);
565 newFragment();
566}
567
568void MCObjectStreamer::emitDwarfLineEndEntry(MCSection *Section,
569 MCSymbol *LastLabel,
570 MCSymbol *EndLabel) {
571 // Emit a DW_LNE_end_sequence into the line table. When EndLabel is null, it
572 // means we should emit the entry for the end of the section and therefore we
573 // use the section end label for the reference label. After having the
574 // appropriate reference label, we emit the address delta and use INT64_MAX as
575 // the line delta which is the signal that this is actually a
576 // DW_LNE_end_sequence.
577 if (!EndLabel)
578 EndLabel = endSection(Section);
579
580 // Switch back the dwarf line section, in case endSection had to switch the
581 // section.
582 MCContext &Ctx = getContext();
583 switchSection(Section: Ctx.getObjectFileInfo()->getDwarfLineSection());
584
585 const MCAsmInfo *AsmInfo = Ctx.getAsmInfo();
586 emitDwarfAdvanceLineAddr(INT64_MAX, LastLabel, Label: EndLabel,
587 PointerSize: AsmInfo->getCodePointerSize());
588}
589
590void MCObjectStreamer::emitDwarfAdvanceFrameAddr(const MCSymbol *LastLabel,
591 const MCSymbol *Label,
592 SMLoc Loc) {
593 auto *F = getCurrentFragment();
594 F->Kind = MCFragment::FT_DwarfFrame;
595 F->setDwarfAddrDelta(buildSymbolDiff(OS&: *this, A: Label, B: LastLabel, Loc));
596 newFragment();
597}
598
599void MCObjectStreamer::emitSFrameCalculateFuncOffset(const MCSymbol *FuncBase,
600 const MCSymbol *FREBegin,
601 MCFragment *FDEFrag,
602 SMLoc Loc) {
603 assert(FuncBase && "No function base address");
604 assert(FREBegin && "FRE doesn't describe a location");
605 auto *F = getCurrentFragment();
606 F->Kind = MCFragment::FT_SFrame;
607 F->setSFrameAddrDelta(buildSymbolDiff(OS&: *this, A: FREBegin, B: FuncBase, Loc));
608 F->setSFrameFDE(FDEFrag);
609 newFragment();
610}
611
612void MCObjectStreamer::emitCVLocDirective(unsigned FunctionId, unsigned FileNo,
613 unsigned Line, unsigned Column,
614 bool PrologueEnd, bool IsStmt,
615 StringRef FileName, SMLoc Loc) {
616 // Validate the directive.
617 if (!checkCVLocSection(FuncId: FunctionId, FileNo, Loc))
618 return;
619
620 // Emit a label at the current position and record it in the CodeViewContext.
621 MCSymbol *LineSym = getContext().createTempSymbol();
622 emitLabel(Symbol: LineSym);
623 getContext().getCVContext().recordCVLoc(Ctx&: getContext(), Label: LineSym, FunctionId,
624 FileNo, Line, Column, PrologueEnd,
625 IsStmt);
626}
627
628void MCObjectStreamer::emitCVLinetableDirective(unsigned FunctionId,
629 const MCSymbol *Begin,
630 const MCSymbol *End) {
631 getContext().getCVContext().emitLineTableForFunction(OS&: *this, FuncId: FunctionId, FuncBegin: Begin,
632 FuncEnd: End);
633 this->MCStreamer::emitCVLinetableDirective(FunctionId, FnStart: Begin, FnEnd: End);
634}
635
636void MCObjectStreamer::emitCVInlineLinetableDirective(
637 unsigned PrimaryFunctionId, unsigned SourceFileId, unsigned SourceLineNum,
638 const MCSymbol *FnStartSym, const MCSymbol *FnEndSym) {
639 getContext().getCVContext().emitInlineLineTableForFunction(
640 OS&: *this, PrimaryFunctionId, SourceFileId, SourceLineNum, FnStartSym,
641 FnEndSym);
642 this->MCStreamer::emitCVInlineLinetableDirective(
643 PrimaryFunctionId, SourceFileId, SourceLineNum, FnStartSym, FnEndSym);
644}
645
646void MCObjectStreamer::emitCVDefRangeDirective(
647 ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
648 StringRef FixedSizePortion) {
649 getContext().getCVContext().emitDefRange(OS&: *this, Ranges, FixedSizePortion);
650 // Attach labels that were pending before we created the defrange fragment to
651 // the beginning of the new fragment.
652 this->MCStreamer::emitCVDefRangeDirective(Ranges, FixedSizePortion);
653}
654
655void MCObjectStreamer::emitCVStringTableDirective() {
656 getContext().getCVContext().emitStringTable(OS&: *this);
657}
658void MCObjectStreamer::emitCVFileChecksumsDirective() {
659 getContext().getCVContext().emitFileChecksums(OS&: *this);
660}
661
662void MCObjectStreamer::emitCVFileChecksumOffsetDirective(unsigned FileNo) {
663 getContext().getCVContext().emitFileChecksumOffset(OS&: *this, FileNo);
664}
665
666void MCObjectStreamer::emitBytes(StringRef Data) {
667 MCDwarfLineEntry::make(MCOS: this, Section: getCurrentSectionOnly());
668 appendContents(Contents: ArrayRef(Data.data(), Data.size()));
669}
670
671void MCObjectStreamer::emitValueToAlignment(Align Alignment, int64_t Fill,
672 uint8_t FillLen,
673 unsigned MaxBytesToEmit) {
674 if (MaxBytesToEmit == 0)
675 MaxBytesToEmit = Alignment.value();
676 MCFragment *F = getCurrentFragment();
677 F->makeAlign(Alignment, Fill, FillLen, MaxBytesToEmit);
678 newFragment();
679
680 // Update the maximum alignment on the current section if necessary.
681 F->getParent()->ensureMinAlignment(MinAlignment: Alignment);
682}
683
684void MCObjectStreamer::emitCodeAlignment(Align Alignment,
685 const MCSubtargetInfo *STI,
686 unsigned MaxBytesToEmit) {
687 auto *F = getCurrentFragment();
688 emitValueToAlignment(Alignment, Fill: 0, FillLen: 1, MaxBytesToEmit);
689 F->u.align.EmitNops = true;
690 F->STI = STI;
691}
692
693void MCObjectStreamer::emitPrefAlign(Align Alignment) {
694 getCurrentSectionOnly()->ensurePreferredAlignment(PrefAlign: Alignment);
695}
696
697void MCObjectStreamer::emitValueToOffset(const MCExpr *Offset,
698 unsigned char Value,
699 SMLoc Loc) {
700 newSpecialFragment<MCOrgFragment>(args: *Offset, args&: Value, args&: Loc);
701}
702
703void MCObjectStreamer::emitRelocDirective(const MCExpr &Offset, StringRef Name,
704 const MCExpr *Expr, SMLoc Loc) {
705 std::optional<MCFixupKind> MaybeKind =
706 Assembler->getBackend().getFixupKind(Name);
707 if (!MaybeKind) {
708 getContext().reportError(L: Loc, Msg: "unknown relocation name");
709 return;
710 }
711
712 MCFixupKind Kind = *MaybeKind;
713 if (Expr)
714 visitUsedExpr(Expr: *Expr);
715 else
716 Expr =
717 MCSymbolRefExpr::create(Symbol: getContext().createTempSymbol(), Ctx&: getContext());
718
719 auto *O = &Offset;
720 int64_t Val;
721 if (Offset.evaluateAsAbsolute(Res&: Val, Asm: nullptr)) {
722 auto *SecSym = getCurrentSectionOnly()->getBeginSymbol();
723 O = MCBinaryExpr::createAdd(LHS: MCSymbolRefExpr::create(Symbol: SecSym, Ctx&: getContext()),
724 RHS: O, Ctx&: getContext(), Loc);
725 }
726 getAssembler().addRelocDirective(RD: {.Offset: *O, .Expr: Expr, .Kind: Kind});
727}
728
729void MCObjectStreamer::emitFill(const MCExpr &NumBytes, uint64_t FillValue,
730 SMLoc Loc) {
731 assert(getCurrentSectionOnly() && "need a section");
732 newSpecialFragment<MCFillFragment>(args&: FillValue, args: 1, args: NumBytes, args&: Loc);
733}
734
735void MCObjectStreamer::emitFill(const MCExpr &NumValues, int64_t Size,
736 int64_t Expr, SMLoc Loc) {
737 int64_t IntNumValues;
738 // Do additional checking now if we can resolve the value.
739 if (NumValues.evaluateAsAbsolute(Res&: IntNumValues, Asm: getAssembler())) {
740 if (IntNumValues < 0) {
741 getContext().getSourceManager()->PrintMessage(
742 Loc, Kind: SourceMgr::DK_Warning,
743 Msg: "'.fill' directive with negative repeat count has no effect");
744 return;
745 }
746 // Emit now if we can for better errors.
747 int64_t NonZeroSize = Size > 4 ? 4 : Size;
748 Expr &= ~0ULL >> (64 - NonZeroSize * 8);
749 for (uint64_t i = 0, e = IntNumValues; i != e; ++i) {
750 emitIntValue(Value: Expr, Size: NonZeroSize);
751 if (NonZeroSize < Size)
752 emitIntValue(Value: 0, Size: Size - NonZeroSize);
753 }
754 return;
755 }
756
757 // Otherwise emit as fragment.
758 assert(getCurrentSectionOnly() && "need a section");
759 newSpecialFragment<MCFillFragment>(args&: Expr, args&: Size, args: NumValues, args&: Loc);
760}
761
762void MCObjectStreamer::emitNops(int64_t NumBytes, int64_t ControlledNopLength,
763 SMLoc Loc, const MCSubtargetInfo &STI) {
764 assert(getCurrentSectionOnly() && "need a section");
765 newSpecialFragment<MCNopsFragment>(args&: NumBytes, args&: ControlledNopLength, args&: Loc, args: STI);
766}
767
768void MCObjectStreamer::emitFileDirective(StringRef Filename) {
769 MCAssembler &Asm = getAssembler();
770 Asm.getWriter().addFileName(FileName: Filename);
771}
772
773void MCObjectStreamer::emitFileDirective(StringRef Filename,
774 StringRef CompilerVersion,
775 StringRef TimeStamp,
776 StringRef Description) {
777 MCObjectWriter &W = getAssembler().getWriter();
778 W.addFileName(FileName: Filename);
779 if (CompilerVersion.size())
780 W.setCompilerVersion(CompilerVersion);
781 // TODO: add TimeStamp and Description to .file symbol table entry
782 // with the integrated assembler.
783}
784
785void MCObjectStreamer::emitAddrsig() {
786 getAssembler().getWriter().emitAddrsigSection();
787}
788
789void MCObjectStreamer::emitAddrsigSym(const MCSymbol *Sym) {
790 getAssembler().getWriter().addAddrsigSymbol(Sym);
791}
792
793void MCObjectStreamer::finishImpl() {
794 getContext().RemapDebugPaths();
795
796 // If we are generating dwarf for assembly source files dump out the sections.
797 if (getContext().getGenDwarfForAssembly())
798 MCGenDwarfInfo::Emit(MCOS: this);
799
800 // Dump out the dwarf file & directory tables and line tables.
801 MCDwarfLineTable::emit(MCOS: this, Params: getAssembler().getDWARFLinetableParams());
802
803 // Emit pseudo probes for the current module.
804 MCPseudoProbeTable::emit(MCOS: this);
805
806 getAssembler().Finish();
807}
808