1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-26 04:32:44 +01:00

[WebAssembly] Add COMDAT support

This adds COMDAT support to the Wasm object-file format.
Spec: https://github.com/WebAssembly/tool-conventions/pull/31

Corresponding LLD change:
https://bugs.llvm.org/show_bug.cgi?id=35533, and D40845

Patch by Nicholas Wilson

Differential Revision: https://reviews.llvm.org/D40844

llvm-svn: 322135
This commit is contained in:
Sam Clegg 2018-01-09 23:43:14 +00:00
parent bfc554dace
commit 9c22504bad
13 changed files with 326 additions and 32 deletions

View File

@ -883,8 +883,8 @@ The selection kind must be one of the following:
The linker may choose any COMDAT key but the sections must contain the
same amount of data.
Note that the Mach-O platform doesn't support COMDATs and ELF only supports
``any`` as a selection kind.
Note that the Mach-O platform doesn't support COMDATs, and ELF and WebAssembly
only support ``any`` as a selection kind.
Here is an example of a COMDAT group where a function will only be selected if
the COMDAT key's section is the largest:

View File

@ -660,9 +660,9 @@ public:
return getArch() == Triple::aarch64 || getArch() == Triple::aarch64_be;
}
/// Tests wether the target supports comdat
/// Tests whether the target supports comdat
bool supportsCOMDAT() const {
return !isOSBinFormatMachO() && !isOSBinFormatWasm();
return !isOSBinFormatMachO();
}
/// @}

View File

