// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

library vm.bytecode.disassembler;

import 'dart:typed_data';

import 'dbc.dart';
import 'exceptions.dart';

class _Instruction {
  final Opcode opcode;
  final List<int> operands;
  _Instruction(this.opcode, this.operands);
}

class BytecodeDisassembler {
  static const int kOpcodeMask = 0xFF;
  static const int kBitsPerInt = 64;

  List<_Instruction> _instructions;
  int _labelCount;
  Map<int, String> _labels;
  Map<int, List<String>> _markers;

  String disassemble(List<int> bytecode, ExceptionsTable exceptionsTable) {
    _init(bytecode);
    _scanForJumpTargets();
    _markTryBlocks(exceptionsTable);
    return _disasm();
  }

  void _init(List<int> bytecode) {
    final uint8list = new Uint8List.fromList(bytecode);
    // TODO(alexmarkov): endianness?
    Uint32List words = uint8list.buffer.asUint32List();

    _instructions = new List<_Instruction>(words.length);
    for (int i = 0; i < words.length; i++) {
      _instructions[i] = _decodeInstruction(words[i]);
    }

    _labelCount = 0;
    _labels = <int, String>{};
    _markers = <int, List<String>>{};
  }

  _Instruction _decodeInstruction(int word) {
    final opcode = Opcode.values[word & kOpcodeMask];
    final format = BytecodeFormats[opcode];
    return new _Instruction(opcode, _decodeOperands(format, word));
  }

  List<int> _decodeOperands(Format format, int word) {
    switch (format.encoding) {
      case Encoding.k0:
        return const [];
      case Encoding.kA:
        return [_unsigned(word, 8, 8)];
      case Encoding.kAD:
        return [_unsigned(word, 8, 8), _unsigned(word, 16, 16)];
      case Encoding.kAX:
        return [_unsigned(word, 8, 8), _signed(word, 16, 16)];
      case Encoding.kD:
        return [_unsigned(word, 16, 16)];
      case Encoding.kX:
        return [_signed(word, 16, 16)];
      case Encoding.kABC:
        return [
          _unsigned(word, 8, 8),
          _unsigned(word, 16, 8),
          _unsigned(word, 24, 8)
        ];
      case Encoding.kABY:
        return [
          _unsigned(word, 8, 8),
          _unsigned(word, 16, 8),
          _signed(word, 24, 8)
        ];
      case Encoding.kT:
        return [_signed(word, 8, 24)];
    }
    throw 'Unexpected format $format';
  }

  int _unsigned(int word, int pos, int bits) =>
      (word >> pos) & ((1 << bits) - 1);

  int _signed(int word, int pos, int bits) =>
      _unsigned(word, pos, bits) <<
      (kBitsPerInt - bits) >>
      (kBitsPerInt - bits);

  void _scanForJumpTargets() {
    for (int i = 0; i < _instructions.length; i++) {
      final instr = _instructions[i];
      if (isJump(instr.opcode)) {
        final target = i + instr.operands[0];
        assert(0 <= target && target < _instructions.length);
        if (!_labels.containsKey(target)) {
          final label = 'L${++_labelCount}';
          _labels[target] = label;
          _addMarker(target, '$label:');
        }
      }
    }
  }

  void _markTryBlocks(ExceptionsTable exceptionsTable) {
    for (var tryBlock in exceptionsTable.blocks) {
      final int tryIndex = tryBlock.tryIndex;
      _addMarker(tryBlock.startPC, 'Try #$tryIndex start:');
      _addMarker(tryBlock.endPC, 'Try #$tryIndex end:');
      _addMarker(tryBlock.handlerPC, 'Try #$tryIndex handler:');
    }
  }

  void _addMarker(int pc, String marker) {
    final markers = (_markers[pc] ??= <String>[]);
    markers.add(marker);
  }

  String _disasm() {
    StringBuffer out = new StringBuffer();
    for (int i = 0; i < _instructions.length; i++) {
      List<String> markers = _markers[i];
      if (markers != null) {
        markers.forEach(out.writeln);
      }
      _writeInstruction(out, i, _instructions[i]);
    }
    return out.toString();
  }

  void _writeInstruction(StringBuffer out, int bci, _Instruction instr) {
    final format = BytecodeFormats[instr.opcode];
    assert(format != null);

    out.write('  ');

    const int kOpcodeWidth = 20;
    const String kOpcodePrefix = 'Opcode.k';

    String opcode = instr.opcode.toString();
    assert(opcode.startsWith(kOpcodePrefix));
    opcode = opcode.substring(kOpcodePrefix.length);

    if (instr.operands.isEmpty) {
      out.writeln(opcode);
      return;
    }

    out.write(opcode.padRight(kOpcodeWidth));

    for (int i = 0; i < instr.operands.length; i++) {
      if (i == 0) {
        out.write(' ');
      } else {
        out.write(', ');
      }
      final operand =
          _formatOperand(bci, format.operands[i], instr.operands[i]);
      out.write(operand);
    }

    out.writeln();
  }

  String _formatOperand(int bci, Operand fmt, int value) {
    switch (fmt) {
      case Operand.none:
        break;
      case Operand.imm:
        return '$value';
      case Operand.lit:
        return 'CP#$value';
      case Operand.reg:
        return 'r$value';
      case Operand.xeg:
        return (value < 0) ? 'FP[$value]' : 'r$value';
      case Operand.tgt:
        return _labels[bci + value] ?? (throw 'Label not found');
      case Operand.spe:
        return SpecialIndex.values[value]
            .toString()
            .substring('SpecialIndex.'.length);
    }
    throw 'Unexpected operand format $fmt';
  }
}
