Extend the instruction class with instruction attributes.
Change-Id: I52a4f640bd45d1891050876a7a0c031ec3a58974
diff --git a/src/dex_instruction.h b/src/dex_instruction.h
index b233ad5..f1bb7bf 100644
--- a/src/dex_instruction.h
+++ b/src/dex_instruction.h
@@ -11,22 +11,71 @@
class Instruction {
public:
+ // NOP-encoded switch-statement signatures.
+ enum {
+ kPackedSwitchSignature = 0x0100,
+ kSparseSwitchSignature = 0x0200,
+ kArrayDataSignature = 0x0300
+ };
+
enum Code {
-#define INSTRUCTION_ENUM(cname, opcode) cname = opcode,
+#define INSTRUCTION_ENUM(opcode, cname, p, f, r, i, a) cname = opcode,
#include "src/dex_instruction_list.h"
DEX_INSTRUCTION_LIST(INSTRUCTION_ENUM)
#undef DEX_INSTRUCTION_LIST
#undef INSTRUCTION_ENUM
};
+ enum InstructionFormat {
+ k10x, // op
+ k12x, // op vA, vB
+ k11n, // op vA, #+B
+ k11x, // op vAA
+ k10t, // op +AA
+ k20t, // op +AAAA
+ k22x, // op vAA, vBBBB
+ k21t, // op vAA, +BBBB
+ k21s, // op vAA, #+BBBB
+ k21h, // op vAA, #+BBBB00000[00000000]
+ k21c, // op vAA, thing@BBBB
+ k23x, // op vAA, vBB, vCC
+ k22b, // op vAA, vBB, #+CC
+ k22t, // op vA, vB, +CCCC
+ k22s, // op vA, vB, #+CCCC
+ k22c, // op vA, vB, thing@CCCC
+ k32x, // op vAAAA, vBBBB
+ k30t, // op +AAAAAAAA
+ k31t, // op vAA, +BBBBBBBB
+ k31i, // op vAA, #+BBBBBBBB
+ k31c, // op vAA, thing@BBBBBBBB
+ k35c, // op {vC, vD, vE, vF, vG}, thing@BBBB (B: count, A: vG)
+ k3rc, // op {vCCCC .. v(CCCC+AA-1)}, meth@BBBB
+ k51l, // op vAA, #+BBBBBBBBBBBBBBBB
+ };
+
+ enum Flags {
+ kBranch = 0x01, // conditional or unconditional branch
+ kContinue = 0x02, // flow can continue to next statement
+ kSwitch = 0x04, // switch statement
+ kThrow = 0x08, // could cause an exception to be thrown
+ kReturn = 0x10, // returns, no additional statements
+ kInvoke = 0x20, // a flavor of invoke
+ // TODO: kUnconditional
+ };
+
// Returns the size in bytes of this instruction.
- size_t Size();
+ size_t Size() const;
// Returns a pointer to the next instruction in the stream.
- const Instruction* Next();
+ const Instruction* Next() const;
+
+ // Name of the instruction.
+ const char* Name() const {
+ return kInstructionNames[Opcode()];
+ }
// Returns the opcode field of the instruction.
- Code Opcode();
+ Code Opcode() const;
// Reads an instruction out of the stream at the specified address.
static Instruction* At(byte* code) {
@@ -34,7 +83,35 @@
return reinterpret_cast<Instruction*>(code);
}
+ // Returns the format of the current instruction.
+ InstructionFormat Format() const {
+ return kInstructionFormats[Opcode()];
+ }
+
+ // Returns true if this instruction is a branch.
+ bool IsBranch() const {
+ return (kInstructionFlags[Opcode()] & kBranch) != 0;
+ }
+
+ // Determine if the instruction is any of 'return' instructions.
+ bool IsReturn() const {
+ return (kInstructionFlags[Opcode()] & kReturn) != 0;
+ }
+
+ // Determine if this instruction ends execution of its basic block.
+ bool IsBasicBlockEnd() const {
+ return IsBranch() || IsReturn() || Opcode() == THROW;
+ }
+
+ // Determine if this instruction is an invoke.
+ bool IsInvoke() const {
+ return (kInstructionFlags[Opcode()] & kInvoke) != 0;
+ }
+
private:
+ static const char* const kInstructionNames[];
+ static InstructionFormat const kInstructionFormats[];
+ static int const kInstructionFlags[];
DISALLOW_IMPLICIT_CONSTRUCTORS(Instruction);
};