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