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