diff options
-rw-r--r-- | CHANGELOG.md | 2 | ||||
-rw-r--r-- | src/passes/FuncCastEmulation.cpp | 34 | ||||
-rw-r--r-- | test/passes/fpcast-emu_pass-arg=max-func-params@5.txt | 43 | ||||
-rw-r--r-- | test/passes/fpcast-emu_pass-arg=max-func-params@5.wast | 14 |
4 files changed, 77 insertions, 16 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 1d6edfac3..27a097a76 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,8 @@ Current Trunk - Remove old/broken SpollPointers pass. This pass: Spills values that might be pointers to the C stack. This allows Boehm-style GC to see them properly. This can be revived if needed from git history (#3261). +- Make `NUM_PARAMS` in `FuncCastEmulation` a runtime configuration option named + `max-func-params`. This defaults to the original value of 16. v98 --- diff --git a/src/passes/FuncCastEmulation.cpp b/src/passes/FuncCastEmulation.cpp index ba6d1d583..9d232c9eb 100644 --- a/src/passes/FuncCastEmulation.cpp +++ b/src/passes/FuncCastEmulation.cpp @@ -28,6 +28,8 @@ // params must be identical, i.e., the "ABI" must match. // +#include <string> + #include <ir/literal-utils.h> #include <pass.h> #include <wasm-builder.h> @@ -35,11 +37,6 @@ namespace wasm { -// This should be enough for everybody. (As described above, we need this -// to match when dynamically linking, and also dynamic linking is why we -// can't just detect this automatically in the module we see.) -static const int NUM_PARAMS = 16; - // Converts a value to the ABI type of i64. static Expression* toABI(Expression* value, Module* module) { Builder builder(*module); @@ -133,20 +130,23 @@ struct ParallelFuncCastEmulation : public WalkerPass<PostWalker<ParallelFuncCastEmulation>> { bool isFunctionParallel() override { return true; } - Pass* create() override { return new ParallelFuncCastEmulation(ABIType); } + Pass* create() override { + return new ParallelFuncCastEmulation(ABIType, numParams); + } - ParallelFuncCastEmulation(Signature ABIType) : ABIType(ABIType) {} + ParallelFuncCastEmulation(Signature ABIType, Index numParams) + : ABIType(ABIType), numParams(numParams) {} void visitCallIndirect(CallIndirect* curr) { - if (curr->operands.size() > NUM_PARAMS) { - Fatal() << "FuncCastEmulation::NUM_PARAMS needs to be at least " + if (curr->operands.size() > numParams) { + Fatal() << "max-func-params needs to be at least " << curr->operands.size(); } for (Expression*& operand : curr->operands) { operand = toABI(operand, getModule()); } // Add extra operands as needed. - while (curr->operands.size() < NUM_PARAMS) { + while (curr->operands.size() < numParams) { curr->operands.push_back(LiteralUtils::makeZero(Type::i64, *getModule())); } // Set the new types @@ -161,20 +161,22 @@ struct ParallelFuncCastEmulation private: // The signature of a call with the right params and return Signature ABIType; + Index numParams; }; struct FuncCastEmulation : public Pass { void run(PassRunner* runner, Module* module) override { + Index numParams = + std::stoul(runner->options.getArgumentOrDefault("max-func-params", "16")); // we just need the one ABI function type for all indirect calls - Signature ABIType(Type(std::vector<Type>(NUM_PARAMS, Type::i64)), - Type::i64); + Signature ABIType(Type(std::vector<Type>(numParams, Type::i64)), Type::i64); // Add a thunk for each function in the table, and do the call through it. std::unordered_map<Name, Name> funcThunks; for (auto& segment : module->table.segments) { for (auto& name : segment.data) { auto iter = funcThunks.find(name); if (iter == funcThunks.end()) { - auto thunk = makeThunk(name, module); + auto thunk = makeThunk(name, module, numParams); funcThunks[name] = thunk; name = thunk; } else { @@ -183,12 +185,12 @@ struct FuncCastEmulation : public Pass { } } // update call_indirects - ParallelFuncCastEmulation(ABIType).run(runner, module); + ParallelFuncCastEmulation(ABIType, numParams).run(runner, module); } private: // Creates a thunk for a function, casting args and return value as needed. - Name makeThunk(Name name, Module* module) { + Name makeThunk(Name name, Module* module, Index numParams) { Name thunk = std::string("byn$fpcast-emu$") + name.str; if (module->getFunctionOrNull(thunk)) { Fatal() << "FuncCastEmulation::makeThunk seems a thunk name already in " @@ -206,7 +208,7 @@ private: } auto* call = builder.makeCall(name, callOperands, type); std::vector<Type> thunkParams; - for (Index i = 0; i < NUM_PARAMS; i++) { + for (Index i = 0; i < numParams; i++) { thunkParams.push_back(Type::i64); } auto thunkFunc = diff --git a/test/passes/fpcast-emu_pass-arg=max-func-params@5.txt b/test/passes/fpcast-emu_pass-arg=max-func-params@5.txt new file mode 100644 index 000000000..4382aaca0 --- /dev/null +++ b/test/passes/fpcast-emu_pass-arg=max-func-params@5.txt @@ -0,0 +1,43 @@ +(module + (type $i64_i64_i64_i64_i64_=>_i64 (func (param i64 i64 i64 i64 i64) (result i64))) + (type $i32_i64_f32_f64_=>_none (func (param i32 i64 f32 f64))) + (table $0 10 10 funcref) + (elem (i32.const 0) $byn$fpcast-emu$a) + (func $a (param $x i32) (param $y i64) (param $z f32) (param $w f64) + (drop + (call_indirect (type $i64_i64_i64_i64_i64_=>_i64) + (i64.extend_i32_u + (i32.const 1) + ) + (i64.const 2) + (i64.extend_i32_u + (i32.reinterpret_f32 + (f32.const 3) + ) + ) + (i64.reinterpret_f64 + (f64.const 4) + ) + (i64.const 0) + (i32.const 1337) + ) + ) + ) + (func $byn$fpcast-emu$a (param $0 i64) (param $1 i64) (param $2 i64) (param $3 i64) (param $4 i64) (result i64) + (call $a + (i32.wrap_i64 + (local.get $0) + ) + (local.get $1) + (f32.reinterpret_i32 + (i32.wrap_i64 + (local.get $2) + ) + ) + (f64.reinterpret_i64 + (local.get $3) + ) + ) + (i64.const 0) + ) +) diff --git a/test/passes/fpcast-emu_pass-arg=max-func-params@5.wast b/test/passes/fpcast-emu_pass-arg=max-func-params@5.wast new file mode 100644 index 000000000..b1b0369c4 --- /dev/null +++ b/test/passes/fpcast-emu_pass-arg=max-func-params@5.wast @@ -0,0 +1,14 @@ +(module + (type $vijfd (func (param i32) (param i64) (param f32) (param f64))) + (table 10 10 funcref) + (elem (i32.const 0) $a) + (func $a (param $x i32) (param $y i64) (param $z f32) (param $w f64) + (call_indirect (type $vijfd) + (i32.const 1) + (i64.const 2) + (f32.const 3) + (f64.const 4) + (i32.const 1337) + ) + ) +) |