com.strobel.decompiler.ast.AstCode Maven / Gradle / Ivy
/*
* AstCode.java
*
* Copyright (c) 2013 Mike Strobel
*
* This source code is based on Mono.Cecil from Jb Evain, Copyright (c) Jb Evain;
* and ILSpy/ICSharpCode from SharpDevelop, Copyright (c) AlphaSierraPapa.
*
* This source code is subject to terms and conditions of the Apache License, Version 2.0.
* A copy of the license can be found in the License.html file at the root of this distribution.
* By using this source code in any fashion, you are agreeing to be bound by the terms of the
* Apache License, Version 2.0.
*
* You must not remove this notice, or any other, from this software.
*/
package com.strobel.decompiler.ast;
import com.strobel.assembler.ir.OpCode;
import com.strobel.assembler.metadata.MethodBody;
import com.strobel.core.StringUtilities;
import com.strobel.core.StrongBox;
public enum AstCode {
Nop,
AConstNull,
__IConstM1,
__IConst0,
__IConst1,
__IConst2,
__IConst3,
__IConst4,
__IConst5,
__LConst0,
__LConst1,
__FConst0,
__FConst1,
__FConst2,
__DConst0,
__DConst1,
__BIPush,
__SIPush,
LdC,
__LdCW,
__LdC2W,
__ILoad,
__LLoad,
__FLoad,
__DLoad,
__ALoad,
__ILoad0,
__ILoad1,
__ILoad2,
__ILoad3,
__LLoad0,
__LLoad1,
__LLoad2,
__LLoad3,
__FLoad0,
__FLoad1,
__FLoad2,
__FLoad3,
__DLoad0,
__DLoad1,
__DLoad2,
__DLoad3,
__ALoad0,
__ALoad1,
__ALoad2,
__ALoad3,
__IALoad,
__LALoad,
__FALoad,
__DALoad,
__AALoad,
__BALoad,
__CALoad,
__SALoad,
__IStore,
__LStore,
__FStore,
__DStore,
__AStore,
__IStore0,
__IStore1,
__IStore2,
__IStore3,
__LStore0,
__LStore1,
__LStore2,
__LStore3,
__FStore0,
__FStore1,
__FStore2,
__FStore3,
__DStore0,
__DStore1,
__DStore2,
__DStore3,
__AStore0,
__AStore1,
__AStore2,
__AStore3,
__IAStore,
__LAStore,
__FAStore,
__DAStore,
__AAStore,
__BAStore,
__CAStore,
__SAStore,
Pop,
Pop2,
Dup,
DupX1,
DupX2,
Dup2,
Dup2X1,
Dup2X2,
Swap,
__IAdd,
__LAdd,
__FAdd,
__DAdd,
__ISub,
__LSub,
__FSub,
__DSub,
__IMul,
__LMul,
__FMul,
__DMul,
__IDiv,
__LDiv,
__FDiv,
__DDiv,
__IRem,
__LRem,
__FRem,
__DRem,
__INeg,
__LNeg,
__FNeg,
__DNeg,
__IShl,
__LShl,
__IShr,
__LShr,
__IUShr,
__LUShr,
__IAnd,
__LAnd,
__IOr,
__LOr,
__IXor,
__LXor,
__IInc,
I2L,
I2F,
I2D,
L2I,
L2F,
L2D,
F2I,
F2L,
F2D,
D2I,
D2L,
D2F,
I2B,
I2C,
I2S,
__LCmp,
__FCmpL,
__FCmpG,
__DCmpL,
__DCmpG,
__IfEq,
__IfNe,
__IfLt,
__IfGe,
__IfGt,
__IfLe,
__IfICmpEq,
__IfICmpNe,
__IfICmpLt,
__IfICmpGe,
__IfICmpGt,
__IfICmpLe,
__IfACmpEq,
__IfACmpNe,
Goto,
Jsr,
Ret,
__TableSwitch,
__LookupSwitch,
__IReturn,
__LReturn,
__FReturn,
__DReturn,
__AReturn,
__Return,
GetStatic,
PutStatic,
GetField,
PutField,
InvokeVirtual,
InvokeSpecial,
InvokeStatic,
InvokeInterface,
InvokeDynamic,
__New,
__NewArray,
__ANewArray,
ArrayLength,
AThrow,
CheckCast,
InstanceOf,
MonitorEnter,
MonitorExit,
MultiANewArray,
__IfNull,
__IfNonNull,
__GotoW,
__JsrW,
Breakpoint,
__ILoadW,
__LLoadW,
__FLoadW,
__DLoadW,
__ALoadW,
__IStoreW,
__LStoreW,
__FStoreW,
__DStoreW,
__AStoreW,
__IIncW,
__RetW,
/**
* Special placeholder to mark the end of try and catch blocks with an unconditional branch.
* Will be removed during optimization.
*/
Leave,
/**
* Special placeholder to mark the end of finally blocks with an unconditional branch.
* Will be removed during optimization.
*/
EndFinally,
//
// Virtual codes, defined for convenience.
//
Load,
Store,
LoadElement,
StoreElement,
Add,
Sub,
Mul,
Div,
Rem,
Neg,
Shl,
Shr,
UShr,
And,
Or,
Not,
Xor,
Inc,
CmpEq,
CmpNe,
CmpLt,
CmpGe,
CmpGt,
CmpLe,
IfTrue,
Return,
NewArray,
LoadException,
LogicalNot,
LogicalAnd,
LogicalOr,
InitObject,
InitArray,
Switch,
/**
* Defines a barrier between the parent expression and the argument expression that prevents combining them.
*/
Wrap,
Bind,
TernaryOp,
LoopOrSwitchBreak,
LoopContinue,
/**
* Expression with a single binary operator child. Indicates that the binary operator will also assign the new value to its left-hand side.
* {@code CompoundAssignment} must not be used for local variables, as inlining and other optimizations don't know that it modifies the variable.
*/
CompoundAssignment,
PreIncrement,
PostIncrement,
/**
* Simulates creation of a boxed type from its corresponding primitive type.
*/
Box,
/**
* Simulates extraction of a primitive type from its corresponding boxed type.
*/
Unbox,
DefaultValue;
private final static OpCode[] STANDARD_CODES = OpCode.values();
public final String getName() {
return StringUtilities.trimAndRemoveLeft(name().toLowerCase(), "__");
}
public final boolean isLoad() {
switch (this) {
case Load:
// case PreIncrement:
// case PostIncrement:
case Ret:
case Inc:
return true;
default:
return false;
}
}
public final boolean isFieldRead() {
switch (this) {
case GetStatic:
case GetField:
return true;
default:
return false;
}
}
public final boolean isFieldWrite() {
switch (this) {
case PutStatic:
case PutField:
return true;
default:
return false;
}
}
public final boolean isStore() {
switch (this) {
case Store:
case Inc:
case PreIncrement:
case PostIncrement:
return true;
default:
return false;
}
}
public final boolean isDup() {
switch (this) {
case Dup:
case DupX1:
case DupX2:
case Dup2:
case Dup2X1:
case Dup2X2:
return true;
default:
return false;
}
}
public final boolean isComparison() {
switch (this) {
case CmpEq:
case CmpNe:
case CmpLe:
case CmpGt:
case CmpGe:
case CmpLt:
return true;
default:
return false;
}
}
public final boolean isLogical() {
switch (this) {
case LogicalNot:
case LogicalAnd:
case LogicalOr:
return true;
default:
return false;
}
}
public final boolean isShortCircuiting() {
switch (this) {
case LogicalAnd:
case LogicalOr:
return true;
default:
return false;
}
}
public final boolean isWriteOperation() {
switch (this) {
case Store:
case StoreElement:
case PutField:
case PutStatic:
return true;
default:
return false;
}
}
public final AstCode reverse() {
switch (this) {
case CmpEq:
return CmpNe;
case CmpNe:
return CmpEq;
case CmpLe:
return CmpGt;
case CmpGt:
return CmpLe;
case CmpGe:
return CmpLt;
case CmpLt:
return CmpGe;
case LogicalAnd:
return LogicalOr;
case LogicalOr:
return LogicalAnd;
default:
return this;
}
}
public final boolean isConditionalControlFlow() {
final int ordinal = ordinal();
if (ordinal < STANDARD_CODES.length) {
final OpCode standardCode = STANDARD_CODES[ordinal];
return standardCode.isBranch() && !standardCode.isUnconditionalBranch();
}
return this == IfTrue;
}
public final boolean isUnconditionalControlFlow() {
switch (this) {
case LoopContinue:
case LoopOrSwitchBreak:
case Return:
case Leave:
case Switch:
case EndFinally:
return true;
default:
final int ordinal = ordinal();
if (ordinal < STANDARD_CODES.length) {
final OpCode standardCode = STANDARD_CODES[ordinal];
return standardCode.isUnconditionalBranch();
}
return false;
}
}
public static boolean expandMacro(final StrongBox code, final StrongBox