diff options
author | Derek Schuff <dschuff@chromium.org> | 2025-01-17 17:26:44 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-01-17 17:26:44 -0800 |
commit | 9fdc38c81c7d1b61cb0750e5f5b273d6d1877513 (patch) | |
tree | 6c0d6d9e627a6f6d34434ae9935a57c55cbe080f /llvm/lib/Object/WasmObjectFile.cpp | |
parent | 87e4b68195adc81fae40a4fa27e33458a9586fe5 (diff) | |
download | llvm-9fdc38c81c7d1b61cb0750e5f5b273d6d1877513.zip llvm-9fdc38c81c7d1b61cb0750e5f5b273d6d1877513.tar.gz llvm-9fdc38c81c7d1b61cb0750e5f5b273d6d1877513.tar.bz2 |
[WebAssembly][Object] Support more elem segment flags (#123427)
Some tools (e.g. Rust tooling) produce element segment descriptors with
neither
elemkind or element type descriptors, but with init exprs instead of
func indices
(this is with the flags value of 4 in
https://webassembly.github.io/spec/core/binary/modules.html#element-section).
LLVM doesn't fully model reference types or the various ways to
initialize element
segments, but we do want to correctly parse and skip over all type
sections, so
this change updates the object parser to handle that case, and refactors
for more
clarity.
The test file is updated to include one additional elem segment with a
flags value
of 4, an initializer value of (32.const 0) and an empty vector.
Also support parsing files that export imported (undefined) functions.
Diffstat (limited to 'llvm/lib/Object/WasmObjectFile.cpp')
-rw-r--r-- | llvm/lib/Object/WasmObjectFile.cpp | 41 |
1 files changed, 27 insertions, 14 deletions
diff --git a/llvm/lib/Object/WasmObjectFile.cpp b/llvm/lib/Object/WasmObjectFile.cpp index 2c9b878..0f6fd56 100644 --- a/llvm/lib/Object/WasmObjectFile.cpp +++ b/llvm/lib/Object/WasmObjectFile.cpp @@ -1440,15 +1440,20 @@ Error WasmObjectFile::parseExportSection(ReadContext &Ctx) { Info.Flags = 0; switch (Ex.Kind) { case wasm::WASM_EXTERNAL_FUNCTION: { - if (!isDefinedFunctionIndex(Ex.Index)) + if (!isValidFunctionIndex(Ex.Index)) return make_error<GenericBinaryError>("invalid function export", object_error::parse_failed); - getDefinedFunction(Ex.Index).ExportName = Ex.Name; Info.Kind = wasm::WASM_SYMBOL_TYPE_FUNCTION; Info.ElementIndex = Ex.Index; - unsigned FuncIndex = Info.ElementIndex - NumImportedFunctions; - wasm::WasmFunction &Function = Functions[FuncIndex]; - Signature = &Signatures[Function.SigIndex]; + if (isDefinedFunctionIndex(Ex.Index)) { + getDefinedFunction(Ex.Index).ExportName = Ex.Name; + unsigned FuncIndex = Info.ElementIndex - NumImportedFunctions; + wasm::WasmFunction &Function = Functions[FuncIndex]; + Signature = &Signatures[Function.SigIndex]; + } + // Else the function is imported. LLVM object files don't use this + // pattern and we still treat this as an undefined symbol, but we want to + // parse it without crashing. break; } case wasm::WASM_EXTERNAL_GLOBAL: { @@ -1645,17 +1650,25 @@ Error WasmObjectFile::parseElemSection(ReadContext &Ctx) { return make_error<GenericBinaryError>( "Unsupported flags for element segment", object_error::parse_failed); - bool IsPassive = (Segment.Flags & wasm::WASM_ELEM_SEGMENT_IS_PASSIVE) != 0; - bool IsDeclarative = - IsPassive && (Segment.Flags & wasm::WASM_ELEM_SEGMENT_IS_DECLARATIVE); + wasm::ElemSegmentMode Mode; + if ((Segment.Flags & wasm::WASM_ELEM_SEGMENT_IS_PASSIVE) == 0) { + Mode = wasm::ElemSegmentMode::Active; + } else if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_IS_DECLARATIVE) { + Mode = wasm::ElemSegmentMode::Declarative; + } else { + Mode = wasm::ElemSegmentMode::Passive; + } bool HasTableNumber = - !IsPassive && + Mode == wasm::ElemSegmentMode::Active && (Segment.Flags & wasm::WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER); + bool HasElemKind = + (Segment.Flags & wasm::WASM_ELEM_SEGMENT_MASK_HAS_ELEM_DESC) && + !(Segment.Flags & wasm::WASM_ELEM_SEGMENT_HAS_INIT_EXPRS); + bool HasElemType = + (Segment.Flags & wasm::WASM_ELEM_SEGMENT_MASK_HAS_ELEM_DESC) && + (Segment.Flags & wasm::WASM_ELEM_SEGMENT_HAS_INIT_EXPRS); bool HasInitExprs = (Segment.Flags & wasm::WASM_ELEM_SEGMENT_HAS_INIT_EXPRS); - bool HasElemKind = - (Segment.Flags & wasm::WASM_ELEM_SEGMENT_MASK_HAS_ELEM_KIND) && - !HasInitExprs; if (HasTableNumber) Segment.TableNumber = readVaruint32(Ctx); @@ -1666,7 +1679,7 @@ Error WasmObjectFile::parseElemSection(ReadContext &Ctx) { return make_error<GenericBinaryError>("invalid TableNumber", object_error::parse_failed); - if (IsPassive || IsDeclarative) { + if (Mode != wasm::ElemSegmentMode::Active) { Segment.Offset.Extended = false; Segment.Offset.Inst.Opcode = wasm::WASM_OPCODE_I32_CONST; Segment.Offset.Inst.Value.Int32 = 0; @@ -1692,7 +1705,7 @@ Error WasmObjectFile::parseElemSection(ReadContext &Ctx) { object_error::parse_failed); Segment.ElemKind = wasm::ValType::FUNCREF; } - } else if (HasInitExprs) { + } else if (HasElemType) { auto ElemType = parseValType(Ctx, readVaruint32(Ctx)); Segment.ElemKind = ElemType; } else { |