// Copyright 2019 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Flags: --experimental-wasm-type-reflection --experimental-wasm-simd
// SIMD in Liftoff only works with these cpu features, force them on.
// Flags: --enable-sse3 --enable-ssse3 --enable-sse4-1

utils.load('test/inspector/wasm-inspector-test.js');

let {session, contextGroup, Protocol} = InspectorTest.start(
    'Test retrieving scope information from compiled Liftoff frames');
session.setupScriptMap();
Protocol.Debugger.enable();
Protocol.Debugger.onPaused(printPauseLocationsAndContinue);

let breakpointLocation = -1;

(async function test() {
  // Instantiate wasm and wait for three wasm scripts for the three functions.
  instantiateWasm();
  let scriptIds = await waitForWasmScripts();

  // Set a breakpoint.
  InspectorTest.log(
      'Setting breakpoint on line 2 (first instruction) of third function');
  let breakpoint = await Protocol.Debugger.setBreakpoint(
      {'location': {'scriptId': scriptIds[0], 'lineNumber': 0, 'columnNumber': breakpointLocation}});
  printIfFailure(breakpoint);
  InspectorTest.logMessage(breakpoint.result.actualLocation);

  // Now run the wasm code.
  await WasmInspectorTest.evalWithUrl('instance.exports.main(42)', 'runWasm');
  InspectorTest.log('exports.main returned. Test finished.');
  InspectorTest.completeTest();
})();

async function printPauseLocationsAndContinue(msg) {
  let loc = msg.params.callFrames[0].location;
  InspectorTest.log('Paused:');
  await session.logSourceLocation(loc);
  InspectorTest.log('Scope:');
  for (var frame of msg.params.callFrames) {
    var isWasmFrame = /^wasm/.test(frame.url);
    var functionName = frame.functionName || '(anonymous)';
    var lineNumber = frame.location.lineNumber;
    var columnNumber = frame.location.columnNumber;
    InspectorTest.log(`at ${functionName} (${lineNumber}:${columnNumber}):`);
    for (var scope of frame.scopeChain) {
      InspectorTest.logObject(' - scope (' + scope.type + '):');
      if (!isWasmFrame && scope.type == 'global') {
        // Skip global scope for non wasm-functions.
        InspectorTest.logObject('   -- skipped globals');
        continue;
      }
      var properties = await Protocol.Runtime.getProperties(
          {'objectId': scope.object.objectId});
      await WasmInspectorTest.dumpScopeProperties(properties);
    }
  }
  InspectorTest.log();
  Protocol.Debugger.stepOver();
}

async function instantiateWasm() {
  var builder = new WasmModuleBuilder();
  // Add a global, memory and exports to populate the module scope.
  builder.addGlobal(kWasmI32, true).exportAs('exported_global');
  builder.addMemory(1,1).exportMemoryAs('exported_memory');
  builder.addTable(kWasmAnyFunc, 3).exportAs('exported_table');

  // Add two functions without breakpoint, to check that locals and operand
  // stack values are shown correctly in Liftoff code.
  // Function A will have its parameter spilled to the stack, because it calls
  // function B.
  // Function B has a local with a constant value (not using a register), the
  // parameter will be held in a register.
  const main = builder.addFunction('A (liftoff)', kSig_v_i)
      .addBody([
        // Call function 'B', forwarding param 0.
        kExprLocalGet, 0, kExprCallFunction, 1
      ])
      .exportAs('main');

  builder.addFunction('B (liftoff)', kSig_v_i, ['i32_arg'])
      .addLocals(kWasmI32, 1, ['i32_local'])
      .addLocals(kWasmF32, 4, ['f32_local', '0', '0'])
      .addLocals(kWasmS128, 1, ['v128_local'])
      .addBody([
        // Load a parameter and a constant onto the operand stack.
        kExprLocalGet, 0, kExprI32Const, 3,
        // Set local 6 to v128 i32.x4 23, 23, 23, 23.
        kExprI32Const, 23,
        kSimdPrefix, kExprI32x4Splat,
        kExprLocalSet, 6,
        // Set local 2 to 7.2.
        ...wasmF32Const(7.2), kExprLocalSet, 2,
        // Call function 'C', forwarding param 0.
        kExprLocalGet, 0, kExprCallFunction, 2,
        // Drop the two operand stack values.
        kExprDrop, kExprDrop
      ]);

  // A third function which will be stepped through.
  let func = builder.addFunction('C (interpreted)', kSig_v_i, ['i32_arg'])
      .addLocals(kWasmI32, 1, ['i32_local'])
      .addLocals(kWasmF32, 1, [''])
      .addBody([
        // Set global 0 to param 0.
        kExprLocalGet, 0, kExprGlobalSet, 0,
        // Set local 1 to 47.
        kExprI32Const, 47, kExprLocalSet, 1,
      ]);

  // Append function to table to test function table output.
  builder.appendToTable([main.index]);

  var module_bytes = builder.toArray();
  breakpointLocation = func.body_offset;


  function addWasmJSToTable() {
    // Create WasmJS functions to test the function tables output.
    const js_func = function js_func() { return 7; };
    const wasmjs_func = new WebAssembly.Function({parameters:[], results:['i32']}, js_func);
    const wasmjs_anonymous_func = new WebAssembly.Function({parameters:[], results:['i32']}, _ => 7);

    instance.exports.exported_table.set(0, wasmjs_func);
    instance.exports.exported_table.set(1, wasmjs_anonymous_func);
  }

  InspectorTest.log('Calling instantiate function.');
  await WasmInspectorTest.instantiate(module_bytes);
  await WasmInspectorTest.evalWithUrl(`(${addWasmJSToTable})()`, 'populateTable');
}

function printIfFailure(message) {
  if (!message.result) {
    InspectorTest.logMessage(message);
  }
  return message;
}

async function waitForWasmScripts() {
  InspectorTest.log('Waiting for wasm script to be parsed.');
  let wasm_script_ids = [];
  while (wasm_script_ids.length < 1) {
    let script_msg = await Protocol.Debugger.onceScriptParsed();
    let url = script_msg.params.url;
    if (url.startsWith('wasm://')) {
      InspectorTest.log('Got wasm script!');
      wasm_script_ids.push(script_msg.params.scriptId);
    }
  }
  return wasm_script_ids;
}
