|  | //===- lib/MC/MCObjectStreamer.cpp - Object File MCStreamer Interface -----===// | 
|  | // | 
|  | //                     The LLVM Compiler Infrastructure | 
|  | // | 
|  | // This file is distributed under the University of Illinois Open Source | 
|  | // License. See LICENSE.TXT for details. | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  |  | 
|  | #include "llvm/MC/MCObjectStreamer.h" | 
|  | #include "llvm/ADT/STLExtras.h" | 
|  | #include "llvm/MC/MCAsmBackend.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/MCObjectWriter.h" | 
|  | #include "llvm/MC/MCSection.h" | 
|  | #include "llvm/MC/MCSymbol.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(llvm::make_unique<MCAssembler>( | 
|  | Context, std::move(TAB), std::move(Emitter), std::move(OW))), | 
|  | EmitEHFrame(true), EmitDebugFrame(false) {} | 
|  |  | 
|  | MCObjectStreamer::~MCObjectStreamer() {} | 
|  |  | 
|  | // 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::flushPendingLabels(MCFragment *F, uint64_t FOffset) { | 
|  | if (PendingLabels.empty()) | 
|  | return; | 
|  | if (!F) { | 
|  | F = new MCDataFragment(); | 
|  | MCSection *CurSection = getCurrentSectionOnly(); | 
|  | CurSection->getFragmentList().insert(CurInsertionPoint, F); | 
|  | F->setParent(CurSection); | 
|  | } | 
|  | for (MCSymbol *Sym : PendingLabels) { | 
|  | Sym->setFragment(F); | 
|  | Sym->setOffset(FOffset); | 
|  | } | 
|  | PendingLabels.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 Optional<uint64_t> | 
|  | absoluteSymbolDiff(MCAssembler &Asm, const MCSymbol *Hi, const MCSymbol *Lo) { | 
|  | assert(Hi && Lo); | 
|  | if (Asm.getBackendPtr()->requiresDiffExpressionRelocations()) | 
|  | return None; | 
|  |  | 
|  | if (!Hi->getFragment() || Hi->getFragment() != Lo->getFragment() || | 
|  | Hi->isVariable() || Lo->isVariable()) | 
|  | return None; | 
|  |  | 
|  | return Hi->getOffset() - Lo->getOffset(); | 
|  | } | 
|  |  | 
|  | void MCObjectStreamer::emitAbsoluteSymbolDiff(const MCSymbol *Hi, | 
|  | const MCSymbol *Lo, | 
|  | unsigned Size) { | 
|  | if (Optional<uint64_t> Diff = absoluteSymbolDiff(getAssembler(), Hi, Lo)) { | 
|  | EmitIntValue(*Diff, Size); | 
|  | return; | 
|  | } | 
|  | MCStreamer::emitAbsoluteSymbolDiff(Hi, Lo, Size); | 
|  | } | 
|  |  | 
|  | void MCObjectStreamer::emitAbsoluteSymbolDiffAsULEB128(const MCSymbol *Hi, | 
|  | const MCSymbol *Lo) { | 
|  | if (Optional<uint64_t> Diff = absoluteSymbolDiff(getAssembler(), 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(); | 
|  | 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; | 
|  | } | 
|  |  | 
|  | MCPaddingFragment *MCObjectStreamer::getOrCreatePaddingFragment() { | 
|  | MCPaddingFragment *F = | 
|  | dyn_cast_or_null<MCPaddingFragment>(getCurrentFragment()); | 
|  | if (!F) { | 
|  | F = new MCPaddingFragment(); | 
|  | 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", true); | 
|  | 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 { | 
|  | PendingLabels.push_back(Symbol); | 
|  | } | 
|  | } | 
|  |  | 
|  | void MCObjectStreamer::EmitLabel(MCSymbol *Symbol, SMLoc Loc, MCFragment *F) { | 
|  | MCStreamer::EmitLabel(Symbol, Loc); | 
|  | getAssembler().registerSymbol(*Symbol); | 
|  | auto *DF = dyn_cast_or_null<MCDataFragment>(F); | 
|  | if (DF) | 
|  | Symbol->setFragment(F); | 
|  | else | 
|  | PendingLabels.push_back(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!"); | 
|  | flushPendingLabels(nullptr); | 
|  | 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"); | 
|  | CurInsertionPoint = | 
|  | Section->getSubsectionInsertionPoint(unsigned(IntSubsection)); | 
|  | return Created; | 
|  | } | 
|  |  | 
|  | void MCObjectStreamer::EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) { | 
|  | getAssembler().registerSymbol(*Symbol); | 
|  | MCStreamer::EmitAssignment(Symbol, Value); | 
|  | } | 
|  |  | 
|  | bool MCObjectStreamer::mayHaveInstructions(MCSection &Sec) const { | 
|  | return Sec.hasInstructions(); | 
|  | } | 
|  |  | 
|  | void MCObjectStreamer::EmitInstruction(const MCInst &Inst, | 
|  | const MCSubtargetInfo &STI, bool) { | 
|  | getAssembler().getBackend().handleCodePaddingInstructionBegin(Inst); | 
|  | EmitInstructionImpl(Inst, STI); | 
|  | getAssembler().getBackend().handleCodePaddingInstructionEnd(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(); | 
|  | if (!Assembler.getBackend().mayNeedRelaxation(Inst, STI)) { | 
|  | 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; | 
|  | getAssembler().getBackend().relaxInstruction(Inst, STI, Relaxed); | 
|  | while (getAssembler().getBackend().mayNeedRelaxation(Relaxed, STI)) | 
|  | getAssembler().getBackend().relaxInstruction(Relaxed, STI, Relaxed); | 
|  | 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(unsigned AlignPow2) { | 
|  | 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::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) { | 
|  | getContext().getCVContext().emitDefRange(*this, Ranges, FixedSizePortion); | 
|  | 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()); | 
|  |  | 
|  | // EmitBytes might not cover all possible ways we emit data (or could be used | 
|  | // to emit executable code in some cases), but is the best method we have | 
|  | // right now for checking this. | 
|  | MCSection *Sec = getCurrentSectionOnly(); | 
|  | Sec->setHasData(true); | 
|  | } | 
|  |  | 
|  | void MCObjectStreamer::EmitValueToAlignment(unsigned ByteAlignment, | 
|  | int64_t Value, | 
|  | unsigned ValueSize, | 
|  | unsigned MaxBytesToEmit) { | 
|  | if (MaxBytesToEmit == 0) | 
|  | MaxBytesToEmit = ByteAlignment; | 
|  | insert(new MCAlignFragment(ByteAlignment, Value, ValueSize, MaxBytesToEmit)); | 
|  |  | 
|  | // Update the maximum alignment on the current section if necessary. | 
|  | MCSection *CurSec = getCurrentSectionOnly(); | 
|  | if (ByteAlignment > CurSec->getAlignment()) | 
|  | CurSec->setAlignment(ByteAlignment); | 
|  | } | 
|  |  | 
|  | void MCObjectStreamer::EmitCodeAlignment(unsigned ByteAlignment, | 
|  | unsigned MaxBytesToEmit) { | 
|  | EmitValueToAlignment(ByteAlignment, 0, 1, MaxBytesToEmit); | 
|  | cast<MCAlignFragment>(getCurrentFragment())->setEmitNops(true); | 
|  | } | 
|  |  | 
|  | void MCObjectStreamer::emitValueToOffset(const MCExpr *Offset, | 
|  | unsigned char Value, | 
|  | SMLoc Loc) { | 
|  | insert(new MCOrgFragment(*Offset, Value, Loc)); | 
|  | } | 
|  |  | 
|  | void MCObjectStreamer::EmitCodePaddingBasicBlockStart( | 
|  | const MCCodePaddingContext &Context) { | 
|  | getAssembler().getBackend().handleCodePaddingBasicBlockStart(this, Context); | 
|  | } | 
|  |  | 
|  | void MCObjectStreamer::EmitCodePaddingBasicBlockEnd( | 
|  | const MCCodePaddingContext &Context) { | 
|  | getAssembler().getBackend().handleCodePaddingBasicBlockEnd(Context); | 
|  | } | 
|  |  | 
|  | // 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); | 
|  | } | 
|  |  | 
|  | bool MCObjectStreamer::EmitRelocDirective(const MCExpr &Offset, StringRef Name, | 
|  | const MCExpr *Expr, SMLoc Loc, | 
|  | const MCSubtargetInfo &STI) { | 
|  | int64_t OffsetValue; | 
|  | if (!Offset.evaluateAsAbsolute(OffsetValue)) | 
|  | llvm_unreachable("Offset is not absolute"); | 
|  |  | 
|  | if (OffsetValue < 0) | 
|  | llvm_unreachable("Offset is negative"); | 
|  |  | 
|  | MCDataFragment *DF = getOrCreateDataFragment(&STI); | 
|  | flushPendingLabels(DF, DF->getContents().size()); | 
|  |  | 
|  | Optional<MCFixupKind> MaybeKind = Assembler->getBackend().getFixupKind(Name); | 
|  | if (!MaybeKind.hasValue()) | 
|  | return true; | 
|  |  | 
|  | MCFixupKind Kind = *MaybeKind; | 
|  |  | 
|  | if (Expr == nullptr) | 
|  | Expr = | 
|  | MCSymbolRefExpr::create(getContext().createTempSymbol(), getContext()); | 
|  | DF->getFixups().push_back(MCFixup::create(OffsetValue, Expr, Kind, Loc)); | 
|  | return false; | 
|  | } | 
|  |  | 
|  | 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::EmitFileDirective(StringRef Filename) { | 
|  | getAssembler().addFileName(Filename); | 
|  | } | 
|  |  | 
|  | void MCObjectStreamer::EmitAddrsig() { | 
|  | getAssembler().getWriter().emitAddrsigSection(); | 
|  | } | 
|  |  | 
|  | void MCObjectStreamer::EmitAddrsigSym(const MCSymbol *Sym) { | 
|  | getAssembler().registerSymbol(*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()); | 
|  |  | 
|  | flushPendingLabels(); | 
|  | getAssembler().Finish(); | 
|  | } |