123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936 |
- //===- lib/MC/MCObjectStreamer.cpp - Object File MCStreamer Interface -----===//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- #include "llvm/MC/MCObjectStreamer.h"
- #include "llvm/MC/MCAsmBackend.h"
- #include "llvm/MC/MCAsmInfo.h"
- #include "llvm/MC/MCAssembler.h"
- #include "llvm/MC/MCCodeEmitter.h"
- #include "llvm/MC/MCCodeView.h"
- #include "llvm/MC/MCContext.h"
- #include "llvm/MC/MCDwarf.h"
- #include "llvm/MC/MCExpr.h"
- #include "llvm/MC/MCObjectFileInfo.h"
- #include "llvm/MC/MCObjectWriter.h"
- #include "llvm/MC/MCSection.h"
- #include "llvm/MC/MCSymbol.h"
- #include "llvm/MC/MCValue.h"
- #include "llvm/Support/ErrorHandling.h"
- #include "llvm/Support/SourceMgr.h"
- using namespace llvm;
- MCObjectStreamer::MCObjectStreamer(MCContext &Context,
- std::unique_ptr<MCAsmBackend> TAB,
- std::unique_ptr<MCObjectWriter> OW,
- std::unique_ptr<MCCodeEmitter> Emitter)
- : MCStreamer(Context),
- Assembler(std::make_unique<MCAssembler>(
- Context, std::move(TAB), std::move(Emitter), std::move(OW))),
- EmitEHFrame(true), EmitDebugFrame(false) {
- if (Assembler->getBackendPtr())
- setAllowAutoPadding(Assembler->getBackend().allowAutoPadding());
- }
- MCObjectStreamer::~MCObjectStreamer() = default;
- // AssemblerPtr is used for evaluation of expressions and causes
- // difference between asm and object outputs. Return nullptr to in
- // inline asm mode to limit divergence to assembly inputs.
- MCAssembler *MCObjectStreamer::getAssemblerPtr() {
- if (getUseAssemblerInfoForParsing())
- return Assembler.get();
- return nullptr;
- }
- void MCObjectStreamer::addPendingLabel(MCSymbol* S) {
- MCSection *CurSection = getCurrentSectionOnly();
- if (CurSection) {
- // Register labels that have not yet been assigned to a Section.
- if (!PendingLabels.empty()) {
- for (MCSymbol* Sym : PendingLabels)
- CurSection->addPendingLabel(Sym);
- PendingLabels.clear();
- }
- // Add this label to the current Section / Subsection.
- CurSection->addPendingLabel(S, CurSubsectionIdx);
- // Add this Section to the list of PendingLabelSections.
- PendingLabelSections.insert(CurSection);
- } else
- // There is no Section / Subsection for this label yet.
- PendingLabels.push_back(S);
- }
- void MCObjectStreamer::flushPendingLabels(MCFragment *F, uint64_t FOffset) {
- MCSection *CurSection = getCurrentSectionOnly();
- if (!CurSection) {
- assert(PendingLabels.empty());
- return;
- }
- // Register labels that have not yet been assigned to a Section.
- if (!PendingLabels.empty()) {
- for (MCSymbol* Sym : PendingLabels)
- CurSection->addPendingLabel(Sym, CurSubsectionIdx);
- PendingLabels.clear();
- }
- // Associate a fragment with this label, either the supplied fragment
- // or an empty data fragment.
- if (F)
- CurSection->flushPendingLabels(F, FOffset, CurSubsectionIdx);
- else
- CurSection->flushPendingLabels(nullptr, 0, CurSubsectionIdx);
- }
- void MCObjectStreamer::flushPendingLabels() {
- // Register labels that have not yet been assigned to a Section.
- if (!PendingLabels.empty()) {
- MCSection *CurSection = getCurrentSectionOnly();
- assert(CurSection);
- for (MCSymbol* Sym : PendingLabels)
- CurSection->addPendingLabel(Sym, CurSubsectionIdx);
- PendingLabels.clear();
- }
- // Assign an empty data fragment to all remaining pending labels.
- for (MCSection* Section : PendingLabelSections)
- Section->flushPendingLabels();
- }
- // When fixup's offset is a forward declared label, e.g.:
- //
- // .reloc 1f, R_MIPS_JALR, foo
- // 1: nop
- //
- // postpone adding it to Fixups vector until the label is defined and its offset
- // is known.
- void MCObjectStreamer::resolvePendingFixups() {
- for (PendingMCFixup &PendingFixup : PendingFixups) {
- if (!PendingFixup.Sym || PendingFixup.Sym->isUndefined ()) {
- getContext().reportError(PendingFixup.Fixup.getLoc(),
- "unresolved relocation offset");
- continue;
- }
- flushPendingLabels(PendingFixup.DF, PendingFixup.DF->getContents().size());
- PendingFixup.Fixup.setOffset(PendingFixup.Sym->getOffset() +
- PendingFixup.Fixup.getOffset());
- // If the location symbol to relocate is in MCEncodedFragmentWithFixups,
- // put the Fixup into location symbol's fragment. Otherwise
- // put into PendingFixup.DF
- MCFragment *SymFragment = PendingFixup.Sym->getFragment();
- switch (SymFragment->getKind()) {
- case MCFragment::FT_Relaxable:
- case MCFragment::FT_Dwarf:
- case MCFragment::FT_PseudoProbe:
- cast<MCEncodedFragmentWithFixups<8, 1>>(SymFragment)
- ->getFixups()
- .push_back(PendingFixup.Fixup);
- break;
- case MCFragment::FT_Data:
- case MCFragment::FT_CVDefRange:
- cast<MCEncodedFragmentWithFixups<32, 4>>(SymFragment)
- ->getFixups()
- .push_back(PendingFixup.Fixup);
- break;
- default:
- PendingFixup.DF->getFixups().push_back(PendingFixup.Fixup);
- break;
- }
- }
- PendingFixups.clear();
- }
- // As a compile-time optimization, avoid allocating and evaluating an MCExpr
- // tree for (Hi - Lo) when Hi and Lo are offsets into the same fragment.
- static std::optional<uint64_t> absoluteSymbolDiff(const MCSymbol *Hi,
- const MCSymbol *Lo) {
- assert(Hi && Lo);
- if (!Hi->getFragment() || Hi->getFragment() != Lo->getFragment() ||
- Hi->isVariable() || Lo->isVariable())
- return std::nullopt;
- return Hi->getOffset() - Lo->getOffset();
- }
- void MCObjectStreamer::emitAbsoluteSymbolDiff(const MCSymbol *Hi,
- const MCSymbol *Lo,
- unsigned Size) {
- if (!getAssembler().getContext().getTargetTriple().isRISCV())
- if (std::optional<uint64_t> Diff = absoluteSymbolDiff(Hi, Lo))
- return emitIntValue(*Diff, Size);
- MCStreamer::emitAbsoluteSymbolDiff(Hi, Lo, Size);
- }
- void MCObjectStreamer::emitAbsoluteSymbolDiffAsULEB128(const MCSymbol *Hi,
- const MCSymbol *Lo) {
- if (!getAssembler().getContext().getTargetTriple().isRISCV())
- if (std::optional<uint64_t> Diff = absoluteSymbolDiff(Hi, Lo)) {
- emitULEB128IntValue(*Diff);
- return;
- }
- MCStreamer::emitAbsoluteSymbolDiffAsULEB128(Hi, Lo);
- }
- void MCObjectStreamer::reset() {
- if (Assembler)
- Assembler->reset();
- CurInsertionPoint = MCSection::iterator();
- EmitEHFrame = true;
- EmitDebugFrame = false;
- PendingLabels.clear();
- PendingLabelSections.clear();
- MCStreamer::reset();
- }
- void MCObjectStreamer::emitFrames(MCAsmBackend *MAB) {
- if (!getNumFrameInfos())
- return;
- if (EmitEHFrame)
- MCDwarfFrameEmitter::Emit(*this, MAB, true);
- if (EmitDebugFrame)
- MCDwarfFrameEmitter::Emit(*this, MAB, false);
- }
- MCFragment *MCObjectStreamer::getCurrentFragment() const {
- assert(getCurrentSectionOnly() && "No current section!");
- if (CurInsertionPoint != getCurrentSectionOnly()->getFragmentList().begin())
- return &*std::prev(CurInsertionPoint);
- return nullptr;
- }
- static bool canReuseDataFragment(const MCDataFragment &F,
- const MCAssembler &Assembler,
- const MCSubtargetInfo *STI) {
- if (!F.hasInstructions())
- return true;
- // When bundling is enabled, we don't want to add data to a fragment that
- // already has instructions (see MCELFStreamer::emitInstToData for details)
- if (Assembler.isBundlingEnabled())
- return Assembler.getRelaxAll();
- // If the subtarget is changed mid fragment we start a new fragment to record
- // the new STI.
- return !STI || F.getSubtargetInfo() == STI;
- }
- MCDataFragment *
- MCObjectStreamer::getOrCreateDataFragment(const MCSubtargetInfo *STI) {
- MCDataFragment *F = dyn_cast_or_null<MCDataFragment>(getCurrentFragment());
- if (!F || !canReuseDataFragment(*F, *Assembler, STI)) {
- F = new MCDataFragment();
- insert(F);
- }
- return F;
- }
- void MCObjectStreamer::visitUsedSymbol(const MCSymbol &Sym) {
- Assembler->registerSymbol(Sym);
- }
- void MCObjectStreamer::emitCFISections(bool EH, bool Debug) {
- MCStreamer::emitCFISections(EH, Debug);
- EmitEHFrame = EH;
- EmitDebugFrame = Debug;
- }
- void MCObjectStreamer::emitValueImpl(const MCExpr *Value, unsigned Size,
- SMLoc Loc) {
- MCStreamer::emitValueImpl(Value, Size, Loc);
- MCDataFragment *DF = getOrCreateDataFragment();
- flushPendingLabels(DF, DF->getContents().size());
- MCDwarfLineEntry::make(this, getCurrentSectionOnly());
- // Avoid fixups when possible.
- int64_t AbsValue;
- if (Value->evaluateAsAbsolute(AbsValue, getAssemblerPtr())) {
- if (!isUIntN(8 * Size, AbsValue) && !isIntN(8 * Size, AbsValue)) {
- getContext().reportError(
- Loc, "value evaluated as " + Twine(AbsValue) + " is out of range.");
- return;
- }
- emitIntValue(AbsValue, Size);
- return;
- }
- DF->getFixups().push_back(
- MCFixup::create(DF->getContents().size(), Value,
- MCFixup::getKindForSize(Size, false), Loc));
- DF->getContents().resize(DF->getContents().size() + Size, 0);
- }
- MCSymbol *MCObjectStreamer::emitCFILabel() {
- MCSymbol *Label = getContext().createTempSymbol("cfi");
- emitLabel(Label);
- return Label;
- }
- void MCObjectStreamer::emitCFIStartProcImpl(MCDwarfFrameInfo &Frame) {
- // We need to create a local symbol to avoid relocations.
- Frame.Begin = getContext().createTempSymbol();
- emitLabel(Frame.Begin);
- }
- void MCObjectStreamer::emitCFIEndProcImpl(MCDwarfFrameInfo &Frame) {
- Frame.End = getContext().createTempSymbol();
- emitLabel(Frame.End);
- }
- void MCObjectStreamer::emitLabel(MCSymbol *Symbol, SMLoc Loc) {
- MCStreamer::emitLabel(Symbol, Loc);
- getAssembler().registerSymbol(*Symbol);
- // If there is a current fragment, mark the symbol as pointing into it.
- // Otherwise queue the label and set its fragment pointer when we emit the
- // next fragment.
- auto *F = dyn_cast_or_null<MCDataFragment>(getCurrentFragment());
- if (F && !(getAssembler().isBundlingEnabled() &&
- getAssembler().getRelaxAll())) {
- Symbol->setFragment(F);
- Symbol->setOffset(F->getContents().size());
- } else {
- // Assign all pending labels to offset 0 within the dummy "pending"
- // fragment. (They will all be reassigned to a real fragment in
- // flushPendingLabels())
- Symbol->setOffset(0);
- addPendingLabel(Symbol);
- }
- emitPendingAssignments(Symbol);
- }
- void MCObjectStreamer::emitPendingAssignments(MCSymbol *Symbol) {
- auto Assignments = pendingAssignments.find(Symbol);
- if (Assignments != pendingAssignments.end()) {
- for (const PendingAssignment &A : Assignments->second)
- emitAssignment(A.Symbol, A.Value);
- pendingAssignments.erase(Assignments);
- }
- }
- // Emit a label at a previously emitted fragment/offset position. This must be
- // within the currently-active section.
- void MCObjectStreamer::emitLabelAtPos(MCSymbol *Symbol, SMLoc Loc,
- MCFragment *F, uint64_t Offset) {
- assert(F->getParent() == getCurrentSectionOnly());
- MCStreamer::emitLabel(Symbol, Loc);
- getAssembler().registerSymbol(*Symbol);
- auto *DF = dyn_cast_or_null<MCDataFragment>(F);
- Symbol->setOffset(Offset);
- if (DF) {
- Symbol->setFragment(F);
- } else {
- assert(isa<MCDummyFragment>(F) &&
- "F must either be an MCDataFragment or the pending MCDummyFragment");
- assert(Offset == 0);
- addPendingLabel(Symbol);
- }
- }
- void MCObjectStreamer::emitULEB128Value(const MCExpr *Value) {
- int64_t IntValue;
- if (Value->evaluateAsAbsolute(IntValue, getAssemblerPtr())) {
- emitULEB128IntValue(IntValue);
- return;
- }
- insert(new MCLEBFragment(*Value, false));
- }
- void MCObjectStreamer::emitSLEB128Value(const MCExpr *Value) {
- int64_t IntValue;
- if (Value->evaluateAsAbsolute(IntValue, getAssemblerPtr())) {
- emitSLEB128IntValue(IntValue);
- return;
- }
- insert(new MCLEBFragment(*Value, true));
- }
- void MCObjectStreamer::emitWeakReference(MCSymbol *Alias,
- const MCSymbol *Symbol) {
- report_fatal_error("This file format doesn't support weak aliases.");
- }
- void MCObjectStreamer::changeSection(MCSection *Section,
- const MCExpr *Subsection) {
- changeSectionImpl(Section, Subsection);
- }
- bool MCObjectStreamer::changeSectionImpl(MCSection *Section,
- const MCExpr *Subsection) {
- assert(Section && "Cannot switch to a null section!");
- getContext().clearDwarfLocSeen();
- bool Created = getAssembler().registerSection(*Section);
- int64_t IntSubsection = 0;
- if (Subsection &&
- !Subsection->evaluateAsAbsolute(IntSubsection, getAssemblerPtr()))
- report_fatal_error("Cannot evaluate subsection number");
- if (IntSubsection < 0 || IntSubsection > 8192)
- report_fatal_error("Subsection number out of range");
- CurSubsectionIdx = unsigned(IntSubsection);
- CurInsertionPoint =
- Section->getSubsectionInsertionPoint(CurSubsectionIdx);
- return Created;
- }
- void MCObjectStreamer::emitAssignment(MCSymbol *Symbol, const MCExpr *Value) {
- getAssembler().registerSymbol(*Symbol);
- MCStreamer::emitAssignment(Symbol, Value);
- emitPendingAssignments(Symbol);
- }
- void MCObjectStreamer::emitConditionalAssignment(MCSymbol *Symbol,
- const MCExpr *Value) {
- const MCSymbol *Target = &cast<MCSymbolRefExpr>(*Value).getSymbol();
- // If the symbol already exists, emit the assignment. Otherwise, emit it
- // later only if the symbol is also emitted.
- if (Target->isRegistered())
- emitAssignment(Symbol, Value);
- else
- pendingAssignments[Target].push_back({Symbol, Value});
- }
- bool MCObjectStreamer::mayHaveInstructions(MCSection &Sec) const {
- return Sec.hasInstructions();
- }
- void MCObjectStreamer::emitInstruction(const MCInst &Inst,
- const MCSubtargetInfo &STI) {
- const MCSection &Sec = *getCurrentSectionOnly();
- if (Sec.isVirtualSection()) {
- getContext().reportError(Inst.getLoc(), Twine(Sec.getVirtualSectionKind()) +
- " section '" + Sec.getName() +
- "' cannot have instructions");
- return;
- }
- getAssembler().getBackend().emitInstructionBegin(*this, Inst, STI);
- emitInstructionImpl(Inst, STI);
- getAssembler().getBackend().emitInstructionEnd(*this, Inst);
- }
- void MCObjectStreamer::emitInstructionImpl(const MCInst &Inst,
- const MCSubtargetInfo &STI) {
- MCStreamer::emitInstruction(Inst, STI);
- MCSection *Sec = getCurrentSectionOnly();
- Sec->setHasInstructions(true);
- // Now that a machine instruction has been assembled into this section, make
- // a line entry for any .loc directive that has been seen.
- MCDwarfLineEntry::make(this, getCurrentSectionOnly());
- // If this instruction doesn't need relaxation, just emit it as data.
- MCAssembler &Assembler = getAssembler();
- MCAsmBackend &Backend = Assembler.getBackend();
- if (!(Backend.mayNeedRelaxation(Inst, STI) ||
- Backend.allowEnhancedRelaxation())) {
- emitInstToData(Inst, STI);
- return;
- }
- // Otherwise, relax and emit it as data if either:
- // - The RelaxAll flag was passed
- // - Bundling is enabled and this instruction is inside a bundle-locked
- // group. We want to emit all such instructions into the same data
- // fragment.
- if (Assembler.getRelaxAll() ||
- (Assembler.isBundlingEnabled() && Sec->isBundleLocked())) {
- MCInst Relaxed = Inst;
- while (Backend.mayNeedRelaxation(Relaxed, STI))
- Backend.relaxInstruction(Relaxed, STI);
- emitInstToData(Relaxed, STI);
- return;
- }
- // Otherwise emit to a separate fragment.
- emitInstToFragment(Inst, STI);
- }
- void MCObjectStreamer::emitInstToFragment(const MCInst &Inst,
- const MCSubtargetInfo &STI) {
- if (getAssembler().getRelaxAll() && getAssembler().isBundlingEnabled())
- llvm_unreachable("All instructions should have already been relaxed");
- // Always create a new, separate fragment here, because its size can change
- // during relaxation.
- MCRelaxableFragment *IF = new MCRelaxableFragment(Inst, STI);
- insert(IF);
- SmallString<128> Code;
- raw_svector_ostream VecOS(Code);
- getAssembler().getEmitter().encodeInstruction(Inst, VecOS, IF->getFixups(),
- STI);
- IF->getContents().append(Code.begin(), Code.end());
- }
- #ifndef NDEBUG
- static const char *const BundlingNotImplementedMsg =
- "Aligned bundling is not implemented for this object format";
- #endif
- void MCObjectStreamer::emitBundleAlignMode(Align Alignment) {
- llvm_unreachable(BundlingNotImplementedMsg);
- }
- void MCObjectStreamer::emitBundleLock(bool AlignToEnd) {
- llvm_unreachable(BundlingNotImplementedMsg);
- }
- void MCObjectStreamer::emitBundleUnlock() {
- llvm_unreachable(BundlingNotImplementedMsg);
- }
- void MCObjectStreamer::emitDwarfLocDirective(unsigned FileNo, unsigned Line,
- unsigned Column, unsigned Flags,
- unsigned Isa,
- unsigned Discriminator,
- StringRef FileName) {
- // In case we see two .loc directives in a row, make sure the
- // first one gets a line entry.
- MCDwarfLineEntry::make(this, getCurrentSectionOnly());
- this->MCStreamer::emitDwarfLocDirective(FileNo, Line, Column, Flags, Isa,
- Discriminator, FileName);
- }
- static const MCExpr *buildSymbolDiff(MCObjectStreamer &OS, const MCSymbol *A,
- const MCSymbol *B) {
- MCContext &Context = OS.getContext();
- MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None;
- const MCExpr *ARef = MCSymbolRefExpr::create(A, Variant, Context);
- const MCExpr *BRef = MCSymbolRefExpr::create(B, Variant, Context);
- const MCExpr *AddrDelta =
- MCBinaryExpr::create(MCBinaryExpr::Sub, ARef, BRef, Context);
- return AddrDelta;
- }
- static void emitDwarfSetLineAddr(MCObjectStreamer &OS,
- MCDwarfLineTableParams Params,
- int64_t LineDelta, const MCSymbol *Label,
- int PointerSize) {
- // emit the sequence to set the address
- OS.emitIntValue(dwarf::DW_LNS_extended_op, 1);
- OS.emitULEB128IntValue(PointerSize + 1);
- OS.emitIntValue(dwarf::DW_LNE_set_address, 1);
- OS.emitSymbolValue(Label, PointerSize);
- // emit the sequence for the LineDelta (from 1) and a zero address delta.
- MCDwarfLineAddr::Emit(&OS, Params, LineDelta, 0);
- }
- void MCObjectStreamer::emitDwarfAdvanceLineAddr(int64_t LineDelta,
- const MCSymbol *LastLabel,
- const MCSymbol *Label,
- unsigned PointerSize) {
- if (!LastLabel) {
- emitDwarfSetLineAddr(*this, Assembler->getDWARFLinetableParams(), LineDelta,
- Label, PointerSize);
- return;
- }
- const MCExpr *AddrDelta = buildSymbolDiff(*this, Label, LastLabel);
- int64_t Res;
- if (AddrDelta->evaluateAsAbsolute(Res, getAssemblerPtr())) {
- MCDwarfLineAddr::Emit(this, Assembler->getDWARFLinetableParams(), LineDelta,
- Res);
- return;
- }
- insert(new MCDwarfLineAddrFragment(LineDelta, *AddrDelta));
- }
- void MCObjectStreamer::emitDwarfLineEndEntry(MCSection *Section,
- MCSymbol *LastLabel) {
- // Emit a DW_LNE_end_sequence for the end of the section.
- // Use the section end label to compute the address delta and use INT64_MAX
- // as the line delta which is the signal that this is actually a
- // DW_LNE_end_sequence.
- MCSymbol *SectionEnd = endSection(Section);
- // Switch back the dwarf line section, in case endSection had to switch the
- // section.
- MCContext &Ctx = getContext();
- switchSection(Ctx.getObjectFileInfo()->getDwarfLineSection());
- const MCAsmInfo *AsmInfo = Ctx.getAsmInfo();
- emitDwarfAdvanceLineAddr(INT64_MAX, LastLabel, SectionEnd,
- AsmInfo->getCodePointerSize());
- }
- void MCObjectStreamer::emitDwarfAdvanceFrameAddr(const MCSymbol *LastLabel,
- const MCSymbol *Label) {
- const MCExpr *AddrDelta = buildSymbolDiff(*this, Label, LastLabel);
- int64_t Res;
- if (AddrDelta->evaluateAsAbsolute(Res, getAssemblerPtr())) {
- MCDwarfFrameEmitter::EmitAdvanceLoc(*this, Res);
- return;
- }
- insert(new MCDwarfCallFrameFragment(*AddrDelta));
- }
- void MCObjectStreamer::emitCVLocDirective(unsigned FunctionId, unsigned FileNo,
- unsigned Line, unsigned Column,
- bool PrologueEnd, bool IsStmt,
- StringRef FileName, SMLoc Loc) {
- // Validate the directive.
- if (!checkCVLocSection(FunctionId, FileNo, Loc))
- return;
- // Emit a label at the current position and record it in the CodeViewContext.
- MCSymbol *LineSym = getContext().createTempSymbol();
- emitLabel(LineSym);
- getContext().getCVContext().recordCVLoc(getContext(), LineSym, FunctionId,
- FileNo, Line, Column, PrologueEnd,
- IsStmt);
- }
- void MCObjectStreamer::emitCVLinetableDirective(unsigned FunctionId,
- const MCSymbol *Begin,
- const MCSymbol *End) {
- getContext().getCVContext().emitLineTableForFunction(*this, FunctionId, Begin,
- End);
- this->MCStreamer::emitCVLinetableDirective(FunctionId, Begin, End);
- }
- void MCObjectStreamer::emitCVInlineLinetableDirective(
- unsigned PrimaryFunctionId, unsigned SourceFileId, unsigned SourceLineNum,
- const MCSymbol *FnStartSym, const MCSymbol *FnEndSym) {
- getContext().getCVContext().emitInlineLineTableForFunction(
- *this, PrimaryFunctionId, SourceFileId, SourceLineNum, FnStartSym,
- FnEndSym);
- this->MCStreamer::emitCVInlineLinetableDirective(
- PrimaryFunctionId, SourceFileId, SourceLineNum, FnStartSym, FnEndSym);
- }
- void MCObjectStreamer::emitCVDefRangeDirective(
- ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,
- StringRef FixedSizePortion) {
- MCFragment *Frag =
- getContext().getCVContext().emitDefRange(*this, Ranges, FixedSizePortion);
- // Attach labels that were pending before we created the defrange fragment to
- // the beginning of the new fragment.
- flushPendingLabels(Frag, 0);
- this->MCStreamer::emitCVDefRangeDirective(Ranges, FixedSizePortion);
- }
- void MCObjectStreamer::emitCVStringTableDirective() {
- getContext().getCVContext().emitStringTable(*this);
- }
- void MCObjectStreamer::emitCVFileChecksumsDirective() {
- getContext().getCVContext().emitFileChecksums(*this);
- }
- void MCObjectStreamer::emitCVFileChecksumOffsetDirective(unsigned FileNo) {
- getContext().getCVContext().emitFileChecksumOffset(*this, FileNo);
- }
- void MCObjectStreamer::emitBytes(StringRef Data) {
- MCDwarfLineEntry::make(this, getCurrentSectionOnly());
- MCDataFragment *DF = getOrCreateDataFragment();
- flushPendingLabels(DF, DF->getContents().size());
- DF->getContents().append(Data.begin(), Data.end());
- }
- void MCObjectStreamer::emitValueToAlignment(Align Alignment, int64_t Value,
- unsigned ValueSize,
- unsigned MaxBytesToEmit) {
- if (MaxBytesToEmit == 0)
- MaxBytesToEmit = Alignment.value();
- insert(new MCAlignFragment(Alignment, Value, ValueSize, MaxBytesToEmit));
- // Update the maximum alignment on the current section if necessary.
- MCSection *CurSec = getCurrentSectionOnly();
- CurSec->ensureMinAlignment(Alignment);
- }
- void MCObjectStreamer::emitCodeAlignment(Align Alignment,
- const MCSubtargetInfo *STI,
- unsigned MaxBytesToEmit) {
- emitValueToAlignment(Alignment, 0, 1, MaxBytesToEmit);
- cast<MCAlignFragment>(getCurrentFragment())->setEmitNops(true, STI);
- }
- void MCObjectStreamer::emitValueToOffset(const MCExpr *Offset,
- unsigned char Value,
- SMLoc Loc) {
- insert(new MCOrgFragment(*Offset, Value, Loc));
- }
- // Associate DTPRel32 fixup with data and resize data area
- void MCObjectStreamer::emitDTPRel32Value(const MCExpr *Value) {
- MCDataFragment *DF = getOrCreateDataFragment();
- flushPendingLabels(DF, DF->getContents().size());
- DF->getFixups().push_back(MCFixup::create(DF->getContents().size(),
- Value, FK_DTPRel_4));
- DF->getContents().resize(DF->getContents().size() + 4, 0);
- }
- // Associate DTPRel64 fixup with data and resize data area
- void MCObjectStreamer::emitDTPRel64Value(const MCExpr *Value) {
- MCDataFragment *DF = getOrCreateDataFragment();
- flushPendingLabels(DF, DF->getContents().size());
- DF->getFixups().push_back(MCFixup::create(DF->getContents().size(),
- Value, FK_DTPRel_8));
- DF->getContents().resize(DF->getContents().size() + 8, 0);
- }
- // Associate TPRel32 fixup with data and resize data area
- void MCObjectStreamer::emitTPRel32Value(const MCExpr *Value) {
- MCDataFragment *DF = getOrCreateDataFragment();
- flushPendingLabels(DF, DF->getContents().size());
- DF->getFixups().push_back(MCFixup::create(DF->getContents().size(),
- Value, FK_TPRel_4));
- DF->getContents().resize(DF->getContents().size() + 4, 0);
- }
- // Associate TPRel64 fixup with data and resize data area
- void MCObjectStreamer::emitTPRel64Value(const MCExpr *Value) {
- MCDataFragment *DF = getOrCreateDataFragment();
- flushPendingLabels(DF, DF->getContents().size());
- DF->getFixups().push_back(MCFixup::create(DF->getContents().size(),
- Value, FK_TPRel_8));
- DF->getContents().resize(DF->getContents().size() + 8, 0);
- }
- // Associate GPRel32 fixup with data and resize data area
- void MCObjectStreamer::emitGPRel32Value(const MCExpr *Value) {
- MCDataFragment *DF = getOrCreateDataFragment();
- flushPendingLabels(DF, DF->getContents().size());
- DF->getFixups().push_back(
- MCFixup::create(DF->getContents().size(), Value, FK_GPRel_4));
- DF->getContents().resize(DF->getContents().size() + 4, 0);
- }
- // Associate GPRel64 fixup with data and resize data area
- void MCObjectStreamer::emitGPRel64Value(const MCExpr *Value) {
- MCDataFragment *DF = getOrCreateDataFragment();
- flushPendingLabels(DF, DF->getContents().size());
- DF->getFixups().push_back(
- MCFixup::create(DF->getContents().size(), Value, FK_GPRel_4));
- DF->getContents().resize(DF->getContents().size() + 8, 0);
- }
- static std::optional<std::pair<bool, std::string>>
- getOffsetAndDataFragment(const MCSymbol &Symbol, uint32_t &RelocOffset,
- MCDataFragment *&DF) {
- if (Symbol.isVariable()) {
- const MCExpr *SymbolExpr = Symbol.getVariableValue();
- MCValue OffsetVal;
- if(!SymbolExpr->evaluateAsRelocatable(OffsetVal, nullptr, nullptr))
- return std::make_pair(false,
- std::string("symbol in .reloc offset is not "
- "relocatable"));
- if (OffsetVal.isAbsolute()) {
- RelocOffset = OffsetVal.getConstant();
- MCFragment *Fragment = Symbol.getFragment();
- // FIXME Support symbols with no DF. For example:
- // .reloc .data, ENUM_VALUE, <some expr>
- if (!Fragment || Fragment->getKind() != MCFragment::FT_Data)
- return std::make_pair(false,
- std::string("symbol in offset has no data "
- "fragment"));
- DF = cast<MCDataFragment>(Fragment);
- return std::nullopt;
- }
- if (OffsetVal.getSymB())
- return std::make_pair(false,
- std::string(".reloc symbol offset is not "
- "representable"));
- const MCSymbolRefExpr &SRE = cast<MCSymbolRefExpr>(*OffsetVal.getSymA());
- if (!SRE.getSymbol().isDefined())
- return std::make_pair(false,
- std::string("symbol used in the .reloc offset is "
- "not defined"));
- if (SRE.getSymbol().isVariable())
- return std::make_pair(false,
- std::string("symbol used in the .reloc offset is "
- "variable"));
- MCFragment *Fragment = SRE.getSymbol().getFragment();
- // FIXME Support symbols with no DF. For example:
- // .reloc .data, ENUM_VALUE, <some expr>
- if (!Fragment || Fragment->getKind() != MCFragment::FT_Data)
- return std::make_pair(false,
- std::string("symbol in offset has no data "
- "fragment"));
- RelocOffset = SRE.getSymbol().getOffset() + OffsetVal.getConstant();
- DF = cast<MCDataFragment>(Fragment);
- } else {
- RelocOffset = Symbol.getOffset();
- MCFragment *Fragment = Symbol.getFragment();
- // FIXME Support symbols with no DF. For example:
- // .reloc .data, ENUM_VALUE, <some expr>
- if (!Fragment || Fragment->getKind() != MCFragment::FT_Data)
- return std::make_pair(false,
- std::string("symbol in offset has no data "
- "fragment"));
- DF = cast<MCDataFragment>(Fragment);
- }
- return std::nullopt;
- }
- std::optional<std::pair<bool, std::string>>
- MCObjectStreamer::emitRelocDirective(const MCExpr &Offset, StringRef Name,
- const MCExpr *Expr, SMLoc Loc,
- const MCSubtargetInfo &STI) {
- std::optional<MCFixupKind> MaybeKind =
- Assembler->getBackend().getFixupKind(Name);
- if (!MaybeKind)
- return std::make_pair(true, std::string("unknown relocation name"));
- MCFixupKind Kind = *MaybeKind;
- if (Expr == nullptr)
- Expr =
- MCSymbolRefExpr::create(getContext().createTempSymbol(), getContext());
- MCDataFragment *DF = getOrCreateDataFragment(&STI);
- flushPendingLabels(DF, DF->getContents().size());
- MCValue OffsetVal;
- if (!Offset.evaluateAsRelocatable(OffsetVal, nullptr, nullptr))
- return std::make_pair(false,
- std::string(".reloc offset is not relocatable"));
- if (OffsetVal.isAbsolute()) {
- if (OffsetVal.getConstant() < 0)
- return std::make_pair(false, std::string(".reloc offset is negative"));
- DF->getFixups().push_back(
- MCFixup::create(OffsetVal.getConstant(), Expr, Kind, Loc));
- return std::nullopt;
- }
- if (OffsetVal.getSymB())
- return std::make_pair(false,
- std::string(".reloc offset is not representable"));
- const MCSymbolRefExpr &SRE = cast<MCSymbolRefExpr>(*OffsetVal.getSymA());
- const MCSymbol &Symbol = SRE.getSymbol();
- if (Symbol.isDefined()) {
- uint32_t SymbolOffset = 0;
- std::optional<std::pair<bool, std::string>> Error =
- getOffsetAndDataFragment(Symbol, SymbolOffset, DF);
- if (Error != std::nullopt)
- return Error;
- DF->getFixups().push_back(
- MCFixup::create(SymbolOffset + OffsetVal.getConstant(),
- Expr, Kind, Loc));
- return std::nullopt;
- }
- PendingFixups.emplace_back(
- &SRE.getSymbol(), DF,
- MCFixup::create(OffsetVal.getConstant(), Expr, Kind, Loc));
- return std::nullopt;
- }
- void MCObjectStreamer::emitFill(const MCExpr &NumBytes, uint64_t FillValue,
- SMLoc Loc) {
- MCDataFragment *DF = getOrCreateDataFragment();
- flushPendingLabels(DF, DF->getContents().size());
- assert(getCurrentSectionOnly() && "need a section");
- insert(new MCFillFragment(FillValue, 1, NumBytes, Loc));
- }
- void MCObjectStreamer::emitFill(const MCExpr &NumValues, int64_t Size,
- int64_t Expr, SMLoc Loc) {
- int64_t IntNumValues;
- // Do additional checking now if we can resolve the value.
- if (NumValues.evaluateAsAbsolute(IntNumValues, getAssemblerPtr())) {
- if (IntNumValues < 0) {
- getContext().getSourceManager()->PrintMessage(
- Loc, SourceMgr::DK_Warning,
- "'.fill' directive with negative repeat count has no effect");
- return;
- }
- // Emit now if we can for better errors.
- int64_t NonZeroSize = Size > 4 ? 4 : Size;
- Expr &= ~0ULL >> (64 - NonZeroSize * 8);
- for (uint64_t i = 0, e = IntNumValues; i != e; ++i) {
- emitIntValue(Expr, NonZeroSize);
- if (NonZeroSize < Size)
- emitIntValue(0, Size - NonZeroSize);
- }
- return;
- }
- // Otherwise emit as fragment.
- MCDataFragment *DF = getOrCreateDataFragment();
- flushPendingLabels(DF, DF->getContents().size());
- assert(getCurrentSectionOnly() && "need a section");
- insert(new MCFillFragment(Expr, Size, NumValues, Loc));
- }
- void MCObjectStreamer::emitNops(int64_t NumBytes, int64_t ControlledNopLength,
- SMLoc Loc, const MCSubtargetInfo &STI) {
- // Emit an NOP fragment.
- MCDataFragment *DF = getOrCreateDataFragment();
- flushPendingLabels(DF, DF->getContents().size());
- assert(getCurrentSectionOnly() && "need a section");
- insert(new MCNopsFragment(NumBytes, ControlledNopLength, Loc, STI));
- }
- void MCObjectStreamer::emitFileDirective(StringRef Filename) {
- getAssembler().addFileName(Filename);
- }
- void MCObjectStreamer::emitFileDirective(StringRef Filename,
- StringRef CompilerVerion,
- StringRef TimeStamp,
- StringRef Description) {
- getAssembler().addFileName(Filename);
- // TODO: add additional info to integrated assembler.
- }
- void MCObjectStreamer::emitAddrsig() {
- getAssembler().getWriter().emitAddrsigSection();
- }
- void MCObjectStreamer::emitAddrsigSym(const MCSymbol *Sym) {
- getAssembler().getWriter().addAddrsigSymbol(Sym);
- }
- void MCObjectStreamer::finishImpl() {
- getContext().RemapDebugPaths();
- // If we are generating dwarf for assembly source files dump out the sections.
- if (getContext().getGenDwarfForAssembly())
- MCGenDwarfInfo::Emit(this);
- // Dump out the dwarf file & directory tables and line tables.
- MCDwarfLineTable::emit(this, getAssembler().getDWARFLinetableParams());
- // Emit pseudo probes for the current module.
- MCPseudoProbeTable::emit(this);
- // Update any remaining pending labels with empty data fragments.
- flushPendingLabels();
- resolvePendingFixups();
- getAssembler().Finish();
- }
|