From 9504ab32b76646116585cae4298f700cf46721ab Mon Sep 17 00:00:00 2001 From: Sam Clegg Date: Wed, 9 Mar 2022 18:11:44 -0800 Subject: [WebAssembly] Second phase of implemented extended const proposal This change continues to lay the ground work for supporting extended const expressions in the linker. The included test covers object file reading and writing and the YAML representation. Differential Revision: https://reviews.llvm.org/D121349 --- llvm/lib/Object/WasmObjectFile.cpp | 77 +++++++++++++++++++++++++++----------- 1 file changed, 56 insertions(+), 21 deletions(-) (limited to 'llvm/lib/Object/WasmObjectFile.cpp') diff --git a/llvm/lib/Object/WasmObjectFile.cpp b/llvm/lib/Object/WasmObjectFile.cpp index 1122f42..8e317b0 100644 --- a/llvm/lib/Object/WasmObjectFile.cpp +++ b/llvm/lib/Object/WasmObjectFile.cpp @@ -164,23 +164,25 @@ static uint8_t readOpcode(WasmObjectFile::ReadContext &Ctx) { static Error readInitExpr(wasm::WasmInitExpr &Expr, WasmObjectFile::ReadContext &Ctx) { - Expr.Opcode = readOpcode(Ctx); + auto Start = Ctx.Ptr; - switch (Expr.Opcode) { + Expr.Extended = false; + Expr.Inst.Opcode = readOpcode(Ctx); + switch (Expr.Inst.Opcode) { case wasm::WASM_OPCODE_I32_CONST: - Expr.Value.Int32 = readVarint32(Ctx); + Expr.Inst.Value.Int32 = readVarint32(Ctx); break; case wasm::WASM_OPCODE_I64_CONST: - Expr.Value.Int64 = readVarint64(Ctx); + Expr.Inst.Value.Int64 = readVarint64(Ctx); break; case wasm::WASM_OPCODE_F32_CONST: - Expr.Value.Float32 = readFloat32(Ctx); + Expr.Inst.Value.Float32 = readFloat32(Ctx); break; case wasm::WASM_OPCODE_F64_CONST: - Expr.Value.Float64 = readFloat64(Ctx); + Expr.Inst.Value.Float64 = readFloat64(Ctx); break; case wasm::WASM_OPCODE_GLOBAL_GET: - Expr.Value.Global = readULEB128(Ctx); + Expr.Inst.Value.Global = readULEB128(Ctx); break; case wasm::WASM_OPCODE_REF_NULL: { wasm::ValType Ty = static_cast(readULEB128(Ctx)); @@ -191,15 +193,46 @@ static Error readInitExpr(wasm::WasmInitExpr &Expr, break; } default: - return make_error("invalid opcode in init_expr", - object_error::parse_failed); + Expr.Extended = true; } - uint8_t EndOpcode = readOpcode(Ctx); - if (EndOpcode != wasm::WASM_OPCODE_END) { - return make_error("invalid init_expr", - object_error::parse_failed); + if (!Expr.Extended) { + uint8_t EndOpcode = readOpcode(Ctx); + if (EndOpcode != wasm::WASM_OPCODE_END) + Expr.Extended = true; + } + + if (Expr.Extended) { + Ctx.Ptr = Start; + while (1) { + uint8_t Opcode = readOpcode(Ctx); + switch (Opcode) { + case wasm::WASM_OPCODE_I32_CONST: + case wasm::WASM_OPCODE_GLOBAL_GET: + case wasm::WASM_OPCODE_REF_NULL: + case wasm::WASM_OPCODE_I64_CONST: + case wasm::WASM_OPCODE_F32_CONST: + case wasm::WASM_OPCODE_F64_CONST: + readULEB128(Ctx); + break; + case wasm::WASM_OPCODE_I32_ADD: + case wasm::WASM_OPCODE_I32_SUB: + case wasm::WASM_OPCODE_I32_MUL: + case wasm::WASM_OPCODE_I64_ADD: + case wasm::WASM_OPCODE_I64_SUB: + case wasm::WASM_OPCODE_I64_MUL: + break; + case wasm::WASM_OPCODE_END: + Expr.Body = ArrayRef(Start, Ctx.Ptr - Start); + return Error::success(); + default: + return make_error( + Twine("invalid opcode in init_expr: ") + Twine(unsigned(Opcode)), + object_error::parse_failed); + } + } } + return Error::success(); } @@ -1441,8 +1474,8 @@ Error WasmObjectFile::parseElemSection(ReadContext &Ctx) { object_error::parse_failed); if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_IS_PASSIVE) { - Segment.Offset.Opcode = wasm::WASM_OPCODE_I32_CONST; - Segment.Offset.Value.Int32 = 0; + Segment.Offset.Inst.Opcode = wasm::WASM_OPCODE_I32_CONST; + Segment.Offset.Inst.Value.Int32 = 0; } else { if (Error Err = readInitExpr(Segment.Offset, Ctx)) return Err; @@ -1501,8 +1534,8 @@ Error WasmObjectFile::parseDataSection(ReadContext &Ctx) { if (Error Err = readInitExpr(Segment.Data.Offset, Ctx)) return Err; } else { - Segment.Data.Offset.Opcode = wasm::WASM_OPCODE_I32_CONST; - Segment.Data.Offset.Value.Int32 = 0; + Segment.Data.Offset.Inst.Opcode = wasm::WASM_OPCODE_I32_CONST; + Segment.Data.Offset.Inst.Value.Int32 = 0; } uint32_t Size = readVaruint32(Ctx); if (Size > (size_t)(Ctx.End - Ctx.Ptr)) @@ -1600,10 +1633,12 @@ uint64_t WasmObjectFile::getWasmSymbolValue(const WasmSymbol &Sym) const { // offset within the segment. uint32_t SegmentIndex = Sym.Info.DataRef.Segment; const wasm::WasmDataSegment &Segment = DataSegments[SegmentIndex].Data; - if (Segment.Offset.Opcode == wasm::WASM_OPCODE_I32_CONST) { - return Segment.Offset.Value.Int32 + Sym.Info.DataRef.Offset; - } else if (Segment.Offset.Opcode == wasm::WASM_OPCODE_I64_CONST) { - return Segment.Offset.Value.Int64 + Sym.Info.DataRef.Offset; + if (Segment.Offset.Extended) { + llvm_unreachable("extended init exprs not supported"); + } else if (Segment.Offset.Inst.Opcode == wasm::WASM_OPCODE_I32_CONST) { + return Segment.Offset.Inst.Value.Int32 + Sym.Info.DataRef.Offset; + } else if (Segment.Offset.Inst.Opcode == wasm::WASM_OPCODE_I64_CONST) { + return Segment.Offset.Inst.Value.Int64 + Sym.Info.DataRef.Offset; } else { llvm_unreachable("unknown init expr opcode"); } -- cgit v1.1