diff options
author | 2020-07-07 01:10:07 +0100 | |
---|---|---|
committer | 2020-07-09 15:58:18 +0000 | |
commit | 194f555db74816aa380d2f46f63c8626f38e9b71 (patch) | |
tree | d81626d2023f2d5a7f77b1ff4718e353ee76bc90 /compiler/utils/assembler_thumb_test.cc | |
parent | d6e14e0b6a3447d6e89a93d0a017e92b11dc5f6f (diff) |
Refactor arm assembly tests.
Another step in preparation to move to the LLVM toolchain.
Bug: 147817558
Test: m test-art-host-gtest
Change-Id: Ie5be337165d8f24e04740de0486144fa6a62f063
Diffstat (limited to 'compiler/utils/assembler_thumb_test.cc')
-rw-r--r-- | compiler/utils/assembler_thumb_test.cc | 189 |
1 files changed, 37 insertions, 152 deletions
diff --git a/compiler/utils/assembler_thumb_test.cc b/compiler/utils/assembler_thumb_test.cc index 4e1518b7cd..72dfef184d 100644 --- a/compiler/utils/assembler_thumb_test.cc +++ b/compiler/utils/assembler_thumb_test.cc @@ -25,6 +25,7 @@ #include "jni/quick/calling_convention.h" #include "utils/arm/jni_macro_assembler_arm_vixl.h" +#include "utils/assembler_test_base.h" #include "base/hex_dump.h" #include "base/malloc_arena_pool.h" @@ -36,170 +37,54 @@ namespace arm { // Include results file (generated manually) #include "assembler_thumb_test_expected.cc.inc" -#ifndef ART_TARGET_ANDROID -// This controls whether the results are printed to the -// screen or compared against the expected output. -// To generate new expected output, set this to true and -// copy the output into the .cc.inc file in the form -// of the other results. -// -// When this is false, the results are not printed to the -// output, but are compared against the expected results -// in the .cc.inc file. -static constexpr bool kPrintResults = false; -#endif - -void SetAndroidData() { - const char* data = getenv("ANDROID_DATA"); - if (data == nullptr) { - setenv("ANDROID_DATA", "/tmp", 1); - } -} +class ArmVIXLAssemblerTest : public AssemblerTestBase { + public: + ArmVIXLAssemblerTest() : pool(), allocator(&pool), assembler(&allocator) { } -int CompareIgnoringSpace(const char* s1, const char* s2) { - while (*s1 != '\0') { - while (isspace(*s1)) ++s1; - while (isspace(*s2)) ++s2; - if (*s1 == '\0' || *s1 != *s2) { - break; - } - ++s1; - ++s2; - } - return *s1 - *s2; -} + protected: + InstructionSet GetIsa() override { return InstructionSet::kThumb2; } -void InitResults() { - if (test_results.empty()) { - setup_results(); - } -} - -std::string GetToolsDir() { + void DumpAndCheck(std::vector<uint8_t>& code, const char* testname, const std::string& expected) { #ifndef ART_TARGET_ANDROID - // This will only work on the host. There is no as, objcopy or objdump on the device. - static std::string toolsdir; - - if (toolsdir.empty()) { - setup_results(); - toolsdir = CommonRuntimeTest::GetAndroidTargetToolsDir(InstructionSet::kThumb2); - SetAndroidData(); + std::string obj_file = scratch_dir_->GetPath() + testname + ".o"; + WriteElf</*IsElf64=*/false>(obj_file, InstructionSet::kThumb2, code); + std::string disassembly; + ASSERT_TRUE(Disassemble(obj_file, &disassembly)); + + std::string expected2 = "\n" + + obj_file + ": file format elf32-littlearm\n\n\n" + "Disassembly of section .text:\n\n" + "00000000 <.text>:\n" + + expected; + EXPECT_EQ(expected2, disassembly); + if (expected2 != disassembly) { + std::string out = " \"" + Replace(disassembly, "\n", "\\n\"\n \"") + "\""; + printf("C++ formatted disassembler output for %s:\n%s\n", testname, out.c_str()); + } +#endif // ART_TARGET_ANDROID } - return toolsdir; -#else - return std::string(); -#endif -} +#define __ assembler. -void DumpAndCheck(std::vector<uint8_t>& code, const char* testname, const char* const* results) { -#ifndef ART_TARGET_ANDROID - static std::string toolsdir = GetToolsDir(); - - ScratchFile file; - - const char* filename = file.GetFilename().c_str(); - - std::ofstream out(filename); - if (out) { - out << ".section \".text\"\n"; - out << ".syntax unified\n"; - out << ".arch armv7-a\n"; - out << ".thumb\n"; - out << ".thumb_func\n"; - out << ".type " << testname << ", #function\n"; - out << ".global " << testname << "\n"; - out << testname << ":\n"; - out << ".fnstart\n"; - - for (uint32_t i = 0 ; i < code.size(); ++i) { - out << ".byte " << (static_cast<int>(code[i]) & 0xff) << "\n"; - } - out << ".fnend\n"; - out << ".size " << testname << ", .-" << testname << "\n"; - } - out.close(); - - char cmd[1024]; - - // Assemble the .S - snprintf(cmd, sizeof(cmd), "%sas %s -o %s.o", toolsdir.c_str(), filename, filename); - int cmd_result = system(cmd); - ASSERT_EQ(cmd_result, 0) << cmd << strerror(errno); - - // Disassemble. - snprintf(cmd, sizeof(cmd), "%sobjdump -D -M force-thumb --section=.text %s.o | grep '^ *[0-9a-f][0-9a-f]*:'", - toolsdir.c_str(), filename); - if (kPrintResults) { - // Print the results only, don't check. This is used to generate new output for inserting - // into the .inc file, so let's add the appropriate prefix/suffix needed in the C++ code. - strcat(cmd, " | sed '-es/^/ \"/' | sed '-es/$/\\\\n\",/'"); - int cmd_result3 = system(cmd); - ASSERT_EQ(cmd_result3, 0) << strerror(errno); - } else { - // Check the results match the appropriate results in the .inc file. - FILE *fp = popen(cmd, "r"); - ASSERT_TRUE(fp != nullptr); - - uint32_t lineindex = 0; - - while (!feof(fp)) { - char testline[256]; - char *s = fgets(testline, sizeof(testline), fp); - if (s == nullptr) { - break; - } - if (CompareIgnoringSpace(results[lineindex], testline) != 0) { - LOG(FATAL) << "Output is not as expected at line: " << lineindex - << results[lineindex] << "/" << testline << ", test name: " << testname; - } - ++lineindex; - } - // Check that we are at the end. - ASSERT_TRUE(results[lineindex] == nullptr); - fclose(fp); + void EmitAndCheck(const char* testname, const char* expected) { + __ FinalizeCode(); + size_t cs = __ CodeSize(); + std::vector<uint8_t> managed_code(cs); + MemoryRegion code(&managed_code[0], managed_code.size()); + __ FinalizeInstructions(code); + + DumpAndCheck(managed_code, testname, expected); } - char buf[FILENAME_MAX]; - snprintf(buf, sizeof(buf), "%s.o", filename); - unlink(buf); -#endif // ART_TARGET_ANDROID -} +#undef __ -class ArmVIXLAssemblerTest : public ::testing::Test { - public: - ArmVIXLAssemblerTest() : pool(), allocator(&pool), assembler(&allocator) { } +#define __ assembler. MallocArenaPool pool; ArenaAllocator allocator; ArmVIXLJNIMacroAssembler assembler; }; -#define __ assembler-> - -void EmitAndCheck(ArmVIXLJNIMacroAssembler* assembler, const char* testname, - const char* const* results) { - __ FinalizeCode(); - size_t cs = __ CodeSize(); - std::vector<uint8_t> managed_code(cs); - MemoryRegion code(&managed_code[0], managed_code.size()); - __ FinalizeInstructions(code); - - DumpAndCheck(managed_code, testname, results); -} - -void EmitAndCheck(ArmVIXLJNIMacroAssembler* assembler, const char* testname) { - InitResults(); - std::map<std::string, const char* const*>::iterator results = test_results.find(testname); - ASSERT_NE(results, test_results.end()); - - EmitAndCheck(assembler, testname, results->second); -} - -#undef __ - -#define __ assembler. - TEST_F(ArmVIXLAssemblerTest, VixlJniHelpers) { // Run the test only with Baker read barriers, as the expected // generated code contains a Marking Register refresh instruction. @@ -296,7 +181,7 @@ TEST_F(ArmVIXLAssemblerTest, VixlJniHelpers) { __ DecreaseFrameSize(32); __ RemoveFrame(frame_size, callee_save_regs, /* may_suspend= */ true); - EmitAndCheck(&assembler, "VixlJniHelpers"); + EmitAndCheck("VixlJniHelpers", VixlJniHelpersResults); } #undef __ @@ -339,7 +224,7 @@ TEST_F(ArmVIXLAssemblerTest, VixlLoadFromOffset) { __ LoadFromOffset(kLoadUnsignedByte, R2, R4, 12); __ LoadFromOffset(kLoadSignedHalfword, R2, R4, 12); - EmitAndCheck(&assembler, "VixlLoadFromOffset"); + EmitAndCheck("VixlLoadFromOffset", VixlLoadFromOffsetResults); } TEST_F(ArmVIXLAssemblerTest, VixlStoreToOffset) { @@ -370,7 +255,7 @@ TEST_F(ArmVIXLAssemblerTest, VixlStoreToOffset) { __ StoreToOffset(kStoreByte, R2, R4, 12); - EmitAndCheck(&assembler, "VixlStoreToOffset"); + EmitAndCheck("VixlStoreToOffset", VixlStoreToOffsetResults); } #undef __ |