2727#include " emscripten-optimizer/istring.h"
2828#include " support/name.h"
2929#include " wasm-builder.h"
30+ #include " abi/js.h"
3031#include " ir/flat.h"
3132#include " ir/iteration.h"
3233#include " ir/memory-utils.h"
@@ -337,25 +338,30 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> {
337338 template <typename T>
338339 using BuilderFunc = std::function<T*(std::vector<Expression*>&, Type)>;
339340
341+ // Fixes up a call. If we performed fixups, returns the call; otherwise returns nullptr;
340342 template <typename T>
341- void visitGenericCall (T* curr, BuilderFunc<T> callBuilder) {
343+ T* visitGenericCall (T* curr, BuilderFunc<T> callBuilder) {
344+ bool fixed = false ;
342345 std::vector<Expression*> args;
343346 for (auto * e : curr->operands ) {
344347 args.push_back (e);
345348 if (hasOutParam (e)) {
346349 TempVar argHighBits = fetchOutParam (e);
347350 args.push_back (builder->makeGetLocal (argHighBits, i32 ));
351+ fixed = true ;
348352 }
349353 }
350354 if (curr->type != i64 ) {
351- replaceCurrent (callBuilder (args, curr->type ));
352- return ;
355+ auto * ret = callBuilder (args, curr->type );
356+ replaceCurrent (ret);
357+ return fixed ? ret : nullptr ;
353358 }
354359 TempVar lowBits = getTemp ();
355360 TempVar highBits = getTemp ();
361+ auto * call = callBuilder (args, i32 );
356362 SetLocal* doCall = builder->makeSetLocal (
357363 lowBits,
358- callBuilder (args, i32 )
364+ call
359365 );
360366 SetLocal* setHigh = builder->makeSetLocal (
361367 highBits,
@@ -365,14 +371,21 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> {
365371 Block* result = builder->blockify (doCall, setHigh, getLow);
366372 setOutParam (result, std::move (highBits));
367373 replaceCurrent (result);
374+ return call;
368375 }
369376 void visitCall (Call* curr) {
370- visitGenericCall<Call>(
377+ auto * fixedCall = visitGenericCall<Call>(
371378 curr,
372379 [&](std::vector<Expression*>& args, Type ty) {
373380 return builder->makeCall (curr->target , args, ty);
374381 }
375382 );
383+ // If this was to an import, we need to call the legal version. This assumes
384+ // that legalize-js-interface has been run before.
385+ if (fixedCall && getModule ()->getFunction (fixedCall->target )->imported ()) {
386+ fixedCall->target = std::string (" legalfunc$" ) + fixedCall->target .str ;
387+ return ;
388+ }
376389 }
377390
378391 void visitCallIndirect (CallIndirect* curr) {
@@ -635,51 +648,31 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> {
635648 // our f64 through memory at address 0
636649 TempVar highBits = getTemp ();
637650 Block *result = builder->blockify (
638- builder->makeStore ( 8 , 0 , 8 , makeGetTempMemory (), curr->value , f64 ),
651+ builder->makeCall (ABI::wasm2js::SCRATCH_STORE_F64, { curr->value }, none ),
639652 builder->makeSetLocal (
640653 highBits,
641- builder->makeLoad ( 4 , true , 4 , 4 , makeGetTempMemory () , i32 )
654+ builder->makeCall (ABI::wasm2js::SCRATCH_LOAD_I32, { builder-> makeConst ( Literal ( int32_t ( 1 ))) } , i32 )
642655 ),
643- builder->makeLoad ( 4 , true , 0 , 4 , makeGetTempMemory () , i32 )
656+ builder->makeCall (ABI::wasm2js::SCRATCH_LOAD_I32, { builder-> makeConst ( Literal ( int32_t ( 0 ))) } , i32 )
644657 );
645658 setOutParam (result, std::move (highBits));
646659 replaceCurrent (result);
647660 MemoryUtils::ensureExists (getModule ()->memory );
648- ensureTempMemoryGlobal ( );
661+ ABI::wasm2js::ensureScratchMemoryHelpers ( getModule () );
649662 }
650663
651664 void lowerReinterpretInt64 (Unary* curr) {
652665 // Assume that the wasm file assumes the address 0 is invalid and roundtrip
653666 // our i64 through memory at address 0
654667 TempVar highBits = fetchOutParam (curr->value );
655668 Block *result = builder->blockify (
656- builder->makeStore ( 4 , 0 , 4 , makeGetTempMemory () , curr->value , i32 ),
657- builder->makeStore ( 4 , 4 , 4 , makeGetTempMemory () , builder->makeGetLocal (highBits, i32 ), i32 ),
658- builder->makeLoad ( 8 , true , 0 , 8 , makeGetTempMemory () , f64 )
669+ builder->makeCall (ABI::wasm2js::SCRATCH_STORE_I32, { builder-> makeConst ( Literal ( int32_t ( 0 ))) , curr->value }, none ),
670+ builder->makeCall (ABI::wasm2js::SCRATCH_STORE_I32, { builder-> makeConst ( Literal ( int32_t ( 1 ))) , builder->makeGetLocal (highBits, i32 ) }, none ),
671+ builder->makeCall (ABI::wasm2js::SCRATCH_LOAD_F64, {} , f64 )
659672 );
660673 replaceCurrent (result);
661674 MemoryUtils::ensureExists (getModule ()->memory );
662- ensureTempMemoryGlobal ();
663- }
664-
665- Name tempMemory = " __tempMemory__" ;
666-
667- void ensureTempMemoryGlobal () {
668- // Ensure the existence of an imported global, __tempMemory__, which points to 8
669- // bytes of scratch memory we can use for roundtrip purposes.
670- if (!getModule ()->getGlobalOrNull (tempMemory)) {
671- auto global = make_unique<Global>();
672- global->name = tempMemory;
673- global->type = i32 ;
674- global->mutable_ = false ;
675- global->module = ENV;
676- global->base = tempMemory;
677- getModule ()->addGlobal (global.release ());
678- }
679- }
680-
681- Expression* makeGetTempMemory () {
682- return builder->makeGetGlobal (tempMemory, i32 );
675+ ABI::wasm2js::ensureScratchMemoryHelpers (getModule ());
683676 }
684677
685678 void lowerTruncFloatToInt (Unary *curr) {
0 commit comments