blob: 7885e3013a51d3f67a74891d81890cbf88653a5c [file] [log] [blame]
//===- 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())
.Case("debug_pubnames",
MC->getObjectFileInfo()->getDwarfPubNamesSection())
.Case("debug_pubtypes",
MC->getObjectFileInfo()->getDwarfPubTypesSection())
.Case("debug_names", MC->getObjectFileInfo()->getDwarfDebugNamesSection())
.Case("apple_names", MC->getObjectFileInfo()->getDwarfAccelNamesSection())
.Case("apple_namespac",
MC->getObjectFileInfo()->getDwarfAccelNamespaceSection())
.Case("apple_objc", MC->getObjectFileInfo()->getDwarfAccelObjCSection())
.Case("apple_types", MC->getObjectFileInfo()->getDwarfAccelTypesSection())
.Default(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.getUnitSize() - 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();
}
void DwarfEmitterImpl::emitDebugNames(
AccelTable<DWARF5AccelTableStaticData> &Table,
DebugNamesUnitsOffsets &CUOffsets, CompUnitIDToIdx &CUidToIdx) {
if (CUOffsets.empty())
return;
Asm->OutStreamer->switchSection(MOFI->getDwarfDebugNamesSection());
emitDWARF5AccelTable(Asm.get(), Table, CUOffsets,
[&CUidToIdx](const DWARF5AccelTableStaticData &Entry) {
return CUidToIdx[Entry.getCUIndex()];
});
}
void DwarfEmitterImpl::emitAppleNamespaces(
AccelTable<AppleAccelTableStaticOffsetData> &Table) {
Asm->OutStreamer->switchSection(MOFI->getDwarfAccelNamespaceSection());
auto *SectionBegin = Asm->createTempSymbol("namespac_begin");
Asm->OutStreamer->emitLabel(SectionBegin);
emitAppleAccelTable(Asm.get(), Table, "namespac", SectionBegin);
}
void DwarfEmitterImpl::emitAppleNames(
AccelTable<AppleAccelTableStaticOffsetData> &Table) {
Asm->OutStreamer->switchSection(MOFI->getDwarfAccelNamesSection());
auto *SectionBegin = Asm->createTempSymbol("names_begin");
Asm->OutStreamer->emitLabel(SectionBegin);
emitAppleAccelTable(Asm.get(), Table, "names", SectionBegin);
}
void DwarfEmitterImpl::emitAppleObjc(
AccelTable<AppleAccelTableStaticOffsetData> &Table) {
Asm->OutStreamer->switchSection(MOFI->getDwarfAccelObjCSection());
auto *SectionBegin = Asm->createTempSymbol("objc_begin");
Asm->OutStreamer->emitLabel(SectionBegin);
emitAppleAccelTable(Asm.get(), Table, "objc", SectionBegin);
}
void DwarfEmitterImpl::emitAppleTypes(
AccelTable<AppleAccelTableStaticTypeData> &Table) {
Asm->OutStreamer->switchSection(MOFI->getDwarfAccelTypesSection());
auto *SectionBegin = Asm->createTempSymbol("types_begin");
Asm->OutStreamer->emitLabel(SectionBegin);
emitAppleAccelTable(Asm.get(), Table, "types", SectionBegin);
}
} // end of namespace dwarflinker_parallel
} // namespace llvm