diff options
Diffstat (limited to 'llvm/lib/MC/MCAsmStreamer.cpp')
| -rw-r--r-- | llvm/lib/MC/MCAsmStreamer.cpp | 182 |
1 files changed, 109 insertions, 73 deletions
diff --git a/llvm/lib/MC/MCAsmStreamer.cpp b/llvm/lib/MC/MCAsmStreamer.cpp index 9309d5987dc9..dd8058c6d5cd 100644 --- a/llvm/lib/MC/MCAsmStreamer.cpp +++ b/llvm/lib/MC/MCAsmStreamer.cpp @@ -55,6 +55,8 @@ class MCAsmStreamer final : public MCStreamer { raw_svector_ostream CommentStream; raw_null_ostream NullStream; + bool EmittedSectionDirective = false; + bool IsVerboseAsm = false; bool ShowInst = false; bool UseDwarfDirectory = false; @@ -160,7 +162,8 @@ public: /// @name MCStreamer Interface /// @{ - void changeSection(MCSection *Section, uint32_t Subsection) override; + void switchSection(MCSection *Section, uint32_t Subsection) override; + bool popSection() override; void emitELFSymverDirective(const MCSymbol *OriginalSym, StringRef Name, bool KeepOriginalSym) override; @@ -169,8 +172,8 @@ public: void emitGNUAttribute(unsigned Tag, unsigned Value) override; - StringRef getMnemonic(MCInst &MI) override { - auto [Ptr, Bits] = InstPrinter->getMnemonic(&MI); + StringRef getMnemonic(const MCInst &MI) const override { + auto [Ptr, Bits] = InstPrinter->getMnemonic(MI); assert((Bits != 0 || Ptr == nullptr) && "Invalid char pointer for instruction with no mnemonic"); return Ptr; @@ -206,6 +209,8 @@ public: void emitCOFFSectionIndex(MCSymbol const *Symbol) override; void emitCOFFSecRel32(MCSymbol const *Symbol, uint64_t Offset) override; void emitCOFFImgRel32(MCSymbol const *Symbol, int64_t Offset) override; + void emitCOFFSecNumber(MCSymbol const *Symbol) override; + void emitCOFFSecOffset(MCSymbol const *Symbol) override; void emitXCOFFLocalCommonSymbol(MCSymbol *LabelSym, uint64_t Size, MCSymbol *CsectSym, Align Alignment) override; void emitXCOFFSymbolLinkageWithVisibility(MCSymbol *Symbol, @@ -301,6 +306,8 @@ public: unsigned Flags, unsigned Isa, unsigned Discriminator, StringRef FileName) override; + virtual void emitDwarfLocLabelDirective(SMLoc Loc, StringRef Name) override; + MCSymbol *getDwarfLineTableSymbol(unsigned CUID) override; bool emitCVFileDirective(unsigned FileNo, StringRef Filename, @@ -371,8 +378,10 @@ public: SMLoc Loc) override; void emitCFIWindowSave(SMLoc Loc) override; void emitCFINegateRAState(SMLoc Loc) override; + void emitCFINegateRAStateWithPC(SMLoc Loc) override; void emitCFIReturnColumn(int64_t Register) override; void emitCFILabelDirective(SMLoc Loc, StringRef Name) override; + void emitCFIValOffset(int64_t Register, int64_t Offset, SMLoc Loc) override; void emitWinCFIStartProc(const MCSymbol *Symbol, SMLoc Loc) override; void emitWinCFIEndProc(SMLoc Loc) override; @@ -429,13 +438,12 @@ public: void emitDwarfLineStartLabel(MCSymbol *StartSym) override; - void emitDwarfLineEndEntry(MCSection *Section, MCSymbol *LastLabel) override; + void emitDwarfLineEndEntry(MCSection *Section, MCSymbol *LastLabel, + MCSymbol *EndLabel = nullptr) override; void emitDwarfAdvanceLineAddr(int64_t LineDelta, const MCSymbol *LastLabel, const MCSymbol *Label, unsigned PointerSize) override; - - void doFinalizationAtSectionEnd(MCSection *Section) override; }; } // end anonymous namespace. @@ -491,7 +499,7 @@ void MCAsmStreamer::addExplicitComment(const Twine &T) { ExplicitCommentToEmit.append("\t"); ExplicitCommentToEmit.append(MAI->getCommentString()); // drop // - ExplicitCommentToEmit.append(c.slice(2, c.size()).str()); + ExplicitCommentToEmit.append(c.substr(2).str()); } else if (c.starts_with(StringRef("/*"))) { size_t p = 2, len = c.size() - 2; // emit each line in comment as separate newline. @@ -512,7 +520,7 @@ void MCAsmStreamer::addExplicitComment(const Twine &T) { ExplicitCommentToEmit.append("\t"); ExplicitCommentToEmit.append(MAI->getCommentString()); - ExplicitCommentToEmit.append(c.slice(1, c.size()).str()); + ExplicitCommentToEmit.append(c.substr(1).str()); } else assert(false && "Unexpected Assembly Comment"); // full line comments immediately output @@ -527,14 +535,27 @@ void MCAsmStreamer::emitExplicitComments() { ExplicitCommentToEmit.clear(); } -void MCAsmStreamer::changeSection(MCSection *Section, uint32_t Subsection) { - if (MCTargetStreamer *TS = getTargetStreamer()) { - TS->changeSection(getCurrentSection().first, Section, Subsection, OS); - } else { - Section->printSwitchToSection(*MAI, getContext().getTargetTriple(), OS, - Subsection); +void MCAsmStreamer::switchSection(MCSection *Section, uint32_t Subsection) { + MCSectionSubPair Cur = getCurrentSection(); + if (!EmittedSectionDirective || + MCSectionSubPair(Section, Subsection) != Cur) { + EmittedSectionDirective = true; + if (MCTargetStreamer *TS = getTargetStreamer()) { + TS->changeSection(Cur.first, Section, Subsection, OS); + } else { + Section->printSwitchToSection(*MAI, getContext().getTargetTriple(), OS, + Subsection); + } } - MCStreamer::changeSection(Section, Subsection); + MCStreamer::switchSection(Section, Subsection); +} + +bool MCAsmStreamer::popSection() { + if (!MCStreamer::popSection()) + return false; + auto [Sec, Subsec] = getCurrentSection(); + Sec->printSwitchToSection(*MAI, getContext().getTargetTriple(), OS, Subsec); + return true; } void MCAsmStreamer::emitELFSymverDirective(const MCSymbol *OriginalSym, @@ -874,6 +895,18 @@ void MCAsmStreamer::emitCOFFImgRel32(MCSymbol const *Symbol, int64_t Offset) { EmitEOL(); } +void MCAsmStreamer::emitCOFFSecNumber(MCSymbol const *Symbol) { + OS << "\t.secnum\t"; + Symbol->print(OS, MAI); + EmitEOL(); +} + +void MCAsmStreamer::emitCOFFSecOffset(MCSymbol const *Symbol) { + OS << "\t.secoffset\t"; + Symbol->print(OS, MAI); + EmitEOL(); +} + // We need an XCOFF-specific version of this directive as the AIX syntax // requires a QualName argument identifying the csect name and storage mapping // class to appear before the alignment if we are specifying it. @@ -1198,7 +1231,7 @@ static void PrintByteList(StringRef Data, raw_ostream &OS, void MCAsmStreamer::PrintQuotedString(StringRef Data, raw_ostream &OS) const { OS << '"'; - if (MAI->hasPairedDoubleQuoteStringConstants()) { + if (MAI->isAIX()) { for (unsigned char C : Data) { if (C == '"') OS << "\"\""; @@ -1252,6 +1285,25 @@ void MCAsmStreamer::emitBytes(StringRef Data) { if (Data.empty()) return; const auto emitAsString = [this](StringRef Data) { + if (MAI->isAIX()) { + if (isPrintableString(Data)) { + // For target with DoubleQuoteString constants, .string and .byte are + // used as replacement of .asciz and .ascii. + if (Data.back() == 0) { + OS << "\t.string\t"; + Data = Data.substr(0, Data.size() - 1); + } else { + OS << "\t.byte\t"; + } + PrintQuotedString(Data, OS); + } else { + OS << "\t.byte\t"; + PrintByteList(Data, OS, MAI->characterLiteralSyntax()); + } + EmitEOL(); + return true; + } + // If the data ends with 0 and the target supports .asciz, use it, otherwise // use .ascii or a byte-list directive if (MAI->getAscizDirective() && Data.back() == 0) { @@ -1259,27 +1311,6 @@ void MCAsmStreamer::emitBytes(StringRef Data) { Data = Data.substr(0, Data.size() - 1); } else if (LLVM_LIKELY(MAI->getAsciiDirective())) { OS << MAI->getAsciiDirective(); - } else if (MAI->hasPairedDoubleQuoteStringConstants() && - isPrintableString(Data)) { - // For target with DoubleQuoteString constants, .string and .byte are used - // as replacement of .asciz and .ascii. - assert(MAI->getPlainStringDirective() && - "hasPairedDoubleQuoteStringConstants target must support " - "PlainString Directive"); - assert(MAI->getByteListDirective() && - "hasPairedDoubleQuoteStringConstants target must support ByteList " - "Directive"); - if (Data.back() == 0) { - OS << MAI->getPlainStringDirective(); - Data = Data.substr(0, Data.size() - 1); - } else { - OS << MAI->getByteListDirective(); - } - } else if (MAI->getByteListDirective()) { - OS << MAI->getByteListDirective(); - PrintByteList(Data, OS, MAI->characterLiteralSyntax()); - EmitEOL(); - return true; } else { return false; } @@ -1462,7 +1493,7 @@ void MCAsmStreamer::emitFill(const MCExpr &NumBytes, uint64_t FillValue, return; if (const char *ZeroDirective = MAI->getZeroDirective()) { - if (MAI->doesZeroDirectiveSupportNonZeroValue() || FillValue == 0) { + if (!MAI->isAIX() || FillValue == 0) { // FIXME: Emit location directives OS << ZeroDirective; NumBytes.print(OS, MAI); @@ -1498,7 +1529,7 @@ void MCAsmStreamer::emitAlignmentDirective(uint64_t ByteAlignment, std::optional<int64_t> Value, unsigned ValueSize, unsigned MaxBytesToEmit) { - if (MAI->useDotAlignForAlignment()) { + if (MAI->isAIX()) { if (!isPowerOf2_64(ByteAlignment)) report_fatal_error("Only power-of-two alignments are supported " "with .align."); @@ -1602,7 +1633,7 @@ void MCAsmStreamer::emitFileDirective(StringRef Filename, StringRef CompilerVersion, StringRef TimeStamp, StringRef Description) { - assert(MAI->hasFourStringsDotFile()); + assert(MAI->isAIX()); OS << "\t.file\t"; PrintQuotedString(Filename, OS); bool useTimeStamp = !TimeStamp.empty(); @@ -1673,8 +1704,7 @@ Expected<unsigned> MCAsmStreamer::tryEmitDwarfFileDirective( // Return early if this file is already emitted before or if target doesn't // support .file directive. - if (NumFiles == Table.getMCDwarfFiles().size() || - !MAI->usesDwarfFileAndLocDirectives()) + if (NumFiles == Table.getMCDwarfFiles().size() || MAI->isAIX()) return FileNo; SmallString<128> Str; @@ -1703,7 +1733,7 @@ void MCAsmStreamer::emitDwarfFile0Directive( Source); // Target doesn't support .loc/.file directives, return early. - if (!MAI->usesDwarfFileAndLocDirectives()) + if (MAI->isAIX()) return; SmallString<128> Str; @@ -1723,7 +1753,7 @@ void MCAsmStreamer::emitDwarfLocDirective(unsigned FileNo, unsigned Line, StringRef FileName) { // If target doesn't support .loc/.file directive, we need to record the lines // same way like we do in object mode. - if (!MAI->usesDwarfFileAndLocDirectives()) { + if (MAI->isAIX()) { // In case we see two .loc directives in a row, make sure the // first one gets a line entry. MCDwarfLineEntry::make(this, getCurrentSectionOnly()); @@ -1767,6 +1797,12 @@ void MCAsmStreamer::emitDwarfLocDirective(unsigned FileNo, unsigned Line, Discriminator, FileName); } +void MCAsmStreamer::emitDwarfLocLabelDirective(SMLoc Loc, StringRef Name) { + MCStreamer::emitDwarfLocLabelDirective(Loc, Name); + OS << ".loc_label\t" << Name; + EmitEOL(); +} + MCSymbol *MCAsmStreamer::getDwarfLineTableSymbol(unsigned CUID) { // Always use the zeroth line table, since asm syntax only supports one line // table for now. @@ -1971,7 +2007,7 @@ void MCAsmStreamer::EmitRegisterName(int64_t Register) { // just ones that map to LLVM register numbers and have known names. // Fall back to using the original number directly if no name is known. const MCRegisterInfo *MRI = getContext().getRegisterInfo(); - if (std::optional<unsigned> LLVMRegister = + if (std::optional<MCRegister> LLVMRegister = MRI->getLLVMRegNum(Register, true)) { InstPrinter->printRegName(OS, *LLVMRegister); return; @@ -2136,6 +2172,12 @@ void MCAsmStreamer::emitCFINegateRAState(SMLoc Loc) { EmitEOL(); } +void MCAsmStreamer::emitCFINegateRAStateWithPC(SMLoc Loc) { + MCStreamer::emitCFINegateRAStateWithPC(Loc); + OS << "\t.cfi_negate_ra_state_with_pc"; + EmitEOL(); +} + void MCAsmStreamer::emitCFIReturnColumn(int64_t Register) { MCStreamer::emitCFIReturnColumn(Register); OS << "\t.cfi_return_column "; @@ -2161,6 +2203,15 @@ void MCAsmStreamer::emitCFIMTETaggedFrame() { EmitEOL(); } +void MCAsmStreamer::emitCFIValOffset(int64_t Register, int64_t Offset, + SMLoc Loc) { + MCStreamer::emitCFIValOffset(Register, Offset, Loc); + OS << "\t.cfi_val_offset "; + EmitRegisterName(Register); + OS << ", " << Offset; + EmitEOL(); +} + void MCAsmStreamer::emitWinCFIStartProc(const MCSymbol *Symbol, SMLoc Loc) { MCStreamer::emitWinCFIStartProc(Symbol, Loc); @@ -2402,10 +2453,7 @@ void MCAsmStreamer::AddEncodingComment(const MCInst &Inst, void MCAsmStreamer::emitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI) { - assert(getCurrentSectionOnly() && - "Cannot emit contents before setting section!"); - - if (!MAI->usesDwarfFileAndLocDirectives()) + if (MAI->isAIX() && CurFrag) // 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()); @@ -2508,7 +2556,7 @@ void MCAsmStreamer::finishImpl() { // Now it is time to emit debug line sections if target doesn't support .loc // and .line directives. - if (!MAI->usesDwarfFileAndLocDirectives()) { + if (MAI->isAIX()) { MCDwarfLineTable::emit(this, getAssembler().getDWARFLinetableParams()); return; } @@ -2520,7 +2568,7 @@ void MCAsmStreamer::finishImpl() { if (!Tables.empty()) { assert(Tables.size() == 1 && "asm output only supports one line table"); if (auto *Label = Tables.begin()->second.getLabel()) { - switchSection(getContext().getObjectFileInfo()->getDwarfLineSection()); + switchSection(getContext().getObjectFileInfo()->getDwarfLineSection(), 0); emitLabel(Label); } } @@ -2533,7 +2581,7 @@ void MCAsmStreamer::emitDwarfUnitLength(uint64_t Length, const Twine &Comment) { // the debug section headers. In such cases, any label we placed occurs // after the implied length field. We need to adjust the reference here // to account for the offset introduced by the inserted length field. - if (!MAI->needsDwarfSectionSizeInHeader()) + if (MAI->isAIX()) return; MCStreamer::emitDwarfUnitLength(Length, Comment); } @@ -2546,7 +2594,7 @@ MCSymbol *MCAsmStreamer::emitDwarfUnitLength(const Twine &Prefix, // the debug section headers. In such cases, any label we placed occurs // after the implied length field. We need to adjust the reference here // to account for the offset introduced by the inserted length field. - if (!MAI->needsDwarfSectionSizeInHeader()) + if (MAI->isAIX()) return getContext().createTempSymbol(Prefix + "_end"); return MCStreamer::emitDwarfUnitLength(Prefix, Comment); } @@ -2559,7 +2607,7 @@ void MCAsmStreamer::emitDwarfLineStartLabel(MCSymbol *StartSym) { // after the implied length field. We need to adjust the reference here // to account for the offset introduced by the inserted length field. MCContext &Ctx = getContext(); - if (!MAI->needsDwarfSectionSizeInHeader()) { + if (MAI->isAIX()) { MCSymbol *DebugLineSymTmp = Ctx.createTempSymbol("debug_line_"); // Emit the symbol which does not contain the unit length field. emitLabel(DebugLineSymTmp); @@ -2579,13 +2627,14 @@ void MCAsmStreamer::emitDwarfLineStartLabel(MCSymbol *StartSym) { } void MCAsmStreamer::emitDwarfLineEndEntry(MCSection *Section, - MCSymbol *LastLabel) { + MCSymbol *LastLabel, + MCSymbol *EndLabel) { // If the targets write the raw debug line data for assembly output (We can // not switch to Section and add the end symbol there for assembly output) // we currently use the .text end label as any section end. This will not // impact the debugability as we will jump to the caller of the last function // in the section before we come into the .text end address. - assert(!MAI->usesDwarfFileAndLocDirectives() && + assert(MAI->isAIX() && ".loc should not be generated together with raw data!"); MCContext &Ctx = getContext(); @@ -2596,9 +2645,10 @@ void MCAsmStreamer::emitDwarfLineEndEntry(MCSection *Section, MCSection *TextSection = Ctx.getObjectFileInfo()->getTextSection(); assert(TextSection->hasEnded() && ".text section is not end!"); - MCSymbol *SectionEnd = TextSection->getEndSymbol(Ctx); + if (!EndLabel) + EndLabel = TextSection->getEndSymbol(Ctx); const MCAsmInfo *AsmInfo = Ctx.getAsmInfo(); - emitDwarfAdvanceLineAddr(INT64_MAX, LastLabel, SectionEnd, + emitDwarfAdvanceLineAddr(INT64_MAX, LastLabel, EndLabel, AsmInfo->getCodePointerSize()); } @@ -2607,7 +2657,7 @@ void MCAsmStreamer::emitDwarfAdvanceLineAddr(int64_t LineDelta, const MCSymbol *LastLabel, const MCSymbol *Label, unsigned PointerSize) { - assert(!MAI->usesDwarfFileAndLocDirectives() && + assert(MAI->isAIX() && ".loc/.file don't need raw data in debug line section!"); // Set to new address. @@ -2641,20 +2691,6 @@ void MCAsmStreamer::emitDwarfAdvanceLineAddr(int64_t LineDelta, emitIntValue(dwarf::DW_LNS_copy, 1); } -void MCAsmStreamer::doFinalizationAtSectionEnd(MCSection *Section) { - // Emit section end. This is used to tell the debug line section where the end - // is for a text section if we don't use .loc to represent the debug line. - if (MAI->usesDwarfFileAndLocDirectives()) - return; - - switchSectionNoPrint(Section); - - MCSymbol *Sym = getCurrentSectionOnly()->getEndSymbol(getContext()); - - if (!Sym->isInSection()) - emitLabel(Sym); -} - MCStreamer *llvm::createAsmStreamer(MCContext &Context, std::unique_ptr<formatted_raw_ostream> OS, MCInstPrinter *IP, |
