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

#include <memory>
#include <vector>

#include "arch/instruction_set.h"
#include "base/macros.h"
#include "base/runtime_debug.h"
#include "cfi_test.h"
#include "driver/compiler_options.h"
#include "gtest/gtest.h"
#include "optimizing/code_generator.h"
#include "optimizing/optimizing_unit_test.h"
#include "read_barrier_config.h"
#include "utils/arm/assembler_arm_vixl.h"
#include "utils/assembler.h"

#include "optimizing/optimizing_cfi_test_expected.inc"

namespace vixl32 = vixl::aarch32;

namespace art HIDDEN {

// Run the tests only on host.
#ifndef ART_TARGET_ANDROID

class OptimizingCFITest : public CFITest, public OptimizingUnitTestHelper {
 public:
  // Enable this flag to generate the expected outputs.
  static constexpr bool kGenerateExpected = false;

  OptimizingCFITest()
      : graph_(nullptr),
        code_gen_(),
        blocks_(GetAllocator()->Adapter()) {}

  void SetUpFrame(InstructionSet isa) {
    OverrideInstructionSetFeatures(isa, "default");

    // Ensure that slow-debug is off, so that there is no unexpected read-barrier check emitted.
    SetRuntimeDebugFlagsEnabled(false);

    // Setup simple context.
    graph_ = CreateGraph();
    // Generate simple frame with some spills.
    code_gen_ = CodeGenerator::Create(graph_, *compiler_options_);
    code_gen_->GetAssembler()->cfi().SetEnabled(true);
    code_gen_->InitializeCodeGenerationData();
    const int frame_size = 64;
    int core_reg = 0;
    int fp_reg = 0;
    for (int i = 0; i < 2; i++) {  // Two registers of each kind.
      for (; core_reg < 32; core_reg++) {
        if (code_gen_->IsCoreCalleeSaveRegister(core_reg)) {
          auto location = Location::RegisterLocation(core_reg);
          code_gen_->AddAllocatedRegister(location);
          core_reg++;
          break;
        }
      }
      for (; fp_reg < 32; fp_reg++) {
        if (code_gen_->IsFloatingPointCalleeSaveRegister(fp_reg)) {
          auto location = Location::FpuRegisterLocation(fp_reg);
          code_gen_->AddAllocatedRegister(location);
          fp_reg++;
          break;
        }
      }
    }
    code_gen_->block_order_ = &blocks_;
    code_gen_->ComputeSpillMask();
    code_gen_->SetFrameSize(frame_size);
    code_gen_->GenerateFrameEntry();
  }

  void Finish() {
    code_gen_->GenerateFrameExit();
    code_gen_->Finalize();
  }

  void Check(InstructionSet isa,
             const char* isa_str,
             const std::vector<uint8_t>& expected_asm,
             const std::vector<uint8_t>& expected_cfi) {
    // Get the outputs.
    ArrayRef<const uint8_t> actual_asm = code_gen_->GetCode();
    Assembler* opt_asm = code_gen_->GetAssembler();
    ArrayRef<const uint8_t> actual_cfi(*(opt_asm->cfi().data()));

    if (kGenerateExpected) {
      GenerateExpected(stdout, isa, isa_str, actual_asm, actual_cfi);
    } else {
      EXPECT_EQ(ArrayRef<const uint8_t>(expected_asm), actual_asm);
      EXPECT_EQ(ArrayRef<const uint8_t>(expected_cfi), actual_cfi);
    }
  }

  void TestImpl(InstructionSet isa, const char*
                isa_str,
                const std::vector<uint8_t>& expected_asm,
                const std::vector<uint8_t>& expected_cfi) {
    SetUpFrame(isa);
    Finish();
    Check(isa, isa_str, expected_asm, expected_cfi);
  }

  CodeGenerator* GetCodeGenerator() {
    return code_gen_.get();
  }

 private:
  HGraph* graph_;
  std::unique_ptr<CodeGenerator> code_gen_;
  ArenaVector<HBasicBlock*> blocks_;
};

#define TEST_ISA(isa)                                                 \
  TEST_F(OptimizingCFITest, isa) {                                    \
    std::vector<uint8_t> expected_asm(                                \
        expected_asm_##isa,                                           \
        expected_asm_##isa + arraysize(expected_asm_##isa));          \
    std::vector<uint8_t> expected_cfi(                                \
        expected_cfi_##isa,                                           \
        expected_cfi_##isa + arraysize(expected_cfi_##isa));          \
    TestImpl(InstructionSet::isa, #isa, expected_asm, expected_cfi);  \
  }

#ifdef ART_ENABLE_CODEGEN_arm
TEST_ISA(kThumb2)
#endif

#ifdef ART_ENABLE_CODEGEN_arm64
// Run the tests for ARM64 only with Baker read barriers, as the
// expected generated code saves and restore X21 and X22 (instead of
// X20 and X21), as X20 is used as Marking Register in the Baker read
// barrier configuration, and as such is removed from the set of
// callee-save registers in the ARM64 code generator of the Optimizing
// compiler.
//
// We can't use compile-time macros for read-barrier as the introduction
// of userfaultfd-GC has made it a runtime choice.
TEST_F(OptimizingCFITest, kArm64) {
  if (kUseBakerReadBarrier && gUseReadBarrier) {
    std::vector<uint8_t> expected_asm(
        expected_asm_kArm64,
        expected_asm_kArm64 + arraysize(expected_asm_kArm64));
    std::vector<uint8_t> expected_cfi(
        expected_cfi_kArm64,
        expected_cfi_kArm64 + arraysize(expected_cfi_kArm64));
    TestImpl(InstructionSet::kArm64, "kArm64", expected_asm, expected_cfi);
  }
}
#endif

#ifdef ART_ENABLE_CODEGEN_x86
TEST_ISA(kX86)
#endif

#ifdef ART_ENABLE_CODEGEN_x86_64
TEST_ISA(kX86_64)
#endif

#ifdef ART_ENABLE_CODEGEN_arm
TEST_F(OptimizingCFITest, kThumb2Adjust) {
  using vixl32::r0;
  std::vector<uint8_t> expected_asm(
      expected_asm_kThumb2_adjust,
      expected_asm_kThumb2_adjust + arraysize(expected_asm_kThumb2_adjust));
  std::vector<uint8_t> expected_cfi(
      expected_cfi_kThumb2_adjust,
      expected_cfi_kThumb2_adjust + arraysize(expected_cfi_kThumb2_adjust));
  SetUpFrame(InstructionSet::kThumb2);
#define __ down_cast<arm::ArmVIXLAssembler*>(GetCodeGenerator() \
    ->GetAssembler())->GetVIXLAssembler()->
  vixl32::Label target;
  __ CompareAndBranchIfZero(r0, &target);
  // Push the target out of range of CBZ.
  for (size_t i = 0; i != 65; ++i) {
    __ Ldr(r0, vixl32::MemOperand(r0));
  }
  __ Bind(&target);
#undef __
  Finish();
  Check(InstructionSet::kThumb2, "kThumb2_adjust", expected_asm, expected_cfi);
}
#endif

#endif  // ART_TARGET_ANDROID

}  // namespace art
