mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-22 10:42:39 +01:00
Support dwarf fission for wasm object files
Initial support for dwarf fission sections (-gsplit-dwarf) on wasm. The most interesting change is support for writing 2 files (.o and .dwo) in the wasm object writer. My approach moves object-writing logic into its own function and calls it twice, swapping out the endian::Writer (W) in between calls. It also splits the import-preparation step into its own function (and skips it when writing a dwo). Differential Revision: https://reviews.llvm.org/D85685
This commit is contained in:
parent
57f2631c85
commit
28f861215e
@ -52,6 +52,10 @@ std::unique_ptr<MCObjectWriter>
|
||||
createWasmObjectWriter(std::unique_ptr<MCWasmObjectTargetWriter> MOTW,
|
||||
raw_pwrite_stream &OS);
|
||||
|
||||
std::unique_ptr<MCObjectWriter>
|
||||
createWasmDwoObjectWriter(std::unique_ptr<MCWasmObjectTargetWriter> MOTW,
|
||||
raw_pwrite_stream &OS, raw_pwrite_stream &DwoOS);
|
||||
|
||||
} // namespace llvm
|
||||
|
||||
#endif
|
||||
|
@ -422,7 +422,10 @@ DIE &DwarfCompileUnit::updateSubprogramScopeDIE(const DISubprogram *SP) {
|
||||
// FIXME: duplicated from Target/WebAssembly/WebAssembly.h
|
||||
// don't want to depend on target specific headers in this code?
|
||||
const unsigned TI_GLOBAL_RELOC = 3;
|
||||
if (FrameBase.Location.WasmLoc.Kind == TI_GLOBAL_RELOC) {
|
||||
// FIXME: when writing dwo, we need to avoid relocations. Probably
|
||||
// the "right" solution is to treat globals the way func and data symbols
|
||||
// are (with entries in .debug_addr).
|
||||
if (FrameBase.Location.WasmLoc.Kind == TI_GLOBAL_RELOC && !isDwoUnit()) {
|
||||
// These need to be relocatable.
|
||||
assert(FrameBase.Location.WasmLoc.Index == 0); // Only SP so far.
|
||||
auto SPSym = cast<MCSymbolWasm>(
|
||||
|
@ -54,10 +54,17 @@ std::unique_ptr<MCObjectWriter>
|
||||
MCAsmBackend::createDwoObjectWriter(raw_pwrite_stream &OS,
|
||||
raw_pwrite_stream &DwoOS) const {
|
||||
auto TW = createObjectTargetWriter();
|
||||
if (TW->getFormat() != Triple::ELF)
|
||||
report_fatal_error("dwo only supported with ELF");
|
||||
return createELFDwoObjectWriter(cast<MCELFObjectTargetWriter>(std::move(TW)),
|
||||
OS, DwoOS, Endian == support::little);
|
||||
switch (TW->getFormat()) {
|
||||
case Triple::ELF:
|
||||
return createELFDwoObjectWriter(
|
||||
cast<MCELFObjectTargetWriter>(std::move(TW)), OS, DwoOS,
|
||||
Endian == support::little);
|
||||
case Triple::Wasm:
|
||||
return createWasmDwoObjectWriter(
|
||||
cast<MCWasmObjectTargetWriter>(std::move(TW)), OS, DwoOS);
|
||||
default:
|
||||
report_fatal_error("dwo only supported with ELF and Wasm");
|
||||
}
|
||||
}
|
||||
|
||||
Optional<MCFixupKind> MCAsmBackend::getFixupKind(StringRef Name) const {
|
||||
|
@ -796,6 +796,10 @@ void MCObjectFileInfo::initWasmMCObjectFileInfo(const Triple &T) {
|
||||
DwarfFrameSection = Ctx->getWasmSection(".debug_frame", SectionKind::getMetadata());
|
||||
DwarfPubNamesSection = Ctx->getWasmSection(".debug_pubnames", SectionKind::getMetadata());
|
||||
DwarfPubTypesSection = Ctx->getWasmSection(".debug_pubtypes", SectionKind::getMetadata());
|
||||
DwarfGnuPubNamesSection =
|
||||
Ctx->getWasmSection(".debug_gnu_pubnames", SectionKind::getMetadata());
|
||||
DwarfGnuPubTypesSection =
|
||||
Ctx->getWasmSection(".debug_gnu_pubtypes", SectionKind::getMetadata());
|
||||
|
||||
DwarfDebugNamesSection =
|
||||
Ctx->getWasmSection(".debug_names", SectionKind::getMetadata());
|
||||
@ -808,6 +812,37 @@ void MCObjectFileInfo::initWasmMCObjectFileInfo(const Triple &T) {
|
||||
DwarfLoclistsSection =
|
||||
Ctx->getWasmSection(".debug_loclists", SectionKind::getMetadata());
|
||||
|
||||
// Fission Sections
|
||||
DwarfInfoDWOSection =
|
||||
Ctx->getWasmSection(".debug_info.dwo", SectionKind::getMetadata());
|
||||
DwarfTypesDWOSection =
|
||||
Ctx->getWasmSection(".debug_types.dwo", SectionKind::getMetadata());
|
||||
DwarfAbbrevDWOSection =
|
||||
Ctx->getWasmSection(".debug_abbrev.dwo", SectionKind::getMetadata());
|
||||
DwarfStrDWOSection =
|
||||
Ctx->getWasmSection(".debug_str.dwo", SectionKind::getMetadata());
|
||||
DwarfLineDWOSection =
|
||||
Ctx->getWasmSection(".debug_line.dwo", SectionKind::getMetadata());
|
||||
DwarfLocDWOSection =
|
||||
Ctx->getWasmSection(".debug_loc.dwo", SectionKind::getMetadata());
|
||||
DwarfStrOffDWOSection =
|
||||
Ctx->getWasmSection(".debug_str_offsets.dwo", SectionKind::getMetadata());
|
||||
DwarfRnglistsDWOSection =
|
||||
Ctx->getWasmSection(".debug_rnglists.dwo", SectionKind::getMetadata());
|
||||
DwarfMacinfoDWOSection =
|
||||
Ctx->getWasmSection(".debug_macinfo.dwo", SectionKind::getMetadata());
|
||||
DwarfMacroDWOSection =
|
||||
Ctx->getWasmSection(".debug_macro.dwo", SectionKind::getMetadata());
|
||||
|
||||
DwarfLoclistsDWOSection =
|
||||
Ctx->getWasmSection(".debug_loclists.dwo", SectionKind::getMetadata());
|
||||
|
||||
// DWP Sections
|
||||
DwarfCUIndexSection =
|
||||
Ctx->getWasmSection(".debug_cu_index", SectionKind::getMetadata(), 0);
|
||||
DwarfTUIndexSection =
|
||||
Ctx->getWasmSection(".debug_tu_index", SectionKind::getMetadata(), 0);
|
||||
|
||||
// Wasm use data section for LSDA.
|
||||
// TODO Consider putting each function's exception table in a separate
|
||||
// section, as in -function-sections, to facilitate lld's --gc-section.
|
||||
|
@ -216,8 +216,12 @@ static void patchI64(raw_pwrite_stream &Stream, uint64_t X, uint64_t Offset) {
|
||||
Stream.pwrite((char *)Buffer, sizeof(Buffer), Offset);
|
||||
}
|
||||
|
||||
bool isDwoSection(const MCSection &Sec) {
|
||||
return Sec.getName().endswith(".dwo");
|
||||
}
|
||||
|
||||
class WasmObjectWriter : public MCObjectWriter {
|
||||
support::endian::Writer W;
|
||||
support::endian::Writer *W;
|
||||
|
||||
/// The target specific Wasm writer instance.
|
||||
std::unique_ptr<MCWasmObjectTargetWriter> TargetObjectWriter;
|
||||
@ -260,7 +264,16 @@ class WasmObjectWriter : public MCObjectWriter {
|
||||
unsigned NumEventImports = 0;
|
||||
uint32_t SectionCount = 0;
|
||||
|
||||
// TargetObjectWriter wrappers.
|
||||
enum class DwoMode {
|
||||
AllSections,
|
||||
NonDwoOnly,
|
||||
DwoOnly,
|
||||
};
|
||||
bool IsSplitDwarf = false;
|
||||
raw_pwrite_stream *OS = nullptr;
|
||||
raw_pwrite_stream *DwoOS = nullptr;
|
||||
|
||||
// TargetObjectWriter wranppers.
|
||||
bool is64Bit() const { return TargetObjectWriter->is64Bit(); }
|
||||
bool isEmscripten() const { return TargetObjectWriter->isEmscripten(); }
|
||||
|
||||
@ -270,8 +283,13 @@ class WasmObjectWriter : public MCObjectWriter {
|
||||
|
||||
public:
|
||||
WasmObjectWriter(std::unique_ptr<MCWasmObjectTargetWriter> MOTW,
|
||||
raw_pwrite_stream &OS)
|
||||
: W(OS, support::little), TargetObjectWriter(std::move(MOTW)) {}
|
||||
raw_pwrite_stream &OS_)
|
||||
: TargetObjectWriter(std::move(MOTW)), OS(&OS_) {}
|
||||
|
||||
WasmObjectWriter(std::unique_ptr<MCWasmObjectTargetWriter> MOTW,
|
||||
raw_pwrite_stream &OS_, raw_pwrite_stream &DwoOS_)
|
||||
: TargetObjectWriter(std::move(MOTW)), IsSplitDwarf(true), OS(&OS_),
|
||||
DwoOS(&DwoOS_) {}
|
||||
|
||||
private:
|
||||
void reset() override {
|
||||
@ -303,27 +321,31 @@ private:
|
||||
|
||||
void executePostLayoutBinding(MCAssembler &Asm,
|
||||
const MCAsmLayout &Layout) override;
|
||||
|
||||
void prepareImports(SmallVectorImpl<wasm::WasmImport> &Imports,
|
||||
MCAssembler &Asm, const MCAsmLayout &Layout);
|
||||
uint64_t writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) override;
|
||||
|
||||
uint64_t writeOneObject(MCAssembler &Asm, const MCAsmLayout &Layout,
|
||||
DwoMode Mode);
|
||||
|
||||
void writeString(const StringRef Str) {
|
||||
encodeULEB128(Str.size(), W.OS);
|
||||
W.OS << Str;
|
||||
encodeULEB128(Str.size(), W->OS);
|
||||
W->OS << Str;
|
||||
}
|
||||
|
||||
void writeI32(int32_t val) {
|
||||
char Buffer[4];
|
||||
support::endian::write32le(Buffer, val);
|
||||
W.OS.write(Buffer, sizeof(Buffer));
|
||||
W->OS.write(Buffer, sizeof(Buffer));
|
||||
}
|
||||
|
||||
void writeI64(int64_t val) {
|
||||
char Buffer[8];
|
||||
support::endian::write64le(Buffer, val);
|
||||
W.OS.write(Buffer, sizeof(Buffer));
|
||||
W->OS.write(Buffer, sizeof(Buffer));
|
||||
}
|
||||
|
||||
void writeValueType(wasm::ValType Ty) { W.OS << static_cast<char>(Ty); }
|
||||
void writeValueType(wasm::ValType Ty) { W->OS << static_cast<char>(Ty); }
|
||||
|
||||
void writeTypeSection(ArrayRef<WasmSignature> Signatures);
|
||||
void writeImportSection(ArrayRef<wasm::WasmImport> Imports, uint64_t DataSize,
|
||||
@ -368,17 +390,17 @@ private:
|
||||
void WasmObjectWriter::startSection(SectionBookkeeping &Section,
|
||||
unsigned SectionId) {
|
||||
LLVM_DEBUG(dbgs() << "startSection " << SectionId << "\n");
|
||||
W.OS << char(SectionId);
|
||||
W->OS << char(SectionId);
|
||||
|
||||
Section.SizeOffset = W.OS.tell();
|
||||
Section.SizeOffset = W->OS.tell();
|
||||
|
||||
// The section size. We don't know the size yet, so reserve enough space
|
||||
// for any 32-bit value; we'll patch it later.
|
||||
encodeULEB128(0, W.OS, 5);
|
||||
encodeULEB128(0, W->OS, 5);
|
||||
|
||||
// The position where the section starts, for measuring its size.
|
||||
Section.ContentsOffset = W.OS.tell();
|
||||
Section.PayloadOffset = W.OS.tell();
|
||||
Section.ContentsOffset = W->OS.tell();
|
||||
Section.PayloadOffset = W->OS.tell();
|
||||
Section.Index = SectionCount++;
|
||||
}
|
||||
|
||||
@ -388,19 +410,19 @@ void WasmObjectWriter::startCustomSection(SectionBookkeeping &Section,
|
||||
startSection(Section, wasm::WASM_SEC_CUSTOM);
|
||||
|
||||
// The position where the section header ends, for measuring its size.
|
||||
Section.PayloadOffset = W.OS.tell();
|
||||
Section.PayloadOffset = W->OS.tell();
|
||||
|
||||
// Custom sections in wasm also have a string identifier.
|
||||
writeString(Name);
|
||||
|
||||
// The position where the custom section starts.
|
||||
Section.ContentsOffset = W.OS.tell();
|
||||
Section.ContentsOffset = W->OS.tell();
|
||||
}
|
||||
|
||||
// Now that the section is complete and we know how big it is, patch up the
|
||||
// section size field at the start of the section.
|
||||
void WasmObjectWriter::endSection(SectionBookkeeping &Section) {
|
||||
uint64_t Size = W.OS.tell();
|
||||
uint64_t Size = W->OS.tell();
|
||||
// /dev/null doesn't support seek/tell and can report offset of 0.
|
||||
// Simply skip this patching in that case.
|
||||
if (!Size)
|
||||
@ -414,14 +436,14 @@ void WasmObjectWriter::endSection(SectionBookkeeping &Section) {
|
||||
|
||||
// Write the final section size to the payload_len field, which follows
|
||||
// the section id byte.
|
||||
writePatchableLEB<5>(static_cast<raw_pwrite_stream &>(W.OS), Size,
|
||||
writePatchableLEB<5>(static_cast<raw_pwrite_stream &>(W->OS), Size,
|
||||
Section.SizeOffset);
|
||||
}
|
||||
|
||||
// Emit the Wasm header.
|
||||
void WasmObjectWriter::writeHeader(const MCAssembler &Asm) {
|
||||
W.OS.write(wasm::WasmMagic, sizeof(wasm::WasmMagic));
|
||||
W.write<uint32_t>(wasm::WasmVersion);
|
||||
W->OS.write(wasm::WasmMagic, sizeof(wasm::WasmMagic));
|
||||
W->write<uint32_t>(wasm::WasmVersion);
|
||||
}
|
||||
|
||||
void WasmObjectWriter::executePostLayoutBinding(MCAssembler &Asm,
|
||||
@ -663,7 +685,7 @@ WasmObjectWriter::getRelocationIndexValue(const WasmRelocationEntry &RelEntry) {
|
||||
void WasmObjectWriter::applyRelocations(
|
||||
ArrayRef<WasmRelocationEntry> Relocations, uint64_t ContentsOffset,
|
||||
const MCAsmLayout &Layout) {
|
||||
auto &Stream = static_cast<raw_pwrite_stream &>(W.OS);
|
||||
auto &Stream = static_cast<raw_pwrite_stream &>(W->OS);
|
||||
for (const WasmRelocationEntry &RelEntry : Relocations) {
|
||||
uint64_t Offset = ContentsOffset +
|
||||
RelEntry.FixupSection->getSectionOffset() +
|
||||
@ -718,14 +740,14 @@ void WasmObjectWriter::writeTypeSection(ArrayRef<WasmSignature> Signatures) {
|
||||
SectionBookkeeping Section;
|
||||
startSection(Section, wasm::WASM_SEC_TYPE);
|
||||
|
||||
encodeULEB128(Signatures.size(), W.OS);
|
||||
encodeULEB128(Signatures.size(), W->OS);
|
||||
|
||||
for (const WasmSignature &Sig : Signatures) {
|
||||
W.OS << char(wasm::WASM_TYPE_FUNC);
|
||||
encodeULEB128(Sig.Params.size(), W.OS);
|
||||
W->OS << char(wasm::WASM_TYPE_FUNC);
|
||||
encodeULEB128(Sig.Params.size(), W->OS);
|
||||
for (wasm::ValType Ty : Sig.Params)
|
||||
writeValueType(Ty);
|
||||
encodeULEB128(Sig.Returns.size(), W.OS);
|
||||
encodeULEB128(Sig.Returns.size(), W->OS);
|
||||
for (wasm::ValType Ty : Sig.Returns)
|
||||
writeValueType(Ty);
|
||||
}
|
||||
@ -744,32 +766,32 @@ void WasmObjectWriter::writeImportSection(ArrayRef<wasm::WasmImport> Imports,
|
||||
SectionBookkeeping Section;
|
||||
startSection(Section, wasm::WASM_SEC_IMPORT);
|
||||
|
||||
encodeULEB128(Imports.size(), W.OS);
|
||||
encodeULEB128(Imports.size(), W->OS);
|
||||
for (const wasm::WasmImport &Import : Imports) {
|
||||
writeString(Import.Module);
|
||||
writeString(Import.Field);
|
||||
W.OS << char(Import.Kind);
|
||||
W->OS << char(Import.Kind);
|
||||
|
||||
switch (Import.Kind) {
|
||||
case wasm::WASM_EXTERNAL_FUNCTION:
|
||||
encodeULEB128(Import.SigIndex, W.OS);
|
||||
encodeULEB128(Import.SigIndex, W->OS);
|
||||
break;
|
||||
case wasm::WASM_EXTERNAL_GLOBAL:
|
||||
W.OS << char(Import.Global.Type);
|
||||
W.OS << char(Import.Global.Mutable ? 1 : 0);
|
||||
W->OS << char(Import.Global.Type);
|
||||
W->OS << char(Import.Global.Mutable ? 1 : 0);
|
||||
break;
|
||||
case wasm::WASM_EXTERNAL_MEMORY:
|
||||
encodeULEB128(Import.Memory.Flags, W.OS);
|
||||
encodeULEB128(NumPages, W.OS); // initial
|
||||
encodeULEB128(Import.Memory.Flags, W->OS);
|
||||
encodeULEB128(NumPages, W->OS); // initial
|
||||
break;
|
||||
case wasm::WASM_EXTERNAL_TABLE:
|
||||
W.OS << char(Import.Table.ElemType);
|
||||
encodeULEB128(0, W.OS); // flags
|
||||
encodeULEB128(NumElements, W.OS); // initial
|
||||
W->OS << char(Import.Table.ElemType);
|
||||
encodeULEB128(0, W->OS); // flags
|
||||
encodeULEB128(NumElements, W->OS); // initial
|
||||
break;
|
||||
case wasm::WASM_EXTERNAL_EVENT:
|
||||
encodeULEB128(Import.Event.Attribute, W.OS);
|
||||
encodeULEB128(Import.Event.SigIndex, W.OS);
|
||||
encodeULEB128(Import.Event.Attribute, W->OS);
|
||||
encodeULEB128(Import.Event.SigIndex, W->OS);
|
||||
break;
|
||||
default:
|
||||
llvm_unreachable("unsupported import kind");
|
||||
@ -786,9 +808,9 @@ void WasmObjectWriter::writeFunctionSection(ArrayRef<WasmFunction> Functions) {
|
||||
SectionBookkeeping Section;
|
||||
startSection(Section, wasm::WASM_SEC_FUNCTION);
|
||||
|
||||
encodeULEB128(Functions.size(), W.OS);
|
||||
encodeULEB128(Functions.size(), W->OS);
|
||||
for (const WasmFunction &Func : Functions)
|
||||
encodeULEB128(Func.SigIndex, W.OS);
|
||||
encodeULEB128(Func.SigIndex, W->OS);
|
||||
|
||||
endSection(Section);
|
||||
}
|
||||
@ -800,10 +822,10 @@ void WasmObjectWriter::writeEventSection(ArrayRef<wasm::WasmEventType> Events) {
|
||||
SectionBookkeeping Section;
|
||||
startSection(Section, wasm::WASM_SEC_EVENT);
|
||||
|
||||
encodeULEB128(Events.size(), W.OS);
|
||||
encodeULEB128(Events.size(), W->OS);
|
||||
for (const wasm::WasmEventType &Event : Events) {
|
||||
encodeULEB128(Event.Attribute, W.OS);
|
||||
encodeULEB128(Event.SigIndex, W.OS);
|
||||
encodeULEB128(Event.Attribute, W->OS);
|
||||
encodeULEB128(Event.SigIndex, W->OS);
|
||||
}
|
||||
|
||||
endSection(Section);
|
||||
@ -816,17 +838,17 @@ void WasmObjectWriter::writeGlobalSection(ArrayRef<wasm::WasmGlobal> Globals) {
|
||||
SectionBookkeeping Section;
|
||||
startSection(Section, wasm::WASM_SEC_GLOBAL);
|
||||
|
||||
encodeULEB128(Globals.size(), W.OS);
|
||||
encodeULEB128(Globals.size(), W->OS);
|
||||
for (const wasm::WasmGlobal &Global : Globals) {
|
||||
encodeULEB128(Global.Type.Type, W.OS);
|
||||
W.OS << char(Global.Type.Mutable);
|
||||
W.OS << char(Global.InitExpr.Opcode);
|
||||
encodeULEB128(Global.Type.Type, W->OS);
|
||||
W->OS << char(Global.Type.Mutable);
|
||||
W->OS << char(Global.InitExpr.Opcode);
|
||||
switch (Global.Type.Type) {
|
||||
case wasm::WASM_TYPE_I32:
|
||||
encodeSLEB128(0, W.OS);
|
||||
encodeSLEB128(0, W->OS);
|
||||
break;
|
||||
case wasm::WASM_TYPE_I64:
|
||||
encodeSLEB128(0, W.OS);
|
||||
encodeSLEB128(0, W->OS);
|
||||
break;
|
||||
case wasm::WASM_TYPE_F32:
|
||||
writeI32(0);
|
||||
@ -840,7 +862,7 @@ void WasmObjectWriter::writeGlobalSection(ArrayRef<wasm::WasmGlobal> Globals) {
|
||||
default:
|
||||
llvm_unreachable("unexpected type");
|
||||
}
|
||||
W.OS << char(wasm::WASM_OPCODE_END);
|
||||
W->OS << char(wasm::WASM_OPCODE_END);
|
||||
}
|
||||
|
||||
endSection(Section);
|
||||
@ -853,11 +875,11 @@ void WasmObjectWriter::writeExportSection(ArrayRef<wasm::WasmExport> Exports) {
|
||||
SectionBookkeeping Section;
|
||||
startSection(Section, wasm::WASM_SEC_EXPORT);
|
||||
|
||||
encodeULEB128(Exports.size(), W.OS);
|
||||
encodeULEB128(Exports.size(), W->OS);
|
||||
for (const wasm::WasmExport &Export : Exports) {
|
||||
writeString(Export.Name);
|
||||
W.OS << char(Export.Kind);
|
||||
encodeULEB128(Export.Index, W.OS);
|
||||
W->OS << char(Export.Kind);
|
||||
encodeULEB128(Export.Index, W->OS);
|
||||
}
|
||||
|
||||
endSection(Section);
|
||||
@ -870,17 +892,17 @@ void WasmObjectWriter::writeElemSection(ArrayRef<uint32_t> TableElems) {
|
||||
SectionBookkeeping Section;
|
||||
startSection(Section, wasm::WASM_SEC_ELEM);
|
||||
|
||||
encodeULEB128(1, W.OS); // number of "segments"
|
||||
encodeULEB128(0, W.OS); // the table index
|
||||
encodeULEB128(1, W->OS); // number of "segments"
|
||||
encodeULEB128(0, W->OS); // the table index
|
||||
|
||||
// init expr for starting offset
|
||||
W.OS << char(wasm::WASM_OPCODE_I32_CONST);
|
||||
encodeSLEB128(InitialTableOffset, W.OS);
|
||||
W.OS << char(wasm::WASM_OPCODE_END);
|
||||
W->OS << char(wasm::WASM_OPCODE_I32_CONST);
|
||||
encodeSLEB128(InitialTableOffset, W->OS);
|
||||
W->OS << char(wasm::WASM_OPCODE_END);
|
||||
|
||||
encodeULEB128(TableElems.size(), W.OS);
|
||||
encodeULEB128(TableElems.size(), W->OS);
|
||||
for (uint32_t Elem : TableElems)
|
||||
encodeULEB128(Elem, W.OS);
|
||||
encodeULEB128(Elem, W->OS);
|
||||
|
||||
endSection(Section);
|
||||
}
|
||||
@ -891,7 +913,7 @@ void WasmObjectWriter::writeDataCountSection() {
|
||||
|
||||
SectionBookkeeping Section;
|
||||
startSection(Section, wasm::WASM_SEC_DATACOUNT);
|
||||
encodeULEB128(DataSegments.size(), W.OS);
|
||||
encodeULEB128(DataSegments.size(), W->OS);
|
||||
endSection(Section);
|
||||
}
|
||||
|
||||
@ -904,7 +926,7 @@ uint32_t WasmObjectWriter::writeCodeSection(const MCAssembler &Asm,
|
||||
SectionBookkeeping Section;
|
||||
startSection(Section, wasm::WASM_SEC_CODE);
|
||||
|
||||
encodeULEB128(Functions.size(), W.OS);
|
||||
encodeULEB128(Functions.size(), W->OS);
|
||||
|
||||
for (const WasmFunction &Func : Functions) {
|
||||
auto &FuncSection = static_cast<MCSectionWasm &>(Func.Sym->getSection());
|
||||
@ -913,9 +935,9 @@ uint32_t WasmObjectWriter::writeCodeSection(const MCAssembler &Asm,
|
||||
if (!Func.Sym->getSize()->evaluateAsAbsolute(Size, Layout))
|
||||
report_fatal_error(".size expression must be evaluatable");
|
||||
|
||||
encodeULEB128(Size, W.OS);
|
||||
FuncSection.setSectionOffset(W.OS.tell() - Section.ContentsOffset);
|
||||
Asm.writeSectionData(W.OS, &FuncSection, Layout);
|
||||
encodeULEB128(Size, W->OS);
|
||||
FuncSection.setSectionOffset(W->OS.tell() - Section.ContentsOffset);
|
||||
Asm.writeSectionData(W->OS, &FuncSection, Layout);
|
||||
}
|
||||
|
||||
// Apply fixups.
|
||||
@ -932,21 +954,21 @@ uint32_t WasmObjectWriter::writeDataSection(const MCAsmLayout &Layout) {
|
||||
SectionBookkeeping Section;
|
||||
startSection(Section, wasm::WASM_SEC_DATA);
|
||||
|
||||
encodeULEB128(DataSegments.size(), W.OS); // count
|
||||
encodeULEB128(DataSegments.size(), W->OS); // count
|
||||
|
||||
for (const WasmDataSegment &Segment : DataSegments) {
|
||||
encodeULEB128(Segment.InitFlags, W.OS); // flags
|
||||
encodeULEB128(Segment.InitFlags, W->OS); // flags
|
||||
if (Segment.InitFlags & wasm::WASM_SEGMENT_HAS_MEMINDEX)
|
||||
encodeULEB128(0, W.OS); // memory index
|
||||
encodeULEB128(0, W->OS); // memory index
|
||||
if ((Segment.InitFlags & wasm::WASM_SEGMENT_IS_PASSIVE) == 0) {
|
||||
W.OS << char(Segment.Offset > INT32_MAX ? wasm::WASM_OPCODE_I64_CONST
|
||||
: wasm::WASM_OPCODE_I32_CONST);
|
||||
encodeSLEB128(Segment.Offset, W.OS); // offset
|
||||
W.OS << char(wasm::WASM_OPCODE_END);
|
||||
W->OS << char(Segment.Offset > INT32_MAX ? wasm::WASM_OPCODE_I64_CONST
|
||||
: wasm::WASM_OPCODE_I32_CONST);
|
||||
encodeSLEB128(Segment.Offset, W->OS); // offset
|
||||
W->OS << char(wasm::WASM_OPCODE_END);
|
||||
}
|
||||
encodeULEB128(Segment.Data.size(), W.OS); // size
|
||||
Segment.Section->setSectionOffset(W.OS.tell() - Section.ContentsOffset);
|
||||
W.OS << Segment.Data; // data
|
||||
encodeULEB128(Segment.Data.size(), W->OS); // size
|
||||
Segment.Section->setSectionOffset(W->OS.tell() - Section.ContentsOffset);
|
||||
W->OS << Segment.Data; // data
|
||||
}
|
||||
|
||||
// Apply fixups.
|
||||
@ -979,18 +1001,18 @@ void WasmObjectWriter::writeRelocSection(
|
||||
SectionBookkeeping Section;
|
||||
startCustomSection(Section, std::string("reloc.") + Name.str());
|
||||
|
||||
encodeULEB128(SectionIndex, W.OS);
|
||||
encodeULEB128(Relocs.size(), W.OS);
|
||||
encodeULEB128(SectionIndex, W->OS);
|
||||
encodeULEB128(Relocs.size(), W->OS);
|
||||
for (const WasmRelocationEntry &RelEntry : Relocs) {
|
||||
uint64_t Offset =
|
||||
RelEntry.Offset + RelEntry.FixupSection->getSectionOffset();
|
||||
uint32_t Index = getRelocationIndexValue(RelEntry);
|
||||
|
||||
W.OS << char(RelEntry.Type);
|
||||
encodeULEB128(Offset, W.OS);
|
||||
encodeULEB128(Index, W.OS);
|
||||
W->OS << char(RelEntry.Type);
|
||||
encodeULEB128(Offset, W->OS);
|
||||
encodeULEB128(Index, W->OS);
|
||||
if (RelEntry.hasAddend())
|
||||
encodeSLEB128(RelEntry.Addend, W.OS);
|
||||
encodeSLEB128(RelEntry.Addend, W->OS);
|
||||
}
|
||||
|
||||
endSection(Section);
|
||||
@ -1009,20 +1031,20 @@ void WasmObjectWriter::writeLinkingMetaDataSection(
|
||||
const std::map<StringRef, std::vector<WasmComdatEntry>> &Comdats) {
|
||||
SectionBookkeeping Section;
|
||||
startCustomSection(Section, "linking");
|
||||
encodeULEB128(wasm::WasmMetadataVersion, W.OS);
|
||||
encodeULEB128(wasm::WasmMetadataVersion, W->OS);
|
||||
|
||||
SectionBookkeeping SubSection;
|
||||
if (SymbolInfos.size() != 0) {
|
||||
startSection(SubSection, wasm::WASM_SYMBOL_TABLE);
|
||||
encodeULEB128(SymbolInfos.size(), W.OS);
|
||||
encodeULEB128(SymbolInfos.size(), W->OS);
|
||||
for (const wasm::WasmSymbolInfo &Sym : SymbolInfos) {
|
||||
encodeULEB128(Sym.Kind, W.OS);
|
||||
encodeULEB128(Sym.Flags, W.OS);
|
||||
encodeULEB128(Sym.Kind, W->OS);
|
||||
encodeULEB128(Sym.Flags, W->OS);
|
||||
switch (Sym.Kind) {
|
||||
case wasm::WASM_SYMBOL_TYPE_FUNCTION:
|
||||
case wasm::WASM_SYMBOL_TYPE_GLOBAL:
|
||||
case wasm::WASM_SYMBOL_TYPE_EVENT:
|
||||
encodeULEB128(Sym.ElementIndex, W.OS);
|
||||
encodeULEB128(Sym.ElementIndex, W->OS);
|
||||
if ((Sym.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0 ||
|
||||
(Sym.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0)
|
||||
writeString(Sym.Name);
|
||||
@ -1030,15 +1052,15 @@ void WasmObjectWriter::writeLinkingMetaDataSection(
|
||||
case wasm::WASM_SYMBOL_TYPE_DATA:
|
||||
writeString(Sym.Name);
|
||||
if ((Sym.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0) {
|
||||
encodeULEB128(Sym.DataRef.Segment, W.OS);
|
||||
encodeULEB128(Sym.DataRef.Offset, W.OS);
|
||||
encodeULEB128(Sym.DataRef.Size, W.OS);
|
||||
encodeULEB128(Sym.DataRef.Segment, W->OS);
|
||||
encodeULEB128(Sym.DataRef.Offset, W->OS);
|
||||
encodeULEB128(Sym.DataRef.Size, W->OS);
|
||||
}
|
||||
break;
|
||||
case wasm::WASM_SYMBOL_TYPE_SECTION: {
|
||||
const uint32_t SectionIndex =
|
||||
CustomSections[Sym.ElementIndex].OutputIndex;
|
||||
encodeULEB128(SectionIndex, W.OS);
|
||||
encodeULEB128(SectionIndex, W->OS);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@ -1050,35 +1072,35 @@ void WasmObjectWriter::writeLinkingMetaDataSection(
|
||||
|
||||
if (DataSegments.size()) {
|
||||
startSection(SubSection, wasm::WASM_SEGMENT_INFO);
|
||||
encodeULEB128(DataSegments.size(), W.OS);
|
||||
encodeULEB128(DataSegments.size(), W->OS);
|
||||
for (const WasmDataSegment &Segment : DataSegments) {
|
||||
writeString(Segment.Name);
|
||||
encodeULEB128(Segment.Alignment, W.OS);
|
||||
encodeULEB128(Segment.LinkerFlags, W.OS);
|
||||
encodeULEB128(Segment.Alignment, W->OS);
|
||||
encodeULEB128(Segment.LinkerFlags, W->OS);
|
||||
}
|
||||
endSection(SubSection);
|
||||
}
|
||||
|
||||
if (!InitFuncs.empty()) {
|
||||
startSection(SubSection, wasm::WASM_INIT_FUNCS);
|
||||
encodeULEB128(InitFuncs.size(), W.OS);
|
||||
encodeULEB128(InitFuncs.size(), W->OS);
|
||||
for (auto &StartFunc : InitFuncs) {
|
||||
encodeULEB128(StartFunc.first, W.OS); // priority
|
||||
encodeULEB128(StartFunc.second, W.OS); // function index
|
||||
encodeULEB128(StartFunc.first, W->OS); // priority
|
||||
encodeULEB128(StartFunc.second, W->OS); // function index
|
||||
}
|
||||
endSection(SubSection);
|
||||
}
|
||||
|
||||
if (Comdats.size()) {
|
||||
startSection(SubSection, wasm::WASM_COMDAT_INFO);
|
||||
encodeULEB128(Comdats.size(), W.OS);
|
||||
encodeULEB128(Comdats.size(), W->OS);
|
||||
for (const auto &C : Comdats) {
|
||||
writeString(C.first);
|
||||
encodeULEB128(0, W.OS); // flags for future use
|
||||
encodeULEB128(C.second.size(), W.OS);
|
||||
encodeULEB128(0, W->OS); // flags for future use
|
||||
encodeULEB128(C.second.size(), W->OS);
|
||||
for (const WasmComdatEntry &Entry : C.second) {
|
||||
encodeULEB128(Entry.Kind, W.OS);
|
||||
encodeULEB128(Entry.Index, W.OS);
|
||||
encodeULEB128(Entry.Kind, W->OS);
|
||||
encodeULEB128(Entry.Index, W->OS);
|
||||
}
|
||||
}
|
||||
endSection(SubSection);
|
||||
@ -1094,8 +1116,8 @@ void WasmObjectWriter::writeCustomSection(WasmCustomSection &CustomSection,
|
||||
auto *Sec = CustomSection.Section;
|
||||
startCustomSection(Section, CustomSection.Name);
|
||||
|
||||
Sec->setSectionOffset(W.OS.tell() - Section.ContentsOffset);
|
||||
Asm.writeSectionData(W.OS, Sec, Layout);
|
||||
Sec->setSectionOffset(W->OS.tell() - Section.ContentsOffset);
|
||||
Asm.writeSectionData(W->OS, Sec, Layout);
|
||||
|
||||
CustomSection.OutputContentsOffset = Section.ContentsOffset;
|
||||
CustomSection.OutputIndex = Section.Index;
|
||||
@ -1175,25 +1197,9 @@ static bool isInSymtab(const MCSymbolWasm &Sym) {
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm,
|
||||
const MCAsmLayout &Layout) {
|
||||
uint64_t StartOffset = W.OS.tell();
|
||||
|
||||
LLVM_DEBUG(dbgs() << "WasmObjectWriter::writeObject\n");
|
||||
|
||||
// Collect information from the available symbols.
|
||||
SmallVector<WasmFunction, 4> Functions;
|
||||
SmallVector<uint32_t, 4> TableElems;
|
||||
SmallVector<wasm::WasmImport, 4> Imports;
|
||||
SmallVector<wasm::WasmExport, 4> Exports;
|
||||
SmallVector<wasm::WasmEventType, 1> Events;
|
||||
SmallVector<wasm::WasmGlobal, 1> Globals;
|
||||
SmallVector<wasm::WasmSymbolInfo, 4> SymbolInfos;
|
||||
SmallVector<std::pair<uint16_t, uint32_t>, 2> InitFuncs;
|
||||
std::map<StringRef, std::vector<WasmComdatEntry>> Comdats;
|
||||
uint64_t DataSize = 0;
|
||||
|
||||
void WasmObjectWriter::prepareImports(
|
||||
SmallVectorImpl<wasm::WasmImport> &Imports, MCAssembler &Asm,
|
||||
const MCAsmLayout &Layout) {
|
||||
// For now, always emit the memory import, since loads and stores are not
|
||||
// valid without it. In the future, we could perhaps be more clever and omit
|
||||
// it if there are no loads or stores.
|
||||
@ -1291,13 +1297,57 @@ uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm,
|
||||
GOTIndices[&WS] = NumGlobalImports++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm,
|
||||
const MCAsmLayout &Layout) {
|
||||
support::endian::Writer MainWriter(*OS, support::little);
|
||||
W = &MainWriter;
|
||||
if (IsSplitDwarf) {
|
||||
uint64_t TotalSize = writeOneObject(Asm, Layout, DwoMode::NonDwoOnly);
|
||||
assert(DwoOS);
|
||||
support::endian::Writer DwoWriter(*DwoOS, support::little);
|
||||
W = &DwoWriter;
|
||||
return TotalSize + writeOneObject(Asm, Layout, DwoMode::DwoOnly);
|
||||
} else {
|
||||
return writeOneObject(Asm, Layout, DwoMode::AllSections);
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t WasmObjectWriter::writeOneObject(MCAssembler &Asm,
|
||||
const MCAsmLayout &Layout,
|
||||
DwoMode Mode) {
|
||||
uint64_t StartOffset = W->OS.tell();
|
||||
SectionCount = 0;
|
||||
CustomSections.clear();
|
||||
|
||||
LLVM_DEBUG(dbgs() << "WasmObjectWriter::writeObject\n");
|
||||
|
||||
// Collect information from the available symbols.
|
||||
SmallVector<WasmFunction, 4> Functions;
|
||||
SmallVector<uint32_t, 4> TableElems;
|
||||
SmallVector<wasm::WasmImport, 4> Imports;
|
||||
SmallVector<wasm::WasmExport, 4> Exports;
|
||||
SmallVector<wasm::WasmEventType, 1> Events;
|
||||
SmallVector<wasm::WasmGlobal, 1> Globals;
|
||||
SmallVector<wasm::WasmSymbolInfo, 4> SymbolInfos;
|
||||
SmallVector<std::pair<uint16_t, uint32_t>, 2> InitFuncs;
|
||||
std::map<StringRef, std::vector<WasmComdatEntry>> Comdats;
|
||||
uint64_t DataSize = 0;
|
||||
if (Mode != DwoMode::DwoOnly) {
|
||||
prepareImports(Imports, Asm, Layout);
|
||||
}
|
||||
// Populate DataSegments and CustomSections, which must be done before
|
||||
// populating DataLocations.
|
||||
for (MCSection &Sec : Asm) {
|
||||
auto &Section = static_cast<MCSectionWasm &>(Sec);
|
||||
StringRef SectionName = Section.getName();
|
||||
|
||||
if (Mode == DwoMode::NonDwoOnly && isDwoSection(Sec))
|
||||
continue;
|
||||
if (Mode == DwoMode::DwoOnly && !isDwoSection(Sec))
|
||||
continue;
|
||||
|
||||
// .init_array sections are handled specially elsewhere.
|
||||
if (SectionName.startswith(".init_array"))
|
||||
continue;
|
||||
@ -1694,23 +1744,33 @@ uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm,
|
||||
// Write out the Wasm header.
|
||||
writeHeader(Asm);
|
||||
|
||||
writeTypeSection(Signatures);
|
||||
writeImportSection(Imports, DataSize, TableElems.size());
|
||||
writeFunctionSection(Functions);
|
||||
// Skip the "table" section; we import the table instead.
|
||||
// Skip the "memory" section; we import the memory instead.
|
||||
writeEventSection(Events);
|
||||
writeGlobalSection(Globals);
|
||||
writeExportSection(Exports);
|
||||
writeElemSection(TableElems);
|
||||
writeDataCountSection();
|
||||
uint32_t CodeSectionIndex = writeCodeSection(Asm, Layout, Functions);
|
||||
uint32_t DataSectionIndex = writeDataSection(Layout);
|
||||
for (auto &CustomSection : CustomSections)
|
||||
uint32_t CodeSectionIndex, DataSectionIndex;
|
||||
if (Mode != DwoMode::DwoOnly) {
|
||||
writeTypeSection(Signatures);
|
||||
writeImportSection(Imports, DataSize, TableElems.size());
|
||||
writeFunctionSection(Functions);
|
||||
// Skip the "table" section; we import the table instead.
|
||||
// Skip the "memory" section; we import the memory instead.
|
||||
writeEventSection(Events);
|
||||
writeGlobalSection(Globals);
|
||||
writeExportSection(Exports);
|
||||
writeElemSection(TableElems);
|
||||
writeDataCountSection();
|
||||
|
||||
CodeSectionIndex = writeCodeSection(Asm, Layout, Functions);
|
||||
DataSectionIndex = writeDataSection(Layout);
|
||||
}
|
||||
|
||||
for (auto &CustomSection : CustomSections) {
|
||||
writeCustomSection(CustomSection, Asm, Layout);
|
||||
writeLinkingMetaDataSection(SymbolInfos, InitFuncs, Comdats);
|
||||
writeRelocSection(CodeSectionIndex, "CODE", CodeRelocations);
|
||||
writeRelocSection(DataSectionIndex, "DATA", DataRelocations);
|
||||
}
|
||||
|
||||
if (Mode != DwoMode::DwoOnly) {
|
||||
writeLinkingMetaDataSection(SymbolInfos, InitFuncs, Comdats);
|
||||
|
||||
writeRelocSection(CodeSectionIndex, "CODE", CodeRelocations);
|
||||
writeRelocSection(DataSectionIndex, "DATA", DataRelocations);
|
||||
}
|
||||
writeCustomRelocSections();
|
||||
if (ProducersSection)
|
||||
writeCustomSection(*ProducersSection, Asm, Layout);
|
||||
@ -1718,7 +1778,7 @@ uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm,
|
||||
writeCustomSection(*TargetFeaturesSection, Asm, Layout);
|
||||
|
||||
// TODO: Translate the .comment section to the output.
|
||||
return W.OS.tell() - StartOffset;
|
||||
return W->OS.tell() - StartOffset;
|
||||
}
|
||||
|
||||
std::unique_ptr<MCObjectWriter>
|
||||
@ -1726,3 +1786,10 @@ llvm::createWasmObjectWriter(std::unique_ptr<MCWasmObjectTargetWriter> MOTW,
|
||||
raw_pwrite_stream &OS) {
|
||||
return std::make_unique<WasmObjectWriter>(std::move(MOTW), OS);
|
||||
}
|
||||
|
||||
std::unique_ptr<MCObjectWriter>
|
||||
llvm::createWasmDwoObjectWriter(std::unique_ptr<MCWasmObjectTargetWriter> MOTW,
|
||||
raw_pwrite_stream &OS,
|
||||
raw_pwrite_stream &DwoOS) {
|
||||
return std::make_unique<WasmObjectWriter>(std::move(MOTW), OS, DwoOS);
|
||||
}
|
||||
|
121
test/DebugInfo/WebAssembly/fission-cu.ll
Normal file
121
test/DebugInfo/WebAssembly/fission-cu.ll
Normal file
@ -0,0 +1,121 @@
|
||||
; RUN: llc -split-dwarf-file=baz.dwo -O0 %s -mtriple=wasm32-unknown-unknown -filetype=obj -o %t
|
||||
; RUN: llvm-dwarfdump -v -all %t | FileCheck %s
|
||||
; RUN: llvm-readobj --relocations %t | FileCheck --check-prefix=OBJ %s
|
||||
; RUN: llvm-objdump -h %t | FileCheck --check-prefix=HDR %s
|
||||
|
||||
; This test is derived from test/DebugInfo/X86/fission-cu.ll
|
||||
|
||||
source_filename = "test/DebugInfo/WebAssembly/fission-cu.ll"
|
||||
|
||||
@a = global i32 0, align 4, !dbg !0
|
||||
|
||||
!llvm.dbg.cu = !{!4}
|
||||
!llvm.module.flags = !{!7}
|
||||
|
||||
!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
|
||||
!1 = !DIGlobalVariable(name: "a", scope: null, file: !2, line: 1, type: !3, isLocal: false, isDefinition: true)
|
||||
!2 = !DIFile(filename: "baz.c", directory: "/usr/local/google/home/echristo/tmp")
|
||||
!3 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed)
|
||||
!4 = distinct !DICompileUnit(language: DW_LANG_C99, file: !2, producer: "clang version 3.3 (trunk 169021) (llvm/trunk 169020)", isOptimized: false, runtimeVersion: 0, splitDebugFilename: "baz.dwo", emissionKind: FullDebug, enums: !5, retainedTypes: !5, globals: !6, imports: !5)
|
||||
!5 = !{}
|
||||
; Check that the skeleton compile unit contains the proper attributes:
|
||||
; This DIE has the following attributes: DW_AT_comp_dir, DW_AT_stmt_list,
|
||||
; DW_AT_low_pc, DW_AT_high_pc, DW_AT_ranges, DW_AT_dwo_name, DW_AT_dwo_id,
|
||||
; DW_AT_ranges_base, DW_AT_addr_base.
|
||||
|
||||
; CHECK: .debug_abbrev contents:
|
||||
; CHECK: Abbrev table for offset: 0x00000000
|
||||
; CHECK: [1] DW_TAG_compile_unit DW_CHILDREN_no
|
||||
; CHECK: DW_AT_stmt_list DW_FORM_sec_offset
|
||||
; CHECK: DW_AT_comp_dir DW_FORM_strp
|
||||
; CHECK: DW_AT_GNU_dwo_name DW_FORM_strp
|
||||
; CHECK: DW_AT_GNU_dwo_id DW_FORM_data8
|
||||
|
||||
; Check that we're using the right forms.
|
||||
; CHECK: .debug_abbrev.dwo contents:
|
||||
; CHECK: Abbrev table for offset: 0x00000000
|
||||
; CHECK: [1] DW_TAG_compile_unit DW_CHILDREN_yes
|
||||
; CHECK: DW_AT_producer DW_FORM_GNU_str_index
|
||||
; CHECK: DW_AT_language DW_FORM_data2
|
||||
; CHECK: DW_AT_name DW_FORM_GNU_str_index
|
||||
; CHECK: DW_AT_GNU_dwo_name DW_FORM_GNU_str_index
|
||||
; CHECK-NOT: DW_AT_low_pc
|
||||
; CHECK-NOT: DW_AT_stmt_list
|
||||
; CHECK-NOT: DW_AT_comp_dir
|
||||
; CHECK: DW_AT_GNU_dwo_id DW_FORM_data8
|
||||
|
||||
; CHECK: [2] DW_TAG_variable DW_CHILDREN_no
|
||||
; CHECK: DW_AT_name DW_FORM_GNU_str_index
|
||||
; CHECK: DW_AT_type DW_FORM_ref4
|
||||
; CHECK: DW_AT_external DW_FORM_flag_present
|
||||
; CHECK: DW_AT_decl_file DW_FORM_data1
|
||||
; CHECK: DW_AT_decl_line DW_FORM_data1
|
||||
; CHECK: DW_AT_location DW_FORM_exprloc
|
||||
|
||||
; CHECK: [3] DW_TAG_base_type DW_CHILDREN_no
|
||||
; CHECK: DW_AT_name DW_FORM_GNU_str_index
|
||||
; CHECK: DW_AT_encoding DW_FORM_data1
|
||||
; CHECK: DW_AT_byte_size DW_FORM_data1
|
||||
|
||||
; CHECK: .debug_info contents:
|
||||
; CHECK: DW_TAG_compile_unit
|
||||
; CHECK-NEXT: DW_AT_stmt_list [DW_FORM_sec_offset] (0x00000000)
|
||||
; CHECK-NEXT: DW_AT_comp_dir [DW_FORM_strp] ( .debug_str[0x00000000] = "/usr/local/google/home/echristo/tmp")
|
||||
; CHECK-NEXT: DW_AT_GNU_dwo_name [DW_FORM_strp] ( .debug_str[0x00000024] = "baz.dwo")
|
||||
; CHECK-NEXT: DW_AT_GNU_dwo_id [DW_FORM_data8] (0x1f1f859683d49324)
|
||||
|
||||
; Check that the rest of the compile units have information.
|
||||
; CHECK: .debug_info.dwo contents:
|
||||
; CHECK: DW_TAG_compile_unit
|
||||
; CHECK: DW_AT_producer [DW_FORM_GNU_str_index] (indexed (00000002) string = "clang version 3.3 (trunk 169021) (llvm/trunk 169020)")
|
||||
; CHECK: DW_AT_language [DW_FORM_data2] (DW_LANG_C99)
|
||||
; CHECK: DW_AT_name [DW_FORM_GNU_str_index] (indexed (00000003) string = "baz.c")
|
||||
; CHECK: DW_AT_GNU_dwo_name [DW_FORM_GNU_str_index] (indexed (00000004) string = "baz.dwo")
|
||||
; CHECK-NOT: DW_AT_low_pc
|
||||
; CHECK-NOT: DW_AT_stmt_list
|
||||
; CHECK-NOT: DW_AT_comp_dir
|
||||
; CHECK: DW_AT_GNU_dwo_id [DW_FORM_data8] (0x1f1f859683d49324)
|
||||
; CHECK: DW_TAG_variable
|
||||
; CHECK: DW_AT_name [DW_FORM_GNU_str_index] (indexed (00000000) string = "a")
|
||||
; CHECK: DW_AT_type [DW_FORM_ref4] (cu + 0x{{[0-9a-f]*}} => {[[TYPE:0x[0-9a-f]*]]}
|
||||
; CHECK: DW_AT_external [DW_FORM_flag_present] (true)
|
||||
; CHECK: DW_AT_decl_file [DW_FORM_data1] (0x01)
|
||||
; CHECK: DW_AT_decl_line [DW_FORM_data1] (1)
|
||||
; CHECK: DW_AT_location [DW_FORM_exprloc] (DW_OP_GNU_addr_index 0x0)
|
||||
; CHECK: [[TYPE]]: DW_TAG_base_type
|
||||
; CHECK: DW_AT_name [DW_FORM_GNU_str_index] (indexed (00000001) string = "int")
|
||||
|
||||
; CHECK: .debug_str contents:
|
||||
; CHECK: 0x00000000: "/usr/local/google/home/echristo/tmp"
|
||||
; CHECK: 0x00000024: "baz.dwo"
|
||||
|
||||
; CHECK: .debug_str.dwo contents:
|
||||
; CHECK: 0x00000000: "a"
|
||||
; CHECK: 0x00000002: "int"
|
||||
; CHECK: 0x00000006: "clang version 3.3 (trunk 169021) (llvm/trunk 169020)"
|
||||
; CHECK: 0x0000003b: "baz.c"
|
||||
; CHECK: 0x00000041: "baz.dwo"
|
||||
|
||||
; CHECK: .debug_str_offsets.dwo contents:
|
||||
; CHECK: 0x00000000: 00000000
|
||||
; CHECK: 0x00000004: 00000002
|
||||
; CHECK: 0x00000008: 00000006
|
||||
; CHECK: 0x0000000c: 0000003b
|
||||
; CHECK: 0x00000010: 00000041
|
||||
|
||||
; Object file checks
|
||||
; For wasm we should have this set of relocations for the debug info section
|
||||
;
|
||||
; OBJ: .debug_info
|
||||
; OBJ-NEXT: R_WASM_SECTION_OFFSET_I32 .debug_abbrev 0
|
||||
; OBJ-NEXT: R_WASM_SECTION_OFFSET_I32 .debug_line 0
|
||||
; OBJ-NEXT: R_WASM_SECTION_OFFSET_I32 .debug_str 0
|
||||
; OBJ-NEXT: R_WASM_SECTION_OFFSET_I32 .debug_str 36
|
||||
; OBJ-NEXT: R_WASM_SECTION_OFFSET_I32 .debug_addr 0
|
||||
; OBJ-NEXT: }
|
||||
|
||||
; HDR-NOT: .debug_aranges
|
||||
; HDR-NOT: .rela.{{.*}}.dwo
|
||||
|
||||
!6 = !{!0}
|
||||
!7 = !{i32 1, !"Debug Info Version", i32 3}
|
48
test/DebugInfo/WebAssembly/fission-sections.ll
Normal file
48
test/DebugInfo/WebAssembly/fission-sections.ll
Normal file
@ -0,0 +1,48 @@
|
||||
; RUN: llc -split-dwarf-file=baz.dwo -split-dwarf-output=%t.dwo -O0 %s -mtriple=wasm32-unknown-unknown -filetype=obj -o %t
|
||||
; RUN: llvm-objdump -h %t | FileCheck --check-prefix=OBJ %s
|
||||
; RUN: llvm-objdump -h %t.dwo | FileCheck --check-prefix=DWO %s
|
||||
|
||||
|
||||
; This test is derived from test/DebugInfo/X86/fission-cu.ll
|
||||
; But it checks that the output objects have the expected sections
|
||||
|
||||
source_filename = "test/DebugInfo/WebAssembly/fission-cu.ll"
|
||||
|
||||
@a = global i32 0, align 4, !dbg !0
|
||||
|
||||
!llvm.dbg.cu = !{!4}
|
||||
!llvm.module.flags = !{!7}
|
||||
|
||||
!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
|
||||
!1 = !DIGlobalVariable(name: "a", scope: null, file: !2, line: 1, type: !3, isLocal: false, isDefinition: true)
|
||||
!2 = !DIFile(filename: "baz.c", directory: "/usr/local/google/home/echristo/tmp")
|
||||
!3 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed)
|
||||
!4 = distinct !DICompileUnit(language: DW_LANG_C99, file: !2, producer: "clang version 3.3 (trunk 169021) (llvm/trunk 169020)", isOptimized: false, runtimeVersion: 0, splitDebugFilename: "baz.dwo", emissionKind: FullDebug, enums: !5, retainedTypes: !5, globals: !6, imports: !5)
|
||||
!5 = !{}
|
||||
!6 = !{!0}
|
||||
!7 = !{i32 1, !"Debug Info Version", i32 3}
|
||||
|
||||
; CHECK-LABEL: Sections:
|
||||
|
||||
; OBJ: Idx Name
|
||||
; OBJ-NEXT: 0 IMPORT
|
||||
; OBJ-NEXT: DATACOUNT
|
||||
; OBJ-NEXT: DATA
|
||||
; OBJ-NEXT: .debug_abbrev
|
||||
; OBJ-NEXT: .debug_info
|
||||
; OBJ-NEXT: .debug_str
|
||||
; OBJ-NEXT: .debug_addr
|
||||
; OBJ-NEXT: .debug_pubnames
|
||||
; OBJ-NEXT: .debug_pubtypes
|
||||
; OBJ-NEXT: .debug_line
|
||||
; OBJ-NEXT: linking
|
||||
|
||||
|
||||
; DWO: Idx Name
|
||||
; DWO-NOT: IMPORT
|
||||
; DWO-NOT: DATA
|
||||
; DWO: 0 .debug_str.dwo
|
||||
; DWO-NEXT: .debug_str_offsets.dwo
|
||||
; DWO-NEXT: .debug_info.dwo
|
||||
; DWO-NEXT: .debug_abbrev.dwo
|
||||
; DWO-NEXT: producers
|
Loading…
Reference in New Issue
Block a user