792 lines · cpp
1//===- lib/MC/MCObjectStreamer.cpp - Object File MCStreamer Interface -----===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "llvm/MC/MCObjectStreamer.h"10#include "llvm/MC/MCAsmBackend.h"11#include "llvm/MC/MCAsmInfo.h"12#include "llvm/MC/MCAssembler.h"13#include "llvm/MC/MCCodeEmitter.h"14#include "llvm/MC/MCCodeView.h"15#include "llvm/MC/MCContext.h"16#include "llvm/MC/MCDwarf.h"17#include "llvm/MC/MCExpr.h"18#include "llvm/MC/MCObjectFileInfo.h"19#include "llvm/MC/MCObjectWriter.h"20#include "llvm/MC/MCSFrame.h"21#include "llvm/MC/MCSection.h"22#include "llvm/MC/MCSymbol.h"23#include "llvm/Support/ErrorHandling.h"24#include "llvm/Support/SourceMgr.h"25using namespace llvm;26 27MCObjectStreamer::MCObjectStreamer(MCContext &Context,28 std::unique_ptr<MCAsmBackend> TAB,29 std::unique_ptr<MCObjectWriter> OW,30 std::unique_ptr<MCCodeEmitter> Emitter)31 : MCStreamer(Context),32 Assembler(std::make_unique<MCAssembler>(33 Context, std::move(TAB), std::move(Emitter), std::move(OW))),34 EmitEHFrame(true), EmitDebugFrame(false), EmitSFrame(false) {35 assert(Assembler->getBackendPtr() && Assembler->getEmitterPtr());36 IsObj = true;37 setAllowAutoPadding(Assembler->getBackend().allowAutoPadding());38 if (Context.getTargetOptions() && Context.getTargetOptions()->MCRelaxAll)39 Assembler->setRelaxAll(true);40}41 42MCObjectStreamer::~MCObjectStreamer() = default;43 44MCAssembler *MCObjectStreamer::getAssemblerPtr() {45 if (getUseAssemblerInfoForParsing())46 return Assembler.get();47 return nullptr;48}49 50constexpr size_t FragBlockSize = 16384;51// Ensure the new fragment can at least store a few bytes.52constexpr size_t NewFragHeadroom = 8;53 54static_assert(NewFragHeadroom >= alignof(MCFragment));55static_assert(FragBlockSize >= sizeof(MCFragment) + NewFragHeadroom);56 57MCFragment *MCObjectStreamer::allocFragSpace(size_t Headroom) {58 auto Size = std::max(FragBlockSize, sizeof(MCFragment) + Headroom);59 FragSpace = Size - sizeof(MCFragment);60 auto Block = std::unique_ptr<uint8_t[]>(new uint8_t[Size]);61 auto *F = reinterpret_cast<MCFragment *>(Block.get());62 FragStorage.push_back(std::move(Block));63 return F;64}65 66void MCObjectStreamer::newFragment() {67 MCFragment *F;68 if (LLVM_LIKELY(sizeof(MCFragment) + NewFragHeadroom <= FragSpace)) {69 auto End = reinterpret_cast<size_t>(getCurFragEnd());70 F = reinterpret_cast<MCFragment *>(71 alignToPowerOf2(End, alignof(MCFragment)));72 FragSpace -= size_t(F) - End + sizeof(MCFragment);73 } else {74 F = allocFragSpace(0);75 }76 new (F) MCFragment();77 addFragment(F);78}79 80void MCObjectStreamer::ensureHeadroom(size_t Headroom) {81 if (Headroom <= FragSpace)82 return;83 auto *F = allocFragSpace(Headroom);84 new (F) MCFragment();85 addFragment(F);86}87 88void MCObjectStreamer::addSpecialFragment(MCFragment *Frag) {89 assert(Frag->getKind() != MCFragment::FT_Data &&90 "Frag should have a variable-size tail");91 // Frag is not connected to FragSpace. Before modifying CurFrag with92 // addFragment(Frag), allocate an empty fragment to maintain FragSpace93 // connectivity, potentially reusing CurFrag's associated space.94 MCFragment *F;95 if (LLVM_LIKELY(sizeof(MCFragment) + NewFragHeadroom <= FragSpace)) {96 auto End = reinterpret_cast<size_t>(getCurFragEnd());97 F = reinterpret_cast<MCFragment *>(98 alignToPowerOf2(End, alignof(MCFragment)));99 FragSpace -= size_t(F) - End + sizeof(MCFragment);100 } else {101 F = allocFragSpace(0);102 }103 new (F) MCFragment();104 105 addFragment(Frag);106 addFragment(F);107}108 109void MCObjectStreamer::appendContents(ArrayRef<char> Contents) {110 ensureHeadroom(Contents.size());111 assert(FragSpace >= Contents.size());112 llvm::copy(Contents, getCurFragEnd());113 CurFrag->FixedSize += Contents.size();114 FragSpace -= Contents.size();115}116 117void MCObjectStreamer::appendContents(size_t Num, uint8_t Elt) {118 ensureHeadroom(Num);119 MutableArrayRef<uint8_t> Data(getCurFragEnd(), Num);120 llvm::fill(Data, Elt);121 CurFrag->FixedSize += Num;122 FragSpace -= Num;123}124 125void MCObjectStreamer::addFixup(const MCExpr *Value, MCFixupKind Kind) {126 CurFrag->addFixup(MCFixup::create(getCurFragSize(), Value, Kind));127}128 129// As a compile-time optimization, avoid allocating and evaluating an MCExpr130// tree for (Hi - Lo) when Hi and Lo are offsets into the same fragment's fixed131// part.132static std::optional<uint64_t> absoluteSymbolDiff(const MCSymbol *Hi,133 const MCSymbol *Lo) {134 assert(Hi && Lo);135 if (Lo == Hi)136 return 0;137 if (Hi->isVariable() || Lo->isVariable())138 return std::nullopt;139 auto *LoF = Lo->getFragment();140 if (!LoF || Hi->getFragment() != LoF || LoF->isLinkerRelaxable())141 return std::nullopt;142 // If either symbol resides in the variable part, bail out.143 auto Fixed = LoF->getFixedSize();144 if (Lo->getOffset() > Fixed || Hi->getOffset() > Fixed)145 return std::nullopt;146 147 return Hi->getOffset() - Lo->getOffset();148}149 150void MCObjectStreamer::emitAbsoluteSymbolDiff(const MCSymbol *Hi,151 const MCSymbol *Lo,152 unsigned Size) {153 if (std::optional<uint64_t> Diff = absoluteSymbolDiff(Hi, Lo))154 emitIntValue(*Diff, Size);155 else156 MCStreamer::emitAbsoluteSymbolDiff(Hi, Lo, Size);157}158 159void MCObjectStreamer::emitAbsoluteSymbolDiffAsULEB128(const MCSymbol *Hi,160 const MCSymbol *Lo) {161 if (std::optional<uint64_t> Diff = absoluteSymbolDiff(Hi, Lo))162 emitULEB128IntValue(*Diff);163 else164 MCStreamer::emitAbsoluteSymbolDiffAsULEB128(Hi, Lo);165}166 167void MCObjectStreamer::reset() {168 if (Assembler) {169 Assembler->reset();170 if (getContext().getTargetOptions())171 Assembler->setRelaxAll(getContext().getTargetOptions()->MCRelaxAll);172 }173 EmitEHFrame = true;174 EmitDebugFrame = false;175 FragStorage.clear();176 FragSpace = 0;177 SpecialFragAllocator.Reset();178 MCStreamer::reset();179}180 181void MCObjectStreamer::emitFrames() {182 if (!getNumFrameInfos())183 return;184 185 auto *MAB = &getAssembler().getBackend();186 if (EmitEHFrame)187 MCDwarfFrameEmitter::Emit(*this, MAB, true);188 189 if (EmitDebugFrame)190 MCDwarfFrameEmitter::Emit(*this, MAB, false);191 192 if (EmitSFrame || (getContext().getTargetOptions() &&193 getContext().getTargetOptions()->EmitSFrameUnwind))194 MCSFrameEmitter::emit(*this);195}196 197void MCObjectStreamer::visitUsedSymbol(const MCSymbol &Sym) {198 Assembler->registerSymbol(Sym);199}200 201void MCObjectStreamer::emitCFISections(bool EH, bool Debug, bool SFrame) {202 MCStreamer::emitCFISections(EH, Debug, SFrame);203 EmitEHFrame = EH;204 EmitDebugFrame = Debug;205 EmitSFrame = SFrame;206}207 208void MCObjectStreamer::emitValueImpl(const MCExpr *Value, unsigned Size,209 SMLoc Loc) {210 MCStreamer::emitValueImpl(Value, Size, Loc);211 212 MCDwarfLineEntry::make(this, getCurrentSectionOnly());213 214 // Avoid fixups when possible.215 int64_t AbsValue;216 if (Value->evaluateAsAbsolute(AbsValue, getAssemblerPtr())) {217 if (!isUIntN(8 * Size, AbsValue) && !isIntN(8 * Size, AbsValue)) {218 getContext().reportError(219 Loc, "value evaluated as " + Twine(AbsValue) + " is out of range.");220 return;221 }222 emitIntValue(AbsValue, Size);223 return;224 }225 ensureHeadroom(Size);226 addFixup(Value, MCFixup::getDataKindForSize(Size));227 appendContents(Size, 0);228}229 230MCSymbol *MCObjectStreamer::emitCFILabel() {231 MCSymbol *Label = getContext().createTempSymbol("cfi");232 emitLabel(Label);233 return Label;234}235 236void MCObjectStreamer::emitCFIStartProcImpl(MCDwarfFrameInfo &Frame) {237 // We need to create a local symbol to avoid relocations.238 Frame.Begin = getContext().createTempSymbol();239 emitLabel(Frame.Begin);240}241 242void MCObjectStreamer::emitCFIEndProcImpl(MCDwarfFrameInfo &Frame) {243 Frame.End = getContext().createTempSymbol();244 emitLabel(Frame.End);245}246 247void MCObjectStreamer::emitLabel(MCSymbol *Symbol, SMLoc Loc) {248 MCStreamer::emitLabel(Symbol, Loc);249 // If Symbol is a non-redefiniable variable, emitLabel has reported an error.250 // Bail out.251 if (Symbol->isVariable())252 return;253 254 getAssembler().registerSymbol(*Symbol);255 256 // Set the fragment and offset. This function might be called by257 // changeSection, when the section stack top hasn't been changed to the new258 // section.259 MCFragment *F = CurFrag;260 Symbol->setFragment(F);261 Symbol->setOffset(F->getFixedSize());262 263 emitPendingAssignments(Symbol);264}265 266void MCObjectStreamer::emitPendingAssignments(MCSymbol *Symbol) {267 auto Assignments = pendingAssignments.find(Symbol);268 if (Assignments != pendingAssignments.end()) {269 for (const PendingAssignment &A : Assignments->second)270 emitAssignment(A.Symbol, A.Value);271 272 pendingAssignments.erase(Assignments);273 }274}275 276// Emit a label at a previously emitted fragment/offset position. This must be277// within the currently-active section.278void MCObjectStreamer::emitLabelAtPos(MCSymbol *Symbol, SMLoc Loc,279 MCFragment &F, uint64_t Offset) {280 assert(F.getParent() == getCurrentSectionOnly());281 MCStreamer::emitLabel(Symbol, Loc);282 getAssembler().registerSymbol(*Symbol);283 Symbol->setFragment(&F);284 Symbol->setOffset(Offset);285}286 287void MCObjectStreamer::emitULEB128Value(const MCExpr *Value) {288 int64_t IntValue;289 if (Value->evaluateAsAbsolute(IntValue, getAssembler())) {290 emitULEB128IntValue(IntValue);291 return;292 }293 auto *F = getCurrentFragment();294 F->makeLEB(false, Value);295 newFragment();296}297 298void MCObjectStreamer::emitSLEB128Value(const MCExpr *Value) {299 int64_t IntValue;300 if (Value->evaluateAsAbsolute(IntValue, getAssembler())) {301 emitSLEB128IntValue(IntValue);302 return;303 }304 auto *F = getCurrentFragment();305 F->makeLEB(true, Value);306 newFragment();307}308 309void MCObjectStreamer::emitWeakReference(MCSymbol *Alias,310 const MCSymbol *Target) {311 reportFatalUsageError("this file format doesn't support weak aliases");312}313 314void MCObjectStreamer::changeSection(MCSection *Section, uint32_t Subsection) {315 assert(Section && "Cannot switch to a null section!");316 getContext().clearDwarfLocSeen();317 318 // Register the section and create an initial fragment for subsection 0319 // if `Subsection` is non-zero.320 bool NewSec = getAssembler().registerSection(*Section);321 MCFragment *F0 = nullptr;322 if (NewSec && Subsection) {323 changeSection(Section, 0);324 F0 = CurFrag;325 }326 327 // To maintain connectivity between CurFrag and FragSpace when CurFrag is328 // modified, allocate an empty fragment and append it to the fragment list.329 // (Subsections[I].second.Tail is not connected to FragSpace.)330 MCFragment *F;331 if (LLVM_LIKELY(sizeof(MCFragment) + NewFragHeadroom <= FragSpace)) {332 auto End = reinterpret_cast<size_t>(getCurFragEnd());333 F = reinterpret_cast<MCFragment *>(334 alignToPowerOf2(End, alignof(MCFragment)));335 FragSpace -= size_t(F) - End + sizeof(MCFragment);336 } else {337 F = allocFragSpace(0);338 }339 new (F) MCFragment();340 F->setParent(Section);341 342 auto &Subsections = Section->Subsections;343 size_t I = 0, E = Subsections.size();344 while (I != E && Subsections[I].first < Subsection)345 ++I;346 // If the subsection number is not in the sorted Subsections list, create a347 // new fragment list.348 if (I == E || Subsections[I].first != Subsection) {349 Subsections.insert(Subsections.begin() + I,350 {Subsection, MCSection::FragList{F, F}});351 Section->CurFragList = &Subsections[I].second;352 CurFrag = F;353 } else {354 Section->CurFragList = &Subsections[I].second;355 CurFrag = Subsections[I].second.Tail;356 // Ensure CurFrag is associated with FragSpace.357 addFragment(F);358 }359 360 // Define the section symbol at subsection 0's initial fragment if required.361 if (!NewSec)362 return;363 if (auto *Sym = Section->getBeginSymbol()) {364 Sym->setFragment(Subsection ? F0 : CurFrag);365 getAssembler().registerSymbol(*Sym);366 }367}368 369void MCObjectStreamer::emitAssignment(MCSymbol *Symbol, const MCExpr *Value) {370 getAssembler().registerSymbol(*Symbol);371 MCStreamer::emitAssignment(Symbol, Value);372 emitPendingAssignments(Symbol);373}374 375void MCObjectStreamer::emitConditionalAssignment(MCSymbol *Symbol,376 const MCExpr *Value) {377 const MCSymbol *Target = &cast<MCSymbolRefExpr>(*Value).getSymbol();378 379 // If the symbol already exists, emit the assignment. Otherwise, emit it380 // later only if the symbol is also emitted.381 if (Target->isRegistered())382 emitAssignment(Symbol, Value);383 else384 pendingAssignments[Target].push_back({Symbol, Value});385}386 387bool MCObjectStreamer::mayHaveInstructions(MCSection &Sec) const {388 return Sec.hasInstructions();389}390 391void MCObjectStreamer::emitInstruction(const MCInst &Inst,392 const MCSubtargetInfo &STI) {393 MCStreamer::emitInstruction(Inst, STI);394 395 MCSection *Sec = getCurrentSectionOnly();396 Sec->setHasInstructions(true);397 398 // Now that a machine instruction has been assembled into this section, make399 // a line entry for any .loc directive that has been seen.400 MCDwarfLineEntry::make(this, getCurrentSectionOnly());401 402 // If this instruction doesn't need relaxation, just emit it as data.403 MCAssembler &Assembler = getAssembler();404 MCAsmBackend &Backend = Assembler.getBackend();405 if (!(Backend.mayNeedRelaxation(Inst.getOpcode(), Inst.getOperands(), STI) ||406 Backend.allowEnhancedRelaxation())) {407 emitInstToData(Inst, STI);408 return;409 }410 411 // Otherwise, relax and emit it as data if RelaxAll is specified.412 if (Assembler.getRelaxAll()) {413 MCInst Relaxed = Inst;414 while (Backend.mayNeedRelaxation(Relaxed.getOpcode(), Relaxed.getOperands(),415 STI))416 Backend.relaxInstruction(Relaxed, STI);417 emitInstToData(Relaxed, STI);418 return;419 }420 421 emitInstToFragment(Inst, STI);422}423 424void MCObjectStreamer::emitInstToData(const MCInst &Inst,425 const MCSubtargetInfo &STI) {426 MCFragment *F = getCurrentFragment();427 428 // Append the instruction to the data fragment.429 size_t CodeOffset = getCurFragSize();430 SmallString<16> Content;431 SmallVector<MCFixup, 1> Fixups;432 getAssembler().getEmitter().encodeInstruction(Inst, Content, Fixups, STI);433 appendContents(Content);434 if (CurFrag != F) {435 F = CurFrag;436 CodeOffset = 0;437 }438 F->setHasInstructions(STI);439 440 if (Fixups.empty())441 return;442 bool MarkedLinkerRelaxable = false;443 for (auto &Fixup : Fixups) {444 Fixup.setOffset(Fixup.getOffset() + CodeOffset);445 if (!Fixup.isLinkerRelaxable() || MarkedLinkerRelaxable)446 continue;447 MarkedLinkerRelaxable = true;448 // Set the fragment's order within the subsection for use by449 // MCAssembler::relaxAlign.450 auto *Sec = F->getParent();451 if (!Sec->isLinkerRelaxable())452 Sec->setFirstLinkerRelaxable(F->getLayoutOrder());453 // Do not add data after a linker-relaxable instruction. The difference454 // between a new label and a label at or before the linker-relaxable455 // instruction cannot be resolved at assemble-time.456 F->setLinkerRelaxable();457 newFragment();458 }459 F->appendFixups(Fixups);460}461 462void MCObjectStreamer::emitInstToFragment(const MCInst &Inst,463 const MCSubtargetInfo &STI) {464 auto *F = getCurrentFragment();465 SmallVector<char, 16> Data;466 SmallVector<MCFixup, 1> Fixups;467 getAssembler().getEmitter().encodeInstruction(Inst, Data, Fixups, STI);468 469 F->Kind = MCFragment::FT_Relaxable;470 F->setHasInstructions(STI);471 472 F->setVarContents(Data);473 F->setInst(Inst);474 475 bool MarkedLinkerRelaxable = false;476 for (auto &Fixup : Fixups) {477 if (!Fixup.isLinkerRelaxable() || MarkedLinkerRelaxable)478 continue;479 MarkedLinkerRelaxable = true;480 auto *Sec = F->getParent();481 if (!Sec->isLinkerRelaxable())482 Sec->setFirstLinkerRelaxable(F->getLayoutOrder());483 F->setLinkerRelaxable();484 }485 F->setVarFixups(Fixups);486 487 newFragment();488}489 490void MCObjectStreamer::emitDwarfLocDirective(unsigned FileNo, unsigned Line,491 unsigned Column, unsigned Flags,492 unsigned Isa,493 unsigned Discriminator,494 StringRef FileName,495 StringRef Comment) {496 // In case we see two .loc directives in a row, make sure the497 // first one gets a line entry.498 MCDwarfLineEntry::make(this, getCurrentSectionOnly());499 500 this->MCStreamer::emitDwarfLocDirective(FileNo, Line, Column, Flags, Isa,501 Discriminator, FileName, Comment);502}503 504static const MCExpr *buildSymbolDiff(MCObjectStreamer &OS, const MCSymbol *A,505 const MCSymbol *B, SMLoc Loc) {506 MCContext &Context = OS.getContext();507 const MCExpr *ARef = MCSymbolRefExpr::create(A, Context);508 const MCExpr *BRef = MCSymbolRefExpr::create(B, Context);509 const MCExpr *AddrDelta =510 MCBinaryExpr::create(MCBinaryExpr::Sub, ARef, BRef, Context, Loc);511 return AddrDelta;512}513 514static void emitDwarfSetLineAddr(MCObjectStreamer &OS,515 MCDwarfLineTableParams Params,516 int64_t LineDelta, const MCSymbol *Label,517 int PointerSize) {518 // emit the sequence to set the address519 OS.emitIntValue(dwarf::DW_LNS_extended_op, 1);520 OS.emitULEB128IntValue(PointerSize + 1);521 OS.emitIntValue(dwarf::DW_LNE_set_address, 1);522 OS.emitSymbolValue(Label, PointerSize);523 524 // emit the sequence for the LineDelta (from 1) and a zero address delta.525 MCDwarfLineAddr::Emit(&OS, Params, LineDelta, 0);526}527 528void MCObjectStreamer::emitDwarfAdvanceLineAddr(int64_t LineDelta,529 const MCSymbol *LastLabel,530 const MCSymbol *Label,531 unsigned PointerSize) {532 if (!LastLabel) {533 emitDwarfSetLineAddr(*this, Assembler->getDWARFLinetableParams(), LineDelta,534 Label, PointerSize);535 return;536 }537 538 // If the two labels are within the same fragment, then the address-offset is539 // already a fixed constant and is not relaxable. Emit the advance-line-addr540 // data immediately to save time and memory.541 if (auto OptAddrDelta = absoluteSymbolDiff(Label, LastLabel)) {542 SmallString<16> Tmp;543 MCDwarfLineAddr::encode(getContext(), Assembler->getDWARFLinetableParams(),544 LineDelta, *OptAddrDelta, Tmp);545 emitBytes(Tmp);546 return;547 }548 549 auto *F = getCurrentFragment();550 F->Kind = MCFragment::FT_Dwarf;551 F->setDwarfAddrDelta(buildSymbolDiff(*this, Label, LastLabel, SMLoc()));552 F->setDwarfLineDelta(LineDelta);553 newFragment();554}555 556void MCObjectStreamer::emitDwarfLineEndEntry(MCSection *Section,557 MCSymbol *LastLabel,558 MCSymbol *EndLabel) {559 // Emit a DW_LNE_end_sequence into the line table. When EndLabel is null, it560 // means we should emit the entry for the end of the section and therefore we561 // use the section end label for the reference label. After having the562 // appropriate reference label, we emit the address delta and use INT64_MAX as563 // the line delta which is the signal that this is actually a564 // DW_LNE_end_sequence.565 if (!EndLabel)566 EndLabel = endSection(Section);567 568 // Switch back the dwarf line section, in case endSection had to switch the569 // section.570 MCContext &Ctx = getContext();571 switchSection(Ctx.getObjectFileInfo()->getDwarfLineSection());572 573 const MCAsmInfo *AsmInfo = Ctx.getAsmInfo();574 emitDwarfAdvanceLineAddr(INT64_MAX, LastLabel, EndLabel,575 AsmInfo->getCodePointerSize());576}577 578void MCObjectStreamer::emitDwarfAdvanceFrameAddr(const MCSymbol *LastLabel,579 const MCSymbol *Label,580 SMLoc Loc) {581 auto *F = getCurrentFragment();582 F->Kind = MCFragment::FT_DwarfFrame;583 F->setDwarfAddrDelta(buildSymbolDiff(*this, Label, LastLabel, Loc));584 newFragment();585}586 587void MCObjectStreamer::emitSFrameCalculateFuncOffset(const MCSymbol *FuncBase,588 const MCSymbol *FREBegin,589 MCFragment *FDEFrag,590 SMLoc Loc) {591 assert(FuncBase && "No function base address");592 assert(FREBegin && "FRE doesn't describe a location");593 auto *F = getCurrentFragment();594 F->Kind = MCFragment::FT_SFrame;595 F->setSFrameAddrDelta(buildSymbolDiff(*this, FREBegin, FuncBase, Loc));596 F->setSFrameFDE(FDEFrag);597 newFragment();598}599 600void MCObjectStreamer::emitCVLocDirective(unsigned FunctionId, unsigned FileNo,601 unsigned Line, unsigned Column,602 bool PrologueEnd, bool IsStmt,603 StringRef FileName, SMLoc Loc) {604 // Validate the directive.605 if (!checkCVLocSection(FunctionId, FileNo, Loc))606 return;607 608 // Emit a label at the current position and record it in the CodeViewContext.609 MCSymbol *LineSym = getContext().createTempSymbol();610 emitLabel(LineSym);611 getContext().getCVContext().recordCVLoc(getContext(), LineSym, FunctionId,612 FileNo, Line, Column, PrologueEnd,613 IsStmt);614}615 616void MCObjectStreamer::emitCVLinetableDirective(unsigned FunctionId,617 const MCSymbol *Begin,618 const MCSymbol *End) {619 getContext().getCVContext().emitLineTableForFunction(*this, FunctionId, Begin,620 End);621 this->MCStreamer::emitCVLinetableDirective(FunctionId, Begin, End);622}623 624void MCObjectStreamer::emitCVInlineLinetableDirective(625 unsigned PrimaryFunctionId, unsigned SourceFileId, unsigned SourceLineNum,626 const MCSymbol *FnStartSym, const MCSymbol *FnEndSym) {627 getContext().getCVContext().emitInlineLineTableForFunction(628 *this, PrimaryFunctionId, SourceFileId, SourceLineNum, FnStartSym,629 FnEndSym);630 this->MCStreamer::emitCVInlineLinetableDirective(631 PrimaryFunctionId, SourceFileId, SourceLineNum, FnStartSym, FnEndSym);632}633 634void MCObjectStreamer::emitCVDefRangeDirective(635 ArrayRef<std::pair<const MCSymbol *, const MCSymbol *>> Ranges,636 StringRef FixedSizePortion) {637 getContext().getCVContext().emitDefRange(*this, Ranges, FixedSizePortion);638 // Attach labels that were pending before we created the defrange fragment to639 // the beginning of the new fragment.640 this->MCStreamer::emitCVDefRangeDirective(Ranges, FixedSizePortion);641}642 643void MCObjectStreamer::emitCVStringTableDirective() {644 getContext().getCVContext().emitStringTable(*this);645}646void MCObjectStreamer::emitCVFileChecksumsDirective() {647 getContext().getCVContext().emitFileChecksums(*this);648}649 650void MCObjectStreamer::emitCVFileChecksumOffsetDirective(unsigned FileNo) {651 getContext().getCVContext().emitFileChecksumOffset(*this, FileNo);652}653 654void MCObjectStreamer::emitBytes(StringRef Data) {655 MCDwarfLineEntry::make(this, getCurrentSectionOnly());656 appendContents(ArrayRef(Data.data(), Data.size()));657}658 659void MCObjectStreamer::emitValueToAlignment(Align Alignment, int64_t Fill,660 uint8_t FillLen,661 unsigned MaxBytesToEmit) {662 if (MaxBytesToEmit == 0)663 MaxBytesToEmit = Alignment.value();664 MCFragment *F = getCurrentFragment();665 F->makeAlign(Alignment, Fill, FillLen, MaxBytesToEmit);666 newFragment();667 668 // Update the maximum alignment on the current section if necessary.669 F->getParent()->ensureMinAlignment(Alignment);670}671 672void MCObjectStreamer::emitCodeAlignment(Align Alignment,673 const MCSubtargetInfo *STI,674 unsigned MaxBytesToEmit) {675 auto *F = getCurrentFragment();676 emitValueToAlignment(Alignment, 0, 1, MaxBytesToEmit);677 F->u.align.EmitNops = true;678 F->STI = STI;679}680 681void MCObjectStreamer::emitValueToOffset(const MCExpr *Offset,682 unsigned char Value,683 SMLoc Loc) {684 newSpecialFragment<MCOrgFragment>(*Offset, Value, Loc);685}686 687void MCObjectStreamer::emitRelocDirective(const MCExpr &Offset, StringRef Name,688 const MCExpr *Expr, SMLoc Loc) {689 std::optional<MCFixupKind> MaybeKind =690 Assembler->getBackend().getFixupKind(Name);691 if (!MaybeKind) {692 getContext().reportError(Loc, "unknown relocation name");693 return;694 }695 696 MCFixupKind Kind = *MaybeKind;697 if (Expr)698 visitUsedExpr(*Expr);699 else700 Expr =701 MCSymbolRefExpr::create(getContext().createTempSymbol(), getContext());702 703 auto *O = &Offset;704 int64_t Val;705 if (Offset.evaluateAsAbsolute(Val, nullptr)) {706 auto *SecSym = getCurrentSectionOnly()->getBeginSymbol();707 O = MCBinaryExpr::createAdd(MCSymbolRefExpr::create(SecSym, getContext()),708 O, getContext(), Loc);709 }710 getAssembler().addRelocDirective({*O, Expr, Kind});711}712 713void MCObjectStreamer::emitFill(const MCExpr &NumBytes, uint64_t FillValue,714 SMLoc Loc) {715 assert(getCurrentSectionOnly() && "need a section");716 newSpecialFragment<MCFillFragment>(FillValue, 1, NumBytes, Loc);717}718 719void MCObjectStreamer::emitFill(const MCExpr &NumValues, int64_t Size,720 int64_t Expr, SMLoc Loc) {721 int64_t IntNumValues;722 // Do additional checking now if we can resolve the value.723 if (NumValues.evaluateAsAbsolute(IntNumValues, getAssembler())) {724 if (IntNumValues < 0) {725 getContext().getSourceManager()->PrintMessage(726 Loc, SourceMgr::DK_Warning,727 "'.fill' directive with negative repeat count has no effect");728 return;729 }730 // Emit now if we can for better errors.731 int64_t NonZeroSize = Size > 4 ? 4 : Size;732 Expr &= ~0ULL >> (64 - NonZeroSize * 8);733 for (uint64_t i = 0, e = IntNumValues; i != e; ++i) {734 emitIntValue(Expr, NonZeroSize);735 if (NonZeroSize < Size)736 emitIntValue(0, Size - NonZeroSize);737 }738 return;739 }740 741 // Otherwise emit as fragment.742 assert(getCurrentSectionOnly() && "need a section");743 newSpecialFragment<MCFillFragment>(Expr, Size, NumValues, Loc);744}745 746void MCObjectStreamer::emitNops(int64_t NumBytes, int64_t ControlledNopLength,747 SMLoc Loc, const MCSubtargetInfo &STI) {748 assert(getCurrentSectionOnly() && "need a section");749 newSpecialFragment<MCNopsFragment>(NumBytes, ControlledNopLength, Loc, STI);750}751 752void MCObjectStreamer::emitFileDirective(StringRef Filename) {753 MCAssembler &Asm = getAssembler();754 Asm.getWriter().addFileName(Filename);755}756 757void MCObjectStreamer::emitFileDirective(StringRef Filename,758 StringRef CompilerVersion,759 StringRef TimeStamp,760 StringRef Description) {761 MCObjectWriter &W = getAssembler().getWriter();762 W.addFileName(Filename);763 if (CompilerVersion.size())764 W.setCompilerVersion(CompilerVersion);765 // TODO: add TimeStamp and Description to .file symbol table entry766 // with the integrated assembler.767}768 769void MCObjectStreamer::emitAddrsig() {770 getAssembler().getWriter().emitAddrsigSection();771}772 773void MCObjectStreamer::emitAddrsigSym(const MCSymbol *Sym) {774 getAssembler().getWriter().addAddrsigSymbol(Sym);775}776 777void MCObjectStreamer::finishImpl() {778 getContext().RemapDebugPaths();779 780 // If we are generating dwarf for assembly source files dump out the sections.781 if (getContext().getGenDwarfForAssembly())782 MCGenDwarfInfo::Emit(this);783 784 // Dump out the dwarf file & directory tables and line tables.785 MCDwarfLineTable::emit(this, getAssembler().getDWARFLinetableParams());786 787 // Emit pseudo probes for the current module.788 MCPseudoProbeTable::emit(this);789 790 getAssembler().Finish();791}792