/* * 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 #include #include "arch/instruction_set.h" #include "arch/instruction_set_features.h" #include "cfi_test.h" #include "dex/compiler_ir.h" #include "dex/mir_graph.h" #include "dex/pass_manager.h" #include "dex/quick/dex_file_to_method_inliner_map.h" #include "dex/quick/quick_compiler.h" #include "dex/quick/mir_to_lir.h" #include "dex/verification_results.h" #include "driver/compiler_driver.h" #include "driver/compiler_options.h" #include "gtest/gtest.h" #include "dex/quick/quick_cfi_test_expected.inc" namespace art { // Run the tests only on host. #ifndef HAVE_ANDROID_OS class QuickCFITest : 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& expected_asm, const std::vector& expected_cfi) { // Setup simple compiler context. ArenaPool pool; ArenaAllocator arena(&pool); CompilerOptions compiler_options( CompilerOptions::kDefaultCompilerFilter, CompilerOptions::kDefaultHugeMethodThreshold, CompilerOptions::kDefaultLargeMethodThreshold, CompilerOptions::kDefaultSmallMethodThreshold, CompilerOptions::kDefaultTinyMethodThreshold, CompilerOptions::kDefaultNumDexMethodsThreshold, CompilerOptions::kDefaultInlineDepthLimit, CompilerOptions::kDefaultInlineMaxCodeUnits, false, CompilerOptions::kDefaultTopKProfileThreshold, false, true, // generate_debug_info. false, false, false, false, nullptr, new PassManagerOptions(), nullptr, false); VerificationResults verification_results(&compiler_options); DexFileToMethodInlinerMap method_inliner_map; std::unique_ptr isa_features; std::string error; isa_features.reset(InstructionSetFeatures::FromVariant(isa, "default", &error)); CompilerDriver driver(&compiler_options, &verification_results, &method_inliner_map, Compiler::kQuick, isa, isa_features.get(), false, nullptr, nullptr, nullptr, 0, false, false, "", 0, -1, ""); ClassLinker* linker = nullptr; CompilationUnit cu(&pool, isa, &driver, linker); DexFile::CodeItem code_item { 0, 0, 0, 0, 0, 0, { 0 } }; // NOLINT cu.mir_graph.reset(new MIRGraph(&cu, &arena)); cu.mir_graph->current_code_item_ = &code_item; // Generate empty method with some spills. std::unique_ptr m2l(QuickCompiler::GetCodeGenerator(&cu, nullptr)); m2l->frame_size_ = 64u; m2l->CompilerInitializeRegAlloc(); for (const auto& info : m2l->reg_pool_->core_regs_) { if (m2l->num_core_spills_ < 2 && !info->IsTemp() && !info->InUse()) { m2l->core_spill_mask_ |= 1 << info->GetReg().GetRegNum(); m2l->num_core_spills_++; } } for (const auto& info : m2l->reg_pool_->sp_regs_) { if (m2l->num_fp_spills_ < 2 && !info->IsTemp() && !info->InUse()) { m2l->fp_spill_mask_ |= 1 << info->GetReg().GetRegNum(); m2l->num_fp_spills_++; } } m2l->AdjustSpillMask(); m2l->GenEntrySequence(nullptr, m2l->GetCompilationUnit()->target64 ? m2l->LocCReturnWide() : m2l->LocCReturnRef()); m2l->GenExitSequence(); m2l->HandleSlowPaths(); m2l->AssembleLIR(); std::vector actual_asm(m2l->code_buffer_.begin(), m2l->code_buffer_.end()); auto const& cfi_data = m2l->cfi().Patch(actual_asm.size()); std::vector actual_cfi(cfi_data->begin(), cfi_data->end()); EXPECT_EQ(m2l->cfi().GetCurrentPC(), static_cast(actual_asm.size())); if (kGenerateExpected) { GenerateExpected(stdout, isa, isa_str, actual_asm, actual_cfi); } else { EXPECT_EQ(expected_asm, actual_asm); EXPECT_EQ(expected_cfi, actual_cfi); } } }; #define TEST_ISA(isa) \ TEST_F(QuickCFITest, isa) { \ std::vector expected_asm(expected_asm_##isa, \ expected_asm_##isa + arraysize(expected_asm_##isa)); \ std::vector 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) TEST_ISA(kMips) TEST_ISA(kMips64) #endif // HAVE_ANDROID_OS } // namespace art