/*
 * Copyright (C) 2011 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_SRC_COMPILED_METHOD_H_
#define ART_SRC_COMPILED_METHOD_H_

#include <vector>

#include "instruction_set.h"
#include "utils.h"
#include "UniquePtr.h"

namespace llvm {
  class Function;
}

namespace art {

class CompiledCode {
 public:
  CompiledCode(InstructionSet instruction_set)
      : instruction_set_(instruction_set) {
  }

  CompiledCode(InstructionSet instruction_set, const std::vector<uint8_t>& code)
      : instruction_set_(instruction_set), code_(code) {
    CHECK_NE(code.size(), 0U);
  }

  InstructionSet GetInstructionSet() const {
    return instruction_set_;
  }

  const std::vector<uint8_t>& GetCode() const {
    return code_;
  }

  void SetCode(const std::vector<uint8_t>& code) {
    CHECK_NE(code.size(), 0U);
    code_ = code;
  }

  bool operator==(const CompiledCode& rhs) const {
    return (code_ == rhs.code_);
  }

  // To align an offset from a page-aligned value to make it suitable
  // for code storage. For example on ARM, to ensure that PC relative
  // valu computations work out as expected.
  uint32_t AlignCode(uint32_t offset) const;
  static uint32_t AlignCode(uint32_t offset, InstructionSet instruction_set);

  // returns the difference between the code address and a usable PC.
  // mainly to cope with kThumb2 where the lower bit must be set.
  size_t CodeDelta() const;

  // Returns a pointer suitable for invoking the code at the argument
  // code_pointer address.  Mainly to cope with kThumb2 where the
  // lower bit must be set to indicate Thumb mode.
  static const void* CodePointer(const void* code_pointer,
                                 InstructionSet instruction_set);

 private:
  const InstructionSet instruction_set_;
  std::vector<uint8_t> code_;
};

class CompiledMethod : public CompiledCode {
 public:
  // Constructs a CompiledMethod for the non-LLVM compilers.
  CompiledMethod(InstructionSet instruction_set,
                 const std::vector<uint8_t>& code,
                 const size_t frame_size_in_bytes,
                 const uint32_t core_spill_mask,
                 const uint32_t fp_spill_mask,
                 const std::vector<uint32_t>& mapping_table,
                 const std::vector<uint16_t>& vmap_table,
                 const std::vector<uint8_t>& native_gc_map);

  // Constructs a CompiledMethod for the JniCompiler.
  CompiledMethod(InstructionSet instruction_set,
                 const std::vector<uint8_t>& code,
                 const size_t frame_size_in_bytes,
                 const uint32_t core_spill_mask,
                 const uint32_t fp_spill_mask);

  // Constructs a CompiledMethod for the LLVM compiler.
  CompiledMethod(InstructionSet instruction_set,
                 const std::vector<uint8_t>& code,
                 const std::vector<uint8_t>& gc_map)
      : CompiledCode(instruction_set, code),
        frame_size_in_bytes_(kStackAlignment), core_spill_mask_(0),
        fp_spill_mask_(0), native_gc_map_(gc_map) {
  }

  // Constructs a CompiledMethod for the LLVM JniCompiler.
  CompiledMethod(InstructionSet instruction_set,
                 const std::vector<uint8_t>& code)
      : CompiledCode(instruction_set, code),
        frame_size_in_bytes_(kStackAlignment), core_spill_mask_(0),
        fp_spill_mask_(0) {
  }

  ~CompiledMethod() {}

  size_t GetFrameSizeInBytes() const {
    return frame_size_in_bytes_;
  }

  uint32_t GetCoreSpillMask() const {
    return core_spill_mask_;
  }

  uint32_t GetFpSpillMask() const {
    return fp_spill_mask_;
  }

  const std::vector<uint32_t>& GetMappingTable() const {
    return mapping_table_;
  }

  const std::vector<uint16_t>& GetVmapTable() const {
    return vmap_table_;
  }

  const std::vector<uint8_t>& GetNativeGcMap() const {
    return native_gc_map_;
  }

 private:
  const size_t frame_size_in_bytes_;
  const uint32_t core_spill_mask_;
  const uint32_t fp_spill_mask_;
  std::vector<uint32_t> mapping_table_;
  std::vector<uint16_t> vmap_table_;
  std::vector<uint8_t> native_gc_map_;
};

class CompiledInvokeStub : public CompiledCode {
 public:
  explicit CompiledInvokeStub(InstructionSet instruction_set);

  explicit CompiledInvokeStub(InstructionSet instruction_set,
                              const std::vector<uint8_t>& code);

  ~CompiledInvokeStub() {}
};

}  // namespace art

#endif  // ART_SRC_COMPILED_METHOD_H_
