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