// 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.exceptions;

import 'bytecode_serialization.dart' show BufferedWriter, BufferedReader;

/*

In kernel binary, try blocks are encoded in the following way
(using notation from pkg/kernel/binary.md):

// Offset of a bytecode instruction, in DBC words.
type BytecodeOffset = UInt;

type TryBlock {
  UInt outerTryIndexPlus1;
  BytecodeOffset startPC; // Inclusive.
  BytecodeOffset endPC; // Exclusive.
  BytecodeOffset handlerPC;
  Byte flags (needsStackTrace, isSynthetic);
  List<ConstantIndex> types;
}

type ExceptionsTable {
  // Ordered by startPC, then by nesting (outer precedes inner).
  // Try blocks are properly nested. It means there are no partially
  // overlapping try blocks - each pair of try block regions either
  // has no intersection or one try block region encloses another.
  List<TryBlock> tryBlocks;
}

*/

class TryBlock {
  static const int flagNeedsStackTrace = 1 << 0;
  static const int flagIsSynthetic = 1 << 1;

  final int tryIndex;
  final int outerTryIndex;
  final int startPC;
  int endPC;
  int handlerPC;
  int flags = 0;
  List<int> types = <int>[];

  TryBlock._(this.tryIndex, this.outerTryIndex, this.startPC);

  bool get needsStackTrace => (flags & flagNeedsStackTrace) != 0;

  void set needsStackTrace(bool value) {
    flags = (flags & ~flagNeedsStackTrace) | (value ? flagNeedsStackTrace : 0);
  }

  bool get isSynthetic => (flags & flagIsSynthetic) != 0;

  void set isSynthetic(bool value) {
    flags = (flags & ~flagIsSynthetic) | (value ? flagIsSynthetic : 0);
  }

  void write(BufferedWriter writer) {
    writer.writePackedUInt30(outerTryIndex + 1);
    writer.writePackedUInt30(startPC);
    writer.writePackedUInt30(endPC);
    writer.writePackedUInt30(handlerPC);
    writer.writeByte(flags);
    writer.writePackedUInt30(types.length);
    types.forEach(writer.writePackedUInt30);
  }

  factory TryBlock.read(BufferedReader reader, int tryIndex) {
    final outerTryIndex = reader.readPackedUInt30() - 1;
    final startPC = reader.readPackedUInt30();
    final tryBlock = new TryBlock._(tryIndex, outerTryIndex, startPC);

    tryBlock.endPC = reader.readPackedUInt30();
    tryBlock.handlerPC = reader.readPackedUInt30();
    tryBlock.flags = reader.readByte();
    tryBlock.types = new List<int>.generate(
        reader.readPackedUInt30(), (_) => reader.readPackedUInt30());

    return tryBlock;
  }

  @override
  String toString() => 'try-index $tryIndex, outer $outerTryIndex, '
      'start $startPC, end $endPC, handler $handlerPC, '
      '${needsStackTrace ? 'needs-stack-trace, ' : ''}'
      '${isSynthetic ? 'synthetic, ' : ''}'
      'types ${types.map((t) => 'CP#$t').toList()}';
}

class ExceptionsTable {
  List<TryBlock> blocks = <TryBlock>[];

  ExceptionsTable();

  TryBlock enterTryBlock(int startPC) {
    assert(blocks.isEmpty || blocks.last.startPC <= startPC);
    final tryBlock =
        new TryBlock._(blocks.length, _outerTryBlockIndex(startPC), startPC);
    blocks.add(tryBlock);
    return tryBlock;
  }

  int _outerTryBlockIndex(int startPC) {
    for (int i = blocks.length - 1; i >= 0; --i) {
      final tryBlock = blocks[i];
      if (tryBlock.endPC == null || tryBlock.endPC > startPC) {
        return i;
      }
    }
    return -1;
  }

  void write(BufferedWriter writer) {
    writer.writePackedUInt30(blocks.length);
    blocks.forEach((b) => b.write(writer));
  }

  ExceptionsTable.read(BufferedReader reader)
      : blocks = new List<TryBlock>.generate(reader.readPackedUInt30(),
            (int index) => new TryBlock.read(reader, index));

  @override
  String toString() {
    if (blocks.isEmpty) {
      return '';
    }
    StringBuffer sb = new StringBuffer();
    sb.writeln('ExceptionsTable {');
    for (var tryBlock in blocks) {
      sb.writeln('  $tryBlock');
    }
    sb.writeln('}');
    return sb.toString();
  }
}
