All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.strobel.decompiler.ast.AstCode Maven / Gradle / Ivy

There is a newer version: 2.5.0.Final
Show newest version
/*
 * 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 operand, final MethodBody body, final int offset) { final AstCode op = code.get(); switch (op) { case __IConstM1: code.set(LdC); operand.set(-1); return true; case __IConst0: code.set(LdC); operand.set(0); return true; case __IConst1: code.set(LdC); operand.set(1); return true; case __IConst2: code.set(LdC); operand.set(2); return true; case __IConst3: code.set(LdC); operand.set(3); return true; case __IConst4: code.set(LdC); operand.set(4); return true; case __IConst5: code.set(LdC); operand.set(5); return true; case __LConst0: code.set(LdC); operand.set(0L); return true; case __LConst1: code.set(LdC); operand.set(1L); return true; case __FConst0: code.set(LdC); operand.set(0f); return true; case __FConst1: code.set(LdC); operand.set(1f); return true; case __FConst2: code.set(LdC); operand.set(2f); return true; case __DConst0: code.set(LdC); operand.set(0d); return true; case __DConst1: code.set(LdC); operand.set(1d); return true; case __BIPush: case __SIPush: code.set(LdC); operand.set(((Number) operand.get()).intValue()); return true; case __LdCW: case __LdC2W: code.set(LdC); return true; case __JsrW: code.set(Jsr); return true; case __RetW: code.set(Ret); return true; case __IInc: case __IIncW: { code.set(Inc); return true; } case __IReturn: case __LReturn: case __FReturn: case __DReturn: case __AReturn: case __Return: code.set(Return); return true; case __NewArray: case __ANewArray: code.set(NewArray); return true; case __ILoad: case __LLoad: case __FLoad: case __DLoad: case __ALoad: case __ALoadW: case __ILoadW: case __FLoadW: case __LLoadW: case __DLoadW: code.set(Load); return true; case __ILoad0: code.set(Load); operand.set(body.getVariables().reference(0, STANDARD_CODES[op.ordinal()], offset)); return true; case __ILoad1: code.set(Load); operand.set(body.getVariables().reference(1, STANDARD_CODES[op.ordinal()], offset)); return true; case __ILoad2: code.set(Load); operand.set(body.getVariables().reference(2, STANDARD_CODES[op.ordinal()], offset)); return true; case __ILoad3: code.set(Load); operand.set(body.getVariables().reference(3, STANDARD_CODES[op.ordinal()], offset)); return true; case __LLoad0: code.set(Load); operand.set(body.getVariables().reference(0, STANDARD_CODES[op.ordinal()], offset)); return true; case __LLoad1: code.set(Load); operand.set(body.getVariables().reference(1, STANDARD_CODES[op.ordinal()], offset)); return true; case __LLoad2: code.set(Load); operand.set(body.getVariables().reference(2, STANDARD_CODES[op.ordinal()], offset)); return true; case __LLoad3: code.set(Load); operand.set(body.getVariables().reference(3, STANDARD_CODES[op.ordinal()], offset)); return true; case __FLoad0: code.set(Load); operand.set(body.getVariables().reference(0, STANDARD_CODES[op.ordinal()], offset)); return true; case __FLoad1: code.set(Load); operand.set(body.getVariables().reference(1, STANDARD_CODES[op.ordinal()], offset)); return true; case __FLoad2: code.set(Load); operand.set(body.getVariables().reference(2, STANDARD_CODES[op.ordinal()], offset)); return true; case __FLoad3: code.set(Load); operand.set(body.getVariables().reference(3, STANDARD_CODES[op.ordinal()], offset)); return true; case __DLoad0: code.set(Load); operand.set(body.getVariables().reference(0, STANDARD_CODES[op.ordinal()], offset)); return true; case __DLoad1: code.set(Load); operand.set(body.getVariables().reference(1, STANDARD_CODES[op.ordinal()], offset)); return true; case __DLoad2: code.set(Load); operand.set(body.getVariables().reference(2, STANDARD_CODES[op.ordinal()], offset)); return true; case __DLoad3: code.set(Load); operand.set(body.getVariables().reference(3, STANDARD_CODES[op.ordinal()], offset)); return true; case __ALoad0: code.set(Load); operand.set(body.getVariables().reference(0, STANDARD_CODES[op.ordinal()], offset)); return true; case __ALoad1: code.set(Load); operand.set(body.getVariables().reference(1, STANDARD_CODES[op.ordinal()], offset)); return true; case __ALoad2: code.set(Load); operand.set(body.getVariables().reference(2, STANDARD_CODES[op.ordinal()], offset)); return true; case __ALoad3: code.set(Load); operand.set(body.getVariables().reference(3, STANDARD_CODES[op.ordinal()], offset)); return true; case __IALoad: case __LALoad: case __FALoad: case __DALoad: case __AALoad: case __BALoad: case __CALoad: case __SALoad: code.set(LoadElement); return true; case __GotoW: code.set(Goto); return true; case __IStore: case __LStore: case __FStore: case __DStore: case __AStore: case __AStoreW: case __IStoreW: case __LStoreW: case __FStoreW: case __DStoreW: code.set(Store); return true; case __IStore0: code.set(Store); operand.set(body.getVariables().reference(0, STANDARD_CODES[op.ordinal()], offset)); return true; case __IStore1: code.set(Store); operand.set(body.getVariables().reference(1, STANDARD_CODES[op.ordinal()], offset)); return true; case __IStore2: code.set(Store); operand.set(body.getVariables().reference(2, STANDARD_CODES[op.ordinal()], offset)); return true; case __IStore3: code.set(Store); operand.set(body.getVariables().reference(3, STANDARD_CODES[op.ordinal()], offset)); return true; case __LStore0: code.set(Store); operand.set(body.getVariables().reference(0, STANDARD_CODES[op.ordinal()], offset)); return true; case __LStore1: code.set(Store); operand.set(body.getVariables().reference(1, STANDARD_CODES[op.ordinal()], offset)); return true; case __LStore2: code.set(Store); operand.set(body.getVariables().reference(2, STANDARD_CODES[op.ordinal()], offset)); return true; case __LStore3: code.set(Store); operand.set(body.getVariables().reference(3, STANDARD_CODES[op.ordinal()], offset)); return true; case __FStore0: code.set(Store); operand.set(body.getVariables().reference(0, STANDARD_CODES[op.ordinal()], offset)); return true; case __FStore1: code.set(Store); operand.set(body.getVariables().reference(1, STANDARD_CODES[op.ordinal()], offset)); return true; case __FStore2: code.set(Store); operand.set(body.getVariables().reference(2, STANDARD_CODES[op.ordinal()], offset)); return true; case __FStore3: code.set(Store); operand.set(body.getVariables().reference(3, STANDARD_CODES[op.ordinal()], offset)); return true; case __DStore0: code.set(Store); operand.set(body.getVariables().reference(0, STANDARD_CODES[op.ordinal()], offset)); return true; case __DStore1: code.set(Store); operand.set(body.getVariables().reference(1, STANDARD_CODES[op.ordinal()], offset)); return true; case __DStore2: code.set(Store); operand.set(body.getVariables().reference(2, STANDARD_CODES[op.ordinal()], offset)); return true; case __DStore3: code.set(Store); operand.set(body.getVariables().reference(3, STANDARD_CODES[op.ordinal()], offset)); return true; case __AStore0: code.set(Store); operand.set(body.getVariables().reference(0, STANDARD_CODES[op.ordinal()], offset)); return true; case __AStore1: code.set(Store); operand.set(body.getVariables().reference(1, STANDARD_CODES[op.ordinal()], offset)); return true; case __AStore2: code.set(Store); operand.set(body.getVariables().reference(2, STANDARD_CODES[op.ordinal()], offset)); return true; case __AStore3: code.set(Store); operand.set(body.getVariables().reference(3, STANDARD_CODES[op.ordinal()], offset)); return true; case __IAStore: case __LAStore: case __FAStore: case __DAStore: case __AAStore: case __BAStore: case __CAStore: case __SAStore: code.set(StoreElement); return true; case __IAdd: case __LAdd: case __FAdd: case __DAdd: code.set(Add); return true; case __ISub: case __LSub: case __FSub: case __DSub: code.set(Sub); return true; case __IMul: case __LMul: case __FMul: case __DMul: code.set(Mul); return true; case __IDiv: case __LDiv: case __FDiv: case __DDiv: code.set(Div); return true; case __IRem: case __LRem: case __FRem: case __DRem: code.set(Rem); return true; case __INeg: case __LNeg: case __FNeg: case __DNeg: code.set(Neg); return true; case __IShl: case __LShl: code.set(Shl); return true; case __IShr: case __LShr: code.set(Shr); return true; case __IUShr: case __LUShr: code.set(UShr); return true; case __IAnd: case __LAnd: code.set(And); return true; case __IOr: case __LOr: code.set(Or); return true; case __IXor: case __LXor: code.set(Xor); return true; case __LookupSwitch: case __TableSwitch: code.set(Switch); return true; default: return false; } } }