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