/*
 * Copyright (C) 2016 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_LINKER_MULTI_OAT_RELATIVE_PATCHER_H_
#define ART_COMPILER_LINKER_MULTI_OAT_RELATIVE_PATCHER_H_

#include "arch/instruction_set.h"
#include "method_reference.h"
#include "relative_patcher.h"
#include "safe_map.h"

namespace art {

class CompiledMethod;
class LinkerPatch;
class InstructionSetFeatures;

namespace linker {

// MultiOatRelativePatcher is a helper class for handling patching across
// any number of oat files. It provides storage for method code offsets
// and wraps RelativePatcher calls, adjusting relative offsets according
// to the value set by SetAdjustment().
class MultiOatRelativePatcher FINAL {
 public:
  using const_iterator =
      SafeMap<MethodReference, uint32_t, MethodReferenceComparator>::const_iterator;

  MultiOatRelativePatcher(InstructionSet instruction_set, const InstructionSetFeatures* features);

  // Mark the start of a new oat file (for statistics retrieval) and set the
  // adjustment for a new oat file to apply to all relative offsets that are
  // passed to the MultiOatRelativePatcher.
  //
  // The adjustment should be the global offset of the base from which relative
  // offsets are calculated, such as the start of .rodata for the current oat file.
  // It must must never point directly to a method's code to avoid relative offsets
  // with value 0 because this value is used as a missing offset indication in
  // GetOffset() and an error indication in WriteThunks(). Additionally, it must be
  // page-aligned, so that it does not skew alignment calculations, say arm64 ADRP.
  void StartOatFile(uint32_t adjustment);

  // Get relative offset. Returns 0 when the offset has not been set yet.
  uint32_t GetOffset(MethodReference method_ref) {
    auto it = method_offset_map_.map.find(method_ref);
    return (it != method_offset_map_.map.end()) ? it->second - adjustment_ : 0u;
  }

  // Set the offset.
  void SetOffset(MethodReference method_ref, uint32_t offset) {
    method_offset_map_.map.Put(method_ref, offset + adjustment_);
  }

  // Wrapper around RelativePatcher::ReserveSpace(), doing offset adjustment.
  uint32_t ReserveSpace(uint32_t offset,
                        const CompiledMethod* compiled_method,
                        MethodReference method_ref) {
    offset += adjustment_;
    offset = relative_patcher_->ReserveSpace(offset, compiled_method, method_ref);
    offset -= adjustment_;
    return offset;
  }

  // Wrapper around RelativePatcher::ReserveSpaceEnd(), doing offset adjustment.
  uint32_t ReserveSpaceEnd(uint32_t offset) {
    offset += adjustment_;
    offset = relative_patcher_->ReserveSpaceEnd(offset);
    offset -= adjustment_;
    return offset;
  }

  // Wrapper around RelativePatcher::WriteThunks(), doing offset adjustment.
  uint32_t WriteThunks(OutputStream* out, uint32_t offset) {
    offset += adjustment_;
    offset = relative_patcher_->WriteThunks(out, offset);
    if (offset != 0u) {  // 0u indicates write error.
      offset -= adjustment_;
    }
    return offset;
  }

  // Wrapper around RelativePatcher::PatchCall(), doing offset adjustment.
  void PatchCall(std::vector<uint8_t>* code,
                 uint32_t literal_offset,
                 uint32_t patch_offset,
                 uint32_t target_offset) {
    patch_offset += adjustment_;
    target_offset += adjustment_;
    relative_patcher_->PatchCall(code, literal_offset, patch_offset, target_offset);
  }

  // Wrapper around RelativePatcher::PatchDexCacheReference(), doing offset adjustment.
  void PatchDexCacheReference(std::vector<uint8_t>* code,
                              const LinkerPatch& patch,
                              uint32_t patch_offset,
                              uint32_t target_offset) {
    patch_offset += adjustment_;
    target_offset += adjustment_;
    relative_patcher_->PatchDexCacheReference(code, patch, patch_offset, target_offset);
  }

  // Wrappers around RelativePatcher for statistics retrieval.
  uint32_t CodeAlignmentSize() const;
  uint32_t RelativeCallThunksSize() const;
  uint32_t MiscThunksSize() const;

 private:
  // Map method reference to assigned offset.
  // Wrap the map in a class implementing linker::RelativePatcherTargetProvider.
  class MethodOffsetMap : public linker::RelativePatcherTargetProvider {
   public:
    std::pair<bool, uint32_t> FindMethodOffset(MethodReference ref) OVERRIDE;
    SafeMap<MethodReference, uint32_t, MethodReferenceComparator> map;
  };

  MethodOffsetMap method_offset_map_;
  std::unique_ptr<RelativePatcher> relative_patcher_;
  uint32_t adjustment_;
  InstructionSet instruction_set_;

  uint32_t start_size_code_alignment_;
  uint32_t start_size_relative_call_thunks_;
  uint32_t start_size_misc_thunks_;

  friend class MultiOatRelativePatcherTest;

  DISALLOW_COPY_AND_ASSIGN(MultiOatRelativePatcher);
};

}  // namespace linker
}  // namespace art

#endif  // ART_COMPILER_LINKER_MULTI_OAT_RELATIVE_PATCHER_H_
