github.com/wasilibs/wazerox@v0.0.0-20240124024944-4923be63ab5f/internal/engine/wazevo/frontend/frontend_test.go (about)

     1  package frontend
     2  
     3  import (
     4  	"testing"
     5  
     6  	"github.com/wasilibs/wazerox/api"
     7  	"github.com/wasilibs/wazerox/internal/engine/wazevo/ssa"
     8  	"github.com/wasilibs/wazerox/internal/engine/wazevo/testcases"
     9  	"github.com/wasilibs/wazerox/internal/engine/wazevo/wazevoapi"
    10  	"github.com/wasilibs/wazerox/internal/testing/require"
    11  	"github.com/wasilibs/wazerox/internal/wasm"
    12  )
    13  
    14  func TestCompiler_LowerToSSA(t *testing.T) {
    15  	// Most of the logic should look similar to Cranelift's Wasm frontend, so when you want to see
    16  	// what output should look like, you can run:
    17  	// `~/wasmtime/target/debug/clif-util wasm --target aarch64-apple-darwin testcase.wat -p -t`
    18  	for _, tc := range []struct {
    19  		name              string
    20  		ensureTermination bool
    21  		needListener      bool
    22  		// m is the *wasm.Module to be compiled in this test.
    23  		m *wasm.Module
    24  		// targetIndex is the index of a local function to be compiled in this test.
    25  		targetIndex wasm.Index
    26  		// exp is the *unoptimized* expected SSA IR for the function m.FunctionSection[targetIndex].
    27  		exp string
    28  		// expAfterOpt is not empty when we want to check the result after optimization passes.
    29  		expAfterOpt string
    30  	}{
    31  		{
    32  			name: "empty", m: testcases.Empty.Module,
    33  			exp: `
    34  blk0: (exec_ctx:i64, module_ctx:i64)
    35  	Jump blk_ret
    36  `,
    37  		},
    38  		{
    39  			name: "unreachable", m: testcases.Unreachable.Module,
    40  			exp: `
    41  blk0: (exec_ctx:i64, module_ctx:i64)
    42  	Exit exec_ctx, unreachable
    43  `,
    44  		},
    45  		{
    46  			name: testcases.OnlyReturn.Name, m: testcases.OnlyReturn.Module,
    47  			exp: `
    48  blk0: (exec_ctx:i64, module_ctx:i64)
    49  	Return
    50  `,
    51  		},
    52  		{
    53  			name: "params", m: testcases.Params.Module,
    54  			exp: `
    55  blk0: (exec_ctx:i64, module_ctx:i64, v2:i32, v3:f32, v4:f64)
    56  	Return
    57  `,
    58  		},
    59  		{
    60  			name: "add/sub params return", m: testcases.AddSubParamsReturn.Module,
    61  			exp: `
    62  blk0: (exec_ctx:i64, module_ctx:i64, v2:i32, v3:i32)
    63  	v4:i32 = Iadd v2, v3
    64  	v5:i32 = Isub v4, v2
    65  	Jump blk_ret, v5
    66  `,
    67  		},
    68  		{
    69  			name: "add/sub params return / listener", m: testcases.AddSubParamsReturn.Module,
    70  			needListener: true,
    71  			exp: `
    72  signatures:
    73  	sig1: i64i32i32i32_v
    74  	sig2: i64i32i32_v
    75  
    76  blk0: (exec_ctx:i64, module_ctx:i64, v2:i32, v3:i32)
    77  	Store module_ctx, exec_ctx, 0x8
    78  	v4:i64 = Load module_ctx, 0x8
    79  	v5:i64 = Load v4, 0x0
    80  	v6:i32 = Iconst_32 0x0
    81  	CallIndirect v5:sig1, exec_ctx, v6, v2, v3
    82  	v7:i32 = Iadd v2, v3
    83  	v8:i32 = Isub v7, v2
    84  	Store module_ctx, exec_ctx, 0x8
    85  	v9:i64 = Load module_ctx, 0x10
    86  	v10:i64 = Load v9, 0x0
    87  	v11:i32 = Iconst_32 0x0
    88  	CallIndirect v10:sig2, exec_ctx, v11, v8
    89  	Jump blk_ret, v8
    90  `,
    91  		},
    92  		{
    93  			name: "locals", m: testcases.Locals.Module,
    94  			exp: `
    95  blk0: (exec_ctx:i64, module_ctx:i64)
    96  	v2:i32 = Iconst_32 0x0
    97  	v3:i64 = Iconst_64 0x0
    98  	v4:f32 = F32const 0.000000
    99  	v5:f64 = F64const 0.000000
   100  	Jump blk_ret
   101  `,
   102  			expAfterOpt: `
   103  blk0: (exec_ctx:i64, module_ctx:i64)
   104  	Jump blk_ret
   105  `,
   106  		},
   107  		{
   108  			name: "selects", m: testcases.Selects.Module,
   109  			exp: `
   110  blk0: (exec_ctx:i64, module_ctx:i64, v2:i32, v3:i32, v4:i64, v5:i64, v6:f32, v7:f32, v8:f64, v9:f64)
   111  	v10:i32 = Icmp eq, v4, v5
   112  	v11:i32 = Select v10, v2, v3
   113  	v12:i64 = Select v3, v4, v5
   114  	v13:i32 = Fcmp gt, v8, v9
   115  	v14:f32 = Select v13, v6, v7
   116  	v15:i32 = Fcmp neq, v6, v7
   117  	v16:f64 = Select v15, v8, v9
   118  	Jump blk_ret, v11, v12, v14, v16
   119  `,
   120  		},
   121  		{
   122  			name: "local param tee return", m: testcases.LocalParamTeeReturn.Module,
   123  			exp: `
   124  blk0: (exec_ctx:i64, module_ctx:i64, v2:i32)
   125  	v3:i32 = Iconst_32 0x0
   126  	Jump blk_ret, v2, v2
   127  `,
   128  			expAfterOpt: `
   129  blk0: (exec_ctx:i64, module_ctx:i64, v2:i32)
   130  	Jump blk_ret, v2, v2
   131  `,
   132  		},
   133  		{
   134  			name: "locals + params", m: testcases.LocalsParams.Module,
   135  			exp: `
   136  blk0: (exec_ctx:i64, module_ctx:i64, v2:i64, v3:f32, v4:f64)
   137  	v5:i32 = Iconst_32 0x0
   138  	v6:i64 = Iconst_64 0x0
   139  	v7:f32 = F32const 0.000000
   140  	v8:f64 = F64const 0.000000
   141  	v9:i64 = Iadd v2, v2
   142  	v10:i64 = Isub v9, v2
   143  	v11:f32 = Fadd v3, v3
   144  	v12:f32 = Fsub v11, v3
   145  	v13:f32 = Fmul v12, v3
   146  	v14:f32 = Fdiv v13, v3
   147  	v15:f32 = Fmax v14, v3
   148  	v16:f32 = Fmin v15, v3
   149  	v17:f64 = Fadd v4, v4
   150  	v18:f64 = Fsub v17, v4
   151  	v19:f64 = Fmul v18, v4
   152  	v20:f64 = Fdiv v19, v4
   153  	v21:f64 = Fmax v20, v4
   154  	v22:f64 = Fmin v21, v4
   155  	Jump blk_ret, v10, v16, v22
   156  `,
   157  			expAfterOpt: `
   158  blk0: (exec_ctx:i64, module_ctx:i64, v2:i64, v3:f32, v4:f64)
   159  	v9:i64 = Iadd v2, v2
   160  	v10:i64 = Isub v9, v2
   161  	v11:f32 = Fadd v3, v3
   162  	v12:f32 = Fsub v11, v3
   163  	v13:f32 = Fmul v12, v3
   164  	v14:f32 = Fdiv v13, v3
   165  	v15:f32 = Fmax v14, v3
   166  	v16:f32 = Fmin v15, v3
   167  	v17:f64 = Fadd v4, v4
   168  	v18:f64 = Fsub v17, v4
   169  	v19:f64 = Fmul v18, v4
   170  	v20:f64 = Fdiv v19, v4
   171  	v21:f64 = Fmax v20, v4
   172  	v22:f64 = Fmin v21, v4
   173  	Jump blk_ret, v10, v16, v22
   174  `,
   175  		},
   176  		{
   177  			name: "locals + params + return", m: testcases.LocalParamReturn.Module,
   178  			exp: `
   179  blk0: (exec_ctx:i64, module_ctx:i64, v2:i32)
   180  	v3:i32 = Iconst_32 0x0
   181  	Jump blk_ret, v2, v3
   182  `,
   183  		},
   184  		{
   185  			name: "swap param and return", m: testcases.SwapParamAndReturn.Module,
   186  			exp: `
   187  blk0: (exec_ctx:i64, module_ctx:i64, v2:i32, v3:i32)
   188  	Jump blk_ret, v3, v2
   189  `,
   190  		},
   191  		{
   192  			name: "swap params and return", m: testcases.SwapParamsAndReturn.Module,
   193  			exp: `
   194  blk0: (exec_ctx:i64, module_ctx:i64, v2:i32, v3:i32)
   195  	Jump blk1
   196  
   197  blk1: () <-- (blk0)
   198  	Jump blk_ret, v3, v2
   199  `,
   200  		},
   201  		{
   202  			name: "block - br", m: testcases.BlockBr.Module,
   203  			exp: `
   204  blk0: (exec_ctx:i64, module_ctx:i64)
   205  	v2:i32 = Iconst_32 0x0
   206  	v3:i64 = Iconst_64 0x0
   207  	v4:f32 = F32const 0.000000
   208  	v5:f64 = F64const 0.000000
   209  	Jump blk1
   210  
   211  blk1: () <-- (blk0)
   212  	Jump blk_ret
   213  `,
   214  		},
   215  		{
   216  			name: "block - br_if", m: testcases.BlockBrIf.Module,
   217  			exp: `
   218  blk0: (exec_ctx:i64, module_ctx:i64)
   219  	v2:i32 = Iconst_32 0x0
   220  	Brnz v2, blk1
   221  	Jump blk2
   222  
   223  blk1: () <-- (blk0)
   224  	Jump blk_ret
   225  
   226  blk2: () <-- (blk0)
   227  	Exit exec_ctx, unreachable
   228  `,
   229  		},
   230  		{
   231  			name: "loop - br", m: testcases.LoopBr.Module,
   232  			exp: `
   233  blk0: (exec_ctx:i64, module_ctx:i64)
   234  	Jump blk1
   235  
   236  blk1: () <-- (blk0,blk1)
   237  	Jump blk1
   238  
   239  blk2: ()
   240  `,
   241  			expAfterOpt: `
   242  blk0: (exec_ctx:i64, module_ctx:i64)
   243  	Jump blk1
   244  
   245  blk1: () <-- (blk0,blk1)
   246  	Jump blk1
   247  `,
   248  		},
   249  		{
   250  			name: "loop - br / ensure termination", m: testcases.LoopBr.Module,
   251  			ensureTermination: true,
   252  			exp: `
   253  signatures:
   254  	sig2: i64_v
   255  
   256  blk0: (exec_ctx:i64, module_ctx:i64)
   257  	Jump blk1
   258  
   259  blk1: () <-- (blk0,blk1)
   260  	v2:i64 = Load exec_ctx, 0x58
   261  	CallIndirect v2:sig2, exec_ctx
   262  	Jump blk1
   263  
   264  blk2: ()
   265  `,
   266  			expAfterOpt: `
   267  signatures:
   268  	sig2: i64_v
   269  
   270  blk0: (exec_ctx:i64, module_ctx:i64)
   271  	Jump blk1
   272  
   273  blk1: () <-- (blk0,blk1)
   274  	v2:i64 = Load exec_ctx, 0x58
   275  	CallIndirect v2:sig2, exec_ctx
   276  	Jump blk1
   277  `,
   278  		},
   279  		{
   280  			name: "loop - br_if", m: testcases.LoopBrIf.Module,
   281  			exp: `
   282  blk0: (exec_ctx:i64, module_ctx:i64)
   283  	Jump blk1
   284  
   285  blk1: () <-- (blk0,blk1)
   286  	v2:i32 = Iconst_32 0x1
   287  	Brnz v2, blk1
   288  	Jump blk3
   289  
   290  blk2: ()
   291  
   292  blk3: () <-- (blk1)
   293  	Return
   294  `,
   295  			expAfterOpt: `
   296  blk0: (exec_ctx:i64, module_ctx:i64)
   297  	Jump blk1
   298  
   299  blk1: () <-- (blk0,blk1)
   300  	v2:i32 = Iconst_32 0x1
   301  	Brnz v2, blk1
   302  	Jump blk3
   303  
   304  blk3: () <-- (blk1)
   305  	Return
   306  `,
   307  		},
   308  		{
   309  			name: "block - block - br", m: testcases.BlockBlockBr.Module,
   310  			exp: `
   311  blk0: (exec_ctx:i64, module_ctx:i64)
   312  	v2:i32 = Iconst_32 0x0
   313  	v3:i64 = Iconst_64 0x0
   314  	v4:f32 = F32const 0.000000
   315  	v5:f64 = F64const 0.000000
   316  	Jump blk1
   317  
   318  blk1: () <-- (blk0)
   319  	Jump blk_ret
   320  
   321  blk2: ()
   322  `,
   323  			expAfterOpt: `
   324  blk0: (exec_ctx:i64, module_ctx:i64)
   325  	Jump blk1
   326  
   327  blk1: () <-- (blk0)
   328  	Jump blk_ret
   329  `,
   330  		},
   331  		{
   332  			name: "if without else", m: testcases.IfWithoutElse.Module,
   333  			exp: `
   334  blk0: (exec_ctx:i64, module_ctx:i64)
   335  	v2:i32 = Iconst_32 0x0
   336  	Brz v2, blk2
   337  	Jump blk1
   338  
   339  blk1: () <-- (blk0)
   340  	Jump blk3
   341  
   342  blk2: () <-- (blk0)
   343  	Jump blk3
   344  
   345  blk3: () <-- (blk1,blk2)
   346  	Jump blk_ret
   347  `,
   348  		},
   349  		{
   350  			name: "if-else", m: testcases.IfElse.Module,
   351  			exp: `
   352  blk0: (exec_ctx:i64, module_ctx:i64)
   353  	v2:i32 = Iconst_32 0x0
   354  	Brz v2, blk2
   355  	Jump blk1
   356  
   357  blk1: () <-- (blk0)
   358  	Jump blk3
   359  
   360  blk2: () <-- (blk0)
   361  	Jump blk_ret
   362  
   363  blk3: () <-- (blk1)
   364  	Jump blk_ret
   365  `,
   366  		},
   367  		{
   368  			name: "single predecessor local refs", m: testcases.SinglePredecessorLocalRefs.Module,
   369  			exp: `
   370  blk0: (exec_ctx:i64, module_ctx:i64)
   371  	v2:i32 = Iconst_32 0x0
   372  	v3:i32 = Iconst_32 0x0
   373  	v4:i32 = Iconst_32 0x0
   374  	Brz v2, blk2
   375  	Jump blk1
   376  
   377  blk1: () <-- (blk0)
   378  	Return v4
   379  
   380  blk2: () <-- (blk0)
   381  	Jump blk3
   382  
   383  blk3: () <-- (blk2)
   384  	Jump blk_ret, v2
   385  `,
   386  			expAfterOpt: `
   387  blk0: (exec_ctx:i64, module_ctx:i64)
   388  	v2:i32 = Iconst_32 0x0
   389  	v4:i32 = Iconst_32 0x0
   390  	Brz v2, blk2
   391  	Jump blk1
   392  
   393  blk1: () <-- (blk0)
   394  	Return v4
   395  
   396  blk2: () <-- (blk0)
   397  	Jump blk3
   398  
   399  blk3: () <-- (blk2)
   400  	Jump blk_ret, v2
   401  `,
   402  		},
   403  		{
   404  			name: "multi predecessors local ref",
   405  			m:    testcases.MultiPredecessorLocalRef.Module,
   406  			exp: `
   407  blk0: (exec_ctx:i64, module_ctx:i64, v2:i32, v3:i32)
   408  	v4:i32 = Iconst_32 0x0
   409  	Brz v2, blk2
   410  	Jump blk1
   411  
   412  blk1: () <-- (blk0)
   413  	Jump blk3, v2
   414  
   415  blk2: () <-- (blk0)
   416  	Jump blk3, v3
   417  
   418  blk3: (v5:i32) <-- (blk1,blk2)
   419  	Jump blk_ret, v5
   420  `,
   421  			expAfterOpt: `
   422  blk0: (exec_ctx:i64, module_ctx:i64, v2:i32, v3:i32)
   423  	Brz v2, blk2
   424  	Jump blk1
   425  
   426  blk1: () <-- (blk0)
   427  	Jump blk3, v2
   428  
   429  blk2: () <-- (blk0)
   430  	Jump blk3, v3
   431  
   432  blk3: (v5:i32) <-- (blk1,blk2)
   433  	Jump blk_ret, v5
   434  `,
   435  		},
   436  		{
   437  			name: "reference value from unsealed block",
   438  			m:    testcases.ReferenceValueFromUnsealedBlock.Module,
   439  			exp: `
   440  blk0: (exec_ctx:i64, module_ctx:i64, v2:i32)
   441  	v3:i32 = Iconst_32 0x0
   442  	Jump blk1, v2
   443  
   444  blk1: (v4:i32) <-- (blk0)
   445  	Return v4
   446  
   447  blk2: ()
   448  `,
   449  			expAfterOpt: `
   450  blk0: (exec_ctx:i64, module_ctx:i64, v2:i32)
   451  	Jump blk1
   452  
   453  blk1: () <-- (blk0)
   454  	Return v2
   455  `,
   456  		},
   457  		{
   458  			name: "reference value from unsealed block - #2",
   459  			m:    testcases.ReferenceValueFromUnsealedBlock2.Module,
   460  			exp: `
   461  blk0: (exec_ctx:i64, module_ctx:i64, v2:i32)
   462  	Jump blk1, v2
   463  
   464  blk1: (v3:i32) <-- (blk0,blk1)
   465  	Brnz v3, blk1, v3
   466  	Jump blk4
   467  
   468  blk2: () <-- (blk3)
   469  	v4:i32 = Iconst_32 0x0
   470  	Jump blk_ret, v4
   471  
   472  blk3: () <-- (blk4)
   473  	Jump blk2
   474  
   475  blk4: () <-- (blk1)
   476  	Jump blk3
   477  `,
   478  			expAfterOpt: `
   479  blk0: (exec_ctx:i64, module_ctx:i64, v2:i32)
   480  	Jump blk1
   481  
   482  blk1: () <-- (blk0,blk1)
   483  	Brnz v2, blk1
   484  	Jump blk4
   485  
   486  blk2: () <-- (blk3)
   487  	v4:i32 = Iconst_32 0x0
   488  	Jump blk_ret, v4
   489  
   490  blk3: () <-- (blk4)
   491  	Jump blk2
   492  
   493  blk4: () <-- (blk1)
   494  	Jump blk3
   495  `,
   496  		},
   497  		{
   498  			name: "reference value from unsealed block - #3",
   499  			m:    testcases.ReferenceValueFromUnsealedBlock3.Module,
   500  			exp: `
   501  blk0: (exec_ctx:i64, module_ctx:i64, v2:i32)
   502  	Jump blk1, v2
   503  
   504  blk1: (v3:i32) <-- (blk0,blk3)
   505  	Brnz v3, blk_ret
   506  	Jump blk4
   507  
   508  blk2: ()
   509  
   510  blk3: () <-- (blk4)
   511  	v4:i32 = Iconst_32 0x1
   512  	Jump blk1, v4
   513  
   514  blk4: () <-- (blk1)
   515  	Jump blk3
   516  `,
   517  			expAfterOpt: `
   518  blk0: (exec_ctx:i64, module_ctx:i64, v2:i32)
   519  	Jump blk1, v2
   520  
   521  blk1: (v3:i32) <-- (blk0,blk3)
   522  	Brnz v3, blk_ret
   523  	Jump blk4
   524  
   525  blk3: () <-- (blk4)
   526  	v4:i32 = Iconst_32 0x1
   527  	Jump blk1, v4
   528  
   529  blk4: () <-- (blk1)
   530  	Jump blk3
   531  `,
   532  		},
   533  		{
   534  			name: "call",
   535  			m:    testcases.Call.Module,
   536  			exp: `
   537  signatures:
   538  	sig1: i64i64_i32
   539  	sig2: i64i64i32i32_i32
   540  	sig3: i64i64i32_i32i32
   541  
   542  blk0: (exec_ctx:i64, module_ctx:i64)
   543  	Store module_ctx, exec_ctx, 0x8
   544  	v2:i32 = Call f1:sig1, exec_ctx, module_ctx
   545  	v3:i32 = Iconst_32 0x5
   546  	Store module_ctx, exec_ctx, 0x8
   547  	v4:i32 = Call f2:sig2, exec_ctx, module_ctx, v2, v3
   548  	Store module_ctx, exec_ctx, 0x8
   549  	v5:i32, v6:i32 = Call f3:sig3, exec_ctx, module_ctx, v4
   550  	Jump blk_ret, v5, v6
   551  `,
   552  		},
   553  		{
   554  			name: "call_many_params",
   555  			m:    testcases.CallManyParams.Module,
   556  			exp: `
   557  signatures:
   558  	sig1: i64i64i32i64f32f64i32i64f32f64i32i64f32f64i32i64f32f64i32i64f32f64i32i64f32f64i32i64f32f64i32i64f32f64i32i64f32f64i32i64f32f64_v
   559  
   560  blk0: (exec_ctx:i64, module_ctx:i64, v2:i32, v3:i64, v4:f32, v5:f64)
   561  	Store module_ctx, exec_ctx, 0x8
   562  	Call f1:sig1, exec_ctx, module_ctx, v2, v3, v4, v5, v2, v3, v4, v5, v2, v3, v4, v5, v2, v3, v4, v5, v2, v3, v4, v5, v2, v3, v4, v5, v2, v3, v4, v5, v2, v3, v4, v5, v2, v3, v4, v5, v2, v3, v4, v5
   563  	Jump blk_ret
   564  `,
   565  		},
   566  		{
   567  			name: "call_many_returns",
   568  			m:    testcases.CallManyReturns.Module,
   569  			exp: `
   570  signatures:
   571  	sig0: i64i64i32i64f32f64_i32i64f32f64i32i64f32f64i32i64f32f64i32i64f32f64i32i64f32f64i32i64f32f64i32i64f32f64i32i64f32f64i32i64f32f64i32i64f32f64
   572  
   573  blk0: (exec_ctx:i64, module_ctx:i64, v2:i32, v3:i64, v4:f32, v5:f64)
   574  	Store module_ctx, exec_ctx, 0x8
   575  	v6:i32, v7:i64, v8:f32, v9:f64, v10:i32, v11:i64, v12:f32, v13:f64, v14:i32, v15:i64, v16:f32, v17:f64, v18:i32, v19:i64, v20:f32, v21:f64, v22:i32, v23:i64, v24:f32, v25:f64, v26:i32, v27:i64, v28:f32, v29:f64, v30:i32, v31:i64, v32:f32, v33:f64, v34:i32, v35:i64, v36:f32, v37:f64, v38:i32, v39:i64, v40:f32, v41:f64, v42:i32, v43:i64, v44:f32, v45:f64 = Call f1:sig0, exec_ctx, module_ctx, v2, v3, v4, v5
   576  	Jump blk_ret, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45
   577  `,
   578  		},
   579  		{
   580  			name: "integer comparisons", m: testcases.IntegerComparisons.Module,
   581  			exp: `
   582  blk0: (exec_ctx:i64, module_ctx:i64, v2:i32, v3:i32, v4:i64, v5:i64)
   583  	v6:i32 = Icmp eq, v2, v3
   584  	v7:i32 = Icmp eq, v4, v5
   585  	v8:i32 = Icmp neq, v2, v3
   586  	v9:i32 = Icmp neq, v4, v5
   587  	v10:i32 = Icmp lt_s, v2, v3
   588  	v11:i32 = Icmp lt_s, v4, v5
   589  	v12:i32 = Icmp lt_u, v2, v3
   590  	v13:i32 = Icmp lt_u, v4, v5
   591  	v14:i32 = Icmp gt_s, v2, v3
   592  	v15:i32 = Icmp gt_s, v4, v5
   593  	v16:i32 = Icmp gt_u, v2, v3
   594  	v17:i32 = Icmp gt_u, v4, v5
   595  	v18:i32 = Icmp le_s, v2, v3
   596  	v19:i32 = Icmp le_s, v4, v5
   597  	v20:i32 = Icmp le_u, v2, v3
   598  	v21:i32 = Icmp le_u, v4, v5
   599  	v22:i32 = Icmp ge_s, v2, v3
   600  	v23:i32 = Icmp ge_s, v4, v5
   601  	v24:i32 = Icmp ge_u, v2, v3
   602  	v25:i32 = Icmp ge_u, v4, v5
   603  	Jump blk_ret, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25
   604  `,
   605  			expAfterOpt: `
   606  blk0: (exec_ctx:i64, module_ctx:i64, v2:i32, v3:i32, v4:i64, v5:i64)
   607  	v6:i32 = Icmp eq, v2, v3
   608  	v7:i32 = Icmp eq, v4, v5
   609  	v8:i32 = Icmp neq, v2, v3
   610  	v9:i32 = Icmp neq, v4, v5
   611  	v10:i32 = Icmp lt_s, v2, v3
   612  	v11:i32 = Icmp lt_s, v4, v5
   613  	v12:i32 = Icmp lt_u, v2, v3
   614  	v13:i32 = Icmp lt_u, v4, v5
   615  	v14:i32 = Icmp gt_s, v2, v3
   616  	v15:i32 = Icmp gt_s, v4, v5
   617  	v16:i32 = Icmp gt_u, v2, v3
   618  	v17:i32 = Icmp gt_u, v4, v5
   619  	v18:i32 = Icmp le_s, v2, v3
   620  	v19:i32 = Icmp le_s, v4, v5
   621  	v20:i32 = Icmp le_u, v2, v3
   622  	v21:i32 = Icmp le_u, v4, v5
   623  	v22:i32 = Icmp ge_s, v2, v3
   624  	v23:i32 = Icmp ge_s, v4, v5
   625  	v24:i32 = Icmp ge_u, v2, v3
   626  	v25:i32 = Icmp ge_u, v4, v5
   627  	Jump blk_ret, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25
   628  `,
   629  		},
   630  		{
   631  			name: "integer bitwise", m: testcases.IntegerBitwise.Module,
   632  			exp: `
   633  blk0: (exec_ctx:i64, module_ctx:i64, v2:i32, v3:i32, v4:i64, v5:i64)
   634  	v6:i32 = Band v2, v3
   635  	v7:i32 = Bor v2, v3
   636  	v8:i32 = Bxor v2, v3
   637  	v9:i32 = Rotr v2, v3
   638  	v10:i64 = Band v4, v5
   639  	v11:i64 = Bor v4, v5
   640  	v12:i64 = Bxor v4, v5
   641  	v13:i64 = Iconst_64 0x8
   642  	v14:i64 = Ishl v5, v13
   643  	v15:i64 = Bxor v4, v14
   644  	v16:i64 = Rotl v4, v5
   645  	v17:i64 = Rotr v4, v5
   646  	Jump blk_ret, v6, v7, v8, v9, v10, v11, v12, v15, v16, v17
   647  `,
   648  		},
   649  		{
   650  			name: "integer shift", m: testcases.IntegerShift.Module,
   651  			exp: `
   652  blk0: (exec_ctx:i64, module_ctx:i64, v2:i32, v3:i32, v4:i64, v5:i64)
   653  	v6:i32 = Ishl v2, v3
   654  	v7:i32 = Iconst_32 0x1f
   655  	v8:i32 = Ishl v2, v7
   656  	v9:i64 = Ishl v4, v5
   657  	v10:i64 = Iconst_64 0x20
   658  	v11:i64 = Ishl v4, v10
   659  	v12:i32 = Ushr v2, v3
   660  	v13:i32 = Iconst_32 0x1f
   661  	v14:i32 = Ushr v2, v13
   662  	v15:i64 = Ushr v4, v5
   663  	v16:i64 = Iconst_64 0x20
   664  	v17:i64 = Ushr v4, v16
   665  	v18:i32 = Sshr v2, v3
   666  	v19:i32 = Iconst_32 0x1f
   667  	v20:i32 = Sshr v2, v19
   668  	v21:i64 = Sshr v4, v5
   669  	v22:i64 = Iconst_64 0x20
   670  	v23:i64 = Sshr v4, v22
   671  	Jump blk_ret, v6, v8, v9, v11, v12, v14, v15, v17, v18, v20, v21, v23
   672  `,
   673  		},
   674  		{
   675  			name: "integer extension", m: testcases.IntegerExtensions.Module,
   676  			exp: `
   677  blk0: (exec_ctx:i64, module_ctx:i64, v2:i32, v3:i64)
   678  	v4:i64 = SExtend v2, 32->64
   679  	v5:i64 = UExtend v2, 32->64
   680  	v6:i64 = SExtend v3, 8->64
   681  	v7:i64 = SExtend v3, 16->64
   682  	v8:i64 = SExtend v3, 32->64
   683  	v9:i32 = SExtend v2, 8->32
   684  	v10:i32 = SExtend v2, 16->32
   685  	Jump blk_ret, v4, v5, v6, v7, v8, v9, v10
   686  `,
   687  		},
   688  		{
   689  			name: "integer bit counts", m: testcases.IntegerBitCounts.Module,
   690  			exp: `
   691  blk0: (exec_ctx:i64, module_ctx:i64, v2:i32, v3:i64)
   692  	v4:i32 = Clz v2
   693  	v5:i32 = Ctz v2
   694  	v6:i32 = Popcnt v2
   695  	v7:i64 = Clz v3
   696  	v8:i64 = Ctz v3
   697  	v9:i64 = Popcnt v3
   698  	Jump blk_ret, v4, v5, v6, v7, v8, v9
   699  `,
   700  		},
   701  		{
   702  			name: "float comparisons", m: testcases.FloatComparisons.Module,
   703  			exp: `
   704  blk0: (exec_ctx:i64, module_ctx:i64, v2:f32, v3:f32, v4:f64, v5:f64)
   705  	v6:i32 = Fcmp eq, v2, v3
   706  	v7:i32 = Fcmp neq, v2, v3
   707  	v8:i32 = Fcmp lt, v2, v3
   708  	v9:i32 = Fcmp gt, v2, v3
   709  	v10:i32 = Fcmp le, v2, v3
   710  	v11:i32 = Fcmp ge, v2, v3
   711  	v12:i32 = Fcmp eq, v4, v5
   712  	v13:i32 = Fcmp neq, v4, v5
   713  	v14:i32 = Fcmp lt, v4, v5
   714  	v15:i32 = Fcmp gt, v4, v5
   715  	v16:i32 = Fcmp le, v4, v5
   716  	v17:i32 = Fcmp ge, v4, v5
   717  	Jump blk_ret, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17
   718  `,
   719  		},
   720  		{
   721  			name: "float conversions", m: testcases.FloatConversions.Module,
   722  			exp: `
   723  blk0: (exec_ctx:i64, module_ctx:i64, v2:f64, v3:f32)
   724  	v4:i64 = FcvtToSint v2
   725  	v5:i64 = FcvtToSint v3
   726  	v6:i32 = FcvtToSint v2
   727  	v7:i32 = FcvtToSint v3
   728  	v8:i64 = FcvtToUint v2
   729  	v9:i64 = FcvtToUint v3
   730  	v10:i32 = FcvtToUint v2
   731  	v11:i32 = FcvtToUint v3
   732  	v12:f32 = Fdemote v2
   733  	v13:f64 = Fpromote v3
   734  	Jump blk_ret, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13
   735  `,
   736  		},
   737  		{
   738  			name: "non-trapping float conversions", m: testcases.NonTrappingFloatConversions.Module,
   739  			exp: `
   740  blk0: (exec_ctx:i64, module_ctx:i64, v2:f64, v3:f32)
   741  	v4:i64 = FcvtToSintSat v2
   742  	v5:i64 = FcvtToSintSat v3
   743  	v6:i32 = FcvtToSintSat v2
   744  	v7:i32 = FcvtToSintSat v3
   745  	v8:i64 = FcvtToUintSat v2
   746  	v9:i64 = FcvtToUintSat v3
   747  	v10:i32 = FcvtToUintSat v2
   748  	v11:i32 = FcvtToUintSat v3
   749  	Jump blk_ret, v4, v5, v6, v7, v8, v9, v10, v11
   750  `,
   751  		},
   752  		{
   753  			name: "loop with param and results", m: testcases.LoopBrWithParamResults.Module,
   754  			exp: `
   755  blk0: (exec_ctx:i64, module_ctx:i64, v2:i32, v3:i32)
   756  	Jump blk1, v2, v3
   757  
   758  blk1: (v4:i32,v5:i32) <-- (blk0,blk1)
   759  	v7:i32 = Iconst_32 0x1
   760  	Brnz v7, blk1, v4, v5
   761  	Jump blk3
   762  
   763  blk2: (v6:i32) <-- (blk3)
   764  	Jump blk_ret, v6
   765  
   766  blk3: () <-- (blk1)
   767  	Jump blk2, v4
   768  `,
   769  			expAfterOpt: `
   770  blk0: (exec_ctx:i64, module_ctx:i64, v2:i32, v3:i32)
   771  	Jump blk1
   772  
   773  blk1: () <-- (blk0,blk1)
   774  	v7:i32 = Iconst_32 0x1
   775  	Brnz v7, blk1
   776  	Jump blk3
   777  
   778  blk2: () <-- (blk3)
   779  	Jump blk_ret, v2
   780  
   781  blk3: () <-- (blk1)
   782  	Jump blk2
   783  `,
   784  		},
   785  		{
   786  			name:        "many_params_small_results",
   787  			m:           testcases.ManyParamsSmallResults.Module,
   788  			targetIndex: 0,
   789  			exp: `
   790  blk0: (exec_ctx:i64, module_ctx:i64, v2:i32, v3:i64, v4:f32, v5:f64, v6:i32, v7:i64, v8:f32, v9:f64, v10:i32, v11:i64, v12:f32, v13:f64, v14:i32, v15:i64, v16:f32, v17:f64, v18:i32, v19:i64, v20:f32, v21:f64, v22:i32, v23:i64, v24:f32, v25:f64, v26:i32, v27:i64, v28:f32, v29:f64, v30:i32, v31:i64, v32:f32, v33:f64, v34:i32, v35:i64, v36:f32, v37:f64, v38:i32, v39:i64, v40:f32, v41:f64)
   791  	Jump blk_ret, v2, v11, v20, v29
   792  `,
   793  			expAfterOpt: `
   794  blk0: (exec_ctx:i64, module_ctx:i64, v2:i32, v3:i64, v4:f32, v5:f64, v6:i32, v7:i64, v8:f32, v9:f64, v10:i32, v11:i64, v12:f32, v13:f64, v14:i32, v15:i64, v16:f32, v17:f64, v18:i32, v19:i64, v20:f32, v21:f64, v22:i32, v23:i64, v24:f32, v25:f64, v26:i32, v27:i64, v28:f32, v29:f64, v30:i32, v31:i64, v32:f32, v33:f64, v34:i32, v35:i64, v36:f32, v37:f64, v38:i32, v39:i64, v40:f32, v41:f64)
   795  	Jump blk_ret, v2, v11, v20, v29
   796  `,
   797  		},
   798  		{
   799  			name:        "small_params_many_results",
   800  			m:           testcases.SmallParamsManyResults.Module,
   801  			targetIndex: 0,
   802  			exp: `
   803  blk0: (exec_ctx:i64, module_ctx:i64, v2:i32, v3:i64, v4:f32, v5:f64)
   804  	Jump blk_ret, v2, v3, v4, v5, v2, v3, v4, v5, v2, v3, v4, v5, v2, v3, v4, v5, v2, v3, v4, v5, v2, v3, v4, v5, v2, v3, v4, v5, v2, v3, v4, v5, v2, v3, v4, v5, v2, v3, v4, v5
   805  `,
   806  			expAfterOpt: `
   807  blk0: (exec_ctx:i64, module_ctx:i64, v2:i32, v3:i64, v4:f32, v5:f64)
   808  	Jump blk_ret, v2, v3, v4, v5, v2, v3, v4, v5, v2, v3, v4, v5, v2, v3, v4, v5, v2, v3, v4, v5, v2, v3, v4, v5, v2, v3, v4, v5, v2, v3, v4, v5, v2, v3, v4, v5, v2, v3, v4, v5
   809  `,
   810  		},
   811  		{
   812  			name:        "many_params_many_results",
   813  			m:           testcases.ManyParamsManyResults.Module,
   814  			targetIndex: 0,
   815  			exp: `
   816  blk0: (exec_ctx:i64, module_ctx:i64, v2:i32, v3:i64, v4:f32, v5:f64, v6:i32, v7:i64, v8:f32, v9:f64, v10:i32, v11:i64, v12:f32, v13:f64, v14:i32, v15:i64, v16:f32, v17:f64, v18:i32, v19:i64, v20:f32, v21:f64, v22:i32, v23:i64, v24:f32, v25:f64, v26:i32, v27:i64, v28:f32, v29:f64, v30:i32, v31:i64, v32:f32, v33:f64, v34:i32, v35:i64, v36:f32, v37:f64, v38:i32, v39:i64, v40:f32, v41:f64)
   817  	Jump blk_ret, v41, v40, v39, v38, v37, v36, v35, v34, v33, v32, v31, v30, v29, v28, v27, v26, v25, v24, v23, v22, v21, v20, v19, v18, v17, v16, v15, v14, v13, v12, v11, v10, v9, v8, v7, v6, v5, v4, v3, v2
   818  `,
   819  			expAfterOpt: `
   820  blk0: (exec_ctx:i64, module_ctx:i64, v2:i32, v3:i64, v4:f32, v5:f64, v6:i32, v7:i64, v8:f32, v9:f64, v10:i32, v11:i64, v12:f32, v13:f64, v14:i32, v15:i64, v16:f32, v17:f64, v18:i32, v19:i64, v20:f32, v21:f64, v22:i32, v23:i64, v24:f32, v25:f64, v26:i32, v27:i64, v28:f32, v29:f64, v30:i32, v31:i64, v32:f32, v33:f64, v34:i32, v35:i64, v36:f32, v37:f64, v38:i32, v39:i64, v40:f32, v41:f64)
   821  	Jump blk_ret, v41, v40, v39, v38, v37, v36, v35, v34, v33, v32, v31, v30, v29, v28, v27, v26, v25, v24, v23, v22, v21, v20, v19, v18, v17, v16, v15, v14, v13, v12, v11, v10, v9, v8, v7, v6, v5, v4, v3, v2
   822  `,
   823  		},
   824  		{
   825  			name: "many_middle_values",
   826  			m:    testcases.ManyMiddleValues.Module,
   827  			exp: `
   828  blk0: (exec_ctx:i64, module_ctx:i64, v2:i32, v3:f32)
   829  	v4:i32 = Iconst_32 0x1
   830  	v5:i32 = Imul v2, v4
   831  	v6:i32 = Iconst_32 0x2
   832  	v7:i32 = Imul v2, v6
   833  	v8:i32 = Iconst_32 0x3
   834  	v9:i32 = Imul v2, v8
   835  	v10:i32 = Iconst_32 0x4
   836  	v11:i32 = Imul v2, v10
   837  	v12:i32 = Iconst_32 0x5
   838  	v13:i32 = Imul v2, v12
   839  	v14:i32 = Iconst_32 0x6
   840  	v15:i32 = Imul v2, v14
   841  	v16:i32 = Iconst_32 0x7
   842  	v17:i32 = Imul v2, v16
   843  	v18:i32 = Iconst_32 0x8
   844  	v19:i32 = Imul v2, v18
   845  	v20:i32 = Iconst_32 0x9
   846  	v21:i32 = Imul v2, v20
   847  	v22:i32 = Iconst_32 0xa
   848  	v23:i32 = Imul v2, v22
   849  	v24:i32 = Iconst_32 0xb
   850  	v25:i32 = Imul v2, v24
   851  	v26:i32 = Iconst_32 0xc
   852  	v27:i32 = Imul v2, v26
   853  	v28:i32 = Iconst_32 0xd
   854  	v29:i32 = Imul v2, v28
   855  	v30:i32 = Iconst_32 0xe
   856  	v31:i32 = Imul v2, v30
   857  	v32:i32 = Iconst_32 0xf
   858  	v33:i32 = Imul v2, v32
   859  	v34:i32 = Iconst_32 0x10
   860  	v35:i32 = Imul v2, v34
   861  	v36:i32 = Iconst_32 0x11
   862  	v37:i32 = Imul v2, v36
   863  	v38:i32 = Iconst_32 0x12
   864  	v39:i32 = Imul v2, v38
   865  	v40:i32 = Iconst_32 0x13
   866  	v41:i32 = Imul v2, v40
   867  	v42:i32 = Iconst_32 0x14
   868  	v43:i32 = Imul v2, v42
   869  	v44:i32 = Iadd v41, v43
   870  	v45:i32 = Iadd v39, v44
   871  	v46:i32 = Iadd v37, v45
   872  	v47:i32 = Iadd v35, v46
   873  	v48:i32 = Iadd v33, v47
   874  	v49:i32 = Iadd v31, v48
   875  	v50:i32 = Iadd v29, v49
   876  	v51:i32 = Iadd v27, v50
   877  	v52:i32 = Iadd v25, v51
   878  	v53:i32 = Iadd v23, v52
   879  	v54:i32 = Iadd v21, v53
   880  	v55:i32 = Iadd v19, v54
   881  	v56:i32 = Iadd v17, v55
   882  	v57:i32 = Iadd v15, v56
   883  	v58:i32 = Iadd v13, v57
   884  	v59:i32 = Iadd v11, v58
   885  	v60:i32 = Iadd v9, v59
   886  	v61:i32 = Iadd v7, v60
   887  	v62:i32 = Iadd v5, v61
   888  	v63:f32 = F32const 1.000000
   889  	v64:f32 = Fmul v3, v63
   890  	v65:f32 = F32const 2.000000
   891  	v66:f32 = Fmul v3, v65
   892  	v67:f32 = F32const 3.000000
   893  	v68:f32 = Fmul v3, v67
   894  	v69:f32 = F32const 4.000000
   895  	v70:f32 = Fmul v3, v69
   896  	v71:f32 = F32const 5.000000
   897  	v72:f32 = Fmul v3, v71
   898  	v73:f32 = F32const 6.000000
   899  	v74:f32 = Fmul v3, v73
   900  	v75:f32 = F32const 7.000000
   901  	v76:f32 = Fmul v3, v75
   902  	v77:f32 = F32const 8.000000
   903  	v78:f32 = Fmul v3, v77
   904  	v79:f32 = F32const 9.000000
   905  	v80:f32 = Fmul v3, v79
   906  	v81:f32 = F32const 10.000000
   907  	v82:f32 = Fmul v3, v81
   908  	v83:f32 = F32const 11.000000
   909  	v84:f32 = Fmul v3, v83
   910  	v85:f32 = F32const 12.000000
   911  	v86:f32 = Fmul v3, v85
   912  	v87:f32 = F32const 13.000000
   913  	v88:f32 = Fmul v3, v87
   914  	v89:f32 = F32const 14.000000
   915  	v90:f32 = Fmul v3, v89
   916  	v91:f32 = F32const 15.000000
   917  	v92:f32 = Fmul v3, v91
   918  	v93:f32 = F32const 16.000000
   919  	v94:f32 = Fmul v3, v93
   920  	v95:f32 = F32const 17.000000
   921  	v96:f32 = Fmul v3, v95
   922  	v97:f32 = F32const 18.000000
   923  	v98:f32 = Fmul v3, v97
   924  	v99:f32 = F32const 19.000000
   925  	v100:f32 = Fmul v3, v99
   926  	v101:f32 = F32const 20.000000
   927  	v102:f32 = Fmul v3, v101
   928  	v103:f32 = Fadd v100, v102
   929  	v104:f32 = Fadd v98, v103
   930  	v105:f32 = Fadd v96, v104
   931  	v106:f32 = Fadd v94, v105
   932  	v107:f32 = Fadd v92, v106
   933  	v108:f32 = Fadd v90, v107
   934  	v109:f32 = Fadd v88, v108
   935  	v110:f32 = Fadd v86, v109
   936  	v111:f32 = Fadd v84, v110
   937  	v112:f32 = Fadd v82, v111
   938  	v113:f32 = Fadd v80, v112
   939  	v114:f32 = Fadd v78, v113
   940  	v115:f32 = Fadd v76, v114
   941  	v116:f32 = Fadd v74, v115
   942  	v117:f32 = Fadd v72, v116
   943  	v118:f32 = Fadd v70, v117
   944  	v119:f32 = Fadd v68, v118
   945  	v120:f32 = Fadd v66, v119
   946  	v121:f32 = Fadd v64, v120
   947  	Jump blk_ret, v62, v121
   948  `,
   949  		},
   950  		{
   951  			name: "recursive_fibonacci", m: testcases.FibonacciRecursive.Module,
   952  			exp: `
   953  signatures:
   954  	sig0: i64i64i32_i32
   955  
   956  blk0: (exec_ctx:i64, module_ctx:i64, v2:i32)
   957  	v3:i32 = Iconst_32 0x2
   958  	v4:i32 = Icmp lt_s, v2, v3
   959  	Brz v4, blk2
   960  	Jump blk1
   961  
   962  blk1: () <-- (blk0)
   963  	Return v2
   964  
   965  blk2: () <-- (blk0)
   966  	Jump blk3
   967  
   968  blk3: () <-- (blk2)
   969  	v5:i32 = Iconst_32 0x1
   970  	v6:i32 = Isub v2, v5
   971  	Store module_ctx, exec_ctx, 0x8
   972  	v7:i32 = Call f0:sig0, exec_ctx, module_ctx, v6
   973  	v8:i32 = Iconst_32 0x2
   974  	v9:i32 = Isub v2, v8
   975  	Store module_ctx, exec_ctx, 0x8
   976  	v10:i32 = Call f0:sig0, exec_ctx, module_ctx, v9
   977  	v11:i32 = Iadd v7, v10
   978  	Jump blk_ret, v11
   979  `,
   980  			expAfterOpt: `
   981  signatures:
   982  	sig0: i64i64i32_i32
   983  
   984  blk0: (exec_ctx:i64, module_ctx:i64, v2:i32)
   985  	v3:i32 = Iconst_32 0x2
   986  	v4:i32 = Icmp lt_s, v2, v3
   987  	Brz v4, blk2
   988  	Jump blk1
   989  
   990  blk1: () <-- (blk0)
   991  	Return v2
   992  
   993  blk2: () <-- (blk0)
   994  	Jump blk3
   995  
   996  blk3: () <-- (blk2)
   997  	v5:i32 = Iconst_32 0x1
   998  	v6:i32 = Isub v2, v5
   999  	Store module_ctx, exec_ctx, 0x8
  1000  	v7:i32 = Call f0:sig0, exec_ctx, module_ctx, v6
  1001  	v8:i32 = Iconst_32 0x2
  1002  	v9:i32 = Isub v2, v8
  1003  	Store module_ctx, exec_ctx, 0x8
  1004  	v10:i32 = Call f0:sig0, exec_ctx, module_ctx, v9
  1005  	v11:i32 = Iadd v7, v10
  1006  	Jump blk_ret, v11
  1007  `,
  1008  		},
  1009  		{
  1010  			name: "memory_store_basic", m: testcases.MemoryStoreBasic.Module,
  1011  			exp: `
  1012  blk0: (exec_ctx:i64, module_ctx:i64, v2:i32, v3:i32)
  1013  	v4:i64 = Iconst_64 0x4
  1014  	v5:i64 = UExtend v2, 32->64
  1015  	v6:i64 = Uload32 module_ctx, 0x10
  1016  	v7:i64 = Iadd v5, v4
  1017  	v8:i32 = Icmp lt_u, v6, v7
  1018  	ExitIfTrue v8, exec_ctx, memory_out_of_bounds
  1019  	v9:i64 = Load module_ctx, 0x8
  1020  	v10:i64 = Iadd v9, v5
  1021  	Store v3, v10, 0x0
  1022  	v11:i64 = Iconst_64 0x4
  1023  	v12:i64 = UExtend v2, 32->64
  1024  	v13:i64 = Iadd v12, v11
  1025  	v14:i32 = Icmp lt_u, v6, v13
  1026  	ExitIfTrue v14, exec_ctx, memory_out_of_bounds
  1027  	v15:i64 = Iadd v9, v12
  1028  	v16:i32 = Load v15, 0x0
  1029  	Jump blk_ret, v16
  1030  `,
  1031  		},
  1032  		{
  1033  			name: "memory_load_basic", m: testcases.MemoryLoadBasic.Module,
  1034  			exp: `
  1035  blk0: (exec_ctx:i64, module_ctx:i64, v2:i32)
  1036  	v3:i64 = Iconst_64 0x4
  1037  	v4:i64 = UExtend v2, 32->64
  1038  	v5:i64 = Uload32 module_ctx, 0x10
  1039  	v6:i64 = Iadd v4, v3
  1040  	v7:i32 = Icmp lt_u, v5, v6
  1041  	ExitIfTrue v7, exec_ctx, memory_out_of_bounds
  1042  	v8:i64 = Load module_ctx, 0x8
  1043  	v9:i64 = Iadd v8, v4
  1044  	v10:i32 = Load v9, 0x0
  1045  	Jump blk_ret, v10
  1046  `,
  1047  		},
  1048  		{
  1049  			name: "memory_load_basic2", m: testcases.MemoryLoadBasic2.Module,
  1050  			exp: `
  1051  signatures:
  1052  	sig1: i64i64_v
  1053  
  1054  blk0: (exec_ctx:i64, module_ctx:i64, v2:i32)
  1055  	v3:i32 = Iconst_32 0x0
  1056  	v4:i32 = Icmp eq, v2, v3
  1057  	Brz v4, blk2
  1058  	Jump blk1
  1059  
  1060  blk1: () <-- (blk0)
  1061  	Store module_ctx, exec_ctx, 0x8
  1062  	Call f1:sig1, exec_ctx, module_ctx
  1063  	v5:i64 = Load module_ctx, 0x8
  1064  	v6:i64 = Uload32 module_ctx, 0x10
  1065  	Jump blk3, v2
  1066  
  1067  blk2: () <-- (blk0)
  1068  	Jump blk3, v2
  1069  
  1070  blk3: (v7:i32) <-- (blk1,blk2)
  1071  	v8:i64 = Iconst_64 0x4
  1072  	v9:i64 = UExtend v7, 32->64
  1073  	v10:i64 = Uload32 module_ctx, 0x10
  1074  	v11:i64 = Iadd v9, v8
  1075  	v12:i32 = Icmp lt_u, v10, v11
  1076  	ExitIfTrue v12, exec_ctx, memory_out_of_bounds
  1077  	v13:i64 = Load module_ctx, 0x8
  1078  	v14:i64 = Iadd v13, v9
  1079  	v15:i32 = Load v14, 0x0
  1080  	Jump blk_ret, v15
  1081  `,
  1082  			expAfterOpt: `
  1083  signatures:
  1084  	sig1: i64i64_v
  1085  
  1086  blk0: (exec_ctx:i64, module_ctx:i64, v2:i32)
  1087  	v3:i32 = Iconst_32 0x0
  1088  	v4:i32 = Icmp eq, v2, v3
  1089  	Brz v4, blk2
  1090  	Jump blk1
  1091  
  1092  blk1: () <-- (blk0)
  1093  	Store module_ctx, exec_ctx, 0x8
  1094  	Call f1:sig1, exec_ctx, module_ctx
  1095  	Jump blk3
  1096  
  1097  blk2: () <-- (blk0)
  1098  	Jump blk3
  1099  
  1100  blk3: () <-- (blk1,blk2)
  1101  	v8:i64 = Iconst_64 0x4
  1102  	v9:i64 = UExtend v2, 32->64
  1103  	v10:i64 = Uload32 module_ctx, 0x10
  1104  	v11:i64 = Iadd v9, v8
  1105  	v12:i32 = Icmp lt_u, v10, v11
  1106  	ExitIfTrue v12, exec_ctx, memory_out_of_bounds
  1107  	v13:i64 = Load module_ctx, 0x8
  1108  	v14:i64 = Iadd v13, v9
  1109  	v15:i32 = Load v14, 0x0
  1110  	Jump blk_ret, v15
  1111  `,
  1112  		},
  1113  		{
  1114  			name: "imported_function_call", m: testcases.ImportedFunctionCall.Module,
  1115  			exp: `
  1116  signatures:
  1117  	sig1: i64i64i32i32_i32
  1118  
  1119  blk0: (exec_ctx:i64, module_ctx:i64, v2:i32)
  1120  	Store module_ctx, exec_ctx, 0x8
  1121  	v3:i64 = Load module_ctx, 0x8
  1122  	v4:i64 = Load module_ctx, 0x10
  1123  	v5:i32 = CallIndirect v3:sig1, exec_ctx, v4, v2, v2
  1124  	Jump blk_ret, v5
  1125  `,
  1126  		},
  1127  		{
  1128  			name: "memory_loads", m: testcases.MemoryLoads.Module,
  1129  			exp: `
  1130  blk0: (exec_ctx:i64, module_ctx:i64, v2:i32)
  1131  	v3:i64 = Iconst_64 0x4
  1132  	v4:i64 = UExtend v2, 32->64
  1133  	v5:i64 = Uload32 module_ctx, 0x10
  1134  	v6:i64 = Iadd v4, v3
  1135  	v7:i32 = Icmp lt_u, v5, v6
  1136  	ExitIfTrue v7, exec_ctx, memory_out_of_bounds
  1137  	v8:i64 = Load module_ctx, 0x8
  1138  	v9:i64 = Iadd v8, v4
  1139  	v10:i32 = Load v9, 0x0
  1140  	v11:i64 = Iconst_64 0x8
  1141  	v12:i64 = UExtend v2, 32->64
  1142  	v13:i64 = Iadd v12, v11
  1143  	v14:i32 = Icmp lt_u, v5, v13
  1144  	ExitIfTrue v14, exec_ctx, memory_out_of_bounds
  1145  	v15:i64 = Iadd v8, v12
  1146  	v16:i64 = Load v15, 0x0
  1147  	v17:i64 = Iconst_64 0x4
  1148  	v18:i64 = UExtend v2, 32->64
  1149  	v19:i64 = Iadd v18, v17
  1150  	v20:i32 = Icmp lt_u, v5, v19
  1151  	ExitIfTrue v20, exec_ctx, memory_out_of_bounds
  1152  	v21:i64 = Iadd v8, v18
  1153  	v22:f32 = Load v21, 0x0
  1154  	v23:i64 = Iconst_64 0x8
  1155  	v24:i64 = UExtend v2, 32->64
  1156  	v25:i64 = Iadd v24, v23
  1157  	v26:i32 = Icmp lt_u, v5, v25
  1158  	ExitIfTrue v26, exec_ctx, memory_out_of_bounds
  1159  	v27:i64 = Iadd v8, v24
  1160  	v28:f64 = Load v27, 0x0
  1161  	v29:i64 = Iconst_64 0x13
  1162  	v30:i64 = UExtend v2, 32->64
  1163  	v31:i64 = Iadd v30, v29
  1164  	v32:i32 = Icmp lt_u, v5, v31
  1165  	ExitIfTrue v32, exec_ctx, memory_out_of_bounds
  1166  	v33:i64 = Iadd v8, v30
  1167  	v34:i32 = Load v33, 0xf
  1168  	v35:i64 = Iconst_64 0x17
  1169  	v36:i64 = UExtend v2, 32->64
  1170  	v37:i64 = Iadd v36, v35
  1171  	v38:i32 = Icmp lt_u, v5, v37
  1172  	ExitIfTrue v38, exec_ctx, memory_out_of_bounds
  1173  	v39:i64 = Iadd v8, v36
  1174  	v40:i64 = Load v39, 0xf
  1175  	v41:i64 = Iconst_64 0x13
  1176  	v42:i64 = UExtend v2, 32->64
  1177  	v43:i64 = Iadd v42, v41
  1178  	v44:i32 = Icmp lt_u, v5, v43
  1179  	ExitIfTrue v44, exec_ctx, memory_out_of_bounds
  1180  	v45:i64 = Iadd v8, v42
  1181  	v46:f32 = Load v45, 0xf
  1182  	v47:i64 = Iconst_64 0x17
  1183  	v48:i64 = UExtend v2, 32->64
  1184  	v49:i64 = Iadd v48, v47
  1185  	v50:i32 = Icmp lt_u, v5, v49
  1186  	ExitIfTrue v50, exec_ctx, memory_out_of_bounds
  1187  	v51:i64 = Iadd v8, v48
  1188  	v52:f64 = Load v51, 0xf
  1189  	v53:i64 = Iconst_64 0x1
  1190  	v54:i64 = UExtend v2, 32->64
  1191  	v55:i64 = Iadd v54, v53
  1192  	v56:i32 = Icmp lt_u, v5, v55
  1193  	ExitIfTrue v56, exec_ctx, memory_out_of_bounds
  1194  	v57:i64 = Iadd v8, v54
  1195  	v58:i32 = Sload8 v57, 0x0
  1196  	v59:i64 = Iconst_64 0x10
  1197  	v60:i64 = UExtend v2, 32->64
  1198  	v61:i64 = Iadd v60, v59
  1199  	v62:i32 = Icmp lt_u, v5, v61
  1200  	ExitIfTrue v62, exec_ctx, memory_out_of_bounds
  1201  	v63:i64 = Iadd v8, v60
  1202  	v64:i32 = Sload8 v63, 0xf
  1203  	v65:i64 = Iconst_64 0x1
  1204  	v66:i64 = UExtend v2, 32->64
  1205  	v67:i64 = Iadd v66, v65
  1206  	v68:i32 = Icmp lt_u, v5, v67
  1207  	ExitIfTrue v68, exec_ctx, memory_out_of_bounds
  1208  	v69:i64 = Iadd v8, v66
  1209  	v70:i32 = Uload8 v69, 0x0
  1210  	v71:i64 = Iconst_64 0x10
  1211  	v72:i64 = UExtend v2, 32->64
  1212  	v73:i64 = Iadd v72, v71
  1213  	v74:i32 = Icmp lt_u, v5, v73
  1214  	ExitIfTrue v74, exec_ctx, memory_out_of_bounds
  1215  	v75:i64 = Iadd v8, v72
  1216  	v76:i32 = Uload8 v75, 0xf
  1217  	v77:i64 = Iconst_64 0x2
  1218  	v78:i64 = UExtend v2, 32->64
  1219  	v79:i64 = Iadd v78, v77
  1220  	v80:i32 = Icmp lt_u, v5, v79
  1221  	ExitIfTrue v80, exec_ctx, memory_out_of_bounds
  1222  	v81:i64 = Iadd v8, v78
  1223  	v82:i32 = Sload16 v81, 0x0
  1224  	v83:i64 = Iconst_64 0x11
  1225  	v84:i64 = UExtend v2, 32->64
  1226  	v85:i64 = Iadd v84, v83
  1227  	v86:i32 = Icmp lt_u, v5, v85
  1228  	ExitIfTrue v86, exec_ctx, memory_out_of_bounds
  1229  	v87:i64 = Iadd v8, v84
  1230  	v88:i32 = Sload16 v87, 0xf
  1231  	v89:i64 = Iconst_64 0x2
  1232  	v90:i64 = UExtend v2, 32->64
  1233  	v91:i64 = Iadd v90, v89
  1234  	v92:i32 = Icmp lt_u, v5, v91
  1235  	ExitIfTrue v92, exec_ctx, memory_out_of_bounds
  1236  	v93:i64 = Iadd v8, v90
  1237  	v94:i32 = Uload16 v93, 0x0
  1238  	v95:i64 = Iconst_64 0x11
  1239  	v96:i64 = UExtend v2, 32->64
  1240  	v97:i64 = Iadd v96, v95
  1241  	v98:i32 = Icmp lt_u, v5, v97
  1242  	ExitIfTrue v98, exec_ctx, memory_out_of_bounds
  1243  	v99:i64 = Iadd v8, v96
  1244  	v100:i32 = Uload16 v99, 0xf
  1245  	v101:i64 = Iconst_64 0x1
  1246  	v102:i64 = UExtend v2, 32->64
  1247  	v103:i64 = Iadd v102, v101
  1248  	v104:i32 = Icmp lt_u, v5, v103
  1249  	ExitIfTrue v104, exec_ctx, memory_out_of_bounds
  1250  	v105:i64 = Iadd v8, v102
  1251  	v106:i64 = Sload8 v105, 0x0
  1252  	v107:i64 = Iconst_64 0x10
  1253  	v108:i64 = UExtend v2, 32->64
  1254  	v109:i64 = Iadd v108, v107
  1255  	v110:i32 = Icmp lt_u, v5, v109
  1256  	ExitIfTrue v110, exec_ctx, memory_out_of_bounds
  1257  	v111:i64 = Iadd v8, v108
  1258  	v112:i64 = Sload8 v111, 0xf
  1259  	v113:i64 = Iconst_64 0x1
  1260  	v114:i64 = UExtend v2, 32->64
  1261  	v115:i64 = Iadd v114, v113
  1262  	v116:i32 = Icmp lt_u, v5, v115
  1263  	ExitIfTrue v116, exec_ctx, memory_out_of_bounds
  1264  	v117:i64 = Iadd v8, v114
  1265  	v118:i64 = Uload8 v117, 0x0
  1266  	v119:i64 = Iconst_64 0x10
  1267  	v120:i64 = UExtend v2, 32->64
  1268  	v121:i64 = Iadd v120, v119
  1269  	v122:i32 = Icmp lt_u, v5, v121
  1270  	ExitIfTrue v122, exec_ctx, memory_out_of_bounds
  1271  	v123:i64 = Iadd v8, v120
  1272  	v124:i64 = Uload8 v123, 0xf
  1273  	v125:i64 = Iconst_64 0x2
  1274  	v126:i64 = UExtend v2, 32->64
  1275  	v127:i64 = Iadd v126, v125
  1276  	v128:i32 = Icmp lt_u, v5, v127
  1277  	ExitIfTrue v128, exec_ctx, memory_out_of_bounds
  1278  	v129:i64 = Iadd v8, v126
  1279  	v130:i64 = Sload16 v129, 0x0
  1280  	v131:i64 = Iconst_64 0x11
  1281  	v132:i64 = UExtend v2, 32->64
  1282  	v133:i64 = Iadd v132, v131
  1283  	v134:i32 = Icmp lt_u, v5, v133
  1284  	ExitIfTrue v134, exec_ctx, memory_out_of_bounds
  1285  	v135:i64 = Iadd v8, v132
  1286  	v136:i64 = Sload16 v135, 0xf
  1287  	v137:i64 = Iconst_64 0x2
  1288  	v138:i64 = UExtend v2, 32->64
  1289  	v139:i64 = Iadd v138, v137
  1290  	v140:i32 = Icmp lt_u, v5, v139
  1291  	ExitIfTrue v140, exec_ctx, memory_out_of_bounds
  1292  	v141:i64 = Iadd v8, v138
  1293  	v142:i64 = Uload16 v141, 0x0
  1294  	v143:i64 = Iconst_64 0x11
  1295  	v144:i64 = UExtend v2, 32->64
  1296  	v145:i64 = Iadd v144, v143
  1297  	v146:i32 = Icmp lt_u, v5, v145
  1298  	ExitIfTrue v146, exec_ctx, memory_out_of_bounds
  1299  	v147:i64 = Iadd v8, v144
  1300  	v148:i64 = Uload16 v147, 0xf
  1301  	v149:i64 = Iconst_64 0x4
  1302  	v150:i64 = UExtend v2, 32->64
  1303  	v151:i64 = Iadd v150, v149
  1304  	v152:i32 = Icmp lt_u, v5, v151
  1305  	ExitIfTrue v152, exec_ctx, memory_out_of_bounds
  1306  	v153:i64 = Iadd v8, v150
  1307  	v154:i64 = Sload32 v153, 0x0
  1308  	v155:i64 = Iconst_64 0x13
  1309  	v156:i64 = UExtend v2, 32->64
  1310  	v157:i64 = Iadd v156, v155
  1311  	v158:i32 = Icmp lt_u, v5, v157
  1312  	ExitIfTrue v158, exec_ctx, memory_out_of_bounds
  1313  	v159:i64 = Iadd v8, v156
  1314  	v160:i64 = Sload32 v159, 0xf
  1315  	v161:i64 = Iconst_64 0x4
  1316  	v162:i64 = UExtend v2, 32->64
  1317  	v163:i64 = Iadd v162, v161
  1318  	v164:i32 = Icmp lt_u, v5, v163
  1319  	ExitIfTrue v164, exec_ctx, memory_out_of_bounds
  1320  	v165:i64 = Iadd v8, v162
  1321  	v166:i64 = Uload32 v165, 0x0
  1322  	v167:i64 = Iconst_64 0x13
  1323  	v168:i64 = UExtend v2, 32->64
  1324  	v169:i64 = Iadd v168, v167
  1325  	v170:i32 = Icmp lt_u, v5, v169
  1326  	ExitIfTrue v170, exec_ctx, memory_out_of_bounds
  1327  	v171:i64 = Iadd v8, v168
  1328  	v172:i64 = Uload32 v171, 0xf
  1329  	Jump blk_ret, v10, v16, v22, v28, v34, v40, v46, v52, v58, v64, v70, v76, v82, v88, v94, v100, v106, v112, v118, v124, v130, v136, v142, v148, v154, v160, v166, v172
  1330  `,
  1331  		},
  1332  		{
  1333  			name: "globals_get",
  1334  			m:    testcases.GlobalsGet.Module,
  1335  			exp: `
  1336  blk0: (exec_ctx:i64, module_ctx:i64)
  1337  	v2:i64 = Load module_ctx, 0x8
  1338  	v3:i32 = Load v2, 0x8
  1339  	v4:i64 = Load module_ctx, 0x10
  1340  	v5:i64 = Load v4, 0x8
  1341  	v6:i64 = Load module_ctx, 0x18
  1342  	v7:f32 = Load v6, 0x8
  1343  	v8:i64 = Load module_ctx, 0x20
  1344  	v9:f64 = Load v8, 0x8
  1345  	Jump blk_ret, v3, v5, v7, v9
  1346  `,
  1347  		},
  1348  		{
  1349  			name: "globals_set",
  1350  			m:    testcases.GlobalsSet.Module,
  1351  			exp: `
  1352  blk0: (exec_ctx:i64, module_ctx:i64)
  1353  	v2:i32 = Iconst_32 0x1
  1354  	v3:i64 = Load module_ctx, 0x8
  1355  	Store v2, v3, 0x8
  1356  	v4:i64 = Iconst_64 0x2
  1357  	v5:i64 = Load module_ctx, 0x10
  1358  	Store v4, v5, 0x8
  1359  	v6:f32 = F32const 3.000000
  1360  	v7:i64 = Load module_ctx, 0x18
  1361  	Store v6, v7, 0x8
  1362  	v8:f64 = F64const 4.000000
  1363  	v9:i64 = Load module_ctx, 0x20
  1364  	Store v8, v9, 0x8
  1365  	Jump blk_ret, v2, v4, v6, v8
  1366  `,
  1367  		},
  1368  		{
  1369  			name: "globals_mutable",
  1370  			m:    testcases.GlobalsMutable.Module,
  1371  			exp: `
  1372  signatures:
  1373  	sig1: i64i64_v
  1374  
  1375  blk0: (exec_ctx:i64, module_ctx:i64)
  1376  	v2:i64 = Load module_ctx, 0x8
  1377  	v3:i32 = Load v2, 0x8
  1378  	v4:i64 = Load module_ctx, 0x10
  1379  	v5:i64 = Load v4, 0x8
  1380  	v6:i64 = Load module_ctx, 0x18
  1381  	v7:f32 = Load v6, 0x8
  1382  	v8:i64 = Load module_ctx, 0x20
  1383  	v9:f64 = Load v8, 0x8
  1384  	Store module_ctx, exec_ctx, 0x8
  1385  	Call f1:sig1, exec_ctx, module_ctx
  1386  	v10:i64 = Load module_ctx, 0x8
  1387  	v11:i32 = Load v10, 0x8
  1388  	v12:i64 = Load module_ctx, 0x10
  1389  	v13:i64 = Load v12, 0x8
  1390  	v14:i64 = Load module_ctx, 0x18
  1391  	v15:f32 = Load v14, 0x8
  1392  	v16:i64 = Load module_ctx, 0x20
  1393  	v17:f64 = Load v16, 0x8
  1394  	Jump blk_ret, v3, v5, v7, v9, v11, v13, v15, v17
  1395  `,
  1396  			expAfterOpt: `
  1397  signatures:
  1398  	sig1: i64i64_v
  1399  
  1400  blk0: (exec_ctx:i64, module_ctx:i64)
  1401  	v2:i64 = Load module_ctx, 0x8
  1402  	v3:i32 = Load v2, 0x8
  1403  	v4:i64 = Load module_ctx, 0x10
  1404  	v5:i64 = Load v4, 0x8
  1405  	v6:i64 = Load module_ctx, 0x18
  1406  	v7:f32 = Load v6, 0x8
  1407  	v8:i64 = Load module_ctx, 0x20
  1408  	v9:f64 = Load v8, 0x8
  1409  	Store module_ctx, exec_ctx, 0x8
  1410  	Call f1:sig1, exec_ctx, module_ctx
  1411  	v10:i64 = Load module_ctx, 0x8
  1412  	v11:i32 = Load v10, 0x8
  1413  	v12:i64 = Load module_ctx, 0x10
  1414  	v13:i64 = Load v12, 0x8
  1415  	v14:i64 = Load module_ctx, 0x18
  1416  	v15:f32 = Load v14, 0x8
  1417  	v16:i64 = Load module_ctx, 0x20
  1418  	v17:f64 = Load v16, 0x8
  1419  	Jump blk_ret, v3, v5, v7, v9, v11, v13, v15, v17
  1420  `,
  1421  		},
  1422  		{
  1423  			name: "imported_memory_grow",
  1424  			m:    testcases.ImportedMemoryGrow.Module,
  1425  			exp: `
  1426  signatures:
  1427  	sig0: i64i64_i32
  1428  	sig2: i64i32_i32
  1429  
  1430  blk0: (exec_ctx:i64, module_ctx:i64)
  1431  	Store module_ctx, exec_ctx, 0x8
  1432  	v2:i64 = Load module_ctx, 0x18
  1433  	v3:i64 = Load module_ctx, 0x20
  1434  	v4:i32 = CallIndirect v2:sig0, exec_ctx, v3
  1435  	v5:i64 = Load module_ctx, 0x8
  1436  	v6:i64 = Load v5, 0x0
  1437  	v7:i64 = Load module_ctx, 0x8
  1438  	v8:i64 = Load v7, 0x8
  1439  	v9:i64 = Load module_ctx, 0x8
  1440  	v10:i32 = Load v9, 0x8
  1441  	v11:i32 = Iconst_32 0x10
  1442  	v12:i32 = Ushr v10, v11
  1443  	v13:i32 = Iconst_32 0xa
  1444  	Store module_ctx, exec_ctx, 0x8
  1445  	v14:i64 = Load exec_ctx, 0x48
  1446  	v15:i32 = CallIndirect v14:sig2, exec_ctx, v13
  1447  	v16:i64 = Load module_ctx, 0x8
  1448  	v17:i64 = Load v16, 0x0
  1449  	v18:i64 = Load module_ctx, 0x8
  1450  	v19:i64 = Load v18, 0x8
  1451  	Store module_ctx, exec_ctx, 0x8
  1452  	v20:i64 = Load module_ctx, 0x18
  1453  	v21:i64 = Load module_ctx, 0x20
  1454  	v22:i32 = CallIndirect v20:sig0, exec_ctx, v21
  1455  	v23:i64 = Load module_ctx, 0x8
  1456  	v24:i64 = Load v23, 0x0
  1457  	v25:i64 = Load module_ctx, 0x8
  1458  	v26:i64 = Load v25, 0x8
  1459  	v27:i64 = Load module_ctx, 0x8
  1460  	v28:i32 = Load v27, 0x8
  1461  	v29:i32 = Iconst_32 0x10
  1462  	v30:i32 = Ushr v28, v29
  1463  	Jump blk_ret, v4, v12, v22, v30
  1464  `,
  1465  			expAfterOpt: `
  1466  signatures:
  1467  	sig0: i64i64_i32
  1468  	sig2: i64i32_i32
  1469  
  1470  blk0: (exec_ctx:i64, module_ctx:i64)
  1471  	Store module_ctx, exec_ctx, 0x8
  1472  	v2:i64 = Load module_ctx, 0x18
  1473  	v3:i64 = Load module_ctx, 0x20
  1474  	v4:i32 = CallIndirect v2:sig0, exec_ctx, v3
  1475  	v9:i64 = Load module_ctx, 0x8
  1476  	v10:i32 = Load v9, 0x8
  1477  	v11:i32 = Iconst_32 0x10
  1478  	v12:i32 = Ushr v10, v11
  1479  	v13:i32 = Iconst_32 0xa
  1480  	Store module_ctx, exec_ctx, 0x8
  1481  	v14:i64 = Load exec_ctx, 0x48
  1482  	v15:i32 = CallIndirect v14:sig2, exec_ctx, v13
  1483  	Store module_ctx, exec_ctx, 0x8
  1484  	v20:i64 = Load module_ctx, 0x18
  1485  	v21:i64 = Load module_ctx, 0x20
  1486  	v22:i32 = CallIndirect v20:sig0, exec_ctx, v21
  1487  	v27:i64 = Load module_ctx, 0x8
  1488  	v28:i32 = Load v27, 0x8
  1489  	v29:i32 = Iconst_32 0x10
  1490  	v30:i32 = Ushr v28, v29
  1491  	Jump blk_ret, v4, v12, v22, v30
  1492  `,
  1493  		},
  1494  		{
  1495  			name: "memory_size_grow",
  1496  			m:    testcases.MemorySizeGrow.Module,
  1497  			exp: `
  1498  signatures:
  1499  	sig1: i64i32_i32
  1500  
  1501  blk0: (exec_ctx:i64, module_ctx:i64)
  1502  	v2:i32 = Iconst_32 0x1
  1503  	Store module_ctx, exec_ctx, 0x8
  1504  	v3:i64 = Load exec_ctx, 0x48
  1505  	v4:i32 = CallIndirect v3:sig1, exec_ctx, v2
  1506  	v5:i64 = Load module_ctx, 0x8
  1507  	v6:i64 = Uload32 module_ctx, 0x10
  1508  	v7:i32 = Load module_ctx, 0x10
  1509  	v8:i32 = Iconst_32 0x10
  1510  	v9:i32 = Ushr v7, v8
  1511  	v10:i32 = Iconst_32 0x1
  1512  	Store module_ctx, exec_ctx, 0x8
  1513  	v11:i64 = Load exec_ctx, 0x48
  1514  	v12:i32 = CallIndirect v11:sig1, exec_ctx, v10
  1515  	v13:i64 = Load module_ctx, 0x8
  1516  	v14:i64 = Uload32 module_ctx, 0x10
  1517  	Jump blk_ret, v4, v9, v12
  1518  `,
  1519  			expAfterOpt: `
  1520  signatures:
  1521  	sig1: i64i32_i32
  1522  
  1523  blk0: (exec_ctx:i64, module_ctx:i64)
  1524  	v2:i32 = Iconst_32 0x1
  1525  	Store module_ctx, exec_ctx, 0x8
  1526  	v3:i64 = Load exec_ctx, 0x48
  1527  	v4:i32 = CallIndirect v3:sig1, exec_ctx, v2
  1528  	v7:i32 = Load module_ctx, 0x10
  1529  	v8:i32 = Iconst_32 0x10
  1530  	v9:i32 = Ushr v7, v8
  1531  	v10:i32 = Iconst_32 0x1
  1532  	Store module_ctx, exec_ctx, 0x8
  1533  	v11:i64 = Load exec_ctx, 0x48
  1534  	v12:i32 = CallIndirect v11:sig1, exec_ctx, v10
  1535  	Jump blk_ret, v4, v9, v12
  1536  `,
  1537  		},
  1538  		{
  1539  			name: "call_indirect", m: testcases.CallIndirect.Module,
  1540  			exp: `
  1541  signatures:
  1542  	sig2: i64i64_i32
  1543  
  1544  blk0: (exec_ctx:i64, module_ctx:i64, v2:i32)
  1545  	v3:i64 = Load module_ctx, 0x10
  1546  	v4:i32 = Load v3, 0x8
  1547  	v5:i32 = Icmp ge_u, v2, v4
  1548  	ExitIfTrue v5, exec_ctx, table_out_of_bounds
  1549  	v6:i64 = Load v3, 0x0
  1550  	v7:i64 = Iconst_64 0x3
  1551  	v8:i32 = Ishl v2, v7
  1552  	v9:i64 = Iadd v6, v8
  1553  	v10:i64 = Load v9, 0x0
  1554  	v11:i64 = Iconst_64 0x0
  1555  	v12:i32 = Icmp eq, v10, v11
  1556  	ExitIfTrue v12, exec_ctx, indirect_call_null_pointer
  1557  	v13:i32 = Load v10, 0x10
  1558  	v14:i64 = Load module_ctx, 0x8
  1559  	v15:i32 = Load v14, 0x8
  1560  	v16:i32 = Icmp neq, v13, v15
  1561  	ExitIfTrue v16, exec_ctx, indirect_call_type_mismatch
  1562  	v17:i64 = Load v10, 0x0
  1563  	v18:i64 = Load v10, 0x8
  1564  	Store module_ctx, exec_ctx, 0x8
  1565  	v19:i32 = CallIndirect v17:sig2, exec_ctx, v18
  1566  	Jump blk_ret, v19
  1567  `,
  1568  		},
  1569  		{
  1570  			name: "br_table", m: testcases.BrTable.Module,
  1571  			exp: `
  1572  blk0: (exec_ctx:i64, module_ctx:i64, v2:i32)
  1573  	BrTable v2, [blk7, blk8, blk9, blk10, blk11, blk12, blk13]
  1574  
  1575  blk1: () <-- (blk12)
  1576  	v8:i32 = Iconst_32 0x10
  1577  	Return v8
  1578  
  1579  blk2: () <-- (blk11)
  1580  	v7:i32 = Iconst_32 0xf
  1581  	Return v7
  1582  
  1583  blk3: () <-- (blk10)
  1584  	v6:i32 = Iconst_32 0xe
  1585  	Return v6
  1586  
  1587  blk4: () <-- (blk9)
  1588  	v5:i32 = Iconst_32 0xd
  1589  	Return v5
  1590  
  1591  blk5: () <-- (blk8)
  1592  	v4:i32 = Iconst_32 0xc
  1593  	Return v4
  1594  
  1595  blk6: () <-- (blk7,blk13)
  1596  	v3:i32 = Iconst_32 0xb
  1597  	Return v3
  1598  
  1599  blk7: () <-- (blk0)
  1600  	Jump blk6
  1601  
  1602  blk8: () <-- (blk0)
  1603  	Jump blk5
  1604  
  1605  blk9: () <-- (blk0)
  1606  	Jump blk4
  1607  
  1608  blk10: () <-- (blk0)
  1609  	Jump blk3
  1610  
  1611  blk11: () <-- (blk0)
  1612  	Jump blk2
  1613  
  1614  blk12: () <-- (blk0)
  1615  	Jump blk1
  1616  
  1617  blk13: () <-- (blk0)
  1618  	Jump blk6
  1619  `,
  1620  		},
  1621  		{
  1622  			name: "br_table_with_arg", m: testcases.BrTableWithArg.Module,
  1623  			exp: `
  1624  blk0: (exec_ctx:i64, module_ctx:i64, v2:i32, v3:i32)
  1625  	BrTable v2, [blk7, blk8, blk9, blk10, blk11, blk12, blk13]
  1626  
  1627  blk1: (v4:i32) <-- (blk12)
  1628  	v20:i32 = Iconst_32 0x10
  1629  	v21:i32 = Iadd v4, v20
  1630  	Return v21
  1631  
  1632  blk2: (v5:i32) <-- (blk11)
  1633  	v18:i32 = Iconst_32 0xf
  1634  	v19:i32 = Iadd v5, v18
  1635  	Return v19
  1636  
  1637  blk3: (v6:i32) <-- (blk10)
  1638  	v16:i32 = Iconst_32 0xe
  1639  	v17:i32 = Iadd v6, v16
  1640  	Return v17
  1641  
  1642  blk4: (v7:i32) <-- (blk9)
  1643  	v14:i32 = Iconst_32 0xd
  1644  	v15:i32 = Iadd v7, v14
  1645  	Return v15
  1646  
  1647  blk5: (v8:i32) <-- (blk8)
  1648  	v12:i32 = Iconst_32 0xc
  1649  	v13:i32 = Iadd v8, v12
  1650  	Return v13
  1651  
  1652  blk6: (v9:i32) <-- (blk7,blk13)
  1653  	v10:i32 = Iconst_32 0xb
  1654  	v11:i32 = Iadd v9, v10
  1655  	Return v11
  1656  
  1657  blk7: () <-- (blk0)
  1658  	Jump blk6, v3
  1659  
  1660  blk8: () <-- (blk0)
  1661  	Jump blk5, v3
  1662  
  1663  blk9: () <-- (blk0)
  1664  	Jump blk4, v3
  1665  
  1666  blk10: () <-- (blk0)
  1667  	Jump blk3, v3
  1668  
  1669  blk11: () <-- (blk0)
  1670  	Jump blk2, v3
  1671  
  1672  blk12: () <-- (blk0)
  1673  	Jump blk1, v3
  1674  
  1675  blk13: () <-- (blk0)
  1676  	Jump blk6, v3
  1677  `,
  1678  
  1679  			// TODO: these trivial two hop jumps should be optimized away.
  1680  			expAfterOpt: `
  1681  blk0: (exec_ctx:i64, module_ctx:i64, v2:i32, v3:i32)
  1682  	BrTable v2, [blk7, blk8, blk9, blk10, blk11, blk12, blk13]
  1683  
  1684  blk1: () <-- (blk12)
  1685  	v20:i32 = Iconst_32 0x10
  1686  	v21:i32 = Iadd v3, v20
  1687  	Return v21
  1688  
  1689  blk2: () <-- (blk11)
  1690  	v18:i32 = Iconst_32 0xf
  1691  	v19:i32 = Iadd v3, v18
  1692  	Return v19
  1693  
  1694  blk3: () <-- (blk10)
  1695  	v16:i32 = Iconst_32 0xe
  1696  	v17:i32 = Iadd v3, v16
  1697  	Return v17
  1698  
  1699  blk4: () <-- (blk9)
  1700  	v14:i32 = Iconst_32 0xd
  1701  	v15:i32 = Iadd v3, v14
  1702  	Return v15
  1703  
  1704  blk5: () <-- (blk8)
  1705  	v12:i32 = Iconst_32 0xc
  1706  	v13:i32 = Iadd v3, v12
  1707  	Return v13
  1708  
  1709  blk6: () <-- (blk7,blk13)
  1710  	v10:i32 = Iconst_32 0xb
  1711  	v11:i32 = Iadd v3, v10
  1712  	Return v11
  1713  
  1714  blk7: () <-- (blk0)
  1715  	Jump blk6
  1716  
  1717  blk8: () <-- (blk0)
  1718  	Jump blk5
  1719  
  1720  blk9: () <-- (blk0)
  1721  	Jump blk4
  1722  
  1723  blk10: () <-- (blk0)
  1724  	Jump blk3
  1725  
  1726  blk11: () <-- (blk0)
  1727  	Jump blk2
  1728  
  1729  blk12: () <-- (blk0)
  1730  	Jump blk1
  1731  
  1732  blk13: () <-- (blk0)
  1733  	Jump blk6
  1734  `,
  1735  		},
  1736  		{
  1737  			name: "if_then_end_nesting_unreachable_if_then_else_end", m: testcases.IfThenEndNestingUnreachableIfThenElseEnd.Module,
  1738  			exp: `
  1739  blk0: (exec_ctx:i64, module_ctx:i64, v2:f64, v3:f64, v4:f64)
  1740  	v6:i32 = Load module_ctx, 0x10
  1741  	v7:i32 = Iconst_32 0x10
  1742  	v8:i32 = Ushr v6, v7
  1743  	Brz v8, blk3
  1744  	Jump blk2
  1745  
  1746  blk1: (v5:i64) <-- (blk4)
  1747  	Jump blk_ret
  1748  
  1749  blk2: () <-- (blk0)
  1750  	v9:i32 = Load module_ctx, 0x10
  1751  	v10:i32 = Iconst_32 0x10
  1752  	v11:i32 = Ushr v9, v10
  1753  	Jump blk4
  1754  
  1755  blk3: () <-- (blk0)
  1756  	Jump blk4
  1757  
  1758  blk4: () <-- (blk2,blk3)
  1759  	v12:i64 = Iconst_64 0x0
  1760  	Jump blk1, v12
  1761  `,
  1762  			expAfterOpt: `
  1763  blk0: (exec_ctx:i64, module_ctx:i64, v2:f64, v3:f64, v4:f64)
  1764  	v6:i32 = Load module_ctx, 0x10
  1765  	v7:i32 = Iconst_32 0x10
  1766  	v8:i32 = Ushr v6, v7
  1767  	Brz v8, blk3
  1768  	Jump blk2
  1769  
  1770  blk1: () <-- (blk4)
  1771  	Jump blk_ret
  1772  
  1773  blk2: () <-- (blk0)
  1774  	Jump blk4
  1775  
  1776  blk3: () <-- (blk0)
  1777  	Jump blk4
  1778  
  1779  blk4: () <-- (blk2,blk3)
  1780  	Jump blk1
  1781  `,
  1782  		},
  1783  		{
  1784  			name: "VecShuffle",
  1785  			m:    testcases.VecShuffle.Module,
  1786  			exp: `
  1787  blk0: (exec_ctx:i64, module_ctx:i64, v2:v128, v3:v128)
  1788  	v4:v128 = Shuffle.[0 1 2 3 4 5 6 7 24 25 26 27 28 29 30 31] v2, v3
  1789  	Jump blk_ret, v4
  1790  `,
  1791  		},
  1792  	} {
  1793  
  1794  		tc := tc
  1795  		t.Run(tc.name, func(t *testing.T) {
  1796  			// Just in case let's check the test module is valid.
  1797  			err := tc.m.Validate(api.CoreFeaturesV2)
  1798  			require.NoError(t, err, "invalid test case module!")
  1799  
  1800  			b := ssa.NewBuilder()
  1801  
  1802  			offset := wazevoapi.NewModuleContextOffsetData(tc.m, tc.needListener)
  1803  			fc := NewFrontendCompiler(tc.m, b, &offset, tc.ensureTermination, tc.needListener, false)
  1804  			typeIndex := tc.m.FunctionSection[tc.targetIndex]
  1805  			code := &tc.m.CodeSection[tc.targetIndex]
  1806  			fc.Init(tc.targetIndex, typeIndex, &tc.m.TypeSection[typeIndex], code.LocalTypes, code.Body, tc.needListener, 0)
  1807  
  1808  			fc.LowerToSSA()
  1809  
  1810  			actual := fc.formatBuilder()
  1811  			require.Equal(t, tc.exp, actual)
  1812  
  1813  			b.RunPasses()
  1814  			if expAfterOpt := tc.expAfterOpt; expAfterOpt != "" {
  1815  				actualAfterOpt := fc.formatBuilder()
  1816  				require.Equal(t, expAfterOpt, actualAfterOpt)
  1817  			}
  1818  
  1819  			// Dry-run without checking the results of LayoutBlocks function.
  1820  			b.LayoutBlocks()
  1821  		})
  1822  	}
  1823  }
  1824  
  1825  func TestSignatureForListener(t *testing.T) {
  1826  	for _, tc := range []struct {
  1827  		name          string
  1828  		sig           *wasm.FunctionType
  1829  		before, after *ssa.Signature
  1830  	}{
  1831  		{
  1832  			name:   "empty",
  1833  			sig:    &wasm.FunctionType{},
  1834  			before: &ssa.Signature{Params: []ssa.Type{ssa.TypeI64, ssa.TypeI32}},
  1835  			after:  &ssa.Signature{Params: []ssa.Type{ssa.TypeI64, ssa.TypeI32}},
  1836  		},
  1837  		{
  1838  			name: "multi",
  1839  			sig: &wasm.FunctionType{
  1840  				Params: []wasm.ValueType{wasm.ValueTypeF64, wasm.ValueTypeI32},
  1841  				Results: []wasm.ValueType{
  1842  					wasm.ValueTypeI64, wasm.ValueTypeI32, wasm.ValueTypeF32, wasm.ValueTypeF64, wasm.ValueTypeV128,
  1843  				},
  1844  			},
  1845  			before: &ssa.Signature{
  1846  				Params: []ssa.Type{
  1847  					ssa.TypeI64, ssa.TypeI32,
  1848  					ssa.TypeF64, ssa.TypeI32,
  1849  				},
  1850  			},
  1851  			after: &ssa.Signature{
  1852  				Params: []ssa.Type{
  1853  					ssa.TypeI64, ssa.TypeI32,
  1854  					ssa.TypeI64, ssa.TypeI32, ssa.TypeF32, ssa.TypeF64, ssa.TypeV128,
  1855  				},
  1856  			},
  1857  		},
  1858  	} {
  1859  		tc := tc
  1860  		t.Run(tc.name, func(t *testing.T) {
  1861  			before, after := SignatureForListener(tc.sig)
  1862  			require.Equal(t, tc.before, before)
  1863  			require.Equal(t, tc.after, after)
  1864  		})
  1865  	}
  1866  }
  1867  
  1868  func TestCompiler_declareSignatures(t *testing.T) {
  1869  	m := &wasm.Module{
  1870  		TypeSection: []wasm.FunctionType{
  1871  			{},
  1872  			{Params: []wasm.ValueType{wasm.ValueTypeI64, wasm.ValueTypeI32}},
  1873  			{Params: []wasm.ValueType{wasm.ValueTypeF64, wasm.ValueTypeI32}},
  1874  			{Results: []wasm.ValueType{wasm.ValueTypeI64, wasm.ValueTypeI32}},
  1875  		},
  1876  	}
  1877  
  1878  	t.Run("listener=false", func(t *testing.T) {
  1879  		builder := ssa.NewBuilder()
  1880  		c := &Compiler{m: m, ssaBuilder: builder}
  1881  		c.declareSignatures(false)
  1882  
  1883  		declaredSigs := builder.Signatures()
  1884  		expected := []*ssa.Signature{
  1885  			{ID: 0, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI64}},
  1886  			{ID: 1, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI64, ssa.TypeI64, ssa.TypeI32}},
  1887  			{ID: 2, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI64, ssa.TypeF64, ssa.TypeI32}},
  1888  			{ID: 3, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI64}, Results: []ssa.Type{ssa.TypeI64, ssa.TypeI32}},
  1889  			{ID: 4, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI32}, Results: []ssa.Type{ssa.TypeI32}},
  1890  			{ID: 5, Params: []ssa.Type{ssa.TypeI64}},
  1891  			{ID: 6, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI32, ssa.TypeI32, ssa.TypeI64}, Results: []ssa.Type{ssa.TypeI32}},
  1892  			{ID: 7, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI32}, Results: []ssa.Type{ssa.TypeI64}},
  1893  			{ID: 8, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI64, ssa.TypeI32}},
  1894  		}
  1895  
  1896  		require.Equal(t, len(expected), len(declaredSigs))
  1897  		for i := 0; i < len(expected); i++ {
  1898  			require.Equal(t, expected[i].String(), declaredSigs[i].String(), i)
  1899  		}
  1900  	})
  1901  
  1902  	t.Run("listener=false", func(t *testing.T) {
  1903  		builder := ssa.NewBuilder()
  1904  		c := &Compiler{m: m, ssaBuilder: builder}
  1905  		c.declareSignatures(true)
  1906  
  1907  		declaredSigs := builder.Signatures()
  1908  
  1909  		expected := []*ssa.Signature{
  1910  			{ID: 0, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI64}},
  1911  			{ID: 1, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI64, ssa.TypeI64, ssa.TypeI32}},
  1912  			{ID: 2, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI64, ssa.TypeF64, ssa.TypeI32}},
  1913  			{ID: 3, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI64}, Results: []ssa.Type{ssa.TypeI64, ssa.TypeI32}},
  1914  			// Before.
  1915  			{ID: 4, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI32}},
  1916  			{ID: 5, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI32, ssa.TypeI64, ssa.TypeI32}},
  1917  			{ID: 6, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI32, ssa.TypeF64, ssa.TypeI32}},
  1918  			{ID: 7, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI32}},
  1919  			// After.
  1920  			{ID: 8, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI32}},
  1921  			{ID: 9, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI32}},
  1922  			{ID: 10, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI32}},
  1923  			{ID: 11, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI32, ssa.TypeI64, ssa.TypeI32}},
  1924  			// Misc.
  1925  			{ID: 12, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI32}, Results: []ssa.Type{ssa.TypeI32}},
  1926  			{ID: 13, Params: []ssa.Type{ssa.TypeI64}},
  1927  			{ID: 14, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI32, ssa.TypeI32, ssa.TypeI64}, Results: []ssa.Type{ssa.TypeI32}},
  1928  			{ID: 15, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI32}, Results: []ssa.Type{ssa.TypeI64}},
  1929  			{ID: 16, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI64, ssa.TypeI32}},
  1930  		}
  1931  		require.Equal(t, len(expected), len(declaredSigs))
  1932  		for i := 0; i < len(declaredSigs); i++ {
  1933  			require.Equal(t, expected[i].String(), declaredSigs[i].String(), i)
  1934  		}
  1935  	})
  1936  }