blob: 24daf2f15f0f9a2e0e20fb9f710fc75199ff9807 [file] [log] [blame]
David Srbecky1109fb32015-04-07 20:21:06 +01001/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <vector>
18#include <memory>
19
20#include "arch/instruction_set.h"
21#include "arch/instruction_set_features.h"
22#include "cfi_test.h"
23#include "dex/compiler_ir.h"
24#include "dex/mir_graph.h"
25#include "dex/pass_manager.h"
26#include "dex/quick/dex_file_to_method_inliner_map.h"
27#include "dex/quick/quick_compiler.h"
28#include "dex/quick/mir_to_lir.h"
29#include "dex/verification_results.h"
30#include "driver/compiler_driver.h"
31#include "driver/compiler_options.h"
32#include "gtest/gtest.h"
33
34#include "dex/quick/quick_cfi_test_expected.inc"
35
36namespace art {
37
38// Run the tests only on host.
Andreas Gampec60e1b72015-07-30 08:57:50 -070039#ifndef __ANDROID__
David Srbecky1109fb32015-04-07 20:21:06 +010040
41class QuickCFITest : public CFITest {
42 public:
43 // Enable this flag to generate the expected outputs.
44 static constexpr bool kGenerateExpected = false;
45
46 void TestImpl(InstructionSet isa, const char* isa_str,
47 const std::vector<uint8_t>& expected_asm,
48 const std::vector<uint8_t>& expected_cfi) {
49 // Setup simple compiler context.
50 ArenaPool pool;
51 ArenaAllocator arena(&pool);
52 CompilerOptions compiler_options(
53 CompilerOptions::kDefaultCompilerFilter,
54 CompilerOptions::kDefaultHugeMethodThreshold,
55 CompilerOptions::kDefaultLargeMethodThreshold,
56 CompilerOptions::kDefaultSmallMethodThreshold,
57 CompilerOptions::kDefaultTinyMethodThreshold,
58 CompilerOptions::kDefaultNumDexMethodsThreshold,
Calin Juravle0941b9d2015-07-29 18:59:13 +010059 CompilerOptions::kDefaultInlineDepthLimit,
60 CompilerOptions::kDefaultInlineMaxCodeUnits,
David Srbecky1109fb32015-04-07 20:21:06 +010061 false,
62 CompilerOptions::kDefaultTopKProfileThreshold,
63 false,
David Srbecky8363c772015-05-28 16:12:43 +010064 true, // generate_debug_info.
David Srbecky1109fb32015-04-07 20:21:06 +010065 false,
66 false,
67 false,
68 false,
69 nullptr,
David Srbecky1109fb32015-04-07 20:21:06 +010070 nullptr,
71 false);
72 VerificationResults verification_results(&compiler_options);
73 DexFileToMethodInlinerMap method_inliner_map;
74 std::unique_ptr<const InstructionSetFeatures> isa_features;
75 std::string error;
76 isa_features.reset(InstructionSetFeatures::FromVariant(isa, "default", &error));
77 CompilerDriver driver(&compiler_options, &verification_results, &method_inliner_map,
78 Compiler::kQuick, isa, isa_features.get(),
Calin Juravle87000a92015-08-24 15:34:44 +010079 false, nullptr, nullptr, nullptr, 0, false, false, "", false, 0, -1, "");
David Srbecky1109fb32015-04-07 20:21:06 +010080 ClassLinker* linker = nullptr;
81 CompilationUnit cu(&pool, isa, &driver, linker);
82 DexFile::CodeItem code_item { 0, 0, 0, 0, 0, 0, { 0 } }; // NOLINT
83 cu.mir_graph.reset(new MIRGraph(&cu, &arena));
84 cu.mir_graph->current_code_item_ = &code_item;
85
86 // Generate empty method with some spills.
David Srbecky46325a02015-04-09 22:51:56 +010087 std::unique_ptr<Mir2Lir> m2l(QuickCompiler::GetCodeGenerator(&cu, nullptr));
David Srbecky1109fb32015-04-07 20:21:06 +010088 m2l->frame_size_ = 64u;
89 m2l->CompilerInitializeRegAlloc();
90 for (const auto& info : m2l->reg_pool_->core_regs_) {
91 if (m2l->num_core_spills_ < 2 && !info->IsTemp() && !info->InUse()) {
Dan Albertf9036802015-04-16 11:52:45 -070092 m2l->core_spill_mask_ |= 1 << info->GetReg().GetRegNum();
David Srbecky1109fb32015-04-07 20:21:06 +010093 m2l->num_core_spills_++;
94 }
95 }
96 for (const auto& info : m2l->reg_pool_->sp_regs_) {
97 if (m2l->num_fp_spills_ < 2 && !info->IsTemp() && !info->InUse()) {
Dan Albertf9036802015-04-16 11:52:45 -070098 m2l->fp_spill_mask_ |= 1 << info->GetReg().GetRegNum();
David Srbecky1109fb32015-04-07 20:21:06 +010099 m2l->num_fp_spills_++;
100 }
101 }
102 m2l->AdjustSpillMask();
Mathieu Chartiere401d142015-04-22 13:56:20 -0700103 m2l->GenEntrySequence(nullptr, m2l->GetCompilationUnit()->target64 ?
104 m2l->LocCReturnWide() : m2l->LocCReturnRef());
David Srbecky1109fb32015-04-07 20:21:06 +0100105 m2l->GenExitSequence();
106 m2l->HandleSlowPaths();
107 m2l->AssembleLIR();
108 std::vector<uint8_t> actual_asm(m2l->code_buffer_.begin(), m2l->code_buffer_.end());
109 auto const& cfi_data = m2l->cfi().Patch(actual_asm.size());
110 std::vector<uint8_t> actual_cfi(cfi_data->begin(), cfi_data->end());
111 EXPECT_EQ(m2l->cfi().GetCurrentPC(), static_cast<int>(actual_asm.size()));
112
113 if (kGenerateExpected) {
114 GenerateExpected(stdout, isa, isa_str, actual_asm, actual_cfi);
115 } else {
116 EXPECT_EQ(expected_asm, actual_asm);
117 EXPECT_EQ(expected_cfi, actual_cfi);
118 }
119 }
120};
121
122#define TEST_ISA(isa) \
123 TEST_F(QuickCFITest, isa) { \
124 std::vector<uint8_t> expected_asm(expected_asm_##isa, \
125 expected_asm_##isa + arraysize(expected_asm_##isa)); \
126 std::vector<uint8_t> expected_cfi(expected_cfi_##isa, \
127 expected_cfi_##isa + arraysize(expected_cfi_##isa)); \
128 TestImpl(isa, #isa, expected_asm, expected_cfi); \
129 }
130
131TEST_ISA(kThumb2)
132TEST_ISA(kArm64)
133TEST_ISA(kX86)
134TEST_ISA(kX86_64)
135TEST_ISA(kMips)
136TEST_ISA(kMips64)
137
Andreas Gampec60e1b72015-07-30 08:57:50 -0700138#endif // __ANDROID__
David Srbecky1109fb32015-04-07 20:21:06 +0100139
140} // namespace art