@ -95,6 +95,7 @@ struct WasmFunction {
ArrayRef<uint8_t> Body;
uint32_t CodeSectionOffset;
uint32_t Size;
StringRef Comdat;
};
struct WasmDataSegment {
@ -104,6 +105,7 @@ struct WasmDataSegment {
StringRef Name;
uint32_t Alignment;
uint32_t Flags;
StringRef Comdat;
};
struct WasmElemSegment {
@ -173,11 +175,6 @@ enum : unsigned {
WASM_OPCODE_F64_CONST = 0x44,
};
enum : unsigned {
WASM_NAMES_FUNCTION = 0x1,
WASM_NAMES_LOCAL = 0x2,
};
enum : unsigned {
WASM_LIMITS_FLAG_HAS_MAX = 0x1,
};
@ -190,12 +187,25 @@ enum class ValType {
F64 = WASM_TYPE_F64,
};
// Linking metadata kinds.
// Kind codes used in the custom "name" section
enum : unsigned {
WASM_NAMES_FUNCTION = 0x1,
WASM_NAMES_LOCAL = 0x2,
};
// Kind codes used in the custom "linking" section
enum : unsigned {
WASM_SYMBOL_INFO = 0x2,
WASM_DATA_SIZE = 0x3,
WASM_SEGMENT_INFO = 0x5,
WASM_INIT_FUNCS = 0x6,
WASM_COMDAT_INFO = 0x7,
};
// Kind codes used in the custom "linking" section in the WASM_COMDAT_INFO
enum : unsigned {
WASM_COMDAT_DATA = 0x0,
WASM_COMDAT_FUNCTION = 0x1,
};
const unsigned WASM_SYMBOL_BINDING_MASK = 0x3;

View File

@ -149,6 +149,7 @@ public:
ArrayRef<wasm::WasmElemSegment> elements() const { return ElemSegments; }
ArrayRef<WasmSegment> dataSegments() const { return DataSegments; }
ArrayRef<wasm::WasmFunction> functions() const { return Functions; }
ArrayRef<StringRef> comdats() const { return Comdats; }
uint32_t startFunction() const { return StartFunction; }
void moveSymbolNext(DataRefImpl &Symb) const override;
@ -232,6 +233,7 @@ private:
// Custom section types
Error parseNameSection(const uint8_t *Ptr, const uint8_t *End);
Error parseLinkingSection(const uint8_t *Ptr, const uint8_t *End);
Error parseLinkingSectionComdat(const uint8_t *&Ptr, const uint8_t *End);
Error parseRelocSection(StringRef Name, const uint8_t *Ptr,
const uint8_t *End);
@ -250,6 +252,7 @@ private:
std::vector<WasmSegment> DataSegments;
std::vector<wasm::WasmFunction> Functions;
std::vector<WasmSymbol> Symbols;
std::vector<StringRef> Comdats;
uint32_t StartFunction = -1;
bool HasLinkingSection = false;
wasm::WasmLinkingData LinkingData;

View File

@ -37,6 +37,7 @@ LLVM_YAML_STRONG_TYPEDEF(uint32_t, RelocType)
LLVM_YAML_STRONG_TYPEDEF(uint32_t, SymbolFlags)
LLVM_YAML_STRONG_TYPEDEF(uint32_t, SegmentFlags)
LLVM_YAML_STRONG_TYPEDEF(uint32_t, LimitFlags)
LLVM_YAML_STRONG_TYPEDEF(uint32_t, ComdatKind)
struct FileHeader {
yaml::Hex32 Version;
@ -138,6 +139,16 @@ struct InitFunction {
uint32_t FunctionIndex;
};
struct ComdatEntry {
ComdatKind Kind;
uint32_t Index;
};
struct Comdat {
StringRef Name;
std::vector<ComdatEntry> Entries;
};
struct Section {
explicit Section(SectionType SecType) : Type(SecType) {}
virtual ~Section();
@ -181,6 +192,7 @@ struct LinkingSection : CustomSection {
std::vector<SymbolInfo> SymbolInfos;
std::vector<SegmentInfo> SegmentInfos;
std::vector<InitFunction> InitFunctions;
std::vector<Comdat> Comdats;
};
struct TypeSection : Section {
@ -318,6 +330,8 @@ LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::NameEntry)
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::SegmentInfo)
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::SymbolInfo)
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::InitFunction)
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::ComdatEntry)
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::Comdat)
namespace llvm {
namespace yaml {
@ -414,6 +428,18 @@ template <> struct MappingTraits<WasmYAML::InitFunction> {
static void mapping(IO &IO, WasmYAML::InitFunction &Init);
};
template <> struct ScalarEnumerationTraits<WasmYAML::ComdatKind> {
static void enumeration(IO &IO, WasmYAML::ComdatKind &Kind);
};
template <> struct MappingTraits<WasmYAML::ComdatEntry> {
static void mapping(IO &IO, WasmYAML::ComdatEntry &ComdatEntry);
};
template <> struct MappingTraits<WasmYAML::Comdat> {
static void mapping(IO &IO, WasmYAML::Comdat &Comdat);
};
template <> struct ScalarEnumerationTraits<WasmYAML::ValueType> {
static void enumeration(IO &IO, WasmYAML::ValueType &Type);
};

View File

@ -1254,15 +1254,17 @@ void TargetLoweringObjectFileCOFF::emitLinkerFlagsForGlobal(
// Wasm
//===----------------------------------------------------------------------===//
static void checkWasmComdat(const GlobalValue *GV) {
static const Comdat *getWasmComdat(const GlobalValue *GV) {
const Comdat *C = GV->getComdat();
if (!C)
return;
return nullptr;
// TODO(sbc): At some point we may need COMDAT support but currently
// they are not supported.
report_fatal_error("WebAssembly doesn't support COMDATs, '" + C->getName() +
"' cannot be lowered.");
if (C->getSelectionKind() != Comdat::Any)
report_fatal_error("WebAssembly COMDATs only support "
"SelectionKind::Any, '" + C->getName() + "' cannot be "
"lowered.");
return C;
}
static SectionKind getWasmKindForNamedSection(StringRef Name, SectionKind K) {
@ -1278,16 +1280,25 @@ static SectionKind getWasmKindForNamedSection(StringRef Name, SectionKind K) {
MCSection *TargetLoweringObjectFileWasm::getExplicitSectionGlobal(
const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const {
StringRef Name = GO->getSection();
checkWasmComdat(GO);
Kind = getWasmKindForNamedSection(Name, Kind);
return getContext().getWasmSection(Name, Kind);
StringRef Group = "";
if (const Comdat *C = getWasmComdat(GO)) {
Group = C->getName();
}
return getContext().getWasmSection(Name, Kind, Group,
MCContext::GenericSectionID);
}
static MCSectionWasm *selectWasmSectionForGlobal(
MCContext &Ctx, const GlobalObject *GO, SectionKind Kind, Mangler &Mang,
const TargetMachine &TM, bool EmitUniqueSection, unsigned *NextUniqueID) {
StringRef Group = "";
checkWasmComdat(GO);
if (const Comdat *C = getWasmComdat(GO)) {
Group = C->getName();
}
bool UniqueSectionNames = TM.getUniqueSectionNames();
SmallString<128> Name = getSectionPrefixForGlobal(Kind);

View File

@ -138,6 +138,14 @@ struct WasmGlobal {
uint32_t ImportIndex;
};
// Information about a single item which is part of a COMDAT. For each data
// segment or function which is in the COMDAT, there is a corresponding
// WasmComdatEntry.
struct WasmComdatEntry {
unsigned Kind;
uint32_t Index;
};
// Information about a single relocation.
struct WasmRelocationEntry {
uint64_t Offset; // Where is the relocation.
@ -284,8 +292,9 @@ private:
void writeDataRelocSection();
void writeLinkingMetaDataSection(
ArrayRef<WasmDataSegment> Segments, uint32_t DataSize,
const SmallVector<std::pair<StringRef, uint32_t>, 4> &SymbolFlags,
const SmallVector<std::pair<uint16_t, uint32_t>, 2> &InitFuncs);
ArrayRef<std::pair<StringRef, uint32_t>> SymbolFlags,
ArrayRef<std::pair<uint16_t, uint32_t>> InitFuncs,
const std::map<StringRef, std::vector<WasmComdatEntry>>& Comdats);
uint32_t getProvisionalValue(const WasmRelocationEntry &RelEntry);
void applyRelocations(ArrayRef<WasmRelocationEntry> Relocations,
@ -913,8 +922,9 @@ void WasmObjectWriter::writeDataRelocSection() {
void WasmObjectWriter::writeLinkingMetaDataSection(
ArrayRef<WasmDataSegment> Segments, uint32_t DataSize,
const SmallVector<std::pair<StringRef, uint32_t>, 4> &SymbolFlags,
const SmallVector<std::pair<uint16_t, uint32_t>, 2> &InitFuncs) {
ArrayRef<std::pair<StringRef, uint32_t>> SymbolFlags,
ArrayRef<std::pair<uint16_t, uint32_t>> InitFuncs,
const std::map<StringRef, std::vector<WasmComdatEntry>>& Comdats) {
SectionBookkeeping Section;
startSection(Section, wasm::WASM_SEC_CUSTOM, "linking");
SectionBookkeeping SubSection;
@ -956,6 +966,21 @@ void WasmObjectWriter::writeLinkingMetaDataSection(
endSection(SubSection);
}
if (Comdats.size()) {
startSection(SubSection, wasm::WASM_COMDAT_INFO);
encodeULEB128(Comdats.size(), getStream());
for (const auto &C : Comdats) {
writeString(C.first);
encodeULEB128(0, getStream()); // flags for future use
encodeULEB128(C.second.size(), getStream());
for (const WasmComdatEntry &Entry : C.second) {
encodeULEB128(Entry.Kind, getStream());
encodeULEB128(Entry.Index, getStream());
}
}
endSection(SubSection);
}
endSection(Section);
}
@ -997,6 +1022,7 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
SmallVector<WasmExport, 4> Exports;
SmallVector<std::pair<StringRef, uint32_t>, 4> SymbolFlags;
SmallVector<std::pair<uint16_t, uint32_t>, 2> InitFuncs;
std::map<StringRef, std::vector<WasmComdatEntry>> Comdats;
unsigned NumFuncImports = 0;
SmallVector<WasmDataSegment, 4> DataSegments;
uint32_t DataSize = 0;
@ -1143,6 +1169,12 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
Segment.Flags = 0;
DataSize += Segment.Data.size();
Section.setMemoryOffset(Segment.Offset);
if (const MCSymbolWasm *C = Section.getGroup()) {
Comdats[C->getName()].emplace_back(
WasmComdatEntry{wasm::WASM_COMDAT_DATA,
static_cast<uint32_t>(DataSegments.size()) - 1});
}
}
// Handle regular defined and undefined symbols.
@ -1216,6 +1248,7 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
// address. For externals these will also be named exports.
Index = NumGlobalImports + Globals.size();
auto &DataSection = static_cast<MCSectionWasm &>(WS.getSection());
assert(DataSection.isWasmData());
WasmGlobal Global;
Global.Type = PtrType;
@ -1239,8 +1272,16 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
Export.Kind = wasm::WASM_EXTERNAL_GLOBAL;
DEBUG(dbgs() << " -> export " << Exports.size() << "\n");
Exports.push_back(Export);
if (!WS.isExternal())
SymbolFlags.emplace_back(WS.getName(), wasm::WASM_SYMBOL_BINDING_LOCAL);
if (WS.isFunction()) {
auto &Section = static_cast<MCSectionWasm &>(WS.getSection(false));
if (const MCSymbolWasm *C = Section.getGroup())
Comdats[C->getName()].emplace_back(
WasmComdatEntry{wasm::WASM_COMDAT_FUNCTION, Index});
}
}
}
@ -1372,7 +1413,7 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm,
writeCodeRelocSection();
writeDataRelocSection();
writeLinkingMetaDataSection(DataSegments, DataSize, SymbolFlags,
InitFuncs);
InitFuncs, Comdats);
// TODO: Translate the .comment section to the output.
// TODO: Translate debug sections to the output.

View File

@ -10,6 +10,7 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/ADT/Triple.h"
#include "llvm/BinaryFormat/Wasm.h"
#include "llvm/MC/SubtargetFeature.h"
@ -422,6 +423,10 @@ Error WasmObjectFile::parseLinkingSection(const uint8_t *Ptr,
}
break;
}
case wasm::WASM_COMDAT_INFO:
if (Error Err = parseLinkingSectionComdat(Ptr, SubSectionEnd))
return Err;
break;
default:
Ptr += Size;
break;
@ -436,6 +441,55 @@ Error WasmObjectFile::parseLinkingSection(const uint8_t *Ptr,
return Error::success();
}
Error WasmObjectFile::parseLinkingSectionComdat(const uint8_t *&Ptr,
const uint8_t *End)
{
uint32_t ComdatCount = readVaruint32(Ptr);
StringSet<> ComdatSet;
while (ComdatCount--) {
StringRef Name = readString(Ptr);
if (Name.empty() || !ComdatSet.insert(Name).second)
return make_error<GenericBinaryError>("Bad/duplicate COMDAT name " + Twine(Name),
object_error::parse_failed);
Comdats.emplace_back(Name);
uint32_t Flags = readVaruint32(Ptr);
if (Flags != 0)
return make_error<GenericBinaryError>("Unsupported COMDAT flags",
object_error::parse_failed);
uint32_t EntryCount = readVaruint32(Ptr);
while (EntryCount--) {
unsigned Kind = readVaruint32(Ptr);
unsigned Index = readVaruint32(Ptr);
switch (Kind) {
default:
return make_error<GenericBinaryError>("Invalid COMDAT entry type",
object_error::parse_failed);
case wasm::WASM_COMDAT_DATA:
if (Index >= DataSegments.size())
return make_error<GenericBinaryError>("COMDAT data index out of range",
object_error::parse_failed);
if (!DataSegments[Index].Data.Comdat.empty())
return make_error<GenericBinaryError>("Data segment in two COMDATs",
object_error::parse_failed);
DataSegments[Index].Data.Comdat = Name;
break;
case wasm::WASM_COMDAT_FUNCTION:
if (Index < NumImportedFunctions || !isValidFunctionIndex(Index))
return make_error<GenericBinaryError>("COMDAT function index out of range",
object_error::parse_failed);
Index -= NumImportedFunctions;
if (!Functions[Index].Comdat.empty())
return make_error<GenericBinaryError>("Function in two COMDATs",
object_error::parse_failed);
Functions[Index].Comdat = Name;
break;
}
}
}
return Error::success();
}
WasmSection* WasmObjectFile::findCustomSectionByName(StringRef Name) {
for (WasmSection& Section : Sections) {
if (Section.Type == wasm::WASM_SEC_CUSTOM && Section.Name == Name)

View File

@ -61,6 +61,7 @@ static void sectionMapping(IO &IO, WasmYAML::LinkingSection &Section) {
IO.mapOptional("SymbolInfo", Section.SymbolInfos);
IO.mapOptional("SegmentInfo", Section.SegmentInfos);
IO.mapOptional("InitFunctions", Section.InitFunctions);
IO.mapOptional("Comdats", Section.Comdats);
}
static void sectionMapping(IO &IO, WasmYAML::CustomSection &Section) {
@ -368,6 +369,26 @@ void MappingTraits<WasmYAML::InitFunction>::mapping(
IO.mapRequired("FunctionIndex", Init.FunctionIndex);
}
void ScalarEnumerationTraits<WasmYAML::ComdatKind>::enumeration(
IO &IO, WasmYAML::ComdatKind &Kind) {
#define ECase(X) IO.enumCase(Kind, #X, wasm::WASM_COMDAT_##X);
ECase(FUNCTION);
ECase(DATA);
#undef ECase
}
void MappingTraits<WasmYAML::ComdatEntry>::mapping(
IO &IO, WasmYAML::ComdatEntry &ComdatEntry) {
IO.mapRequired("Kind", ComdatEntry.Kind);
IO.mapRequired("Index", ComdatEntry.Index);
}
void MappingTraits<WasmYAML::Comdat>::mapping(
IO &IO, WasmYAML::Comdat &Comdat) {
IO.mapRequired("Name", Comdat.Name);
IO.mapRequired("Entries", Comdat.Entries);
}
void MappingTraits<WasmYAML::SymbolInfo>::mapping(IO &IO,
WasmYAML::SymbolInfo &Info) {
IO.mapRequired("Name", Info.Name);

View File

@ -1,5 +0,0 @@
; RUN: not llc < %s -mtriple wasm32-unknown-unknown-wasm 2>&1 | FileCheck %s
$f = comdat any
@f = global i32 0, comdat
; CHECK: LLVM ERROR: WebAssembly doesn't support COMDATs, 'f' cannot be lowered.

View File

@ -0,0 +1,99 @@
; RUN: llc -mtriple wasm32-unknown-unknown-wasm -filetype=obj %s -o - | obj2yaml | FileCheck %s
; Import a function just so we can check the index arithmetic for
; WASM_COMDAT_FUNCTION entries is performed correctly
declare i32 @funcImport()
define i32 @callImport() {
entry:
%call = call i32 @funcImport()
ret i32 %call
}
; Function in its own COMDAT
$basicInlineFn = comdat any
define linkonce_odr i32 @basicInlineFn() #1 comdat {
ret i32 0
}
; Global, data, and function in same COMDAT
$sharedComdat = comdat any
@constantData = weak_odr constant [3 x i8] c"abc", comdat($sharedComdat)
define linkonce_odr i32 @sharedFn() #1 comdat($sharedComdat) {
ret i32 0
}
; CHECK: - Type: EXPORT
; CHECK-NEXT: Exports:
; CHECK-NEXT: - Name: callImport
; CHECK-NEXT: Kind: FUNCTION
; CHECK-NEXT: Index: 1
; CHECK-NEXT: - Name: basicInlineFn
; CHECK-NEXT: Kind: FUNCTION
; CHECK-NEXT: Index: 2
; CHECK-NEXT: - Name: sharedFn
; CHECK-NEXT: Kind: FUNCTION
; CHECK-NEXT: Index: 3
; CHECK-NEXT: - Name: constantData
; CHECK-NEXT: Kind: GLOBAL
; CHECK-NEXT: Index: 1
; CHECK-NEXT: - Type: CODE
; CHECK-NEXT: Relocations:
; CHECK-NEXT: - Type: R_WEBASSEMBLY_FUNCTION_INDEX_LEB
; CHECK-NEXT: Index: 0
; CHECK-NEXT: Offset: 0x00000004
; CHECK-NEXT: Functions:
; CHECK-NEXT: - Index: 1
; CHECK-NEXT: Locals:
; CHECK-NEXT: Body: 1080808080000B
; CHECK-NEXT: - Index: 2
; CHECK-NEXT: Locals:
; CHECK-NEXT: Body: 41000B
; CHECK-NEXT: - Index: 3
; CHECK-NEXT: Locals:
; CHECK-NEXT: Body: 41000B
; CHECK-NEXT: - Type: DATA
; CHECK-NEXT: Segments:
; CHECK-NEXT: - SectionOffset: 6
; CHECK-NEXT: MemoryIndex: 0
; CHECK-NEXT: Offset:
; CHECK-NEXT: Opcode: I32_CONST
; CHECK-NEXT: Value: 0
; CHECK-NEXT: Content: '616263'
; CHECK-NEXT: - Type: CUSTOM
; CHECK-NEXT: Name: name
; CHECK-NEXT: FunctionNames:
; CHECK-NEXT: - Index: 0
; CHECK-NEXT: Name: funcImport
; CHECK-NEXT: - Index: 1
; CHECK-NEXT: Name: callImport
; CHECK-NEXT: - Index: 2
; CHECK-NEXT: Name: basicInlineFn
; CHECK-NEXT: - Index: 3
; CHECK-NEXT: Name: sharedFn
; CHECK-NEXT: - Type: CUSTOM
; CHECK-NEXT: Name: linking
; CHECK-NEXT: DataSize: 3
; CHECK-NEXT: SymbolInfo:
; CHECK-NEXT: - Name: basicInlineFn
; CHECK-NEXT: Flags: [ BINDING_WEAK ]
; CHECK-NEXT: - Name: sharedFn
; CHECK-NEXT: Flags: [ BINDING_WEAK ]
; CHECK-NEXT: - Name: constantData
; CHECK-NEXT: Flags: [ BINDING_WEAK ]
; CHECK-NEXT: SegmentInfo:
; CHECK-NEXT: - Index: 0
; CHECK-NEXT: Name: .rodata.constantData
; CHECK-NEXT: Alignment: 1
; CHECK-NEXT: Flags: [ ]
; CHECK-NEXT: Comdats:
; CHECK-NEXT: - Name: basicInlineFn
; CHECK-NEXT: Entries:
; CHECK-NEXT: - Kind: FUNCTION
; CHECK-NEXT: Index: 2
; CHECK-NEXT: - Name: sharedComdat
; CHECK-NEXT: Entries:
; CHECK-NEXT: - Kind: FUNCTION
; CHECK-NEXT: Index: 3
; CHECK-NEXT: - Kind: DATA
; CHECK-NEXT: Index: 0
; CHECK-NEXT: ...

View File

@ -65,17 +65,34 @@ std::unique_ptr<WasmYAML::CustomSection> WasmDumper::dumpCustomSection(const Was
CustomSec = std::move(NameSec);
} else if (WasmSec.Name == "linking") {
std::unique_ptr<WasmYAML::LinkingSection> LinkingSec = make_unique<WasmYAML::LinkingSection>();
size_t Index = 0;
std::map<StringRef,size_t> ComdatIndexes;
for (StringRef ComdatName : Obj.comdats()) {
ComdatIndexes[ComdatName] = LinkingSec->Comdats.size();
LinkingSec->Comdats.emplace_back(WasmYAML::Comdat{ComdatName, {}});
}
for (auto &Func : Obj.functions()) {
if (!Func.Comdat.empty()) {
auto &Comdat = LinkingSec->Comdats[ComdatIndexes[Func.Comdat]];
Comdat.Entries.emplace_back(
WasmYAML::ComdatEntry{wasm::WASM_COMDAT_FUNCTION, Func.Index});
}
}
uint32_t SegmentIndex = 0;
for (const object::WasmSegment &Segment : Obj.dataSegments()) {
if (!Segment.Data.Name.empty()) {
WasmYAML::SegmentInfo SegmentInfo;
SegmentInfo.Name = Segment.Data.Name;
SegmentInfo.Index = Index;
SegmentInfo.Index = SegmentIndex;
SegmentInfo.Alignment = Segment.Data.Alignment;
SegmentInfo.Flags = Segment.Data.Flags;
LinkingSec->SegmentInfos.push_back(SegmentInfo);
}
Index++;
if (!Segment.Data.Comdat.empty()) {
auto &Comdat = LinkingSec->Comdats[ComdatIndexes[Segment.Data.Comdat]];
Comdat.Entries.emplace_back(
WasmYAML::ComdatEntry{wasm::WASM_COMDAT_DATA, SegmentIndex});
}
SegmentIndex++;
}
for (const object::SymbolRef& Sym: Obj.symbols()) {
const object::WasmSymbol Symbol = Obj.getWasmSymbol(Sym);

View File

@ -175,6 +175,23 @@ int WasmWriter::writeSectionContent(raw_ostream &OS, WasmYAML::LinkingSection &S
}
SubSection.Done();
}
// COMDAT_INFO subsection
if (Section.Comdats.size()) {
encodeULEB128(wasm::WASM_COMDAT_INFO, OS);
encodeULEB128(Section.Comdats.size(), SubSection.GetStream());
for (const auto &C : Section.Comdats) {
writeStringRef(C.Name, SubSection.GetStream());
encodeULEB128(0, SubSection.GetStream()); // flags for future use
encodeULEB128(C.Entries.size(), SubSection.GetStream());
for (const WasmYAML::ComdatEntry &Entry : C.Entries) {
encodeULEB128(Entry.Kind, SubSection.GetStream());
encodeULEB128(Entry.Index, SubSection.GetStream());
}
}
SubSection.Done();
}
return 0;
}