/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef ART_COMPILER_DWARF_DEBUG_LINE_OPCODE_WRITER_H_
#define ART_COMPILER_DWARF_DEBUG_LINE_OPCODE_WRITER_H_

#include "dwarf.h"
#include "writer.h"

namespace art {
namespace dwarf {

// Writer for the .debug_line opcodes (DWARF-3).
// The writer is very light-weight, however it will do the following for you:
//  * Choose the most compact encoding of a given opcode.
//  * Keep track of current state and convert absolute values to deltas.
//  * Divide by header-defined factors as appropriate.
template<typename Allocator = std::allocator<uint8_t>>
class DebugLineOpCodeWriter FINAL : private Writer<Allocator> {
 public:
  static constexpr int kOpcodeBase = 13;
  static constexpr bool kDefaultIsStmt = true;
  static constexpr int kLineBase = -5;
  static constexpr int kLineRange = 14;

  void AddRow() {
    this->PushUint8(DW_LNS_copy);
  }

  void AdvancePC(uint64_t absolute_address) {
    DCHECK_NE(current_address_, 0u);  // Use SetAddress for the first advance.
    DCHECK_GE(absolute_address, current_address_);
    if (absolute_address != current_address_) {
      uint64_t delta = FactorCodeOffset(absolute_address - current_address_);
      if (delta <= INT32_MAX) {
        this->PushUint8(DW_LNS_advance_pc);
        this->PushUleb128(static_cast<int>(delta));
        current_address_ = absolute_address;
      } else {
        SetAddress(absolute_address);
      }
    }
  }

  void AdvanceLine(int absolute_line) {
    int delta = absolute_line - current_line_;
    if (delta != 0) {
      this->PushUint8(DW_LNS_advance_line);
      this->PushSleb128(delta);
      current_line_ = absolute_line;
    }
  }

  void SetFile(int file) {
    if (current_file_ != file) {
      this->PushUint8(DW_LNS_set_file);
      this->PushUleb128(file);
      current_file_ = file;
    }
  }

  void SetColumn(int column) {
    this->PushUint8(DW_LNS_set_column);
    this->PushUleb128(column);
  }

  void NegateStmt() {
    this->PushUint8(DW_LNS_negate_stmt);
  }

  void SetBasicBlock() {
    this->PushUint8(DW_LNS_set_basic_block);
  }

  void SetPrologueEnd() {
    uses_dwarf3_features_ = true;
    this->PushUint8(DW_LNS_set_prologue_end);
  }

  void SetEpilogueBegin() {
    uses_dwarf3_features_ = true;
    this->PushUint8(DW_LNS_set_epilogue_begin);
  }

  void SetISA(int isa) {
    uses_dwarf3_features_ = true;
    this->PushUint8(DW_LNS_set_isa);
    this->PushUleb128(isa);
  }

  void EndSequence() {
    this->PushUint8(0);
    this->PushUleb128(1);
    this->PushUint8(DW_LNE_end_sequence);
    current_address_ = 0;
    current_file_ = 1;
    current_line_ = 1;
  }

  // Uncoditionally set address using the long encoding.
  // This gives the linker opportunity to relocate the address.
  void SetAddress(uint64_t absolute_address) {
    DCHECK_GE(absolute_address, current_address_);
    FactorCodeOffset(absolute_address);  // Check if it is factorable.
    this->PushUint8(0);
    if (use_64bit_address_) {
      this->PushUleb128(1 + 8);
      this->PushUint8(DW_LNE_set_address);
      this->PushUint64(absolute_address);
    } else {
      this->PushUleb128(1 + 4);
      this->PushUint8(DW_LNE_set_address);
      this->PushUint32(absolute_address);
    }
    current_address_ = absolute_address;
  }

  void DefineFile(const char* filename,
                  int directory_index,
                  int modification_time,
                  int file_size) {
    int size = 1 +
               strlen(filename) + 1 +
               UnsignedLeb128Size(directory_index) +
               UnsignedLeb128Size(modification_time) +
               UnsignedLeb128Size(file_size);
    this->PushUint8(0);
    this->PushUleb128(size);
    size_t start = data()->size();
    this->PushUint8(DW_LNE_define_file);
    this->PushString(filename);
    this->PushUleb128(directory_index);
    this->PushUleb128(modification_time);
    this->PushUleb128(file_size);
    DCHECK_EQ(start + size, data()->size());
  }

  // Compact address and line opcode.
  void AddRow(uint64_t absolute_address, int absolute_line) {
    DCHECK_GE(absolute_address, current_address_);

    // If the address is definitely too far, use the long encoding.
    uint64_t delta_address = FactorCodeOffset(absolute_address - current_address_);
    if (delta_address > UINT8_MAX) {
      AdvancePC(absolute_address);
      delta_address = 0;
    }

    // If the line is definitely too far, use the long encoding.
    int delta_line = absolute_line - current_line_;
    if (!(kLineBase <= delta_line && delta_line < kLineBase + kLineRange)) {
      AdvanceLine(absolute_line);
      delta_line = 0;
    }

    // Both address and line should be reasonable now.  Use the short encoding.
    int opcode = kOpcodeBase + (delta_line - kLineBase) +
                 (static_cast<int>(delta_address) * kLineRange);
    if (opcode > UINT8_MAX) {
      // If the address is still too far, try to increment it by const amount.
      int const_advance = (0xFF - kOpcodeBase) / kLineRange;
      opcode -= (kLineRange * const_advance);
      if (opcode <= UINT8_MAX) {
        this->PushUint8(DW_LNS_const_add_pc);
      } else {
        // Give up and use long encoding for address.
        AdvancePC(absolute_address);
        // Still use the opcode to do line advance and copy.
        opcode = kOpcodeBase + (delta_line - kLineBase);
      }
    }
    DCHECK(kOpcodeBase <= opcode && opcode <= 0xFF);
    this->PushUint8(opcode);  // Special opcode.
    current_line_ = absolute_line;
    current_address_ = absolute_address;
  }

  int GetCodeFactorBits() const {
    return code_factor_bits_;
  }

  uint64_t CurrentAddress() const {
    return current_address_;
  }

  int CurrentFile() const {
    return current_file_;
  }

  int CurrentLine() const {
    return current_line_;
  }

  using Writer<Allocator>::data;

  DebugLineOpCodeWriter(bool use64bitAddress,
                        int codeFactorBits,
                        const Allocator& alloc = Allocator())
      : Writer<Allocator>(&opcodes_),
        opcodes_(alloc),
        uses_dwarf3_features_(false),
        use_64bit_address_(use64bitAddress),
        code_factor_bits_(codeFactorBits),
        current_address_(0),
        current_file_(1),
        current_line_(1) {
  }

 private:
  uint64_t FactorCodeOffset(uint64_t offset) const {
    DCHECK_GE(code_factor_bits_, 0);
    DCHECK_EQ((offset >> code_factor_bits_) << code_factor_bits_, offset);
    return offset >> code_factor_bits_;
  }

  std::vector<uint8_t, Allocator> opcodes_;
  bool uses_dwarf3_features_;
  bool use_64bit_address_;
  int code_factor_bits_;
  uint64_t current_address_;
  int current_file_;
  int current_line_;

  DISALLOW_COPY_AND_ASSIGN(DebugLineOpCodeWriter);
};

}  // namespace dwarf
}  // namespace art

#endif  // ART_COMPILER_DWARF_DEBUG_LINE_OPCODE_WRITER_H_
