aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Object/WasmObjectFile.cpp
diff options
context:
space:
mode:
authorDerek Schuff <dschuff@chromium.org>2025-01-17 17:26:44 -0800
committerGitHub <noreply@github.com>2025-01-17 17:26:44 -0800
commit9fdc38c81c7d1b61cb0750e5f5b273d6d1877513 (patch)
tree6c0d6d9e627a6f6d34434ae9935a57c55cbe080f /llvm/lib/Object/WasmObjectFile.cpp
parent87e4b68195adc81fae40a4fa27e33458a9586fe5 (diff)
downloadllvm-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.cpp41
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 {