// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <stddef.h>

#include "courgette/assembly_program.h"

#include "base/logging.h"
#include "courgette/encoded_program.h"
#include "courgette/instruction_utils.h"

namespace courgette {

namespace {

// An instruction receptor that adds each received abs32/rel32 Label* to the
// matching VECTOR member variable. Template VECTOR allows code reuse for
// counting (CountingVector) and storage (std::vector).
template <template <typename T, typename... Args> class CONTAINER>
class LabelReceptor : public InstructionReceptor {
 public:
  using VECTOR = CONTAINER<Label*>;

  LabelReceptor() = default;
  ~LabelReceptor() override = default;

  VECTOR* mutable_abs32_vector() { return &abs32_vector_; }
  VECTOR* mutable_rel32_vector() { return &rel32_vector_; }

  // InstructionReceptor:
  CheckBool EmitPeRelocs() override { return true; }
  CheckBool EmitElfRelocation() override { return true; }
  CheckBool EmitElfARMRelocation() override { return true; }
  CheckBool EmitOrigin(RVA rva) override { return true; }
  CheckBool EmitSingleByte(uint8_t byte) override { return true; }
  CheckBool EmitMultipleBytes(const uint8_t* bytes, size_t len) override {
    return true;
  }
  CheckBool EmitRel32(Label* label) override {
    rel32_vector_.push_back(label);
    return true;
  }
  CheckBool EmitRel32ARM(uint16_t op,
                         Label* label,
                         const uint8_t* arm_op,
                         uint16_t op_size) override {
    rel32_vector_.push_back(label);
    return true;
  }
  CheckBool EmitAbs32(Label* label) override {
    abs32_vector_.push_back(label);
    return true;
  }
  CheckBool EmitAbs64(Label* label) override {
    abs32_vector_.push_back(label);
    return true;
  }

 private:
  VECTOR abs32_vector_;
  VECTOR rel32_vector_;

  DISALLOW_COPY_AND_ASSIGN(LabelReceptor);
};

}  // namespace

AssemblyProgram::AssemblyProgram(ExecutableType kind, uint64_t image_base)
    : kind_(kind), image_base_(image_base) {}

AssemblyProgram::~AssemblyProgram() = default;

void AssemblyProgram::PrecomputeLabels(RvaVisitor* abs32_visitor,
                                       RvaVisitor* rel32_visitor) {
  abs32_label_manager_.Read(abs32_visitor);
  rel32_label_manager_.Read(rel32_visitor);
  TrimLabels();
}

// Chosen empirically to give the best reduction in payload size for
// an update from daisy_3701.98.0 to daisy_4206.0.0.
const int AssemblyProgram::kLabelLowerLimit = 5;

void AssemblyProgram::TrimLabels() {
  // For now only trim for ARM binaries.
  if (kind() != EXE_ELF_32_ARM)
    return;

  int lower_limit = kLabelLowerLimit;

  VLOG(1) << "TrimLabels: threshold " << lower_limit;

  rel32_label_manager_.RemoveUnderusedLabels(lower_limit);
}

void AssemblyProgram::UnassignIndexes() {
  abs32_label_manager_.UnassignIndexes();
  rel32_label_manager_.UnassignIndexes();
}

void AssemblyProgram::DefaultAssignIndexes() {
  abs32_label_manager_.DefaultAssignIndexes();
  rel32_label_manager_.DefaultAssignIndexes();
}

void AssemblyProgram::AssignRemainingIndexes() {
  abs32_label_manager_.AssignRemainingIndexes();
  rel32_label_manager_.AssignRemainingIndexes();
}

Label* AssemblyProgram::FindAbs32Label(RVA rva) {
  return abs32_label_manager_.Find(rva);
}

Label* AssemblyProgram::FindRel32Label(RVA rva) {
  return rel32_label_manager_.Find(rva);
}

CheckBool AssemblyProgram::AnnotateLabels(const InstructionGenerator& gen) {
  // Pass 1: Compute required space.
  LabelReceptor<CountingVector> count_receptor;
  if (!gen.Run(&count_receptor))
    return false;

  // Pass 2: Reserve and store annotations.
  LabelReceptor<std::vector> annotate_receptor;
  annotate_receptor.mutable_abs32_vector()->reserve(
      count_receptor.mutable_abs32_vector()->size());
  annotate_receptor.mutable_rel32_vector()->reserve(
      count_receptor.mutable_rel32_vector()->size());
  if (!gen.Run(&annotate_receptor))
    return false;

  // Move results to |abs32_label_annotations_| and |re32_label_annotations_|.
  abs32_label_annotations_.swap(*annotate_receptor.mutable_abs32_vector());
  rel32_label_annotations_.swap(*annotate_receptor.mutable_rel32_vector());
  return true;
}

bool AssemblyProgram::PrepareEncodedProgram(EncodedProgram* encoded) const {
  encoded->set_image_base(image_base_);
  return encoded->ImportLabels(abs32_label_manager_, rel32_label_manager_);
}

}  // namespace courgette
