2023-10-03 11:14:36 +08:00
"use strict" ;
Object . defineProperty ( exports , "__esModule" , {
value : true
} ) ;
exports . transform = transform ;
var _index = require ( "../../index" ) ;
var _astModuleToModuleContext = require ( "../ast-module-to-module-context" ) ;
function _typeof ( obj ) { "@babel/helpers - typeof" ; if ( typeof Symbol === "function" && typeof Symbol . iterator === "symbol" ) { _typeof = function _typeof ( obj ) { return typeof obj ; } ; } else { _typeof = function _typeof ( obj ) { return obj && typeof Symbol === "function" && obj . constructor === Symbol && obj !== Symbol . prototype ? "symbol" : typeof obj ; } ; } return _typeof ( obj ) ; }
function _slicedToArray ( arr , i ) { return _arrayWithHoles ( arr ) || _iterableToArrayLimit ( arr , i ) || _unsupportedIterableToArray ( arr , i ) || _nonIterableRest ( ) ; }
function _nonIterableRest ( ) { throw new TypeError ( "Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method." ) ; }
function _unsupportedIterableToArray ( o , minLen ) { if ( ! o ) return ; if ( typeof o === "string" ) return _arrayLikeToArray ( o , minLen ) ; var n = Object . prototype . toString . call ( o ) . slice ( 8 , - 1 ) ; if ( n === "Object" && o . constructor ) n = o . constructor . name ; if ( n === "Map" || n === "Set" ) return Array . from ( o ) ; if ( n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/ . test ( n ) ) return _arrayLikeToArray ( o , minLen ) ; }
function _arrayLikeToArray ( arr , len ) { if ( len == null || len > arr . length ) len = arr . length ; for ( var i = 0 , arr2 = new Array ( len ) ; i < len ; i ++ ) { arr2 [ i ] = arr [ i ] ; } return arr2 ; }
function _iterableToArrayLimit ( arr , i ) { var _i = arr == null ? null : typeof Symbol !== "undefined" && arr [ Symbol . iterator ] || arr [ "@@iterator" ] ; if ( _i == null ) return ; var _arr = [ ] ; var _n = true ; var _d = false ; var _s , _e ; try { for ( _i = _i . call ( arr ) ; ! ( _n = ( _s = _i . next ( ) ) . done ) ; _n = true ) { _arr . push ( _s . value ) ; if ( i && _arr . length === i ) break ; } } catch ( err ) { _d = true ; _e = err ; } finally { try { if ( ! _n && _i [ "return" ] != null ) _i [ "return" ] ( ) ; } finally { if ( _d ) throw _e ; } } return _arr ; }
function _arrayWithHoles ( arr ) { if ( Array . isArray ( arr ) ) return arr ; }
// FIXME(sven): do the same with all block instructions, must be more generic here
function newUnexpectedFunction ( i ) {
return new Error ( "unknown function at offset: " + i ) ;
}
function transform ( ast ) {
var module = null ;
( 0 , _index . traverse ) ( ast , {
Module : function ( _Module ) {
function Module ( _x ) {
return _Module . apply ( this , arguments ) ;
}
Module . toString = function ( ) {
return _Module . toString ( ) ;
} ;
return Module ;
} ( function ( path ) {
module = path . node ;
} )
} ) ;
if ( module == null ) {
throw new Error ( "Module not foudn in program" ) ;
}
var moduleContext = ( 0 , _astModuleToModuleContext . moduleContextFromModuleAST ) ( module ) ; // Transform the actual instruction in function bodies
( 0 , _index . traverse ) ( ast , {
Func : function ( _Func ) {
function Func ( _x2 ) {
return _Func . apply ( this , arguments ) ;
}
Func . toString = function ( ) {
return _Func . toString ( ) ;
} ;
return Func ;
} ( function ( path ) {
transformFuncPath ( path , moduleContext ) ;
} ) ,
Start : function ( _Start ) {
function Start ( _x3 ) {
return _Start . apply ( this , arguments ) ;
}
Start . toString = function ( ) {
return _Start . toString ( ) ;
} ;
return Start ;
} ( function ( path ) {
var index = path . node . index ;
if ( ( 0 , _index . isIdentifier ) ( index ) === true ) {
var offsetInModule = moduleContext . getFunctionOffsetByIdentifier ( index . value ) ;
if ( typeof offsetInModule === "undefined" ) {
throw newUnexpectedFunction ( index . value ) ;
} // Replace the index Identifier
// $FlowIgnore: reference?
path . node . index = ( 0 , _index . numberLiteralFromRaw ) ( offsetInModule ) ;
}
} )
} ) ;
}
function transformFuncPath ( funcPath , moduleContext ) {
var funcNode = funcPath . node ;
var signature = funcNode . signature ;
if ( signature . type !== "Signature" ) {
throw new Error ( "Function signatures must be denormalised before execution" ) ;
}
var params = signature . params ; // Add func locals in the context
params . forEach ( function ( p ) {
return moduleContext . addLocal ( p . valtype ) ;
} ) ;
( 0 , _index . traverse ) ( funcNode , {
Instr : function ( _Instr ) {
function Instr ( _x4 ) {
return _Instr . apply ( this , arguments ) ;
}
Instr . toString = function ( ) {
return _Instr . toString ( ) ;
} ;
return Instr ;
} ( function ( instrPath ) {
var instrNode = instrPath . node ;
/ * *
* Local access
* /
if ( instrNode . id === "get_local" || instrNode . id === "set_local" || instrNode . id === "tee_local" ) {
var _instrNode$args = _slicedToArray ( instrNode . args , 1 ) ,
firstArg = _instrNode$args [ 0 ] ;
if ( firstArg . type === "Identifier" ) {
var offsetInParams = params . findIndex ( function ( _ref ) {
var id = _ref . id ;
return id === firstArg . value ;
} ) ;
if ( offsetInParams === - 1 ) {
throw new Error ( "" . concat ( firstArg . value , " not found in " ) . concat ( instrNode . id , ": not declared in func params" ) ) ;
} // Replace the Identifer node by our new NumberLiteral node
instrNode . args [ 0 ] = ( 0 , _index . numberLiteralFromRaw ) ( offsetInParams ) ;
}
}
/ * *
* Global access
* /
if ( instrNode . id === "get_global" || instrNode . id === "set_global" ) {
var _instrNode$args2 = _slicedToArray ( instrNode . args , 1 ) ,
_firstArg = _instrNode$args2 [ 0 ] ;
if ( ( 0 , _index . isIdentifier ) ( _firstArg ) === true ) {
var globalOffset = moduleContext . getGlobalOffsetByIdentifier ( // $FlowIgnore: reference?
_firstArg . value ) ;
if ( typeof globalOffset === "undefined" ) {
// $FlowIgnore: reference?
throw new Error ( "global " . concat ( _firstArg . value , " not found in module" ) ) ;
} // Replace the Identifer node by our new NumberLiteral node
instrNode . args [ 0 ] = ( 0 , _index . numberLiteralFromRaw ) ( globalOffset ) ;
}
}
/ * *
* Labels lookup
* /
if ( instrNode . id === "br" ) {
var _instrNode$args3 = _slicedToArray ( instrNode . args , 1 ) ,
_firstArg2 = _instrNode$args3 [ 0 ] ;
if ( ( 0 , _index . isIdentifier ) ( _firstArg2 ) === true ) {
// if the labels is not found it is going to be replaced with -1
// which is invalid.
var relativeBlockCount = - 1 ; // $FlowIgnore: reference?
instrPath . findParent ( function ( _ref2 ) {
var node = _ref2 . node ;
if ( ( 0 , _index . isBlock ) ( node ) ) {
relativeBlockCount ++ ; // $FlowIgnore: reference?
var name = node . label || node . name ;
if ( _typeof ( name ) === "object" ) {
// $FlowIgnore: isIdentifier ensures that
if ( name . value === _firstArg2 . value ) {
// Found it
return false ;
}
}
}
if ( ( 0 , _index . isFunc ) ( node ) ) {
return false ;
}
} ) ; // Replace the Identifer node by our new NumberLiteral node
instrNode . args [ 0 ] = ( 0 , _index . numberLiteralFromRaw ) ( relativeBlockCount ) ;
}
}
} ) ,
/ * *
* Func lookup
* /
CallInstruction : function ( _CallInstruction ) {
function CallInstruction ( _x5 ) {
return _CallInstruction . apply ( this , arguments ) ;
}
CallInstruction . toString = function ( ) {
return _CallInstruction . toString ( ) ;
} ;
return CallInstruction ;
} ( function ( _ref3 ) {
var node = _ref3 . node ;
var index = node . index ;
if ( ( 0 , _index . isIdentifier ) ( index ) === true ) {
var offsetInModule = moduleContext . getFunctionOffsetByIdentifier ( index . value ) ;
if ( typeof offsetInModule === "undefined" ) {
throw newUnexpectedFunction ( index . value ) ;
} // Replace the index Identifier
// $FlowIgnore: reference?
node . index = ( 0 , _index . numberLiteralFromRaw ) ( offsetInModule ) ;
}
} )
} ) ;
2023-09-25 15:58:56 +08:00
}