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

#ifndef VM_REGEXP_ASSEMBLER_BYTECODE_H_
#define VM_REGEXP_ASSEMBLER_BYTECODE_H_

#include "vm/object.h"
#include "vm/regexp_assembler.h"

namespace dart {

class BytecodeRegExpMacroAssembler: public RegExpMacroAssembler {
 public:
  // Create an assembler. Instructions and relocation information are emitted
  // into a buffer, with the instructions starting from the beginning and the
  // relocation information starting from the end of the buffer. See CodeDesc
  // for a detailed comment on the layout (globals.h).
  //
  // If the provided buffer is NULL, the assembler allocates and grows its own
  // buffer, and buffer_size determines the initial buffer size. The buffer is
  // owned by the assembler and deallocated upon destruction of the assembler.
  //
  // If the provided buffer is not NULL, the assembler uses the provided buffer
  // for code generation and assumes its size to be buffer_size. If the buffer
  // is too small, a fatal error occurs. No deallocation of the buffer is done
  // upon destruction of the assembler.
  BytecodeRegExpMacroAssembler(ZoneGrowableArray<uint8_t>* buffer,
                               Zone* zone);
  virtual ~BytecodeRegExpMacroAssembler();

  // The byte-code interpreter checks on each push anyway.
  virtual intptr_t stack_limit_slack() { return 1; }
  virtual bool CanReadUnaligned() { return false; }
  virtual void BindBlock(BlockLabel* label);
  virtual void AdvanceCurrentPosition(intptr_t by);  // Signed cp change.
  virtual void PopCurrentPosition();
  virtual void PushCurrentPosition();
  virtual void Backtrack();
  virtual void GoTo(BlockLabel* label);
  virtual void PushBacktrack(BlockLabel* label);
  virtual bool Succeed();
  virtual void Fail();
  virtual void PopRegister(intptr_t register_index);
  virtual void PushRegister(intptr_t register_index);
  virtual void AdvanceRegister(intptr_t reg, intptr_t by);  // r[reg] += by.
  virtual void SetCurrentPositionFromEnd(intptr_t by);
  virtual void SetRegister(intptr_t register_index, intptr_t to);
  virtual void WriteCurrentPositionToRegister(intptr_t reg, intptr_t cp_offset);
  virtual void ClearRegisters(intptr_t reg_from, intptr_t reg_to);
  virtual void ReadCurrentPositionFromRegister(intptr_t reg);
  virtual void WriteStackPointerToRegister(intptr_t reg);
  virtual void ReadStackPointerFromRegister(intptr_t reg);
  virtual void LoadCurrentCharacter(intptr_t cp_offset,
                                    BlockLabel* on_end_of_input,
                                    bool check_bounds = true,
                                    intptr_t characters = 1);
  virtual void CheckCharacter(unsigned c, BlockLabel* on_equal);
  virtual void CheckCharacterAfterAnd(unsigned c,
                                      unsigned mask,
                                      BlockLabel* on_equal);
  virtual void CheckCharacterGT(uint16_t limit, BlockLabel* on_greater);
  virtual void CheckCharacterLT(uint16_t limit, BlockLabel* on_less);
  virtual void CheckGreedyLoop(BlockLabel* on_tos_equals_current_position);
  virtual void CheckAtStart(BlockLabel* on_at_start);
  virtual void CheckNotAtStart(BlockLabel* on_not_at_start);
  virtual void CheckNotCharacter(unsigned c, BlockLabel* on_not_equal);
  virtual void CheckNotCharacterAfterAnd(unsigned c,
                                         unsigned mask,
                                         BlockLabel* on_not_equal);
  virtual void CheckNotCharacterAfterMinusAnd(uint16_t c,
                                              uint16_t minus,
                                              uint16_t mask,
                                              BlockLabel* on_not_equal);
  virtual void CheckCharacterInRange(uint16_t from,
                                     uint16_t to,
                                     BlockLabel* on_in_range);
  virtual void CheckCharacterNotInRange(uint16_t from,
                                        uint16_t to,
                                        BlockLabel* on_not_in_range);
  virtual void CheckBitInTable(const TypedData& table, BlockLabel* on_bit_set);
  virtual void CheckNotBackReference(intptr_t start_reg,
                                     BlockLabel* on_no_match);
  virtual void CheckNotBackReferenceIgnoreCase(intptr_t start_reg,
                                               BlockLabel* on_no_match);
  virtual void IfRegisterLT(intptr_t register_index,
                            intptr_t comparand,
                            BlockLabel* if_lt);
  virtual void IfRegisterGE(intptr_t register_index,
                            intptr_t comparand,
                            BlockLabel* if_ge);
  virtual void IfRegisterEqPos(intptr_t register_index, BlockLabel* if_eq);

  virtual IrregexpImplementation Implementation();
  // virtual Handle<HeapObject> GetCode(Handle<String> source);
  RawTypedData* GetBytecode();

  // New
  virtual bool IsClosed() const {
    // Added by Dart for the IR version. Bytecode version should never need an
    // extra goto.
    return true;
  }
  virtual void Print(const char* str)  { UNIMPLEMENTED(); }
  virtual void PrintBlocks() { UNIMPLEMENTED(); }
  /////

  static RawInstance* Interpret(const RegExp& regexp,
                                const String& str,
                                const Smi& start_index,
                                Zone* zone);

 private:
  void Expand();
  // Code and bitmap emission.
  inline void EmitOrLink(BlockLabel* label);
  inline void Emit32(uint32_t x);
  inline void Emit16(uint32_t x);
  inline void Emit8(uint32_t x);
  inline void Emit(uint32_t bc, uint32_t arg);
  // Bytecode buffer.
  intptr_t length();

  // The buffer into which code and relocation info are generated.
  ZoneGrowableArray<uint8_t>* buffer_;

  // The program counter.
  intptr_t pc_;

  BlockLabel backtrack_;

  intptr_t advance_current_start_;
  intptr_t advance_current_offset_;
  intptr_t advance_current_end_;

  static const int kInvalidPC = -1;

  DISALLOW_IMPLICIT_CONSTRUCTORS(BytecodeRegExpMacroAssembler);
};


}  // namespace dart

#endif  // VM_REGEXP_ASSEMBLER_BYTECODE_H_
