[WebAssembly] Add support for init functions linking metadata
Summary: This change lays the groundwork lowering of @llvm.global_ctors and @llvm.global_dtors for the wasm object format. Some parts of this patch are subset of: https://reviews.llvm.org/D40759 See https://github.com/WebAssembly/tool-conventions/issues/25 Subscribers: jfb, dschuff, jgravelle-google, aheejin, sunfish Differential Revision: https://reviews.llvm.org/D41208 llvm-svn: 320742
This commit is contained in:
parent
ea244bf89b
commit
4273998cf9
|
@ -115,8 +115,14 @@ struct WasmRelocation {
|
||||||
int64_t Addend; // A value to add to the symbol.
|
int64_t Addend; // A value to add to the symbol.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct WasmInitFunc {
|
||||||
|
uint32_t Priority;
|
||||||
|
uint32_t FunctionIndex;
|
||||||
|
};
|
||||||
|
|
||||||
struct WasmLinkingData {
|
struct WasmLinkingData {
|
||||||
uint32_t DataSize;
|
uint32_t DataSize;
|
||||||
|
std::vector<WasmInitFunc> InitFunctions;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum : unsigned {
|
enum : unsigned {
|
||||||
|
@ -185,6 +191,7 @@ enum : unsigned {
|
||||||
WASM_SYMBOL_INFO = 0x2,
|
WASM_SYMBOL_INFO = 0x2,
|
||||||
WASM_DATA_SIZE = 0x3,
|
WASM_DATA_SIZE = 0x3,
|
||||||
WASM_SEGMENT_INFO = 0x5,
|
WASM_SEGMENT_INFO = 0x5,
|
||||||
|
WASM_INIT_FUNCS = 0x6,
|
||||||
};
|
};
|
||||||
|
|
||||||
const unsigned WASM_SYMBOL_BINDING_MASK = 0x3;
|
const unsigned WASM_SYMBOL_BINDING_MASK = 0x3;
|
||||||
|
|
|
@ -206,6 +206,7 @@ public:
|
||||||
bool isRelocatableObject() const override;
|
bool isRelocatableObject() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
bool isValidFunctionIndex(uint32_t Index) const;
|
||||||
const WasmSection &getWasmSection(DataRefImpl Ref) const;
|
const WasmSection &getWasmSection(DataRefImpl Ref) const;
|
||||||
const wasm::WasmRelocation &getWasmRelocation(DataRefImpl Ref) const;
|
const wasm::WasmRelocation &getWasmRelocation(DataRefImpl Ref) const;
|
||||||
|
|
||||||
|
|
|
@ -131,6 +131,11 @@ struct SymbolInfo {
|
||||||
SymbolFlags Flags;
|
SymbolFlags Flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct InitFunction {
|
||||||
|
uint32_t Priority;
|
||||||
|
uint32_t FunctionIndex;
|
||||||
|
};
|
||||||
|
|
||||||
struct Section {
|
struct Section {
|
||||||
explicit Section(SectionType SecType) : Type(SecType) {}
|
explicit Section(SectionType SecType) : Type(SecType) {}
|
||||||
virtual ~Section();
|
virtual ~Section();
|
||||||
|
@ -173,6 +178,7 @@ struct LinkingSection : CustomSection {
|
||||||
uint32_t DataSize;
|
uint32_t DataSize;
|
||||||
std::vector<SymbolInfo> SymbolInfos;
|
std::vector<SymbolInfo> SymbolInfos;
|
||||||
std::vector<SegmentInfo> SegmentInfos;
|
std::vector<SegmentInfo> SegmentInfos;
|
||||||
|
std::vector<InitFunction> InitFunctions;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TypeSection : Section {
|
struct TypeSection : Section {
|
||||||
|
@ -309,6 +315,7 @@ LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::Relocation)
|
||||||
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::NameEntry)
|
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::NameEntry)
|
||||||
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::SegmentInfo)
|
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::SegmentInfo)
|
||||||
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::SymbolInfo)
|
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::SymbolInfo)
|
||||||
|
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::InitFunction)
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
namespace yaml {
|
namespace yaml {
|
||||||
|
@ -401,6 +408,10 @@ template <> struct MappingTraits<WasmYAML::SymbolInfo> {
|
||||||
static void mapping(IO &IO, WasmYAML::SymbolInfo &Info);
|
static void mapping(IO &IO, WasmYAML::SymbolInfo &Info);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <> struct MappingTraits<WasmYAML::InitFunction> {
|
||||||
|
static void mapping(IO &IO, WasmYAML::InitFunction &Init);
|
||||||
|
};
|
||||||
|
|
||||||
template <> struct ScalarEnumerationTraits<WasmYAML::ValueType> {
|
template <> struct ScalarEnumerationTraits<WasmYAML::ValueType> {
|
||||||
static void enumeration(IO &IO, WasmYAML::ValueType &Type);
|
static void enumeration(IO &IO, WasmYAML::ValueType &Type);
|
||||||
};
|
};
|
||||||
|
|
|
@ -398,6 +398,21 @@ Error WasmObjectFile::parseLinkingSection(const uint8_t *Ptr,
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case wasm::WASM_INIT_FUNCS: {
|
||||||
|
uint32_t Count = readVaruint32(Ptr);
|
||||||
|
LinkingData.InitFunctions.reserve(Count);
|
||||||
|
for (uint32_t i = 0; i < Count; i++) {
|
||||||
|
wasm::WasmInitFunc Init;
|
||||||
|
Init.Priority = readVaruint32(Ptr);
|
||||||
|
Init.FunctionIndex = readVaruint32(Ptr);
|
||||||
|
if (!isValidFunctionIndex(Init.FunctionIndex))
|
||||||
|
return make_error<GenericBinaryError>("Invalid function index: " +
|
||||||
|
Twine(Init.FunctionIndex),
|
||||||
|
object_error::parse_failed);
|
||||||
|
LinkingData.InitFunctions.emplace_back(Init);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
Ptr += Size;
|
Ptr += Size;
|
||||||
break;
|
break;
|
||||||
|
@ -656,9 +671,13 @@ Error WasmObjectFile::parseExportSection(const uint8_t *Ptr, const uint8_t *End)
|
||||||
return Error::success();
|
return Error::success();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool WasmObjectFile::isValidFunctionIndex(uint32_t Index) const {
|
||||||
|
return Index < FunctionTypes.size() + NumImportedFunctions;
|
||||||
|
}
|
||||||
|
|
||||||
Error WasmObjectFile::parseStartSection(const uint8_t *Ptr, const uint8_t *End) {
|
Error WasmObjectFile::parseStartSection(const uint8_t *Ptr, const uint8_t *End) {
|
||||||
StartFunction = readVaruint32(Ptr);
|
StartFunction = readVaruint32(Ptr);
|
||||||
if (StartFunction >= FunctionTypes.size())
|
if (!isValidFunctionIndex(StartFunction))
|
||||||
return make_error<GenericBinaryError>("Invalid start function",
|
return make_error<GenericBinaryError>("Invalid start function",
|
||||||
object_error::parse_failed);
|
object_error::parse_failed);
|
||||||
return Error::success();
|
return Error::success();
|
||||||
|
|
|
@ -60,6 +60,7 @@ static void sectionMapping(IO &IO, WasmYAML::LinkingSection &Section) {
|
||||||
IO.mapRequired("DataSize", Section.DataSize);
|
IO.mapRequired("DataSize", Section.DataSize);
|
||||||
IO.mapOptional("SymbolInfo", Section.SymbolInfos);
|
IO.mapOptional("SymbolInfo", Section.SymbolInfos);
|
||||||
IO.mapOptional("SegmentInfo", Section.SegmentInfos);
|
IO.mapOptional("SegmentInfo", Section.SegmentInfos);
|
||||||
|
IO.mapOptional("InitFunctions", Section.InitFunctions);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sectionMapping(IO &IO, WasmYAML::CustomSection &Section) {
|
static void sectionMapping(IO &IO, WasmYAML::CustomSection &Section) {
|
||||||
|
@ -359,6 +360,12 @@ void MappingTraits<WasmYAML::DataSegment>::mapping(
|
||||||
IO.mapRequired("Content", Segment.Content);
|
IO.mapRequired("Content", Segment.Content);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MappingTraits<WasmYAML::InitFunction>::mapping(
|
||||||
|
IO &IO, WasmYAML::InitFunction &Init) {
|
||||||
|
IO.mapRequired("Priority", Init.Priority);
|
||||||
|
IO.mapRequired("FunctionIndex", Init.FunctionIndex);
|
||||||
|
}
|
||||||
|
|
||||||
void MappingTraits<WasmYAML::SymbolInfo>::mapping(IO &IO,
|
void MappingTraits<WasmYAML::SymbolInfo>::mapping(IO &IO,
|
||||||
WasmYAML::SymbolInfo &Info) {
|
WasmYAML::SymbolInfo &Info) {
|
||||||
IO.mapRequired("Name", Info.Name);
|
IO.mapRequired("Name", Info.Name);
|
||||||
|
|
|
@ -41,6 +41,9 @@ Sections:
|
||||||
Alignment: 2
|
Alignment: 2
|
||||||
Flags: [ ]
|
Flags: [ ]
|
||||||
Name: moredata
|
Name: moredata
|
||||||
|
InitFunctions:
|
||||||
|
- Priority: 1
|
||||||
|
FunctionIndex: 0
|
||||||
...
|
...
|
||||||
# CHECK: - Type: CUSTOM
|
# CHECK: - Type: CUSTOM
|
||||||
# CHECK-NEXT: Name: linking
|
# CHECK-NEXT: Name: linking
|
||||||
|
@ -57,4 +60,7 @@ Sections:
|
||||||
# CHECK-NEXT: Name: moredata
|
# CHECK-NEXT: Name: moredata
|
||||||
# CHECK-NEXT: Alignment: 2
|
# CHECK-NEXT: Alignment: 2
|
||||||
# CHECK-NEXT: Flags: [ ]
|
# CHECK-NEXT: Flags: [ ]
|
||||||
|
# CHECK-NEXT: InitFunctions:
|
||||||
|
# CHECK-NEXT: - Priority: 1
|
||||||
|
# CHECK-NEXT: FunctionIndex: 0
|
||||||
# CHECK-NEXT: ...
|
# CHECK-NEXT: ...
|
||||||
|
|
|
@ -80,11 +80,15 @@ std::unique_ptr<WasmYAML::CustomSection> WasmDumper::dumpCustomSection(const Was
|
||||||
for (const object::SymbolRef& Sym: Obj.symbols()) {
|
for (const object::SymbolRef& Sym: Obj.symbols()) {
|
||||||
const object::WasmSymbol Symbol = Obj.getWasmSymbol(Sym);
|
const object::WasmSymbol Symbol = Obj.getWasmSymbol(Sym);
|
||||||
if (Symbol.Flags != 0) {
|
if (Symbol.Flags != 0) {
|
||||||
WasmYAML::SymbolInfo Info = { Symbol.Name, Symbol.Flags };
|
WasmYAML::SymbolInfo Info{Symbol.Name, Symbol.Flags};
|
||||||
LinkingSec->SymbolInfos.push_back(Info);
|
LinkingSec->SymbolInfos.emplace_back(Info);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LinkingSec->DataSize = Obj.linkingData().DataSize;
|
LinkingSec->DataSize = Obj.linkingData().DataSize;
|
||||||
|
for (const wasm::WasmInitFunc &Func : Obj.linkingData().InitFunctions) {
|
||||||
|
WasmYAML::InitFunction F{Func.Priority, Func.FunctionIndex};
|
||||||
|
LinkingSec->InitFunctions.emplace_back(F);
|
||||||
|
}
|
||||||
CustomSec = std::move(LinkingSec);
|
CustomSec = std::move(LinkingSec);
|
||||||
} else {
|
} else {
|
||||||
CustomSec = make_unique<WasmYAML::CustomSection>(WasmSec.Name);
|
CustomSec = make_unique<WasmYAML::CustomSection>(WasmSec.Name);
|
||||||
|
|
|
@ -162,6 +162,17 @@ int WasmWriter::writeSectionContent(raw_ostream &OS, WasmYAML::LinkingSection &S
|
||||||
}
|
}
|
||||||
SubSection.Done();
|
SubSection.Done();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// INIT_FUNCS subsection
|
||||||
|
if (Section.InitFunctions.size()) {
|
||||||
|
encodeULEB128(wasm::WASM_INIT_FUNCS, OS);
|
||||||
|
encodeULEB128(Section.InitFunctions.size(), SubSection.GetStream());
|
||||||
|
for (const WasmYAML::InitFunction &Func : Section.InitFunctions) {
|
||||||
|
encodeULEB128(Func.Priority, SubSection.GetStream());
|
||||||
|
encodeULEB128(Func.FunctionIndex, SubSection.GetStream());
|
||||||
|
}
|
||||||
|
SubSection.Done();
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue