Skip to content

Commit 04c67d2

Browse files
committed
Add a ReFinalize helper, and use that to properly handle asm.js imports whose return value is polymorphic
1 parent 6a3b85d commit 04c67d2

7 files changed

+263
-65
lines changed

src/asm2wasm.h

+25-9
Original file line numberDiff line numberDiff line change
@@ -224,12 +224,6 @@ class Asm2WasmBuilder {
224224
// if we already saw this signature, verify it's the same (or else handle that)
225225
if (importedFunctionTypes.find(importName) != importedFunctionTypes.end()) {
226226
FunctionType* previous = importedFunctionTypes[importName].get();
227-
#if 0
228-
std::cout << "compare " << importName.str << "\nfirst: ";
229-
type.print(std::cout, 0);
230-
std::cout << "\nsecond: ";
231-
previous.print(std::cout, 0) << ".\n";
232-
#endif
233227
if (*type != *previous) {
234228
// merge it in. we'll add on extra 0 parameters for ones not actually used, and upgrade types to
235229
// double where there is a conflict (which is ok since in JS, double can contain everything
@@ -247,6 +241,8 @@ class Asm2WasmBuilder {
247241
}
248242
if (previous->result == none) {
249243
previous->result = type->result; // use a more concrete type
244+
} else if (previous->result != type->result) {
245+
previous->result = f64; // overloaded return type, make it a double
250246
}
251247
}
252248
} else {
@@ -752,7 +748,10 @@ void Asm2WasmBuilder::processAsm(Ref ast) {
752748

753749
void visitCall(Call* curr) {
754750
assert(getModule()->checkFunction(curr->target) ? true : (std::cerr << curr->target << '\n', false));
755-
curr->type = getModule()->getFunction(curr->target)->result;
751+
auto result = getModule()->getFunction(curr->target)->result;
752+
if (curr->type != result) {
753+
curr->type = result;
754+
}
756755
}
757756

758757
void visitCallImport(CallImport* curr) {
@@ -776,9 +775,25 @@ void Asm2WasmBuilder::processAsm(Ref ast) {
776775
}
777776
}
778777
}
779-
780-
curr->type = getModule()->getImport(curr->target)->functionType->result;
778+
auto importResult = getModule()->getImport(curr->target)->functionType->result;
779+
if (curr->type != importResult) {
780+
if (importResult == f64) {
781+
// we use a JS f64 value which is the most general, and convert to it
782+
switch (curr->type) {
783+
case i32: replaceCurrent(parent->builder.makeUnary(TruncSFloat64ToInt32, curr)); break;
784+
case f32: replaceCurrent(parent->builder.makeUnary(DemoteFloat64, curr)); break;
785+
case none: replaceCurrent(parent->builder.makeDrop(curr)); break;
786+
default: WASM_UNREACHABLE();
787+
}
788+
} else {
789+
assert(curr->type == none);
790+
// we don't want a return value here, but the import does provide one
791+
replaceCurrent(parent->builder.makeDrop(curr));
792+
}
793+
curr->type = importResult;
794+
}
781795
}
796+
782797
void visitCallIndirect(CallIndirect* curr) {
783798
// we already call into target = something + offset, where offset is a callImport with the name of the table. replace that with the table offset
784799
auto add = curr->target->cast<Binary>();
@@ -789,6 +804,7 @@ void Asm2WasmBuilder::processAsm(Ref ast) {
789804
};
790805
PassRunner passRunner(&wasm);
791806
passRunner.add<FinalizeCalls>(this);
807+
passRunner.add<ReFinalize>(); // FinalizeCalls changes call types, need to percolate
792808
passRunner.add<AutoDrop>(); // FinalizeCalls may cause us to require additional drops
793809
if (optimize) {
794810
passRunner.add("vacuum"); // autodrop can add some garbage

src/ast_utils.h

+28
Original file line numberDiff line numberDiff line change
@@ -821,6 +821,34 @@ struct AutoDrop : public WalkerPass<ExpressionStackWalker<AutoDrop, Visitor<Auto
821821
}
822822
};
823823

824+
// Finalizes a node
825+
826+
struct ReFinalize : public WalkerPass<PostWalker<ReFinalize, Visitor<ReFinalize>>> {
827+
void visitBlock(Block *curr) { curr->finalize(); }
828+
void visitIf(If *curr) { curr->finalize(); }
829+
void visitLoop(Loop *curr) { curr->finalize(); }
830+
void visitBreak(Break *curr) { curr->finalize(); }
831+
void visitSwitch(Switch *curr) { curr->finalize(); }
832+
void visitCall(Call *curr) { curr->finalize(); }
833+
void visitCallImport(CallImport *curr) { curr->finalize(); }
834+
void visitCallIndirect(CallIndirect *curr) { curr->finalize(); }
835+
void visitGetLocal(GetLocal *curr) { curr->finalize(); }
836+
void visitSetLocal(SetLocal *curr) { curr->finalize(); }
837+
void visitGetGlobal(GetGlobal *curr) { curr->finalize(); }
838+
void visitSetGlobal(SetGlobal *curr) { curr->finalize(); }
839+
void visitLoad(Load *curr) { curr->finalize(); }
840+
void visitStore(Store *curr) { curr->finalize(); }
841+
void visitConst(Const *curr) { curr->finalize(); }
842+
void visitUnary(Unary *curr) { curr->finalize(); }
843+
void visitBinary(Binary *curr) { curr->finalize(); }
844+
void visitSelect(Select *curr) { curr->finalize(); }
845+
void visitDrop(Drop *curr) { curr->finalize(); }
846+
void visitReturn(Return *curr) { curr->finalize(); }
847+
void visitHost(Host *curr) { curr->finalize(); }
848+
void visitNop(Nop *curr) { curr->finalize(); }
849+
void visitUnreachable(Unreachable *curr) { curr->finalize(); }
850+
};
851+
824852
} // namespace wasm
825853

826854
#endif // wasm_ast_utils_h

test/unit.asm.js

+6
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,12 @@ function asm(global, env, buffer) {
324324
return HEAP8[x | 0] | 0;
325325
}
326326

327+
function conditionalTypeFun() {
328+
var x = 0, y = +0;
329+
x = 1 ? abort(5) | 0 : 2;
330+
y = 3 ? +abort(7) : 4.5;
331+
}
332+
327333
function z() {
328334
}
329335
function w() {

test/unit.fromasm

+50-14
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,13 @@
77
(type $FUNCSIG$vf (func (param f32)))
88
(type $FUNCSIG$vi (func (param i32)))
99
(type $FUNCSIG$ii (func (param i32) (result i32)))
10-
(type $FUNCSIG$vd (func (param f64)))
10+
(type $FUNCSIG$dd (func (param f64) (result f64)))
1111
(import $t global "global" "NaN" f64)
1212
(import $u global "global" "Infinity" f64)
1313
(import $tempDoublePtr global "env" "tempDoublePtr" i32)
1414
(import $n global "env" "gb" i32)
1515
(import $setTempRet0 "env" "setTempRet0" (param i32) (result i32))
16-
(import $abort "env" "abort" (param f64))
16+
(import $abort "env" "abort" (param f64) (result f64))
1717
(import $print "env" "print" (param i32))
1818
(import $h "env" "h" (param i32))
1919
(import $f64-to-int "asm2wasm" "f64-to-int" (param f64) (result i32))
@@ -319,23 +319,33 @@
319319
(nop)
320320
)
321321
(func $aborts
322-
(call_import $abort
323-
(f64.const 0)
322+
(drop
323+
(call_import $abort
324+
(f64.const 0)
325+
)
324326
)
325-
(call_import $abort
326-
(f64.convert_s/i32
327-
(i32.const 55)
327+
(drop
328+
(call_import $abort
329+
(f64.convert_s/i32
330+
(i32.const 55)
331+
)
328332
)
329333
)
330-
(call_import $abort
331-
(f64.const 0)
334+
(drop
335+
(call_import $abort
336+
(f64.const 0)
337+
)
332338
)
333-
(call_import $abort
334-
(f64.const 12.34)
339+
(drop
340+
(call_import $abort
341+
(f64.const 12.34)
342+
)
335343
)
336-
(call_import $abort
337-
(f64.promote/f32
338-
(f32.const 56.779998779296875)
344+
(drop
345+
(call_import $abort
346+
(f64.promote/f32
347+
(f32.const 56.779998779296875)
348+
)
339349
)
340350
)
341351
)
@@ -580,4 +590,30 @@
580590
(get_local $0)
581591
)
582592
)
593+
(func $conditionalTypeFun
594+
(drop
595+
(if
596+
(i32.const 1)
597+
(i32.trunc_s/f64
598+
(call_import $abort
599+
(f64.convert_s/i32
600+
(i32.const 5)
601+
)
602+
)
603+
)
604+
(i32.const 2)
605+
)
606+
)
607+
(drop
608+
(if
609+
(i32.const 3)
610+
(call_import $abort
611+
(f64.convert_s/i32
612+
(i32.const 7)
613+
)
614+
)
615+
(f64.const 4.5)
616+
)
617+
)
618+
)
583619
)

test/unit.fromasm.imprecise

+50-14
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@
44
(type $FUNCSIG$vf (func (param f32)))
55
(type $FUNCSIG$vi (func (param i32)))
66
(type $FUNCSIG$ii (func (param i32) (result i32)))
7-
(type $FUNCSIG$vd (func (param f64)))
7+
(type $FUNCSIG$dd (func (param f64) (result f64)))
88
(import $t global "global" "NaN" f64)
99
(import $u global "global" "Infinity" f64)
1010
(import $tempDoublePtr global "env" "tempDoublePtr" i32)
1111
(import $n global "env" "gb" i32)
1212
(import $setTempRet0 "env" "setTempRet0" (param i32) (result i32))
13-
(import $abort "env" "abort" (param f64))
13+
(import $abort "env" "abort" (param f64) (result f64))
1414
(import $print "env" "print" (param i32))
1515
(import $h "env" "h" (param i32))
1616
(import $f64-rem "asm2wasm" "f64-rem" (param f64 f64) (result f64))
@@ -300,23 +300,33 @@
300300
(nop)
301301
)
302302
(func $aborts
303-
(call_import $abort
304-
(f64.const 0)
303+
(drop
304+
(call_import $abort
305+
(f64.const 0)
306+
)
305307
)
306-
(call_import $abort
307-
(f64.convert_s/i32
308-
(i32.const 55)
308+
(drop
309+
(call_import $abort
310+
(f64.convert_s/i32
311+
(i32.const 55)
312+
)
309313
)
310314
)
311-
(call_import $abort
312-
(f64.const 0)
315+
(drop
316+
(call_import $abort
317+
(f64.const 0)
318+
)
313319
)
314-
(call_import $abort
315-
(f64.const 12.34)
320+
(drop
321+
(call_import $abort
322+
(f64.const 12.34)
323+
)
316324
)
317-
(call_import $abort
318-
(f64.promote/f32
319-
(f32.const 56.779998779296875)
325+
(drop
326+
(call_import $abort
327+
(f64.promote/f32
328+
(f32.const 56.779998779296875)
329+
)
320330
)
321331
)
322332
)
@@ -561,4 +571,30 @@
561571
(get_local $0)
562572
)
563573
)
574+
(func $conditionalTypeFun
575+
(drop
576+
(if
577+
(i32.const 1)
578+
(i32.trunc_s/f64
579+
(call_import $abort
580+
(f64.convert_s/i32
581+
(i32.const 5)
582+
)
583+
)
584+
)
585+
(i32.const 2)
586+
)
587+
)
588+
(drop
589+
(if
590+
(i32.const 3)
591+
(call_import $abort
592+
(f64.convert_s/i32
593+
(i32.const 7)
594+
)
595+
)
596+
(f64.const 4.5)
597+
)
598+
)
599+
)
564600
)

0 commit comments

Comments
 (0)