diff options
author | Alexey Frunze <Alexey.Frunze@imgtec.com> | 2016-08-30 21:40:46 -0700 |
---|---|---|
committer | Alexey Frunze <Alexey.Frunze@imgtec.com> | 2016-09-01 16:36:54 -0700 |
commit | 58320ce35715f2814700707a9d35ad5055fff9ce (patch) | |
tree | f691e4d824213ecadb0bf4f858ad63b5a2584467 /compiler/optimizing/codegen_test.cc | |
parent | 370e6e412bb8361fec0f0788c396621bccfb6e2a (diff) |
MIPS32: Ensure preservation of RA in leaf methods if it's clobbered
Test: booted MIPS32 in QEMU
Test: test-art-host-gtest
Test: test-art-target-gtest-codegen_test in QEMU
Test: test-art-target-run-test-optimizing on CI20
Change-Id: Ia3da5902d967cd7af313f03ebf414320b0063619
Diffstat (limited to 'compiler/optimizing/codegen_test.cc')
-rw-r--r-- | compiler/optimizing/codegen_test.cc | 63 |
1 files changed, 63 insertions, 0 deletions
diff --git a/compiler/optimizing/codegen_test.cc b/compiler/optimizing/codegen_test.cc index fe6c0a305e..d00a7867e8 100644 --- a/compiler/optimizing/codegen_test.cc +++ b/compiler/optimizing/codegen_test.cc @@ -991,4 +991,67 @@ TEST_F(CodegenTest, ComparisonsLong) { } } +#ifdef ART_ENABLE_CODEGEN_mips +TEST_F(CodegenTest, MipsClobberRA) { + std::unique_ptr<const MipsInstructionSetFeatures> features_mips( + MipsInstructionSetFeatures::FromCppDefines()); + if (!CanExecute(kMips) || features_mips->IsR6()) { + // HMipsComputeBaseMethodAddress and the NAL instruction behind it + // should only be generated on non-R6. + return; + } + + ArenaPool pool; + ArenaAllocator allocator(&pool); + HGraph* graph = CreateGraph(&allocator); + + HBasicBlock* entry_block = new (&allocator) HBasicBlock(graph); + graph->AddBlock(entry_block); + graph->SetEntryBlock(entry_block); + entry_block->AddInstruction(new (&allocator) HGoto()); + + HBasicBlock* block = new (&allocator) HBasicBlock(graph); + graph->AddBlock(block); + + HBasicBlock* exit_block = new (&allocator) HBasicBlock(graph); + graph->AddBlock(exit_block); + graph->SetExitBlock(exit_block); + exit_block->AddInstruction(new (&allocator) HExit()); + + entry_block->AddSuccessor(block); + block->AddSuccessor(exit_block); + + // To simplify matters, don't create PC-relative HLoadClass or HLoadString. + // Instead, generate HMipsComputeBaseMethodAddress directly. + HMipsComputeBaseMethodAddress* base = new (&allocator) HMipsComputeBaseMethodAddress(); + block->AddInstruction(base); + // HMipsComputeBaseMethodAddress is defined as int, so just make the + // compiled method return it. + block->AddInstruction(new (&allocator) HReturn(base)); + + graph->BuildDominatorTree(); + + mips::CodeGeneratorMIPS codegenMIPS(graph, *features_mips.get(), CompilerOptions()); + // Since there isn't HLoadClass or HLoadString, we need to manually indicate + // that RA is clobbered and the method entry code should generate a stack frame + // and preserve RA in it. And this is what we're testing here. + codegenMIPS.ClobberRA(); + // Without ClobberRA() the code would be: + // nal # Sets RA to point to the jr instruction below + // move v0, ra # and the CPU falls into an infinite loop. + // jr ra + // nop + // The expected code is: + // addiu sp, sp, -16 + // sw ra, 12(sp) + // sw a0, 0(sp) + // nal # Sets RA to point to the lw instruction below. + // move v0, ra + // lw ra, 12(sp) + // jr ra + // addiu sp, sp, 16 + RunCode(&codegenMIPS, graph, [](HGraph*) {}, false, 0); +} +#endif + } // namespace art |