aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/llvm/lib/MC
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2022-03-20 11:40:34 +0000
committerDimitry Andric <dim@FreeBSD.org>2022-05-14 11:43:05 +0000
commit349cc55c9796c4596a5b9904cd3281af295f878f (patch)
tree410c5a785075730a35f1272ca6a7adf72222ad03 /contrib/llvm-project/llvm/lib/MC
parentcb2ae6163174b90e999326ecec3699ee093a5d43 (diff)
parentc0981da47d5696fe36474fcf86b4ce03ae3ff818 (diff)
downloadsrc-349cc55c9796c4596a5b9904cd3281af295f878f.tar.gz
src-349cc55c9796c4596a5b9904cd3281af295f878f.zip
Merge llvm-project main llvmorg-14-init-10186-gff7f2cfa959b
This updates llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp to llvmorg-14-init-10186-gff7f2cfa959b. PR: 261742 MFC after: 2 weeks
Diffstat (limited to 'contrib/llvm-project/llvm/lib/MC')
-rw-r--r--contrib/llvm-project/llvm/lib/MC/ConstantPools.cpp2
-rw-r--r--contrib/llvm-project/llvm/lib/MC/ELFObjectWriter.cpp3
-rw-r--r--contrib/llvm-project/llvm/lib/MC/MCAsmInfoGOFF.cpp27
-rw-r--r--contrib/llvm-project/llvm/lib/MC/MCAsmStreamer.cpp5
-rw-r--r--contrib/llvm-project/llvm/lib/MC/MCAssembler.cpp17
-rw-r--r--contrib/llvm-project/llvm/lib/MC/MCContext.cpp2
-rw-r--r--contrib/llvm-project/llvm/lib/MC/MCDisassembler/Disassembler.cpp2
-rw-r--r--contrib/llvm-project/llvm/lib/MC/MCDisassembler/MCRelocationInfo.cpp2
-rw-r--r--contrib/llvm-project/llvm/lib/MC/MCDwarf.cpp94
-rw-r--r--contrib/llvm-project/llvm/lib/MC/MCELFStreamer.cpp11
-rw-r--r--contrib/llvm-project/llvm/lib/MC/MCExpr.cpp4
-rw-r--r--contrib/llvm-project/llvm/lib/MC/MCFragment.cpp8
-rw-r--r--contrib/llvm-project/llvm/lib/MC/MCInstrAnalysis.cpp12
-rw-r--r--contrib/llvm-project/llvm/lib/MC/MCMachOStreamer.cpp2
-rw-r--r--contrib/llvm-project/llvm/lib/MC/MCObjectFileInfo.cpp15
-rw-r--r--contrib/llvm-project/llvm/lib/MC/MCObjectStreamer.cpp10
-rw-r--r--contrib/llvm-project/llvm/lib/MC/MCParser/AsmLexer.cpp3
-rw-r--r--contrib/llvm-project/llvm/lib/MC/MCParser/AsmParser.cpp18
-rw-r--r--contrib/llvm-project/llvm/lib/MC/MCParser/ELFAsmParser.cpp25
-rw-r--r--contrib/llvm-project/llvm/lib/MC/MCParser/GOFFAsmParser.cpp48
-rw-r--r--contrib/llvm-project/llvm/lib/MC/MCParser/MasmParser.cpp7
-rw-r--r--contrib/llvm-project/llvm/lib/MC/MCPseudoProbe.cpp392
-rw-r--r--contrib/llvm-project/llvm/lib/MC/MCSectionXCOFF.cpp6
-rw-r--r--contrib/llvm-project/llvm/lib/MC/MCStreamer.cpp7
-rw-r--r--contrib/llvm-project/llvm/lib/MC/MCWasmStreamer.cpp87
-rw-r--r--contrib/llvm-project/llvm/lib/MC/MCWin64EH.cpp6
-rw-r--r--contrib/llvm-project/llvm/lib/MC/MCWinCOFFStreamer.cpp9
-rw-r--r--contrib/llvm-project/llvm/lib/MC/MCXCOFFStreamer.cpp2
-rw-r--r--contrib/llvm-project/llvm/lib/MC/MachObjectWriter.cpp2
-rw-r--r--contrib/llvm-project/llvm/lib/MC/TargetRegistry.cpp134
-rw-r--r--contrib/llvm-project/llvm/lib/MC/WasmObjectWriter.cpp79
-rw-r--r--contrib/llvm-project/llvm/lib/MC/XCOFFObjectWriter.cpp339
32 files changed, 1176 insertions, 204 deletions
diff --git a/contrib/llvm-project/llvm/lib/MC/ConstantPools.cpp b/contrib/llvm-project/llvm/lib/MC/ConstantPools.cpp
index d4199025ad77..d8a08a4bd439 100644
--- a/contrib/llvm-project/llvm/lib/MC/ConstantPools.cpp
+++ b/contrib/llvm-project/llvm/lib/MC/ConstantPools.cpp
@@ -28,7 +28,7 @@ void ConstantPool::emitEntries(MCStreamer &Streamer) {
return;
Streamer.emitDataRegion(MCDR_DataRegion);
for (const ConstantPoolEntry &Entry : Entries) {
- Streamer.emitCodeAlignment(Entry.Size); // align naturally
+ Streamer.emitValueToAlignment(Entry.Size); // align naturally
Streamer.emitLabel(Entry.Label);
Streamer.emitValue(Entry.Value, Entry.Size, Entry.Loc);
}
diff --git a/contrib/llvm-project/llvm/lib/MC/ELFObjectWriter.cpp b/contrib/llvm-project/llvm/lib/MC/ELFObjectWriter.cpp
index e0ea44626b7f..883735fcc293 100644
--- a/contrib/llvm-project/llvm/lib/MC/ELFObjectWriter.cpp
+++ b/contrib/llvm-project/llvm/lib/MC/ELFObjectWriter.cpp
@@ -796,7 +796,7 @@ MCSectionELF *ELFWriter::createRelocationSection(MCContext &Ctx,
else
EntrySize = is64Bit() ? sizeof(ELF::Elf64_Rel) : sizeof(ELF::Elf32_Rel);
- unsigned Flags = 0;
+ unsigned Flags = ELF::SHF_INFO_LINK;
if (Sec.getFlags() & ELF::SHF_GROUP)
Flags = ELF::SHF_GROUP;
@@ -1311,6 +1311,7 @@ bool ELFObjectWriter::shouldRelocateWithSymbol(const MCAssembler &Asm,
case MCSymbolRefExpr::VK_GOT:
case MCSymbolRefExpr::VK_PLT:
case MCSymbolRefExpr::VK_GOTPCREL:
+ case MCSymbolRefExpr::VK_GOTPCREL_NORELAX:
case MCSymbolRefExpr::VK_PPC_GOT_LO:
case MCSymbolRefExpr::VK_PPC_GOT_HI:
case MCSymbolRefExpr::VK_PPC_GOT_HA:
diff --git a/contrib/llvm-project/llvm/lib/MC/MCAsmInfoGOFF.cpp b/contrib/llvm-project/llvm/lib/MC/MCAsmInfoGOFF.cpp
new file mode 100644
index 000000000000..81704ffe4b24
--- /dev/null
+++ b/contrib/llvm-project/llvm/lib/MC/MCAsmInfoGOFF.cpp
@@ -0,0 +1,27 @@
+//===- MCAsmInfoGOFF.cpp - MCGOFFAsmInfo properties -----------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file defines certain target specific asm properties for GOFF (z/OS)
+/// based targets.
+///
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCAsmInfoGOFF.h"
+
+using namespace llvm;
+
+void MCAsmInfoGOFF::anchor() {}
+
+MCAsmInfoGOFF::MCAsmInfoGOFF() {
+ Data64bitsDirective = "\t.quad\t";
+ HasDotTypeDotSizeDirective = false;
+ PrivateGlobalPrefix = "@@";
+ PrivateLabelPrefix = "@";
+ ZeroDirective = "\t.space\t";
+}
diff --git a/contrib/llvm-project/llvm/lib/MC/MCAsmStreamer.cpp b/contrib/llvm-project/llvm/lib/MC/MCAsmStreamer.cpp
index 72f4ee3f33be..154b2d051f34 100644
--- a/contrib/llvm-project/llvm/lib/MC/MCAsmStreamer.cpp
+++ b/contrib/llvm-project/llvm/lib/MC/MCAsmStreamer.cpp
@@ -30,13 +30,13 @@
#include "llvm/MC/MCSectionMachO.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSymbolXCOFF.h"
+#include "llvm/MC/TargetRegistry.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/LEB128.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/Path.h"
-#include "llvm/Support/TargetRegistry.h"
#include <cctype>
using namespace llvm;
@@ -245,7 +245,7 @@ public:
unsigned ValueSize = 1,
unsigned MaxBytesToEmit = 0) override;
- void emitCodeAlignment(unsigned ByteAlignment,
+ void emitCodeAlignment(unsigned ByteAlignment, const MCSubtargetInfo *STI,
unsigned MaxBytesToEmit = 0) override;
void emitValueToOffset(const MCExpr *Offset,
@@ -1429,6 +1429,7 @@ void MCAsmStreamer::emitValueToAlignment(unsigned ByteAlignment, int64_t Value,
}
void MCAsmStreamer::emitCodeAlignment(unsigned ByteAlignment,
+ const MCSubtargetInfo *STI,
unsigned MaxBytesToEmit) {
// Emit with a text fill value.
emitValueToAlignment(ByteAlignment, MAI->getTextAlignFillValue(),
diff --git a/contrib/llvm-project/llvm/lib/MC/MCAssembler.cpp b/contrib/llvm-project/llvm/lib/MC/MCAssembler.cpp
index 9ed8d1083a40..d5e9f4fc66bc 100644
--- a/contrib/llvm-project/llvm/lib/MC/MCAssembler.cpp
+++ b/contrib/llvm-project/llvm/lib/MC/MCAssembler.cpp
@@ -483,6 +483,7 @@ void MCAssembler::writeFragmentPadding(raw_ostream &OS,
"Writing bundle padding for a fragment without instructions");
unsigned TotalLength = BundlePadding + static_cast<unsigned>(FSize);
+ const MCSubtargetInfo *STI = EF.getSubtargetInfo();
if (EF.alignToBundleEnd() && TotalLength > getBundleAlignSize()) {
// If the padding itself crosses a bundle boundary, it must be emitted
// in 2 pieces, since even nop instructions must not cross boundaries.
@@ -493,12 +494,12 @@ void MCAssembler::writeFragmentPadding(raw_ostream &OS,
// ----------------------------
// ^-------------------^ <- TotalLength
unsigned DistanceToBoundary = TotalLength - getBundleAlignSize();
- if (!getBackend().writeNopData(OS, DistanceToBoundary))
+ if (!getBackend().writeNopData(OS, DistanceToBoundary, STI))
report_fatal_error("unable to write NOP sequence of " +
Twine(DistanceToBoundary) + " bytes");
BundlePadding -= DistanceToBoundary;
}
- if (!getBackend().writeNopData(OS, BundlePadding))
+ if (!getBackend().writeNopData(OS, BundlePadding, STI))
report_fatal_error("unable to write NOP sequence of " +
Twine(BundlePadding) + " bytes");
}
@@ -544,7 +545,7 @@ static void writeFragment(raw_ostream &OS, const MCAssembler &Asm,
// bytes left to fill use the Value and ValueSize to fill the rest.
// If we are aligning with nops, ask that target to emit the right data.
if (AF.hasEmitNops()) {
- if (!Asm.getBackend().writeNopData(OS, Count))
+ if (!Asm.getBackend().writeNopData(OS, Count, AF.getSubtargetInfo()))
report_fatal_error("unable to write nop sequence of " +
Twine(Count) + " bytes");
break;
@@ -621,9 +622,11 @@ static void writeFragment(raw_ostream &OS, const MCAssembler &Asm,
case MCFragment::FT_Nops: {
++stats::EmittedNopsFragments;
const MCNopsFragment &NF = cast<MCNopsFragment>(F);
+
int64_t NumBytes = NF.getNumBytes();
int64_t ControlledNopLength = NF.getControlledNopLength();
- int64_t MaximumNopLength = Asm.getBackend().getMaximumNopSize();
+ int64_t MaximumNopLength =
+ Asm.getBackend().getMaximumNopSize(*NF.getSubtargetInfo());
assert(NumBytes > 0 && "Expected positive NOPs fragment size");
assert(ControlledNopLength >= 0 && "Expected non-negative NOP size");
@@ -647,7 +650,8 @@ static void writeFragment(raw_ostream &OS, const MCAssembler &Asm,
uint64_t NumBytesToEmit =
(uint64_t)std::min(NumBytes, ControlledNopLength);
assert(NumBytesToEmit && "try to emit empty NOP instruction");
- if (!Asm.getBackend().writeNopData(OS, NumBytesToEmit)) {
+ if (!Asm.getBackend().writeNopData(OS, NumBytesToEmit,
+ NF.getSubtargetInfo())) {
report_fatal_error("unable to write nop sequence of the remaining " +
Twine(NumBytesToEmit) + " bytes");
break;
@@ -664,7 +668,8 @@ static void writeFragment(raw_ostream &OS, const MCAssembler &Asm,
}
case MCFragment::FT_BoundaryAlign: {
- if (!Asm.getBackend().writeNopData(OS, FragmentSize))
+ const MCBoundaryAlignFragment &BF = cast<MCBoundaryAlignFragment>(F);
+ if (!Asm.getBackend().writeNopData(OS, FragmentSize, BF.getSubtargetInfo()))
report_fatal_error("unable to write nop sequence of " +
Twine(FragmentSize) + " bytes");
break;
diff --git a/contrib/llvm-project/llvm/lib/MC/MCContext.cpp b/contrib/llvm-project/llvm/lib/MC/MCContext.cpp
index cc349af6393b..aa4051aa2400 100644
--- a/contrib/llvm-project/llvm/lib/MC/MCContext.cpp
+++ b/contrib/llvm-project/llvm/lib/MC/MCContext.cpp
@@ -586,7 +586,7 @@ void MCContext::recordELFMergeableSectionInfo(StringRef SectionName,
unsigned Flags, unsigned UniqueID,
unsigned EntrySize) {
bool IsMergeable = Flags & ELF::SHF_MERGE;
- if (IsMergeable && (UniqueID == GenericSectionID))
+ if (UniqueID == GenericSectionID)
ELFSeenGenericMergeableSections.insert(SectionName);
// For mergeable sections or non-mergeable sections with a generic mergeable
diff --git a/contrib/llvm-project/llvm/lib/MC/MCDisassembler/Disassembler.cpp b/contrib/llvm-project/llvm/lib/MC/MCDisassembler/Disassembler.cpp
index 52ab0b41f539..aaa3b747682c 100644
--- a/contrib/llvm-project/llvm/lib/MC/MCDisassembler/Disassembler.cpp
+++ b/contrib/llvm-project/llvm/lib/MC/MCDisassembler/Disassembler.cpp
@@ -25,9 +25,9 @@
#include "llvm/MC/MCSchedule.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/MC/MCTargetOptions.h"
+#include "llvm/MC/TargetRegistry.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FormattedStream.h"
-#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/raw_ostream.h"
#include <cassert>
#include <cstddef>
diff --git a/contrib/llvm-project/llvm/lib/MC/MCDisassembler/MCRelocationInfo.cpp b/contrib/llvm-project/llvm/lib/MC/MCDisassembler/MCRelocationInfo.cpp
index 64e216e0051d..735be23206e4 100644
--- a/contrib/llvm-project/llvm/lib/MC/MCDisassembler/MCRelocationInfo.cpp
+++ b/contrib/llvm-project/llvm/lib/MC/MCDisassembler/MCRelocationInfo.cpp
@@ -8,7 +8,7 @@
#include "llvm/MC/MCDisassembler/MCRelocationInfo.h"
#include "llvm-c/Disassembler.h"
-#include "llvm/Support/TargetRegistry.h"
+#include "llvm/MC/TargetRegistry.h"
using namespace llvm;
diff --git a/contrib/llvm-project/llvm/lib/MC/MCDwarf.cpp b/contrib/llvm-project/llvm/lib/MC/MCDwarf.cpp
index 27bb7a103165..1c9cfb9042e2 100644
--- a/contrib/llvm-project/llvm/lib/MC/MCDwarf.cpp
+++ b/contrib/llvm-project/llvm/lib/MC/MCDwarf.cpp
@@ -27,7 +27,6 @@
#include "llvm/MC/MCSection.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSymbol.h"
-#include "llvm/MC/StringTableBuilder.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/EndianStream.h"
@@ -66,29 +65,6 @@ MCSymbol *mcdwarf::emitListsTableHeaderStart(MCStreamer &S) {
return End;
}
-/// Manage the .debug_line_str section contents, if we use it.
-class llvm::MCDwarfLineStr {
- MCSymbol *LineStrLabel = nullptr;
- StringTableBuilder LineStrings{StringTableBuilder::DWARF};
- bool UseRelocs = false;
-
-public:
- /// Construct an instance that can emit .debug_line_str (for use in a normal
- /// v5 line table).
- explicit MCDwarfLineStr(MCContext &Ctx) {
- UseRelocs = Ctx.getAsmInfo()->doesDwarfUseRelocationsAcrossSections();
- if (UseRelocs)
- LineStrLabel =
- Ctx.getObjectFileInfo()->getDwarfLineStrSection()->getBeginSymbol();
- }
-
- /// Emit a reference to the string.
- void emitRef(MCStreamer *MCOS, StringRef Path);
-
- /// Emit the .debug_line_str section if appropriate.
- void emitSection(MCStreamer *MCOS);
-};
-
static inline uint64_t ScaleAddrDelta(MCContext &Context, uint64_t AddrDelta) {
unsigned MinInsnLength = Context.getAsmInfo()->getMinInstAlignment();
if (MinInsnLength == 1)
@@ -100,6 +76,13 @@ static inline uint64_t ScaleAddrDelta(MCContext &Context, uint64_t AddrDelta) {
return AddrDelta / MinInsnLength;
}
+MCDwarfLineStr::MCDwarfLineStr(MCContext &Ctx) {
+ UseRelocs = Ctx.getAsmInfo()->doesDwarfUseRelocationsAcrossSections();
+ if (UseRelocs)
+ LineStrLabel =
+ Ctx.getObjectFileInfo()->getDwarfLineStrSection()->getBeginSymbol();
+}
+
//
// This is called when an instruction is assembled into the specified section
// and if there is information from the last .loc directive that has yet to have
@@ -158,23 +141,58 @@ makeStartPlusIntExpr(MCContext &Ctx, const MCSymbol &Start, int IntVal) {
return Res;
}
+void MCLineSection::addEndEntry(MCSymbol *EndLabel) {
+ auto *Sec = &EndLabel->getSection();
+ // The line table may be empty, which we should skip adding an end entry.
+ // There are two cases:
+ // (1) MCAsmStreamer - emitDwarfLocDirective emits a location directive in
+ // place instead of adding a line entry if the target has
+ // usesDwarfFileAndLocDirectives.
+ // (2) MCObjectStreamer - if a function has incomplete debug info where
+ // instructions don't have DILocations, the line entries are missing.
+ auto I = MCLineDivisions.find(Sec);
+ if (I != MCLineDivisions.end()) {
+ auto &Entries = I->second;
+ auto EndEntry = Entries.back();
+ EndEntry.setEndLabel(EndLabel);
+ Entries.push_back(EndEntry);
+ }
+}
+
//
// This emits the Dwarf line table for the specified section from the entries
// in the LineSection.
//
-static inline void emitDwarfLineTable(
+void MCDwarfLineTable::emitOne(
MCStreamer *MCOS, MCSection *Section,
const MCLineSection::MCDwarfLineEntryCollection &LineEntries) {
- unsigned FileNum = 1;
- unsigned LastLine = 1;
- unsigned Column = 0;
- unsigned Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0;
- unsigned Isa = 0;
- unsigned Discriminator = 0;
- MCSymbol *LastLabel = nullptr;
+
+ unsigned FileNum, LastLine, Column, Flags, Isa, Discriminator;
+ MCSymbol *LastLabel;
+ auto init = [&]() {
+ FileNum = 1;
+ LastLine = 1;
+ Column = 0;
+ Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0;
+ Isa = 0;
+ Discriminator = 0;
+ LastLabel = nullptr;
+ };
+ init();
// Loop through each MCDwarfLineEntry and encode the dwarf line number table.
+ bool EndEntryEmitted = false;
for (const MCDwarfLineEntry &LineEntry : LineEntries) {
+ MCSymbol *Label = LineEntry.getLabel();
+ const MCAsmInfo *asmInfo = MCOS->getContext().getAsmInfo();
+ if (LineEntry.IsEndEntry) {
+ MCOS->emitDwarfAdvanceLineAddr(INT64_MAX, LastLabel, Label,
+ asmInfo->getCodePointerSize());
+ init();
+ EndEntryEmitted = true;
+ continue;
+ }
+
int64_t LineDelta = static_cast<int64_t>(LineEntry.getLine()) - LastLine;
if (FileNum != LineEntry.getFileNum()) {
@@ -212,12 +230,9 @@ static inline void emitDwarfLineTable(
if (LineEntry.getFlags() & DWARF2_FLAG_EPILOGUE_BEGIN)
MCOS->emitInt8(dwarf::DW_LNS_set_epilogue_begin);
- MCSymbol *Label = LineEntry.getLabel();
-
// At this point we want to emit/create the sequence to encode the delta in
// line numbers and the increment of the address from the previous Label
// and the current Label.
- const MCAsmInfo *asmInfo = MCOS->getContext().getAsmInfo();
MCOS->emitDwarfAdvanceLineAddr(LineDelta, LastLabel, Label,
asmInfo->getCodePointerSize());
@@ -227,7 +242,12 @@ static inline void emitDwarfLineTable(
}
// Generate DWARF line end entry.
- MCOS->emitDwarfLineEndEntry(Section, LastLabel);
+ // We do not need this for DwarfDebug that explicitly terminates the line
+ // table using ranges whenever CU or section changes. However, the MC path
+ // does not track ranges nor terminate the line table. In that case,
+ // conservatively use the section end symbol to end the line table.
+ if (!EndEntryEmitted)
+ MCOS->emitDwarfLineEndEntry(Section, LastLabel);
}
//
@@ -522,7 +542,7 @@ void MCDwarfLineTable::emitCU(MCStreamer *MCOS, MCDwarfLineTableParams Params,
// Put out the line tables.
for (const auto &LineSec : MCLineSections.getMCLineEntries())
- emitDwarfLineTable(MCOS, LineSec.first, LineSec.second);
+ emitOne(MCOS, LineSec.first, LineSec.second);
// This is the end of the section, so set the value of the symbol at the end
// of this section (that was used in a previous expression).
diff --git a/contrib/llvm-project/llvm/lib/MC/MCELFStreamer.cpp b/contrib/llvm-project/llvm/lib/MC/MCELFStreamer.cpp
index 784d66805d63..1ba999a63113 100644
--- a/contrib/llvm-project/llvm/lib/MC/MCELFStreamer.cpp
+++ b/contrib/llvm-project/llvm/lib/MC/MCELFStreamer.cpp
@@ -29,10 +29,10 @@
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/MC/MCSymbolELF.h"
+#include "llvm/MC/TargetRegistry.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/LEB128.h"
-#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/raw_ostream.h"
#include <cassert>
#include <cstdint>
@@ -88,10 +88,10 @@ void MCELFStreamer::mergeFragment(MCDataFragment *DF,
DF->getContents().append(EF->getContents().begin(), EF->getContents().end());
}
-void MCELFStreamer::InitSections(bool NoExecStack) {
+void MCELFStreamer::initSections(bool NoExecStack, const MCSubtargetInfo &STI) {
MCContext &Ctx = getContext();
SwitchSection(Ctx.getObjectFileInfo()->getTextSection());
- emitCodeAlignment(4);
+ emitCodeAlignment(Ctx.getObjectFileInfo()->getTextSectionAlignment(), &STI);
if (NoExecStack)
SwitchSection(Ctx.getAsmInfo()->getNonexecutableStackSection(Ctx));
@@ -224,6 +224,7 @@ bool MCELFStreamer::emitSymbolAttribute(MCSymbol *S, MCSymbolAttr Attribute) {
case MCSA_ELF_TypeGnuUniqueObject:
Symbol->setType(CombineSymbolTypes(Symbol->getType(), ELF::STT_OBJECT));
Symbol->setBinding(ELF::STB_GNU_UNIQUE);
+ getAssembler().getWriter().markGnuAbi();
break;
case MCSA_Global:
@@ -325,7 +326,7 @@ void MCELFStreamer::emitCommonSymbol(MCSymbol *S, uint64_t Size,
SwitchSection(P.first, P.second);
} else {
if(Symbol->declareCommon(Size, ByteAlignment))
- report_fatal_error("Symbol: " + Symbol->getName() +
+ report_fatal_error(Twine("Symbol: ") + Symbol->getName() +
" redeclared as different type");
}
@@ -500,7 +501,7 @@ void MCELFStreamer::finalizeCGProfileEntry(const MCSymbolRefExpr *&SRE,
*MCOffset, "BFD_RELOC_NONE", SRE, SRE->getLoc(),
*getContext().getSubtargetInfo()))
report_fatal_error("Relocation for CG Profile could not be created: " +
- Err->second);
+ Twine(Err->second));
}
void MCELFStreamer::finalizeCGProfile() {
diff --git a/contrib/llvm-project/llvm/lib/MC/MCExpr.cpp b/contrib/llvm-project/llvm/lib/MC/MCExpr.cpp
index 84ec0f6bb57b..10d494b5ac61 100644
--- a/contrib/llvm-project/llvm/lib/MC/MCExpr.cpp
+++ b/contrib/llvm-project/llvm/lib/MC/MCExpr.cpp
@@ -230,6 +230,7 @@ StringRef MCSymbolRefExpr::getVariantKindName(VariantKind Kind) {
case VK_GOTREL: return "GOTREL";
case VK_PCREL: return "PCREL";
case VK_GOTPCREL: return "GOTPCREL";
+ case VK_GOTPCREL_NORELAX: return "GOTPCREL_NORELAX";
case VK_GOTTPOFF: return "GOTTPOFF";
case VK_INDNTPOFF: return "INDNTPOFF";
case VK_NTPOFF: return "NTPOFF";
@@ -358,6 +359,7 @@ StringRef MCSymbolRefExpr::getVariantKindName(VariantKind Kind) {
case VK_WASM_MBREL: return "MBREL";
case VK_WASM_TLSREL: return "TLSREL";
case VK_WASM_TBREL: return "TBREL";
+ case VK_WASM_GOT_TLS: return "GOT@TLS";
case VK_AMDGPU_GOTPCREL32_LO: return "gotpcrel32@lo";
case VK_AMDGPU_GOTPCREL32_HI: return "gotpcrel32@hi";
case VK_AMDGPU_REL32_LO: return "rel32@lo";
@@ -393,6 +395,7 @@ MCSymbolRefExpr::getVariantKindForName(StringRef Name) {
.Case("gotrel", VK_GOTREL)
.Case("pcrel", VK_PCREL)
.Case("gotpcrel", VK_GOTPCREL)
+ .Case("gotpcrel_norelax", VK_GOTPCREL_NORELAX)
.Case("gottpoff", VK_GOTTPOFF)
.Case("indntpoff", VK_INDNTPOFF)
.Case("ntpoff", VK_NTPOFF)
@@ -499,6 +502,7 @@ MCSymbolRefExpr::getVariantKindForName(StringRef Name) {
.Case("tbrel", VK_WASM_TBREL)
.Case("mbrel", VK_WASM_MBREL)
.Case("tlsrel", VK_WASM_TLSREL)
+ .Case("got@tls", VK_WASM_GOT_TLS)
.Case("gotpcrel32@lo", VK_AMDGPU_GOTPCREL32_LO)
.Case("gotpcrel32@hi", VK_AMDGPU_GOTPCREL32_HI)
.Case("rel32@lo", VK_AMDGPU_REL32_LO)
diff --git a/contrib/llvm-project/llvm/lib/MC/MCFragment.cpp b/contrib/llvm-project/llvm/lib/MC/MCFragment.cpp
index 0f8543f51096..4634de863b2f 100644
--- a/contrib/llvm-project/llvm/lib/MC/MCFragment.cpp
+++ b/contrib/llvm-project/llvm/lib/MC/MCFragment.cpp
@@ -128,7 +128,11 @@ static bool getSymbolOffsetImpl(const MCAsmLayout &Layout, const MCSymbol &S,
const MCSymbolRefExpr *A = Target.getSymA();
if (A) {
uint64_t ValA;
- if (!getLabelOffset(Layout, A->getSymbol(), ReportError, ValA))
+ // FIXME: On most platforms, `Target`'s component symbols are labels from
+ // having been simplified during evaluation, but on Mach-O they can be
+ // variables due to PR19203. This, and the line below for `B` can be
+ // restored to call `getLabelOffset` when PR19203 is fixed.
+ if (!getSymbolOffsetImpl(Layout, A->getSymbol(), ReportError, ValA))
return false;
Offset += ValA;
}
@@ -136,7 +140,7 @@ static bool getSymbolOffsetImpl(const MCAsmLayout &Layout, const MCSymbol &S,
const MCSymbolRefExpr *B = Target.getSymB();
if (B) {
uint64_t ValB;
- if (!getLabelOffset(Layout, B->getSymbol(), ReportError, ValB))
+ if (!getSymbolOffsetImpl(Layout, B->getSymbol(), ReportError, ValB))
return false;
Offset -= ValB;
}
diff --git a/contrib/llvm-project/llvm/lib/MC/MCInstrAnalysis.cpp b/contrib/llvm-project/llvm/lib/MC/MCInstrAnalysis.cpp
index a7dc0626d0ab..52b59185c6fc 100644
--- a/contrib/llvm-project/llvm/lib/MC/MCInstrAnalysis.cpp
+++ b/contrib/llvm-project/llvm/lib/MC/MCInstrAnalysis.cpp
@@ -29,8 +29,14 @@ bool MCInstrAnalysis::evaluateBranch(const MCInst & /*Inst*/, uint64_t /*Addr*/,
return false;
}
-Optional<uint64_t>
-MCInstrAnalysis::evaluateMemoryOperandAddress(const MCInst &Inst, uint64_t Addr,
- uint64_t Size) const {
+Optional<uint64_t> MCInstrAnalysis::evaluateMemoryOperandAddress(
+ const MCInst &Inst, const MCSubtargetInfo *STI, uint64_t Addr,
+ uint64_t Size) const {
return None;
}
+
+Optional<uint64_t>
+MCInstrAnalysis::getMemoryOperandRelocationOffset(const MCInst &Inst,
+ uint64_t Size) const {
+ return None;
+} \ No newline at end of file
diff --git a/contrib/llvm-project/llvm/lib/MC/MCMachOStreamer.cpp b/contrib/llvm-project/llvm/lib/MC/MCMachOStreamer.cpp
index f0948a184598..aa94b141d8be 100644
--- a/contrib/llvm-project/llvm/lib/MC/MCMachOStreamer.cpp
+++ b/contrib/llvm-project/llvm/lib/MC/MCMachOStreamer.cpp
@@ -30,9 +30,9 @@
#include "llvm/MC/MCSymbol.h"
#include "llvm/MC/MCSymbolMachO.h"
#include "llvm/MC/MCValue.h"
+#include "llvm/MC/TargetRegistry.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/raw_ostream.h"
#include <cassert>
#include <vector>
diff --git a/contrib/llvm-project/llvm/lib/MC/MCObjectFileInfo.cpp b/contrib/llvm-project/llvm/lib/MC/MCObjectFileInfo.cpp
index 7ea1106068b7..d7f85f793c55 100644
--- a/contrib/llvm-project/llvm/lib/MC/MCObjectFileInfo.cpp
+++ b/contrib/llvm-project/llvm/lib/MC/MCObjectFileInfo.cpp
@@ -896,6 +896,19 @@ void MCObjectFileInfo::initXCOFFMCObjectFileInfo(const Triple &T) {
".rodata", SectionKind::getReadOnly(),
XCOFF::CsectProperties(XCOFF::StorageMappingClass::XMC_RO, XCOFF::XTY_SD),
/* MultiSymbolsAllowed*/ true);
+ ReadOnlySection->setAlignment(Align(4));
+
+ ReadOnly8Section = Ctx->getXCOFFSection(
+ ".rodata.8", SectionKind::getReadOnly(),
+ XCOFF::CsectProperties(XCOFF::StorageMappingClass::XMC_RO, XCOFF::XTY_SD),
+ /* MultiSymbolsAllowed*/ true);
+ ReadOnly8Section->setAlignment(Align(8));
+
+ ReadOnly16Section = Ctx->getXCOFFSection(
+ ".rodata.16", SectionKind::getReadOnly(),
+ XCOFF::CsectProperties(XCOFF::StorageMappingClass::XMC_RO, XCOFF::XTY_SD),
+ /* MultiSymbolsAllowed*/ true);
+ ReadOnly16Section->setAlignment(Align(16));
TLSDataSection = Ctx->getXCOFFSection(
".tdata", SectionKind::getThreadData(),
@@ -968,6 +981,8 @@ void MCObjectFileInfo::initXCOFFMCObjectFileInfo(const Triple &T) {
/* MultiSymbolsAllowed */ true, ".dwmac", XCOFF::SSUBTYP_DWMAC);
}
+MCObjectFileInfo::~MCObjectFileInfo() {}
+
void MCObjectFileInfo::initMCObjectFileInfo(MCContext &MCCtx, bool PIC,
bool LargeCodeModel) {
PositionIndependent = PIC;
diff --git a/contrib/llvm-project/llvm/lib/MC/MCObjectStreamer.cpp b/contrib/llvm-project/llvm/lib/MC/MCObjectStreamer.cpp
index 2865a2ad80a9..9c86fcc86bcb 100644
--- a/contrib/llvm-project/llvm/lib/MC/MCObjectStreamer.cpp
+++ b/contrib/llvm-project/llvm/lib/MC/MCObjectStreamer.cpp
@@ -368,7 +368,7 @@ void MCObjectStreamer::emitInstruction(const MCInst &Inst,
"' cannot have instructions");
return;
}
- getAssembler().getBackend().emitInstructionBegin(*this, Inst);
+ getAssembler().getBackend().emitInstructionBegin(*this, Inst, STI);
emitInstructionImpl(Inst, STI);
getAssembler().getBackend().emitInstructionEnd(*this, Inst);
}
@@ -609,9 +609,10 @@ void MCObjectStreamer::emitValueToAlignment(unsigned ByteAlignment,
}
void MCObjectStreamer::emitCodeAlignment(unsigned ByteAlignment,
+ const MCSubtargetInfo *STI,
unsigned MaxBytesToEmit) {
emitValueToAlignment(ByteAlignment, 0, 1, MaxBytesToEmit);
- cast<MCAlignFragment>(getCurrentFragment())->setEmitNops(true);
+ cast<MCAlignFragment>(getCurrentFragment())->setEmitNops(true, STI);
}
void MCObjectStreamer::emitValueToOffset(const MCExpr *Offset,
@@ -835,13 +836,14 @@ void MCObjectStreamer::emitFill(const MCExpr &NumValues, int64_t Size,
}
void MCObjectStreamer::emitNops(int64_t NumBytes, int64_t ControlledNopLength,
- SMLoc Loc) {
+ SMLoc Loc, const MCSubtargetInfo &STI) {
// Emit an NOP fragment.
MCDataFragment *DF = getOrCreateDataFragment();
flushPendingLabels(DF, DF->getContents().size());
assert(getCurrentSectionOnly() && "need a section");
- insert(new MCNopsFragment(NumBytes, ControlledNopLength, Loc));
+
+ insert(new MCNopsFragment(NumBytes, ControlledNopLength, Loc, STI));
}
void MCObjectStreamer::emitFileDirective(StringRef Filename) {
diff --git a/contrib/llvm-project/llvm/lib/MC/MCParser/AsmLexer.cpp b/contrib/llvm-project/llvm/lib/MC/MCParser/AsmLexer.cpp
index e328ba5315af..bf9b9e916d6f 100644
--- a/contrib/llvm-project/llvm/lib/MC/MCParser/AsmLexer.cpp
+++ b/contrib/llvm-project/llvm/lib/MC/MCParser/AsmLexer.cpp
@@ -228,6 +228,7 @@ AsmToken AsmLexer::LexLineComment() {
int CurChar = getNextChar();
while (CurChar != '\n' && CurChar != '\r' && CurChar != EOF)
CurChar = getNextChar();
+ const char *NewlinePtr = CurPtr;
if (CurChar == '\r' && CurPtr != CurBuf.end() && *CurPtr == '\n')
++CurPtr;
@@ -235,7 +236,7 @@ AsmToken AsmLexer::LexLineComment() {
if (CommentConsumer) {
CommentConsumer->HandleComment(
SMLoc::getFromPointer(CommentTextStart),
- StringRef(CommentTextStart, CurPtr - 1 - CommentTextStart));
+ StringRef(CommentTextStart, NewlinePtr - 1 - CommentTextStart));
}
IsAtStartOfLine = true;
diff --git a/contrib/llvm-project/llvm/lib/MC/MCParser/AsmParser.cpp b/contrib/llvm-project/llvm/lib/MC/MCParser/AsmParser.cpp
index d3cb5ca59bf3..ed9f2066dc20 100644
--- a/contrib/llvm-project/llvm/lib/MC/MCParser/AsmParser.cpp
+++ b/contrib/llvm-project/llvm/lib/MC/MCParser/AsmParser.cpp
@@ -749,6 +749,7 @@ namespace llvm {
extern MCAsmParserExtension *createDarwinAsmParser();
extern MCAsmParserExtension *createELFAsmParser();
extern MCAsmParserExtension *createCOFFAsmParser();
+extern MCAsmParserExtension *createGOFFAsmParser();
extern MCAsmParserExtension *createXCOFFAsmParser();
extern MCAsmParserExtension *createWasmAsmParser();
@@ -783,7 +784,8 @@ AsmParser::AsmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out,
PlatformParser.reset(createELFAsmParser());
break;
case MCContext::IsGOFF:
- report_fatal_error("GOFFAsmParser support not implemented yet");
+ PlatformParser.reset(createGOFFAsmParser());
+ break;
case MCContext::IsWasm:
PlatformParser.reset(createWasmAsmParser());
break;
@@ -950,7 +952,7 @@ bool AsmParser::Run(bool NoInitialTextSection, bool NoFinalize) {
// Create the initial section, if requested.
if (!NoInitialTextSection)
- Out.InitSections(false);
+ Out.initSections(false, getTargetParser().getSTI());
// Prime the lexer.
Lex();
@@ -1052,18 +1054,21 @@ bool AsmParser::Run(bool NoInitialTextSection, bool NoFinalize) {
}
}
}
-
// Finalize the output stream if there are no errors and if the client wants
// us to.
- if (!HadError && !NoFinalize)
+ if (!HadError && !NoFinalize) {
+ if (auto *TS = Out.getTargetStreamer())
+ TS->emitConstantPools();
+
Out.Finish(Lexer.getLoc());
+ }
return HadError || getContext().hadError();
}
bool AsmParser::checkForValidSection() {
if (!ParsingMSInlineAsm && !getStreamer().getCurrentSectionOnly()) {
- Out.InitSections(false);
+ Out.initSections(false, getTargetParser().getSTI());
return Error(getTok().getLoc(),
"expected section directive before assembly directive");
}
@@ -3451,7 +3456,8 @@ bool AsmParser::parseDirectiveAlign(bool IsPow2, unsigned ValueSize) {
bool UseCodeAlign = Section->UseCodeAlign();
if ((!HasFillExpr || Lexer.getMAI().getTextAlignFillValue() == FillExpr) &&
ValueSize == 1 && UseCodeAlign) {
- getStreamer().emitCodeAlignment(Alignment, MaxBytesToFill);
+ getStreamer().emitCodeAlignment(Alignment, &getTargetParser().getSTI(),
+ MaxBytesToFill);
} else {
// FIXME: Target specific behavior about how the "extra" bytes are filled.
getStreamer().emitValueToAlignment(Alignment, FillExpr, ValueSize,
diff --git a/contrib/llvm-project/llvm/lib/MC/MCParser/ELFAsmParser.cpp b/contrib/llvm-project/llvm/lib/MC/MCParser/ELFAsmParser.cpp
index 70d69fc8dd32..ddc41d0a08ab 100644
--- a/contrib/llvm-project/llvm/lib/MC/MCParser/ELFAsmParser.cpp
+++ b/contrib/llvm-project/llvm/lib/MC/MCParser/ELFAsmParser.cpp
@@ -502,6 +502,23 @@ static bool hasPrefix(StringRef SectionName, StringRef Prefix) {
return SectionName.startswith(Prefix) || SectionName == Prefix.drop_back();
}
+static bool allowSectionTypeMismatch(const Triple &TT, StringRef SectionName,
+ unsigned Type) {
+ if (TT.getArch() == Triple::x86_64) {
+ // x86-64 psABI names SHT_X86_64_UNWIND as the canonical type for .eh_frame,
+ // but GNU as emits SHT_PROGBITS .eh_frame for .cfi_* directives. Don't
+ // error for SHT_PROGBITS .eh_frame
+ return SectionName == ".eh_frame" && Type == ELF::SHT_PROGBITS;
+ }
+ if (TT.isMIPS()) {
+ // MIPS .debug_* sections should have SHT_MIPS_DWARF section type to
+ // distinguish among sections contain DWARF and ECOFF debug formats,
+ // but in assembly files these sections have SHT_PROGBITS type.
+ return hasPrefix(SectionName, ".debug_") && Type == ELF::SHT_PROGBITS;
+ }
+ return false;
+}
+
bool ELFAsmParser::ParseSectionArguments(bool IsPush, SMLoc loc) {
StringRef SectionName;
@@ -659,11 +676,9 @@ EndStmt:
getContext().getELFSection(SectionName, Type, Flags, Size, GroupName,
IsComdat, UniqueID, LinkedToSym);
getStreamer().SwitchSection(Section, Subsection);
- // x86-64 psABI names SHT_X86_64_UNWIND as the canonical type for .eh_frame,
- // but GNU as emits SHT_PROGBITS .eh_frame for .cfi_* directives. Don't error
- // for SHT_PROGBITS .eh_frame
if (Section->getType() != Type &&
- !(SectionName == ".eh_frame" && Type == ELF::SHT_PROGBITS))
+ !allowSectionTypeMismatch(getContext().getTargetTriple(), SectionName,
+ Type))
Error(loc, "changed section type for " + SectionName + ", expected: 0x" +
utohexstr(Section->getType()));
// Check that flags are used consistently. However, the GNU assembler permits
@@ -815,7 +830,7 @@ bool ELFAsmParser::ParseDirectiveSymver(StringRef, SMLoc) {
if (getParser().parseIdentifier(Name))
return TokError("expected identifier in directive");
- if (Name.find('@') == StringRef::npos)
+ if (!Name.contains('@'))
return TokError("expected a '@' in the name");
bool KeepOriginalSym = !Name.contains("@@@");
if (parseOptionalToken(AsmToken::Comma)) {
diff --git a/contrib/llvm-project/llvm/lib/MC/MCParser/GOFFAsmParser.cpp b/contrib/llvm-project/llvm/lib/MC/MCParser/GOFFAsmParser.cpp
new file mode 100644
index 000000000000..c2a7eaee8029
--- /dev/null
+++ b/contrib/llvm-project/llvm/lib/MC/MCParser/GOFFAsmParser.cpp
@@ -0,0 +1,48 @@
+//===- GOFFAsmParser.cpp - GOFF Assembly Parser ---------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCParser/MCAsmLexer.h"
+#include "llvm/MC/MCParser/MCAsmParserExtension.h"
+#include "llvm/MC/MCSectionGOFF.h"
+#include "llvm/MC/MCStreamer.h"
+#include "llvm/MC/MCSymbolGOFF.h"
+
+using namespace llvm;
+
+namespace {
+
+class GOFFAsmParser : public MCAsmParserExtension {
+ template <bool (GOFFAsmParser::*HandlerMethod)(StringRef, SMLoc)>
+ void addDirectiveHandler(StringRef Directive) {
+ MCAsmParser::ExtensionDirectiveHandler Handler =
+ std::make_pair(this, HandleDirective<GOFFAsmParser, HandlerMethod>);
+
+ getParser().addDirectiveHandler(Directive, Handler);
+ }
+
+public:
+ GOFFAsmParser() {}
+
+ void Initialize(MCAsmParser &Parser) override {
+ // Call the base implementation.
+ this->MCAsmParserExtension::Initialize(Parser);
+ }
+};
+
+} // namespace
+
+namespace llvm {
+
+MCAsmParserExtension *createGOFFAsmParser() { return new GOFFAsmParser; }
+
+} // namespace llvm
diff --git a/contrib/llvm-project/llvm/lib/MC/MCParser/MasmParser.cpp b/contrib/llvm-project/llvm/lib/MC/MCParser/MasmParser.cpp
index 7b4d6e529cc2..f1704cef46ac 100644
--- a/contrib/llvm-project/llvm/lib/MC/MCParser/MasmParser.cpp
+++ b/contrib/llvm-project/llvm/lib/MC/MCParser/MasmParser.cpp
@@ -1319,7 +1319,7 @@ bool MasmParser::enabledGenDwarfForAssembly() {
bool MasmParser::Run(bool NoInitialTextSection, bool NoFinalize) {
// Create the initial section, if requested.
if (!NoInitialTextSection)
- Out.InitSections(false);
+ Out.initSections(false, getTargetParser().getSTI());
// Prime the lexer.
Lex();
@@ -1437,7 +1437,7 @@ bool MasmParser::Run(bool NoInitialTextSection, bool NoFinalize) {
bool MasmParser::checkForValidSection() {
if (!ParsingMSInlineAsm && !getStreamer().getCurrentSectionOnly()) {
- Out.InitSections(false);
+ Out.initSections(false, getTargetParser().getSTI());
return Error(getTok().getLoc(),
"expected section directive before assembly directive");
}
@@ -4772,7 +4772,8 @@ bool MasmParser::emitAlignTo(int64_t Alignment) {
const MCSection *Section = getStreamer().getCurrentSectionOnly();
assert(Section && "must have section to emit alignment");
if (Section->UseCodeAlign()) {
- getStreamer().emitCodeAlignment(Alignment, /*MaxBytesToEmit=*/0);
+ getStreamer().emitCodeAlignment(Alignment, &getTargetParser().getSTI(),
+ /*MaxBytesToEmit=*/0);
} else {
// FIXME: Target specific behavior about how the "extra" bytes are filled.
getStreamer().emitValueToAlignment(Alignment, /*Value=*/0,
diff --git a/contrib/llvm-project/llvm/lib/MC/MCPseudoProbe.cpp b/contrib/llvm-project/llvm/lib/MC/MCPseudoProbe.cpp
index 731831d3bce3..e35bcec8fe75 100644
--- a/contrib/llvm-project/llvm/lib/MC/MCPseudoProbe.cpp
+++ b/contrib/llvm-project/llvm/lib/MC/MCPseudoProbe.cpp
@@ -12,10 +12,17 @@
#include "llvm/MC/MCObjectFileInfo.h"
#include "llvm/MC/MCObjectStreamer.h"
#include "llvm/MC/MCStreamer.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/LEB128.h"
+#include "llvm/Support/raw_ostream.h"
+#include <limits>
+#include <memory>
+#include <sstream>
#define DEBUG_TYPE "mcpseudoprobe"
using namespace llvm;
+using namespace support;
#ifndef NDEBUG
int MCPseudoProbeTable::DdgPrintIndent = 0;
@@ -69,23 +76,6 @@ void MCPseudoProbe::emit(MCObjectStreamer *MCOS,
});
}
-MCPseudoProbeInlineTree::~MCPseudoProbeInlineTree() {
- for (auto &Inlinee : Inlinees)
- delete Inlinee.second;
-}
-
-MCPseudoProbeInlineTree *
-MCPseudoProbeInlineTree::getOrAddNode(InlineSite Site) {
- auto Iter = Inlinees.find(Site);
- if (Iter == Inlinees.end()) {
- auto *Node = new MCPseudoProbeInlineTree(std::get<0>(Site));
- Inlinees[Site] = Node;
- return Node;
- } else {
- return Iter->second;
- }
-}
-
void MCPseudoProbeInlineTree::addPseudoProbe(
const MCPseudoProbe &Probe, const MCPseudoProbeInlineStack &InlineStack) {
// The function should not be called on the root.
@@ -147,7 +137,7 @@ void MCPseudoProbeInlineTree::emit(MCObjectStreamer *MCOS,
// Emit number of probes in this node
MCOS->emitULEB128IntValue(Probes.size());
// Emit number of direct inlinees
- MCOS->emitULEB128IntValue(Inlinees.size());
+ MCOS->emitULEB128IntValue(Children.size());
// Emit probes in this group
for (const auto &Probe : Probes) {
Probe.emit(MCOS, LastProbe);
@@ -157,7 +147,13 @@ void MCPseudoProbeInlineTree::emit(MCObjectStreamer *MCOS,
assert(Probes.empty() && "Root should not have probes");
}
- // Emit descendent
+ // Emit sorted descendant
+ // InlineSite is unique for each pair,
+ // so there will be no ordering of Inlinee based on MCPseudoProbeInlineTree*
+ std::map<InlineSite, MCPseudoProbeInlineTree *> Inlinees;
+ for (auto Child = Children.begin(); Child != Children.end(); ++Child)
+ Inlinees[Child->first] = Child->second.get();
+
for (const auto &Inlinee : Inlinees) {
if (Guid) {
// Emit probe index
@@ -211,3 +207,361 @@ void MCPseudoProbeTable::emit(MCObjectStreamer *MCOS) {
// Put out the probe.
ProbeSections.emit(MCOS);
}
+
+static StringRef getProbeFNameForGUID(const GUIDProbeFunctionMap &GUID2FuncMAP,
+ uint64_t GUID) {
+ auto It = GUID2FuncMAP.find(GUID);
+ assert(It != GUID2FuncMAP.end() &&
+ "Probe function must exist for a valid GUID");
+ return It->second.FuncName;
+}
+
+void MCPseudoProbeFuncDesc::print(raw_ostream &OS) {
+ OS << "GUID: " << FuncGUID << " Name: " << FuncName << "\n";
+ OS << "Hash: " << FuncHash << "\n";
+}
+
+void MCDecodedPseudoProbe::getInlineContext(
+ SmallVectorImpl<MCPseduoProbeFrameLocation> &ContextStack,
+ const GUIDProbeFunctionMap &GUID2FuncMAP) const {
+ uint32_t Begin = ContextStack.size();
+ MCDecodedPseudoProbeInlineTree *Cur = InlineTree;
+ // It will add the string of each node's inline site during iteration.
+ // Note that it won't include the probe's belonging function(leaf location)
+ while (Cur->hasInlineSite()) {
+ StringRef FuncName =
+ getProbeFNameForGUID(GUID2FuncMAP, std::get<0>(Cur->ISite));
+ ContextStack.emplace_back(
+ MCPseduoProbeFrameLocation(FuncName, std::get<1>(Cur->ISite)));
+ Cur = static_cast<MCDecodedPseudoProbeInlineTree *>(Cur->Parent);
+ }
+ // Make the ContextStack in caller-callee order
+ std::reverse(ContextStack.begin() + Begin, ContextStack.end());
+}
+
+std::string MCDecodedPseudoProbe::getInlineContextStr(
+ const GUIDProbeFunctionMap &GUID2FuncMAP) const {
+ std::ostringstream OContextStr;
+ SmallVector<MCPseduoProbeFrameLocation, 16> ContextStack;
+ getInlineContext(ContextStack, GUID2FuncMAP);
+ for (auto &Cxt : ContextStack) {
+ if (OContextStr.str().size())
+ OContextStr << " @ ";
+ OContextStr << Cxt.first.str() << ":" << Cxt.second;
+ }
+ return OContextStr.str();
+}
+
+static const char *PseudoProbeTypeStr[3] = {"Block", "IndirectCall",
+ "DirectCall"};
+
+void MCDecodedPseudoProbe::print(raw_ostream &OS,
+ const GUIDProbeFunctionMap &GUID2FuncMAP,
+ bool ShowName) const {
+ OS << "FUNC: ";
+ if (ShowName) {
+ StringRef FuncName = getProbeFNameForGUID(GUID2FuncMAP, Guid);
+ OS << FuncName.str() << " ";
+ } else {
+ OS << Guid << " ";
+ }
+ OS << "Index: " << Index << " ";
+ OS << "Type: " << PseudoProbeTypeStr[static_cast<uint8_t>(Type)] << " ";
+ std::string InlineContextStr = getInlineContextStr(GUID2FuncMAP);
+ if (InlineContextStr.size()) {
+ OS << "Inlined: @ ";
+ OS << InlineContextStr;
+ }
+ OS << "\n";
+}
+
+template <typename T> ErrorOr<T> MCPseudoProbeDecoder::readUnencodedNumber() {
+ if (Data + sizeof(T) > End) {
+ return std::error_code();
+ }
+ T Val = endian::readNext<T, little, unaligned>(Data);
+ return ErrorOr<T>(Val);
+}
+
+template <typename T> ErrorOr<T> MCPseudoProbeDecoder::readUnsignedNumber() {
+ unsigned NumBytesRead = 0;
+ uint64_t Val = decodeULEB128(Data, &NumBytesRead);
+ if (Val > std::numeric_limits<T>::max() || (Data + NumBytesRead > End)) {
+ return std::error_code();
+ }
+ Data += NumBytesRead;
+ return ErrorOr<T>(static_cast<T>(Val));
+}
+
+template <typename T> ErrorOr<T> MCPseudoProbeDecoder::readSignedNumber() {
+ unsigned NumBytesRead = 0;
+ int64_t Val = decodeSLEB128(Data, &NumBytesRead);
+ if (Val > std::numeric_limits<T>::max() || (Data + NumBytesRead > End)) {
+ return std::error_code();
+ }
+ Data += NumBytesRead;
+ return ErrorOr<T>(static_cast<T>(Val));
+}
+
+ErrorOr<StringRef> MCPseudoProbeDecoder::readString(uint32_t Size) {
+ StringRef Str(reinterpret_cast<const char *>(Data), Size);
+ if (Data + Size > End) {
+ return std::error_code();
+ }
+ Data += Size;
+ return ErrorOr<StringRef>(Str);
+}
+
+bool MCPseudoProbeDecoder::buildGUID2FuncDescMap(const uint8_t *Start,
+ std::size_t Size) {
+ // The pseudo_probe_desc section has a format like:
+ // .section .pseudo_probe_desc,"",@progbits
+ // .quad -5182264717993193164 // GUID
+ // .quad 4294967295 // Hash
+ // .uleb 3 // Name size
+ // .ascii "foo" // Name
+ // .quad -2624081020897602054
+ // .quad 174696971957
+ // .uleb 34
+ // .ascii "main"
+
+ Data = Start;
+ End = Data + Size;
+
+ while (Data < End) {
+ auto ErrorOrGUID = readUnencodedNumber<uint64_t>();
+ if (!ErrorOrGUID)
+ return false;
+
+ auto ErrorOrHash = readUnencodedNumber<uint64_t>();
+ if (!ErrorOrHash)
+ return false;
+
+ auto ErrorOrNameSize = readUnsignedNumber<uint32_t>();
+ if (!ErrorOrNameSize)
+ return false;
+ uint32_t NameSize = std::move(*ErrorOrNameSize);
+
+ auto ErrorOrName = readString(NameSize);
+ if (!ErrorOrName)
+ return false;
+
+ uint64_t GUID = std::move(*ErrorOrGUID);
+ uint64_t Hash = std::move(*ErrorOrHash);
+ StringRef Name = std::move(*ErrorOrName);
+
+ // Initialize PseudoProbeFuncDesc and populate it into GUID2FuncDescMap
+ GUID2FuncDescMap.emplace(GUID, MCPseudoProbeFuncDesc(GUID, Hash, Name));
+ }
+ assert(Data == End && "Have unprocessed data in pseudo_probe_desc section");
+ return true;
+}
+
+bool MCPseudoProbeDecoder::buildAddress2ProbeMap(const uint8_t *Start,
+ std::size_t Size) {
+ // The pseudo_probe section encodes an inline forest and each tree has a
+ // format like:
+ // FUNCTION BODY (one for each uninlined function present in the text
+ // section)
+ // GUID (uint64)
+ // GUID of the function
+ // NPROBES (ULEB128)
+ // Number of probes originating from this function.
+ // NUM_INLINED_FUNCTIONS (ULEB128)
+ // Number of callees inlined into this function, aka number of
+ // first-level inlinees
+ // PROBE RECORDS
+ // A list of NPROBES entries. Each entry contains:
+ // INDEX (ULEB128)
+ // TYPE (uint4)
+ // 0 - block probe, 1 - indirect call, 2 - direct call
+ // ATTRIBUTE (uint3)
+ // 1 - tail call, 2 - dangling
+ // ADDRESS_TYPE (uint1)
+ // 0 - code address, 1 - address delta
+ // CODE_ADDRESS (uint64 or ULEB128)
+ // code address or address delta, depending on Flag
+ // INLINED FUNCTION RECORDS
+ // A list of NUM_INLINED_FUNCTIONS entries describing each of the
+ // inlined callees. Each record contains:
+ // INLINE SITE
+ // Index of the callsite probe (ULEB128)
+ // FUNCTION BODY
+ // A FUNCTION BODY entry describing the inlined function.
+
+ Data = Start;
+ End = Data + Size;
+
+ MCDecodedPseudoProbeInlineTree *Root = &DummyInlineRoot;
+ MCDecodedPseudoProbeInlineTree *Cur = &DummyInlineRoot;
+ uint64_t LastAddr = 0;
+ uint32_t Index = 0;
+ // A DFS-based decoding
+ while (Data < End) {
+ if (Root == Cur) {
+ // Use a sequential id for top level inliner.
+ Index = Root->getChildren().size();
+ } else {
+ // Read inline site for inlinees
+ auto ErrorOrIndex = readUnsignedNumber<uint32_t>();
+ if (!ErrorOrIndex)
+ return false;
+ Index = std::move(*ErrorOrIndex);
+ }
+ // Switch/add to a new tree node(inlinee)
+ Cur = Cur->getOrAddNode(std::make_tuple(Cur->Guid, Index));
+ // Read guid
+ auto ErrorOrCurGuid = readUnencodedNumber<uint64_t>();
+ if (!ErrorOrCurGuid)
+ return false;
+ Cur->Guid = std::move(*ErrorOrCurGuid);
+ // Read number of probes in the current node.
+ auto ErrorOrNodeCount = readUnsignedNumber<uint32_t>();
+ if (!ErrorOrNodeCount)
+ return false;
+ uint32_t NodeCount = std::move(*ErrorOrNodeCount);
+ // Read number of direct inlinees
+ auto ErrorOrCurChildrenToProcess = readUnsignedNumber<uint32_t>();
+ if (!ErrorOrCurChildrenToProcess)
+ return false;
+ Cur->ChildrenToProcess = std::move(*ErrorOrCurChildrenToProcess);
+ // Read all probes in this node
+ for (std::size_t I = 0; I < NodeCount; I++) {
+ // Read index
+ auto ErrorOrIndex = readUnsignedNumber<uint32_t>();
+ if (!ErrorOrIndex)
+ return false;
+ uint32_t Index = std::move(*ErrorOrIndex);
+ // Read type | flag.
+ auto ErrorOrValue = readUnencodedNumber<uint8_t>();
+ if (!ErrorOrValue)
+ return false;
+ uint8_t Value = std::move(*ErrorOrValue);
+ uint8_t Kind = Value & 0xf;
+ uint8_t Attr = (Value & 0x70) >> 4;
+ // Read address
+ uint64_t Addr = 0;
+ if (Value & 0x80) {
+ auto ErrorOrOffset = readSignedNumber<int64_t>();
+ if (!ErrorOrOffset)
+ return false;
+ int64_t Offset = std::move(*ErrorOrOffset);
+ Addr = LastAddr + Offset;
+ } else {
+ auto ErrorOrAddr = readUnencodedNumber<int64_t>();
+ if (!ErrorOrAddr)
+ return false;
+ Addr = std::move(*ErrorOrAddr);
+ }
+ // Populate Address2ProbesMap
+ auto &Probes = Address2ProbesMap[Addr];
+ Probes.emplace_back(Addr, Cur->Guid, Index, PseudoProbeType(Kind), Attr,
+ Cur);
+ Cur->addProbes(&Probes.back());
+ LastAddr = Addr;
+ }
+
+ // Look for the parent for the next node by subtracting the current
+ // node count from tree counts along the parent chain. The first node
+ // in the chain that has a non-zero tree count is the target.
+ while (Cur != Root) {
+ if (Cur->ChildrenToProcess == 0) {
+ Cur = static_cast<MCDecodedPseudoProbeInlineTree *>(Cur->Parent);
+ if (Cur != Root) {
+ assert(Cur->ChildrenToProcess > 0 &&
+ "Should have some unprocessed nodes");
+ Cur->ChildrenToProcess -= 1;
+ }
+ } else {
+ break;
+ }
+ }
+ }
+
+ assert(Data == End && "Have unprocessed data in pseudo_probe section");
+ assert(Cur == Root &&
+ " Cur should point to root when the forest is fully built up");
+ return true;
+}
+
+void MCPseudoProbeDecoder::printGUID2FuncDescMap(raw_ostream &OS) {
+ OS << "Pseudo Probe Desc:\n";
+ // Make the output deterministic
+ std::map<uint64_t, MCPseudoProbeFuncDesc> OrderedMap(GUID2FuncDescMap.begin(),
+ GUID2FuncDescMap.end());
+ for (auto &I : OrderedMap) {
+ I.second.print(OS);
+ }
+}
+
+void MCPseudoProbeDecoder::printProbeForAddress(raw_ostream &OS,
+ uint64_t Address) {
+ auto It = Address2ProbesMap.find(Address);
+ if (It != Address2ProbesMap.end()) {
+ for (auto &Probe : It->second) {
+ OS << " [Probe]:\t";
+ Probe.print(OS, GUID2FuncDescMap, true);
+ }
+ }
+}
+
+void MCPseudoProbeDecoder::printProbesForAllAddresses(raw_ostream &OS) {
+ std::vector<uint64_t> Addresses;
+ for (auto Entry : Address2ProbesMap)
+ Addresses.push_back(Entry.first);
+ std::sort(Addresses.begin(), Addresses.end());
+ for (auto K : Addresses) {
+ OS << "Address:\t";
+ OS << K;
+ OS << "\n";
+ printProbeForAddress(OS, K);
+ }
+}
+
+const MCDecodedPseudoProbe *
+MCPseudoProbeDecoder::getCallProbeForAddr(uint64_t Address) const {
+ auto It = Address2ProbesMap.find(Address);
+ if (It == Address2ProbesMap.end())
+ return nullptr;
+ const auto &Probes = It->second;
+
+ const MCDecodedPseudoProbe *CallProbe = nullptr;
+ for (const auto &Probe : Probes) {
+ if (Probe.isCall()) {
+ assert(!CallProbe &&
+ "There should be only one call probe corresponding to address "
+ "which is a callsite.");
+ CallProbe = &Probe;
+ }
+ }
+ return CallProbe;
+}
+
+const MCPseudoProbeFuncDesc *
+MCPseudoProbeDecoder::getFuncDescForGUID(uint64_t GUID) const {
+ auto It = GUID2FuncDescMap.find(GUID);
+ assert(It != GUID2FuncDescMap.end() && "Function descriptor doesn't exist");
+ return &It->second;
+}
+
+void MCPseudoProbeDecoder::getInlineContextForProbe(
+ const MCDecodedPseudoProbe *Probe,
+ SmallVectorImpl<MCPseduoProbeFrameLocation> &InlineContextStack,
+ bool IncludeLeaf) const {
+ Probe->getInlineContext(InlineContextStack, GUID2FuncDescMap);
+ if (!IncludeLeaf)
+ return;
+ // Note that the context from probe doesn't include leaf frame,
+ // hence we need to retrieve and prepend leaf if requested.
+ const auto *FuncDesc = getFuncDescForGUID(Probe->getGuid());
+ InlineContextStack.emplace_back(
+ MCPseduoProbeFrameLocation(FuncDesc->FuncName, Probe->getIndex()));
+}
+
+const MCPseudoProbeFuncDesc *MCPseudoProbeDecoder::getInlinerDescForProbe(
+ const MCDecodedPseudoProbe *Probe) const {
+ MCDecodedPseudoProbeInlineTree *InlinerNode = Probe->getInlineTreeNode();
+ if (!InlinerNode->hasInlineSite())
+ return nullptr;
+ return getFuncDescForGUID(std::get<0>(InlinerNode->ISite));
+}
diff --git a/contrib/llvm-project/llvm/lib/MC/MCSectionXCOFF.cpp b/contrib/llvm-project/llvm/lib/MC/MCSectionXCOFF.cpp
index 648efc14da06..7f7380bf810d 100644
--- a/contrib/llvm-project/llvm/lib/MC/MCSectionXCOFF.cpp
+++ b/contrib/llvm-project/llvm/lib/MC/MCSectionXCOFF.cpp
@@ -118,6 +118,10 @@ void MCSectionXCOFF::PrintSwitchToSection(const MCAsmInfo &MAI, const Triple &T,
bool MCSectionXCOFF::UseCodeAlign() const { return getKind().isText(); }
bool MCSectionXCOFF::isVirtualSection() const {
- assert(isCsect() && "Only csect section can be virtual!");
+ // DWARF sections are always not virtual.
+ if (isDwarfSect())
+ return false;
+ assert(isCsect() &&
+ "Handling for isVirtualSection not implemented for this section!");
return XCOFF::XTY_CM == CsectProp->Type;
}
diff --git a/contrib/llvm-project/llvm/lib/MC/MCStreamer.cpp b/contrib/llvm-project/llvm/lib/MC/MCStreamer.cpp
index fc7fb555f0b9..f4e64b42c817 100644
--- a/contrib/llvm-project/llvm/lib/MC/MCStreamer.cpp
+++ b/contrib/llvm-project/llvm/lib/MC/MCStreamer.cpp
@@ -53,6 +53,8 @@ void MCTargetStreamer::emitLabel(MCSymbol *Symbol) {}
void MCTargetStreamer::finish() {}
+void MCTargetStreamer::emitConstantPools() {}
+
void MCTargetStreamer::changeSection(const MCSection *CurSection,
MCSection *Section,
const MCExpr *Subsection,
@@ -218,7 +220,7 @@ void MCStreamer::emitFill(uint64_t NumBytes, uint8_t FillValue) {
}
void llvm::MCStreamer::emitNops(int64_t NumBytes, int64_t ControlledNopLen,
- llvm::SMLoc) {}
+ llvm::SMLoc, const MCSubtargetInfo& STI) {}
/// The implementation in this class just redirects to emitFill.
void MCStreamer::emitZeros(uint64_t NumBytes) { emitFill(NumBytes, 0); }
@@ -397,7 +399,7 @@ void MCStreamer::emitEHSymAttributes(const MCSymbol *Symbol,
MCSymbol *EHSymbol) {
}
-void MCStreamer::InitSections(bool NoExecStack) {
+void MCStreamer::initSections(bool NoExecStack, const MCSubtargetInfo &STI) {
SwitchSection(getContext().getObjectFileInfo()->getTextSection());
}
@@ -1198,6 +1200,7 @@ void MCStreamer::emitValueToAlignment(unsigned ByteAlignment, int64_t Value,
unsigned ValueSize,
unsigned MaxBytesToEmit) {}
void MCStreamer::emitCodeAlignment(unsigned ByteAlignment,
+ const MCSubtargetInfo *STI,
unsigned MaxBytesToEmit) {}
void MCStreamer::emitValueToOffset(const MCExpr *Offset, unsigned char Value,
SMLoc Loc) {}
diff --git a/contrib/llvm-project/llvm/lib/MC/MCWasmStreamer.cpp b/contrib/llvm-project/llvm/lib/MC/MCWasmStreamer.cpp
index e3d2439cef81..90249fb7380a 100644
--- a/contrib/llvm-project/llvm/lib/MC/MCWasmStreamer.cpp
+++ b/contrib/llvm-project/llvm/lib/MC/MCWasmStreamer.cpp
@@ -26,10 +26,10 @@
#include "llvm/MC/MCSymbol.h"
#include "llvm/MC/MCSymbolWasm.h"
#include "llvm/MC/MCValue.h"
+#include "llvm/MC/TargetRegistry.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
@@ -49,6 +49,27 @@ void MCWasmStreamer::mergeFragment(MCDataFragment *DF, MCDataFragment *EF) {
DF->getContents().append(EF->getContents().begin(), EF->getContents().end());
}
+void MCWasmStreamer::emitLabel(MCSymbol *S, SMLoc Loc) {
+ auto *Symbol = cast<MCSymbolWasm>(S);
+ MCObjectStreamer::emitLabel(Symbol, Loc);
+
+ const MCSectionWasm &Section =
+ static_cast<const MCSectionWasm &>(*getCurrentSectionOnly());
+ if (Section.getSegmentFlags() & wasm::WASM_SEG_FLAG_TLS)
+ Symbol->setTLS();
+}
+
+void MCWasmStreamer::emitLabelAtPos(MCSymbol *S, SMLoc Loc, MCFragment *F,
+ uint64_t Offset) {
+ auto *Symbol = cast<MCSymbolWasm>(S);
+ MCObjectStreamer::emitLabelAtPos(Symbol, Loc, F, Offset);
+
+ const MCSectionWasm &Section =
+ static_cast<const MCSectionWasm &>(*getCurrentSectionOnly());
+ if (Section.getSegmentFlags() & wasm::WASM_SEG_FLAG_TLS)
+ Symbol->setTLS();
+}
+
void MCWasmStreamer::emitAssemblerFlag(MCAssemblerFlag Flag) {
// Let the target do whatever target specific stuff it needs to do.
getAssembler().getBackend().handleAssemblerFlag(Flag);
@@ -117,6 +138,10 @@ bool MCWasmStreamer::emitSymbolAttribute(MCSymbol *S, MCSymbolAttr Attribute) {
Symbol->setType(wasm::WASM_SYMBOL_TYPE_FUNCTION);
break;
+ case MCSA_ELF_TypeTLS:
+ Symbol->setTLS();
+ break;
+
case MCSA_ELF_TypeObject:
case MCSA_Cold:
break;
@@ -156,6 +181,10 @@ void MCWasmStreamer::emitIdent(StringRef IdentString) {
void MCWasmStreamer::emitInstToFragment(const MCInst &Inst,
const MCSubtargetInfo &STI) {
this->MCObjectStreamer::emitInstToFragment(Inst, STI);
+ MCRelaxableFragment &F = *cast<MCRelaxableFragment>(getCurrentFragment());
+
+ for (auto &Fixup : F.getFixups())
+ fixSymbolsInTLSFixups(Fixup.getValue());
}
void MCWasmStreamer::emitInstToData(const MCInst &Inst,
@@ -166,6 +195,9 @@ void MCWasmStreamer::emitInstToData(const MCInst &Inst,
raw_svector_ostream VecOS(Code);
Assembler.getEmitter().encodeInstruction(Inst, VecOS, Fixups, STI);
+ for (auto &Fixup : Fixups)
+ fixSymbolsInTLSFixups(Fixup.getValue());
+
// Append the encoded instruction to the current data fragment (or create a
// new such fragment if the current fragment is not a data fragment).
MCDataFragment *DF = getOrCreateDataFragment();
@@ -185,16 +217,37 @@ void MCWasmStreamer::finishImpl() {
this->MCObjectStreamer::finishImpl();
}
-MCStreamer *llvm::createWasmStreamer(MCContext &Context,
- std::unique_ptr<MCAsmBackend> &&MAB,
- std::unique_ptr<MCObjectWriter> &&OW,
- std::unique_ptr<MCCodeEmitter> &&CE,
- bool RelaxAll) {
- MCWasmStreamer *S =
- new MCWasmStreamer(Context, std::move(MAB), std::move(OW), std::move(CE));
- if (RelaxAll)
- S->getAssembler().setRelaxAll(true);
- return S;
+void MCWasmStreamer::fixSymbolsInTLSFixups(const MCExpr *expr) {
+ switch (expr->getKind()) {
+ case MCExpr::Target:
+ case MCExpr::Constant:
+ break;
+
+ case MCExpr::Binary: {
+ const MCBinaryExpr *be = cast<MCBinaryExpr>(expr);
+ fixSymbolsInTLSFixups(be->getLHS());
+ fixSymbolsInTLSFixups(be->getRHS());
+ break;
+ }
+
+ case MCExpr::SymbolRef: {
+ const MCSymbolRefExpr &symRef = *cast<MCSymbolRefExpr>(expr);
+ switch (symRef.getKind()) {
+ case MCSymbolRefExpr::VK_WASM_TLSREL:
+ case MCSymbolRefExpr::VK_WASM_GOT_TLS:
+ getAssembler().registerSymbol(symRef.getSymbol());
+ cast<MCSymbolWasm>(symRef.getSymbol()).setTLS();
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+
+ case MCExpr::Unary:
+ fixSymbolsInTLSFixups(cast<MCUnaryExpr>(expr)->getSubExpr());
+ break;
+ }
}
void MCWasmStreamer::emitThumbFunc(MCSymbol *Func) {
@@ -215,3 +268,15 @@ void MCWasmStreamer::emitTBSSSymbol(MCSection *Section, MCSymbol *Symbol,
uint64_t Size, unsigned ByteAlignment) {
llvm_unreachable("Wasm doesn't support this directive");
}
+
+MCStreamer *llvm::createWasmStreamer(MCContext &Context,
+ std::unique_ptr<MCAsmBackend> &&MAB,
+ std::unique_ptr<MCObjectWriter> &&OW,
+ std::unique_ptr<MCCodeEmitter> &&CE,
+ bool RelaxAll) {
+ MCWasmStreamer *S =
+ new MCWasmStreamer(Context, std::move(MAB), std::move(OW), std::move(CE));
+ if (RelaxAll)
+ S->getAssembler().setRelaxAll(true);
+ return S;
+}
diff --git a/contrib/llvm-project/llvm/lib/MC/MCWin64EH.cpp b/contrib/llvm-project/llvm/lib/MC/MCWin64EH.cpp
index de1b0fd3c742..7773d8828931 100644
--- a/contrib/llvm-project/llvm/lib/MC/MCWin64EH.cpp
+++ b/contrib/llvm-project/llvm/lib/MC/MCWin64EH.cpp
@@ -144,8 +144,8 @@ static void EmitRuntimeFunction(MCStreamer &streamer,
MCContext &context = streamer.getContext();
streamer.emitValueToAlignment(4);
- EmitSymbolRefWithOfs(streamer, info->Function, info->Begin);
- EmitSymbolRefWithOfs(streamer, info->Function, info->End);
+ EmitSymbolRefWithOfs(streamer, info->Begin, info->Begin);
+ EmitSymbolRefWithOfs(streamer, info->Begin, info->End);
streamer.emitValue(MCSymbolRefExpr::create(info->Symbol,
MCSymbolRefExpr::VK_COFF_IMGREL32,
context), 4);
@@ -1073,7 +1073,7 @@ static void ARM64EmitRuntimeFunction(MCStreamer &streamer,
MCContext &context = streamer.getContext();
streamer.emitValueToAlignment(4);
- EmitSymbolRefWithOfs(streamer, info->Function, info->Begin);
+ EmitSymbolRefWithOfs(streamer, info->Begin, info->Begin);
if (info->PackedInfo)
streamer.emitInt32(info->PackedInfo);
else
diff --git a/contrib/llvm-project/llvm/lib/MC/MCWinCOFFStreamer.cpp b/contrib/llvm-project/llvm/lib/MC/MCWinCOFFStreamer.cpp
index 69dc71b39fd1..0dfe5a5c2bdb 100644
--- a/contrib/llvm-project/llvm/lib/MC/MCWinCOFFStreamer.cpp
+++ b/contrib/llvm-project/llvm/lib/MC/MCWinCOFFStreamer.cpp
@@ -66,18 +66,19 @@ void MCWinCOFFStreamer::emitInstToData(const MCInst &Inst,
DF->getContents().append(Code.begin(), Code.end());
}
-void MCWinCOFFStreamer::InitSections(bool NoExecStack) {
+void MCWinCOFFStreamer::initSections(bool NoExecStack,
+ const MCSubtargetInfo &STI) {
// FIXME: this is identical to the ELF one.
// This emulates the same behavior of GNU as. This makes it easier
// to compare the output as the major sections are in the same order.
SwitchSection(getContext().getObjectFileInfo()->getTextSection());
- emitCodeAlignment(4);
+ emitCodeAlignment(4, &STI);
SwitchSection(getContext().getObjectFileInfo()->getDataSection());
- emitCodeAlignment(4);
+ emitCodeAlignment(4, &STI);
SwitchSection(getContext().getObjectFileInfo()->getBSSSection());
- emitCodeAlignment(4);
+ emitCodeAlignment(4, &STI);
SwitchSection(getContext().getObjectFileInfo()->getTextSection());
}
diff --git a/contrib/llvm-project/llvm/lib/MC/MCXCOFFStreamer.cpp b/contrib/llvm-project/llvm/lib/MC/MCXCOFFStreamer.cpp
index ec9e89fac416..90604782de13 100644
--- a/contrib/llvm-project/llvm/lib/MC/MCXCOFFStreamer.cpp
+++ b/contrib/llvm-project/llvm/lib/MC/MCXCOFFStreamer.cpp
@@ -18,7 +18,7 @@
#include "llvm/MC/MCObjectWriter.h"
#include "llvm/MC/MCSectionXCOFF.h"
#include "llvm/MC/MCSymbolXCOFF.h"
-#include "llvm/Support/TargetRegistry.h"
+#include "llvm/MC/TargetRegistry.h"
using namespace llvm;
diff --git a/contrib/llvm-project/llvm/lib/MC/MachObjectWriter.cpp b/contrib/llvm-project/llvm/lib/MC/MachObjectWriter.cpp
index 10ae27c2acc2..277d88cf1cd2 100644
--- a/contrib/llvm-project/llvm/lib/MC/MachObjectWriter.cpp
+++ b/contrib/llvm-project/llvm/lib/MC/MachObjectWriter.cpp
@@ -965,7 +965,7 @@ uint64_t MachObjectWriter::writeObject(MCAssembler &Asm,
// Write the section relocation entries, in reverse order to match 'as'
// (approximately, the exact algorithm is more complicated than this).
std::vector<RelAndSymbol> &Relocs = Relocations[&Sec];
- for (const RelAndSymbol &Rel : make_range(Relocs.rbegin(), Relocs.rend())) {
+ for (const RelAndSymbol &Rel : llvm::reverse(Relocs)) {
W.write<uint32_t>(Rel.MRE.r_word0);
W.write<uint32_t>(Rel.MRE.r_word1);
}
diff --git a/contrib/llvm-project/llvm/lib/MC/TargetRegistry.cpp b/contrib/llvm-project/llvm/lib/MC/TargetRegistry.cpp
new file mode 100644
index 000000000000..0948a6b9f1a1
--- /dev/null
+++ b/contrib/llvm-project/llvm/lib/MC/TargetRegistry.cpp
@@ -0,0 +1,134 @@
+//===--- TargetRegistry.cpp - Target registration -------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/TargetRegistry.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/raw_ostream.h"
+#include <cassert>
+#include <vector>
+using namespace llvm;
+
+// Clients are responsible for avoid race conditions in registration.
+static Target *FirstTarget = nullptr;
+
+iterator_range<TargetRegistry::iterator> TargetRegistry::targets() {
+ return make_range(iterator(FirstTarget), iterator());
+}
+
+const Target *TargetRegistry::lookupTarget(const std::string &ArchName,
+ Triple &TheTriple,
+ std::string &Error) {
+ // Allocate target machine. First, check whether the user has explicitly
+ // specified an architecture to compile for. If so we have to look it up by
+ // name, because it might be a backend that has no mapping to a target triple.
+ const Target *TheTarget = nullptr;
+ if (!ArchName.empty()) {
+ auto I = find_if(targets(),
+ [&](const Target &T) { return ArchName == T.getName(); });
+
+ if (I == targets().end()) {
+ Error = "error: invalid target '" + ArchName + "'.\n";
+ return nullptr;
+ }
+
+ TheTarget = &*I;
+
+ // Adjust the triple to match (if known), otherwise stick with the
+ // given triple.
+ Triple::ArchType Type = Triple::getArchTypeForLLVMName(ArchName);
+ if (Type != Triple::UnknownArch)
+ TheTriple.setArch(Type);
+ } else {
+ // Get the target specific parser.
+ std::string TempError;
+ TheTarget = TargetRegistry::lookupTarget(TheTriple.getTriple(), TempError);
+ if (!TheTarget) {
+ Error = ": error: unable to get target for '"
+ + TheTriple.getTriple()
+ + "', see --version and --triple.\n";
+ return nullptr;
+ }
+ }
+
+ return TheTarget;
+}
+
+const Target *TargetRegistry::lookupTarget(const std::string &TT,
+ std::string &Error) {
+ // Provide special warning when no targets are initialized.
+ if (targets().begin() == targets().end()) {
+ Error = "Unable to find target for this triple (no targets are registered)";
+ return nullptr;
+ }
+ Triple::ArchType Arch = Triple(TT).getArch();
+ auto ArchMatch = [&](const Target &T) { return T.ArchMatchFn(Arch); };
+ auto I = find_if(targets(), ArchMatch);
+
+ if (I == targets().end()) {
+ Error = "No available targets are compatible with triple \"" + TT + "\"";
+ return nullptr;
+ }
+
+ auto J = std::find_if(std::next(I), targets().end(), ArchMatch);
+ if (J != targets().end()) {
+ Error = std::string("Cannot choose between targets \"") + I->Name +
+ "\" and \"" + J->Name + "\"";
+ return nullptr;
+ }
+
+ return &*I;
+}
+
+void TargetRegistry::RegisterTarget(Target &T, const char *Name,
+ const char *ShortDesc,
+ const char *BackendName,
+ Target::ArchMatchFnTy ArchMatchFn,
+ bool HasJIT) {
+ assert(Name && ShortDesc && ArchMatchFn &&
+ "Missing required target information!");
+
+ // Check if this target has already been initialized, we allow this as a
+ // convenience to some clients.
+ if (T.Name)
+ return;
+
+ // Add to the list of targets.
+ T.Next = FirstTarget;
+ FirstTarget = &T;
+
+ T.Name = Name;
+ T.ShortDesc = ShortDesc;
+ T.BackendName = BackendName;
+ T.ArchMatchFn = ArchMatchFn;
+ T.HasJIT = HasJIT;
+}
+
+static int TargetArraySortFn(const std::pair<StringRef, const Target *> *LHS,
+ const std::pair<StringRef, const Target *> *RHS) {
+ return LHS->first.compare(RHS->first);
+}
+
+void TargetRegistry::printRegisteredTargetsForVersion(raw_ostream &OS) {
+ std::vector<std::pair<StringRef, const Target*> > Targets;
+ size_t Width = 0;
+ for (const auto &T : TargetRegistry::targets()) {
+ Targets.push_back(std::make_pair(T.getName(), &T));
+ Width = std::max(Width, Targets.back().first.size());
+ }
+ array_pod_sort(Targets.begin(), Targets.end(), TargetArraySortFn);
+
+ OS << " Registered Targets:\n";
+ for (unsigned i = 0, e = Targets.size(); i != e; ++i) {
+ OS << " " << Targets[i].first;
+ OS.indent(Width - Targets[i].first.size()) << " - "
+ << Targets[i].second->getShortDescription() << '\n';
+ }
+ if (Targets.empty())
+ OS << " (none)\n";
+}
diff --git a/contrib/llvm-project/llvm/lib/MC/WasmObjectWriter.cpp b/contrib/llvm-project/llvm/lib/MC/WasmObjectWriter.cpp
index 0dc5c9111db2..636c1d238932 100644
--- a/contrib/llvm-project/llvm/lib/MC/WasmObjectWriter.cpp
+++ b/contrib/llvm-project/llvm/lib/MC/WasmObjectWriter.cpp
@@ -292,6 +292,8 @@ private:
W->OS << Str;
}
+ void writeStringWithAlignment(const StringRef Str, unsigned Alignment);
+
void writeI32(int32_t val) {
char Buffer[4];
support::endian::write32le(Buffer, val);
@@ -317,7 +319,7 @@ private:
uint32_t writeCodeSection(const MCAssembler &Asm, const MCAsmLayout &Layout,
ArrayRef<WasmFunction> Functions);
uint32_t writeDataSection(const MCAsmLayout &Layout);
- void writeTagSection(ArrayRef<wasm::WasmTagType> Tags);
+ void writeTagSection(ArrayRef<uint32_t> TagTypes);
void writeGlobalSection(ArrayRef<wasm::WasmGlobal> Globals);
void writeTableSection(ArrayRef<wasm::WasmTable> Tables);
void writeRelocSection(uint32_t SectionIndex, StringRef Name,
@@ -362,6 +364,28 @@ void WasmObjectWriter::startSection(SectionBookkeeping &Section,
Section.Index = SectionCount++;
}
+// Write a string with extra paddings for trailing alignment
+// TODO: support alignment at asm and llvm level?
+void WasmObjectWriter::writeStringWithAlignment(const StringRef Str,
+ unsigned Alignment) {
+
+ // Calculate the encoded size of str length and add pads based on it and
+ // alignment.
+ raw_null_ostream NullOS;
+ uint64_t StrSizeLength = encodeULEB128(Str.size(), NullOS);
+ uint64_t Offset = W->OS.tell() + StrSizeLength + Str.size();
+ uint64_t Paddings = offsetToAlignment(Offset, Align(Alignment));
+ Offset += Paddings;
+
+ // LEB128 greater than 5 bytes is invalid
+ assert((StrSizeLength + Paddings) <= 5 && "too long string to align");
+
+ encodeSLEB128(Str.size(), W->OS, StrSizeLength + Paddings);
+ W->OS << Str;
+
+ assert(W->OS.tell() == Offset && "invalid padding");
+}
+
void WasmObjectWriter::startCustomSection(SectionBookkeeping &Section,
StringRef Name) {
LLVM_DEBUG(dbgs() << "startCustomSection " << Name << "\n");
@@ -371,7 +395,12 @@ void WasmObjectWriter::startCustomSection(SectionBookkeeping &Section,
Section.PayloadOffset = W->OS.tell();
// Custom sections in wasm also have a string identifier.
- writeString(Name);
+ if (Name != "__clangast") {
+ writeString(Name);
+ } else {
+ // The on-disk hashtable in clangast needs to be aligned by 4 bytes.
+ writeStringWithAlignment(Name, 4);
+ }
// The position where the custom section starts.
Section.ContentsOffset = W->OS.tell();
@@ -565,8 +594,14 @@ void WasmObjectWriter::recordRelocation(MCAssembler &Asm,
SymA->setUsedInReloc();
}
- if (RefA->getKind() == MCSymbolRefExpr::VK_GOT)
+ switch (RefA->getKind()) {
+ case MCSymbolRefExpr::VK_GOT:
+ case MCSymbolRefExpr::VK_WASM_GOT_TLS:
SymA->setUsedInGOT();
+ break;
+ default:
+ break;
+ }
WasmRelocationEntry Rec(FixupOffset, SymA, C, Type, &FixupSection);
LLVM_DEBUG(dbgs() << "WasmReloc: " << Rec << "\n");
@@ -825,8 +860,8 @@ void WasmObjectWriter::writeImportSection(ArrayRef<wasm::WasmImport> Imports,
encodeULEB128(NumElements, W->OS); // initial
break;
case wasm::WASM_EXTERNAL_TAG:
- W->OS << char(Import.Tag.Attribute);
- encodeULEB128(Import.Tag.SigIndex, W->OS);
+ W->OS << char(0); // Reserved 'attribute' field
+ encodeULEB128(Import.SigIndex, W->OS);
break;
default:
llvm_unreachable("unsupported import kind");
@@ -850,17 +885,17 @@ void WasmObjectWriter::writeFunctionSection(ArrayRef<WasmFunction> Functions) {
endSection(Section);
}
-void WasmObjectWriter::writeTagSection(ArrayRef<wasm::WasmTagType> Tags) {
- if (Tags.empty())
+void WasmObjectWriter::writeTagSection(ArrayRef<uint32_t> TagTypes) {
+ if (TagTypes.empty())
return;
SectionBookkeeping Section;
startSection(Section, wasm::WASM_SEC_TAG);
- encodeULEB128(Tags.size(), W->OS);
- for (const wasm::WasmTagType &Tag : Tags) {
- W->OS << char(Tag.Attribute);
- encodeULEB128(Tag.SigIndex, W->OS);
+ encodeULEB128(TagTypes.size(), W->OS);
+ for (uint32_t Index : TagTypes) {
+ W->OS << char(0); // Reserved 'attribute' field
+ encodeULEB128(Index, W->OS);
}
endSection(Section);
@@ -1052,7 +1087,7 @@ uint32_t WasmObjectWriter::writeDataSection(const MCAsmLayout &Layout) {
void WasmObjectWriter::writeRelocSection(
uint32_t SectionIndex, StringRef Name,
std::vector<WasmRelocationEntry> &Relocs) {
- // See: https://github.com/WebAssembly/tool-conventions/blob/master/Linking.md
+ // See: https://github.com/WebAssembly/tool-conventions/blob/main/Linking.md
// for descriptions of the reloc sections.
if (Relocs.empty())
@@ -1340,8 +1375,7 @@ void WasmObjectWriter::prepareImports(
Import.Module = WS.getImportModule();
Import.Field = WS.getImportName();
Import.Kind = wasm::WASM_EXTERNAL_TAG;
- Import.Tag.Attribute = wasm::WASM_TAG_ATTRIBUTE_EXCEPTION;
- Import.Tag.SigIndex = getTagType(WS);
+ Import.SigIndex = getTagType(WS);
Imports.push_back(Import);
assert(WasmIndices.count(&WS) == 0);
WasmIndices[&WS] = NumTagImports++;
@@ -1409,7 +1443,7 @@ uint64_t WasmObjectWriter::writeOneObject(MCAssembler &Asm,
SmallVector<uint32_t, 4> TableElems;
SmallVector<wasm::WasmImport, 4> Imports;
SmallVector<wasm::WasmExport, 4> Exports;
- SmallVector<wasm::WasmTagType, 1> Tags;
+ SmallVector<uint32_t, 2> TagTypes;
SmallVector<wasm::WasmGlobal, 1> Globals;
SmallVector<wasm::WasmTable, 1> Tables;
SmallVector<wasm::WasmSymbolInfo, 4> SymbolInfos;
@@ -1644,16 +1678,15 @@ uint64_t WasmObjectWriter::writeOneObject(MCAssembler &Asm,
LLVM_DEBUG(dbgs() << " -> table index: "
<< WasmIndices.find(&WS)->second << "\n");
} else if (WS.isTag()) {
- // C++ exception symbol (__cpp_exception)
+ // C++ exception symbol (__cpp_exception) or longjmp symbol
+ // (__c_longjmp)
unsigned Index;
if (WS.isDefined()) {
- Index = NumTagImports + Tags.size();
- wasm::WasmTagType Tag;
- Tag.SigIndex = getTagType(WS);
- Tag.Attribute = wasm::WASM_TAG_ATTRIBUTE_EXCEPTION;
+ Index = NumTagImports + TagTypes.size();
+ uint32_t SigIndex = getTagType(WS);
assert(WasmIndices.count(&WS) == 0);
WasmIndices[&WS] = Index;
- Tags.push_back(Tag);
+ TagTypes.push_back(SigIndex);
} else {
// An import; the index was assigned above.
assert(WasmIndices.count(&WS) > 0);
@@ -1747,6 +1780,8 @@ uint64_t WasmObjectWriter::writeOneObject(MCAssembler &Asm,
Flags |= wasm::WASM_SYMBOL_EXPLICIT_NAME;
if (WS.hasExportName())
Flags |= wasm::WASM_SYMBOL_EXPORTED;
+ if (WS.isTLS())
+ Flags |= wasm::WASM_SYMBOL_TLS;
wasm::WasmSymbolInfo Info;
Info.Name = WS.getName();
@@ -1869,7 +1904,7 @@ uint64_t WasmObjectWriter::writeOneObject(MCAssembler &Asm,
writeFunctionSection(Functions);
writeTableSection(Tables);
// Skip the "memory" section; we import the memory instead.
- writeTagSection(Tags);
+ writeTagSection(TagTypes);
writeGlobalSection(Globals);
writeExportSection(Exports);
const MCSymbol *IndirectFunctionTable =
diff --git a/contrib/llvm-project/llvm/lib/MC/XCOFFObjectWriter.cpp b/contrib/llvm-project/llvm/lib/MC/XCOFFObjectWriter.cpp
index adf0d3eb443c..177253d7a9d7 100644
--- a/contrib/llvm-project/llvm/lib/MC/XCOFFObjectWriter.cpp
+++ b/contrib/llvm-project/llvm/lib/MC/XCOFFObjectWriter.cpp
@@ -168,6 +168,24 @@ struct CsectSectionEntry : public SectionEntry {
virtual ~CsectSectionEntry() {}
};
+struct DwarfSectionEntry : public SectionEntry {
+ // For DWARF section entry.
+ std::unique_ptr<XCOFFSection> DwarfSect;
+
+ DwarfSectionEntry(StringRef N, int32_t Flags,
+ std::unique_ptr<XCOFFSection> Sect)
+ : SectionEntry(N, Flags | XCOFF::STYP_DWARF), DwarfSect(std::move(Sect)) {
+ assert(DwarfSect->MCSec->isDwarfSect() &&
+ "This should be a DWARF section!");
+ assert(N.size() <= XCOFF::NameSize && "section name too long");
+ memcpy(Name, N.data(), N.size());
+ }
+
+ DwarfSectionEntry(DwarfSectionEntry &&s) = default;
+
+ virtual ~DwarfSectionEntry() {}
+};
+
class XCOFFObjectWriter : public MCObjectWriter {
uint32_t SymbolTableEntryCount = 0;
@@ -213,6 +231,8 @@ class XCOFFObjectWriter : public MCObjectWriter {
std::array<CsectSectionEntry *const, 5> Sections{
{&Text, &Data, &BSS, &TData, &TBSS}};
+ std::vector<DwarfSectionEntry> DwarfSections;
+
CsectGroup &getCsectGroup(const MCSectionXCOFF *MCSec);
virtual void reset() override;
@@ -231,12 +251,21 @@ class XCOFFObjectWriter : public MCObjectWriter {
uint64_t);
void writeSymbolTableEntryForControlSection(const XCOFFSection &, int16_t,
XCOFF::StorageClass);
+ void writeSymbolTableEntryForDwarfSection(const XCOFFSection &, int16_t);
void writeFileHeader();
void writeSectionHeaderTable();
void writeSections(const MCAssembler &Asm, const MCAsmLayout &Layout);
+ void writeSectionForControlSectionEntry(const MCAssembler &Asm,
+ const MCAsmLayout &Layout,
+ const CsectSectionEntry &CsectEntry,
+ uint32_t &CurrentAddressLocation);
+ void writeSectionForDwarfSectionEntry(const MCAssembler &Asm,
+ const MCAsmLayout &Layout,
+ const DwarfSectionEntry &DwarfEntry,
+ uint32_t &CurrentAddressLocation);
void writeSymbolTable(const MCAsmLayout &Layout);
void writeRelocations();
- void writeRelocation(XCOFFRelocation Reloc, const XCOFFSection &CSection);
+ void writeRelocation(XCOFFRelocation Reloc, const XCOFFSection &Section);
// Called after all the csects and symbols have been processed by
// `executePostLayoutBinding`, this function handles building up the majority
@@ -290,6 +319,8 @@ void XCOFFObjectWriter::reset() {
// Reset any sections we have written to, and empty the section header table.
for (auto *Sec : Sections)
Sec->reset();
+ for (auto &DwarfSec : DwarfSections)
+ DwarfSec.reset();
// Reset states in XCOFFObjectWriter.
SymbolTableEntryCount = 0;
@@ -372,17 +403,32 @@ void XCOFFObjectWriter::executePostLayoutBinding(MCAssembler &Asm,
const auto *MCSec = cast<const MCSectionXCOFF>(&S);
assert(SectionMap.find(MCSec) == SectionMap.end() &&
"Cannot add a section twice.");
- assert(XCOFF::XTY_ER != MCSec->getCSectType() &&
- "An undefined csect should not get registered.");
// If the name does not fit in the storage provided in the symbol table
// entry, add it to the string table.
if (nameShouldBeInStringTable(MCSec->getSymbolTableName()))
Strings.add(MCSec->getSymbolTableName());
-
- CsectGroup &Group = getCsectGroup(MCSec);
- Group.emplace_back(MCSec);
- SectionMap[MCSec] = &Group.back();
+ if (MCSec->isCsect()) {
+ // A new control section. Its CsectSectionEntry should already be staticly
+ // generated as Text/Data/BSS/TDATA/TBSS. Add this section to the group of
+ // the CsectSectionEntry.
+ assert(XCOFF::XTY_ER != MCSec->getCSectType() &&
+ "An undefined csect should not get registered.");
+ CsectGroup &Group = getCsectGroup(MCSec);
+ Group.emplace_back(MCSec);
+ SectionMap[MCSec] = &Group.back();
+ } else if (MCSec->isDwarfSect()) {
+ // A new DwarfSectionEntry.
+ std::unique_ptr<XCOFFSection> DwarfSec =
+ std::make_unique<XCOFFSection>(MCSec);
+ SectionMap[MCSec] = DwarfSec.get();
+
+ DwarfSectionEntry SecEntry(MCSec->getName(),
+ MCSec->getDwarfSubtypeFlags().getValue(),
+ std::move(DwarfSec));
+ DwarfSections.push_back(std::move(SecEntry));
+ } else
+ llvm_unreachable("unsupport section type!");
}
for (const MCSymbol &S : Asm.symbols()) {
@@ -443,13 +489,20 @@ void XCOFFObjectWriter::recordRelocation(MCAssembler &Asm,
: SymbolIndexMap[ContainingCsect->getQualNameSymbol()];
};
- auto getVirtualAddress = [this,
- &Layout](const MCSymbol *Sym,
- const MCSectionXCOFF *ContainingCsect) {
- // If Sym is a csect, return csect's address.
- // If Sym is a label, return csect's address + label's offset from the csect.
- return SectionMap[ContainingCsect]->Address +
- (Sym->isDefined() ? Layout.getSymbolOffset(*Sym) : 0);
+ auto getVirtualAddress =
+ [this, &Layout](const MCSymbol *Sym,
+ const MCSectionXCOFF *ContainingSect) -> uint64_t {
+ // A DWARF section.
+ if (ContainingSect->isDwarfSect())
+ return Layout.getSymbolOffset(*Sym);
+
+ // A csect.
+ if (!Sym->isDefined())
+ return SectionMap[ContainingSect]->Address;
+
+ // A label.
+ assert(Sym->isDefined() && "not a valid object that has address!");
+ return SectionMap[ContainingSect]->Address + Layout.getSymbolOffset(*Sym);
};
const MCSymbol *const SymA = &Target.getSymA()->getSymbol();
@@ -538,41 +591,12 @@ void XCOFFObjectWriter::recordRelocation(MCAssembler &Asm,
void XCOFFObjectWriter::writeSections(const MCAssembler &Asm,
const MCAsmLayout &Layout) {
uint32_t CurrentAddressLocation = 0;
- for (const auto *Section : Sections) {
- // Nothing to write for this Section.
- if (Section->Index == SectionEntry::UninitializedIndex ||
- Section->IsVirtual)
- continue;
-
- // There could be a gap (without corresponding zero padding) between
- // sections.
- assert(((CurrentAddressLocation <= Section->Address) ||
- (Section->Flags == XCOFF::STYP_TDATA) ||
- (Section->Flags == XCOFF::STYP_TBSS)) &&
- "CurrentAddressLocation should be less than or equal to section "
- "address if the section is not TData or TBSS.");
-
- CurrentAddressLocation = Section->Address;
-
- for (const auto *Group : Section->Groups) {
- for (const auto &Csect : *Group) {
- if (uint32_t PaddingSize = Csect.Address - CurrentAddressLocation)
- W.OS.write_zeros(PaddingSize);
- if (Csect.Size)
- Asm.writeSectionData(W.OS, Csect.MCSec, Layout);
- CurrentAddressLocation = Csect.Address + Csect.Size;
- }
- }
-
- // The size of the tail padding in a section is the end virtual address of
- // the current section minus the the end virtual address of the last csect
- // in that section.
- if (uint32_t PaddingSize =
- Section->Address + Section->Size - CurrentAddressLocation) {
- W.OS.write_zeros(PaddingSize);
- CurrentAddressLocation += PaddingSize;
- }
- }
+ for (const auto *Section : Sections)
+ writeSectionForControlSectionEntry(Asm, Layout, *Section,
+ CurrentAddressLocation);
+ for (const auto &DwarfSection : DwarfSections)
+ writeSectionForDwarfSectionEntry(Asm, Layout, DwarfSection,
+ CurrentAddressLocation);
}
uint64_t XCOFFObjectWriter::writeObject(MCAssembler &Asm,
@@ -654,6 +678,36 @@ void XCOFFObjectWriter::writeSymbolTableEntryForCsectMemberLabel(
W.write<uint16_t>(0);
}
+void XCOFFObjectWriter::writeSymbolTableEntryForDwarfSection(
+ const XCOFFSection &DwarfSectionRef, int16_t SectionIndex) {
+ assert(DwarfSectionRef.MCSec->isDwarfSect() && "Not a DWARF section!");
+
+ // n_name, n_zeros, n_offset
+ writeSymbolName(DwarfSectionRef.getSymbolTableName());
+ // n_value
+ W.write<uint32_t>(0);
+ // n_scnum
+ W.write<int16_t>(SectionIndex);
+ // n_type
+ W.write<uint16_t>(0);
+ // n_sclass
+ W.write<uint8_t>(XCOFF::C_DWARF);
+ // Always 1 aux entry for now.
+ W.write<uint8_t>(1);
+
+ // Now output the auxiliary entry.
+ // x_scnlen
+ W.write<uint32_t>(DwarfSectionRef.Size);
+ // Reserved
+ W.write<uint32_t>(0);
+ // x_nreloc. Set to 0 for now.
+ W.write<uint32_t>(0);
+ // Reserved
+ W.write<uint32_t>(0);
+ // Reserved
+ W.write<uint16_t>(0);
+}
+
void XCOFFObjectWriter::writeSymbolTableEntryForControlSection(
const XCOFFSection &CSectionRef, int16_t SectionIndex,
XCOFF::StorageClass StorageClass) {
@@ -711,10 +765,10 @@ void XCOFFObjectWriter::writeFileHeader() {
}
void XCOFFObjectWriter::writeSectionHeaderTable() {
- for (const auto *Sec : Sections) {
+ auto writeSectionHeader = [&](const SectionEntry *Sec, bool IsDwarf) {
// Nothing to write for this Section.
if (Sec->Index == SectionEntry::UninitializedIndex)
- continue;
+ return false;
// Write Name.
ArrayRef<char> NameRef(Sec->Name, XCOFF::NameSize);
@@ -722,8 +776,14 @@ void XCOFFObjectWriter::writeSectionHeaderTable() {
// Write the Physical Address and Virtual Address. In an object file these
// are the same.
- W.write<uint32_t>(Sec->Address);
- W.write<uint32_t>(Sec->Address);
+ // We use 0 for DWARF sections' Physical and Virtual Addresses.
+ if (!IsDwarf) {
+ W.write<uint32_t>(Sec->Address);
+ W.write<uint32_t>(Sec->Address);
+ } else {
+ W.write<uint32_t>(0);
+ W.write<uint32_t>(0);
+ }
W.write<uint32_t>(Sec->Size);
W.write<uint32_t>(Sec->FileOffsetToData);
@@ -738,12 +798,25 @@ void XCOFFObjectWriter::writeSectionHeaderTable() {
W.write<uint16_t>(0);
W.write<int32_t>(Sec->Flags);
- }
+
+ return true;
+ };
+
+ for (const auto *CsectSec : Sections)
+ writeSectionHeader(CsectSec, /* IsDwarf */ false);
+ for (const auto &DwarfSec : DwarfSections)
+ writeSectionHeader(&DwarfSec, /* IsDwarf */ true);
}
void XCOFFObjectWriter::writeRelocation(XCOFFRelocation Reloc,
- const XCOFFSection &CSection) {
- W.write<uint32_t>(CSection.Address + Reloc.FixupOffsetInCsect);
+ const XCOFFSection &Section) {
+ if (Section.MCSec->isCsect())
+ W.write<uint32_t>(Section.Address + Reloc.FixupOffsetInCsect);
+ else {
+ // DWARF sections' address is set to 0.
+ assert(Section.MCSec->isDwarfSect() && "unsupport section type!");
+ W.write<uint32_t>(Reloc.FixupOffsetInCsect);
+ }
W.write<uint32_t>(Reloc.SymbolTableIndex);
W.write<uint8_t>(Reloc.SignAndSize);
W.write<uint8_t>(Reloc.Type);
@@ -765,6 +838,10 @@ void XCOFFObjectWriter::writeRelocations() {
}
}
}
+
+ for (const auto &DwarfSection : DwarfSections)
+ for (const auto &Reloc : DwarfSection.DwarfSect->Relocations)
+ writeRelocation(Reloc, *DwarfSection.DwarfSect);
}
void XCOFFObjectWriter::writeSymbolTable(const MCAsmLayout &Layout) {
@@ -819,6 +896,10 @@ void XCOFFObjectWriter::writeSymbolTable(const MCAsmLayout &Layout) {
}
}
}
+
+ for (const auto &DwarfSection : DwarfSections)
+ writeSymbolTableEntryForDwarfSection(*DwarfSection.DwarfSect,
+ DwarfSection.Index);
}
void XCOFFObjectWriter::finalizeSectionInfo() {
@@ -844,11 +925,17 @@ void XCOFFObjectWriter::finalizeSectionInfo() {
}
}
+ for (auto &DwarfSection : DwarfSections)
+ DwarfSection.RelocationCount = DwarfSection.DwarfSect->Relocations.size();
+
// Calculate the file offset to the relocation entries.
uint64_t RawPointer = RelocationEntryOffset;
- for (auto Sec : Sections) {
- if (Sec->Index == SectionEntry::UninitializedIndex || !Sec->RelocationCount)
- continue;
+ auto calcOffsetToRelocations = [&](SectionEntry *Sec, bool IsDwarf) {
+ if (!IsDwarf && Sec->Index == SectionEntry::UninitializedIndex)
+ return false;
+
+ if (!Sec->RelocationCount)
+ return false;
Sec->FileOffsetToRelocations = RawPointer;
const uint32_t RelocationSizeInSec =
@@ -856,7 +943,15 @@ void XCOFFObjectWriter::finalizeSectionInfo() {
RawPointer += RelocationSizeInSec;
if (RawPointer > UINT32_MAX)
report_fatal_error("Relocation data overflowed this object file.");
- }
+
+ return true;
+ };
+
+ for (auto *Sec : Sections)
+ calcOffsetToRelocations(Sec, /* IsDwarf */ false);
+
+ for (auto &DwarfSec : DwarfSections)
+ calcOffsetToRelocations(&DwarfSec, /* IsDwarf */ true);
// TODO Error check that the number of symbol table entries fits in 32-bits
// signed ...
@@ -944,6 +1039,37 @@ void XCOFFObjectWriter::assignAddressesAndIndices(const MCAsmLayout &Layout) {
Section->Size = Address - Section->Address;
}
+ for (auto &DwarfSection : DwarfSections) {
+ assert((SectionIndex <= MaxSectionIndex) && "Section index overflow!");
+
+ XCOFFSection &DwarfSect = *DwarfSection.DwarfSect;
+ const MCSectionXCOFF *MCSec = DwarfSect.MCSec;
+
+ // Section index.
+ DwarfSection.Index = SectionIndex++;
+ SectionCount++;
+
+ // Symbol index.
+ DwarfSect.SymbolTableIndex = SymbolTableIndex;
+ SymbolIndexMap[MCSec->getQualNameSymbol()] = DwarfSect.SymbolTableIndex;
+ // 1 main and 1 auxiliary symbol table entry for the csect.
+ SymbolTableIndex += 2;
+
+ // Section address. Make it align to section alignment.
+ // We use address 0 for DWARF sections' Physical and Virtual Addresses.
+ // This address is used to tell where is the section in the final object.
+ // See writeSectionForDwarfSectionEntry().
+ DwarfSection.Address = DwarfSect.Address =
+ alignTo(Address, MCSec->getAlignment());
+
+ // Section size.
+ // For DWARF section, we must use the real size which may be not aligned.
+ DwarfSection.Size = DwarfSect.Size = Layout.getSectionAddressSize(MCSec);
+
+ // Make the Address align to default alignment for follow section.
+ Address = alignTo(DwarfSect.Address + DwarfSect.Size, DefaultSectionAlign);
+ }
+
SymbolTableEntryCount = SymbolTableIndex;
// Calculate the RawPointer value for each section.
@@ -959,9 +1085,102 @@ void XCOFFObjectWriter::assignAddressesAndIndices(const MCAsmLayout &Layout) {
report_fatal_error("Section raw data overflowed this object file.");
}
+ for (auto &DwarfSection : DwarfSections) {
+ // Address of csect sections are always aligned to DefaultSectionAlign, but
+ // address of DWARF section are aligned to Section alignment which may be
+ // bigger than DefaultSectionAlign, need to execlude the padding bits.
+ RawPointer =
+ alignTo(RawPointer, DwarfSection.DwarfSect->MCSec->getAlignment());
+
+ DwarfSection.FileOffsetToData = RawPointer;
+ // Some section entries, like DWARF section size is not aligned, so
+ // RawPointer may be not aligned.
+ RawPointer += DwarfSection.Size;
+ // Make sure RawPointer is aligned.
+ RawPointer = alignTo(RawPointer, DefaultSectionAlign);
+
+ assert(RawPointer <= UINT32_MAX &&
+ "Section raw data overflowed this object file.");
+ }
+
RelocationEntryOffset = RawPointer;
}
+void XCOFFObjectWriter::writeSectionForControlSectionEntry(
+ const MCAssembler &Asm, const MCAsmLayout &Layout,
+ const CsectSectionEntry &CsectEntry, uint32_t &CurrentAddressLocation) {
+ // Nothing to write for this Section.
+ if (CsectEntry.Index == SectionEntry::UninitializedIndex)
+ return;
+
+ // There could be a gap (without corresponding zero padding) between
+ // sections.
+ // There could be a gap (without corresponding zero padding) between
+ // sections.
+ assert(((CurrentAddressLocation <= CsectEntry.Address) ||
+ (CsectEntry.Flags == XCOFF::STYP_TDATA) ||
+ (CsectEntry.Flags == XCOFF::STYP_TBSS)) &&
+ "CurrentAddressLocation should be less than or equal to section "
+ "address if the section is not TData or TBSS.");
+
+ CurrentAddressLocation = CsectEntry.Address;
+
+ // For virtual sections, nothing to write. But need to increase
+ // CurrentAddressLocation for later sections like DWARF section has a correct
+ // writing location.
+ if (CsectEntry.IsVirtual) {
+ CurrentAddressLocation += CsectEntry.Size;
+ return;
+ }
+
+ for (const auto &Group : CsectEntry.Groups) {
+ for (const auto &Csect : *Group) {
+ if (uint32_t PaddingSize = Csect.Address - CurrentAddressLocation)
+ W.OS.write_zeros(PaddingSize);
+ if (Csect.Size)
+ Asm.writeSectionData(W.OS, Csect.MCSec, Layout);
+ CurrentAddressLocation = Csect.Address + Csect.Size;
+ }
+ }
+
+ // The size of the tail padding in a section is the end virtual address of
+ // the current section minus the the end virtual address of the last csect
+ // in that section.
+ if (uint32_t PaddingSize =
+ CsectEntry.Address + CsectEntry.Size - CurrentAddressLocation) {
+ W.OS.write_zeros(PaddingSize);
+ CurrentAddressLocation += PaddingSize;
+ }
+}
+
+void XCOFFObjectWriter::writeSectionForDwarfSectionEntry(
+ const MCAssembler &Asm, const MCAsmLayout &Layout,
+ const DwarfSectionEntry &DwarfEntry, uint32_t &CurrentAddressLocation) {
+ // There could be a gap (without corresponding zero padding) between
+ // sections. For example DWARF section alignment is bigger than
+ // DefaultSectionAlign.
+ assert(CurrentAddressLocation <= DwarfEntry.Address &&
+ "CurrentAddressLocation should be less than or equal to section "
+ "address.");
+
+ if (uint32_t PaddingSize = DwarfEntry.Address - CurrentAddressLocation)
+ W.OS.write_zeros(PaddingSize);
+
+ if (DwarfEntry.Size)
+ Asm.writeSectionData(W.OS, DwarfEntry.DwarfSect->MCSec, Layout);
+
+ CurrentAddressLocation = DwarfEntry.Address + DwarfEntry.Size;
+
+ // DWARF section size is not aligned to DefaultSectionAlign.
+ // Make sure CurrentAddressLocation is aligned to DefaultSectionAlign.
+ uint32_t Mod = CurrentAddressLocation % DefaultSectionAlign;
+ uint32_t TailPaddingSize = Mod ? DefaultSectionAlign - Mod : 0;
+ if (TailPaddingSize)
+ W.OS.write_zeros(TailPaddingSize);
+
+ CurrentAddressLocation += TailPaddingSize;
+}
+
// Takes the log base 2 of the alignment and shifts the result into the 5 most
// significant bits of a byte, then or's in the csect type into the least
// significant 3 bits.