Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 30 additions & 18 deletions src/compiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7079,36 +7079,48 @@ export class Compiler extends DiagnosticEmitter {
}
}

let allTrivial = (getSideEffects(functionArg, module.ref) & SideEffects.WritesGlobal) == 0;
if(operands && allTrivial) {
for(let i = 0; i < numOperands; ++i) {
if(!module.isTrivialExpression(operands[i])){
allTrivial = false;
break;
}
}
}

let stmts = new Array<ExpressionRef>();
let sizeTypeRef = this.options.sizeTypeRef;

if(!allTrivial){
let functionArgLocal = this.currentFlow.getTempLocal(this.options.usizeType);
let functionArgSetExpr = module.local_set(functionArgLocal.index, functionArg, true);
stmts.push(functionArgSetExpr);
functionArg = module.local_get(functionArgLocal.index, sizeTypeRef);
}

// We might be calling a varargs stub here, even if all operands have been
// provided, so we must set `argumentsLength` in any case. Inject setting it
// into the index argument, which becomes executed last after any operands.
let argumentsLength = this.ensureArgumentsLength();
let sizeTypeRef = this.options.sizeTypeRef;
if (getSideEffects(functionArg, module.ref) & SideEffects.WritesGlobal) {
let flow = this.currentFlow;
let temp = flow.getTempLocal(this.options.usizeType);
let tempIndex = temp.index;
functionArg = module.block(null, [
module.local_set(tempIndex, functionArg, true), // Function
module.global_set(argumentsLength, module.i32(numArguments)),
module.local_get(tempIndex, sizeTypeRef)
], sizeTypeRef);
} else { // simplify
functionArg = module.block(null, [
module.global_set(argumentsLength, module.i32(numArguments)),
functionArg
], sizeTypeRef);
}


let functionArgWithVararg = module.block(null, [
module.global_set(argumentsLength, module.i32(numArguments)),
functionArg
], sizeTypeRef);

if (operands) this.operandsTostack(signature, operands);
let expr = module.call_indirect(
null, // TODO: handle multiple tables
module.load(4, false, functionArg, TypeRef.I32), // ._index
module.load(4, false, functionArgWithVararg, TypeRef.I32), // ._index
operands,
signature.paramRefs,
signature.resultRefs
);
this.currentType = returnType;
return expr;
stmts.push(expr);
return module.flatten(stmts, returnType.toRef());
}

