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