diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2022-03-20 11:40:34 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2022-05-14 11:43:05 +0000 |
commit | 349cc55c9796c4596a5b9904cd3281af295f878f (patch) | |
tree | 410c5a785075730a35f1272ca6a7adf72222ad03 /contrib/llvm-project/llvm/lib/MC | |
parent | cb2ae6163174b90e999326ecec3699ee093a5d43 (diff) | |
parent | c0981da47d5696fe36474fcf86b4ce03ae3ff818 (diff) | |
download | src-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')
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. |