// Copyright (c) 2024, 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.

import 'dart:typed_data';

import 'package:kernel/ast.dart' show listEquals, listHashCode;

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

class Instruction {
  final Opcode opcode;
  final bool isWide;
  final List<int> operands;
  final int pc;

  Instruction(this.opcode, this.isWide, this.operands, this.pc);

  Format get format => BytecodeFormats[opcode]!;

  int get length => instructionSize(format.encoding, isWide);

  @override
  int get hashCode => opcode.index.hashCode ^ listHashCode(operands);

  @override
  bool operator ==(other) {
    return (other is Instruction) &&
        (opcode == other.opcode) &&
        listEquals(operands, other.operands);
  }
}

class BytecodeDisassembler {
  late Uint8List _bytecode;
  late List<Instruction> _instructions;
  late int _labelCount;
  late Map<int, String> _labels;
  late Map<int, List<String>> _markers;

  String disassemble(List<int> bytecode, ExceptionsTable exceptionsTable,
      {List<Map<int, String>>? annotations}) {
    _init(bytecode);
    _scanForJumpTargets();
    _markTryBlocks(exceptionsTable);
    if (annotations != null) {
      _markAnnotations(annotations);
    }
    return _disasm();
  }

  List<Instruction> decode(Uint8List bytecode) {
    _init(bytecode);
    return _instructions;
  }

  void _init(List<int> bytecode) {
    _bytecode = new Uint8List.fromList(bytecode);

    _instructions = <Instruction>[];
    for (int pos = 0; pos < _bytecode.length;) {
      final instr = decodeInstructionAt(pos);
      _instructions.add(instr);
      pos += instr.length;
    }

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

  Instruction decodeInstructionAt(int pos) {
    Opcode opcode = Opcode.values[_bytecode[pos]];
    bool isWide = isWideOpcode(opcode);
    if (isWide) {
      opcode = fromWideOpcode(opcode);
    }

    final format = BytecodeFormats[opcode]!;
    final operands = _decodeOperands(format, pos, isWide);
    return new Instruction(opcode, isWide, operands, pos);
  }

  List<int> _decodeOperands(Format format, int pos, bool isWide) {
    switch (format.encoding) {
      case Encoding.k0:
        return const [];
      case Encoding.kA:
        return [_bytecode[pos + 1]];
      case Encoding.kD:
        return isWide ? [_decodeUint32At(pos + 1)] : [_bytecode[pos + 1]];
      case Encoding.kX:
        return isWide
            ? [_decodeUint32At(pos + 1).toSigned(32)]
            : [_bytecode[pos + 1].toSigned(8)];
      case Encoding.kT:
        return isWide
            ? [
                (_bytecode[pos + 1] +
                        (_bytecode[pos + 2] << 8) +
                        (_bytecode[pos + 3] << 16))
                    .toSigned(24)
              ]
            : [_bytecode[pos + 1].toSigned(8)];
      case Encoding.kAE:
        return [
          _bytecode[pos + 1],
          isWide ? _decodeUint32At(pos + 2) : _bytecode[pos + 2],
        ];
      case Encoding.kAY:
        return [
          _bytecode[pos + 1],
          isWide
              ? _decodeUint32At(pos + 2).toSigned(32)
              : _bytecode[pos + 2].toSigned(8)
        ];
      case Encoding.kDF:
        return isWide
            ? [_decodeUint32At(pos + 1), _bytecode[pos + 5]]
            : [_bytecode[pos + 1], _bytecode[pos + 2]];
      case Encoding.kABC:
        return [_bytecode[pos + 1], _bytecode[pos + 2], _bytecode[pos + 3]];
    }
  }

  int _decodeUint32At(int pos) =>
      _bytecode[pos] +
      (_bytecode[pos + 1] << 8) +
      (_bytecode[pos + 2] << 16) +
      (_bytecode[pos + 3] << 24);

  void _scanForJumpTargets() {
    for (int i = 0; i < _instructions.length; i++) {
      final instr = _instructions[i];
      if (isJump(instr.opcode)) {
        final target = instr.pc + instr.operands[0];
        assert(0 <= target && target < _bytecode.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 _markAnnotations(List<Map<int, String>> annotations) {
    for (var map in annotations) {
      map.forEach((int pc, String annotation) {
        _addMarker(pc, '# $annotation');
      });
    }
  }

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

  String _disasm() {
    StringBuffer out = new StringBuffer();
    for (Instruction instr in _instructions) {
      List<String>? markers = _markers[instr.pc];
      if (markers != null) {
        markers.forEach(out.writeln);
      }
      writeInstruction(out, instr);
    }
    return out.toString();
  }

  void writeInstruction(StringBuffer out, Instruction instr) {
    final format = BytecodeFormats[instr.opcode]!;

    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(instr.pc, format.operands[i], instr.operands[i]);
      out.write(operand);
    }

    out.writeln();
  }

  String _formatOperand(int pc, 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[pc + value] ?? (throw 'Label not found');
      case Operand.spe:
        return SpecialIndex.values[value]
            .toString()
            .substring('SpecialIndex.'.length);
    }
    throw 'Unexpected operand format $fmt';
  }
}
