| /* | 
 |  * Copyright (C) 2014 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 "base/stringprintf.h" | 
 | #include "builder.h" | 
 | #include "dex_file.h" | 
 | #include "dex_instruction.h" | 
 | #include "nodes.h" | 
 | #include "optimizing_unit_test.h" | 
 | #include "pretty_printer.h" | 
 | #include "utils/arena_allocator.h" | 
 |  | 
 | #include "gtest/gtest.h" | 
 |  | 
 | namespace art { | 
 |  | 
 | static void TestCode(const uint16_t* data, const char* expected) { | 
 |   ArenaPool pool; | 
 |   ArenaAllocator allocator(&pool); | 
 |   HGraphBuilder builder(&allocator); | 
 |   const DexFile::CodeItem* item = reinterpret_cast<const DexFile::CodeItem*>(data); | 
 |   HGraph* graph = builder.BuildGraph(*item); | 
 |   ASSERT_NE(graph, nullptr); | 
 |   StringPrettyPrinter printer(graph); | 
 |   printer.VisitInsertionOrder(); | 
 |   ASSERT_STREQ(expected, printer.str().c_str()); | 
 | } | 
 |  | 
 | TEST(PrettyPrinterTest, ReturnVoid) { | 
 |   const uint16_t data[] = ZERO_REGISTER_CODE_ITEM( | 
 |       Instruction::RETURN_VOID); | 
 |  | 
 |   const char* expected = | 
 |       "BasicBlock 0, succ: 1\n" | 
 |       "  2: SuspendCheck\n" | 
 |       "  3: Goto 1\n" | 
 |       "BasicBlock 1, pred: 0, succ: 2\n" | 
 |       "  0: ReturnVoid\n" | 
 |       "BasicBlock 2, pred: 1\n" | 
 |       "  1: Exit\n"; | 
 |  | 
 |   TestCode(data, expected); | 
 | } | 
 |  | 
 | TEST(PrettyPrinterTest, CFG1) { | 
 |   const char* expected = | 
 |     "BasicBlock 0, succ: 1\n" | 
 |     "  3: SuspendCheck\n" | 
 |     "  4: Goto 1\n" | 
 |     "BasicBlock 1, pred: 0, succ: 2\n" | 
 |     "  0: Goto 2\n" | 
 |     "BasicBlock 2, pred: 1, succ: 3\n" | 
 |     "  1: ReturnVoid\n" | 
 |     "BasicBlock 3, pred: 2\n" | 
 |     "  2: Exit\n"; | 
 |  | 
 |   const uint16_t data[] = | 
 |     ZERO_REGISTER_CODE_ITEM( | 
 |       Instruction::GOTO | 0x100, | 
 |       Instruction::RETURN_VOID); | 
 |  | 
 |   TestCode(data, expected); | 
 | } | 
 |  | 
 | TEST(PrettyPrinterTest, CFG2) { | 
 |   const char* expected = | 
 |     "BasicBlock 0, succ: 1\n" | 
 |     "  4: SuspendCheck\n" | 
 |     "  5: Goto 1\n" | 
 |     "BasicBlock 1, pred: 0, succ: 2\n" | 
 |     "  0: Goto 2\n" | 
 |     "BasicBlock 2, pred: 1, succ: 3\n" | 
 |     "  1: Goto 3\n" | 
 |     "BasicBlock 3, pred: 2, succ: 4\n" | 
 |     "  2: ReturnVoid\n" | 
 |     "BasicBlock 4, pred: 3\n" | 
 |     "  3: Exit\n"; | 
 |  | 
 |   const uint16_t data[] = ZERO_REGISTER_CODE_ITEM( | 
 |     Instruction::GOTO | 0x100, | 
 |     Instruction::GOTO | 0x100, | 
 |     Instruction::RETURN_VOID); | 
 |  | 
 |   TestCode(data, expected); | 
 | } | 
 |  | 
 | TEST(PrettyPrinterTest, CFG3) { | 
 |   const char* expected = | 
 |     "BasicBlock 0, succ: 1\n" | 
 |     "  5: SuspendCheck\n" | 
 |     "  6: Goto 1\n" | 
 |     "BasicBlock 1, pred: 0, succ: 3\n" | 
 |     "  0: Goto 3\n" | 
 |     "BasicBlock 2, pred: 3, succ: 4\n" | 
 |     "  1: ReturnVoid\n" | 
 |     "BasicBlock 3, pred: 1, succ: 2\n" | 
 |     "  2: SuspendCheck\n" | 
 |     "  3: Goto 2\n" | 
 |     "BasicBlock 4, pred: 2\n" | 
 |     "  4: Exit\n"; | 
 |  | 
 |   const uint16_t data1[] = ZERO_REGISTER_CODE_ITEM( | 
 |     Instruction::GOTO | 0x200, | 
 |     Instruction::RETURN_VOID, | 
 |     Instruction::GOTO | 0xFF00); | 
 |  | 
 |   TestCode(data1, expected); | 
 |  | 
 |   const uint16_t data2[] = ZERO_REGISTER_CODE_ITEM( | 
 |     Instruction::GOTO_16, 3, | 
 |     Instruction::RETURN_VOID, | 
 |     Instruction::GOTO_16, 0xFFFF); | 
 |  | 
 |   TestCode(data2, expected); | 
 |  | 
 |   const uint16_t data3[] = ZERO_REGISTER_CODE_ITEM( | 
 |     Instruction::GOTO_32, 4, 0, | 
 |     Instruction::RETURN_VOID, | 
 |     Instruction::GOTO_32, 0xFFFF, 0xFFFF); | 
 |  | 
 |   TestCode(data3, expected); | 
 | } | 
 |  | 
 | TEST(PrettyPrinterTest, CFG4) { | 
 |   const char* expected = | 
 |     "BasicBlock 0, succ: 1\n" | 
 |     "  3: SuspendCheck\n" | 
 |     "  4: Goto 1\n" | 
 |     "BasicBlock 1, pred: 0, 1, succ: 1\n" | 
 |     "  0: SuspendCheck\n" | 
 |     "  1: Goto 1\n" | 
 |     "BasicBlock 2\n" | 
 |     "  2: Exit\n"; | 
 |  | 
 |   const uint16_t data1[] = ZERO_REGISTER_CODE_ITEM( | 
 |     Instruction::NOP, | 
 |     Instruction::GOTO | 0xFF00); | 
 |  | 
 |   TestCode(data1, expected); | 
 |  | 
 |   const uint16_t data2[] = ZERO_REGISTER_CODE_ITEM( | 
 |     Instruction::GOTO_32, 0, 0); | 
 |  | 
 |   TestCode(data2, expected); | 
 | } | 
 |  | 
 | TEST(PrettyPrinterTest, CFG5) { | 
 |   const char* expected = | 
 |     "BasicBlock 0, succ: 1\n" | 
 |     "  4: SuspendCheck\n" | 
 |     "  5: Goto 1\n" | 
 |     "BasicBlock 1, pred: 0, 2, succ: 3\n" | 
 |     "  0: ReturnVoid\n" | 
 |     "BasicBlock 2, succ: 1\n" | 
 |     "  1: SuspendCheck\n" | 
 |     "  2: Goto 1\n" | 
 |     "BasicBlock 3, pred: 1\n" | 
 |     "  3: Exit\n"; | 
 |  | 
 |   const uint16_t data[] = ZERO_REGISTER_CODE_ITEM( | 
 |     Instruction::RETURN_VOID, | 
 |     Instruction::GOTO | 0x100, | 
 |     Instruction::GOTO | 0xFE00); | 
 |  | 
 |   TestCode(data, expected); | 
 | } | 
 |  | 
 | TEST(PrettyPrinterTest, CFG6) { | 
 |   const char* expected = | 
 |     "BasicBlock 0, succ: 1\n" | 
 |     "  0: Local [4, 3, 2]\n" | 
 |     "  1: IntConstant [2]\n" | 
 |     "  10: SuspendCheck\n" | 
 |     "  11: Goto 1\n" | 
 |     "BasicBlock 1, pred: 0, succ: 3, 2\n" | 
 |     "  2: StoreLocal(0, 1)\n" | 
 |     "  3: LoadLocal(0) [5]\n" | 
 |     "  4: LoadLocal(0) [5]\n" | 
 |     "  5: Equal(3, 4) [6]\n" | 
 |     "  6: If(5)\n" | 
 |     "BasicBlock 2, pred: 1, succ: 3\n" | 
 |     "  7: Goto 3\n" | 
 |     "BasicBlock 3, pred: 1, 2, succ: 4\n" | 
 |     "  8: ReturnVoid\n" | 
 |     "BasicBlock 4, pred: 3\n" | 
 |     "  9: Exit\n"; | 
 |  | 
 |   const uint16_t data[] = ONE_REGISTER_CODE_ITEM( | 
 |     Instruction::CONST_4 | 0 | 0, | 
 |     Instruction::IF_EQ, 3, | 
 |     Instruction::GOTO | 0x100, | 
 |     Instruction::RETURN_VOID); | 
 |  | 
 |   TestCode(data, expected); | 
 | } | 
 |  | 
 | TEST(PrettyPrinterTest, CFG7) { | 
 |   const char* expected = | 
 |     "BasicBlock 0, succ: 1\n" | 
 |     "  0: Local [4, 3, 2]\n" | 
 |     "  1: IntConstant [2]\n" | 
 |     "  11: SuspendCheck\n" | 
 |     "  12: Goto 1\n" | 
 |     "BasicBlock 1, pred: 0, succ: 3, 2\n" | 
 |     "  2: StoreLocal(0, 1)\n" | 
 |     "  3: LoadLocal(0) [5]\n" | 
 |     "  4: LoadLocal(0) [5]\n" | 
 |     "  5: Equal(3, 4) [6]\n" | 
 |     "  6: If(5)\n" | 
 |     "BasicBlock 2, pred: 1, 3, succ: 3\n" | 
 |     "  7: Goto 3\n" | 
 |     "BasicBlock 3, pred: 1, 2, succ: 2\n" | 
 |     "  8: SuspendCheck\n" | 
 |     "  9: Goto 2\n" | 
 |     "BasicBlock 4\n" | 
 |     "  10: Exit\n"; | 
 |  | 
 |   const uint16_t data[] = ONE_REGISTER_CODE_ITEM( | 
 |     Instruction::CONST_4 | 0 | 0, | 
 |     Instruction::IF_EQ, 3, | 
 |     Instruction::GOTO | 0x100, | 
 |     Instruction::GOTO | 0xFF00); | 
 |  | 
 |   TestCode(data, expected); | 
 | } | 
 |  | 
 | TEST(PrettyPrinterTest, IntConstant) { | 
 |   const char* expected = | 
 |     "BasicBlock 0, succ: 1\n" | 
 |     "  0: Local [2]\n" | 
 |     "  1: IntConstant [2]\n" | 
 |     "  5: SuspendCheck\n" | 
 |     "  6: Goto 1\n" | 
 |     "BasicBlock 1, pred: 0, succ: 2\n" | 
 |     "  2: StoreLocal(0, 1)\n" | 
 |     "  3: ReturnVoid\n" | 
 |     "BasicBlock 2, pred: 1\n" | 
 |     "  4: Exit\n"; | 
 |  | 
 |   const uint16_t data[] = ONE_REGISTER_CODE_ITEM( | 
 |     Instruction::CONST_4 | 0 | 0, | 
 |     Instruction::RETURN_VOID); | 
 |  | 
 |   TestCode(data, expected); | 
 | } | 
 | }  // namespace art |