[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:
Sam Clegg 2017-12-14 21:10:03 +00:00
parent ea244bf89b
commit 4273998cf9
8 changed files with 69 additions and 3 deletions

View File

@ -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;

View File

@ -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;

View File

@ -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);
}; };

View File

@ -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();

View File

@ -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);

View File

@ -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: ...

View File

@ -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);

View File

@ -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;
} }