tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

codegen-x86-test.js (3016B)


      1 // Scaffolding for testing x86 Ion code generation patterns .  See
      2 // codegen-x64-test.js in this directory for more information.
      3 
      4 load(libdir + "codegen-test-common.js");
      5 
      6 // Note that Zydis disassembles x86 absolute addresses as relative, so
      7 // the binary encoding and the text encoding may not correspond precisely.
      8 
      9 // Absolute address (disp32) following the instruction mnemonic.
     10 var ABS = `0x${HEXES}`;
     11 
     12 // End of prologue. The move from esi to rbp is writing the callee's wasm
     13 // instance into the frame for debug checks -- see WasmFrame.h. The mov to eax
     14 // is debug code, inserted by the register allocator to clobber eax before a
     15 // move group. But it is only present if there is a move group there.
     16 //
     17 // -0x21524111 is 0xDEADBEEF.
     18 var x86_prefix = `
     19 mov %esp, %ebp(
     20 movl %esi, 0x08\\(%rbp\\))?(
     21 mov \\$-0x21524111, %eax)?
     22 `
     23 
     24 // `.bp` because zydis chooses 'rbp' even on 32-bit systems
     25 var x86_loadarg0 = `
     26 movdqux 0x${HEXES}\\(%.bp\\), %xmm0
     27 `;
     28 
     29 // Start of epilogue.  `.bp` for the same reason as above.
     30 var x86_suffix = `pop %.bp`;
     31 
     32 // v128 OP literal -> v128
     33 // inputs: [[complete-opname, rhs-literal, expected-pattern], ...]
     34 function codegenTestX86_v128xLITERAL_v128(inputs, options = {}) {
     35    for ( let [op, literal, expected] of inputs ) {
     36        codegenTestX86_adhoc(wrap(options, `
     37    (func (export "f") (param v128) (result v128)
     38      (${op} (local.get 0) ${literal}))`),
     39                             'f',
     40                             x86_loadarg0 + expected,
     41                             options)
     42    }
     43 }
     44 
     45 // For when nothing else applies: `module_text` is the complete source text of
     46 // the module, `export_name` is the name of the function to be tested,
     47 // `expected` is the non-preprocessed pattern, and options is an options bag,
     48 // described above.
     49 function codegenTestX86_adhoc(module_text, export_name, expected, options = {}) {
     50    assertEq(hasDisassembler(), true);
     51 
     52    let ins = wasmEvalText(module_text);
     53    let output = wasmDis(ins.exports[export_name], {tier:"ion", asString:true});
     54 
     55    const expected_initial = expected;
     56    if (!options.no_prefix)
     57        expected = x86_prefix + '\n' + expected;
     58    if (!options.no_suffix)
     59        expected = expected + '\n' + x86_suffix;
     60    expected = fixlines(expected);
     61 
     62    const output_simple = stripencoding(output, `(?:${HEX}{2} )*`);
     63    const output_matches_expected = output_simple.match(new RegExp(expected)) != null;
     64    if (!output_matches_expected) {
     65        print("---- codegen-x86-test.js: TEST FAILED ----");
     66    }
     67    if (options.log && output_matches_expected) {
     68        print("---- codegen-x86-test.js: TEST PASSED ----");
     69    }
     70    if (options.log || !output_matches_expected) {
     71        print("---- module text");
     72        print(module_text);
     73        print("---- actual");
     74        print(output);
     75        print("---- expected (initial)");
     76        print(expected_initial);
     77        print("---- expected (as used)");
     78        print(expected);
     79        print("----");
     80    }
     81 
     82    assertEq(output_matches_expected, true);
     83 }