/*
 * 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 "cfi_test.h"
#include "gtest/gtest.h"
#include "optimizing/code_generator.h"
#include "optimizing/optimizing_unit_test.h"
#include "utils/assembler.h"

#include "optimizing/optimizing_cfi_test_expected.inc"

namespace art {

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

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

  void TestImpl(InstructionSet isa, const char* isa_str,
                const std::vector<uint8_t>& expected_asm,
                const std::vector<uint8_t>& expected_cfi) {
    // Setup simple context.
    ArenaPool pool;
    ArenaAllocator allocator(&pool);
    CompilerOptions opts;
    std::unique_ptr<const InstructionSetFeatures> isa_features;
    std::string error;
    isa_features.reset(InstructionSetFeatures::FromVariant(isa, "default", &error));
    HGraph* graph = CreateGraph(&allocator);
    // Generate simple frame with some spills.
    std::unique_ptr<CodeGenerator> code_gen(
        CodeGenerator::Create(graph, isa, *isa_features.get(), opts));
    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;
        }
      }
    }
    GrowableArray<HBasicBlock*> blocks(&allocator, 0);
    code_gen->block_order_ = &blocks;
    code_gen->ComputeSpillMask();
    code_gen->SetFrameSize(frame_size);
    code_gen->GenerateFrameEntry();
    code_gen->GenerateFrameExit();
    // Get the outputs.
    InternalCodeAllocator code_allocator;
    code_gen->Finalize(&code_allocator);
    const std::vector<uint8_t>& actual_asm = code_allocator.GetMemory();
    Assembler* opt_asm = code_gen->GetAssembler();
    const std::vector<uint8_t>& actual_cfi = *(opt_asm->cfi().data());

    if (kGenerateExpected) {
      GenerateExpected(stdout, isa, isa_str, actual_asm, actual_cfi);
    } else {
      EXPECT_EQ(expected_asm, actual_asm);
      EXPECT_EQ(expected_cfi, actual_cfi);
    }
  }

 private:
  class InternalCodeAllocator : public CodeAllocator {
   public:
    InternalCodeAllocator() {}

    virtual uint8_t* Allocate(size_t size) {
      memory_.resize(size);
      return memory_.data();
    }

    const std::vector<uint8_t>& GetMemory() { return memory_; }

   private:
    std::vector<uint8_t> memory_;

    DISALLOW_COPY_AND_ASSIGN(InternalCodeAllocator);
  };
};

#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(isa, #isa, expected_asm, expected_cfi); \
  }

TEST_ISA(kThumb2)
TEST_ISA(kArm64)
TEST_ISA(kX86)
TEST_ISA(kX86_64)

#endif  // __ANDROID__

}  // namespace art
