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

#ifndef RUNTIME_VM_COMPILER_RELOCATION_H_
#define RUNTIME_VM_COMPILER_RELOCATION_H_

#include "vm/allocation.h"
#include "vm/image_snapshot.h"
#include "vm/intrusive_dlist.h"
#include "vm/object.h"
#include "vm/type_testing_stubs.h"
#include "vm/visitor.h"

namespace dart {

#if defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_DBC) &&                  \
    !defined(TARGET_ARCH_IA32)

// Represents a pc-relative call which has not been patched up with the final
// destination.
class UnresolvedCall : public IntrusiveDListEntry<UnresolvedCall>,
                       public IntrusiveDListEntry<UnresolvedCall, 2> {
 public:
  UnresolvedCall(RawCode* caller,
                 intptr_t call_offset,
                 Code::CallEntryPoint call_entry_point,
                 intptr_t text_offset,
                 RawCode* callee)
      : caller(caller),
        call_offset(call_offset),
        call_entry_point(call_entry_point),
        text_offset(text_offset),
        callee(callee) {}

  UnresolvedCall(const UnresolvedCall& other)
      : caller(other.caller),
        call_offset(other.call_offset),
        call_entry_point(other.call_entry_point),
        text_offset(other.text_offset),
        callee(other.callee) {}

  // The caller which has an unresolved call.
  RawCode* caller;
  // The offset from the payload of the calling code which performs the call.
  intptr_t call_offset;
  // Type entry-point type we call in the destination.
  Code::CallEntryPoint call_entry_point;
  // The offset in the .text segment where the call happens.
  intptr_t text_offset;
  // The target of the forward call.
  RawCode* callee;
};

// A list of all unresolved calls.
using AllUnresolvedCallsList = IntrusiveDList<UnresolvedCall>;

// A list of all unresolved calls which call the same destination.
using SameDestinationUnresolvedCallsList = IntrusiveDList<UnresolvedCall, 2>;

// Represents a trampoline which has not been patched up with the final
// destination.
//
// The [CodeRelocator] will insert trampolines into the ".text" segment which
// increase the range of PC-relative calls.  If a pc-relative call in normal
// code is too far away from it's destination, it will call a trampoline
// instead (which will tail-call the destination).
struct UnresolvedTrampoline {
  // The entry-point type we call in the destination.
  Code::CallEntryPoint call_entry_point;
  // The target of the forward call.
  RawCode* callee;

  // The trampoline buffer.
  uint8_t* trampoline_bytes;
  // The offset in the .text segment where the trampoline starts.
  intptr_t text_offset;
};

template <typename ValueType, ValueType kNoValue>
class InstructionsMapTraits {
 public:
  struct Pair {
    RawInstructions* instructions;
    ValueType value;

    Pair() : instructions(nullptr), value(kNoValue) {}
    Pair(RawInstructions* i, const ValueType& value)
        : instructions(i), value(value) {}
  };

  typedef const RawInstructions* Key;
  typedef const ValueType Value;

  static Key KeyOf(Pair kv) { return kv.instructions; }
  static ValueType ValueOf(Pair kv) { return kv.value; }
  static inline intptr_t Hashcode(Key key) {
    return reinterpret_cast<intptr_t>(key);
  }
  static inline bool IsKeyEqual(Pair pair, Key key) {
    return pair.instructions == key;
  }
};

using InstructionsPosition =
    DirectChainedHashMap<InstructionsMapTraits<intptr_t, -1>>;

using InstructionsUnresolvedCalls = DirectChainedHashMap<
    InstructionsMapTraits<SameDestinationUnresolvedCallsList*, nullptr>>;

// Relocates the given code objects by patching the instructions with the
// correct pc offsets.
//
// Produces a set of [ImageWriterCommand]s which tell the image writer in which
// order (and at which offset) to emit instructions.
class CodeRelocator : public StackResource {
 public:
  // Relocates instructions of the code objects provided by patching any
  // pc-relative calls/jumps.
  //
  // Populates the image writer command array which must be used later to write
  // the ".text" segment.
  static void Relocate(Thread* thread,
                       GrowableArray<RawCode*>* code_objects,
                       GrowableArray<ImageWriterCommand>* commands,
                       bool is_vm_isolate) {
    CodeRelocator relocator(thread, code_objects, commands);
    relocator.Relocate(is_vm_isolate);
  }

 private:
  CodeRelocator(Thread* thread,
                GrowableArray<RawCode*>* code_objects,
                GrowableArray<ImageWriterCommand>* commands);

  void Relocate(bool is_vm_isolate);

  bool AddInstructionsToText(RawCode* code);
  void AddTrampolineToText(RawInstructions* destination,
                           uint8_t* trampoline_bytes,
                           intptr_t trampoline_length);
  void ScanCallTargets(const Code& code,
                       const Array& call_targets,
                       intptr_t code_text_offset);

  void EnqueueUnresolvedCall(UnresolvedCall* unresolved_call);
  void EnqueueUnresolvedTrampoline(UnresolvedTrampoline* unresolved_trampoline);

  bool TryResolveBackwardsCall(UnresolvedCall* unresolved_call);
  void ResolveUnresolvedCallsTargeting(const RawInstructions* instructions);
  void ResolveCall(UnresolvedCall* unresolved_call);
  void ResolveCallToDestination(UnresolvedCall* unresolved_call,
                                intptr_t destination_text);
  void ResolveTrampoline(UnresolvedTrampoline* unresolved_trampoline);

  void BuildTrampolinesForAlmostOutOfRangeCalls();

  intptr_t FindDestinationInText(const RawInstructions* destination,
                                 Code::CallEntryPoint call_entry_point);

  bool IsTargetInRangeFor(UnresolvedCall* unresolved_call,
                          intptr_t target_text_offset);

  const GrowableArray<RawCode*>* code_objects_;
  GrowableArray<ImageWriterCommand>* commands_;

  // The size of largest instructions object in bytes.
  intptr_t max_instructions_size_ = 0;
  // The maximum number of pc-relative calls in an instructions object.
  intptr_t max_calls_ = 0;

  // Data structures used for relocation.
  intptr_t next_text_offset_ = 0;
  InstructionsPosition text_offsets_;
  InstructionsPosition trampoline_text_offsets_;
  InstructionsUnresolvedCalls unresolved_calls_by_destination_;
  AllUnresolvedCallsList all_unresolved_calls_;
  GrowableArray<UnresolvedTrampoline*> unresolved_trampolines_;

  // Reusable handles for [ScanCallTargets].
  Smi& kind_type_and_offset_;
  Object& target_;
  Code& destination_;
};

#endif  // defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_DBC) &&           \
        // !defined(TARGET_ARCH_IA32)

}  // namespace dart

#endif  // RUNTIME_VM_COMPILER_RELOCATION_H_
