1c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky/*
2c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky * Copyright (C) 2015 The Android Open Source Project
3c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky *
4c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky * Licensed under the Apache License, Version 2.0 (the "License");
5c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky * you may not use this file except in compliance with the License.
6c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky * You may obtain a copy of the License at
7c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky *
8c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky *      http://www.apache.org/licenses/LICENSE-2.0
9c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky *
10c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky * Unless required by applicable law or agreed to in writing, software
11c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky * distributed under the License is distributed on an "AS IS" BASIS,
12c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky * See the License for the specific language governing permissions and
14c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky * limitations under the License.
15c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky */
16c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky
17c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky#include <memory>
18c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky#include <vector>
19c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky
20c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky#include "arch/instruction_set.h"
21c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky#include "cfi_test.h"
22c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky#include "gtest/gtest.h"
23c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky#include "optimizing/code_generator.h"
240a23d74dc2751440822960eab218be4cb8843647Nicolas Geoffray#include "optimizing/optimizing_unit_test.h"
25c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky#include "utils/assembler.h"
26c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky
27c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky#include "optimizing/optimizing_cfi_test_expected.inc"
28c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky
29c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbeckynamespace art {
30c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky
31c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky// Run the tests only on host.
32c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky#ifndef HAVE_ANDROID_OS
33c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky
343d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartierclass OptimizingCFITest : public CFITest {
35c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky public:
36c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky  // Enable this flag to generate the expected outputs.
37c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky  static constexpr bool kGenerateExpected = false;
38c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky
39c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky  void TestImpl(InstructionSet isa, const char* isa_str,
40c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky                const std::vector<uint8_t>& expected_asm,
41c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky                const std::vector<uint8_t>& expected_cfi) {
42c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky    // Setup simple context.
43c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky    ArenaPool pool;
44c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky    ArenaAllocator allocator(&pool);
45c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky    CompilerOptions opts;
46c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky    std::unique_ptr<const InstructionSetFeatures> isa_features;
47c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky    std::string error;
48c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky    isa_features.reset(InstructionSetFeatures::FromVariant(isa, "default", &error));
490a23d74dc2751440822960eab218be4cb8843647Nicolas Geoffray    HGraph* graph = CreateGraph(&allocator);
50c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky    // Generate simple frame with some spills.
5146325a0fae06ccbf5e0d7a7dd34d6cfe49226a40David Srbecky    std::unique_ptr<CodeGenerator> code_gen(
520a23d74dc2751440822960eab218be4cb8843647Nicolas Geoffray        CodeGenerator::Create(graph, isa, *isa_features.get(), opts));
53c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky    const int frame_size = 64;
54c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky    int core_reg = 0;
55c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky    int fp_reg = 0;
56c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky    for (int i = 0; i < 2; i++) {  // Two registers of each kind.
57c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky      for (; core_reg < 32; core_reg++) {
58c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky        if (code_gen->IsCoreCalleeSaveRegister(core_reg)) {
59c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky          auto location = Location::RegisterLocation(core_reg);
60c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky          code_gen->AddAllocatedRegister(location);
61c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky          core_reg++;
62c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky          break;
63c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky        }
64c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky      }
65c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky      for (; fp_reg < 32; fp_reg++) {
66c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky        if (code_gen->IsFloatingPointCalleeSaveRegister(fp_reg)) {
67c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky          auto location = Location::FpuRegisterLocation(fp_reg);
68c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky          code_gen->AddAllocatedRegister(location);
69c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky          fp_reg++;
70c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky          break;
71c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky        }
72c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky      }
73c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky    }
74c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky    code_gen->ComputeSpillMask();
75c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky    code_gen->SetFrameSize(frame_size);
76c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky    code_gen->GenerateFrameEntry();
77c34dc9362b9ec624b3bdd97d36b6b2098814cd73David Srbecky    code_gen->GenerateFrameExit();
78c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky    // Get the outputs.
7946325a0fae06ccbf5e0d7a7dd34d6cfe49226a40David Srbecky    InternalCodeAllocator code_allocator;
8046325a0fae06ccbf5e0d7a7dd34d6cfe49226a40David Srbecky    code_gen->Finalize(&code_allocator);
8146325a0fae06ccbf5e0d7a7dd34d6cfe49226a40David Srbecky    const std::vector<uint8_t>& actual_asm = code_allocator.GetMemory();
82c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky    Assembler* opt_asm = code_gen->GetAssembler();
83c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky    const std::vector<uint8_t>& actual_cfi = *(opt_asm->cfi().data());
84c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky
85c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky    if (kGenerateExpected) {
86c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky      GenerateExpected(stdout, isa, isa_str, actual_asm, actual_cfi);
87c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky    } else {
88c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky      EXPECT_EQ(expected_asm, actual_asm);
89c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky      EXPECT_EQ(expected_cfi, actual_cfi);
90c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky    }
91c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky  }
9246325a0fae06ccbf5e0d7a7dd34d6cfe49226a40David Srbecky
9346325a0fae06ccbf5e0d7a7dd34d6cfe49226a40David Srbecky private:
9446325a0fae06ccbf5e0d7a7dd34d6cfe49226a40David Srbecky  class InternalCodeAllocator : public CodeAllocator {
9546325a0fae06ccbf5e0d7a7dd34d6cfe49226a40David Srbecky   public:
9646325a0fae06ccbf5e0d7a7dd34d6cfe49226a40David Srbecky    InternalCodeAllocator() {}
9746325a0fae06ccbf5e0d7a7dd34d6cfe49226a40David Srbecky
9846325a0fae06ccbf5e0d7a7dd34d6cfe49226a40David Srbecky    virtual uint8_t* Allocate(size_t size) {
9946325a0fae06ccbf5e0d7a7dd34d6cfe49226a40David Srbecky      memory_.resize(size);
10046325a0fae06ccbf5e0d7a7dd34d6cfe49226a40David Srbecky      return memory_.data();
10146325a0fae06ccbf5e0d7a7dd34d6cfe49226a40David Srbecky    }
10246325a0fae06ccbf5e0d7a7dd34d6cfe49226a40David Srbecky
10346325a0fae06ccbf5e0d7a7dd34d6cfe49226a40David Srbecky    const std::vector<uint8_t>& GetMemory() { return memory_; }
10446325a0fae06ccbf5e0d7a7dd34d6cfe49226a40David Srbecky
10546325a0fae06ccbf5e0d7a7dd34d6cfe49226a40David Srbecky   private:
10646325a0fae06ccbf5e0d7a7dd34d6cfe49226a40David Srbecky    std::vector<uint8_t> memory_;
10746325a0fae06ccbf5e0d7a7dd34d6cfe49226a40David Srbecky
10846325a0fae06ccbf5e0d7a7dd34d6cfe49226a40David Srbecky    DISALLOW_COPY_AND_ASSIGN(InternalCodeAllocator);
10946325a0fae06ccbf5e0d7a7dd34d6cfe49226a40David Srbecky  };
110c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky};
111c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky
112c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky#define TEST_ISA(isa) \
113c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky  TEST_F(OptimizingCFITest, isa) { \
114c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky    std::vector<uint8_t> expected_asm(expected_asm_##isa, \
115c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky        expected_asm_##isa + arraysize(expected_asm_##isa)); \
116c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky    std::vector<uint8_t> expected_cfi(expected_cfi_##isa, \
117c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky        expected_cfi_##isa + arraysize(expected_cfi_##isa)); \
118c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky    TestImpl(isa, #isa, expected_asm, expected_cfi); \
119c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky  }
120c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky
121c6b4dd8980350aaf250f0185f73e9c42ec17cd57David SrbeckyTEST_ISA(kThumb2)
122c6b4dd8980350aaf250f0185f73e9c42ec17cd57David SrbeckyTEST_ISA(kArm64)
123c6b4dd8980350aaf250f0185f73e9c42ec17cd57David SrbeckyTEST_ISA(kX86)
124c6b4dd8980350aaf250f0185f73e9c42ec17cd57David SrbeckyTEST_ISA(kX86_64)
125c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky
126c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky#endif  // HAVE_ANDROID_OS
127c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky
128c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky}  // namespace art
129