// Copyright 2020 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.

const {session, contextGroup, Protocol} =
    InspectorTest.start('Test inspecting register values in Liftoff.');

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

const num_locals = 10;
const configs = {
  i32: {type: kWasmI32, add: kExprI32Add, from_i32: kExprNop},
  i64: {type: kWasmI64, add: kExprI64Add, from_i32: kExprI64SConvertI32},
  f32: {type: kWasmF32, add: kExprF32Add, from_i32: kExprF32SConvertI32},
  f64: {type: kWasmF64, add: kExprF64Add, from_i32: kExprF64SConvertI32}
};

Protocol.Debugger.onPaused(async msg => {
  let loc = msg.params.callFrames[0].location;
  let line = [`Paused at offset ${loc.columnNumber}`];
  // Inspect only the top wasm frame.
  var frame = msg.params.callFrames[0];
  for (var scope of frame.scopeChain) {
    if (scope.type == 'module') continue;
    var scope_properties =
        await Protocol.Runtime.getProperties({objectId: scope.object.objectId});
    let str = scope_properties.result.result.map(
        elem => WasmInspectorTest.getWasmValue(elem.value)).join(', ');
    line.push(`${scope.type}: [${str}]`);
  }
  InspectorTest.log(line.join('; '));
  Protocol.Debugger.resume();
});

// Build a function which receives a lot of arguments. It loads them all and
// adds them together.
// In Liftoff, this will hold many values in registers at the break sites.
function buildModuleBytes(config) {
  const sig = makeSig(
      new Array(num_locals).fill(configs[config].type), [configs[config].type]);
  const body = [];
  for (let i = 0; i < num_locals; ++i) body.push(kExprLocalGet, i);
  for (let i = 0; i < num_locals - 1; ++i) body.push(configs[config].add);
  body.push(kExprReturn);
  const builder = new WasmModuleBuilder();
  const test_func = builder.addFunction('test_' + config, sig).addBody(body);
  const main_body = [];
  for (let i = 0; i < num_locals; ++i)
    main_body.push(kExprI32Const, i, configs[config].from_i32);
  main_body.push(kExprCallFunction, test_func.index, kExprDrop);
  const main =
      builder.addFunction('main', kSig_v_v).addBody(main_body).exportAs('main');

  const module_bytes = builder.toArray();

  // Break at every {kExprLocalGet} and at every addition.
  const interesting_opcodes = [kExprLocalGet, kExprReturn, configs[config].add];
  const breakpoints = [];
  for (let idx = 0; idx < body.length; ++idx) {
    if (interesting_opcodes.find(elem => elem == body[idx])) {
      breakpoints.push(test_func.body_offset + idx);
    }
  }

  return [module_bytes, breakpoints];
}

async function testConfig(config) {
  InspectorTest.log(`Testing ${config}.`);
  const [module_bytes, breakpoints] = buildModuleBytes(config);
  const instance_name = `instance_${config}`;
  // Spawn asynchronously:
  WasmInspectorTest.instantiate(module_bytes, instance_name);
  InspectorTest.log('Waiting for wasm script.');
  const [, {params: wasm_script}] = await Protocol.Debugger.onceScriptParsed(2);
  InspectorTest.log(`Setting ${breakpoints.length} breakpoints.`);
  for (let offset of breakpoints) {
    await Protocol.Debugger.setBreakpoint({
      'location': {
        'scriptId': wasm_script.scriptId,
        'lineNumber': 0,
        'columnNumber': offset
      }
    });
  }
  InspectorTest.log('Calling main.');
  await WasmInspectorTest.evalWithUrl(`${instance_name}.exports.main()`, `run_${config}`);
  InspectorTest.log('main returned.');
}

(async function test() {
  await Protocol.Debugger.enable();
  for (let config in configs) {
    await testConfig(config);
  }
  InspectorTest.log('Finished!');
  InspectorTest.completeTest();
})();