private compileCommaExpression(
Expand Down
11 changes: 9 additions & 2 deletions src/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2901,6 +2901,13 @@ export class Module {

/** Makes a copy of a trivial expression (doesn't contain subexpressions). Returns `0` if non-trivial. */
tryCopyTrivialExpression(expr: ExpressionRef): ExpressionRef {
if (this.isTrivialExpression(expr)) {
return this.copyExpression(expr);
}
return 0;
}

isTrivialExpression(expr: ExpressionRef): bool {
switch (binaryen._BinaryenExpressionGetId(expr)) {
case ExpressionId.LocalGet:
case ExpressionId.GlobalGet:
Expand All @@ -2909,9 +2916,9 @@ export class Module {
case ExpressionId.Nop:
case ExpressionId.Unreachable:
case ExpressionId.DataDrop:
case ExpressionId.RefNull: return this.copyExpression(expr);
case ExpressionId.RefNull: return true;
}
return 0;
return false;
}

/** Makes a copy of any expression including all subexpressions. */
Expand Down
103 changes: 58 additions & 45 deletions tests/compiler/call-rest.debug.wat
Original file line number Diff line number Diff line change
Expand Up @@ -3403,14 +3403,19 @@
(local $7 i32)
(local $8 i32)
(local $9 i32)
(local $10 i32)
(local $11 i32)
global.get $~lib/memory/__stack_pointer
i32.const 8
i32.const 16
i32.sub
global.set $~lib/memory/__stack_pointer
call $~stack_check
global.get $~lib/memory/__stack_pointer
i64.const 0
i64.store
global.get $~lib/memory/__stack_pointer
i64.const 0
i64.store offset=8
memory.size
i32.const 16
i32.shl
Expand Down Expand Up @@ -3469,11 +3474,11 @@
i32.const 4
i32.const 560
call $~lib/rt/__newArray
local.set $9
local.set $11
global.get $~lib/memory/__stack_pointer
local.get $9
local.get $11
i32.store
local.get $9
local.get $11
call $call-rest/fn
i32.const 6
i32.eq
Expand All @@ -3493,11 +3498,11 @@
i32.const 4
i32.const 592
call $~lib/rt/__newArray
local.set $9
local.set $11
global.get $~lib/memory/__stack_pointer
local.get $9
local.get $11
i32.store
local.get $9
local.get $11
call $call-rest/fn
i32.const 15
i32.eq
Expand Down Expand Up @@ -3548,21 +3553,25 @@
call $~lib/builtins/abort
unreachable
end
global.get $~lib/memory/__stack_pointer
global.get $call-rest/indirect
local.tee $3
i32.store offset=4
i32.const 1
i32.const 2
i32.const 1
i32.const 2
i32.const 4
i32.const 656
call $~lib/rt/__newArray
local.set $9
local.set $11
global.get $~lib/memory/__stack_pointer
local.get $9
local.get $11
i32.store
local.get $9
local.get $11
i32.const 3
global.set $~argumentsLength
global.get $call-rest/indirect
local.get $3
i32.load
call_indirect (type $3)
i32.const 6
Expand All @@ -3576,21 +3585,25 @@
call $~lib/builtins/abort
unreachable
end
global.get $~lib/memory/__stack_pointer
global.get $call-rest/indirect
local.tee $5
i32.store offset=8
i32.const 1
i32.const 2
i32.const 3
i32.const 2
i32.const 4
i32.const 688
call $~lib/rt/__newArray
local.set $9
local.set $11
global.get $~lib/memory/__stack_pointer
local.get $9
local.get $11
i32.store
local.get $9
local.get $11
i32.const 3
global.set $~argumentsLength
global.get $call-rest/indirect
local.get $5
i32.load
call_indirect (type $3)
i32.const 15
Expand All @@ -3611,11 +3624,11 @@
global.set $~argumentsLength
i32.const 0
call $call-rest/Foo#constructor@varargs
local.set $9
local.set $11
global.get $~lib/memory/__stack_pointer
local.get $9
local.get $11
i32.store
local.get $9
local.get $11
call $call-rest/Foo#sum
i32.const 1
i32.eq
Expand All @@ -3635,11 +3648,11 @@
global.set $~argumentsLength
i32.const 0
call $call-rest/Foo#constructor@varargs
local.set $9
local.set $11
global.get $~lib/memory/__stack_pointer
local.get $9
local.get $11
i32.store
local.get $9
local.get $11
call $call-rest/Foo#sum
i32.const 3
i32.eq
Expand All @@ -3660,17 +3673,17 @@
i32.const 4
i32.const 800
call $~lib/rt/__newArray
local.set $9
local.set $11
global.get $~lib/memory/__stack_pointer
local.get $9
i32.store offset=4
local.get $9
local.get $11
i32.store offset=12
local.get $11
call $call-rest/Foo#constructor
local.set $9
local.set $11
global.get $~lib/memory/__stack_pointer
local.get $9
local.get $11
i32.store
local.get $9
local.get $11
call $call-rest/Foo#sum
i32.const 6
i32.eq
Expand All @@ -3691,17 +3704,17 @@
i32.const 4
i32.const 832
call $~lib/rt/__newArray
local.set $9
local.set $11
global.get $~lib/memory/__stack_pointer
local.get $9
i32.store offset=4
local.get $9
local.get $11
i32.store offset=12
local.get $11
call $call-rest/Foo#constructor
local.set $9
local.set $11
global.get $~lib/memory/__stack_pointer
local.get $9
local.get $11
i32.store
local.get $9
local.get $11
call $call-rest/Foo#sum
i32.const 15
i32.eq
Expand Down Expand Up @@ -3734,11 +3747,11 @@
i32.const 4
i32.const 896
call $~lib/rt/__newArray
local.set $9
local.set $11
global.get $~lib/memory/__stack_pointer
local.get $9
local.get $11
i32.store
local.get $9
local.get $11
call $call-rest/count<i32>
i32.const 1
i32.eq
Expand All @@ -3756,11 +3769,11 @@
i32.const 4
i32.const 928
call $~lib/rt/__newArray
local.set $9
local.set $11
global.get $~lib/memory/__stack_pointer
local.get $9
local.get $11
i32.store
local.get $9
local.get $11
call $call-rest/count<i32>
i32.const 3
i32.eq
Expand All @@ -3778,11 +3791,11 @@
i32.const 8
i32.const 1056
call $~lib/rt/__newArray
local.set $9
local.set $11
global.get $~lib/memory/__stack_pointer
local.get $9
local.get $11
i32.store
local.get $9
local.get $11
call $call-rest/count<~lib/string/String>
i32.const 3
i32.eq
Expand All @@ -3796,7 +3809,7 @@
unreachable
end
global.get $~lib/memory/__stack_pointer
i32.const 8
i32.const 16
i32.add
global.set $~lib/memory/__stack_pointer
)
Expand Down
Loading
Loading