• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2011 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 #ifndef ART_LIBDEXFILE_DEX_DEX_INSTRUCTION_H_
18 #define ART_LIBDEXFILE_DEX_DEX_INSTRUCTION_H_
19 
20 #include <android-base/logging.h>
21 
22 #include "base/globals.h"
23 #include "base/macros.h"
24 #include "dex_instruction_list.h"
25 
26 using uint4_t = uint8_t;
27 using int4_t = int8_t;
28 
29 namespace art {
30 
31 class DexFile;
32 
33 // The number of Dalvik opcodes.
34 static constexpr size_t kNumPackedOpcodes = 0x100;
35 
36 class Instruction {
37  public:
38   // NOP-encoded switch-statement signatures.
39   enum Signatures {
40     kPackedSwitchSignature = 0x0100,
41     kSparseSwitchSignature = 0x0200,
42     kArrayDataSignature = 0x0300,
43   };
44 
45   struct PACKED(4) PackedSwitchPayload {
46     const uint16_t ident;
47     const uint16_t case_count;
48     const int32_t first_key;
49     const int32_t targets[];
50 
51    private:
52     DISALLOW_COPY_AND_ASSIGN(PackedSwitchPayload);
53   };
54 
55   struct PACKED(4) SparseSwitchPayload {
56     const uint16_t ident;
57     const uint16_t case_count;
58     const int32_t keys_and_targets[];
59 
60    public:
GetKeysSparseSwitchPayload61     const int32_t* GetKeys() const {
62       return keys_and_targets;
63     }
64 
GetTargetsSparseSwitchPayload65     const int32_t* GetTargets() const {
66       return keys_and_targets + case_count;
67     }
68 
69    private:
70     DISALLOW_COPY_AND_ASSIGN(SparseSwitchPayload);
71   };
72 
73   struct PACKED(4) ArrayDataPayload {
74     const uint16_t ident;
75     const uint16_t element_width;
76     const uint32_t element_count;
77     const uint8_t data[];
78 
79    private:
80     DISALLOW_COPY_AND_ASSIGN(ArrayDataPayload);
81   };
82 
83   enum Code {  // private marker to avoid generate-operator-out.py from processing.
84 #define INSTRUCTION_ENUM(opcode, cname, p, f, i, a, e, v) cname = (opcode),
85     DEX_INSTRUCTION_LIST(INSTRUCTION_ENUM)
86 #undef INSTRUCTION_ENUM
87     RSUB_INT_LIT16 = RSUB_INT,
88   };
89 
90   enum Format : uint8_t {
91     k10x,  // op
92     k12x,  // op vA, vB
93     k11n,  // op vA, #+B
94     k11x,  // op vAA
95     k10t,  // op +AA
96     k20t,  // op +AAAA
97     k22x,  // op vAA, vBBBB
98     k21t,  // op vAA, +BBBB
99     k21s,  // op vAA, #+BBBB
100     k21h,  // op vAA, #+BBBB00000[00000000]
101     k21c,  // op vAA, thing@BBBB
102     k23x,  // op vAA, vBB, vCC
103     k22b,  // op vAA, vBB, #+CC
104     k22t,  // op vA, vB, +CCCC
105     k22s,  // op vA, vB, #+CCCC
106     k22c,  // op vA, vB, thing@CCCC
107     k32x,  // op vAAAA, vBBBB
108     k30t,  // op +AAAAAAAA
109     k31t,  // op vAA, +BBBBBBBB
110     k31i,  // op vAA, #+BBBBBBBB
111     k31c,  // op vAA, thing@BBBBBBBB
112     k35c,  // op {vC, vD, vE, vF, vG}, thing@BBBB (B: count, A: vG)
113     k3rc,  // op {vCCCC .. v(CCCC+AA-1)}, meth@BBBB
114 
115     // op {vC, vD, vE, vF, vG}, meth@BBBB, proto@HHHH (A: count)
116     // format: AG op BBBB FEDC HHHH
117     k45cc,
118 
119     // op {VCCCC .. v(CCCC+AA-1)}, meth@BBBB, proto@HHHH (AA: count)
120     // format: AA op BBBB CCCC HHHH
121     k4rcc,  // op {VCCCC .. v(CCCC+AA-1)}, meth@BBBB, proto@HHHH (AA: count)
122 
123     k51l,  // op vAA, #+BBBBBBBBBBBBBBBB
124     kInvalidFormat,
125   };
126 
127   enum IndexType : uint8_t {
128     kIndexUnknown = 0,
129     kIndexNone,               // has no index
130     kIndexTypeRef,            // type reference index
131     kIndexStringRef,          // string reference index
132     kIndexMethodRef,          // method reference index
133     kIndexFieldRef,           // field reference index
134     kIndexMethodAndProtoRef,  // method and a proto reference index (for invoke-polymorphic)
135     kIndexCallSiteRef,        // call site reference index
136     kIndexMethodHandleRef,    // constant method handle reference index
137     kIndexProtoRef,           // prototype reference index
138   };
139 
140   enum Flags : uint8_t {  // private marker to avoid generate-operator-out.py from processing.
141     kBranch              = 0x01,  // conditional or unconditional branch
142     kContinue            = 0x02,  // flow can continue to next statement
143     kSwitch              = 0x04,  // switch statement
144     kThrow               = 0x08,  // could cause an exception to be thrown
145     kReturn              = 0x10,  // returns, no additional statements
146     kInvoke              = 0x20,  // a flavor of invoke
147     kUnconditional       = 0x40,  // unconditional branch
148     kExperimental        = 0x80,  // is an experimental opcode
149   };
150 
151   // Old flags. Keeping them around in case we might need them again some day.
152   enum ExtendedFlags : uint32_t {
153     kAdd                 = 0x0000080,  // addition
154     kSubtract            = 0x0000100,  // subtract
155     kMultiply            = 0x0000200,  // multiply
156     kDivide              = 0x0000400,  // division
157     kRemainder           = 0x0000800,  // remainder
158     kAnd                 = 0x0001000,  // and
159     kOr                  = 0x0002000,  // or
160     kXor                 = 0x0004000,  // xor
161     kShl                 = 0x0008000,  // shl
162     kShr                 = 0x0010000,  // shr
163     kUshr                = 0x0020000,  // ushr
164     kCast                = 0x0040000,  // cast
165     kStore               = 0x0080000,  // store opcode
166     kLoad                = 0x0100000,  // load opcode
167     kClobber             = 0x0200000,  // clobbers memory in a big way (not just a write)
168     kRegCFieldOrConstant = 0x0400000,  // is the third virtual register a field or literal constant (vC)
169     kRegBFieldOrConstant = 0x0800000,  // is the second virtual register a field or literal constant (vB)
170   };
171 
172   enum VerifyFlag : uint32_t {  // private marker to avoid generate-operator-out.py from processing.
173     kVerifyNothing            = 0x0000000,
174     kVerifyRegA               = 0x0000001,
175     kVerifyRegAWide           = 0x0000002,
176     kVerifyRegB               = 0x0000004,
177     kVerifyRegBField          = 0x0000008,
178     kVerifyRegBMethod         = 0x0000010,
179     kVerifyRegBNewInstance    = 0x0000020,
180     kVerifyRegBString         = 0x0000040,
181     kVerifyRegBType           = 0x0000080,
182     kVerifyRegBWide           = 0x0000100,
183     kVerifyRegC               = 0x0000200,
184     kVerifyRegCField          = 0x0000400,
185     kVerifyRegCNewArray       = 0x0000800,
186     kVerifyRegCType           = 0x0001000,
187     kVerifyRegCWide           = 0x0002000,
188     kVerifyArrayData          = 0x0004000,
189     kVerifyBranchTarget       = 0x0008000,
190     kVerifySwitchTargets      = 0x0010000,
191     kVerifyVarArg             = 0x0020000,
192     kVerifyVarArgNonZero      = 0x0040000,
193     kVerifyVarArgRange        = 0x0080000,
194     kVerifyVarArgRangeNonZero = 0x0100000,
195     kVerifyError              = 0x0200000,
196     kVerifyRegHPrototype      = 0x0400000,
197     kVerifyRegBCallSite       = 0x0800000,
198     kVerifyRegBMethodHandle   = 0x1000000,
199     kVerifyRegBPrototype      = 0x2000000,
200     kVerifyRegBFilledNewArray = 0x4000000,
201   };
202 
203   // Collect the enums in a struct for better locality.
204   struct InstructionDescriptor {
205     uint32_t verify_flags;         // Set of VerifyFlag.
206     Format format;
207     IndexType index_type;
208     uint8_t flags;                 // Set of Flags.
209     int8_t size_in_code_units;
210   };
211 
212   static constexpr uint32_t kMaxVarArgRegs = 5;
213 
214   static constexpr bool kHaveExperimentalInstructions = false;
215 
216   // Returns the size (in 2 byte code units) of this instruction.
SizeInCodeUnits()217   size_t SizeInCodeUnits() const {
218     int8_t result = InstructionDescriptorOf(Opcode()).size_in_code_units;
219     if (UNLIKELY(result < 0)) {
220       return SizeInCodeUnitsComplexOpcode();
221     } else {
222       return static_cast<size_t>(result);
223     }
224   }
225 
226   // Returns the size (in 2 byte code units) of the given instruction format.
227   ALWAYS_INLINE static constexpr size_t SizeInCodeUnits(Format format);
228 
229   // Reads an instruction out of the stream at the specified address.
At(const uint16_t * code)230   static const Instruction* At(const uint16_t* code) {
231     DCHECK(code != nullptr);
232     return reinterpret_cast<const Instruction*>(code);
233   }
234 
235   // Reads an instruction out of the stream from the current address plus an offset.
RelativeAt(int32_t offset)236   const Instruction* RelativeAt(int32_t offset) const WARN_UNUSED {
237     return At(reinterpret_cast<const uint16_t*>(this) + offset);
238   }
239 
240   // Returns a pointer to the next instruction in the stream.
Next()241   const Instruction* Next() const {
242     return RelativeAt(SizeInCodeUnits());
243   }
244 
245   // Returns a pointer to the instruction after this 1xx instruction in the stream.
Next_1xx()246   const Instruction* Next_1xx() const {
247     DCHECK(FormatOf(Opcode()) >= k10x && FormatOf(Opcode()) <= k10t);
248     return RelativeAt(1);
249   }
250 
251   // Returns a pointer to the instruction after this 2xx instruction in the stream.
Next_2xx()252   const Instruction* Next_2xx() const {
253     DCHECK(FormatOf(Opcode()) >= k20t && FormatOf(Opcode()) <= k22c);
254     return RelativeAt(2);
255   }
256 
257   // Returns a pointer to the instruction after this 3xx instruction in the stream.
Next_3xx()258   const Instruction* Next_3xx() const {
259     DCHECK(FormatOf(Opcode()) >= k32x && FormatOf(Opcode()) <= k3rc);
260     return RelativeAt(3);
261   }
262 
263   // Returns a pointer to the instruction after this 4xx instruction in the stream.
Next_4xx()264   const Instruction* Next_4xx() const {
265     DCHECK(FormatOf(Opcode()) >= k45cc && FormatOf(Opcode()) <= k4rcc);
266     return RelativeAt(4);
267   }
268 
269   // Returns a pointer to the instruction after this 51l instruction in the stream.
Next_51l()270   const Instruction* Next_51l() const {
271     DCHECK(FormatOf(Opcode()) == k51l);
272     return RelativeAt(5);
273   }
274 
275   // Returns the name of this instruction's opcode.
Name()276   const char* Name() const {
277     return Instruction::Name(Opcode());
278   }
279 
280   // Returns the name of the given opcode.
Name(Code opcode)281   static const char* Name(Code opcode) {
282     return kInstructionNames[opcode];
283   }
284 
285   // VRegA
286   bool HasVRegA() const;
287   ALWAYS_INLINE int32_t VRegA() const;
288   ALWAYS_INLINE int32_t VRegA(Format format, uint16_t inst_data) const;
289 
VRegA_10t()290   int8_t VRegA_10t() const {
291     return VRegA_10t(Fetch16(0));
292   }
VRegA_10x()293   uint8_t VRegA_10x() const {
294     return VRegA_10x(Fetch16(0));
295   }
VRegA_11n()296   uint4_t VRegA_11n() const {
297     return VRegA_11n(Fetch16(0));
298   }
VRegA_11x()299   uint8_t VRegA_11x() const {
300     return VRegA_11x(Fetch16(0));
301   }
VRegA_12x()302   uint4_t VRegA_12x() const {
303     return VRegA_12x(Fetch16(0));
304   }
305   int16_t VRegA_20t() const;
VRegA_21c()306   uint8_t VRegA_21c() const {
307     return VRegA_21c(Fetch16(0));
308   }
VRegA_21h()309   uint8_t VRegA_21h() const {
310     return VRegA_21h(Fetch16(0));
311   }
VRegA_21s()312   uint8_t VRegA_21s() const {
313     return VRegA_21s(Fetch16(0));
314   }
VRegA_21t()315   uint8_t VRegA_21t() const {
316     return VRegA_21t(Fetch16(0));
317   }
VRegA_22b()318   uint8_t VRegA_22b() const {
319     return VRegA_22b(Fetch16(0));
320   }
VRegA_22c()321   uint4_t VRegA_22c() const {
322     return VRegA_22c(Fetch16(0));
323   }
VRegA_22s()324   uint4_t VRegA_22s() const {
325     return VRegA_22s(Fetch16(0));
326   }
VRegA_22t()327   uint4_t VRegA_22t() const {
328     return VRegA_22t(Fetch16(0));
329   }
VRegA_22x()330   uint8_t VRegA_22x() const {
331     return VRegA_22x(Fetch16(0));
332   }
VRegA_23x()333   uint8_t VRegA_23x() const {
334     return VRegA_23x(Fetch16(0));
335   }
336   int32_t VRegA_30t() const;
VRegA_31c()337   uint8_t VRegA_31c() const {
338     return VRegA_31c(Fetch16(0));
339   }
VRegA_31i()340   uint8_t VRegA_31i() const {
341     return VRegA_31i(Fetch16(0));
342   }
VRegA_31t()343   uint8_t VRegA_31t() const {
344     return VRegA_31t(Fetch16(0));
345   }
346   uint16_t VRegA_32x() const;
VRegA_35c()347   uint4_t VRegA_35c() const {
348     return VRegA_35c(Fetch16(0));
349   }
VRegA_3rc()350   uint8_t VRegA_3rc() const {
351     return VRegA_3rc(Fetch16(0));
352   }
VRegA_51l()353   uint8_t VRegA_51l() const {
354     return VRegA_51l(Fetch16(0));
355   }
VRegA_45cc()356   uint4_t VRegA_45cc() const {
357     return VRegA_45cc(Fetch16(0));
358   }
VRegA_4rcc()359   uint8_t VRegA_4rcc() const {
360     return VRegA_4rcc(Fetch16(0));
361   }
362 
363   // The following methods return the vA operand for various instruction formats. The "inst_data"
364   // parameter holds the first 16 bits of instruction which the returned value is decoded from.
365   int8_t VRegA_10t(uint16_t inst_data) const;
366   uint8_t VRegA_10x(uint16_t inst_data) const;
367   uint4_t VRegA_11n(uint16_t inst_data) const;
368   uint8_t VRegA_11x(uint16_t inst_data) const;
369   uint4_t VRegA_12x(uint16_t inst_data) const;
370   uint8_t VRegA_21c(uint16_t inst_data) const;
371   uint8_t VRegA_21h(uint16_t inst_data) const;
372   uint8_t VRegA_21s(uint16_t inst_data) const;
373   uint8_t VRegA_21t(uint16_t inst_data) const;
374   uint8_t VRegA_22b(uint16_t inst_data) const;
375   uint4_t VRegA_22c(uint16_t inst_data) const;
376   uint4_t VRegA_22s(uint16_t inst_data) const;
377   uint4_t VRegA_22t(uint16_t inst_data) const;
378   uint8_t VRegA_22x(uint16_t inst_data) const;
379   uint8_t VRegA_23x(uint16_t inst_data) const;
380   uint8_t VRegA_31c(uint16_t inst_data) const;
381   uint8_t VRegA_31i(uint16_t inst_data) const;
382   uint8_t VRegA_31t(uint16_t inst_data) const;
383   uint4_t VRegA_35c(uint16_t inst_data) const;
384   uint8_t VRegA_3rc(uint16_t inst_data) const;
385   uint8_t VRegA_51l(uint16_t inst_data) const;
386   uint4_t VRegA_45cc(uint16_t inst_data) const;
387   uint8_t VRegA_4rcc(uint16_t inst_data) const;
388 
389   // VRegB
390   bool HasVRegB() const;
391   ALWAYS_INLINE int32_t VRegB() const;
392   ALWAYS_INLINE int32_t VRegB(Format format, uint16_t inst_data) const;
393 
394   bool HasWideVRegB() const;
395   uint64_t WideVRegB() const;
396 
VRegB_11n()397   int4_t VRegB_11n() const {
398     return VRegB_11n(Fetch16(0));
399   }
VRegB_12x()400   uint4_t VRegB_12x() const {
401     return VRegB_12x(Fetch16(0));
402   }
403   uint16_t VRegB_21c() const;
404   uint16_t VRegB_21h() const;
405   int16_t VRegB_21s() const;
406   int16_t VRegB_21t() const;
407   uint8_t VRegB_22b() const;
VRegB_22c()408   uint4_t VRegB_22c() const {
409     return VRegB_22c(Fetch16(0));
410   }
VRegB_22s()411   uint4_t VRegB_22s() const {
412     return VRegB_22s(Fetch16(0));
413   }
VRegB_22t()414   uint4_t VRegB_22t() const {
415     return VRegB_22t(Fetch16(0));
416   }
417   uint16_t VRegB_22x() const;
418   uint8_t VRegB_23x() const;
419   uint32_t VRegB_31c() const;
420   int32_t VRegB_31i() const;
421   int32_t VRegB_31t() const;
422   uint16_t VRegB_32x() const;
423   uint16_t VRegB_35c() const;
424   uint16_t VRegB_3rc() const;
425   uint64_t VRegB_51l() const;  // vB_wide
426   uint16_t VRegB_45cc() const;
427   uint16_t VRegB_4rcc() const;
428 
429   // The following methods return the vB operand for all instruction formats where it is encoded in
430   // the first 16 bits of instruction. The "inst_data" parameter holds these 16 bits. The returned
431   // value is decoded from it.
432   int4_t VRegB_11n(uint16_t inst_data) const;
433   uint4_t VRegB_12x(uint16_t inst_data) const;
434   uint4_t VRegB_22c(uint16_t inst_data) const;
435   uint4_t VRegB_22s(uint16_t inst_data) const;
436   uint4_t VRegB_22t(uint16_t inst_data) const;
437 
438   // VRegC
439   bool HasVRegC() const;
440   ALWAYS_INLINE int32_t VRegC() const;
441   ALWAYS_INLINE int32_t VRegC(Format format) const;
442 
443   int8_t VRegC_22b() const;
444   uint16_t VRegC_22c() const;
445   int16_t VRegC_22s() const;
446   int16_t VRegC_22t() const;
447   uint8_t VRegC_23x() const;
448   uint4_t VRegC_35c() const;
449   uint16_t VRegC_3rc() const;
450   uint4_t VRegC_45cc() const;
451   uint16_t VRegC_4rcc() const;
452 
453 
454   // VRegH
455   bool HasVRegH() const;
456   int32_t VRegH() const;
457   ALWAYS_INLINE int32_t VRegH(Format format) const;
458   uint16_t VRegH_45cc() const;
459   uint16_t VRegH_4rcc() const;
460 
461   // Fills the given array with the 'arg' array of the instruction.
462   bool HasVarArgs() const;
463   uint32_t GetVarArgs(uint32_t args[kMaxVarArgRegs], uint16_t inst_data) const;
GetVarArgs(uint32_t args[kMaxVarArgRegs])464   uint32_t GetVarArgs(uint32_t args[kMaxVarArgRegs]) const {
465     return GetVarArgs(args, Fetch16(0));
466   }
467 
468   // Returns the opcode field of the instruction. The given "inst_data" parameter must be the first
469   // 16 bits of instruction.
Opcode(uint16_t inst_data)470   Code Opcode(uint16_t inst_data) const {
471     DCHECK_EQ(inst_data, Fetch16(0));
472     return static_cast<Code>(inst_data & 0xFF);
473   }
474 
475   // Returns the opcode field of the instruction from the first 16 bits of instruction.
Opcode()476   Code Opcode() const {
477     return Opcode(Fetch16(0));
478   }
479 
SetOpcode(Code opcode)480   void SetOpcode(Code opcode) {
481     DCHECK_LT(static_cast<uint16_t>(opcode), 256u);
482     uint16_t* insns = reinterpret_cast<uint16_t*>(this);
483     insns[0] = (insns[0] & 0xff00) | static_cast<uint16_t>(opcode);
484   }
485 
SetVRegA_10x(uint8_t val)486   void SetVRegA_10x(uint8_t val) {
487     DCHECK(FormatOf(Opcode()) == k10x);
488     uint16_t* insns = reinterpret_cast<uint16_t*>(this);
489     insns[0] = (val << 8) | (insns[0] & 0x00ff);
490   }
491 
SetVRegB_3rc(uint16_t val)492   void SetVRegB_3rc(uint16_t val) {
493     DCHECK(FormatOf(Opcode()) == k3rc);
494     uint16_t* insns = reinterpret_cast<uint16_t*>(this);
495     insns[1] = val;
496   }
497 
SetVRegB_35c(uint16_t val)498   void SetVRegB_35c(uint16_t val) {
499     DCHECK(FormatOf(Opcode()) == k35c);
500     uint16_t* insns = reinterpret_cast<uint16_t*>(this);
501     insns[1] = val;
502   }
503 
SetVRegC_22c(uint16_t val)504   void SetVRegC_22c(uint16_t val) {
505     DCHECK(FormatOf(Opcode()) == k22c);
506     uint16_t* insns = reinterpret_cast<uint16_t*>(this);
507     insns[1] = val;
508   }
509 
SetVRegA_21c(uint8_t val)510   void SetVRegA_21c(uint8_t val) {
511     DCHECK(FormatOf(Opcode()) == k21c);
512     uint16_t* insns = reinterpret_cast<uint16_t*>(this);
513     insns[0] = (val << 8) | (insns[0] & 0x00ff);
514   }
515 
SetVRegB_21c(uint16_t val)516   void SetVRegB_21c(uint16_t val) {
517     DCHECK(FormatOf(Opcode()) == k21c);
518     uint16_t* insns = reinterpret_cast<uint16_t*>(this);
519     insns[1] = val;
520   }
521 
522   // Returns the format of the given opcode.
FormatOf(Code opcode)523   static constexpr Format FormatOf(Code opcode) {
524     return InstructionDescriptorOf(opcode).format;
525   }
526 
527   // Returns the index type of the given opcode.
IndexTypeOf(Code opcode)528   static constexpr IndexType IndexTypeOf(Code opcode) {
529     return InstructionDescriptorOf(opcode).index_type;
530   }
531 
532   // Returns the flags for the given opcode.
FlagsOf(Code opcode)533   static constexpr uint8_t FlagsOf(Code opcode) {
534     return InstructionDescriptorOf(opcode).flags;
535   }
536 
537   // Return the verify flags for the given opcode.
VerifyFlagsOf(Code opcode)538   static constexpr uint32_t VerifyFlagsOf(Code opcode) {
539     return InstructionDescriptorOf(opcode).verify_flags;
540   }
541 
542   // Returns true if this instruction is a branch.
IsBranch()543   bool IsBranch() const {
544     return (InstructionDescriptorOf(Opcode()).flags & kBranch) != 0;
545   }
546 
547   // Returns true if this instruction is a unconditional branch.
IsUnconditional()548   bool IsUnconditional() const {
549     return (InstructionDescriptorOf(Opcode()).flags & kUnconditional) != 0;
550   }
551 
552   // Returns the branch offset if this instruction is a branch.
553   int32_t GetTargetOffset() const;
554 
555   // Returns true if the instruction allows control flow to go to the following instruction.
CanFlowThrough()556   bool CanFlowThrough() const {
557     return (FlagsOf(Opcode()) & Instruction::kContinue) != 0;
558   }
559 
560   // Returns true if this instruction is a switch.
IsSwitch()561   bool IsSwitch() const {
562     return (InstructionDescriptorOf(Opcode()).flags & kSwitch) != 0;
563   }
564 
565   // Returns true if this instruction can throw.
IsThrow()566   bool IsThrow() const {
567     return (InstructionDescriptorOf(Opcode()).flags & kThrow) != 0;
568   }
569 
570   // Determine if the instruction is any of 'return' instructions.
IsReturn(Code opcode)571   static constexpr bool IsReturn(Code opcode) {
572     return (InstructionDescriptorOf(opcode).flags & kReturn) != 0;
573   }
IsReturn()574   bool IsReturn() const {
575     return IsReturn(Opcode());
576   }
577 
578   // Determine if this instruction ends execution of its basic block.
IsBasicBlockEnd()579   bool IsBasicBlockEnd() const {
580     return IsBranch() || IsReturn() || Opcode() == THROW;
581   }
582 
583   // Determine if this instruction is an invoke.
IsInvoke()584   bool IsInvoke() const {
585     return (InstructionDescriptorOf(Opcode()).flags & kInvoke) != 0;
586   }
587 
588   // Determine if this instruction is experimental.
IsExperimental()589   bool IsExperimental() const {
590     return (InstructionDescriptorOf(Opcode()).flags & kExperimental) != 0;
591   }
592 
GetVerifyTypeArgumentAOf(Code opcode)593   static constexpr uint32_t GetVerifyTypeArgumentAOf(Code opcode) {
594     constexpr uint32_t kMask = kVerifyRegA | kVerifyRegAWide;
595     return VerifyFlagsOf(opcode) & kMask;
596   }
597 
GetVerifyTypeArgumentA()598   uint32_t GetVerifyTypeArgumentA() const {
599     return GetVerifyTypeArgumentAOf(Opcode());
600   }
601 
GetVerifyTypeArgumentBOf(Code opcode)602   static constexpr uint32_t GetVerifyTypeArgumentBOf(Code opcode) {
603     constexpr uint32_t kMask =
604         kVerifyRegB |
605         kVerifyRegBField |
606         kVerifyRegBMethod |
607         kVerifyRegBNewInstance |
608         kVerifyRegBString |
609         kVerifyRegBType |
610         kVerifyRegBWide |
611         kVerifyRegBFilledNewArray;
612     return VerifyFlagsOf(opcode) & kMask;
613   }
614 
GetVerifyTypeArgumentB()615   uint32_t GetVerifyTypeArgumentB() const {
616     return GetVerifyTypeArgumentBOf(Opcode());
617   }
618 
GetVerifyTypeArgumentCOf(Code opcode)619   static constexpr uint32_t GetVerifyTypeArgumentCOf(Code opcode) {
620     constexpr uint32_t kMask =
621         kVerifyRegC | kVerifyRegCField | kVerifyRegCNewArray | kVerifyRegCType | kVerifyRegCWide;
622     return VerifyFlagsOf(opcode) & kMask;
623   }
624 
GetVerifyTypeArgumentC()625   uint32_t GetVerifyTypeArgumentC() const {
626     return GetVerifyTypeArgumentCOf(Opcode());
627   }
628 
GetVerifyTypeArgumentHOf(Code opcode)629   static constexpr uint32_t GetVerifyTypeArgumentHOf(Code opcode) {
630     constexpr uint32_t kMask = kVerifyRegHPrototype;
631     return VerifyFlagsOf(opcode) & kMask;
632   }
633 
GetVerifyTypeArgumentH()634   uint32_t GetVerifyTypeArgumentH() const {
635     return GetVerifyTypeArgumentHOf(Opcode());
636   }
637 
GetVerifyExtraFlagsOf(Code opcode)638   static constexpr uint32_t GetVerifyExtraFlagsOf(Code opcode) {
639     constexpr uint32_t kMask =
640         kVerifyArrayData |
641         kVerifyBranchTarget |
642         kVerifySwitchTargets |
643         kVerifyVarArg |
644         kVerifyVarArgNonZero |
645         kVerifyVarArgRange |
646         kVerifyVarArgRangeNonZero |
647         kVerifyError;
648     return VerifyFlagsOf(opcode) & kMask;
649   }
650 
GetVerifyExtraFlags()651   uint32_t GetVerifyExtraFlags() const {
652     return GetVerifyExtraFlagsOf(Opcode());
653   }
654 
655   // Get the dex PC of this instruction as a offset in code units from the beginning of insns.
GetDexPc(const uint16_t * insns)656   uint32_t GetDexPc(const uint16_t* insns) const {
657     return (reinterpret_cast<const uint16_t*>(this) - insns);
658   }
659 
660   // Dump decoded version of instruction
661   std::string DumpString(const DexFile*) const;
662 
663   // Dump code_units worth of this instruction, padding to code_units for shorter instructions
664   std::string DumpHex(size_t code_units) const;
665 
666   // Little-endian dump code_units worth of this instruction, padding to code_units for
667   // shorter instructions
668   std::string DumpHexLE(size_t instr_code_units) const;
669 
Fetch16(size_t offset)670   uint16_t Fetch16(size_t offset) const {
671     const uint16_t* insns = reinterpret_cast<const uint16_t*>(this);
672     return insns[offset];
673   }
674 
675   size_t SizeInCodeUnitsComplexOpcode() const;
676 
677  private:
InstructionDescriptorOf(Code opcode)678   static constexpr const InstructionDescriptor& InstructionDescriptorOf(Code opcode) {
679     return kInstructionDescriptors[opcode];
680   }
681 
Fetch32(size_t offset)682   uint32_t Fetch32(size_t offset) const {
683     return (Fetch16(offset) | ((uint32_t) Fetch16(offset + 1) << 16));
684   }
685 
InstA()686   uint4_t InstA() const {
687     return InstA(Fetch16(0));
688   }
689 
InstB()690   uint4_t InstB() const {
691     return InstB(Fetch16(0));
692   }
693 
InstAA()694   uint8_t InstAA() const {
695     return InstAA(Fetch16(0));
696   }
697 
InstA(uint16_t inst_data)698   uint4_t InstA(uint16_t inst_data) const {
699     DCHECK_EQ(inst_data, Fetch16(0));
700     return static_cast<uint4_t>((inst_data >> 8) & 0x0f);
701   }
702 
InstB(uint16_t inst_data)703   uint4_t InstB(uint16_t inst_data) const {
704     DCHECK_EQ(inst_data, Fetch16(0));
705     return static_cast<uint4_t>(inst_data >> 12);
706   }
707 
InstAA(uint16_t inst_data)708   uint8_t InstAA(uint16_t inst_data) const {
709     DCHECK_EQ(inst_data, Fetch16(0));
710     return static_cast<uint8_t>(inst_data >> 8);
711   }
712 
713   static const char* const kInstructionNames[];
714 
715   static constexpr std::array<InstructionDescriptor, 256> kInstructionDescriptors = []() constexpr {
716     auto InstructionSizeInCodeUnitsByOpcode = [](Instruction::Code opcode,
717                                                  Instruction::Format format) constexpr -> int8_t {
718       if (opcode == Instruction::Code::NOP) {
719         return -1;
720       } else if ((format >= Instruction::Format::k10x) && (format <= Instruction::Format::k10t)) {
721         return 1;
722       } else if ((format >= Instruction::Format::k20t) && (format <= Instruction::Format::k22c)) {
723         return 2;
724       } else if ((format >= Instruction::Format::k32x) && (format <= Instruction::Format::k3rc)) {
725         return 3;
726       } else if ((format >= Instruction::Format::k45cc) && (format <= Instruction::Format::k4rcc)) {
727         return 4;
728       } else if (format == Instruction::Format::k51l) {
729         return 5;
730       } else {
731         return -1;
732       }
733     };
734 
735     std::array<InstructionDescriptor, 256> result;
736 #define INSTRUCTION_DESCR(opcode, c, p, format, index, flags, eflags, vflags) \
737     result[opcode] = {                                                        \
738         vflags,                                                               \
739         format,                                                               \
740         index,                                                                \
741         flags,                                                                \
742         InstructionSizeInCodeUnitsByOpcode((c), (format)),                    \
743     };
744     DEX_INSTRUCTION_LIST(INSTRUCTION_DESCR)
745 #undef INSTRUCTION_DESCR
746     return result;
747   }();
748 
749   DISALLOW_IMPLICIT_CONSTRUCTORS(Instruction);
750 };
751 std::ostream& operator<<(std::ostream& os, Instruction::Code code);
752 std::ostream& operator<<(std::ostream& os, Instruction::Format format);
753 
754 // Base class for accessing instruction operands. Unifies operand
755 // access for instructions that have range and varargs forms
756 // (e.g. invoke-polymoprhic/range and invoke-polymorphic).
757 class InstructionOperands {
758  public:
InstructionOperands(size_t num_operands)759   explicit InstructionOperands(size_t num_operands) : num_operands_(num_operands) {}
~InstructionOperands()760   virtual ~InstructionOperands() {}
761   virtual uint32_t GetOperand(size_t index) const = 0;
GetNumberOfOperands()762   size_t GetNumberOfOperands() const { return num_operands_; }
763 
764  private:
765   const size_t num_operands_;
766 
767   DISALLOW_IMPLICIT_CONSTRUCTORS(InstructionOperands);
768 };
769 
770 // Class for accessing operands for instructions with a range format
771 // (e.g. 3rc and 4rcc).
772 class RangeInstructionOperands final : public InstructionOperands {
773  public:
RangeInstructionOperands(uint32_t first_operand,size_t num_operands)774   RangeInstructionOperands(uint32_t first_operand, size_t num_operands)
775       : InstructionOperands(num_operands), first_operand_(first_operand) {}
~RangeInstructionOperands()776   ~RangeInstructionOperands() {}
777   uint32_t GetOperand(size_t operand_index) const override;
778 
779  private:
780   const uint32_t first_operand_;
781 
782   DISALLOW_IMPLICIT_CONSTRUCTORS(RangeInstructionOperands);
783 };
784 
785 // Class for accessing operands for instructions with a variable
786 // number of arguments format (e.g. 35c and 45cc).
787 class VarArgsInstructionOperands final : public InstructionOperands {
788  public:
VarArgsInstructionOperands(const uint32_t (& operands)[Instruction::kMaxVarArgRegs],size_t num_operands)789   VarArgsInstructionOperands(const uint32_t (&operands)[Instruction::kMaxVarArgRegs],
790                              size_t num_operands)
791       : InstructionOperands(num_operands), operands_(operands) {}
~VarArgsInstructionOperands()792   ~VarArgsInstructionOperands() {}
793   uint32_t GetOperand(size_t operand_index) const override;
794 
795  private:
796   const uint32_t (&operands_)[Instruction::kMaxVarArgRegs];
797 
798   DISALLOW_IMPLICIT_CONSTRUCTORS(VarArgsInstructionOperands);
799 };
800 
801 // Class for accessing operands without the receiver by wrapping an
802 // existing InstructionOperands instance.
803 class NoReceiverInstructionOperands final : public InstructionOperands {
804  public:
NoReceiverInstructionOperands(const InstructionOperands * const inner)805   explicit NoReceiverInstructionOperands(const InstructionOperands* const inner)
806       : InstructionOperands(inner->GetNumberOfOperands() - 1), inner_(inner) {}
~NoReceiverInstructionOperands()807   ~NoReceiverInstructionOperands() {}
808   uint32_t GetOperand(size_t operand_index) const override;
809 
810  private:
811   const InstructionOperands* const inner_;
812 
813   DISALLOW_IMPLICIT_CONSTRUCTORS(NoReceiverInstructionOperands);
814 };
815 
816 }  // namespace art
817 
818 #endif  // ART_LIBDEXFILE_DEX_DEX_INSTRUCTION_H_
819