github.com/bananabytelabs/wazero@v0.0.0-20240105073314-54b22a776da8/internal/engine/wazevo/frontend/frontend_test.go (about)

     1  package frontend
     2  
     3  import (
     4  	"testing"
     5  
     6  	"github.com/bananabytelabs/wazero/api"
     7  	"github.com/bananabytelabs/wazero/internal/engine/wazevo/ssa"
     8  	"github.com/bananabytelabs/wazero/internal/engine/wazevo/testcases"
     9  	"github.com/bananabytelabs/wazero/internal/engine/wazevo/wazevoapi"
    10  	"github.com/bananabytelabs/wazero/internal/testing/require"
    11  	"github.com/bananabytelabs/wazero/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:i32 = Load v10, 0x0
  1023  	Jump blk_ret, v11
  1024  `,
  1025  		},
  1026  		{
  1027  			name: "memory_load_basic", m: testcases.MemoryLoadBasic.Module,
  1028  			exp: `
  1029  blk0: (exec_ctx:i64, module_ctx:i64, v2:i32)
  1030  	v3:i64 = Iconst_64 0x4
  1031  	v4:i64 = UExtend v2, 32->64
  1032  	v5:i64 = Uload32 module_ctx, 0x10
  1033  	v6:i64 = Iadd v4, v3
  1034  	v7:i32 = Icmp lt_u, v5, v6
  1035  	ExitIfTrue v7, exec_ctx, memory_out_of_bounds
  1036  	v8:i64 = Load module_ctx, 0x8
  1037  	v9:i64 = Iadd v8, v4
  1038  	v10:i32 = Load v9, 0x0
  1039  	Jump blk_ret, v10
  1040  `,
  1041  		},
  1042  		{
  1043  			name: "memory_load_basic2", m: testcases.MemoryLoadBasic2.Module,
  1044  			exp: `
  1045  signatures:
  1046  	sig1: i64i64_v
  1047  
  1048  blk0: (exec_ctx:i64, module_ctx:i64, v2:i32)
  1049  	v3:i32 = Iconst_32 0x0
  1050  	v4:i32 = Icmp eq, v2, v3
  1051  	Brz v4, blk2
  1052  	Jump blk1
  1053  
  1054  blk1: () <-- (blk0)
  1055  	Store module_ctx, exec_ctx, 0x8
  1056  	Call f1:sig1, exec_ctx, module_ctx
  1057  	v5:i64 = Load module_ctx, 0x8
  1058  	v6:i64 = Uload32 module_ctx, 0x10
  1059  	Jump blk3, v2
  1060  
  1061  blk2: () <-- (blk0)
  1062  	Jump blk3, v2
  1063  
  1064  blk3: (v7:i32) <-- (blk1,blk2)
  1065  	v8:i64 = Iconst_64 0x4
  1066  	v9:i64 = UExtend v7, 32->64
  1067  	v10:i64 = Uload32 module_ctx, 0x10
  1068  	v11:i64 = Iadd v9, v8
  1069  	v12:i32 = Icmp lt_u, v10, v11
  1070  	ExitIfTrue v12, exec_ctx, memory_out_of_bounds
  1071  	v13:i64 = Load module_ctx, 0x8
  1072  	v14:i64 = Iadd v13, v9
  1073  	v15:i32 = Load v14, 0x0
  1074  	Jump blk_ret, v15
  1075  `,
  1076  			expAfterOpt: `
  1077  signatures:
  1078  	sig1: i64i64_v
  1079  
  1080  blk0: (exec_ctx:i64, module_ctx:i64, v2:i32)
  1081  	v3:i32 = Iconst_32 0x0
  1082  	v4:i32 = Icmp eq, v2, v3
  1083  	Brz v4, blk2
  1084  	Jump blk1
  1085  
  1086  blk1: () <-- (blk0)
  1087  	Store module_ctx, exec_ctx, 0x8
  1088  	Call f1:sig1, exec_ctx, module_ctx
  1089  	Jump blk3
  1090  
  1091  blk2: () <-- (blk0)
  1092  	Jump blk3
  1093  
  1094  blk3: () <-- (blk1,blk2)
  1095  	v8:i64 = Iconst_64 0x4
  1096  	v9:i64 = UExtend v2, 32->64
  1097  	v10:i64 = Uload32 module_ctx, 0x10
  1098  	v11:i64 = Iadd v9, v8
  1099  	v12:i32 = Icmp lt_u, v10, v11
  1100  	ExitIfTrue v12, exec_ctx, memory_out_of_bounds
  1101  	v13:i64 = Load module_ctx, 0x8
  1102  	v14:i64 = Iadd v13, v9
  1103  	v15:i32 = Load v14, 0x0
  1104  	Jump blk_ret, v15
  1105  `,
  1106  		},
  1107  		{
  1108  			name: "imported_function_call", m: testcases.ImportedFunctionCall.Module,
  1109  			exp: `
  1110  signatures:
  1111  	sig1: i64i64i32i32_i32
  1112  
  1113  blk0: (exec_ctx:i64, module_ctx:i64, v2:i32)
  1114  	Store module_ctx, exec_ctx, 0x8
  1115  	v3:i64 = Load module_ctx, 0x8
  1116  	v4:i64 = Load module_ctx, 0x10
  1117  	v5:i32 = CallIndirect v3:sig1, exec_ctx, v4, v2, v2
  1118  	Jump blk_ret, v5
  1119  `,
  1120  		},
  1121  		{
  1122  			name: "memory_loads", m: testcases.MemoryLoads.Module,
  1123  			exp: `
  1124  blk0: (exec_ctx:i64, module_ctx:i64, v2:i32)
  1125  	v3:i64 = Iconst_64 0x4
  1126  	v4:i64 = UExtend v2, 32->64
  1127  	v5:i64 = Uload32 module_ctx, 0x10
  1128  	v6:i64 = Iadd v4, v3
  1129  	v7:i32 = Icmp lt_u, v5, v6
  1130  	ExitIfTrue v7, exec_ctx, memory_out_of_bounds
  1131  	v8:i64 = Load module_ctx, 0x8
  1132  	v9:i64 = Iadd v8, v4
  1133  	v10:i32 = Load v9, 0x0
  1134  	v11:i64 = Iconst_64 0x8
  1135  	v12:i64 = UExtend v2, 32->64
  1136  	v13:i64 = Iadd v12, v11
  1137  	v14:i32 = Icmp lt_u, v5, v13
  1138  	ExitIfTrue v14, exec_ctx, memory_out_of_bounds
  1139  	v15:i64 = Load v9, 0x0
  1140  	v16:f32 = Load v9, 0x0
  1141  	v17:f64 = Load v9, 0x0
  1142  	v18:i64 = Iconst_64 0x13
  1143  	v19:i64 = UExtend v2, 32->64
  1144  	v20:i64 = Iadd v19, v18
  1145  	v21:i32 = Icmp lt_u, v5, v20
  1146  	ExitIfTrue v21, exec_ctx, memory_out_of_bounds
  1147  	v22:i32 = Load v9, 0xf
  1148  	v23:i64 = Iconst_64 0x17
  1149  	v24:i64 = UExtend v2, 32->64
  1150  	v25:i64 = Iadd v24, v23
  1151  	v26:i32 = Icmp lt_u, v5, v25
  1152  	ExitIfTrue v26, exec_ctx, memory_out_of_bounds
  1153  	v27:i64 = Load v9, 0xf
  1154  	v28:f32 = Load v9, 0xf
  1155  	v29:f64 = Load v9, 0xf
  1156  	v30:i32 = Sload8 v9, 0x0
  1157  	v31:i32 = Sload8 v9, 0xf
  1158  	v32:i32 = Uload8 v9, 0x0
  1159  	v33:i32 = Uload8 v9, 0xf
  1160  	v34:i32 = Sload16 v9, 0x0
  1161  	v35:i32 = Sload16 v9, 0xf
  1162  	v36:i32 = Uload16 v9, 0x0
  1163  	v37:i32 = Uload16 v9, 0xf
  1164  	v38:i64 = Sload8 v9, 0x0
  1165  	v39:i64 = Sload8 v9, 0xf
  1166  	v40:i64 = Uload8 v9, 0x0
  1167  	v41:i64 = Uload8 v9, 0xf
  1168  	v42:i64 = Sload16 v9, 0x0
  1169  	v43:i64 = Sload16 v9, 0xf
  1170  	v44:i64 = Uload16 v9, 0x0
  1171  	v45:i64 = Uload16 v9, 0xf
  1172  	v46:i64 = Sload32 v9, 0x0
  1173  	v47:i64 = Sload32 v9, 0xf
  1174  	v48:i64 = Uload32 v9, 0x0
  1175  	v49:i64 = Uload32 v9, 0xf
  1176  	Jump blk_ret, v10, v15, v16, v17, v22, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49
  1177  `,
  1178  		},
  1179  		{
  1180  			name: "globals_get",
  1181  			m:    testcases.GlobalsGet.Module,
  1182  			exp: `
  1183  blk0: (exec_ctx:i64, module_ctx:i64)
  1184  	v2:i32 = Load module_ctx, 0x8
  1185  	v3:i64 = Load module_ctx, 0x18
  1186  	v4:f32 = Load module_ctx, 0x28
  1187  	v5:f64 = Load module_ctx, 0x38
  1188  	Jump blk_ret, v2, v3, v4, v5
  1189  `,
  1190  		},
  1191  		{
  1192  			name: "globals_set",
  1193  			m:    testcases.GlobalsSet.Module,
  1194  			exp: `
  1195  blk0: (exec_ctx:i64, module_ctx:i64)
  1196  	v2:i32 = Iconst_32 0x1
  1197  	Store v2, module_ctx, 0x8
  1198  	v3:i64 = Iconst_64 0x2
  1199  	Store v3, module_ctx, 0x18
  1200  	v4:f32 = F32const 3.000000
  1201  	Store v4, module_ctx, 0x28
  1202  	v5:f64 = F64const 4.000000
  1203  	Store v5, module_ctx, 0x38
  1204  	Jump blk_ret, v2, v3, v4, v5
  1205  `,
  1206  		},
  1207  		{
  1208  			name: "globals_mutable",
  1209  			m:    testcases.GlobalsMutable.Module,
  1210  			exp: `
  1211  signatures:
  1212  	sig1: i64i64_v
  1213  
  1214  blk0: (exec_ctx:i64, module_ctx:i64)
  1215  	v2:i32 = Load module_ctx, 0x8
  1216  	v3:i64 = Load module_ctx, 0x18
  1217  	v4:f32 = Load module_ctx, 0x28
  1218  	v5:f64 = Load module_ctx, 0x38
  1219  	Store module_ctx, exec_ctx, 0x8
  1220  	Call f1:sig1, exec_ctx, module_ctx
  1221  	v6:i32 = Load module_ctx, 0x8
  1222  	v7:i64 = Load module_ctx, 0x18
  1223  	v8:f32 = Load module_ctx, 0x28
  1224  	v9:f64 = Load module_ctx, 0x38
  1225  	Jump blk_ret, v2, v3, v4, v5, v6, v7, v8, v9
  1226  `,
  1227  			expAfterOpt: `
  1228  signatures:
  1229  	sig1: i64i64_v
  1230  
  1231  blk0: (exec_ctx:i64, module_ctx:i64)
  1232  	v2:i32 = Load module_ctx, 0x8
  1233  	v3:i64 = Load module_ctx, 0x18
  1234  	v4:f32 = Load module_ctx, 0x28
  1235  	v5:f64 = Load module_ctx, 0x38
  1236  	Store module_ctx, exec_ctx, 0x8
  1237  	Call f1:sig1, exec_ctx, module_ctx
  1238  	v6:i32 = Load module_ctx, 0x8
  1239  	v7:i64 = Load module_ctx, 0x18
  1240  	v8:f32 = Load module_ctx, 0x28
  1241  	v9:f64 = Load module_ctx, 0x38
  1242  	Jump blk_ret, v2, v3, v4, v5, v6, v7, v8, v9
  1243  `,
  1244  		},
  1245  		{
  1246  			name: "imported_memory_grow",
  1247  			m:    testcases.ImportedMemoryGrow.Module,
  1248  			exp: `
  1249  signatures:
  1250  	sig0: i64i64_i32
  1251  	sig2: i64i32_i32
  1252  
  1253  blk0: (exec_ctx:i64, module_ctx:i64)
  1254  	Store module_ctx, exec_ctx, 0x8
  1255  	v2:i64 = Load module_ctx, 0x18
  1256  	v3:i64 = Load module_ctx, 0x20
  1257  	v4:i32 = CallIndirect v2:sig0, exec_ctx, v3
  1258  	v5:i64 = Load module_ctx, 0x8
  1259  	v6:i64 = Load v5, 0x0
  1260  	v7:i64 = Load module_ctx, 0x8
  1261  	v8:i64 = Load v7, 0x8
  1262  	v9:i64 = Load module_ctx, 0x8
  1263  	v10:i32 = Load v9, 0x8
  1264  	v11:i32 = Iconst_32 0x10
  1265  	v12:i32 = Ushr v10, v11
  1266  	v13:i32 = Iconst_32 0xa
  1267  	Store module_ctx, exec_ctx, 0x8
  1268  	v14:i64 = Load exec_ctx, 0x48
  1269  	v15:i32 = CallIndirect v14:sig2, exec_ctx, v13
  1270  	v16:i64 = Load module_ctx, 0x8
  1271  	v17:i64 = Load v16, 0x0
  1272  	v18:i64 = Load module_ctx, 0x8
  1273  	v19:i64 = Load v18, 0x8
  1274  	Store module_ctx, exec_ctx, 0x8
  1275  	v20:i64 = Load module_ctx, 0x18
  1276  	v21:i64 = Load module_ctx, 0x20
  1277  	v22:i32 = CallIndirect v20:sig0, exec_ctx, v21
  1278  	v23:i64 = Load module_ctx, 0x8
  1279  	v24:i64 = Load v23, 0x0
  1280  	v25:i64 = Load module_ctx, 0x8
  1281  	v26:i64 = Load v25, 0x8
  1282  	v27:i64 = Load module_ctx, 0x8
  1283  	v28:i32 = Load v27, 0x8
  1284  	v29:i32 = Iconst_32 0x10
  1285  	v30:i32 = Ushr v28, v29
  1286  	Jump blk_ret, v4, v12, v22, v30
  1287  `,
  1288  			expAfterOpt: `
  1289  signatures:
  1290  	sig0: i64i64_i32
  1291  	sig2: i64i32_i32
  1292  
  1293  blk0: (exec_ctx:i64, module_ctx:i64)
  1294  	Store module_ctx, exec_ctx, 0x8
  1295  	v2:i64 = Load module_ctx, 0x18
  1296  	v3:i64 = Load module_ctx, 0x20
  1297  	v4:i32 = CallIndirect v2:sig0, exec_ctx, v3
  1298  	v9:i64 = Load module_ctx, 0x8
  1299  	v10:i32 = Load v9, 0x8
  1300  	v11:i32 = Iconst_32 0x10
  1301  	v12:i32 = Ushr v10, v11
  1302  	v13:i32 = Iconst_32 0xa
  1303  	Store module_ctx, exec_ctx, 0x8
  1304  	v14:i64 = Load exec_ctx, 0x48
  1305  	v15:i32 = CallIndirect v14:sig2, exec_ctx, v13
  1306  	Store module_ctx, exec_ctx, 0x8
  1307  	v20:i64 = Load module_ctx, 0x18
  1308  	v21:i64 = Load module_ctx, 0x20
  1309  	v22:i32 = CallIndirect v20:sig0, exec_ctx, v21
  1310  	v27:i64 = Load module_ctx, 0x8
  1311  	v28:i32 = Load v27, 0x8
  1312  	v29:i32 = Iconst_32 0x10
  1313  	v30:i32 = Ushr v28, v29
  1314  	Jump blk_ret, v4, v12, v22, v30
  1315  `,
  1316  		},
  1317  		{
  1318  			name: "memory_size_grow",
  1319  			m:    testcases.MemorySizeGrow.Module,
  1320  			exp: `
  1321  signatures:
  1322  	sig1: i64i32_i32
  1323  
  1324  blk0: (exec_ctx:i64, module_ctx:i64)
  1325  	v2:i32 = Iconst_32 0x1
  1326  	Store module_ctx, exec_ctx, 0x8
  1327  	v3:i64 = Load exec_ctx, 0x48
  1328  	v4:i32 = CallIndirect v3:sig1, exec_ctx, v2
  1329  	v5:i64 = Load module_ctx, 0x8
  1330  	v6:i64 = Uload32 module_ctx, 0x10
  1331  	v7:i32 = Load module_ctx, 0x10
  1332  	v8:i32 = Iconst_32 0x10
  1333  	v9:i32 = Ushr v7, v8
  1334  	v10:i32 = Iconst_32 0x1
  1335  	Store module_ctx, exec_ctx, 0x8
  1336  	v11:i64 = Load exec_ctx, 0x48
  1337  	v12:i32 = CallIndirect v11:sig1, exec_ctx, v10
  1338  	v13:i64 = Load module_ctx, 0x8
  1339  	v14:i64 = Uload32 module_ctx, 0x10
  1340  	Jump blk_ret, v4, v9, v12
  1341  `,
  1342  			expAfterOpt: `
  1343  signatures:
  1344  	sig1: i64i32_i32
  1345  
  1346  blk0: (exec_ctx:i64, module_ctx:i64)
  1347  	v2:i32 = Iconst_32 0x1
  1348  	Store module_ctx, exec_ctx, 0x8
  1349  	v3:i64 = Load exec_ctx, 0x48
  1350  	v4:i32 = CallIndirect v3:sig1, exec_ctx, v2
  1351  	v7:i32 = Load module_ctx, 0x10
  1352  	v8:i32 = Iconst_32 0x10
  1353  	v9:i32 = Ushr v7, v8
  1354  	v10:i32 = Iconst_32 0x1
  1355  	Store module_ctx, exec_ctx, 0x8
  1356  	v11:i64 = Load exec_ctx, 0x48
  1357  	v12:i32 = CallIndirect v11:sig1, exec_ctx, v10
  1358  	Jump blk_ret, v4, v9, v12
  1359  `,
  1360  		},
  1361  		{
  1362  			name: "call_indirect", m: testcases.CallIndirect.Module,
  1363  			exp: `
  1364  signatures:
  1365  	sig2: i64i64_i32
  1366  
  1367  blk0: (exec_ctx:i64, module_ctx:i64, v2:i32)
  1368  	v3:i64 = Load module_ctx, 0x10
  1369  	v4:i32 = Load v3, 0x8
  1370  	v5:i32 = Icmp ge_u, v2, v4
  1371  	ExitIfTrue v5, exec_ctx, table_out_of_bounds
  1372  	v6:i64 = Load v3, 0x0
  1373  	v7:i64 = Iconst_64 0x3
  1374  	v8:i32 = Ishl v2, v7
  1375  	v9:i64 = Iadd v6, v8
  1376  	v10:i64 = Load v9, 0x0
  1377  	v11:i64 = Iconst_64 0x0
  1378  	v12:i32 = Icmp eq, v10, v11
  1379  	ExitIfTrue v12, exec_ctx, indirect_call_null_pointer
  1380  	v13:i32 = Load v10, 0x10
  1381  	v14:i64 = Load module_ctx, 0x8
  1382  	v15:i32 = Load v14, 0x8
  1383  	v16:i32 = Icmp neq, v13, v15
  1384  	ExitIfTrue v16, exec_ctx, indirect_call_type_mismatch
  1385  	v17:i64 = Load v10, 0x0
  1386  	v18:i64 = Load v10, 0x8
  1387  	Store module_ctx, exec_ctx, 0x8
  1388  	v19:i32 = CallIndirect v17:sig2, exec_ctx, v18
  1389  	Jump blk_ret, v19
  1390  `,
  1391  		},
  1392  		{
  1393  			name: "br_table", m: testcases.BrTable.Module,
  1394  			exp: `
  1395  blk0: (exec_ctx:i64, module_ctx:i64, v2:i32)
  1396  	BrTable v2, [blk7, blk8, blk9, blk10, blk11, blk12, blk13]
  1397  
  1398  blk1: () <-- (blk12)
  1399  	v8:i32 = Iconst_32 0x10
  1400  	Return v8
  1401  
  1402  blk2: () <-- (blk11)
  1403  	v7:i32 = Iconst_32 0xf
  1404  	Return v7
  1405  
  1406  blk3: () <-- (blk10)
  1407  	v6:i32 = Iconst_32 0xe
  1408  	Return v6
  1409  
  1410  blk4: () <-- (blk9)
  1411  	v5:i32 = Iconst_32 0xd
  1412  	Return v5
  1413  
  1414  blk5: () <-- (blk8)
  1415  	v4:i32 = Iconst_32 0xc
  1416  	Return v4
  1417  
  1418  blk6: () <-- (blk7,blk13)
  1419  	v3:i32 = Iconst_32 0xb
  1420  	Return v3
  1421  
  1422  blk7: () <-- (blk0)
  1423  	Jump blk6
  1424  
  1425  blk8: () <-- (blk0)
  1426  	Jump blk5
  1427  
  1428  blk9: () <-- (blk0)
  1429  	Jump blk4
  1430  
  1431  blk10: () <-- (blk0)
  1432  	Jump blk3
  1433  
  1434  blk11: () <-- (blk0)
  1435  	Jump blk2
  1436  
  1437  blk12: () <-- (blk0)
  1438  	Jump blk1
  1439  
  1440  blk13: () <-- (blk0)
  1441  	Jump blk6
  1442  `,
  1443  		},
  1444  		{
  1445  			name: "br_table_with_arg", m: testcases.BrTableWithArg.Module,
  1446  			exp: `
  1447  blk0: (exec_ctx:i64, module_ctx:i64, v2:i32, v3:i32)
  1448  	BrTable v2, [blk7, blk8, blk9, blk10, blk11, blk12, blk13]
  1449  
  1450  blk1: (v4:i32) <-- (blk12)
  1451  	v20:i32 = Iconst_32 0x10
  1452  	v21:i32 = Iadd v4, v20
  1453  	Return v21
  1454  
  1455  blk2: (v5:i32) <-- (blk11)
  1456  	v18:i32 = Iconst_32 0xf
  1457  	v19:i32 = Iadd v5, v18
  1458  	Return v19
  1459  
  1460  blk3: (v6:i32) <-- (blk10)
  1461  	v16:i32 = Iconst_32 0xe
  1462  	v17:i32 = Iadd v6, v16
  1463  	Return v17
  1464  
  1465  blk4: (v7:i32) <-- (blk9)
  1466  	v14:i32 = Iconst_32 0xd
  1467  	v15:i32 = Iadd v7, v14
  1468  	Return v15
  1469  
  1470  blk5: (v8:i32) <-- (blk8)
  1471  	v12:i32 = Iconst_32 0xc
  1472  	v13:i32 = Iadd v8, v12
  1473  	Return v13
  1474  
  1475  blk6: (v9:i32) <-- (blk7,blk13)
  1476  	v10:i32 = Iconst_32 0xb
  1477  	v11:i32 = Iadd v9, v10
  1478  	Return v11
  1479  
  1480  blk7: () <-- (blk0)
  1481  	Jump blk6, v3
  1482  
  1483  blk8: () <-- (blk0)
  1484  	Jump blk5, v3
  1485  
  1486  blk9: () <-- (blk0)
  1487  	Jump blk4, v3
  1488  
  1489  blk10: () <-- (blk0)
  1490  	Jump blk3, v3
  1491  
  1492  blk11: () <-- (blk0)
  1493  	Jump blk2, v3
  1494  
  1495  blk12: () <-- (blk0)
  1496  	Jump blk1, v3
  1497  
  1498  blk13: () <-- (blk0)
  1499  	Jump blk6, v3
  1500  `,
  1501  
  1502  			// TODO: these trivial two hop jumps should be optimized away.
  1503  			expAfterOpt: `
  1504  blk0: (exec_ctx:i64, module_ctx:i64, v2:i32, v3:i32)
  1505  	BrTable v2, [blk7, blk8, blk9, blk10, blk11, blk12, blk13]
  1506  
  1507  blk1: () <-- (blk12)
  1508  	v20:i32 = Iconst_32 0x10
  1509  	v21:i32 = Iadd v3, v20
  1510  	Return v21
  1511  
  1512  blk2: () <-- (blk11)
  1513  	v18:i32 = Iconst_32 0xf
  1514  	v19:i32 = Iadd v3, v18
  1515  	Return v19
  1516  
  1517  blk3: () <-- (blk10)
  1518  	v16:i32 = Iconst_32 0xe
  1519  	v17:i32 = Iadd v3, v16
  1520  	Return v17
  1521  
  1522  blk4: () <-- (blk9)
  1523  	v14:i32 = Iconst_32 0xd
  1524  	v15:i32 = Iadd v3, v14
  1525  	Return v15
  1526  
  1527  blk5: () <-- (blk8)
  1528  	v12:i32 = Iconst_32 0xc
  1529  	v13:i32 = Iadd v3, v12
  1530  	Return v13
  1531  
  1532  blk6: () <-- (blk7,blk13)
  1533  	v10:i32 = Iconst_32 0xb
  1534  	v11:i32 = Iadd v3, v10
  1535  	Return v11
  1536  
  1537  blk7: () <-- (blk0)
  1538  	Jump blk6
  1539  
  1540  blk8: () <-- (blk0)
  1541  	Jump blk5
  1542  
  1543  blk9: () <-- (blk0)
  1544  	Jump blk4
  1545  
  1546  blk10: () <-- (blk0)
  1547  	Jump blk3
  1548  
  1549  blk11: () <-- (blk0)
  1550  	Jump blk2
  1551  
  1552  blk12: () <-- (blk0)
  1553  	Jump blk1
  1554  
  1555  blk13: () <-- (blk0)
  1556  	Jump blk6
  1557  `,
  1558  		},
  1559  		{
  1560  			name: "if_then_end_nesting_unreachable_if_then_else_end", m: testcases.IfThenEndNestingUnreachableIfThenElseEnd.Module,
  1561  			exp: `
  1562  blk0: (exec_ctx:i64, module_ctx:i64, v2:f64, v3:f64, v4:f64)
  1563  	v6:i32 = Load module_ctx, 0x10
  1564  	v7:i32 = Iconst_32 0x10
  1565  	v8:i32 = Ushr v6, v7
  1566  	Brz v8, blk3
  1567  	Jump blk2
  1568  
  1569  blk1: (v5:i64) <-- (blk4)
  1570  	Jump blk_ret
  1571  
  1572  blk2: () <-- (blk0)
  1573  	v9:i32 = Load module_ctx, 0x10
  1574  	v10:i32 = Iconst_32 0x10
  1575  	v11:i32 = Ushr v9, v10
  1576  	Jump blk4
  1577  
  1578  blk3: () <-- (blk0)
  1579  	Jump blk4
  1580  
  1581  blk4: () <-- (blk2,blk3)
  1582  	v12:i64 = Iconst_64 0x0
  1583  	Jump blk1, v12
  1584  `,
  1585  			expAfterOpt: `
  1586  blk0: (exec_ctx:i64, module_ctx:i64, v2:f64, v3:f64, v4:f64)
  1587  	v6:i32 = Load module_ctx, 0x10
  1588  	v7:i32 = Iconst_32 0x10
  1589  	v8:i32 = Ushr v6, v7
  1590  	Brz v8, blk3
  1591  	Jump blk2
  1592  
  1593  blk1: () <-- (blk4)
  1594  	Jump blk_ret
  1595  
  1596  blk2: () <-- (blk0)
  1597  	Jump blk4
  1598  
  1599  blk3: () <-- (blk0)
  1600  	Jump blk4
  1601  
  1602  blk4: () <-- (blk2,blk3)
  1603  	Jump blk1
  1604  `,
  1605  		},
  1606  		{
  1607  			name: "VecShuffle",
  1608  			m:    testcases.VecShuffle.Module,
  1609  			exp: `
  1610  blk0: (exec_ctx:i64, module_ctx:i64, v2:v128, v3:v128)
  1611  	v4:v128 = Shuffle.[0 1 2 3 4 5 6 7 24 25 26 27 28 29 30 31] v2, v3
  1612  	Jump blk_ret, v4
  1613  `,
  1614  		},
  1615  	} {
  1616  
  1617  		tc := tc
  1618  		t.Run(tc.name, func(t *testing.T) {
  1619  			// Just in case let's check the test module is valid.
  1620  			err := tc.m.Validate(api.CoreFeaturesV2)
  1621  			require.NoError(t, err, "invalid test case module!")
  1622  
  1623  			b := ssa.NewBuilder()
  1624  
  1625  			offset := wazevoapi.NewModuleContextOffsetData(tc.m, tc.needListener)
  1626  			fc := NewFrontendCompiler(tc.m, b, &offset, tc.ensureTermination, tc.needListener, false)
  1627  			typeIndex := tc.m.FunctionSection[tc.targetIndex]
  1628  			code := &tc.m.CodeSection[tc.targetIndex]
  1629  			fc.Init(tc.targetIndex, typeIndex, &tc.m.TypeSection[typeIndex], code.LocalTypes, code.Body, tc.needListener, 0)
  1630  
  1631  			fc.LowerToSSA()
  1632  
  1633  			actual := fc.formatBuilder()
  1634  			require.Equal(t, tc.exp, actual)
  1635  
  1636  			b.RunPasses()
  1637  			if expAfterOpt := tc.expAfterOpt; expAfterOpt != "" {
  1638  				actualAfterOpt := fc.formatBuilder()
  1639  				require.Equal(t, expAfterOpt, actualAfterOpt)
  1640  			}
  1641  
  1642  			// Dry-run without checking the results of LayoutBlocks function.
  1643  			b.LayoutBlocks()
  1644  		})
  1645  	}
  1646  }
  1647  
  1648  func TestSignatureForListener(t *testing.T) {
  1649  	for _, tc := range []struct {
  1650  		name          string
  1651  		sig           *wasm.FunctionType
  1652  		before, after *ssa.Signature
  1653  	}{
  1654  		{
  1655  			name:   "empty",
  1656  			sig:    &wasm.FunctionType{},
  1657  			before: &ssa.Signature{Params: []ssa.Type{ssa.TypeI64, ssa.TypeI32}},
  1658  			after:  &ssa.Signature{Params: []ssa.Type{ssa.TypeI64, ssa.TypeI32}},
  1659  		},
  1660  		{
  1661  			name: "multi",
  1662  			sig: &wasm.FunctionType{
  1663  				Params: []wasm.ValueType{wasm.ValueTypeF64, wasm.ValueTypeI32},
  1664  				Results: []wasm.ValueType{
  1665  					wasm.ValueTypeI64, wasm.ValueTypeI32, wasm.ValueTypeF32, wasm.ValueTypeF64, wasm.ValueTypeV128,
  1666  				},
  1667  			},
  1668  			before: &ssa.Signature{
  1669  				Params: []ssa.Type{
  1670  					ssa.TypeI64, ssa.TypeI32,
  1671  					ssa.TypeF64, ssa.TypeI32,
  1672  				},
  1673  			},
  1674  			after: &ssa.Signature{
  1675  				Params: []ssa.Type{
  1676  					ssa.TypeI64, ssa.TypeI32,
  1677  					ssa.TypeI64, ssa.TypeI32, ssa.TypeF32, ssa.TypeF64, ssa.TypeV128,
  1678  				},
  1679  			},
  1680  		},
  1681  	} {
  1682  		tc := tc
  1683  		t.Run(tc.name, func(t *testing.T) {
  1684  			before, after := SignatureForListener(tc.sig)
  1685  			require.Equal(t, tc.before, before)
  1686  			require.Equal(t, tc.after, after)
  1687  		})
  1688  	}
  1689  }
  1690  
  1691  func TestCompiler_declareSignatures(t *testing.T) {
  1692  	m := &wasm.Module{
  1693  		TypeSection: []wasm.FunctionType{
  1694  			{},
  1695  			{Params: []wasm.ValueType{wasm.ValueTypeI64, wasm.ValueTypeI32}},
  1696  			{Params: []wasm.ValueType{wasm.ValueTypeF64, wasm.ValueTypeI32}},
  1697  			{Results: []wasm.ValueType{wasm.ValueTypeI64, wasm.ValueTypeI32}},
  1698  		},
  1699  	}
  1700  
  1701  	t.Run("listener=false", func(t *testing.T) {
  1702  		builder := ssa.NewBuilder()
  1703  		c := &Compiler{m: m, ssaBuilder: builder}
  1704  		c.declareSignatures(false)
  1705  
  1706  		declaredSigs := builder.Signatures()
  1707  		expected := []*ssa.Signature{
  1708  			{ID: 0, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI64}},
  1709  			{ID: 1, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI64, ssa.TypeI64, ssa.TypeI32}},
  1710  			{ID: 2, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI64, ssa.TypeF64, ssa.TypeI32}},
  1711  			{ID: 3, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI64}, Results: []ssa.Type{ssa.TypeI64, ssa.TypeI32}},
  1712  			{ID: 4, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI32}, Results: []ssa.Type{ssa.TypeI32}},
  1713  			{ID: 5, Params: []ssa.Type{ssa.TypeI64}},
  1714  			{ID: 6, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI32, ssa.TypeI32, ssa.TypeI64}, Results: []ssa.Type{ssa.TypeI32}},
  1715  			{ID: 7, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI32}, Results: []ssa.Type{ssa.TypeI64}},
  1716  			{ID: 8, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI64, ssa.TypeI32}},
  1717  		}
  1718  
  1719  		require.Equal(t, len(expected), len(declaredSigs))
  1720  		for i := 0; i < len(expected); i++ {
  1721  			require.Equal(t, expected[i].String(), declaredSigs[i].String(), i)
  1722  		}
  1723  	})
  1724  
  1725  	t.Run("listener=false", func(t *testing.T) {
  1726  		builder := ssa.NewBuilder()
  1727  		c := &Compiler{m: m, ssaBuilder: builder}
  1728  		c.declareSignatures(true)
  1729  
  1730  		declaredSigs := builder.Signatures()
  1731  
  1732  		expected := []*ssa.Signature{
  1733  			{ID: 0, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI64}},
  1734  			{ID: 1, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI64, ssa.TypeI64, ssa.TypeI32}},
  1735  			{ID: 2, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI64, ssa.TypeF64, ssa.TypeI32}},
  1736  			{ID: 3, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI64}, Results: []ssa.Type{ssa.TypeI64, ssa.TypeI32}},
  1737  			// Before.
  1738  			{ID: 4, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI32}},
  1739  			{ID: 5, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI32, ssa.TypeI64, ssa.TypeI32}},
  1740  			{ID: 6, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI32, ssa.TypeF64, ssa.TypeI32}},
  1741  			{ID: 7, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI32}},
  1742  			// After.
  1743  			{ID: 8, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI32}},
  1744  			{ID: 9, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI32}},
  1745  			{ID: 10, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI32}},
  1746  			{ID: 11, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI32, ssa.TypeI64, ssa.TypeI32}},
  1747  			// Misc.
  1748  			{ID: 12, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI32}, Results: []ssa.Type{ssa.TypeI32}},
  1749  			{ID: 13, Params: []ssa.Type{ssa.TypeI64}},
  1750  			{ID: 14, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI32, ssa.TypeI32, ssa.TypeI64}, Results: []ssa.Type{ssa.TypeI32}},
  1751  			{ID: 15, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI32}, Results: []ssa.Type{ssa.TypeI64}},
  1752  			{ID: 16, Params: []ssa.Type{ssa.TypeI64, ssa.TypeI64, ssa.TypeI32}},
  1753  		}
  1754  		require.Equal(t, len(expected), len(declaredSigs))
  1755  		for i := 0; i < len(declaredSigs); i++ {
  1756  			require.Equal(t, expected[i].String(), declaredSigs[i].String(), i)
  1757  		}
  1758  	})
  1759  }
  1760  
  1761  func TestCompiler_recordKnownSafeBound(t *testing.T) {
  1762  	c := &Compiler{}
  1763  	c.recordKnownSafeBound(1, 99, 9999)
  1764  	require.Equal(t, 1, len(c.knownSafeBoundsSet))
  1765  	require.True(t, c.getKnownSafeBound(1).valid())
  1766  	require.Equal(t, uint64(99), c.getKnownSafeBound(1).bound)
  1767  	require.Equal(t, ssa.Value(9999), c.getKnownSafeBound(1).absoluteAddr)
  1768  
  1769  	c.recordKnownSafeBound(1, 150, 9999)
  1770  	require.Equal(t, 1, len(c.knownSafeBoundsSet))
  1771  	require.Equal(t, uint64(150), c.getKnownSafeBound(1).bound)
  1772  
  1773  	c.recordKnownSafeBound(5, 666, 54321)
  1774  	require.Equal(t, 2, len(c.knownSafeBoundsSet))
  1775  	require.Equal(t, uint64(666), c.getKnownSafeBound(5).bound)
  1776  	require.Equal(t, ssa.Value(54321), c.getKnownSafeBound(5).absoluteAddr)
  1777  }
  1778  
  1779  func TestCompiler_getKnownSafeBound(t *testing.T) {
  1780  	c := &Compiler{
  1781  		knownSafeBounds: []knownSafeBound{
  1782  			{}, {bound: 2134},
  1783  		},
  1784  	}
  1785  	require.Nil(t, c.getKnownSafeBound(5))
  1786  	require.Nil(t, c.getKnownSafeBound(12345))
  1787  	require.False(t, c.getKnownSafeBound(0).valid())
  1788  	require.True(t, c.getKnownSafeBound(1).valid())
  1789  }
  1790  
  1791  func TestCompiler_clearSafeBounds(t *testing.T) {
  1792  	c := &Compiler{}
  1793  	c.knownSafeBounds = []knownSafeBound{{bound: 1}, {}, {bound: 2}, {}, {}, {bound: 3}}
  1794  	c.knownSafeBoundsSet = []ssa.ValueID{0, 2, 5}
  1795  	c.clearSafeBounds()
  1796  	require.Equal(t, 0, len(c.knownSafeBoundsSet))
  1797  	require.Equal(t, []knownSafeBound{{}, {}, {}, {}, {}, {}}, c.knownSafeBounds)
  1798  }
  1799  
  1800  func TestKnownSafeBound_valid(t *testing.T) {
  1801  	k := &knownSafeBound{bound: 10, absoluteAddr: 12345}
  1802  	require.True(t, k.valid())
  1803  	k.bound = 0
  1804  	require.False(t, k.valid())
  1805  }