@@ -1261,7 +1261,9 @@ public let WasmCodeGenerators: [CodeGenerator] = [
12611261 let function = b. currentWasmModule. currentWasmFunction
12621262 let loopCtr = function. consti32 ( 10 )
12631263 b. runtimeData. push ( " loopCounter " , loopCtr)
1264- b. emit ( WasmBeginLoop ( with: [ ] => [ ] ) )
1264+ let signature = b. wasmDefineAdHocSignatureType ( signature: [ ] => [ ] )
1265+ b. runtimeData. push ( " loopSignature " , signature)
1266+ b. emit ( WasmBeginLoop ( with: [ ] => [ ] ) , withInputs: [ signature] )
12651267 // Increase loop counter.
12661268 let result = function. wasmi32BinOp (
12671269 loopCtr, function. consti32 ( 1 ) , binOpKind: . Sub)
@@ -1275,38 +1277,59 @@ public let WasmCodeGenerators: [CodeGenerator] = [
12751277 let loopCtr = b. runtimeData. pop ( " loopCounter " )
12761278 // Backedge of loop, we continue if it is not equal to zero.
12771279 let isNotZero = function. wasmi32CompareOp ( loopCtr, function. consti32 ( 0 ) , using: . Ne)
1278- b. emit ( WasmEndLoop ( outputTypes : [ ] ) )
1280+ b. emit ( WasmEndLoop ( outputCount : 0 ) , withInputs : [ b . runtimeData . pop ( " loopSignature " ) ] )
12791281 } ,
12801282 ] ) ,
12811283
1282- CodeGenerator ( " WasmLoopWithSignatureGenerator " , inContext: . single( . wasmFunction) ) {
1283- b in
1284- let function = b. currentWasmModule. currentWasmFunction
1285- // Count upwards here to make it slightly more different from the other loop generator.
1286- // Also, instead of using reassign, this generator uses the signature to pass and update the loop counter.
1287- let randomArgs = b. randomWasmBlockArguments ( upTo: 5 )
1288- let randomArgTypes = randomArgs. map { b. type ( of: $0) }
1289- let args = [ function. consti32 ( 0 ) ] + randomArgs
1290- let parameters = args. map ( b. type)
1291- let outputTypes = b. randomWasmBlockOutputTypes ( upTo: 5 )
1292- // Note that due to the do-while style implementation, the actual iteration count is at least 1.
1293- let iterationCount = Int32 . random ( in: 0 ... 16 )
1284+ CodeGenerator ( " WasmLoopWithSignatureGenerator " , [
1285+ GeneratorStub ( " WasmBeginLoopWithSignatureGenerator " , inContext: . single( . wasmFunction) ,
1286+ provides: [ . wasmFunction] ) { b in
1287+ let function = b. currentWasmModule. currentWasmFunction
1288+ // Count upwards here to make it slightly more different from the other loop generator.
1289+ // Also, instead of using reassign, this generator uses the signature to pass and update the loop counter.
1290+ let randomArgs = b. randomWasmBlockArguments ( upTo: 5 )
1291+ let randomArgTypes = randomArgs. map { b. type ( of: $0) }
1292+ let args = [ function. consti32 ( 0 ) ] + randomArgs
1293+ let parameters = args. map ( b. type)
1294+ // TODO(mliedtke): Also allow index types in the output types.
1295+ let outputTypes = b. randomWasmBlockOutputTypes ( upTo: 5 )
1296+ // Calculate index types for the dynamically created signature.
1297+ let indexTypes = ( parameters + outputTypes)
1298+ . filter { $0. Is ( . anyIndexRef) }
1299+ . map ( b. getWasmTypeDef)
1300+
1301+ // TODO(mliedtke): We need to cleanup the index types here!
1302+ let signature = b. wasmDefineAdHocSignatureType ( signature: parameters => outputTypes)
1303+ let loopBegin = b. emit ( WasmBeginLoop ( parameterCount: parameters. count) ,
1304+ withInputs: [ signature] + args)
1305+ let loopCounter = loopBegin. innerOutput ( 1 )
1306+ assert ( b. type ( of: loopCounter) . Is ( . wasmi32) )
1307+ b. runtimeData. push ( " loopCounter " , loopCounter)
1308+ b. runtimeData. push ( " loopSignature " , signature)
1309+ b. runtimeData. push ( " loopLabel " , loopBegin. innerOutput ( 0 ) )
1310+ } ,
1311+ GeneratorStub ( " WasmEndLoopWithSignatureGenerator " , inContext: . single( . wasmFunction) ,
1312+ provides: [ . wasmFunction] ) { b in
1313+ let signature = b. runtimeData. pop ( " loopSignature " )
1314+ let function = b. currentWasmModule. currentWasmFunction
12941315
1295- function . wasmBuildLoop ( with : parameters => outputTypes , args : args ) {
1296- label , loopArgs in
1297- b . buildRecursive ( n : defaultCodeGenerationAmount )
1316+ // Note that due to the do-while style implementation, the actual iteration count is at
1317+ // least 1.
1318+ let iterationCount = Int32 . random ( in : 0 ... 16 )
12981319 let loopCtr = function. wasmi32BinOp (
1299- args [ 0 ] , function. consti32 ( 1 ) , binOpKind: . Add)
1320+ b . runtimeData . pop ( " loopCounter " ) , function. consti32 ( 1 ) , binOpKind: . Add)
13001321 let condition = function. wasmi32CompareOp (
13011322 loopCtr, function. consti32 ( iterationCount) , using: . Lt_s)
1302- let backedgeArgs =
1303- [ loopCtr] + randomArgTypes. map { b. randomVariable ( ofType: $0) ! }
1323+ let wasmSignature = b. type ( of: signature) . wasmFunctionSignatureDefSignature
1324+ let backedgeArgs = [ loopCtr] + wasmSignature. parameterTypes. dropFirst ( )
1325+ . map { b. randomVariable ( ofType: $0) !}
13041326 function. wasmBranchIf (
1305- condition, to: label , args: backedgeArgs,
1327+ condition, to: b . runtimeData . pop ( " loopLabel " ) , args: backedgeArgs,
13061328 hint: b. randomWasmBranchHint ( ) )
1307- return outputTypes. map ( function. findOrGenerateWasmVar)
1308- }
1309- } ,
1329+ let outputs = wasmSignature. outputTypes. map ( function. findOrGenerateWasmVar)
1330+ b. emit ( WasmEndLoop ( outputCount: outputs. count) , withInputs: [ signature] + outputs)
1331+ } ,
1332+ ] ) ,
13101333
13111334 // TODO Turn this into a multi-part Generator
13121335 CodeGenerator ( " WasmLegacyTryCatchGenerator " , inContext: . single( . wasmFunction) ) {
0 commit comments