llvm-project/llvm/lib/DWARFLinkerParallel/DWARFEmitterImpl.cpp
Alexey Lapshin 5f2a7fa67e [Reland][Reland][DWARFLinkerParallel] Add limited functionality to DWARFLinkerParallel.
This patch is extracted from D96035, it adds support for the existing
DWARFLinker functionality. What is not supported yet:

1. Types deduplication(--odr mode).
2. Modules deduplication.
3. Generation of index tables.

Reland2: temporarily disabled call to "--linker llvm" for tls-variable.test
and location-expression.test as it does not work properly on bigendian
architecture.

Differential Revision: https://reviews.llvm.org/D153268
2023-08-21 11:09:18 +02:00

229 lines
8.6 KiB
C++

//===- DWARFEmitterImpl.cpp -----------------------------------------------===//
//
// 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 "DWARFEmitterImpl.h"
#include "llvm/DWARFLinker/DWARFLinkerCompileUnit.h"
#include "llvm/MC/MCAsmBackend.h"
#include "llvm/MC/MCCodeEmitter.h"
#include "llvm/MC/MCObjectWriter.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/MC/MCTargetOptions.h"
#include "llvm/MC/MCTargetOptionsCommandFlags.h"
#include "llvm/MC/TargetRegistry.h"
#include "llvm/Support/FormattedStream.h"
namespace llvm {
namespace dwarflinker_parallel {
Error DwarfEmitterImpl::init(Triple TheTriple,
StringRef Swift5ReflectionSegmentName) {
std::string ErrorStr;
std::string TripleName;
// Get the target.
const Target *TheTarget =
TargetRegistry::lookupTarget(TripleName, TheTriple, ErrorStr);
if (!TheTarget)
return createStringError(std::errc::invalid_argument, ErrorStr.c_str());
TripleName = TheTriple.getTriple();
// Create all the MC Objects.
MRI.reset(TheTarget->createMCRegInfo(TripleName));
if (!MRI)
return createStringError(std::errc::invalid_argument,
"no register info for target %s",
TripleName.c_str());
MCTargetOptions MCOptions = mc::InitMCTargetOptionsFromFlags();
MAI.reset(TheTarget->createMCAsmInfo(*MRI, TripleName, MCOptions));
if (!MAI)
return createStringError(std::errc::invalid_argument,
"no asm info for target %s", TripleName.c_str());
MSTI.reset(TheTarget->createMCSubtargetInfo(TripleName, "", ""));
if (!MSTI)
return createStringError(std::errc::invalid_argument,
"no subtarget info for target %s",
TripleName.c_str());
MC.reset(new MCContext(TheTriple, MAI.get(), MRI.get(), MSTI.get(), nullptr,
nullptr, true, Swift5ReflectionSegmentName));
MOFI.reset(TheTarget->createMCObjectFileInfo(*MC, /*PIC=*/false, false));
MC->setObjectFileInfo(MOFI.get());
MAB = TheTarget->createMCAsmBackend(*MSTI, *MRI, MCOptions);
if (!MAB)
return createStringError(std::errc::invalid_argument,
"no asm backend for target %s",
TripleName.c_str());
MII.reset(TheTarget->createMCInstrInfo());
if (!MII)
return createStringError(std::errc::invalid_argument,
"no instr info info for target %s",
TripleName.c_str());
MCE = TheTarget->createMCCodeEmitter(*MII, *MC);
if (!MCE)
return createStringError(std::errc::invalid_argument,
"no code emitter for target %s",
TripleName.c_str());
switch (OutFileType) {
case DWARFLinker::OutputFileType::Assembly: {
MIP = TheTarget->createMCInstPrinter(TheTriple, MAI->getAssemblerDialect(),
*MAI, *MII, *MRI);
MS = TheTarget->createAsmStreamer(
*MC, std::make_unique<formatted_raw_ostream>(OutFile), true, true, MIP,
std::unique_ptr<MCCodeEmitter>(MCE), std::unique_ptr<MCAsmBackend>(MAB),
true);
break;
}
case DWARFLinker::OutputFileType::Object: {
MS = TheTarget->createMCObjectStreamer(
TheTriple, *MC, std::unique_ptr<MCAsmBackend>(MAB),
MAB->createObjectWriter(OutFile), std::unique_ptr<MCCodeEmitter>(MCE),
*MSTI, MCOptions.MCRelaxAll, MCOptions.MCIncrementalLinkerCompatible,
/*DWARFMustBeAtTheEnd*/ false);
break;
}
}
if (!MS)
return createStringError(std::errc::invalid_argument,
"no object streamer for target %s",
TripleName.c_str());
// Finally create the AsmPrinter we'll use to emit the DIEs.
TM.reset(TheTarget->createTargetMachine(TripleName, "", "", TargetOptions(),
std::nullopt));
if (!TM)
return createStringError(std::errc::invalid_argument,
"no target machine for target %s",
TripleName.c_str());
Asm.reset(TheTarget->createAsmPrinter(*TM, std::unique_ptr<MCStreamer>(MS)));
if (!Asm)
return createStringError(std::errc::invalid_argument,
"no asm printer for target %s",
TripleName.c_str());
Asm->setDwarfUsesRelocationsAcrossSections(false);
DebugInfoSectionSize = 0;
return Error::success();
}
void DwarfEmitterImpl::emitSwiftAST(StringRef Buffer) {
MCSection *SwiftASTSection = MOFI->getDwarfSwiftASTSection();
SwiftASTSection->setAlignment(Align(32));
MS->switchSection(SwiftASTSection);
MS->emitBytes(Buffer);
}
/// Emit the swift reflection section stored in \p Buffer.
void DwarfEmitterImpl::emitSwiftReflectionSection(
llvm::binaryformat::Swift5ReflectionSectionKind ReflSectionKind,
StringRef Buffer, uint32_t Alignment, uint32_t) {
MCSection *ReflectionSection =
MOFI->getSwift5ReflectionSection(ReflSectionKind);
if (ReflectionSection == nullptr)
return;
ReflectionSection->setAlignment(Align(Alignment));
MS->switchSection(ReflectionSection);
MS->emitBytes(Buffer);
}
void DwarfEmitterImpl::emitSectionContents(StringRef SecData,
StringRef SecName) {
if (SecData.empty())
return;
if (MCSection *Section = switchSection(SecName)) {
MS->switchSection(Section);
MS->emitBytes(SecData);
}
}
MCSection *DwarfEmitterImpl::switchSection(StringRef SecName) {
return StringSwitch<MCSection *>(SecName)
.Case("debug_info", MC->getObjectFileInfo()->getDwarfInfoSection())
.Case("debug_abbrev", MC->getObjectFileInfo()->getDwarfAbbrevSection())
.Case("debug_line", MC->getObjectFileInfo()->getDwarfLineSection())
.Case("debug_loc", MC->getObjectFileInfo()->getDwarfLocSection())
.Case("debug_ranges", MC->getObjectFileInfo()->getDwarfRangesSection())
.Case("debug_frame", MC->getObjectFileInfo()->getDwarfFrameSection())
.Case("debug_aranges", MC->getObjectFileInfo()->getDwarfARangesSection())
.Case("debug_rnglists",
MC->getObjectFileInfo()->getDwarfRnglistsSection())
.Case("debug_loclists",
MC->getObjectFileInfo()->getDwarfLoclistsSection())
.Case("debug_macro", MC->getObjectFileInfo()->getDwarfMacroSection())
.Case("debug_macinfo", MC->getObjectFileInfo()->getDwarfMacinfoSection())
.Case("debug_addr", MC->getObjectFileInfo()->getDwarfAddrSection())
.Case("debug_str", MC->getObjectFileInfo()->getDwarfStrSection())
.Case("debug_line_str", MC->getObjectFileInfo()->getDwarfLineStrSection())
.Case("debug_str_offsets",
MC->getObjectFileInfo()->getDwarfStrOffSection())
.Default(nullptr);
}
MCSymbol *DwarfEmitterImpl::emitTempSym(StringRef SecName, StringRef SymName) {
if (MCSection *Section = switchSection(SecName)) {
MS->switchSection(Section);
MCSymbol *Res = Asm->createTempSymbol(SymName);
Asm->OutStreamer->emitLabel(Res);
return Res;
}
return nullptr;
}
void DwarfEmitterImpl::emitAbbrevs(
const SmallVector<std::unique_ptr<DIEAbbrev>> &Abbrevs,
unsigned DwarfVersion) {
MS->switchSection(MOFI->getDwarfAbbrevSection());
MC->setDwarfVersion(DwarfVersion);
Asm->emitDwarfAbbrevs(Abbrevs);
}
void DwarfEmitterImpl::emitCompileUnitHeader(DwarfUnit &Unit) {
MS->switchSection(MOFI->getDwarfInfoSection());
MC->setDwarfVersion(Unit.getVersion());
// Emit size of content not including length itself. The size has already
// been computed in CompileUnit::computeOffsets(). Subtract 4 to that size to
// account for the length field.
Asm->emitInt32(Unit.getDebugInfoHeaderSize() +
Unit.getOutUnitDIE()->getSize() - 4);
Asm->emitInt16(Unit.getVersion());
if (Unit.getVersion() >= 5) {
Asm->emitInt8(dwarf::DW_UT_compile);
Asm->emitInt8(Unit.getFormParams().AddrSize);
// Proper offset to the abbreviations table will be set later.
Asm->emitInt32(0);
DebugInfoSectionSize += 12;
} else {
// Proper offset to the abbreviations table will be set later.
Asm->emitInt32(0);
Asm->emitInt8(Unit.getFormParams().AddrSize);
DebugInfoSectionSize += 11;
}
}
void DwarfEmitterImpl::emitDIE(DIE &Die) {
MS->switchSection(MOFI->getDwarfInfoSection());
Asm->emitDwarfDIE(Die);
DebugInfoSectionSize += Die.getSize();
}
} // end of namespace dwarflinker_parallel
} // namespace llvm