1 /*
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 "dex_instruction-inl.h"
18 #include "dex_instruction_iterator.h"
19 #include "gtest/gtest.h"
20
21 namespace art {
22
TEST(StaticGetters,PropertiesOfNopTest)23 TEST(StaticGetters, PropertiesOfNopTest) {
24 Instruction::Code nop = Instruction::NOP;
25 EXPECT_STREQ("nop", Instruction::Name(nop));
26 EXPECT_EQ(Instruction::k10x, Instruction::FormatOf(nop));
27 EXPECT_EQ(Instruction::kIndexNone, Instruction::IndexTypeOf(nop));
28 EXPECT_EQ(Instruction::kContinue, Instruction::FlagsOf(nop));
29 EXPECT_EQ(Instruction::kVerifyNothing, Instruction::VerifyFlagsOf(nop));
30 }
31
Build45cc(uint8_t num_args,uint16_t method_idx,uint16_t proto_idx,uint16_t arg_regs,uint16_t * out)32 static void Build45cc(uint8_t num_args, uint16_t method_idx, uint16_t proto_idx,
33 uint16_t arg_regs, uint16_t* out) {
34 // A = num argument registers
35 // B = method_idx
36 // C - G = argument registers
37 // H = proto_idx
38 //
39 // op = 0xFA
40 //
41 // format:
42 // AG op BBBB FEDC HHHH
43 out[0] = 0;
44 out[0] |= (num_args << 12);
45 out[0] |= 0x00FA;
46
47 out[1] = method_idx;
48 out[2] = arg_regs;
49 out[3] = proto_idx;
50 }
51
Build4rcc(uint16_t num_args,uint16_t method_idx,uint16_t proto_idx,uint16_t arg_regs_start,uint16_t * out)52 static void Build4rcc(uint16_t num_args, uint16_t method_idx, uint16_t proto_idx,
53 uint16_t arg_regs_start, uint16_t* out) {
54 // A = num argument registers
55 // B = method_idx
56 // C = first argument register
57 // H = proto_idx
58 //
59 // op = 0xFB
60 //
61 // format:
62 // AA op BBBB CCCC HHHH
63 out[0] = 0;
64 out[0] |= (num_args << 8);
65 out[0] |= 0x00FB;
66
67 out[1] = method_idx;
68 out[2] = arg_regs_start;
69 out[3] = proto_idx;
70 }
71
TEST(Instruction,PropertiesOf45cc)72 TEST(Instruction, PropertiesOf45cc) {
73 uint16_t instruction[4];
74 Build45cc(/* num_args= */ 4u,
75 /* method_idx= */ 16u,
76 /* proto_idx= */ 32u,
77 /* arg_regs= */ 0xcafe,
78 instruction);
79
80 DexInstructionIterator ins(instruction, /*dex_pc=*/ 0u);
81 ASSERT_EQ(4u, ins->SizeInCodeUnits());
82
83 ASSERT_TRUE(ins->HasVRegA());
84 ASSERT_EQ(4, ins->VRegA());
85 ASSERT_EQ(4u, ins->VRegA_45cc());
86 ASSERT_EQ(4u, ins->VRegA_45cc(instruction[0]));
87
88 ASSERT_TRUE(ins->HasVRegB());
89 ASSERT_EQ(16, ins->VRegB());
90 ASSERT_EQ(16u, ins->VRegB_45cc());
91
92 ASSERT_TRUE(ins->HasVRegC());
93 ASSERT_EQ(0xe, ins->VRegC());
94 ASSERT_EQ(0xe, ins->VRegC_45cc());
95
96 ASSERT_TRUE(ins->HasVRegH());
97 ASSERT_EQ(32, ins->VRegH());
98 ASSERT_EQ(32, ins->VRegH_45cc());
99
100 ASSERT_TRUE(ins->HasVarArgs());
101
102 uint32_t arg_regs[Instruction::kMaxVarArgRegs];
103 ins->GetVarArgs(arg_regs);
104 ASSERT_EQ(0xeu, arg_regs[0]);
105 ASSERT_EQ(0xfu, arg_regs[1]);
106 ASSERT_EQ(0xau, arg_regs[2]);
107 ASSERT_EQ(0xcu, arg_regs[3]);
108 }
109
TEST(Instruction,PropertiesOf4rcc)110 TEST(Instruction, PropertiesOf4rcc) {
111 uint16_t instruction[4];
112 Build4rcc(/* num_args= */ 4u,
113 /* method_idx= */ 16u,
114 /* proto_idx= */ 32u,
115 /* arg_regs_start= */ 0xcafe,
116 instruction);
117
118 DexInstructionIterator ins(instruction, /*dex_pc=*/ 0u);
119 ASSERT_EQ(4u, ins->SizeInCodeUnits());
120
121 ASSERT_TRUE(ins->HasVRegA());
122 ASSERT_EQ(4, ins->VRegA());
123 ASSERT_EQ(4u, ins->VRegA_4rcc());
124 ASSERT_EQ(4u, ins->VRegA_4rcc(instruction[0]));
125
126 ASSERT_TRUE(ins->HasVRegB());
127 ASSERT_EQ(16, ins->VRegB());
128 ASSERT_EQ(16u, ins->VRegB_4rcc());
129
130 ASSERT_TRUE(ins->HasVRegC());
131 ASSERT_EQ(0xcafe, ins->VRegC());
132 ASSERT_EQ(0xcafe, ins->VRegC_4rcc());
133
134 ASSERT_TRUE(ins->HasVRegH());
135 ASSERT_EQ(32, ins->VRegH());
136 ASSERT_EQ(32, ins->VRegH_4rcc());
137
138 ASSERT_FALSE(ins->HasVarArgs());
139 }
140
Build35c(uint16_t * out,Instruction::Code code,uint16_t method_idx,const std::vector<uint16_t> & args)141 static void Build35c(uint16_t* out,
142 Instruction::Code code,
143 uint16_t method_idx,
144 const std::vector<uint16_t>& args) {
145 out[0] = 0;
146 out[0] |= (args.size() << 12);
147 out[0] |= static_cast<uint16_t>(code);
148 out[1] = method_idx;
149 size_t i = 0;
150 out[2] = 0;
151 for (; i < 4 && i < args.size(); ++i) {
152 out[2] |= args[i] << (i * 4);
153 }
154 if (args.size() == 5) {
155 out[0] |= args[4] << 8;
156 }
157 }
158
DumpInst35c(Instruction::Code code,uint16_t method_idx,const std::vector<uint16_t> & args)159 static std::string DumpInst35c(Instruction::Code code,
160 uint16_t method_idx,
161 const std::vector<uint16_t>& args) {
162 uint16_t inst[6] = {};
163 Build35c(inst, code, method_idx, args);
164 return Instruction::At(inst)->DumpString(nullptr);
165 }
166
TEST(Instruction,DumpString)167 TEST(Instruction, DumpString) {
168 EXPECT_EQ(DumpInst35c(Instruction::FILLED_NEW_ARRAY, 1234, {3, 2}),
169 "filled-new-array {v3, v2}, type@1234");
170 EXPECT_EQ(DumpInst35c(Instruction::INVOKE_VIRTUAL, 1234, {3, 2, 1, 5, 6}),
171 "invoke-virtual {v3, v2, v1, v5, v6}, thing@1234");
172 EXPECT_EQ(DumpInst35c(Instruction::INVOKE_VIRTUAL_QUICK, 1234, {3, 2, 1, 5}),
173 "invoke-virtual-quick {v3, v2, v1, v5}, thing@1234");
174 EXPECT_EQ(DumpInst35c(Instruction::INVOKE_CUSTOM, 1234, {3, 2, 1}),
175 "invoke-custom {v3, v2, v1}, thing@1234");
176 }
177
178 } // namespace art
179