Path: blob/main/contrib/llvm-project/llvm/lib/MC/MCObjectStreamer.cpp
35233 views
//===- lib/MC/MCObjectStreamer.cpp - Object File MCStreamer Interface -----===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "llvm/MC/MCObjectStreamer.h"9#include "llvm/MC/MCAsmBackend.h"10#include "llvm/MC/MCAsmInfo.h"11#include "llvm/MC/MCAssembler.h"12#include "llvm/MC/MCCodeEmitter.h"13#include "llvm/MC/MCCodeView.h"14#include "llvm/MC/MCContext.h"15#include "llvm/MC/MCDwarf.h"16#include "llvm/MC/MCExpr.h"17#include "llvm/MC/MCObjectFileInfo.h"18#include "llvm/MC/MCObjectWriter.h"19#include "llvm/MC/MCSection.h"20#include "llvm/MC/MCSymbol.h"21#include "llvm/MC/MCValue.h"22#include "llvm/Support/ErrorHandling.h"23#include "llvm/Support/SourceMgr.h"24using namespace llvm;2526MCObjectStreamer::MCObjectStreamer(MCContext &Context,27std::unique_ptr<MCAsmBackend> TAB,28std::unique_ptr<MCObjectWriter> OW,29std::unique_ptr<MCCodeEmitter> Emitter)30: MCStreamer(Context),31Assembler(std::make_unique<MCAssembler>(32Context, std::move(TAB), std::move(Emitter), std::move(OW))),33EmitEHFrame(true), EmitDebugFrame(false) {34assert(Assembler->getBackendPtr() && Assembler->getEmitterPtr());35setAllowAutoPadding(Assembler->getBackend().allowAutoPadding());36if (Context.getTargetOptions() && Context.getTargetOptions()->MCRelaxAll)37Assembler->setRelaxAll(true);38}3940MCObjectStreamer::~MCObjectStreamer() = default;4142MCAssembler *MCObjectStreamer::getAssemblerPtr() {43if (getUseAssemblerInfoForParsing())44return Assembler.get();45return nullptr;46}4748// When fixup's offset is a forward declared label, e.g.:49//50// .reloc 1f, R_MIPS_JALR, foo51// 1: nop52//53// postpone adding it to Fixups vector until the label is defined and its offset54// is known.55void MCObjectStreamer::resolvePendingFixups() {56for (PendingMCFixup &PendingFixup : PendingFixups) {57if (!PendingFixup.Sym || PendingFixup.Sym->isUndefined ()) {58getContext().reportError(PendingFixup.Fixup.getLoc(),59"unresolved relocation offset");60continue;61}62PendingFixup.Fixup.setOffset(PendingFixup.Sym->getOffset() +63PendingFixup.Fixup.getOffset());6465// If the location symbol to relocate is in MCEncodedFragmentWithFixups,66// put the Fixup into location symbol's fragment. Otherwise67// put into PendingFixup.DF68MCFragment *SymFragment = PendingFixup.Sym->getFragment();69switch (SymFragment->getKind()) {70case MCFragment::FT_Relaxable:71case MCFragment::FT_Dwarf:72case MCFragment::FT_PseudoProbe:73cast<MCEncodedFragmentWithFixups<8, 1>>(SymFragment)74->getFixups()75.push_back(PendingFixup.Fixup);76break;77case MCFragment::FT_Data:78case MCFragment::FT_CVDefRange:79cast<MCEncodedFragmentWithFixups<32, 4>>(SymFragment)80->getFixups()81.push_back(PendingFixup.Fixup);82break;83default:84PendingFixup.DF->getFixups().push_back(PendingFixup.Fixup);85break;86}87}88PendingFixups.clear();89}9091// As a compile-time optimization, avoid allocating and evaluating an MCExpr92// tree for (Hi - Lo) when Hi and Lo are offsets into the same fragment.93static std::optional<uint64_t> absoluteSymbolDiff(const MCSymbol *Hi,94const MCSymbol *Lo) {95assert(Hi && Lo);96if (!Hi->getFragment() || Hi->getFragment() != Lo->getFragment() ||97Hi->isVariable() || Lo->isVariable())98return std::nullopt;99100return Hi->getOffset() - Lo->getOffset();101}102103void MCObjectStreamer::emitAbsoluteSymbolDiff(const MCSymbol *Hi,104const MCSymbol *Lo,105unsigned Size) {106if (!getAssembler().getContext().getTargetTriple().isRISCV())107if (std::optional<uint64_t> Diff = absoluteSymbolDiff(Hi, Lo))108return emitIntValue(*Diff, Size);109MCStreamer::emitAbsoluteSymbolDiff(Hi, Lo, Size);110}111112void MCObjectStreamer::emitAbsoluteSymbolDiffAsULEB128(const MCSymbol *Hi,113const MCSymbol *Lo) {114if (!getAssembler().getContext().getTargetTriple().isRISCV())115if (std::optional<uint64_t> Diff = absoluteSymbolDiff(Hi, Lo)) {116emitULEB128IntValue(*Diff);117return;118}119MCStreamer::emitAbsoluteSymbolDiffAsULEB128(Hi, Lo);120}121122void MCObjectStreamer::reset() {123if (Assembler) {124Assembler->reset();125if (getContext().getTargetOptions())126Assembler->setRelaxAll(getContext().getTargetOptions()->MCRelaxAll);127}128EmitEHFrame = true;129EmitDebugFrame = false;130MCStreamer::reset();131}132133void MCObjectStreamer::emitFrames(MCAsmBackend *MAB) {134if (!getNumFrameInfos())135return;136137if (EmitEHFrame)138MCDwarfFrameEmitter::Emit(*this, MAB, true);139140if (EmitDebugFrame)141MCDwarfFrameEmitter::Emit(*this, MAB, false);142}143144static bool canReuseDataFragment(const MCDataFragment &F,145const MCAssembler &Assembler,146const MCSubtargetInfo *STI) {147if (!F.hasInstructions())148return true;149// Do not add data after a linker-relaxable instruction. The difference150// between a new label and a label at or before the linker-relaxable151// instruction cannot be resolved at assemble-time.152if (F.isLinkerRelaxable())153return false;154// When bundling is enabled, we don't want to add data to a fragment that155// already has instructions (see MCELFStreamer::emitInstToData for details)156if (Assembler.isBundlingEnabled())157return false;158// If the subtarget is changed mid fragment we start a new fragment to record159// the new STI.160return !STI || F.getSubtargetInfo() == STI;161}162163MCDataFragment *164MCObjectStreamer::getOrCreateDataFragment(const MCSubtargetInfo *STI) {165auto *F = dyn_cast<MCDataFragment>(getCurrentFragment());166if (!F || !canReuseDataFragment(*F, *Assembler, STI)) {167F = getContext().allocFragment<MCDataFragment>();168insert(F);169}170return F;171}172173void MCObjectStreamer::visitUsedSymbol(const MCSymbol &Sym) {174Assembler->registerSymbol(Sym);175}176177void MCObjectStreamer::emitCFISections(bool EH, bool Debug) {178MCStreamer::emitCFISections(EH, Debug);179EmitEHFrame = EH;180EmitDebugFrame = Debug;181}182183void MCObjectStreamer::emitValueImpl(const MCExpr *Value, unsigned Size,184SMLoc Loc) {185MCStreamer::emitValueImpl(Value, Size, Loc);186MCDataFragment *DF = getOrCreateDataFragment();187188MCDwarfLineEntry::make(this, getCurrentSectionOnly());189190// Avoid fixups when possible.191int64_t AbsValue;192if (Value->evaluateAsAbsolute(AbsValue, getAssemblerPtr())) {193if (!isUIntN(8 * Size, AbsValue) && !isIntN(8 * Size, AbsValue)) {194getContext().reportError(195Loc, "value evaluated as " + Twine(AbsValue) + " is out of range.");196return;197}198emitIntValue(AbsValue, Size);199return;200}201DF->getFixups().push_back(202MCFixup::create(DF->getContents().size(), Value,203MCFixup::getKindForSize(Size, false), Loc));204DF->getContents().resize(DF->getContents().size() + Size, 0);205}206207MCSymbol *MCObjectStreamer::emitCFILabel() {208MCSymbol *Label = getContext().createTempSymbol("cfi");209emitLabel(Label);210return Label;211}212213void MCObjectStreamer::emitCFIStartProcImpl(MCDwarfFrameInfo &Frame) {214// We need to create a local symbol to avoid relocations.215Frame.Begin = getContext().createTempSymbol();216emitLabel(Frame.Begin);217}218219void MCObjectStreamer::emitCFIEndProcImpl(MCDwarfFrameInfo &Frame) {220Frame.End = getContext().createTempSymbol();221emitLabel(Frame.End);222}223224void MCObjectStreamer::emitLabel(MCSymbol *Symbol, SMLoc Loc) {225MCStreamer::emitLabel(Symbol, Loc);226227getAssembler().registerSymbol(*Symbol);228229// If there is a current fragment, mark the symbol as pointing into it.230// Otherwise queue the label and set its fragment pointer when we emit the231// next fragment.232MCDataFragment *F = getOrCreateDataFragment();233Symbol->setFragment(F);234Symbol->setOffset(F->getContents().size());235236emitPendingAssignments(Symbol);237}238239void MCObjectStreamer::emitPendingAssignments(MCSymbol *Symbol) {240auto Assignments = pendingAssignments.find(Symbol);241if (Assignments != pendingAssignments.end()) {242for (const PendingAssignment &A : Assignments->second)243emitAssignment(A.Symbol, A.Value);244245pendingAssignments.erase(Assignments);246}247}248249// Emit a label at a previously emitted fragment/offset position. This must be250// within the currently-active section.251void MCObjectStreamer::emitLabelAtPos(MCSymbol *Symbol, SMLoc Loc,252MCDataFragment &F, uint64_t Offset) {253assert(F.getParent() == getCurrentSectionOnly());254MCStreamer::emitLabel(Symbol, Loc);255getAssembler().registerSymbol(*Symbol);256Symbol->setFragment(&F);257Symbol->setOffset(Offset);258}259260void MCObjectStreamer::emitULEB128Value(const MCExpr *Value) {261int64_t IntValue;262if (Value->evaluateAsAbsolute(IntValue, getAssemblerPtr())) {263emitULEB128IntValue(IntValue);264return;265}266insert(getContext().allocFragment<MCLEBFragment>(*Value, false));267}268269void MCObjectStreamer::emitSLEB128Value(const MCExpr *Value) {270int64_t IntValue;271if (Value->evaluateAsAbsolute(IntValue, getAssemblerPtr())) {272emitSLEB128IntValue(IntValue);273return;274}275insert(getContext().allocFragment<MCLEBFragment>(*Value, true));276}277278void MCObjectStreamer::emitWeakReference(MCSymbol *Alias,279const MCSymbol *Symbol) {280report_fatal_error("This file format doesn't support weak aliases.");281}282283void MCObjectStreamer::changeSection(MCSection *Section, uint32_t Subsection) {284changeSectionImpl(Section, Subsection);285}286287bool MCObjectStreamer::changeSectionImpl(MCSection *Section,288uint32_t Subsection) {289assert(Section && "Cannot switch to a null section!");290getContext().clearDwarfLocSeen();291292auto &Subsections = Section->Subsections;293size_t I = 0, E = Subsections.size();294while (I != E && Subsections[I].first < Subsection)295++I;296// If the subsection number is not in the sorted Subsections list, create a297// new fragment list.298if (I == E || Subsections[I].first != Subsection) {299auto *F = getContext().allocFragment<MCDataFragment>();300F->setParent(Section);301Subsections.insert(Subsections.begin() + I,302{Subsection, MCSection::FragList{F, F}});303}304Section->CurFragList = &Subsections[I].second;305CurFrag = Section->CurFragList->Tail;306307return getAssembler().registerSection(*Section);308}309310void MCObjectStreamer::switchSectionNoPrint(MCSection *Section) {311MCStreamer::switchSectionNoPrint(Section);312changeSection(Section, 0);313}314315void MCObjectStreamer::emitAssignment(MCSymbol *Symbol, const MCExpr *Value) {316getAssembler().registerSymbol(*Symbol);317MCStreamer::emitAssignment(Symbol, Value);318emitPendingAssignments(Symbol);319}320321void MCObjectStreamer::emitConditionalAssignment(MCSymbol *Symbol,322const MCExpr *Value) {323const MCSymbol *Target = &cast<MCSymbolRefExpr>(*Value).getSymbol();324325// If the symbol already exists, emit the assignment. Otherwise, emit it326// later only if the symbol is also emitted.327if (Target->isRegistered())328emitAssignment(Symbol, Value);329else330pendingAssignments[Target].push_back({Symbol, Value});331}332333bool MCObjectStreamer::mayHaveInstructions(MCSection &Sec) const {334return Sec.hasInstructions();335}336337void MCObjectStreamer::emitInstruction(const MCInst &Inst,338const MCSubtargetInfo &STI) {339const MCSection &Sec = *getCurrentSectionOnly();340if (Sec.isVirtualSection()) {341getContext().reportError(Inst.getLoc(), Twine(Sec.getVirtualSectionKind()) +342" section '" + Sec.getName() +343"' cannot have instructions");344return;345}346emitInstructionImpl(Inst, STI);347}348349void MCObjectStreamer::emitInstructionImpl(const MCInst &Inst,350const MCSubtargetInfo &STI) {351MCStreamer::emitInstruction(Inst, STI);352353MCSection *Sec = getCurrentSectionOnly();354Sec->setHasInstructions(true);355356// Now that a machine instruction has been assembled into this section, make357// a line entry for any .loc directive that has been seen.358MCDwarfLineEntry::make(this, getCurrentSectionOnly());359360// If this instruction doesn't need relaxation, just emit it as data.361MCAssembler &Assembler = getAssembler();362MCAsmBackend &Backend = Assembler.getBackend();363if (!(Backend.mayNeedRelaxation(Inst, STI) ||364Backend.allowEnhancedRelaxation())) {365emitInstToData(Inst, STI);366return;367}368369// Otherwise, relax and emit it as data if either:370// - The RelaxAll flag was passed371// - Bundling is enabled and this instruction is inside a bundle-locked372// group. We want to emit all such instructions into the same data373// fragment.374if (Assembler.getRelaxAll() ||375(Assembler.isBundlingEnabled() && Sec->isBundleLocked())) {376MCInst Relaxed = Inst;377while (Backend.mayNeedRelaxation(Relaxed, STI))378Backend.relaxInstruction(Relaxed, STI);379emitInstToData(Relaxed, STI);380return;381}382383// Otherwise emit to a separate fragment.384emitInstToFragment(Inst, STI);385}386387void MCObjectStreamer::emitInstToFragment(const MCInst &Inst,388const MCSubtargetInfo &STI) {389// Always create a new, separate fragment here, because its size can change390// during relaxation.391MCRelaxableFragment *IF =392getContext().allocFragment<MCRelaxableFragment>(Inst, STI);393insert(IF);394395getAssembler().getEmitter().encodeInstruction(Inst, IF->getContents(),396IF->getFixups(), STI);397}398399#ifndef NDEBUG400static const char *const BundlingNotImplementedMsg =401"Aligned bundling is not implemented for this object format";402#endif403404void MCObjectStreamer::emitBundleAlignMode(Align Alignment) {405llvm_unreachable(BundlingNotImplementedMsg);406}407408void MCObjectStreamer::emitBundleLock(bool AlignToEnd) {409llvm_unreachable(BundlingNotImplementedMsg);410}411412void MCObjectStreamer::emitBundleUnlock() {413llvm_unreachable(BundlingNotImplementedMsg);414}415416void MCObjectStreamer::emitDwarfLocDirective(unsigned FileNo, unsigned Line,417unsigned Column, unsigned Flags,418unsigned Isa,419unsigned Discriminator,420StringRef FileName) {421// In case we see two .loc directives in a row, make sure the422// first one gets a line entry.423MCDwarfLineEntry::make(this, getCurrentSectionOnly());424425this->MCStreamer::emitDwarfLocDirective(FileNo, Line, Column, Flags, Isa,426Discriminator, FileName);427}428429static const MCExpr *buildSymbolDiff(MCObjectStreamer &OS, const MCSymbol *A,430const MCSymbol *B, SMLoc Loc) {431MCContext &Context = OS.getContext();432MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None;433const MCExpr *ARef = MCSymbolRefExpr::create(A, Variant, Context);434const MCExpr *BRef = MCSymbolRefExpr::create(B, Variant, Context);435const MCExpr *AddrDelta =436MCBinaryExpr::create(MCBinaryExpr::Sub, ARef, BRef, Context, Loc);437return AddrDelta;438}439440static void emitDwarfSetLineAddr(MCObjectStreamer &OS,441MCDwarfLineTableParams Params,442int64_t LineDelta, const MCSymbol *Label,443int PointerSize) {444// emit the sequence to set the address445OS.emitIntValue(dwarf::DW_LNS_extended_op, 1);446OS.emitULEB128IntValue(PointerSize + 1);447OS.emitIntValue(dwarf::DW_LNE_set_address, 1);448OS.emitSymbolValue(Label, PointerSize);449450// emit the sequence for the LineDelta (from 1) and a zero address delta.451MCDwarfLineAddr::Emit(&OS, Params, LineDelta, 0);452}453454void MCObjectStreamer::emitDwarfAdvanceLineAddr(int64_t LineDelta,455const MCSymbol *LastLabel,456const MCSymbol *Label,457unsigned PointerSize) {458if (!LastLabel) {459emitDwarfSetLineAddr(*this, Assembler->getDWARFLinetableParams(), LineDelta,460Label, PointerSize);461return;462}463const MCExpr *AddrDelta = buildSymbolDiff(*this, Label, LastLabel, SMLoc());464insert(getContext().allocFragment<MCDwarfLineAddrFragment>(LineDelta,465*AddrDelta));466}467468void MCObjectStreamer::emitDwarfLineEndEntry(MCSection *Section,469MCSymbol *LastLabel) {470// Emit a DW_LNE_end_sequence for the end of the section.471// Use the section end label to compute the address delta and use INT64_MAX472// as the line delta which is the signal that this is actually a473// DW_LNE_end_sequence.474MCSymbol *SectionEnd = endSection(Section);475476// Switch back the dwarf line section, in case endSection had to switch the477// section.478MCContext &Ctx = getContext();479switchSection(Ctx.getObjectFileInfo()->getDwarfLineSection());480481const MCAsmInfo *AsmInfo = Ctx.getAsmInfo();482emitDwarfAdvanceLineAddr(INT64_MAX, LastLabel, SectionEnd,483AsmInfo->getCodePointerSize());484}485486void MCObjectStreamer::emitDwarfAdvanceFrameAddr(const MCSymbol *LastLabel,487const MCSymbol *Label,488SMLoc Loc) {489const MCExpr *AddrDelta = buildSymbolDiff(*this, Label, LastLabel, Loc);490insert(getContext().allocFragment<MCDwarfCallFrameFragment>(*AddrDelta));491}492493void MCObjectStreamer::emitCVLocDirective(unsigned FunctionId, unsigned FileNo,494unsigned Line, unsigned Column,495bool PrologueEnd, bool IsStmt,496StringRef FileName, SMLoc Loc) {497// Validate the directive.498if (!checkCVLocSection(FunctionId, FileNo, Loc))499return;500501// Emit a label at the current position and record it in the CodeViewContext.502MCSymbol *LineSym = getContext().createTempSymbol();503emitLabel(LineSym);504getContext().getCVContext().recordCVLoc(getContext(), LineSym, FunctionId,505FileNo, Line, Column, PrologueEnd,506IsStmt);507}508509void MCObjectStreamer::emitCVLinetableDirective(unsigned FunctionId,510const MCSymbol *Begin,511const MCSymbol *End) {512getContext().getCVContext().emitLineTableForFunction(*this, FunctionId, Begin,513End);514this->MCStreamer::emitCVLinetableDirective(FunctionId, Begin, End);515}516517void MCObjectStreamer::emitCVInlineLinetableDirective(518unsigned PrimaryFunctionId, unsigned SourceFileId, unsigned SourceLineNum,519const MCSymbol *FnStartSym, const MCSymbol *FnEndSym) {520getContext().getCVContext().emitInlineLineTableForFunction(521*this, PrimaryFunctionId, SourceFileId, SourceLineNum, FnStartSym,522FnEndSym);523this->MCStreamer::emitCVInlineLinetableDirective(524PrimaryFunctionId, SourceFileId, SourceLineNum, FnStartSym, FnEndSym);525}526527void MCObjectStreamer::emitCVDefRangeDirective(528ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,529StringRef FixedSizePortion) {530getContext().getCVContext().emitDefRange(*this, Ranges, FixedSizePortion);531// Attach labels that were pending before we created the defrange fragment to532// the beginning of the new fragment.533this->MCStreamer::emitCVDefRangeDirective(Ranges, FixedSizePortion);534}535536void MCObjectStreamer::emitCVStringTableDirective() {537getContext().getCVContext().emitStringTable(*this);538}539void MCObjectStreamer::emitCVFileChecksumsDirective() {540getContext().getCVContext().emitFileChecksums(*this);541}542543void MCObjectStreamer::emitCVFileChecksumOffsetDirective(unsigned FileNo) {544getContext().getCVContext().emitFileChecksumOffset(*this, FileNo);545}546547void MCObjectStreamer::emitBytes(StringRef Data) {548MCDwarfLineEntry::make(this, getCurrentSectionOnly());549MCDataFragment *DF = getOrCreateDataFragment();550DF->getContents().append(Data.begin(), Data.end());551}552553void MCObjectStreamer::emitValueToAlignment(Align Alignment, int64_t Value,554unsigned ValueSize,555unsigned MaxBytesToEmit) {556if (MaxBytesToEmit == 0)557MaxBytesToEmit = Alignment.value();558insert(getContext().allocFragment<MCAlignFragment>(559Alignment, Value, ValueSize, MaxBytesToEmit));560561// Update the maximum alignment on the current section if necessary.562MCSection *CurSec = getCurrentSectionOnly();563CurSec->ensureMinAlignment(Alignment);564}565566void MCObjectStreamer::emitCodeAlignment(Align Alignment,567const MCSubtargetInfo *STI,568unsigned MaxBytesToEmit) {569emitValueToAlignment(Alignment, 0, 1, MaxBytesToEmit);570cast<MCAlignFragment>(getCurrentFragment())->setEmitNops(true, STI);571}572573void MCObjectStreamer::emitValueToOffset(const MCExpr *Offset,574unsigned char Value,575SMLoc Loc) {576insert(getContext().allocFragment<MCOrgFragment>(*Offset, Value, Loc));577}578579// Associate DTPRel32 fixup with data and resize data area580void MCObjectStreamer::emitDTPRel32Value(const MCExpr *Value) {581MCDataFragment *DF = getOrCreateDataFragment();582DF->getFixups().push_back(MCFixup::create(DF->getContents().size(),583Value, FK_DTPRel_4));584DF->getContents().resize(DF->getContents().size() + 4, 0);585}586587// Associate DTPRel64 fixup with data and resize data area588void MCObjectStreamer::emitDTPRel64Value(const MCExpr *Value) {589MCDataFragment *DF = getOrCreateDataFragment();590DF->getFixups().push_back(MCFixup::create(DF->getContents().size(),591Value, FK_DTPRel_8));592DF->getContents().resize(DF->getContents().size() + 8, 0);593}594595// Associate TPRel32 fixup with data and resize data area596void MCObjectStreamer::emitTPRel32Value(const MCExpr *Value) {597MCDataFragment *DF = getOrCreateDataFragment();598DF->getFixups().push_back(MCFixup::create(DF->getContents().size(),599Value, FK_TPRel_4));600DF->getContents().resize(DF->getContents().size() + 4, 0);601}602603// Associate TPRel64 fixup with data and resize data area604void MCObjectStreamer::emitTPRel64Value(const MCExpr *Value) {605MCDataFragment *DF = getOrCreateDataFragment();606DF->getFixups().push_back(MCFixup::create(DF->getContents().size(),607Value, FK_TPRel_8));608DF->getContents().resize(DF->getContents().size() + 8, 0);609}610611// Associate GPRel32 fixup with data and resize data area612void MCObjectStreamer::emitGPRel32Value(const MCExpr *Value) {613MCDataFragment *DF = getOrCreateDataFragment();614DF->getFixups().push_back(615MCFixup::create(DF->getContents().size(), Value, FK_GPRel_4));616DF->getContents().resize(DF->getContents().size() + 4, 0);617}618619// Associate GPRel64 fixup with data and resize data area620void MCObjectStreamer::emitGPRel64Value(const MCExpr *Value) {621MCDataFragment *DF = getOrCreateDataFragment();622DF->getFixups().push_back(623MCFixup::create(DF->getContents().size(), Value, FK_GPRel_4));624DF->getContents().resize(DF->getContents().size() + 8, 0);625}626627static std::optional<std::pair<bool, std::string>>628getOffsetAndDataFragment(const MCSymbol &Symbol, uint32_t &RelocOffset,629MCDataFragment *&DF) {630if (Symbol.isVariable()) {631const MCExpr *SymbolExpr = Symbol.getVariableValue();632MCValue OffsetVal;633if(!SymbolExpr->evaluateAsRelocatable(OffsetVal, nullptr, nullptr))634return std::make_pair(false,635std::string("symbol in .reloc offset is not "636"relocatable"));637if (OffsetVal.isAbsolute()) {638RelocOffset = OffsetVal.getConstant();639MCFragment *Fragment = Symbol.getFragment();640// FIXME Support symbols with no DF. For example:641// .reloc .data, ENUM_VALUE, <some expr>642if (!Fragment || Fragment->getKind() != MCFragment::FT_Data)643return std::make_pair(false,644std::string("symbol in offset has no data "645"fragment"));646DF = cast<MCDataFragment>(Fragment);647return std::nullopt;648}649650if (OffsetVal.getSymB())651return std::make_pair(false,652std::string(".reloc symbol offset is not "653"representable"));654655const MCSymbolRefExpr &SRE = cast<MCSymbolRefExpr>(*OffsetVal.getSymA());656if (!SRE.getSymbol().isDefined())657return std::make_pair(false,658std::string("symbol used in the .reloc offset is "659"not defined"));660661if (SRE.getSymbol().isVariable())662return std::make_pair(false,663std::string("symbol used in the .reloc offset is "664"variable"));665666MCFragment *Fragment = SRE.getSymbol().getFragment();667// FIXME Support symbols with no DF. For example:668// .reloc .data, ENUM_VALUE, <some expr>669if (!Fragment || Fragment->getKind() != MCFragment::FT_Data)670return std::make_pair(false,671std::string("symbol in offset has no data "672"fragment"));673RelocOffset = SRE.getSymbol().getOffset() + OffsetVal.getConstant();674DF = cast<MCDataFragment>(Fragment);675} else {676RelocOffset = Symbol.getOffset();677MCFragment *Fragment = Symbol.getFragment();678// FIXME Support symbols with no DF. For example:679// .reloc .data, ENUM_VALUE, <some expr>680if (!Fragment || Fragment->getKind() != MCFragment::FT_Data)681return std::make_pair(false,682std::string("symbol in offset has no data "683"fragment"));684DF = cast<MCDataFragment>(Fragment);685}686return std::nullopt;687}688689std::optional<std::pair<bool, std::string>>690MCObjectStreamer::emitRelocDirective(const MCExpr &Offset, StringRef Name,691const MCExpr *Expr, SMLoc Loc,692const MCSubtargetInfo &STI) {693std::optional<MCFixupKind> MaybeKind =694Assembler->getBackend().getFixupKind(Name);695if (!MaybeKind)696return std::make_pair(true, std::string("unknown relocation name"));697698MCFixupKind Kind = *MaybeKind;699if (Expr)700visitUsedExpr(*Expr);701else702Expr =703MCSymbolRefExpr::create(getContext().createTempSymbol(), getContext());704705MCDataFragment *DF = getOrCreateDataFragment(&STI);706MCValue OffsetVal;707if (!Offset.evaluateAsRelocatable(OffsetVal, nullptr, nullptr))708return std::make_pair(false,709std::string(".reloc offset is not relocatable"));710if (OffsetVal.isAbsolute()) {711if (OffsetVal.getConstant() < 0)712return std::make_pair(false, std::string(".reloc offset is negative"));713DF->getFixups().push_back(714MCFixup::create(OffsetVal.getConstant(), Expr, Kind, Loc));715return std::nullopt;716}717if (OffsetVal.getSymB())718return std::make_pair(false,719std::string(".reloc offset is not representable"));720721const MCSymbolRefExpr &SRE = cast<MCSymbolRefExpr>(*OffsetVal.getSymA());722const MCSymbol &Symbol = SRE.getSymbol();723if (Symbol.isDefined()) {724uint32_t SymbolOffset = 0;725std::optional<std::pair<bool, std::string>> Error =726getOffsetAndDataFragment(Symbol, SymbolOffset, DF);727728if (Error != std::nullopt)729return Error;730731DF->getFixups().push_back(732MCFixup::create(SymbolOffset + OffsetVal.getConstant(),733Expr, Kind, Loc));734return std::nullopt;735}736737PendingFixups.emplace_back(738&SRE.getSymbol(), DF,739MCFixup::create(OffsetVal.getConstant(), Expr, Kind, Loc));740return std::nullopt;741}742743void MCObjectStreamer::emitFill(const MCExpr &NumBytes, uint64_t FillValue,744SMLoc Loc) {745assert(getCurrentSectionOnly() && "need a section");746insert(747getContext().allocFragment<MCFillFragment>(FillValue, 1, NumBytes, Loc));748}749750void MCObjectStreamer::emitFill(const MCExpr &NumValues, int64_t Size,751int64_t Expr, SMLoc Loc) {752int64_t IntNumValues;753// Do additional checking now if we can resolve the value.754if (NumValues.evaluateAsAbsolute(IntNumValues, getAssemblerPtr())) {755if (IntNumValues < 0) {756getContext().getSourceManager()->PrintMessage(757Loc, SourceMgr::DK_Warning,758"'.fill' directive with negative repeat count has no effect");759return;760}761// Emit now if we can for better errors.762int64_t NonZeroSize = Size > 4 ? 4 : Size;763Expr &= ~0ULL >> (64 - NonZeroSize * 8);764for (uint64_t i = 0, e = IntNumValues; i != e; ++i) {765emitIntValue(Expr, NonZeroSize);766if (NonZeroSize < Size)767emitIntValue(0, Size - NonZeroSize);768}769return;770}771772// Otherwise emit as fragment.773assert(getCurrentSectionOnly() && "need a section");774insert(775getContext().allocFragment<MCFillFragment>(Expr, Size, NumValues, Loc));776}777778void MCObjectStreamer::emitNops(int64_t NumBytes, int64_t ControlledNopLength,779SMLoc Loc, const MCSubtargetInfo &STI) {780assert(getCurrentSectionOnly() && "need a section");781insert(getContext().allocFragment<MCNopsFragment>(782NumBytes, ControlledNopLength, Loc, STI));783}784785void MCObjectStreamer::emitFileDirective(StringRef Filename) {786MCAssembler &Asm = getAssembler();787Asm.getWriter().addFileName(Asm, Filename);788}789790void MCObjectStreamer::emitFileDirective(StringRef Filename,791StringRef CompilerVersion,792StringRef TimeStamp,793StringRef Description) {794MCObjectWriter &W = getAssembler().getWriter();795W.addFileName(getAssembler(), Filename);796if (CompilerVersion.size())797W.setCompilerVersion(CompilerVersion);798// TODO: add TimeStamp and Description to .file symbol table entry799// with the integrated assembler.800}801802void MCObjectStreamer::emitAddrsig() {803getAssembler().getWriter().emitAddrsigSection();804}805806void MCObjectStreamer::emitAddrsigSym(const MCSymbol *Sym) {807getAssembler().getWriter().addAddrsigSymbol(Sym);808}809810void MCObjectStreamer::finishImpl() {811getContext().RemapDebugPaths();812813// If we are generating dwarf for assembly source files dump out the sections.814if (getContext().getGenDwarfForAssembly())815MCGenDwarfInfo::Emit(this);816817// Dump out the dwarf file & directory tables and line tables.818MCDwarfLineTable::emit(this, getAssembler().getDWARFLinetableParams());819820// Emit pseudo probes for the current module.821MCPseudoProbeTable::emit(this);822823resolvePendingFixups();824getAssembler().Finish();825}826827828