[Mlir-commits] [mlir] [MLIR][Wasm} Extending Wasm binary to WasmSSA dialect importer (PR #154452)
llvmlistbot at llvm.org
llvmlistbot at llvm.org
Tue Aug 19 19:06:42 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-mlir
Author: Luc Forget (lforg37)
<details>
<summary>Changes</summary>
This is a cherry pick of #<!-- -->154053 with a fix for bad handling of endianess when loading float and double litteral from the binary.
---
Patch is 82.31 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/154452.diff
48 Files Affected:
- (modified) mlir/include/mlir/Target/Wasm/WasmBinaryEncoding.h (+69)
- (modified) mlir/lib/Target/Wasm/TranslateFromWasm.cpp (+301-23)
- (added) mlir/test/Target/Wasm/abs.mlir (+23)
- (added) mlir/test/Target/Wasm/and.mlir (+27)
- (added) mlir/test/Target/Wasm/clz.mlir (+25)
- (added) mlir/test/Target/Wasm/const.mlir (+37)
- (added) mlir/test/Target/Wasm/copysign.mlir (+31)
- (added) mlir/test/Target/Wasm/ctz.mlir (+25)
- (added) mlir/test/Target/Wasm/div.mlir (+127)
- (added) mlir/test/Target/Wasm/global.mlir (+66)
- (added) mlir/test/Target/Wasm/inputs/abs.yaml.wasm (+33)
- (added) mlir/test/Target/Wasm/inputs/and.yaml.wasm (+33)
- (added) mlir/test/Target/Wasm/inputs/clz.yaml.wasm (+33)
- (added) mlir/test/Target/Wasm/inputs/const.yaml.wasm (+39)
- (added) mlir/test/Target/Wasm/inputs/copysign.yaml.wasm (+33)
- (added) mlir/test/Target/Wasm/inputs/ctz.yaml.wasm (+33)
- (added) mlir/test/Target/Wasm/inputs/div.yaml.wasm (+89)
- (added) mlir/test/Target/Wasm/inputs/global.yaml.wasm (+63)
- (added) mlir/test/Target/Wasm/inputs/local.yaml.wasm (+37)
- (added) mlir/test/Target/Wasm/inputs/max.yaml.wasm (+33)
- (added) mlir/test/Target/Wasm/inputs/min.yaml.wasm (+33)
- (added) mlir/test/Target/Wasm/inputs/neg.yaml.wasm (+33)
- (added) mlir/test/Target/Wasm/inputs/or.yaml.wasm (+33)
- (added) mlir/test/Target/Wasm/inputs/popcnt.yaml.wasm (+33)
- (added) mlir/test/Target/Wasm/inputs/rem.yaml.wasm (+45)
- (added) mlir/test/Target/Wasm/inputs/rotl.yaml.wasm (+33)
- (added) mlir/test/Target/Wasm/inputs/rotr.yaml.wasm (+33)
- (added) mlir/test/Target/Wasm/inputs/shl.yaml.wasm (+33)
- (added) mlir/test/Target/Wasm/inputs/shr_s.yaml.wasm (+33)
- (added) mlir/test/Target/Wasm/inputs/shr_u.yaml.wasm (+33)
- (added) mlir/test/Target/Wasm/inputs/sqrt.yaml.wasm (+33)
- (added) mlir/test/Target/Wasm/inputs/sub.yaml.wasm (+39)
- (added) mlir/test/Target/Wasm/inputs/xor.yaml.wasm (+33)
- (added) mlir/test/Target/Wasm/local.mlir (+59)
- (added) mlir/test/Target/Wasm/max.mlir (+30)
- (added) mlir/test/Target/Wasm/min.mlir (+29)
- (added) mlir/test/Target/Wasm/neg.mlir (+23)
- (added) mlir/test/Target/Wasm/or.mlir (+27)
- (added) mlir/test/Target/Wasm/popcnt.mlir (+25)
- (added) mlir/test/Target/Wasm/rem.mlir (+53)
- (added) mlir/test/Target/Wasm/rotl.mlir (+27)
- (added) mlir/test/Target/Wasm/rotr.mlir (+27)
- (added) mlir/test/Target/Wasm/shl.mlir (+27)
- (added) mlir/test/Target/Wasm/shr_s.mlir (+27)
- (added) mlir/test/Target/Wasm/shr_u.mlir (+27)
- (added) mlir/test/Target/Wasm/sqrt.mlir (+23)
- (added) mlir/test/Target/Wasm/sub.mlir (+52)
- (added) mlir/test/Target/Wasm/xor.mlir (+27)
``````````diff
diff --git a/mlir/include/mlir/Target/Wasm/WasmBinaryEncoding.h b/mlir/include/mlir/Target/Wasm/WasmBinaryEncoding.h
index 3280432b5f038..21adde878994e 100644
--- a/mlir/include/mlir/Target/Wasm/WasmBinaryEncoding.h
+++ b/mlir/include/mlir/Target/Wasm/WasmBinaryEncoding.h
@@ -20,10 +20,79 @@ struct WasmBinaryEncoding {
/// Byte encodings for Wasm instructions.
struct OpCode {
// Locals, globals, constants.
+ static constexpr std::byte localGet{0x20};
+ static constexpr std::byte localSet{0x21};
+ static constexpr std::byte localTee{0x22};
+ static constexpr std::byte globalGet{0x23};
static constexpr std::byte constI32{0x41};
static constexpr std::byte constI64{0x42};
static constexpr std::byte constFP32{0x43};
static constexpr std::byte constFP64{0x44};
+
+ // Numeric operations.
+ static constexpr std::byte clzI32{0x67};
+ static constexpr std::byte ctzI32{0x68};
+ static constexpr std::byte popcntI32{0x69};
+ static constexpr std::byte addI32{0x6A};
+ static constexpr std::byte subI32{0x6B};
+ static constexpr std::byte mulI32{0x6C};
+ static constexpr std::byte divSI32{0x6d};
+ static constexpr std::byte divUI32{0x6e};
+ static constexpr std::byte remSI32{0x6f};
+ static constexpr std::byte remUI32{0x70};
+ static constexpr std::byte andI32{0x71};
+ static constexpr std::byte orI32{0x72};
+ static constexpr std::byte xorI32{0x73};
+ static constexpr std::byte shlI32{0x74};
+ static constexpr std::byte shrSI32{0x75};
+ static constexpr std::byte shrUI32{0x76};
+ static constexpr std::byte rotlI32{0x77};
+ static constexpr std::byte rotrI32{0x78};
+ static constexpr std::byte clzI64{0x79};
+ static constexpr std::byte ctzI64{0x7A};
+ static constexpr std::byte popcntI64{0x7B};
+ static constexpr std::byte addI64{0x7C};
+ static constexpr std::byte subI64{0x7D};
+ static constexpr std::byte mulI64{0x7E};
+ static constexpr std::byte divSI64{0x7F};
+ static constexpr std::byte divUI64{0x80};
+ static constexpr std::byte remSI64{0x81};
+ static constexpr std::byte remUI64{0x82};
+ static constexpr std::byte andI64{0x83};
+ static constexpr std::byte orI64{0x84};
+ static constexpr std::byte xorI64{0x85};
+ static constexpr std::byte shlI64{0x86};
+ static constexpr std::byte shrSI64{0x87};
+ static constexpr std::byte shrUI64{0x88};
+ static constexpr std::byte rotlI64{0x89};
+ static constexpr std::byte rotrI64{0x8A};
+ static constexpr std::byte absF32{0x8B};
+ static constexpr std::byte negF32{0x8C};
+ static constexpr std::byte ceilF32{0x8D};
+ static constexpr std::byte floorF32{0x8E};
+ static constexpr std::byte truncF32{0x8F};
+ static constexpr std::byte sqrtF32{0x91};
+ static constexpr std::byte addF32{0x92};
+ static constexpr std::byte subF32{0x93};
+ static constexpr std::byte mulF32{0x94};
+ static constexpr std::byte divF32{0x95};
+ static constexpr std::byte minF32{0x96};
+ static constexpr std::byte maxF32{0x97};
+ static constexpr std::byte copysignF32{0x98};
+ static constexpr std::byte absF64{0x99};
+ static constexpr std::byte negF64{0x9A};
+ static constexpr std::byte ceilF64{0x9B};
+ static constexpr std::byte floorF64{0x9C};
+ static constexpr std::byte truncF64{0x9D};
+ static constexpr std::byte sqrtF64{0x9F};
+ static constexpr std::byte addF64{0xA0};
+ static constexpr std::byte subF64{0xA1};
+ static constexpr std::byte mulF64{0xA2};
+ static constexpr std::byte divF64{0xA3};
+ static constexpr std::byte minF64{0xA4};
+ static constexpr std::byte maxF64{0xA5};
+ static constexpr std::byte copysignF64{0xA6};
+ static constexpr std::byte wrap{0xA7};
};
/// Byte encodings of types in Wasm binaries
diff --git a/mlir/lib/Target/Wasm/TranslateFromWasm.cpp b/mlir/lib/Target/Wasm/TranslateFromWasm.cpp
index 8d450520629eb..f77699cb6ca9c 100644
--- a/mlir/lib/Target/Wasm/TranslateFromWasm.cpp
+++ b/mlir/lib/Target/Wasm/TranslateFromWasm.cpp
@@ -16,15 +16,18 @@
#include "mlir/IR/BuiltinAttributeInterfaces.h"
#include "mlir/IR/BuiltinTypes.h"
#include "mlir/IR/Location.h"
+#include "mlir/Support/LLVM.h"
#include "mlir/Target/Wasm/WasmBinaryEncoding.h"
#include "mlir/Target/Wasm/WasmImporter.h"
-#include "llvm/ADT/Statistic.h"
+#include "llvm/ADT/bit.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/DebugLog.h"
+#include "llvm/Support/Endian.h"
#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/LEB128.h"
+#include "llvm/Support/LogicalResult.h"
-#include <climits>
+#include <cstddef>
#include <cstdint>
#include <variant>
@@ -148,22 +151,22 @@ struct WasmModuleSymbolTables {
}
std::string getNewFuncSymbolName() const {
- auto id = funcSymbols.size();
+ size_t id = funcSymbols.size();
return getNewSymbolName("func_", id);
}
std::string getNewGlobalSymbolName() const {
- auto id = globalSymbols.size();
+ size_t id = globalSymbols.size();
return getNewSymbolName("global_", id);
}
std::string getNewMemorySymbolName() const {
- auto id = memSymbols.size();
+ size_t id = memSymbols.size();
return getNewSymbolName("mem_", id);
}
std::string getNewTableSymbolName() const {
- auto id = tableSymbols.size();
+ size_t id = tableSymbols.size();
return getNewSymbolName("table_", id);
}
};
@@ -232,6 +235,20 @@ class ExpressionParser {
parseConstInst(OpBuilder &builder,
std::enable_if_t<std::is_arithmetic_v<valueT>> * = nullptr);
+ /// Construct an operation with \p numOperands operands and a single result.
+ /// Each operand must have the same type. Suitable for e.g. binops, unary
+ /// ops, etc.
+ ///
+ /// \p opcode - The WASM opcode to build.
+ /// \p valueType - The operand and result type for the built instruction.
+ /// \p numOperands - The number of operands for the built operation.
+ ///
+ /// \returns The parsed instruction result, or failure.
+ template <typename opcode, typename valueType, unsigned int numOperands>
+ inline parsed_inst_t
+ buildNumericOp(OpBuilder &builder,
+ std::enable_if_t<std::is_arithmetic_v<valueType>> * = nullptr);
+
/// This function generates a dispatch tree to associate an opcode with a
/// parser. Parsers are registered by specialising the
/// `parseSpecificInstruction` function for the op code to handle.
@@ -286,10 +303,16 @@ class ExpressionParser {
return valueStack.pushResults(results, ¤tOpLoc.value());
}
+ /// The local.set and local.tee operations behave similarly and only differ
+ /// on their return value. This function factorizes the behavior of the two
+ /// operations in one place.
+ template <typename OpToCreate>
+ parsed_inst_t parseSetOrTee(OpBuilder &);
+
private:
std::optional<Location> currentOpLoc;
ParserHead &parser;
- [[maybe_unused]] WasmModuleSymbolTables const &symbols;
+ WasmModuleSymbolTables const &symbols;
locals_t locals;
ValueStack valueStack;
};
@@ -322,7 +345,7 @@ class ParserHead {
}
FailureOr<std::byte> consumeByte() {
- auto res = consumeNBytes(1);
+ FailureOr<StringRef> res = consumeNBytes(1);
if (failed(res))
return failure();
return std::byte{*res->bytes_begin()};
@@ -482,7 +505,7 @@ class ParserHead {
FileLineColLoc importLoc = getLocation();
FailureOr<std::byte> importType = consumeByte();
auto packager = [](auto parseResult) -> FailureOr<ImportDesc> {
- if (llvm::failed(parseResult))
+ if (failed(parseResult))
return failure();
return {*parseResult};
};
@@ -510,6 +533,60 @@ class ParserHead {
return eParser.parse(builder);
}
+ LogicalResult parseCodeFor(FuncOp func,
+ WasmModuleSymbolTables const &symbols) {
+ SmallVector<local_val_t> locals{};
+ // Populating locals with function argument
+ Block &block = func.getBody().front();
+ // Delete temporary return argument which was only created for IR validity
+ assert(func.getBody().getBlocks().size() == 1 &&
+ "Function should only have its default created block at this point");
+ assert(block.getOperations().size() == 1 &&
+ "Only the placeholder return op should be present at this point");
+ auto returnOp = cast<ReturnOp>(&block.back());
+ assert(returnOp);
+
+ FailureOr<uint32_t> codeSizeInBytes = parseUI32();
+ if (failed(codeSizeInBytes))
+ return failure();
+ FailureOr<StringRef> codeContent = consumeNBytes(*codeSizeInBytes);
+ if (failed(codeContent))
+ return failure();
+ auto name = StringAttr::get(func->getContext(),
+ locName.str() + "::" + func.getSymName());
+ auto cParser = ParserHead{*codeContent, name};
+ FailureOr<uint32_t> localVecSize = cParser.parseVectorSize();
+ if (failed(localVecSize))
+ return failure();
+ OpBuilder builder{&func.getBody().front().back()};
+ for (auto arg : block.getArguments())
+ locals.push_back(cast<TypedValue<LocalRefType>>(arg));
+ // Declare the local ops
+ uint32_t nVarVec = *localVecSize;
+ for (size_t i = 0; i < nVarVec; ++i) {
+ FileLineColLoc varLoc = cParser.getLocation();
+ FailureOr<uint32_t> nSubVar = cParser.parseUI32();
+ if (failed(nSubVar))
+ return failure();
+ FailureOr<Type> varT = cParser.parseValueType(func->getContext());
+ if (failed(varT))
+ return failure();
+ for (size_t j = 0; j < *nSubVar; ++j) {
+ auto local = builder.create<LocalOp>(varLoc, *varT);
+ locals.push_back(local.getResult());
+ }
+ }
+ parsed_inst_t res = cParser.parseExpression(builder, symbols, locals);
+ if (failed(res))
+ return failure();
+ if (!cParser.end())
+ return emitError(cParser.getLocation(),
+ "unparsed garbage remaining at end of code block");
+ builder.create<ReturnOp>(func->getLoc(), *res);
+ returnOp->erase();
+ return success();
+ }
+
bool end() const { return curHead().empty(); }
ParserHead copy() const { return *this; }
@@ -535,22 +612,20 @@ class ParserHead {
template <>
FailureOr<float> ParserHead::parseLiteral<float>() {
- auto bytes = consumeNBytes(4);
+ FailureOr<StringRef> bytes = consumeNBytes(4);
if (failed(bytes))
return failure();
- float result;
- std::memcpy(&result, bytes->bytes_begin(), 4);
- return result;
+ return llvm::support::endian::read<float>(bytes->bytes_begin(),
+ llvm::endianness::little);
}
template <>
FailureOr<double> ParserHead::parseLiteral<double>() {
- auto bytes = consumeNBytes(8);
+ FailureOr<StringRef> bytes = consumeNBytes(8);
if (failed(bytes))
return failure();
- double result;
- std::memcpy(&result, bytes->bytes_begin(), 8);
- return result;
+ return llvm::support::endian::read<double>(bytes->bytes_begin(),
+ llvm::endianness::little);
}
template <>
@@ -650,7 +725,7 @@ parsed_inst_t ValueStack::popOperands(TypeRange operandTypes, Location *opLoc) {
<< " Current stack size: " << values.size();
if (operandTypes.size() > values.size())
return emitError(*opLoc,
- "stack doesn't contain enough values. Trying to get ")
+ "stack doesn't contain enough values. trying to get ")
<< operandTypes.size() << " operands on a stack containing only "
<< values.size() << " values.";
size_t stackIdxOffset = values.size() - operandTypes.size();
@@ -660,7 +735,7 @@ parsed_inst_t ValueStack::popOperands(TypeRange operandTypes, Location *opLoc) {
Value operand = values[i + stackIdxOffset];
Type stackType = operand.getType();
if (stackType != operandTypes[i])
- return emitError(*opLoc, "invalid operand type on stack. Expecting ")
+ return emitError(*opLoc, "invalid operand type on stack. expecting ")
<< operandTypes[i] << ", value on stack is of type " << stackType
<< ".";
LDBG() << " POP: " << operand;
@@ -718,6 +793,70 @@ ExpressionParser::parse(OpBuilder &builder,
}
}
+template <>
+inline parsed_inst_t ExpressionParser::parseSpecificInstruction<
+ WasmBinaryEncoding::OpCode::localGet>(OpBuilder &builder) {
+ FailureOr<uint32_t> id = parser.parseLiteral<uint32_t>();
+ Location instLoc = *currentOpLoc;
+ if (failed(id))
+ return failure();
+ if (*id >= locals.size())
+ return emitError(instLoc, "invalid local index. function has ")
+ << locals.size() << " accessible locals, received index " << *id;
+ return {{builder.create<LocalGetOp>(instLoc, locals[*id]).getResult()}};
+}
+
+template <>
+inline parsed_inst_t ExpressionParser::parseSpecificInstruction<
+ WasmBinaryEncoding::OpCode::globalGet>(OpBuilder &builder) {
+ FailureOr<uint32_t> id = parser.parseLiteral<uint32_t>();
+ Location instLoc = *currentOpLoc;
+ if (failed(id))
+ return failure();
+ if (*id >= symbols.globalSymbols.size())
+ return emitError(instLoc, "invalid global index. function has ")
+ << symbols.globalSymbols.size()
+ << " accessible globals, received index " << *id;
+ GlobalSymbolRefContainer globalVar = symbols.globalSymbols[*id];
+ auto globalOp = builder.create<GlobalGetOp>(instLoc, globalVar.globalType,
+ globalVar.symbol);
+
+ return {{globalOp.getResult()}};
+}
+
+template <typename OpToCreate>
+parsed_inst_t ExpressionParser::parseSetOrTee(OpBuilder &builder) {
+ FailureOr<uint32_t> id = parser.parseLiteral<uint32_t>();
+ if (failed(id))
+ return failure();
+ if (*id >= locals.size())
+ return emitError(*currentOpLoc, "invalid local index. function has ")
+ << locals.size() << " accessible locals, received index " << *id;
+ if (valueStack.empty())
+ return emitError(
+ *currentOpLoc,
+ "invalid stack access, trying to access a value on an empty stack.");
+
+ parsed_inst_t poppedOp = popOperands(locals[*id].getType().getElementType());
+ if (failed(poppedOp))
+ return failure();
+ return {
+ builder.create<OpToCreate>(*currentOpLoc, locals[*id], poppedOp->front())
+ ->getResults()};
+}
+
+template <>
+inline parsed_inst_t ExpressionParser::parseSpecificInstruction<
+ WasmBinaryEncoding::OpCode::localSet>(OpBuilder &builder) {
+ return parseSetOrTee<LocalSetOp>(builder);
+}
+
+template <>
+inline parsed_inst_t ExpressionParser::parseSpecificInstruction<
+ WasmBinaryEncoding::OpCode::localTee>(OpBuilder &builder) {
+ return parseSetOrTee<LocalTeeOp>(builder);
+}
+
template <typename T>
inline Type buildLiteralType(OpBuilder &);
@@ -810,6 +949,94 @@ inline parsed_inst_t ExpressionParser::parseSpecificInstruction<
return parseConstInst<double>(builder);
}
+template <typename opcode, typename valueType, unsigned int numOperands>
+inline parsed_inst_t ExpressionParser::buildNumericOp(
+ OpBuilder &builder, std::enable_if_t<std::is_arithmetic_v<valueType>> *) {
+ auto ty = buildLiteralType<valueType>(builder);
+ LDBG() << "*** buildNumericOp: numOperands = " << numOperands
+ << ", type = " << ty << " ***";
+ auto tysToPop = SmallVector<Type, numOperands>();
+ tysToPop.resize(numOperands);
+ std::fill(tysToPop.begin(), tysToPop.end(), ty);
+ auto operands = popOperands(tysToPop);
+ if (failed(operands))
+ return failure();
+ auto op = builder.create<opcode>(*currentOpLoc, *operands).getResult();
+ LDBG() << "Built operation: " << op;
+ return {{op}};
+}
+
+// Convenience macro for generating numerical operations.
+#define BUILD_NUMERIC_OP(OP_NAME, N_ARGS, PREFIX, SUFFIX, TYPE) \
+ template <> \
+ inline parsed_inst_t ExpressionParser::parseSpecificInstruction< \
+ WasmBinaryEncoding::OpCode::PREFIX##SUFFIX>(OpBuilder & builder) { \
+ return buildNumericOp<OP_NAME, TYPE, N_ARGS>(builder); \
+ }
+
+// Macro to define binops that only support integer types.
+#define BUILD_NUMERIC_BINOP_INT(OP_NAME, PREFIX) \
+ BUILD_NUMERIC_OP(OP_NAME, 2, PREFIX, I32, int32_t) \
+ BUILD_NUMERIC_OP(OP_NAME, 2, PREFIX, I64, int64_t)
+
+// Macro to define binops that only support floating point types.
+#define BUILD_NUMERIC_BINOP_FP(OP_NAME, PREFIX) \
+ BUILD_NUMERIC_OP(OP_NAME, 2, PREFIX, F32, float) \
+ BUILD_NUMERIC_OP(OP_NAME, 2, PREFIX, F64, double)
+
+// Macro to define binops that support both floating point and integer types.
+#define BUILD_NUMERIC_BINOP_INTFP(OP_NAME, PREFIX) \
+ BUILD_NUMERIC_BINOP_INT(OP_NAME, PREFIX) \
+ BUILD_NUMERIC_BINOP_FP(OP_NAME, PREFIX)
+
+// Macro to implement unary ops that only support integers.
+#define BUILD_NUMERIC_UNARY_OP_INT(OP_NAME, PREFIX) \
+ BUILD_NUMERIC_OP(OP_NAME, 1, PREFIX, I32, int32_t) \
+ BUILD_NUMERIC_OP(OP_NAME, 1, PREFIX, I64, int64_t)
+
+// Macro to implement unary ops that support integer and floating point types.
+#define BUILD_NUMERIC_UNARY_OP_FP(OP_NAME, PREFIX) \
+ BUILD_NUMERIC_OP(OP_NAME, 1, PREFIX, F32, float) \
+ BUILD_NUMERIC_OP(OP_NAME, 1, PREFIX, F64, double)
+
+BUILD_NUMERIC_BINOP_FP(CopySignOp, copysign)
+BUILD_NUMERIC_BINOP_FP(DivOp, div)
+BUILD_NUMERIC_BINOP_FP(MaxOp, max)
+BUILD_NUMERIC_BINOP_FP(MinOp, min)
+BUILD_NUMERIC_BINOP_INT(AndOp, and)
+BUILD_NUMERIC_BINOP_INT(DivSIOp, divS)
+BUILD_NUMERIC_BINOP_INT(DivUIOp, divU)
+BUILD_NUMERIC_BINOP_INT(OrOp, or)
+BUILD_NUMERIC_BINOP_INT(RemSIOp, remS)
+BUILD_NUMERIC_BINOP_INT(RemUIOp, remU)
+BUILD_NUMERIC_BINOP_INT(RotlOp, rotl)
+BUILD_NUMERIC_BINOP_INT(RotrOp, rotr)
+BUILD_NUMERIC_BINOP_INT(ShLOp, shl)
+BUILD_NUMERIC_BINOP_INT(ShRSOp, shrS)
+BUILD_NUMERIC_BINOP_INT(ShRUOp, shrU)
+BUILD_NUMERIC_BINOP_INT(XOrOp, xor)
+BUILD_NUMERIC_BINOP_INTFP(AddOp, add)
+BUILD_NUMERIC_BINOP_INTFP(MulOp, mul)
+BUILD_NUMERIC_BINOP_INTFP(SubOp, sub)
+BUILD_NUMERIC_UNARY_OP_FP(AbsOp, abs)
+BUILD_NUMERIC_UNARY_OP_FP(CeilOp, ceil)
+BUILD_NUMERIC_UNARY_OP_FP(FloorOp, floor)
+BUILD_NUMERIC_UNARY_OP_FP(NegOp, neg)
+BUILD_NUMERIC_UNARY_OP_FP(SqrtOp, sqrt)
+BUILD_NUMERIC_UNARY_OP_FP(TruncOp, trunc)
+BUILD_NUMERIC_UNARY_OP_INT(ClzOp, clz)
+BUILD_NUMERIC_UNARY_OP_INT(CtzOp, ctz)
+BUILD_NUMERIC_UNARY_OP_INT(PopCntOp, popcnt)
+
+// Don't need these anymore so let's undef them.
+#undef BUILD_NUMERIC_BINOP_FP
+#undef BUILD_NUMERIC_BINOP_INT
+#undef BUILD_NUMERIC_BINOP_INTFP
+#undef BUILD_NUMERIC_UNARY_OP_FP
+#undef BUILD_NUMERIC_UNARY_OP_INT
+#undef BUILD_NUMERIC_OP
+#undef BUILD_NUMERIC_CAST_OP
+
class WasmBinaryParser {
private:
struct SectionRegistry {
@@ -907,7 +1134,7 @@ class WasmBinaryParser {
if (failed(nElemsParsed))
return failure();
uint32_t nElems = *nElemsParsed;
- LDBG() << "Starting to parse " << nElems << " items for section "
+ LDBG() << "starting to parse " << nElems << " items for section "
<< secName;
for (size_t i = 0; i < nElems; ++i) {
if (failed(parseSectionItem<section>(ph, i)))
@@ -1006,7 +1233,7 @@ class WasmBinaryParser {
return;
if (version->compare(expectedVersionString)) {
emitError(versionLoc,
- "unsupported Wasm version. Only version 1 is supported.");
+ "unsupported Wasm version. only version 1 is supported");
return;
}
LogicalResult fillRegistry = registry.populateFromBody(parser.copy());
@@ -1037,6 +1264,14 @@ class WasmBinaryParser {
if (failed(parsingMems))
return;
+ LogicalResult parsingGlobals = parseSection<WasmSectionType::GLOBAL>();
+ if (failed(parsingGlobals))
+ return;
+
+ LogicalResult parsingCode = parseSection<WasmSectionType::CODE>();
+ if (failed(parsingCode))
+ return;
+
LogicalResult parsingExports = parseSection<WasmSectionType::EXPORT>();
if (failed(parsingExports))
return;
@@ -1193,10 +1428,9 @@ WasmBinaryParser::parseSectionItem<WasmSectionType::FUNCTION>(ParserHead &ph,
auto funcOp =
FuncOp::create(builder, ...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/154452
More information about the Mlir-commits
mailing list