xref: /freebsd-src/contrib/llvm-project/llvm/lib/MC/MCObjectStreamer.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===- lib/MC/MCObjectStreamer.cpp - Object File MCStreamer Interface -----===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "llvm/MC/MCObjectStreamer.h"
100b57cec5SDimitry Andric #include "llvm/MC/MCAsmBackend.h"
11fe6060f1SDimitry Andric #include "llvm/MC/MCAsmInfo.h"
120b57cec5SDimitry Andric #include "llvm/MC/MCAssembler.h"
130b57cec5SDimitry Andric #include "llvm/MC/MCCodeEmitter.h"
140b57cec5SDimitry Andric #include "llvm/MC/MCCodeView.h"
150b57cec5SDimitry Andric #include "llvm/MC/MCContext.h"
160b57cec5SDimitry Andric #include "llvm/MC/MCDwarf.h"
170b57cec5SDimitry Andric #include "llvm/MC/MCExpr.h"
18fe6060f1SDimitry Andric #include "llvm/MC/MCObjectFileInfo.h"
190b57cec5SDimitry Andric #include "llvm/MC/MCObjectWriter.h"
200b57cec5SDimitry Andric #include "llvm/MC/MCSection.h"
210b57cec5SDimitry Andric #include "llvm/MC/MCSymbol.h"
225ffd83dbSDimitry Andric #include "llvm/MC/MCValue.h"
230b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
240b57cec5SDimitry Andric #include "llvm/Support/SourceMgr.h"
250b57cec5SDimitry Andric using namespace llvm;
260b57cec5SDimitry Andric 
270b57cec5SDimitry Andric MCObjectStreamer::MCObjectStreamer(MCContext &Context,
280b57cec5SDimitry Andric                                    std::unique_ptr<MCAsmBackend> TAB,
290b57cec5SDimitry Andric                                    std::unique_ptr<MCObjectWriter> OW,
300b57cec5SDimitry Andric                                    std::unique_ptr<MCCodeEmitter> Emitter)
310b57cec5SDimitry Andric     : MCStreamer(Context),
328bcb0991SDimitry Andric       Assembler(std::make_unique<MCAssembler>(
330b57cec5SDimitry Andric           Context, std::move(TAB), std::move(Emitter), std::move(OW))),
34480093f4SDimitry Andric       EmitEHFrame(true), EmitDebugFrame(false) {
35*0fca6ea1SDimitry Andric   assert(Assembler->getBackendPtr() && Assembler->getEmitterPtr());
36480093f4SDimitry Andric   setAllowAutoPadding(Assembler->getBackend().allowAutoPadding());
37*0fca6ea1SDimitry Andric   if (Context.getTargetOptions() && Context.getTargetOptions()->MCRelaxAll)
38*0fca6ea1SDimitry Andric     Assembler->setRelaxAll(true);
39480093f4SDimitry Andric }
400b57cec5SDimitry Andric 
4181ad6265SDimitry Andric MCObjectStreamer::~MCObjectStreamer() = default;
420b57cec5SDimitry Andric 
430b57cec5SDimitry Andric MCAssembler *MCObjectStreamer::getAssemblerPtr() {
440b57cec5SDimitry Andric   if (getUseAssemblerInfoForParsing())
450b57cec5SDimitry Andric     return Assembler.get();
460b57cec5SDimitry Andric   return nullptr;
470b57cec5SDimitry Andric }
480b57cec5SDimitry Andric 
490b57cec5SDimitry Andric // When fixup's offset is a forward declared label, e.g.:
500b57cec5SDimitry Andric //
510b57cec5SDimitry Andric //   .reloc 1f, R_MIPS_JALR, foo
520b57cec5SDimitry Andric // 1: nop
530b57cec5SDimitry Andric //
540b57cec5SDimitry Andric // postpone adding it to Fixups vector until the label is defined and its offset
550b57cec5SDimitry Andric // is known.
560b57cec5SDimitry Andric void MCObjectStreamer::resolvePendingFixups() {
570b57cec5SDimitry Andric   for (PendingMCFixup &PendingFixup : PendingFixups) {
580b57cec5SDimitry Andric     if (!PendingFixup.Sym || PendingFixup.Sym->isUndefined ()) {
590b57cec5SDimitry Andric       getContext().reportError(PendingFixup.Fixup.getLoc(),
600b57cec5SDimitry Andric                                "unresolved relocation offset");
610b57cec5SDimitry Andric       continue;
620b57cec5SDimitry Andric     }
6304eeddc0SDimitry Andric     PendingFixup.Fixup.setOffset(PendingFixup.Sym->getOffset() +
6404eeddc0SDimitry Andric                                  PendingFixup.Fixup.getOffset());
6504eeddc0SDimitry Andric 
6604eeddc0SDimitry Andric     // If the location symbol to relocate is in MCEncodedFragmentWithFixups,
6704eeddc0SDimitry Andric     // put the Fixup into location symbol's fragment. Otherwise
6804eeddc0SDimitry Andric     // put into PendingFixup.DF
6904eeddc0SDimitry Andric     MCFragment *SymFragment = PendingFixup.Sym->getFragment();
7004eeddc0SDimitry Andric     switch (SymFragment->getKind()) {
7104eeddc0SDimitry Andric     case MCFragment::FT_Relaxable:
7204eeddc0SDimitry Andric     case MCFragment::FT_Dwarf:
7304eeddc0SDimitry Andric     case MCFragment::FT_PseudoProbe:
7404eeddc0SDimitry Andric       cast<MCEncodedFragmentWithFixups<8, 1>>(SymFragment)
7504eeddc0SDimitry Andric           ->getFixups()
7604eeddc0SDimitry Andric           .push_back(PendingFixup.Fixup);
7704eeddc0SDimitry Andric       break;
7804eeddc0SDimitry Andric     case MCFragment::FT_Data:
7904eeddc0SDimitry Andric     case MCFragment::FT_CVDefRange:
8004eeddc0SDimitry Andric       cast<MCEncodedFragmentWithFixups<32, 4>>(SymFragment)
8104eeddc0SDimitry Andric           ->getFixups()
8204eeddc0SDimitry Andric           .push_back(PendingFixup.Fixup);
8304eeddc0SDimitry Andric       break;
8404eeddc0SDimitry Andric     default:
850b57cec5SDimitry Andric       PendingFixup.DF->getFixups().push_back(PendingFixup.Fixup);
8604eeddc0SDimitry Andric       break;
8704eeddc0SDimitry Andric     }
880b57cec5SDimitry Andric   }
890b57cec5SDimitry Andric   PendingFixups.clear();
900b57cec5SDimitry Andric }
910b57cec5SDimitry Andric 
920b57cec5SDimitry Andric // As a compile-time optimization, avoid allocating and evaluating an MCExpr
930b57cec5SDimitry Andric // tree for (Hi - Lo) when Hi and Lo are offsets into the same fragment.
94bdd1243dSDimitry Andric static std::optional<uint64_t> absoluteSymbolDiff(const MCSymbol *Hi,
95fe6060f1SDimitry Andric                                                   const MCSymbol *Lo) {
960b57cec5SDimitry Andric   assert(Hi && Lo);
970b57cec5SDimitry Andric   if (!Hi->getFragment() || Hi->getFragment() != Lo->getFragment() ||
980b57cec5SDimitry Andric       Hi->isVariable() || Lo->isVariable())
99bdd1243dSDimitry Andric     return std::nullopt;
1000b57cec5SDimitry Andric 
1010b57cec5SDimitry Andric   return Hi->getOffset() - Lo->getOffset();
1020b57cec5SDimitry Andric }
1030b57cec5SDimitry Andric 
1040b57cec5SDimitry Andric void MCObjectStreamer::emitAbsoluteSymbolDiff(const MCSymbol *Hi,
1050b57cec5SDimitry Andric                                               const MCSymbol *Lo,
1060b57cec5SDimitry Andric                                               unsigned Size) {
107fe6060f1SDimitry Andric   if (!getAssembler().getContext().getTargetTriple().isRISCV())
108bdd1243dSDimitry Andric     if (std::optional<uint64_t> Diff = absoluteSymbolDiff(Hi, Lo))
109fe6060f1SDimitry Andric       return emitIntValue(*Diff, Size);
1100b57cec5SDimitry Andric   MCStreamer::emitAbsoluteSymbolDiff(Hi, Lo, Size);
1110b57cec5SDimitry Andric }
1120b57cec5SDimitry Andric 
1130b57cec5SDimitry Andric void MCObjectStreamer::emitAbsoluteSymbolDiffAsULEB128(const MCSymbol *Hi,
1140b57cec5SDimitry Andric                                                        const MCSymbol *Lo) {
115fe6060f1SDimitry Andric   if (!getAssembler().getContext().getTargetTriple().isRISCV())
116bdd1243dSDimitry Andric     if (std::optional<uint64_t> Diff = absoluteSymbolDiff(Hi, Lo)) {
117bdd1243dSDimitry Andric       emitULEB128IntValue(*Diff);
118bdd1243dSDimitry Andric       return;
119bdd1243dSDimitry Andric     }
1200b57cec5SDimitry Andric   MCStreamer::emitAbsoluteSymbolDiffAsULEB128(Hi, Lo);
1210b57cec5SDimitry Andric }
1220b57cec5SDimitry Andric 
1230b57cec5SDimitry Andric void MCObjectStreamer::reset() {
124*0fca6ea1SDimitry Andric   if (Assembler) {
1250b57cec5SDimitry Andric     Assembler->reset();
126*0fca6ea1SDimitry Andric     if (getContext().getTargetOptions())
127*0fca6ea1SDimitry Andric       Assembler->setRelaxAll(getContext().getTargetOptions()->MCRelaxAll);
128*0fca6ea1SDimitry Andric   }
1290b57cec5SDimitry Andric   EmitEHFrame = true;
1300b57cec5SDimitry Andric   EmitDebugFrame = false;
1310b57cec5SDimitry Andric   MCStreamer::reset();
1320b57cec5SDimitry Andric }
1330b57cec5SDimitry Andric 
1345ffd83dbSDimitry Andric void MCObjectStreamer::emitFrames(MCAsmBackend *MAB) {
1350b57cec5SDimitry Andric   if (!getNumFrameInfos())
1360b57cec5SDimitry Andric     return;
1370b57cec5SDimitry Andric 
1380b57cec5SDimitry Andric   if (EmitEHFrame)
1390b57cec5SDimitry Andric     MCDwarfFrameEmitter::Emit(*this, MAB, true);
1400b57cec5SDimitry Andric 
1410b57cec5SDimitry Andric   if (EmitDebugFrame)
1420b57cec5SDimitry Andric     MCDwarfFrameEmitter::Emit(*this, MAB, false);
1430b57cec5SDimitry Andric }
1440b57cec5SDimitry Andric 
1455ffd83dbSDimitry Andric static bool canReuseDataFragment(const MCDataFragment &F,
1460b57cec5SDimitry Andric                                  const MCAssembler &Assembler,
1470b57cec5SDimitry Andric                                  const MCSubtargetInfo *STI) {
1480b57cec5SDimitry Andric   if (!F.hasInstructions())
1490b57cec5SDimitry Andric     return true;
15006c3fb27SDimitry Andric   // Do not add data after a linker-relaxable instruction. The difference
15106c3fb27SDimitry Andric   // between a new label and a label at or before the linker-relaxable
15206c3fb27SDimitry Andric   // instruction cannot be resolved at assemble-time.
15306c3fb27SDimitry Andric   if (F.isLinkerRelaxable())
15406c3fb27SDimitry Andric     return false;
1550b57cec5SDimitry Andric   // When bundling is enabled, we don't want to add data to a fragment that
1565ffd83dbSDimitry Andric   // already has instructions (see MCELFStreamer::emitInstToData for details)
1570b57cec5SDimitry Andric   if (Assembler.isBundlingEnabled())
158*0fca6ea1SDimitry Andric     return false;
1590b57cec5SDimitry Andric   // If the subtarget is changed mid fragment we start a new fragment to record
1600b57cec5SDimitry Andric   // the new STI.
1610b57cec5SDimitry Andric   return !STI || F.getSubtargetInfo() == STI;
1620b57cec5SDimitry Andric }
1630b57cec5SDimitry Andric 
1640b57cec5SDimitry Andric MCDataFragment *
1650b57cec5SDimitry Andric MCObjectStreamer::getOrCreateDataFragment(const MCSubtargetInfo *STI) {
166*0fca6ea1SDimitry Andric   auto *F = dyn_cast<MCDataFragment>(getCurrentFragment());
1675ffd83dbSDimitry Andric   if (!F || !canReuseDataFragment(*F, *Assembler, STI)) {
168*0fca6ea1SDimitry Andric     F = getContext().allocFragment<MCDataFragment>();
1690b57cec5SDimitry Andric     insert(F);
1700b57cec5SDimitry Andric   }
1710b57cec5SDimitry Andric   return F;
1720b57cec5SDimitry Andric }
1730b57cec5SDimitry Andric 
1740b57cec5SDimitry Andric void MCObjectStreamer::visitUsedSymbol(const MCSymbol &Sym) {
1750b57cec5SDimitry Andric   Assembler->registerSymbol(Sym);
1760b57cec5SDimitry Andric }
1770b57cec5SDimitry Andric 
1785ffd83dbSDimitry Andric void MCObjectStreamer::emitCFISections(bool EH, bool Debug) {
1795ffd83dbSDimitry Andric   MCStreamer::emitCFISections(EH, Debug);
1800b57cec5SDimitry Andric   EmitEHFrame = EH;
1810b57cec5SDimitry Andric   EmitDebugFrame = Debug;
1820b57cec5SDimitry Andric }
1830b57cec5SDimitry Andric 
1845ffd83dbSDimitry Andric void MCObjectStreamer::emitValueImpl(const MCExpr *Value, unsigned Size,
1850b57cec5SDimitry Andric                                      SMLoc Loc) {
1865ffd83dbSDimitry Andric   MCStreamer::emitValueImpl(Value, Size, Loc);
1870b57cec5SDimitry Andric   MCDataFragment *DF = getOrCreateDataFragment();
1880b57cec5SDimitry Andric 
189fe6060f1SDimitry Andric   MCDwarfLineEntry::make(this, getCurrentSectionOnly());
1900b57cec5SDimitry Andric 
1910b57cec5SDimitry Andric   // Avoid fixups when possible.
1920b57cec5SDimitry Andric   int64_t AbsValue;
1930b57cec5SDimitry Andric   if (Value->evaluateAsAbsolute(AbsValue, getAssemblerPtr())) {
1940b57cec5SDimitry Andric     if (!isUIntN(8 * Size, AbsValue) && !isIntN(8 * Size, AbsValue)) {
1950b57cec5SDimitry Andric       getContext().reportError(
1960b57cec5SDimitry Andric           Loc, "value evaluated as " + Twine(AbsValue) + " is out of range.");
1970b57cec5SDimitry Andric       return;
1980b57cec5SDimitry Andric     }
1995ffd83dbSDimitry Andric     emitIntValue(AbsValue, Size);
2000b57cec5SDimitry Andric     return;
2010b57cec5SDimitry Andric   }
2020b57cec5SDimitry Andric   DF->getFixups().push_back(
2030b57cec5SDimitry Andric       MCFixup::create(DF->getContents().size(), Value,
2040b57cec5SDimitry Andric                       MCFixup::getKindForSize(Size, false), Loc));
2050b57cec5SDimitry Andric   DF->getContents().resize(DF->getContents().size() + Size, 0);
2060b57cec5SDimitry Andric }
2070b57cec5SDimitry Andric 
2085ffd83dbSDimitry Andric MCSymbol *MCObjectStreamer::emitCFILabel() {
209e8d8bef9SDimitry Andric   MCSymbol *Label = getContext().createTempSymbol("cfi");
2105ffd83dbSDimitry Andric   emitLabel(Label);
2110b57cec5SDimitry Andric   return Label;
2120b57cec5SDimitry Andric }
2130b57cec5SDimitry Andric 
2145ffd83dbSDimitry Andric void MCObjectStreamer::emitCFIStartProcImpl(MCDwarfFrameInfo &Frame) {
2150b57cec5SDimitry Andric   // We need to create a local symbol to avoid relocations.
2160b57cec5SDimitry Andric   Frame.Begin = getContext().createTempSymbol();
2175ffd83dbSDimitry Andric   emitLabel(Frame.Begin);
2180b57cec5SDimitry Andric }
2190b57cec5SDimitry Andric 
2205ffd83dbSDimitry Andric void MCObjectStreamer::emitCFIEndProcImpl(MCDwarfFrameInfo &Frame) {
2210b57cec5SDimitry Andric   Frame.End = getContext().createTempSymbol();
2225ffd83dbSDimitry Andric   emitLabel(Frame.End);
2230b57cec5SDimitry Andric }
2240b57cec5SDimitry Andric 
2255ffd83dbSDimitry Andric void MCObjectStreamer::emitLabel(MCSymbol *Symbol, SMLoc Loc) {
2265ffd83dbSDimitry Andric   MCStreamer::emitLabel(Symbol, Loc);
2270b57cec5SDimitry Andric 
2280b57cec5SDimitry Andric   getAssembler().registerSymbol(*Symbol);
2290b57cec5SDimitry Andric 
2300b57cec5SDimitry Andric   // If there is a current fragment, mark the symbol as pointing into it.
2310b57cec5SDimitry Andric   // Otherwise queue the label and set its fragment pointer when we emit the
2320b57cec5SDimitry Andric   // next fragment.
233*0fca6ea1SDimitry Andric   MCDataFragment *F = getOrCreateDataFragment();
2340b57cec5SDimitry Andric   Symbol->setFragment(F);
2350b57cec5SDimitry Andric   Symbol->setOffset(F->getContents().size());
2360eae32dcSDimitry Andric 
2370eae32dcSDimitry Andric   emitPendingAssignments(Symbol);
2380eae32dcSDimitry Andric }
2390eae32dcSDimitry Andric 
2400eae32dcSDimitry Andric void MCObjectStreamer::emitPendingAssignments(MCSymbol *Symbol) {
2410eae32dcSDimitry Andric   auto Assignments = pendingAssignments.find(Symbol);
2420eae32dcSDimitry Andric   if (Assignments != pendingAssignments.end()) {
2430eae32dcSDimitry Andric     for (const PendingAssignment &A : Assignments->second)
2440eae32dcSDimitry Andric       emitAssignment(A.Symbol, A.Value);
2450eae32dcSDimitry Andric 
2460eae32dcSDimitry Andric     pendingAssignments.erase(Assignments);
2470eae32dcSDimitry Andric   }
2480b57cec5SDimitry Andric }
2490b57cec5SDimitry Andric 
250480093f4SDimitry Andric // Emit a label at a previously emitted fragment/offset position. This must be
251480093f4SDimitry Andric // within the currently-active section.
2525ffd83dbSDimitry Andric void MCObjectStreamer::emitLabelAtPos(MCSymbol *Symbol, SMLoc Loc,
253*0fca6ea1SDimitry Andric                                       MCDataFragment &F, uint64_t Offset) {
254*0fca6ea1SDimitry Andric   assert(F.getParent() == getCurrentSectionOnly());
2555ffd83dbSDimitry Andric   MCStreamer::emitLabel(Symbol, Loc);
2560b57cec5SDimitry Andric   getAssembler().registerSymbol(*Symbol);
257*0fca6ea1SDimitry Andric   Symbol->setFragment(&F);
258480093f4SDimitry Andric   Symbol->setOffset(Offset);
2590b57cec5SDimitry Andric }
2600b57cec5SDimitry Andric 
2615ffd83dbSDimitry Andric void MCObjectStreamer::emitULEB128Value(const MCExpr *Value) {
2620b57cec5SDimitry Andric   int64_t IntValue;
2630b57cec5SDimitry Andric   if (Value->evaluateAsAbsolute(IntValue, getAssemblerPtr())) {
2645ffd83dbSDimitry Andric     emitULEB128IntValue(IntValue);
2650b57cec5SDimitry Andric     return;
2660b57cec5SDimitry Andric   }
267*0fca6ea1SDimitry Andric   insert(getContext().allocFragment<MCLEBFragment>(*Value, false));
2680b57cec5SDimitry Andric }
2690b57cec5SDimitry Andric 
2705ffd83dbSDimitry Andric void MCObjectStreamer::emitSLEB128Value(const MCExpr *Value) {
2710b57cec5SDimitry Andric   int64_t IntValue;
2720b57cec5SDimitry Andric   if (Value->evaluateAsAbsolute(IntValue, getAssemblerPtr())) {
2735ffd83dbSDimitry Andric     emitSLEB128IntValue(IntValue);
2740b57cec5SDimitry Andric     return;
2750b57cec5SDimitry Andric   }
276*0fca6ea1SDimitry Andric   insert(getContext().allocFragment<MCLEBFragment>(*Value, true));
2770b57cec5SDimitry Andric }
2780b57cec5SDimitry Andric 
2795ffd83dbSDimitry Andric void MCObjectStreamer::emitWeakReference(MCSymbol *Alias,
2800b57cec5SDimitry Andric                                          const MCSymbol *Symbol) {
2810b57cec5SDimitry Andric   report_fatal_error("This file format doesn't support weak aliases.");
2820b57cec5SDimitry Andric }
2830b57cec5SDimitry Andric 
284*0fca6ea1SDimitry Andric void MCObjectStreamer::changeSection(MCSection *Section, uint32_t Subsection) {
2850b57cec5SDimitry Andric   changeSectionImpl(Section, Subsection);
2860b57cec5SDimitry Andric }
2870b57cec5SDimitry Andric 
2880b57cec5SDimitry Andric bool MCObjectStreamer::changeSectionImpl(MCSection *Section,
289*0fca6ea1SDimitry Andric                                          uint32_t Subsection) {
2900b57cec5SDimitry Andric   assert(Section && "Cannot switch to a null section!");
2910b57cec5SDimitry Andric   getContext().clearDwarfLocSeen();
2920b57cec5SDimitry Andric 
293*0fca6ea1SDimitry Andric   auto &Subsections = Section->Subsections;
294*0fca6ea1SDimitry Andric   size_t I = 0, E = Subsections.size();
295*0fca6ea1SDimitry Andric   while (I != E && Subsections[I].first < Subsection)
296*0fca6ea1SDimitry Andric     ++I;
297*0fca6ea1SDimitry Andric   // If the subsection number is not in the sorted Subsections list, create a
298*0fca6ea1SDimitry Andric   // new fragment list.
299*0fca6ea1SDimitry Andric   if (I == E || Subsections[I].first != Subsection) {
300*0fca6ea1SDimitry Andric     auto *F = getContext().allocFragment<MCDataFragment>();
301*0fca6ea1SDimitry Andric     F->setParent(Section);
302*0fca6ea1SDimitry Andric     Subsections.insert(Subsections.begin() + I,
303*0fca6ea1SDimitry Andric                        {Subsection, MCSection::FragList{F, F}});
30406c3fb27SDimitry Andric   }
305*0fca6ea1SDimitry Andric   Section->CurFragList = &Subsections[I].second;
306*0fca6ea1SDimitry Andric   CurFrag = Section->CurFragList->Tail;
307*0fca6ea1SDimitry Andric 
308*0fca6ea1SDimitry Andric   return getAssembler().registerSection(*Section);
30906c3fb27SDimitry Andric }
31006c3fb27SDimitry Andric 
311*0fca6ea1SDimitry Andric void MCObjectStreamer::switchSectionNoPrint(MCSection *Section) {
312*0fca6ea1SDimitry Andric   MCStreamer::switchSectionNoPrint(Section);
313*0fca6ea1SDimitry Andric   changeSection(Section, 0);
3140b57cec5SDimitry Andric }
3150b57cec5SDimitry Andric 
3165ffd83dbSDimitry Andric void MCObjectStreamer::emitAssignment(MCSymbol *Symbol, const MCExpr *Value) {
3170b57cec5SDimitry Andric   getAssembler().registerSymbol(*Symbol);
3185ffd83dbSDimitry Andric   MCStreamer::emitAssignment(Symbol, Value);
3190eae32dcSDimitry Andric   emitPendingAssignments(Symbol);
3200eae32dcSDimitry Andric }
3210eae32dcSDimitry Andric 
3220eae32dcSDimitry Andric void MCObjectStreamer::emitConditionalAssignment(MCSymbol *Symbol,
3230eae32dcSDimitry Andric                                                  const MCExpr *Value) {
3240eae32dcSDimitry Andric   const MCSymbol *Target = &cast<MCSymbolRefExpr>(*Value).getSymbol();
3250eae32dcSDimitry Andric 
3260eae32dcSDimitry Andric   // If the symbol already exists, emit the assignment. Otherwise, emit it
3270eae32dcSDimitry Andric   // later only if the symbol is also emitted.
3280eae32dcSDimitry Andric   if (Target->isRegistered())
3290eae32dcSDimitry Andric     emitAssignment(Symbol, Value);
3300eae32dcSDimitry Andric   else
3310eae32dcSDimitry Andric     pendingAssignments[Target].push_back({Symbol, Value});
3320b57cec5SDimitry Andric }
3330b57cec5SDimitry Andric 
3340b57cec5SDimitry Andric bool MCObjectStreamer::mayHaveInstructions(MCSection &Sec) const {
3350b57cec5SDimitry Andric   return Sec.hasInstructions();
3360b57cec5SDimitry Andric }
3370b57cec5SDimitry Andric 
3385ffd83dbSDimitry Andric void MCObjectStreamer::emitInstruction(const MCInst &Inst,
3390b57cec5SDimitry Andric                                        const MCSubtargetInfo &STI) {
3405ffd83dbSDimitry Andric   const MCSection &Sec = *getCurrentSectionOnly();
3415ffd83dbSDimitry Andric   if (Sec.isVirtualSection()) {
3425ffd83dbSDimitry Andric     getContext().reportError(Inst.getLoc(), Twine(Sec.getVirtualSectionKind()) +
3435ffd83dbSDimitry Andric                                                 " section '" + Sec.getName() +
3445ffd83dbSDimitry Andric                                                 "' cannot have instructions");
3455ffd83dbSDimitry Andric     return;
3465ffd83dbSDimitry Andric   }
3475ffd83dbSDimitry Andric   emitInstructionImpl(Inst, STI);
3480b57cec5SDimitry Andric }
3490b57cec5SDimitry Andric 
3505ffd83dbSDimitry Andric void MCObjectStreamer::emitInstructionImpl(const MCInst &Inst,
3510b57cec5SDimitry Andric                                            const MCSubtargetInfo &STI) {
3525ffd83dbSDimitry Andric   MCStreamer::emitInstruction(Inst, STI);
3530b57cec5SDimitry Andric 
3540b57cec5SDimitry Andric   MCSection *Sec = getCurrentSectionOnly();
3550b57cec5SDimitry Andric   Sec->setHasInstructions(true);
3560b57cec5SDimitry Andric 
3570b57cec5SDimitry Andric   // Now that a machine instruction has been assembled into this section, make
3580b57cec5SDimitry Andric   // a line entry for any .loc directive that has been seen.
359fe6060f1SDimitry Andric   MCDwarfLineEntry::make(this, getCurrentSectionOnly());
3600b57cec5SDimitry Andric 
3610b57cec5SDimitry Andric   // If this instruction doesn't need relaxation, just emit it as data.
3620b57cec5SDimitry Andric   MCAssembler &Assembler = getAssembler();
3635ffd83dbSDimitry Andric   MCAsmBackend &Backend = Assembler.getBackend();
3645ffd83dbSDimitry Andric   if (!(Backend.mayNeedRelaxation(Inst, STI) ||
3655ffd83dbSDimitry Andric         Backend.allowEnhancedRelaxation())) {
3665ffd83dbSDimitry Andric     emitInstToData(Inst, STI);
3670b57cec5SDimitry Andric     return;
3680b57cec5SDimitry Andric   }
3690b57cec5SDimitry Andric 
3700b57cec5SDimitry Andric   // Otherwise, relax and emit it as data if either:
3710b57cec5SDimitry Andric   // - The RelaxAll flag was passed
3720b57cec5SDimitry Andric   // - Bundling is enabled and this instruction is inside a bundle-locked
3730b57cec5SDimitry Andric   //   group. We want to emit all such instructions into the same data
3740b57cec5SDimitry Andric   //   fragment.
3750b57cec5SDimitry Andric   if (Assembler.getRelaxAll() ||
3760b57cec5SDimitry Andric       (Assembler.isBundlingEnabled() && Sec->isBundleLocked())) {
3775ffd83dbSDimitry Andric     MCInst Relaxed = Inst;
3785ffd83dbSDimitry Andric     while (Backend.mayNeedRelaxation(Relaxed, STI))
3795ffd83dbSDimitry Andric       Backend.relaxInstruction(Relaxed, STI);
3805ffd83dbSDimitry Andric     emitInstToData(Relaxed, STI);
3810b57cec5SDimitry Andric     return;
3820b57cec5SDimitry Andric   }
3830b57cec5SDimitry Andric 
3840b57cec5SDimitry Andric   // Otherwise emit to a separate fragment.
3855ffd83dbSDimitry Andric   emitInstToFragment(Inst, STI);
3860b57cec5SDimitry Andric }
3870b57cec5SDimitry Andric 
3885ffd83dbSDimitry Andric void MCObjectStreamer::emitInstToFragment(const MCInst &Inst,
3890b57cec5SDimitry Andric                                           const MCSubtargetInfo &STI) {
3900b57cec5SDimitry Andric   // Always create a new, separate fragment here, because its size can change
3910b57cec5SDimitry Andric   // during relaxation.
392*0fca6ea1SDimitry Andric   MCRelaxableFragment *IF =
393*0fca6ea1SDimitry Andric       getContext().allocFragment<MCRelaxableFragment>(Inst, STI);
3940b57cec5SDimitry Andric   insert(IF);
3950b57cec5SDimitry Andric 
396*0fca6ea1SDimitry Andric   getAssembler().getEmitter().encodeInstruction(Inst, IF->getContents(),
397*0fca6ea1SDimitry Andric                                                 IF->getFixups(), STI);
3980b57cec5SDimitry Andric }
3990b57cec5SDimitry Andric 
4000b57cec5SDimitry Andric #ifndef NDEBUG
4010b57cec5SDimitry Andric static const char *const BundlingNotImplementedMsg =
4020b57cec5SDimitry Andric   "Aligned bundling is not implemented for this object format";
4030b57cec5SDimitry Andric #endif
4040b57cec5SDimitry Andric 
405bdd1243dSDimitry Andric void MCObjectStreamer::emitBundleAlignMode(Align Alignment) {
4060b57cec5SDimitry Andric   llvm_unreachable(BundlingNotImplementedMsg);
4070b57cec5SDimitry Andric }
4080b57cec5SDimitry Andric 
4095ffd83dbSDimitry Andric void MCObjectStreamer::emitBundleLock(bool AlignToEnd) {
4100b57cec5SDimitry Andric   llvm_unreachable(BundlingNotImplementedMsg);
4110b57cec5SDimitry Andric }
4120b57cec5SDimitry Andric 
4135ffd83dbSDimitry Andric void MCObjectStreamer::emitBundleUnlock() {
4140b57cec5SDimitry Andric   llvm_unreachable(BundlingNotImplementedMsg);
4150b57cec5SDimitry Andric }
4160b57cec5SDimitry Andric 
4175ffd83dbSDimitry Andric void MCObjectStreamer::emitDwarfLocDirective(unsigned FileNo, unsigned Line,
4180b57cec5SDimitry Andric                                              unsigned Column, unsigned Flags,
4190b57cec5SDimitry Andric                                              unsigned Isa,
4200b57cec5SDimitry Andric                                              unsigned Discriminator,
4210b57cec5SDimitry Andric                                              StringRef FileName) {
4220b57cec5SDimitry Andric   // In case we see two .loc directives in a row, make sure the
4230b57cec5SDimitry Andric   // first one gets a line entry.
424fe6060f1SDimitry Andric   MCDwarfLineEntry::make(this, getCurrentSectionOnly());
4250b57cec5SDimitry Andric 
4265ffd83dbSDimitry Andric   this->MCStreamer::emitDwarfLocDirective(FileNo, Line, Column, Flags, Isa,
4275ffd83dbSDimitry Andric                                           Discriminator, FileName);
4280b57cec5SDimitry Andric }
4290b57cec5SDimitry Andric 
4300b57cec5SDimitry Andric static const MCExpr *buildSymbolDiff(MCObjectStreamer &OS, const MCSymbol *A,
43106c3fb27SDimitry Andric                                      const MCSymbol *B, SMLoc Loc) {
4320b57cec5SDimitry Andric   MCContext &Context = OS.getContext();
4330b57cec5SDimitry Andric   MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None;
4340b57cec5SDimitry Andric   const MCExpr *ARef = MCSymbolRefExpr::create(A, Variant, Context);
4350b57cec5SDimitry Andric   const MCExpr *BRef = MCSymbolRefExpr::create(B, Variant, Context);
4360b57cec5SDimitry Andric   const MCExpr *AddrDelta =
43706c3fb27SDimitry Andric       MCBinaryExpr::create(MCBinaryExpr::Sub, ARef, BRef, Context, Loc);
4380b57cec5SDimitry Andric   return AddrDelta;
4390b57cec5SDimitry Andric }
4400b57cec5SDimitry Andric 
4410b57cec5SDimitry Andric static void emitDwarfSetLineAddr(MCObjectStreamer &OS,
4420b57cec5SDimitry Andric                                  MCDwarfLineTableParams Params,
4430b57cec5SDimitry Andric                                  int64_t LineDelta, const MCSymbol *Label,
4440b57cec5SDimitry Andric                                  int PointerSize) {
4450b57cec5SDimitry Andric   // emit the sequence to set the address
4465ffd83dbSDimitry Andric   OS.emitIntValue(dwarf::DW_LNS_extended_op, 1);
4475ffd83dbSDimitry Andric   OS.emitULEB128IntValue(PointerSize + 1);
4485ffd83dbSDimitry Andric   OS.emitIntValue(dwarf::DW_LNE_set_address, 1);
4495ffd83dbSDimitry Andric   OS.emitSymbolValue(Label, PointerSize);
4500b57cec5SDimitry Andric 
4510b57cec5SDimitry Andric   // emit the sequence for the LineDelta (from 1) and a zero address delta.
4520b57cec5SDimitry Andric   MCDwarfLineAddr::Emit(&OS, Params, LineDelta, 0);
4530b57cec5SDimitry Andric }
4540b57cec5SDimitry Andric 
4555ffd83dbSDimitry Andric void MCObjectStreamer::emitDwarfAdvanceLineAddr(int64_t LineDelta,
4560b57cec5SDimitry Andric                                                 const MCSymbol *LastLabel,
4570b57cec5SDimitry Andric                                                 const MCSymbol *Label,
4580b57cec5SDimitry Andric                                                 unsigned PointerSize) {
4590b57cec5SDimitry Andric   if (!LastLabel) {
4600b57cec5SDimitry Andric     emitDwarfSetLineAddr(*this, Assembler->getDWARFLinetableParams(), LineDelta,
4610b57cec5SDimitry Andric                          Label, PointerSize);
4620b57cec5SDimitry Andric     return;
4630b57cec5SDimitry Andric   }
46406c3fb27SDimitry Andric   const MCExpr *AddrDelta = buildSymbolDiff(*this, Label, LastLabel, SMLoc());
465*0fca6ea1SDimitry Andric   insert(getContext().allocFragment<MCDwarfLineAddrFragment>(LineDelta,
466*0fca6ea1SDimitry Andric                                                              *AddrDelta));
4670b57cec5SDimitry Andric }
4680b57cec5SDimitry Andric 
469fe6060f1SDimitry Andric void MCObjectStreamer::emitDwarfLineEndEntry(MCSection *Section,
470fe6060f1SDimitry Andric                                              MCSymbol *LastLabel) {
471fe6060f1SDimitry Andric   // Emit a DW_LNE_end_sequence for the end of the section.
472fe6060f1SDimitry Andric   // Use the section end label to compute the address delta and use INT64_MAX
473fe6060f1SDimitry Andric   // as the line delta which is the signal that this is actually a
474fe6060f1SDimitry Andric   // DW_LNE_end_sequence.
475fe6060f1SDimitry Andric   MCSymbol *SectionEnd = endSection(Section);
476fe6060f1SDimitry Andric 
477fe6060f1SDimitry Andric   // Switch back the dwarf line section, in case endSection had to switch the
478fe6060f1SDimitry Andric   // section.
479fe6060f1SDimitry Andric   MCContext &Ctx = getContext();
48081ad6265SDimitry Andric   switchSection(Ctx.getObjectFileInfo()->getDwarfLineSection());
481fe6060f1SDimitry Andric 
482fe6060f1SDimitry Andric   const MCAsmInfo *AsmInfo = Ctx.getAsmInfo();
483fe6060f1SDimitry Andric   emitDwarfAdvanceLineAddr(INT64_MAX, LastLabel, SectionEnd,
484fe6060f1SDimitry Andric                            AsmInfo->getCodePointerSize());
485fe6060f1SDimitry Andric }
486fe6060f1SDimitry Andric 
4875ffd83dbSDimitry Andric void MCObjectStreamer::emitDwarfAdvanceFrameAddr(const MCSymbol *LastLabel,
48806c3fb27SDimitry Andric                                                  const MCSymbol *Label,
48906c3fb27SDimitry Andric                                                  SMLoc Loc) {
49006c3fb27SDimitry Andric   const MCExpr *AddrDelta = buildSymbolDiff(*this, Label, LastLabel, Loc);
491*0fca6ea1SDimitry Andric   insert(getContext().allocFragment<MCDwarfCallFrameFragment>(*AddrDelta));
4920b57cec5SDimitry Andric }
4930b57cec5SDimitry Andric 
4945ffd83dbSDimitry Andric void MCObjectStreamer::emitCVLocDirective(unsigned FunctionId, unsigned FileNo,
4950b57cec5SDimitry Andric                                           unsigned Line, unsigned Column,
4960b57cec5SDimitry Andric                                           bool PrologueEnd, bool IsStmt,
4970b57cec5SDimitry Andric                                           StringRef FileName, SMLoc Loc) {
4980b57cec5SDimitry Andric   // Validate the directive.
4990b57cec5SDimitry Andric   if (!checkCVLocSection(FunctionId, FileNo, Loc))
5000b57cec5SDimitry Andric     return;
5010b57cec5SDimitry Andric 
5020b57cec5SDimitry Andric   // Emit a label at the current position and record it in the CodeViewContext.
5030b57cec5SDimitry Andric   MCSymbol *LineSym = getContext().createTempSymbol();
5045ffd83dbSDimitry Andric   emitLabel(LineSym);
5050b57cec5SDimitry Andric   getContext().getCVContext().recordCVLoc(getContext(), LineSym, FunctionId,
5060b57cec5SDimitry Andric                                           FileNo, Line, Column, PrologueEnd,
5070b57cec5SDimitry Andric                                           IsStmt);
5080b57cec5SDimitry Andric }
5090b57cec5SDimitry Andric 
5105ffd83dbSDimitry Andric void MCObjectStreamer::emitCVLinetableDirective(unsigned FunctionId,
5110b57cec5SDimitry Andric                                                 const MCSymbol *Begin,
5120b57cec5SDimitry Andric                                                 const MCSymbol *End) {
5130b57cec5SDimitry Andric   getContext().getCVContext().emitLineTableForFunction(*this, FunctionId, Begin,
5140b57cec5SDimitry Andric                                                        End);
5155ffd83dbSDimitry Andric   this->MCStreamer::emitCVLinetableDirective(FunctionId, Begin, End);
5160b57cec5SDimitry Andric }
5170b57cec5SDimitry Andric 
5185ffd83dbSDimitry Andric void MCObjectStreamer::emitCVInlineLinetableDirective(
5190b57cec5SDimitry Andric     unsigned PrimaryFunctionId, unsigned SourceFileId, unsigned SourceLineNum,
5200b57cec5SDimitry Andric     const MCSymbol *FnStartSym, const MCSymbol *FnEndSym) {
5210b57cec5SDimitry Andric   getContext().getCVContext().emitInlineLineTableForFunction(
5220b57cec5SDimitry Andric       *this, PrimaryFunctionId, SourceFileId, SourceLineNum, FnStartSym,
5230b57cec5SDimitry Andric       FnEndSym);
5245ffd83dbSDimitry Andric   this->MCStreamer::emitCVInlineLinetableDirective(
5250b57cec5SDimitry Andric       PrimaryFunctionId, SourceFileId, SourceLineNum, FnStartSym, FnEndSym);
5260b57cec5SDimitry Andric }
5270b57cec5SDimitry Andric 
5285ffd83dbSDimitry Andric void MCObjectStreamer::emitCVDefRangeDirective(
5290b57cec5SDimitry Andric     ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
5300b57cec5SDimitry Andric     StringRef FixedSizePortion) {
5310b57cec5SDimitry Andric   getContext().getCVContext().emitDefRange(*this, Ranges, FixedSizePortion);
5320b57cec5SDimitry Andric   // Attach labels that were pending before we created the defrange fragment to
5330b57cec5SDimitry Andric   // the beginning of the new fragment.
5345ffd83dbSDimitry Andric   this->MCStreamer::emitCVDefRangeDirective(Ranges, FixedSizePortion);
5350b57cec5SDimitry Andric }
5360b57cec5SDimitry Andric 
5375ffd83dbSDimitry Andric void MCObjectStreamer::emitCVStringTableDirective() {
5380b57cec5SDimitry Andric   getContext().getCVContext().emitStringTable(*this);
5390b57cec5SDimitry Andric }
5405ffd83dbSDimitry Andric void MCObjectStreamer::emitCVFileChecksumsDirective() {
5410b57cec5SDimitry Andric   getContext().getCVContext().emitFileChecksums(*this);
5420b57cec5SDimitry Andric }
5430b57cec5SDimitry Andric 
5445ffd83dbSDimitry Andric void MCObjectStreamer::emitCVFileChecksumOffsetDirective(unsigned FileNo) {
5450b57cec5SDimitry Andric   getContext().getCVContext().emitFileChecksumOffset(*this, FileNo);
5460b57cec5SDimitry Andric }
5470b57cec5SDimitry Andric 
5485ffd83dbSDimitry Andric void MCObjectStreamer::emitBytes(StringRef Data) {
549fe6060f1SDimitry Andric   MCDwarfLineEntry::make(this, getCurrentSectionOnly());
5500b57cec5SDimitry Andric   MCDataFragment *DF = getOrCreateDataFragment();
5510b57cec5SDimitry Andric   DF->getContents().append(Data.begin(), Data.end());
5520b57cec5SDimitry Andric }
5530b57cec5SDimitry Andric 
554bdd1243dSDimitry Andric void MCObjectStreamer::emitValueToAlignment(Align Alignment, int64_t Value,
5550b57cec5SDimitry Andric                                             unsigned ValueSize,
5560b57cec5SDimitry Andric                                             unsigned MaxBytesToEmit) {
5570b57cec5SDimitry Andric   if (MaxBytesToEmit == 0)
558bdd1243dSDimitry Andric     MaxBytesToEmit = Alignment.value();
559*0fca6ea1SDimitry Andric   insert(getContext().allocFragment<MCAlignFragment>(
560*0fca6ea1SDimitry Andric       Alignment, Value, ValueSize, MaxBytesToEmit));
5610b57cec5SDimitry Andric 
5620b57cec5SDimitry Andric   // Update the maximum alignment on the current section if necessary.
5630b57cec5SDimitry Andric   MCSection *CurSec = getCurrentSectionOnly();
564bdd1243dSDimitry Andric   CurSec->ensureMinAlignment(Alignment);
5650b57cec5SDimitry Andric }
5660b57cec5SDimitry Andric 
567bdd1243dSDimitry Andric void MCObjectStreamer::emitCodeAlignment(Align Alignment,
568349cc55cSDimitry Andric                                          const MCSubtargetInfo *STI,
5690b57cec5SDimitry Andric                                          unsigned MaxBytesToEmit) {
570bdd1243dSDimitry Andric   emitValueToAlignment(Alignment, 0, 1, MaxBytesToEmit);
571349cc55cSDimitry Andric   cast<MCAlignFragment>(getCurrentFragment())->setEmitNops(true, STI);
5720b57cec5SDimitry Andric }
5730b57cec5SDimitry Andric 
5740b57cec5SDimitry Andric void MCObjectStreamer::emitValueToOffset(const MCExpr *Offset,
5750b57cec5SDimitry Andric                                          unsigned char Value,
5760b57cec5SDimitry Andric                                          SMLoc Loc) {
577*0fca6ea1SDimitry Andric   insert(getContext().allocFragment<MCOrgFragment>(*Offset, Value, Loc));
5780b57cec5SDimitry Andric }
5790b57cec5SDimitry Andric 
5800b57cec5SDimitry Andric // Associate DTPRel32 fixup with data and resize data area
5815ffd83dbSDimitry Andric void MCObjectStreamer::emitDTPRel32Value(const MCExpr *Value) {
5820b57cec5SDimitry Andric   MCDataFragment *DF = getOrCreateDataFragment();
5830b57cec5SDimitry Andric   DF->getFixups().push_back(MCFixup::create(DF->getContents().size(),
5840b57cec5SDimitry Andric                                             Value, FK_DTPRel_4));
5850b57cec5SDimitry Andric   DF->getContents().resize(DF->getContents().size() + 4, 0);
5860b57cec5SDimitry Andric }
5870b57cec5SDimitry Andric 
5880b57cec5SDimitry Andric // Associate DTPRel64 fixup with data and resize data area
5895ffd83dbSDimitry Andric void MCObjectStreamer::emitDTPRel64Value(const MCExpr *Value) {
5900b57cec5SDimitry Andric   MCDataFragment *DF = getOrCreateDataFragment();
5910b57cec5SDimitry Andric   DF->getFixups().push_back(MCFixup::create(DF->getContents().size(),
5920b57cec5SDimitry Andric                                             Value, FK_DTPRel_8));
5930b57cec5SDimitry Andric   DF->getContents().resize(DF->getContents().size() + 8, 0);
5940b57cec5SDimitry Andric }
5950b57cec5SDimitry Andric 
5960b57cec5SDimitry Andric // Associate TPRel32 fixup with data and resize data area
5975ffd83dbSDimitry Andric void MCObjectStreamer::emitTPRel32Value(const MCExpr *Value) {
5980b57cec5SDimitry Andric   MCDataFragment *DF = getOrCreateDataFragment();
5990b57cec5SDimitry Andric   DF->getFixups().push_back(MCFixup::create(DF->getContents().size(),
6000b57cec5SDimitry Andric                                             Value, FK_TPRel_4));
6010b57cec5SDimitry Andric   DF->getContents().resize(DF->getContents().size() + 4, 0);
6020b57cec5SDimitry Andric }
6030b57cec5SDimitry Andric 
6040b57cec5SDimitry Andric // Associate TPRel64 fixup with data and resize data area
6055ffd83dbSDimitry Andric void MCObjectStreamer::emitTPRel64Value(const MCExpr *Value) {
6060b57cec5SDimitry Andric   MCDataFragment *DF = getOrCreateDataFragment();
6070b57cec5SDimitry Andric   DF->getFixups().push_back(MCFixup::create(DF->getContents().size(),
6080b57cec5SDimitry Andric                                             Value, FK_TPRel_8));
6090b57cec5SDimitry Andric   DF->getContents().resize(DF->getContents().size() + 8, 0);
6100b57cec5SDimitry Andric }
6110b57cec5SDimitry Andric 
6120b57cec5SDimitry Andric // Associate GPRel32 fixup with data and resize data area
6135ffd83dbSDimitry Andric void MCObjectStreamer::emitGPRel32Value(const MCExpr *Value) {
6140b57cec5SDimitry Andric   MCDataFragment *DF = getOrCreateDataFragment();
6150b57cec5SDimitry Andric   DF->getFixups().push_back(
6160b57cec5SDimitry Andric       MCFixup::create(DF->getContents().size(), Value, FK_GPRel_4));
6170b57cec5SDimitry Andric   DF->getContents().resize(DF->getContents().size() + 4, 0);
6180b57cec5SDimitry Andric }
6190b57cec5SDimitry Andric 
6200b57cec5SDimitry Andric // Associate GPRel64 fixup with data and resize data area
6215ffd83dbSDimitry Andric void MCObjectStreamer::emitGPRel64Value(const MCExpr *Value) {
6220b57cec5SDimitry Andric   MCDataFragment *DF = getOrCreateDataFragment();
6230b57cec5SDimitry Andric   DF->getFixups().push_back(
6240b57cec5SDimitry Andric       MCFixup::create(DF->getContents().size(), Value, FK_GPRel_4));
6250b57cec5SDimitry Andric   DF->getContents().resize(DF->getContents().size() + 8, 0);
6260b57cec5SDimitry Andric }
6270b57cec5SDimitry Andric 
628bdd1243dSDimitry Andric static std::optional<std::pair<bool, std::string>>
629e8d8bef9SDimitry Andric getOffsetAndDataFragment(const MCSymbol &Symbol, uint32_t &RelocOffset,
630e8d8bef9SDimitry Andric                          MCDataFragment *&DF) {
631e8d8bef9SDimitry Andric   if (Symbol.isVariable()) {
632e8d8bef9SDimitry Andric     const MCExpr *SymbolExpr = Symbol.getVariableValue();
633e8d8bef9SDimitry Andric     MCValue OffsetVal;
634e8d8bef9SDimitry Andric     if(!SymbolExpr->evaluateAsRelocatable(OffsetVal, nullptr, nullptr))
635e8d8bef9SDimitry Andric       return std::make_pair(false,
636e8d8bef9SDimitry Andric                             std::string("symbol in .reloc offset is not "
637e8d8bef9SDimitry Andric                                         "relocatable"));
638e8d8bef9SDimitry Andric     if (OffsetVal.isAbsolute()) {
639e8d8bef9SDimitry Andric       RelocOffset = OffsetVal.getConstant();
640e8d8bef9SDimitry Andric       MCFragment *Fragment = Symbol.getFragment();
641e8d8bef9SDimitry Andric       // FIXME Support symbols with no DF. For example:
642e8d8bef9SDimitry Andric       // .reloc .data, ENUM_VALUE, <some expr>
643e8d8bef9SDimitry Andric       if (!Fragment || Fragment->getKind() != MCFragment::FT_Data)
644e8d8bef9SDimitry Andric         return std::make_pair(false,
645e8d8bef9SDimitry Andric                               std::string("symbol in offset has no data "
646e8d8bef9SDimitry Andric                                           "fragment"));
647e8d8bef9SDimitry Andric       DF = cast<MCDataFragment>(Fragment);
648bdd1243dSDimitry Andric       return std::nullopt;
649e8d8bef9SDimitry Andric     }
650e8d8bef9SDimitry Andric 
651e8d8bef9SDimitry Andric     if (OffsetVal.getSymB())
652e8d8bef9SDimitry Andric       return std::make_pair(false,
653e8d8bef9SDimitry Andric                             std::string(".reloc symbol offset is not "
654e8d8bef9SDimitry Andric                                         "representable"));
655e8d8bef9SDimitry Andric 
656e8d8bef9SDimitry Andric     const MCSymbolRefExpr &SRE = cast<MCSymbolRefExpr>(*OffsetVal.getSymA());
657e8d8bef9SDimitry Andric     if (!SRE.getSymbol().isDefined())
658e8d8bef9SDimitry Andric       return std::make_pair(false,
659e8d8bef9SDimitry Andric                             std::string("symbol used in the .reloc offset is "
660e8d8bef9SDimitry Andric                                         "not defined"));
661e8d8bef9SDimitry Andric 
662e8d8bef9SDimitry Andric     if (SRE.getSymbol().isVariable())
663e8d8bef9SDimitry Andric       return std::make_pair(false,
664e8d8bef9SDimitry Andric                             std::string("symbol used in the .reloc offset is "
665e8d8bef9SDimitry Andric                                         "variable"));
666e8d8bef9SDimitry Andric 
667e8d8bef9SDimitry Andric     MCFragment *Fragment = SRE.getSymbol().getFragment();
668e8d8bef9SDimitry Andric     // FIXME Support symbols with no DF. For example:
669e8d8bef9SDimitry Andric     // .reloc .data, ENUM_VALUE, <some expr>
670e8d8bef9SDimitry Andric     if (!Fragment || Fragment->getKind() != MCFragment::FT_Data)
671e8d8bef9SDimitry Andric       return std::make_pair(false,
672e8d8bef9SDimitry Andric                             std::string("symbol in offset has no data "
673e8d8bef9SDimitry Andric                                         "fragment"));
674e8d8bef9SDimitry Andric     RelocOffset = SRE.getSymbol().getOffset() + OffsetVal.getConstant();
675e8d8bef9SDimitry Andric     DF = cast<MCDataFragment>(Fragment);
676e8d8bef9SDimitry Andric   } else {
677e8d8bef9SDimitry Andric     RelocOffset = Symbol.getOffset();
678e8d8bef9SDimitry Andric     MCFragment *Fragment = Symbol.getFragment();
679e8d8bef9SDimitry Andric     // FIXME Support symbols with no DF. For example:
680e8d8bef9SDimitry Andric     // .reloc .data, ENUM_VALUE, <some expr>
681e8d8bef9SDimitry Andric     if (!Fragment || Fragment->getKind() != MCFragment::FT_Data)
682e8d8bef9SDimitry Andric       return std::make_pair(false,
683e8d8bef9SDimitry Andric                             std::string("symbol in offset has no data "
684e8d8bef9SDimitry Andric                                         "fragment"));
685e8d8bef9SDimitry Andric     DF = cast<MCDataFragment>(Fragment);
686e8d8bef9SDimitry Andric   }
687bdd1243dSDimitry Andric   return std::nullopt;
688e8d8bef9SDimitry Andric }
689e8d8bef9SDimitry Andric 
690bdd1243dSDimitry Andric std::optional<std::pair<bool, std::string>>
6915ffd83dbSDimitry Andric MCObjectStreamer::emitRelocDirective(const MCExpr &Offset, StringRef Name,
6920b57cec5SDimitry Andric                                      const MCExpr *Expr, SMLoc Loc,
6930b57cec5SDimitry Andric                                      const MCSubtargetInfo &STI) {
694bdd1243dSDimitry Andric   std::optional<MCFixupKind> MaybeKind =
695bdd1243dSDimitry Andric       Assembler->getBackend().getFixupKind(Name);
69681ad6265SDimitry Andric   if (!MaybeKind)
6975ffd83dbSDimitry Andric     return std::make_pair(true, std::string("unknown relocation name"));
6980b57cec5SDimitry Andric 
6990b57cec5SDimitry Andric   MCFixupKind Kind = *MaybeKind;
7005f757f3fSDimitry Andric   if (Expr)
7015f757f3fSDimitry Andric     visitUsedExpr(*Expr);
7025f757f3fSDimitry Andric   else
7030b57cec5SDimitry Andric     Expr =
7040b57cec5SDimitry Andric         MCSymbolRefExpr::create(getContext().createTempSymbol(), getContext());
7050b57cec5SDimitry Andric 
7060b57cec5SDimitry Andric   MCDataFragment *DF = getOrCreateDataFragment(&STI);
7075ffd83dbSDimitry Andric   MCValue OffsetVal;
7085ffd83dbSDimitry Andric   if (!Offset.evaluateAsRelocatable(OffsetVal, nullptr, nullptr))
7095ffd83dbSDimitry Andric     return std::make_pair(false,
7105ffd83dbSDimitry Andric                           std::string(".reloc offset is not relocatable"));
7115ffd83dbSDimitry Andric   if (OffsetVal.isAbsolute()) {
7125ffd83dbSDimitry Andric     if (OffsetVal.getConstant() < 0)
7135ffd83dbSDimitry Andric       return std::make_pair(false, std::string(".reloc offset is negative"));
7145ffd83dbSDimitry Andric     DF->getFixups().push_back(
7155ffd83dbSDimitry Andric         MCFixup::create(OffsetVal.getConstant(), Expr, Kind, Loc));
716bdd1243dSDimitry Andric     return std::nullopt;
7170b57cec5SDimitry Andric   }
7185ffd83dbSDimitry Andric   if (OffsetVal.getSymB())
7195ffd83dbSDimitry Andric     return std::make_pair(false,
7205ffd83dbSDimitry Andric                           std::string(".reloc offset is not representable"));
7210b57cec5SDimitry Andric 
7225ffd83dbSDimitry Andric   const MCSymbolRefExpr &SRE = cast<MCSymbolRefExpr>(*OffsetVal.getSymA());
723e8d8bef9SDimitry Andric   const MCSymbol &Symbol = SRE.getSymbol();
724e8d8bef9SDimitry Andric   if (Symbol.isDefined()) {
725e8d8bef9SDimitry Andric     uint32_t SymbolOffset = 0;
726bdd1243dSDimitry Andric     std::optional<std::pair<bool, std::string>> Error =
727bdd1243dSDimitry Andric         getOffsetAndDataFragment(Symbol, SymbolOffset, DF);
728e8d8bef9SDimitry Andric 
729bdd1243dSDimitry Andric     if (Error != std::nullopt)
730e8d8bef9SDimitry Andric       return Error;
731e8d8bef9SDimitry Andric 
7325ffd83dbSDimitry Andric     DF->getFixups().push_back(
733e8d8bef9SDimitry Andric         MCFixup::create(SymbolOffset + OffsetVal.getConstant(),
7340b57cec5SDimitry Andric                         Expr, Kind, Loc));
735bdd1243dSDimitry Andric     return std::nullopt;
7360b57cec5SDimitry Andric   }
7370b57cec5SDimitry Andric 
73804eeddc0SDimitry Andric   PendingFixups.emplace_back(
73904eeddc0SDimitry Andric       &SRE.getSymbol(), DF,
74004eeddc0SDimitry Andric       MCFixup::create(OffsetVal.getConstant(), Expr, Kind, Loc));
741bdd1243dSDimitry Andric   return std::nullopt;
7420b57cec5SDimitry Andric }
7430b57cec5SDimitry Andric 
7440b57cec5SDimitry Andric void MCObjectStreamer::emitFill(const MCExpr &NumBytes, uint64_t FillValue,
7450b57cec5SDimitry Andric                                 SMLoc Loc) {
7460b57cec5SDimitry Andric   assert(getCurrentSectionOnly() && "need a section");
747*0fca6ea1SDimitry Andric   insert(
748*0fca6ea1SDimitry Andric       getContext().allocFragment<MCFillFragment>(FillValue, 1, NumBytes, Loc));
7490b57cec5SDimitry Andric }
7500b57cec5SDimitry Andric 
7510b57cec5SDimitry Andric void MCObjectStreamer::emitFill(const MCExpr &NumValues, int64_t Size,
7520b57cec5SDimitry Andric                                 int64_t Expr, SMLoc Loc) {
7530b57cec5SDimitry Andric   int64_t IntNumValues;
7540b57cec5SDimitry Andric   // Do additional checking now if we can resolve the value.
7550b57cec5SDimitry Andric   if (NumValues.evaluateAsAbsolute(IntNumValues, getAssemblerPtr())) {
7560b57cec5SDimitry Andric     if (IntNumValues < 0) {
7570b57cec5SDimitry Andric       getContext().getSourceManager()->PrintMessage(
7580b57cec5SDimitry Andric           Loc, SourceMgr::DK_Warning,
7590b57cec5SDimitry Andric           "'.fill' directive with negative repeat count has no effect");
7600b57cec5SDimitry Andric       return;
7610b57cec5SDimitry Andric     }
7620b57cec5SDimitry Andric     // Emit now if we can for better errors.
7630b57cec5SDimitry Andric     int64_t NonZeroSize = Size > 4 ? 4 : Size;
7640b57cec5SDimitry Andric     Expr &= ~0ULL >> (64 - NonZeroSize * 8);
7650b57cec5SDimitry Andric     for (uint64_t i = 0, e = IntNumValues; i != e; ++i) {
7665ffd83dbSDimitry Andric       emitIntValue(Expr, NonZeroSize);
7670b57cec5SDimitry Andric       if (NonZeroSize < Size)
7685ffd83dbSDimitry Andric         emitIntValue(0, Size - NonZeroSize);
7690b57cec5SDimitry Andric     }
7700b57cec5SDimitry Andric     return;
7710b57cec5SDimitry Andric   }
7720b57cec5SDimitry Andric 
7730b57cec5SDimitry Andric   // Otherwise emit as fragment.
7740b57cec5SDimitry Andric   assert(getCurrentSectionOnly() && "need a section");
775*0fca6ea1SDimitry Andric   insert(
776*0fca6ea1SDimitry Andric       getContext().allocFragment<MCFillFragment>(Expr, Size, NumValues, Loc));
7770b57cec5SDimitry Andric }
7780b57cec5SDimitry Andric 
779e8d8bef9SDimitry Andric void MCObjectStreamer::emitNops(int64_t NumBytes, int64_t ControlledNopLength,
780349cc55cSDimitry Andric                                 SMLoc Loc, const MCSubtargetInfo &STI) {
781e8d8bef9SDimitry Andric   assert(getCurrentSectionOnly() && "need a section");
782*0fca6ea1SDimitry Andric   insert(getContext().allocFragment<MCNopsFragment>(
783*0fca6ea1SDimitry Andric       NumBytes, ControlledNopLength, Loc, STI));
784e8d8bef9SDimitry Andric }
785e8d8bef9SDimitry Andric 
7865ffd83dbSDimitry Andric void MCObjectStreamer::emitFileDirective(StringRef Filename) {
787*0fca6ea1SDimitry Andric   MCAssembler &Asm = getAssembler();
788*0fca6ea1SDimitry Andric   Asm.getWriter().addFileName(Asm, Filename);
7890b57cec5SDimitry Andric }
7900b57cec5SDimitry Andric 
791fe6060f1SDimitry Andric void MCObjectStreamer::emitFileDirective(StringRef Filename,
792*0fca6ea1SDimitry Andric                                          StringRef CompilerVersion,
793fe6060f1SDimitry Andric                                          StringRef TimeStamp,
794fe6060f1SDimitry Andric                                          StringRef Description) {
795*0fca6ea1SDimitry Andric   MCObjectWriter &W = getAssembler().getWriter();
796*0fca6ea1SDimitry Andric   W.addFileName(getAssembler(), Filename);
797*0fca6ea1SDimitry Andric   if (CompilerVersion.size())
798*0fca6ea1SDimitry Andric     W.setCompilerVersion(CompilerVersion);
799*0fca6ea1SDimitry Andric   // TODO: add TimeStamp and Description to .file symbol table entry
800*0fca6ea1SDimitry Andric   // with the integrated assembler.
801fe6060f1SDimitry Andric }
802fe6060f1SDimitry Andric 
8035ffd83dbSDimitry Andric void MCObjectStreamer::emitAddrsig() {
8040b57cec5SDimitry Andric   getAssembler().getWriter().emitAddrsigSection();
8050b57cec5SDimitry Andric }
8060b57cec5SDimitry Andric 
8075ffd83dbSDimitry Andric void MCObjectStreamer::emitAddrsigSym(const MCSymbol *Sym) {
8080b57cec5SDimitry Andric   getAssembler().getWriter().addAddrsigSymbol(Sym);
8090b57cec5SDimitry Andric }
8100b57cec5SDimitry Andric 
8115ffd83dbSDimitry Andric void MCObjectStreamer::finishImpl() {
8120b57cec5SDimitry Andric   getContext().RemapDebugPaths();
8130b57cec5SDimitry Andric 
8140b57cec5SDimitry Andric   // If we are generating dwarf for assembly source files dump out the sections.
8150b57cec5SDimitry Andric   if (getContext().getGenDwarfForAssembly())
8160b57cec5SDimitry Andric     MCGenDwarfInfo::Emit(this);
8170b57cec5SDimitry Andric 
8180b57cec5SDimitry Andric   // Dump out the dwarf file & directory tables and line tables.
819fe6060f1SDimitry Andric   MCDwarfLineTable::emit(this, getAssembler().getDWARFLinetableParams());
8200b57cec5SDimitry Andric 
821e8d8bef9SDimitry Andric   // Emit pseudo probes for the current module.
822e8d8bef9SDimitry Andric   MCPseudoProbeTable::emit(this);
823e8d8bef9SDimitry Andric 
8240b57cec5SDimitry Andric   resolvePendingFixups();
8250b57cec5SDimitry Andric   getAssembler().Finish();
8260b57cec5SDimitry Andric }
827