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

org.snapscript.dx.Code Maven / Gradle / Ivy

/*
 * Copyright (C) 2011 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.snapscript.dx;

import static org.snapscript.dx.rop.code.Rop.BRANCH_GOTO;
import static org.snapscript.dx.rop.code.Rop.BRANCH_NONE;
import static org.snapscript.dx.rop.code.Rop.BRANCH_RETURN;
import static org.snapscript.dx.rop.type.Type.BT_BYTE;
import static org.snapscript.dx.rop.type.Type.BT_CHAR;
import static org.snapscript.dx.rop.type.Type.BT_INT;
import static org.snapscript.dx.rop.type.Type.BT_SHORT;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

import org.snapscript.dx.rop.code.BasicBlockList;
import org.snapscript.dx.rop.code.Insn;
import org.snapscript.dx.rop.code.PlainCstInsn;
import org.snapscript.dx.rop.code.PlainInsn;
import org.snapscript.dx.rop.code.RegisterSpecList;
import org.snapscript.dx.rop.code.Rop;
import org.snapscript.dx.rop.code.Rops;
import org.snapscript.dx.rop.code.SourcePosition;
import org.snapscript.dx.rop.code.ThrowingCstInsn;
import org.snapscript.dx.rop.code.ThrowingInsn;
import org.snapscript.dx.rop.cst.CstInteger;
import org.snapscript.dx.rop.type.StdTypeList;

/**
 * Builds a sequence of instructions.
 *
 * 

Locals

* All data manipulation takes place in local variables. Each parameter gets its * own local by default; access these using {@link #getParameter * getParameter()}. Non-static methods and constructors also have a {@code this} * parameter; it's available as {@link #getThis getThis()}. Allocate a new local * variable using {@link #newLocal newLocal()}, and assign a default value to it * with {@link #loadConstant loadConstant()}. Copy a value from one local to * another with {@link #move move()}. * *

Every local variable has a fixed type. This is either a primitive type (of * any size) or a reference type. This class emits instructions appropriate to * the types they operate on. Not all operations are local on all types; * attempting to emit such an operation will fail with an unchecked exception. * *

Math and Bit Operations

* Transform a single value into another related value using {@link * #op(UnaryOp,Local,Local) op(UnaryOp, Local, Local)}. Transform two values * into a third value using {@link #op(BinaryOp,Local,Local,Local) op(BinaryOp, * Local, Local, Local)}. In either overload the first {@code Local} parameter * is where the result will be sent; the other {@code Local} parameters are the * inputs. * *

Comparisons

* There are three different comparison operations each with different * constraints: *
    *
  • {@link #compareLongs compareLongs()} compares two locals each * containing a {@code long} primitive. This is the only operation that * can compare longs. The result of the comparison is written to another * {@code int} local.
  • *
  • {@link #compareFloatingPoint compareFloatingPoint()} compares two * locals; both {@code float} primitives or both {@code double} * primitives. This is the only operation that can compare floating * point values. This comparison takes an extra parameter that sets * the desired result if either parameter is {@code NaN}. The result of * the comparison is wrtten to another {@code int} local. *
  • {@link #compare compare()} compares two locals. The {@link * Comparison#EQ} and {@link Comparison#NE} options compare either * {@code int} primitives or references. The other options compare only * {@code int} primitives. This comparison takes a {@link Label} that * will be jumped to if the comparison is true. If the comparison is * false the next instruction in sequence will be executed. *
* There's no single operation to compare longs and jump, or to compare ints and * store the result in a local. Accomplish these goals by chaining multiple * operations together. * *

Branches, Labels and Returns

* Basic control flow is expressed using jumps and labels. Each label must be * marked exactly once and may be jumped to any number of times. Create a label * using its constructor: {@code new Label()}, and mark it using {@link #mark * mark(Label)}. All jumps to a label will execute instructions starting from * that label. You can jump to a label that hasn't yet been marked (jumping * forward) or to a label that has already been marked (jumping backward). Jump * unconditionally with {@link #jump jump(Label)} or conditionally based on a * comparison using {@link #compare compare()}. * *

Most methods should contain a return instruction. Void methods * should use {@link #returnVoid()}; non-void methods should use {@link * #returnValue returnValue()} with a local whose return type matches the * method's return type. Constructors are considered void methods and should * call {@link #returnVoid()}. Methods may make multiple returns. Methods * containing no return statements must either loop infinitely or throw * unconditionally; it is not legal to end a sequence of instructions without a * jump, return or throw. * *

Throwing and Catching

* This API uses labels to handle thrown exceptions, errors and throwables. Call * {@link #addCatchClause addCatchClause()} to register the target label and * throwable class. All statements that follow will jump to that catch clause if * they throw a {@link Throwable} assignable to that type. Use {@link * #removeCatchClause removeCatchClause()} to unregister the throwable class. * *

Throw an throwable by first assigning it to a local and then calling * {@link #throwValue throwValue()}. Control flow will jump to the nearest label * assigned to a type assignable to the thrown type. In this context, "nearest" * means the label requiring the fewest stack frames to be popped. * *

Calling methods

* A method's caller must know its return type, name, parameters, and invoke * kind. Lookup a method on a type using {@link TypeId#getMethod * TypeId.getMethod()}. This is more onerous than Java language invokes, which * can infer the target method using the target object and parameters. There are * four invoke kinds: *
    *
  • {@link #invokeStatic invokeStatic()} is used for static methods.
  • *
  • {@link #invokeDirect invokeDirect()} is used for private instance * methods and for constructors to call their superclass's * constructor.
  • *
  • {@link #invokeInterface invokeInterface()} is used to invoke a method * whose declaring type is an interface.
  • *
  • {@link #invokeVirtual invokeVirtual()} is used to invoke any other * method. The target must not be static, private, a constructor, or an * interface method.
  • *
  • {@link #invokeSuper invokeSuper()} is used to invoke the closest * superclass's virtual method. The target must not be static, private, * a constructor method, or an interface method.
  • *
  • {@link #newInstance newInstance()} is used to invoke a * constructor.
  • *
* All invoke methods take a local for the return value. For void methods this * local is unused and may be null. * *

Field Access

* Read static fields using {@link #sget sget()}; write them using {@link * #sput sput()}. For instance values you'll need to specify the declaring * instance; use {@link #getThis getThis()} in an instance method to use {@code * this}. Read instance values using {@link #iget iget()} and write them with * {@link #iput iput()}. * *

Array Access

* Allocate an array using {@link #newArray newArray()}. Read an array's length * with {@link #arrayLength arrayLength()} and its elements with {@link #aget * aget()}. Write an array's elements with {@link #aput aput()}. * *

Types

* Use {@link #cast cast()} to perform either a numeric cast or * a type cast. Interrogate the type of a value in a local * using {@link #instanceOfType instanceOfType()}. * *

Synchronization

* Acquire a monitor using {@link #monitorEnter monitorEnter()}; release it with * {@link #monitorExit monitorExit()}. It is the caller's responsibility to * guarantee that enter and exit calls are balanced, even in the presence of * exceptions thrown. * * Warning: Even if a method has the {@code synchronized} flag, * dex requires instructions to acquire and release monitors manually. A method * declared with {@link java.lang.reflect.Modifier#SYNCHRONIZED SYNCHRONIZED} * but without manual calls to {@code monitorEnter()} and {@code monitorExit()} * will not be synchronized when executed. */ public final class Code { private final MethodId method; /** * All allocated labels. Although the order of the labels in this list * shouldn't impact behavior, it is used to determine basic block indices. */ private final List




© 2015 - 2024 Weber Informatics LLC | Privacy Policy