1 /*
2  * Copyright (C) 2012 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_COMPILER_DEX_COMPILER_ENUMS_H_
18 #define ART_COMPILER_DEX_COMPILER_ENUMS_H_
19 
20 #include "dex_instruction.h"
21 
22 namespace art {
23 
24 enum RegisterClass {
25   kInvalidRegClass,
26   kCoreReg,
27   kFPReg,
28   kRefReg,
29   kAnyReg,
30 };
31 std::ostream& operator<<(std::ostream& os, const RegisterClass& rhs);
32 
33 enum BitsUsed {
34   kSize32Bits,
35   kSize64Bits,
36   kSize128Bits,
37   kSize256Bits,
38   kSize512Bits,
39   kSize1024Bits,
40 };
41 std::ostream& operator<<(std::ostream& os, const BitsUsed& rhs);
42 
43 enum SpecialTargetRegister {
44   kSelf,            // Thread pointer.
45   kSuspend,         // Used to reduce suspend checks for some targets.
46   kLr,
47   kPc,
48   kSp,
49   kArg0,
50   kArg1,
51   kArg2,
52   kArg3,
53   kArg4,
54   kArg5,
55   kArg6,
56   kArg7,
57   kFArg0,
58   kFArg1,
59   kFArg2,
60   kFArg3,
61   kFArg4,
62   kFArg5,
63   kFArg6,
64   kFArg7,
65   kFArg8,
66   kFArg9,
67   kFArg10,
68   kFArg11,
69   kFArg12,
70   kFArg13,
71   kFArg14,
72   kFArg15,
73   kRet0,
74   kRet1,
75   kInvokeTgt,
76   kHiddenArg,
77   kHiddenFpArg,
78   kCount
79 };
80 std::ostream& operator<<(std::ostream& os, const SpecialTargetRegister& code);
81 
82 enum RegLocationType {
83   kLocDalvikFrame = 0,  // Normal Dalvik register
84   kLocPhysReg,
85   kLocCompilerTemp,
86   kLocInvalid
87 };
88 std::ostream& operator<<(std::ostream& os, const RegLocationType& rhs);
89 
90 enum BBType {
91   kNullBlock,
92   kEntryBlock,
93   kDalvikByteCode,
94   kExitBlock,
95   kExceptionHandling,
96   kDead,
97 };
98 std::ostream& operator<<(std::ostream& os, const BBType& code);
99 
100 // Shared pseudo opcodes - must be < 0.
101 enum LIRPseudoOpcode {
102   kPseudoPrologueBegin = -18,
103   kPseudoPrologueEnd = -17,
104   kPseudoEpilogueBegin = -16,
105   kPseudoEpilogueEnd = -15,
106   kPseudoExportedPC = -14,
107   kPseudoSafepointPC = -13,
108   kPseudoIntrinsicRetry = -12,
109   kPseudoSuspendTarget = -11,
110   kPseudoThrowTarget = -10,
111   kPseudoCaseLabel = -9,
112   kPseudoBarrier = -8,
113   kPseudoEntryBlock = -7,
114   kPseudoExitBlock = -6,
115   kPseudoTargetLabel = -5,
116   kPseudoDalvikByteCodeBoundary = -4,
117   kPseudoPseudoAlign4 = -3,
118   kPseudoEHBlockLabel = -2,
119   kPseudoNormalBlockLabel = -1,
120 };
121 std::ostream& operator<<(std::ostream& os, const LIRPseudoOpcode& rhs);
122 
123 enum ExtendedMIROpcode {
124   kMirOpFirst = kNumPackedOpcodes,
125   kMirOpPhi = kMirOpFirst,
126 
127   // @brief Copy from one VR to another.
128   // @details
129   // vA: destination VR
130   // vB: source VR
131   kMirOpCopy,
132 
133   // @brief Used to do float comparison with less-than bias.
134   // @details Unlike cmpl-float, this does not store result of comparison in VR.
135   // vA: left-hand side VR for comparison.
136   // vB: right-hand side VR for comparison.
137   kMirOpFusedCmplFloat,
138 
139   // @brief Used to do float comparison with greater-than bias.
140   // @details Unlike cmpg-float, this does not store result of comparison in VR.
141   // vA: left-hand side VR for comparison.
142   // vB: right-hand side VR for comparison.
143   kMirOpFusedCmpgFloat,
144 
145   // @brief Used to do double comparison with less-than bias.
146   // @details Unlike cmpl-double, this does not store result of comparison in VR.
147   // vA: left-hand side wide VR for comparison.
148   // vB: right-hand side wide VR for comparison.
149   kMirOpFusedCmplDouble,
150 
151   // @brief Used to do double comparison with greater-than bias.
152   // @details Unlike cmpl-double, this does not store result of comparison in VR.
153   // vA: left-hand side wide VR for comparison.
154   // vB: right-hand side wide VR for comparison.
155   kMirOpFusedCmpgDouble,
156 
157   // @brief Used to do comparison of 64-bit long integers.
158   // @details Unlike cmp-long, this does not store result of comparison in VR.
159   // vA: left-hand side wide VR for comparison.
160   // vB: right-hand side wide VR for comparison.
161   kMirOpFusedCmpLong,
162 
163   // @brief This represents no-op.
164   kMirOpNop,
165 
166   // @brief Do a null check on the object register.
167   // @details The backends may implement this implicitly or explicitly. This MIR is guaranteed
168   // to have the correct offset as an exception thrower.
169   // vA: object register
170   kMirOpNullCheck,
171 
172   kMirOpRangeCheck,
173   kMirOpDivZeroCheck,
174   kMirOpCheck,
175   kMirOpSelect,
176 
177   // Vector opcodes:
178   // TypeSize is an encoded field giving the element type and the vector size.
179   // It is encoded as OpSize << 16 | (number of bits in vector)
180   //
181   // Destination and source are integers that will be interpreted by the
182   // backend that supports Vector operations.  Backends are permitted to support only
183   // certain vector register sizes.
184   //
185   // At this point, only two operand instructions are supported.  Three operand instructions
186   // could be supported by using a bit in TypeSize and arg[0] where needed.
187 
188   // @brief MIR to move constant data to a vector register
189   // vA: destination
190   // vB: number of bits in register
191   // args[0]~args[3]: up to 128 bits of data for initialization
192   kMirOpConstVector,
193 
194   // @brief MIR to move a vectorized register to another
195   // vA: destination
196   // vB: source
197   // vC: TypeSize
198   kMirOpMoveVector,
199 
200   // @brief Packed multiply of units in two vector registers: vB = vB .* vC using vA to know the type of the vector.
201   // vA: destination and source
202   // vB: source
203   // vC: TypeSize
204   kMirOpPackedMultiply,
205 
206   // @brief Packed addition of units in two vector registers: vB = vB .+ vC using vA to know the type of the vector.
207   // vA: destination and source
208   // vB: source
209   // vC: TypeSize
210   kMirOpPackedAddition,
211 
212   // @brief Packed subtraction of units in two vector registers: vB = vB .- vC using vA to know the type of the vector.
213   // vA: destination and source
214   // vB: source
215   // vC: TypeSize
216   kMirOpPackedSubtract,
217 
218   // @brief Packed shift left of units in two vector registers: vB = vB .<< vC using vA to know the type of the vector.
219   // vA: destination and source
220   // vB: amount to shift
221   // vC: TypeSize
222   kMirOpPackedShiftLeft,
223 
224   // @brief Packed signed shift right of units in two vector registers: vB = vB .>> vC using vA to know the type of the vector.
225   // vA: destination and source
226   // vB: amount to shift
227   // vC: TypeSize
228   kMirOpPackedSignedShiftRight,
229 
230   // @brief Packed unsigned shift right of units in two vector registers: vB = vB .>>> vC using vA to know the type of the vector.
231   // vA: destination and source
232   // vB: amount to shift
233   // vC: TypeSize
234   kMirOpPackedUnsignedShiftRight,
235 
236   // @brief Packed bitwise and of units in two vector registers: vB = vB .& vC using vA to know the type of the vector.
237   // vA: destination and source
238   // vB: source
239   // vC: TypeSize
240   kMirOpPackedAnd,
241 
242   // @brief Packed bitwise or of units in two vector registers: vB = vB .| vC using vA to know the type of the vector.
243   // vA: destination and source
244   // vB: source
245   // vC: TypeSize
246   kMirOpPackedOr,
247 
248   // @brief Packed bitwise xor of units in two vector registers: vB = vB .^ vC using vA to know the type of the vector.
249   // vA: destination and source
250   // vB: source
251   // vC: TypeSize
252   kMirOpPackedXor,
253 
254   // @brief Reduce a 128-bit packed element into a single VR by taking lower bits
255   // @details Instruction does a horizontal addition of the packed elements and then adds it to VR
256   // vA: destination and source VR (not vector register)
257   // vB: source (vector register)
258   // vC: TypeSize
259   kMirOpPackedAddReduce,
260 
261   // @brief Extract a packed element into a single VR.
262   // vA: destination VR (not vector register)
263   // vB: source (vector register)
264   // vC: TypeSize
265   // arg[0]: The index to use for extraction from vector register (which packed element)
266   kMirOpPackedReduce,
267 
268   // @brief Create a vector value, with all TypeSize values equal to vC
269   // vA: destination vector register
270   // vB: source VR (not vector register)
271   // vC: TypeSize
272   kMirOpPackedSet,
273 
274   // @brief Reserve a range of vector registers.
275   // vA: Start vector register to reserve.
276   // vB: Inclusive end vector register to reserve.
277   // @note: The backend may choose to map vector numbers used in vector opcodes.
278   //  Reserved registers are removed from the list of backend temporary pool.
279   kMirOpReserveVectorRegisters,
280 
281   // @brief Free a range of reserved vector registers
282   // vA: Start vector register to unreserve.
283   // vB: Inclusive end vector register to unreserve.
284   // @note: All currently reserved vector registers are returned to the temporary pool.
285   kMirOpReturnVectorRegisters,
286 
287   // @brief Create a memory barrier.
288   // vA: a constant defined by enum MemBarrierKind.
289   kMirOpMemBarrier,
290 
291   // @brief Used to fill a vector register with array values.
292   // @details Just as with normal arrays, access on null object register must ensure NullPointerException
293   // and invalid index must ensure ArrayIndexOutOfBoundsException. Exception behavior must be the same
294   // as the aget it replaced and must happen at same index. Therefore, it is generally recommended that
295   // before using this MIR, it is proven that exception is guaranteed to not be thrown and marked with
296   // MIR_IGNORE_NULL_CHECK and MIR_IGNORE_RANGE_CHECK.
297   // vA: destination vector register
298   // vB: array register
299   // vC: index register
300   // arg[0]: TypeSize (most other vector opcodes have this in vC)
301   kMirOpPackedArrayGet,
302 
303   // @brief Used to store a vector register into array.
304   // @details Just as with normal arrays, access on null object register must ensure NullPointerException
305   // and invalid index must ensure ArrayIndexOutOfBoundsException. Exception behavior must be the same
306   // as the aget it replaced and must happen at same index. Therefore, it is generally recommended that
307   // before using this MIR, it is proven that exception is guaranteed to not be thrown and marked with
308   // MIR_IGNORE_NULL_CHECK and MIR_IGNORE_RANGE_CHECK.
309   // vA: source vector register
310   // vB: array register
311   // vC: index register
312   // arg[0]: TypeSize (most other vector opcodes have this in vC)
313   kMirOpPackedArrayPut,
314 
315   // @brief Multiply-add integer.
316   // vA: destination
317   // vB: multiplicand
318   // vC: multiplier
319   // arg[0]: addend
320   kMirOpMaddInt,
321 
322   // @brief Multiply-subtract integer.
323   // vA: destination
324   // vB: multiplicand
325   // vC: multiplier
326   // arg[0]: minuend
327   kMirOpMsubInt,
328 
329   // @brief Multiply-add long.
330   // vA: destination
331   // vB: multiplicand
332   // vC: multiplier
333   // arg[0]: addend
334   kMirOpMaddLong,
335 
336   // @brief Multiply-subtract long.
337   // vA: destination
338   // vB: multiplicand
339   // vC: multiplier
340   // arg[0]: minuend
341   kMirOpMsubLong,
342 
343   kMirOpLast,
344 };
345 
346 enum MIROptimizationFlagPositions {
347   kMIRIgnoreNullCheck = 0,
348   kMIRIgnoreRangeCheck,
349   kMIRIgnoreCheckCast,
350   kMIRStoreNonNullValue,              // Storing non-null value, always mark GC card.
351   kMIRClassIsInitialized,
352   kMIRClassIsInDexCache,
353   kMirIgnoreDivZeroCheck,
354   kMIRInlined,                        // Invoke is inlined (ie dead).
355   kMIRInlinedPred,                    // Invoke is inlined via prediction.
356   kMIRCallee,                         // Instruction is inlined from callee.
357   kMIRIgnoreSuspendCheck,
358   kMIRDup,
359   kMIRMark,                           // Temporary node mark can be used by
360                                       // opt passes for their private needs.
361   kMIRStoreNonTemporal,
362   kMIRLastMIRFlag,
363 };
364 
365 // For successor_block_list.
366 enum BlockListType {
367   kNotUsed = 0,
368   kCatch,
369   kPackedSwitch,
370   kSparseSwitch,
371 };
372 std::ostream& operator<<(std::ostream& os, const BlockListType& rhs);
373 
374 enum AssemblerStatus {
375   kSuccess,
376   kRetryAll,
377 };
378 std::ostream& operator<<(std::ostream& os, const AssemblerStatus& rhs);
379 
380 enum OpSize {
381   kWord,            // Natural word size of target (32/64).
382   k32,
383   k64,
384   kReference,       // Object reference; compressed on 64-bit targets.
385   kSingle,
386   kDouble,
387   kUnsignedHalf,
388   kSignedHalf,
389   kUnsignedByte,
390   kSignedByte,
391 };
392 std::ostream& operator<<(std::ostream& os, const OpSize& kind);
393 
394 enum OpKind {
395   kOpMov,
396   kOpCmov,
397   kOpMvn,
398   kOpCmp,
399   kOpLsl,
400   kOpLsr,
401   kOpAsr,
402   kOpRor,
403   kOpNot,
404   kOpAnd,
405   kOpOr,
406   kOpXor,
407   kOpNeg,
408   kOpAdd,
409   kOpAdc,
410   kOpSub,
411   kOpSbc,
412   kOpRsub,
413   kOpMul,
414   kOpDiv,
415   kOpRem,
416   kOpBic,
417   kOpCmn,
418   kOpTst,
419   kOpRev,
420   kOpRevsh,
421   kOpBkpt,
422   kOpBlx,
423   kOpPush,
424   kOpPop,
425   kOp2Char,
426   kOp2Short,
427   kOp2Byte,
428   kOpCondBr,
429   kOpUncondBr,
430   kOpBx,
431   kOpInvalid,
432 };
433 std::ostream& operator<<(std::ostream& os, const OpKind& rhs);
434 
435 enum MoveType {
436   kMov8GP,      // Move 8-bit general purpose register.
437   kMov16GP,     // Move 16-bit general purpose register.
438   kMov32GP,     // Move 32-bit general purpose register.
439   kMov64GP,     // Move 64-bit general purpose register.
440   kMov32FP,     // Move 32-bit FP register.
441   kMov64FP,     // Move 64-bit FP register.
442   kMovLo64FP,   // Move low 32-bits of 64-bit FP register.
443   kMovHi64FP,   // Move high 32-bits of 64-bit FP register.
444   kMovU128FP,   // Move 128-bit FP register to/from possibly unaligned region.
445   kMov128FP = kMovU128FP,
446   kMovA128FP,   // Move 128-bit FP register to/from region surely aligned to 16-bytes.
447   kMovLo128FP,  // Move low 64-bits of 128-bit FP register.
448   kMovHi128FP,  // Move high 64-bits of 128-bit FP register.
449 };
450 std::ostream& operator<<(std::ostream& os, const MoveType& kind);
451 
452 enum ConditionCode {
453   kCondEq,  // equal
454   kCondNe,  // not equal
455   kCondCs,  // carry set
456   kCondCc,  // carry clear
457   kCondUlt,  // unsigned less than
458   kCondUge,  // unsigned greater than or same
459   kCondMi,  // minus
460   kCondPl,  // plus, positive or zero
461   kCondVs,  // overflow
462   kCondVc,  // no overflow
463   kCondHi,  // unsigned greater than
464   kCondLs,  // unsigned lower or same
465   kCondGe,  // signed greater than or equal
466   kCondLt,  // signed less than
467   kCondGt,  // signed greater than
468   kCondLe,  // signed less than or equal
469   kCondAl,  // always
470   kCondNv,  // never
471 };
472 std::ostream& operator<<(std::ostream& os, const ConditionCode& kind);
473 
474 // Target specific condition encodings
475 enum ArmConditionCode {
476   kArmCondEq = 0x0,  // 0000
477   kArmCondNe = 0x1,  // 0001
478   kArmCondCs = 0x2,  // 0010
479   kArmCondCc = 0x3,  // 0011
480   kArmCondMi = 0x4,  // 0100
481   kArmCondPl = 0x5,  // 0101
482   kArmCondVs = 0x6,  // 0110
483   kArmCondVc = 0x7,  // 0111
484   kArmCondHi = 0x8,  // 1000
485   kArmCondLs = 0x9,  // 1001
486   kArmCondGe = 0xa,  // 1010
487   kArmCondLt = 0xb,  // 1011
488   kArmCondGt = 0xc,  // 1100
489   kArmCondLe = 0xd,  // 1101
490   kArmCondAl = 0xe,  // 1110
491   kArmCondNv = 0xf,  // 1111
492 };
493 std::ostream& operator<<(std::ostream& os, const ArmConditionCode& kind);
494 
495 enum X86ConditionCode {
496   kX86CondO   = 0x0,    // overflow
497   kX86CondNo  = 0x1,    // not overflow
498 
499   kX86CondB   = 0x2,    // below
500   kX86CondNae = kX86CondB,  // not-above-equal
501   kX86CondC   = kX86CondB,  // carry
502 
503   kX86CondNb  = 0x3,    // not-below
504   kX86CondAe  = kX86CondNb,  // above-equal
505   kX86CondNc  = kX86CondNb,  // not-carry
506 
507   kX86CondZ   = 0x4,    // zero
508   kX86CondEq  = kX86CondZ,  // equal
509 
510   kX86CondNz  = 0x5,    // not-zero
511   kX86CondNe  = kX86CondNz,  // not-equal
512 
513   kX86CondBe  = 0x6,    // below-equal
514   kX86CondNa  = kX86CondBe,  // not-above
515 
516   kX86CondNbe = 0x7,    // not-below-equal
517   kX86CondA   = kX86CondNbe,  // above
518 
519   kX86CondS   = 0x8,    // sign
520   kX86CondNs  = 0x9,    // not-sign
521 
522   kX86CondP   = 0xa,    // 8-bit parity even
523   kX86CondPE  = kX86CondP,
524 
525   kX86CondNp  = 0xb,    // 8-bit parity odd
526   kX86CondPo  = kX86CondNp,
527 
528   kX86CondL   = 0xc,    // less-than
529   kX86CondNge = kX86CondL,  // not-greater-equal
530 
531   kX86CondNl  = 0xd,    // not-less-than
532   kX86CondGe  = kX86CondNl,  // not-greater-equal
533 
534   kX86CondLe  = 0xe,    // less-than-equal
535   kX86CondNg  = kX86CondLe,  // not-greater
536 
537   kX86CondNle = 0xf,    // not-less-than
538   kX86CondG   = kX86CondNle,  // greater
539 };
540 std::ostream& operator<<(std::ostream& os, const X86ConditionCode& kind);
541 
542 enum DividePattern {
543   DivideNone,
544   Divide3,
545   Divide5,
546   Divide7,
547 };
548 std::ostream& operator<<(std::ostream& os, const DividePattern& pattern);
549 
550 /**
551  * @brief Memory barrier types (see "The JSR-133 Cookbook for Compiler Writers").
552  * @details We define the combined barrier types that are actually required
553  * by the Java Memory Model, rather than using exactly the terminology from
554  * the JSR-133 cookbook.  These should, in many cases, be replaced by acquire/release
555  * primitives.  Note that the JSR-133 cookbook generally does not deal with
556  * store atomicity issues, and the recipes there are not always entirely sufficient.
557  * The current recipe is as follows:
558  * -# Use AnyStore ~= (LoadStore | StoreStore) ~= release barrier before volatile store.
559  * -# Use AnyAny barrier after volatile store.  (StoreLoad is as expensive.)
560  * -# Use LoadAny barrier ~= (LoadLoad | LoadStore) ~= acquire barrier after each volatile load.
561  * -# Use StoreStore barrier after all stores but before return from any constructor whose
562  *    class has final fields.
563  * -# Use NTStoreStore to order non-temporal stores with respect to all later
564  *    store-to-memory instructions.  Only generated together with non-temporal stores.
565  */
566 enum MemBarrierKind {
567   kAnyStore,
568   kLoadAny,
569   kStoreStore,
570   kAnyAny,
571   kNTStoreStore,
572 };
573 std::ostream& operator<<(std::ostream& os, const MemBarrierKind& kind);
574 
575 enum OpFeatureFlags {
576   kIsBranch = 0,
577   kNoOperand,
578   kIsUnaryOp,
579   kIsBinaryOp,
580   kIsTertiaryOp,
581   kIsQuadOp,
582   kIsQuinOp,
583   kIsSextupleOp,
584   kIsIT,
585   kIsMoveOp,
586   kMemLoad,
587   kMemStore,
588   kMemVolatile,
589   kMemScaledx0,
590   kMemScaledx2,
591   kMemScaledx4,
592   kPCRelFixup,  // x86 FIXME: add NEEDS_FIXUP to instruction attributes.
593   kRegDef0,
594   kRegDef1,
595   kRegDef2,
596   kRegDefA,
597   kRegDefD,
598   kRegDefFPCSList0,
599   kRegDefFPCSList2,
600   kRegDefList0,
601   kRegDefList1,
602   kRegDefList2,
603   kRegDefLR,
604   kRegDefSP,
605   kRegUse0,
606   kRegUse1,
607   kRegUse2,
608   kRegUse3,
609   kRegUse4,
610   kRegUseA,
611   kRegUseC,
612   kRegUseD,
613   kRegUseB,
614   kRegUseFPCSList0,
615   kRegUseFPCSList2,
616   kRegUseList0,
617   kRegUseList1,
618   kRegUseLR,
619   kRegUsePC,
620   kRegUseSP,
621   kSetsCCodes,
622   kUsesCCodes,
623   kUseFpStack,
624   kUseHi,
625   kUseLo,
626   kDefHi,
627   kDefLo
628 };
629 std::ostream& operator<<(std::ostream& os, const OpFeatureFlags& rhs);
630 
631 enum SelectInstructionKind {
632   kSelectNone,
633   kSelectConst,
634   kSelectMove,
635   kSelectGoto
636 };
637 std::ostream& operator<<(std::ostream& os, const SelectInstructionKind& kind);
638 
639 // LIR fixup kinds for Arm and X86.
640 enum FixupKind {
641   kFixupNone,
642   kFixupLabel,             // For labels we just adjust the offset.
643   kFixupLoad,              // Mostly for immediates.
644   kFixupVLoad,             // FP load which *may* be pc-relative.
645   kFixupCBxZ,              // Cbz, Cbnz.
646   kFixupTBxZ,              // Tbz, Tbnz.
647   kFixupCondBranch,        // Conditional branch
648   kFixupT1Branch,          // Thumb1 Unconditional branch
649   kFixupT2Branch,          // Thumb2 Unconditional branch
650   kFixupBlx1,              // Blx1 (start of Blx1/Blx2 pair).
651   kFixupBl1,               // Bl1 (start of Bl1/Bl2 pair).
652   kFixupAdr,               // Adr.
653   kFixupMovImmLST,         // kThumb2MovImm16LST.
654   kFixupMovImmHST,         // kThumb2MovImm16HST.
655   kFixupAlign4,            // Align to 4-byte boundary.
656   kFixupA53Erratum835769,  // Cortex A53 Erratum 835769.
657   kFixupSwitchTable,       // X86_64 packed switch table.
658 };
659 std::ostream& operator<<(std::ostream& os, const FixupKind& kind);
660 
661 enum VolatileKind {
662   kNotVolatile,      // Load/Store is not volatile
663   kVolatile          // Load/Store is volatile
664 };
665 std::ostream& operator<<(std::ostream& os, const VolatileKind& kind);
666 
667 enum WideKind {
668   kNotWide,      // Non-wide view
669   kWide,         // Wide view
670   kRef           // Ref width
671 };
672 std::ostream& operator<<(std::ostream& os, const WideKind& kind);
673 
674 }  // namespace art
675 
676 #endif  // ART_COMPILER_DEX_COMPILER_ENUMS_H_
677