aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/MC/MCAsmStreamer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/MC/MCAsmStreamer.cpp')
-rw-r--r--llvm/lib/MC/MCAsmStreamer.cpp182
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,