• 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_RUNTIME_DEX_INSTRUCTION_H_
18 #define ART_RUNTIME_DEX_INSTRUCTION_H_
19 
20 #include "base/logging.h"
21 #include "base/macros.h"
22 #include "globals.h"
23 
24 typedef uint8_t uint4_t;
25 typedef int8_t int4_t;
26 
27 namespace art {
28 
29 class DexFile;
30 
31 enum {
32   kNumPackedOpcodes = 0x100
33 };
34 
35 class Instruction {
36  public:
37   // NOP-encoded switch-statement signatures.
38   enum {
39     kPackedSwitchSignature = 0x0100,
40     kSparseSwitchSignature = 0x0200,
41     kArrayDataSignature = 0x0300,
42   };
43 
44   struct PACKED(4) PackedSwitchPayload {
45     const uint16_t ident;
46     const uint16_t case_count;
47     const int32_t first_key;
48     const int32_t targets[];
49 
50    private:
51     DISALLOW_COPY_AND_ASSIGN(PackedSwitchPayload);
52   };
53 
54   struct PACKED(4) SparseSwitchPayload {
55     const uint16_t ident;
56     const uint16_t case_count;
57     const int32_t keys_and_targets[];
58 
59    public:
GetKeysSparseSwitchPayload60     const int32_t* GetKeys() const {
61       return keys_and_targets;
62     }
63 
GetTargetsSparseSwitchPayload64     const int32_t* GetTargets() const {
65       return keys_and_targets + case_count;
66     }
67 
68    private:
69     DISALLOW_COPY_AND_ASSIGN(SparseSwitchPayload);
70   };
71 
72   struct PACKED(4) ArrayDataPayload {
73     const uint16_t ident;
74     const uint16_t element_width;
75     const uint32_t element_count;
76     const uint8_t data[];
77 
78    private:
79     DISALLOW_COPY_AND_ASSIGN(ArrayDataPayload);
80   };
81 
82   // TODO: the code layout below is deliberate to avoid this enum being picked up by
83   //       generate-operator-out.py.
84   enum Code
85   {  // NOLINT(whitespace/braces)
86 #define INSTRUCTION_ENUM(opcode, cname, p, f, r, i, a, v) cname = opcode,
87 #include "dex_instruction_list.h"
88     DEX_INSTRUCTION_LIST(INSTRUCTION_ENUM)
89 #undef DEX_INSTRUCTION_LIST
90 #undef INSTRUCTION_ENUM
91   };
92 
93   enum Format {
94     k10x,  // op
95     k12x,  // op vA, vB
96     k11n,  // op vA, #+B
97     k11x,  // op vAA
98     k10t,  // op +AA
99     k20t,  // op +AAAA
100     k22x,  // op vAA, vBBBB
101     k21t,  // op vAA, +BBBB
102     k21s,  // op vAA, #+BBBB
103     k21h,  // op vAA, #+BBBB00000[00000000]
104     k21c,  // op vAA, thing@BBBB
105     k23x,  // op vAA, vBB, vCC
106     k22b,  // op vAA, vBB, #+CC
107     k22t,  // op vA, vB, +CCCC
108     k22s,  // op vA, vB, #+CCCC
109     k22c,  // op vA, vB, thing@CCCC
110     k32x,  // op vAAAA, vBBBB
111     k30t,  // op +AAAAAAAA
112     k31t,  // op vAA, +BBBBBBBB
113     k31i,  // op vAA, #+BBBBBBBB
114     k31c,  // op vAA, thing@BBBBBBBB
115     k35c,  // op {vC, vD, vE, vF, vG}, thing@BBBB (B: count, A: vG)
116     k3rc,  // op {vCCCC .. v(CCCC+AA-1)}, meth@BBBB
117     k51l,  // op vAA, #+BBBBBBBBBBBBBBBB
118   };
119 
120   enum Flags {
121     kBranch              = 0x000001,  // conditional or unconditional branch
122     kContinue            = 0x000002,  // flow can continue to next statement
123     kSwitch              = 0x000004,  // switch statement
124     kThrow               = 0x000008,  // could cause an exception to be thrown
125     kReturn              = 0x000010,  // returns, no additional statements
126     kInvoke              = 0x000020,  // a flavor of invoke
127     kUnconditional       = 0x000040,  // unconditional branch
128     kAdd                 = 0x000080,  // addition
129     kSubtract            = 0x000100,  // subtract
130     kMultiply            = 0x000200,  // multiply
131     kDivide              = 0x000400,  // division
132     kRemainder           = 0x000800,  // remainder
133     kAnd                 = 0x001000,  // and
134     kOr                  = 0x002000,  // or
135     kXor                 = 0x004000,  // xor
136     kShl                 = 0x008000,  // shl
137     kShr                 = 0x010000,  // shr
138     kUshr                = 0x020000,  // ushr
139     kCast                = 0x040000,  // cast
140     kStore               = 0x080000,  // store opcode
141     kLoad                = 0x100000,  // load opcode
142     kClobber             = 0x200000,  // clobbers memory in a big way (not just a write)
143     kRegCFieldOrConstant = 0x400000,  // is the third virtual register a field or literal constant (vC)
144     kRegBFieldOrConstant = 0x800000,  // is the second virtual register a field or literal constant (vB)
145   };
146 
147   enum VerifyFlag {
148     kVerifyNone               = 0x000000,
149     kVerifyRegA               = 0x000001,
150     kVerifyRegAWide           = 0x000002,
151     kVerifyRegB               = 0x000004,
152     kVerifyRegBField          = 0x000008,
153     kVerifyRegBMethod         = 0x000010,
154     kVerifyRegBNewInstance    = 0x000020,
155     kVerifyRegBString         = 0x000040,
156     kVerifyRegBType           = 0x000080,
157     kVerifyRegBWide           = 0x000100,
158     kVerifyRegC               = 0x000200,
159     kVerifyRegCField          = 0x000400,
160     kVerifyRegCNewArray       = 0x000800,
161     kVerifyRegCType           = 0x001000,
162     kVerifyRegCWide           = 0x002000,
163     kVerifyArrayData          = 0x004000,
164     kVerifyBranchTarget       = 0x008000,
165     kVerifySwitchTargets      = 0x010000,
166     kVerifyVarArg             = 0x020000,
167     kVerifyVarArgNonZero      = 0x040000,
168     kVerifyVarArgRange        = 0x080000,
169     kVerifyVarArgRangeNonZero = 0x100000,
170     kVerifyRuntimeOnly        = 0x200000,
171     kVerifyError              = 0x400000,
172   };
173 
174   static constexpr uint32_t kMaxVarArgRegs = 5;
175 
176   // Returns the size (in 2 byte code units) of this instruction.
SizeInCodeUnits()177   size_t SizeInCodeUnits() const {
178     int result = kInstructionSizeInCodeUnits[Opcode()];
179     if (UNLIKELY(result < 0)) {
180       return SizeInCodeUnitsComplexOpcode();
181     } else {
182       return static_cast<size_t>(result);
183     }
184   }
185 
186   // Reads an instruction out of the stream at the specified address.
At(const uint16_t * code)187   static const Instruction* At(const uint16_t* code) {
188     DCHECK(code != NULL);
189     return reinterpret_cast<const Instruction*>(code);
190   }
191 
192   // Reads an instruction out of the stream from the current address plus an offset.
RelativeAt(int32_t offset)193   const Instruction* RelativeAt(int32_t offset) const {
194     return At(reinterpret_cast<const uint16_t*>(this) + offset);
195   }
196 
197   // Returns a pointer to the next instruction in the stream.
Next()198   const Instruction* Next() const {
199     return RelativeAt(SizeInCodeUnits());
200   }
201 
202   // Returns a pointer to the instruction after this 1xx instruction in the stream.
Next_1xx()203   const Instruction* Next_1xx() const {
204     DCHECK(FormatOf(Opcode()) >= k10x && FormatOf(Opcode()) <= k10t);
205     return RelativeAt(1);
206   }
207 
208   // Returns a pointer to the instruction after this 2xx instruction in the stream.
Next_2xx()209   const Instruction* Next_2xx() const {
210     DCHECK(FormatOf(Opcode()) >= k20t && FormatOf(Opcode()) <= k22c);
211     return RelativeAt(2);
212   }
213 
214   // Returns a pointer to the instruction after this 3xx instruction in the stream.
Next_3xx()215   const Instruction* Next_3xx() const {
216     DCHECK(FormatOf(Opcode()) >= k32x && FormatOf(Opcode()) <= k3rc);
217     return RelativeAt(3);
218   }
219 
220   // Returns a pointer to the instruction after this 51l instruction in the stream.
Next_51l()221   const Instruction* Next_51l() const {
222     DCHECK(FormatOf(Opcode()) == k51l);
223     return RelativeAt(5);
224   }
225 
226   // Returns the name of this instruction's opcode.
Name()227   const char* Name() const {
228     return Instruction::Name(Opcode());
229   }
230 
231   // Returns the name of the given opcode.
Name(Code opcode)232   static const char* Name(Code opcode) {
233     return kInstructionNames[opcode];
234   }
235 
236   // VRegA
237   bool HasVRegA() const;
238   int32_t VRegA() const;
239 
VRegA_10t()240   int8_t VRegA_10t() const {
241     return VRegA_10t(Fetch16(0));
242   }
VRegA_10x()243   uint8_t VRegA_10x() const {
244     return VRegA_10x(Fetch16(0));
245   }
VRegA_11n()246   uint4_t VRegA_11n() const {
247     return VRegA_11n(Fetch16(0));
248   }
VRegA_11x()249   uint8_t VRegA_11x() const {
250     return VRegA_11x(Fetch16(0));
251   }
VRegA_12x()252   uint4_t VRegA_12x() const {
253     return VRegA_12x(Fetch16(0));
254   }
255   int16_t VRegA_20t() const;
VRegA_21c()256   uint8_t VRegA_21c() const {
257     return VRegA_21c(Fetch16(0));
258   }
VRegA_21h()259   uint8_t VRegA_21h() const {
260     return VRegA_21h(Fetch16(0));
261   }
VRegA_21s()262   uint8_t VRegA_21s() const {
263     return VRegA_21s(Fetch16(0));
264   }
VRegA_21t()265   uint8_t VRegA_21t() const {
266     return VRegA_21t(Fetch16(0));
267   }
VRegA_22b()268   uint8_t VRegA_22b() const {
269     return VRegA_22b(Fetch16(0));
270   }
VRegA_22c()271   uint4_t VRegA_22c() const {
272     return VRegA_22c(Fetch16(0));
273   }
VRegA_22s()274   uint4_t VRegA_22s() const {
275     return VRegA_22s(Fetch16(0));
276   }
VRegA_22t()277   uint4_t VRegA_22t() const {
278     return VRegA_22t(Fetch16(0));
279   }
VRegA_22x()280   uint8_t VRegA_22x() const {
281     return VRegA_22x(Fetch16(0));
282   }
VRegA_23x()283   uint8_t VRegA_23x() const {
284     return VRegA_23x(Fetch16(0));
285   }
286   int32_t VRegA_30t() const;
VRegA_31c()287   uint8_t VRegA_31c() const {
288     return VRegA_31c(Fetch16(0));
289   }
VRegA_31i()290   uint8_t VRegA_31i() const {
291     return VRegA_31i(Fetch16(0));
292   }
VRegA_31t()293   uint8_t VRegA_31t() const {
294     return VRegA_31t(Fetch16(0));
295   }
296   uint16_t VRegA_32x() const;
VRegA_35c()297   uint4_t VRegA_35c() const {
298     return VRegA_35c(Fetch16(0));
299   }
VRegA_3rc()300   uint8_t VRegA_3rc() const {
301     return VRegA_3rc(Fetch16(0));
302   }
VRegA_51l()303   uint8_t VRegA_51l() const {
304     return VRegA_51l(Fetch16(0));
305   }
306 
307   // The following methods return the vA operand for various instruction formats. The "inst_data"
308   // parameter holds the first 16 bits of instruction which the returned value is decoded from.
309   int8_t VRegA_10t(uint16_t inst_data) const;
310   uint8_t VRegA_10x(uint16_t inst_data) const;
311   uint4_t VRegA_11n(uint16_t inst_data) const;
312   uint8_t VRegA_11x(uint16_t inst_data) const;
313   uint4_t VRegA_12x(uint16_t inst_data) const;
314   uint8_t VRegA_21c(uint16_t inst_data) const;
315   uint8_t VRegA_21h(uint16_t inst_data) const;
316   uint8_t VRegA_21s(uint16_t inst_data) const;
317   uint8_t VRegA_21t(uint16_t inst_data) const;
318   uint8_t VRegA_22b(uint16_t inst_data) const;
319   uint4_t VRegA_22c(uint16_t inst_data) const;
320   uint4_t VRegA_22s(uint16_t inst_data) const;
321   uint4_t VRegA_22t(uint16_t inst_data) const;
322   uint8_t VRegA_22x(uint16_t inst_data) const;
323   uint8_t VRegA_23x(uint16_t inst_data) const;
324   uint8_t VRegA_31c(uint16_t inst_data) const;
325   uint8_t VRegA_31i(uint16_t inst_data) const;
326   uint8_t VRegA_31t(uint16_t inst_data) const;
327   uint4_t VRegA_35c(uint16_t inst_data) const;
328   uint8_t VRegA_3rc(uint16_t inst_data) const;
329   uint8_t VRegA_51l(uint16_t inst_data) const;
330 
331   // VRegB
332   bool HasVRegB() const;
333   int32_t VRegB() const;
334 
335   bool HasWideVRegB() const;
336   uint64_t WideVRegB() const;
337 
VRegB_11n()338   int4_t VRegB_11n() const {
339     return VRegB_11n(Fetch16(0));
340   }
VRegB_12x()341   uint4_t VRegB_12x() const {
342     return VRegB_12x(Fetch16(0));
343   }
344   uint16_t VRegB_21c() const;
345   uint16_t VRegB_21h() const;
346   int16_t VRegB_21s() const;
347   int16_t VRegB_21t() const;
348   uint8_t VRegB_22b() const;
VRegB_22c()349   uint4_t VRegB_22c() const {
350     return VRegB_22c(Fetch16(0));
351   }
VRegB_22s()352   uint4_t VRegB_22s() const {
353     return VRegB_22s(Fetch16(0));
354   }
VRegB_22t()355   uint4_t VRegB_22t() const {
356     return VRegB_22t(Fetch16(0));
357   }
358   uint16_t VRegB_22x() const;
359   uint8_t VRegB_23x() const;
360   uint32_t VRegB_31c() const;
361   int32_t VRegB_31i() const;
362   int32_t VRegB_31t() const;
363   uint16_t VRegB_32x() const;
364   uint16_t VRegB_35c() const;
365   uint16_t VRegB_3rc() const;
366   uint64_t VRegB_51l() const;  // vB_wide
367 
368   // The following methods return the vB operand for all instruction formats where it is encoded in
369   // the first 16 bits of instruction. The "inst_data" parameter holds these 16 bits. The returned
370   // value is decoded from it.
371   int4_t VRegB_11n(uint16_t inst_data) const;
372   uint4_t VRegB_12x(uint16_t inst_data) const;
373   uint4_t VRegB_22c(uint16_t inst_data) const;
374   uint4_t VRegB_22s(uint16_t inst_data) const;
375   uint4_t VRegB_22t(uint16_t inst_data) const;
376 
377   // VRegC
378   bool HasVRegC() const;
379   int32_t VRegC() const;
380 
381   int8_t VRegC_22b() const;
382   uint16_t VRegC_22c() const;
383   int16_t VRegC_22s() const;
384   int16_t VRegC_22t() const;
385   uint8_t VRegC_23x() const;
386   uint4_t VRegC_35c() const;
387   uint16_t VRegC_3rc() const;
388 
389   // Fills the given array with the 'arg' array of the instruction.
390   bool HasVarArgs() const;
391   void GetVarArgs(uint32_t args[kMaxVarArgRegs], uint16_t inst_data) const;
GetVarArgs(uint32_t args[kMaxVarArgRegs])392   void GetVarArgs(uint32_t args[kMaxVarArgRegs]) const {
393     return GetVarArgs(args, Fetch16(0));
394   }
395 
396   // Returns the opcode field of the instruction. The given "inst_data" parameter must be the first
397   // 16 bits of instruction.
Opcode(uint16_t inst_data)398   Code Opcode(uint16_t inst_data) const {
399     DCHECK_EQ(inst_data, Fetch16(0));
400     return static_cast<Code>(inst_data & 0xFF);
401   }
402 
403   // Returns the opcode field of the instruction from the first 16 bits of instruction.
Opcode()404   Code Opcode() const {
405     return Opcode(Fetch16(0));
406   }
407 
SetOpcode(Code opcode)408   void SetOpcode(Code opcode) {
409     DCHECK_LT(static_cast<uint16_t>(opcode), 256u);
410     uint16_t* insns = reinterpret_cast<uint16_t*>(this);
411     insns[0] = (insns[0] & 0xff00) | static_cast<uint16_t>(opcode);
412   }
413 
SetVRegA_10x(uint8_t val)414   void SetVRegA_10x(uint8_t val) {
415     DCHECK(FormatOf(Opcode()) == k10x);
416     uint16_t* insns = reinterpret_cast<uint16_t*>(this);
417     insns[0] = (val << 8) | (insns[0] & 0x00ff);
418   }
419 
SetVRegB_3rc(uint16_t val)420   void SetVRegB_3rc(uint16_t val) {
421     DCHECK(FormatOf(Opcode()) == k3rc);
422     uint16_t* insns = reinterpret_cast<uint16_t*>(this);
423     insns[1] = val;
424   }
425 
SetVRegB_35c(uint16_t val)426   void SetVRegB_35c(uint16_t val) {
427     DCHECK(FormatOf(Opcode()) == k35c);
428     uint16_t* insns = reinterpret_cast<uint16_t*>(this);
429     insns[1] = val;
430   }
431 
SetVRegC_22c(uint16_t val)432   void SetVRegC_22c(uint16_t val) {
433     DCHECK(FormatOf(Opcode()) == k22c);
434     uint16_t* insns = reinterpret_cast<uint16_t*>(this);
435     insns[1] = val;
436   }
437 
438   // Returns the format of the given opcode.
FormatOf(Code opcode)439   static Format FormatOf(Code opcode) {
440     return kInstructionFormats[opcode];
441   }
442 
443   // Returns the flags for the given opcode.
FlagsOf(Code opcode)444   static int FlagsOf(Code opcode) {
445     return kInstructionFlags[opcode];
446   }
447 
448   // Return the verify flags for the given opcode.
VerifyFlagsOf(Code opcode)449   static int VerifyFlagsOf(Code opcode) {
450     return kInstructionVerifyFlags[opcode];
451   }
452 
453   // Returns true if this instruction is a branch.
IsBranch()454   bool IsBranch() const {
455     return (kInstructionFlags[Opcode()] & kBranch) != 0;
456   }
457 
458   // Returns true if this instruction is a unconditional branch.
IsUnconditional()459   bool IsUnconditional() const {
460     return (kInstructionFlags[Opcode()] & kUnconditional) != 0;
461   }
462 
463   // Returns the branch offset if this instruction is a branch.
464   int32_t GetTargetOffset() const;
465 
466   // Returns true if the instruction allows control flow to go to the following instruction.
467   bool CanFlowThrough() const;
468 
469   // Returns true if this instruction is a switch.
IsSwitch()470   bool IsSwitch() const {
471     return (kInstructionFlags[Opcode()] & kSwitch) != 0;
472   }
473 
474   // Returns true if this instruction can throw.
IsThrow()475   bool IsThrow() const {
476     return (kInstructionFlags[Opcode()] & kThrow) != 0;
477   }
478 
479   // Determine if the instruction is any of 'return' instructions.
IsReturn()480   bool IsReturn() const {
481     return (kInstructionFlags[Opcode()] & kReturn) != 0;
482   }
483 
484   // Determine if this instruction ends execution of its basic block.
IsBasicBlockEnd()485   bool IsBasicBlockEnd() const {
486     return IsBranch() || IsReturn() || Opcode() == THROW;
487   }
488 
489   // Determine if this instruction is an invoke.
IsInvoke()490   bool IsInvoke() const {
491     return (kInstructionFlags[Opcode()] & kInvoke) != 0;
492   }
493 
GetVerifyTypeArgumentA()494   int GetVerifyTypeArgumentA() const {
495     return (kInstructionVerifyFlags[Opcode()] & (kVerifyRegA | kVerifyRegAWide));
496   }
497 
GetVerifyTypeArgumentB()498   int GetVerifyTypeArgumentB() const {
499     return (kInstructionVerifyFlags[Opcode()] & (kVerifyRegB | kVerifyRegBField |
500         kVerifyRegBMethod | kVerifyRegBNewInstance | kVerifyRegBString | kVerifyRegBType |
501         kVerifyRegBWide));
502   }
503 
GetVerifyTypeArgumentC()504   int GetVerifyTypeArgumentC() const {
505     return (kInstructionVerifyFlags[Opcode()] & (kVerifyRegC | kVerifyRegCField |
506         kVerifyRegCNewArray | kVerifyRegCType | kVerifyRegCWide));
507   }
508 
GetVerifyExtraFlags()509   int GetVerifyExtraFlags() const {
510     return (kInstructionVerifyFlags[Opcode()] & (kVerifyArrayData | kVerifyBranchTarget |
511         kVerifySwitchTargets | kVerifyVarArg | kVerifyVarArgNonZero | kVerifyVarArgRange |
512         kVerifyVarArgRangeNonZero | kVerifyError));
513   }
514 
GetVerifyIsRuntimeOnly()515   bool GetVerifyIsRuntimeOnly() const {
516     return (kInstructionVerifyFlags[Opcode()] & kVerifyRuntimeOnly) != 0;
517   }
518 
519   // Get the dex PC of this instruction as a offset in code units from the beginning of insns.
GetDexPc(const uint16_t * insns)520   uint32_t GetDexPc(const uint16_t* insns) const {
521     return (reinterpret_cast<const uint16_t*>(this) - insns);
522   }
523 
524   // Dump decoded version of instruction
525   std::string DumpString(const DexFile*) const;
526 
527   // Dump code_units worth of this instruction, padding to code_units for shorter instructions
528   std::string DumpHex(size_t code_units) const;
529 
Fetch16(size_t offset)530   uint16_t Fetch16(size_t offset) const {
531     const uint16_t* insns = reinterpret_cast<const uint16_t*>(this);
532     return insns[offset];
533   }
534 
535  private:
536   size_t SizeInCodeUnitsComplexOpcode() const;
537 
Fetch32(size_t offset)538   uint32_t Fetch32(size_t offset) const {
539     return (Fetch16(offset) | ((uint32_t) Fetch16(offset + 1) << 16));
540   }
541 
InstA()542   uint4_t InstA() const {
543     return InstA(Fetch16(0));
544   }
545 
InstB()546   uint4_t InstB() const {
547     return InstB(Fetch16(0));
548   }
549 
InstAA()550   uint8_t InstAA() const {
551     return InstAA(Fetch16(0));
552   }
553 
InstA(uint16_t inst_data)554   uint4_t InstA(uint16_t inst_data) const {
555     DCHECK_EQ(inst_data, Fetch16(0));
556     return static_cast<uint4_t>((inst_data >> 8) & 0x0f);
557   }
558 
InstB(uint16_t inst_data)559   uint4_t InstB(uint16_t inst_data) const {
560     DCHECK_EQ(inst_data, Fetch16(0));
561     return static_cast<uint4_t>(inst_data >> 12);
562   }
563 
InstAA(uint16_t inst_data)564   uint8_t InstAA(uint16_t inst_data) const {
565     DCHECK_EQ(inst_data, Fetch16(0));
566     return static_cast<uint8_t>(inst_data >> 8);
567   }
568 
569   static const char* const kInstructionNames[];
570   static Format const kInstructionFormats[];
571   static int const kInstructionFlags[];
572   static int const kInstructionVerifyFlags[];
573   static int const kInstructionSizeInCodeUnits[];
574   DISALLOW_IMPLICIT_CONSTRUCTORS(Instruction);
575 };
576 std::ostream& operator<<(std::ostream& os, const Instruction::Code& code);
577 std::ostream& operator<<(std::ostream& os, const Instruction::Format& format);
578 std::ostream& operator<<(std::ostream& os, const Instruction::Flags& flags);
579 std::ostream& operator<<(std::ostream& os, const Instruction::VerifyFlag& vflags);
580 
581 }  // namespace art
582 
583 #endif  // ART_RUNTIME_DEX_INSTRUCTION_H_
584