diff options
author | Jesse Wilson <jessewilson@google.com> | 2012-01-09 09:53:37 -0500 |
---|---|---|
committer | Jesse Wilson <jessewilson@google.com> | 2012-01-09 09:53:37 -0500 |
commit | d6c77efc0b187577dd7956070adfc7c335f65698 (patch) | |
tree | 0cbf49ff0b9627426f23e7897688ffcd7b449f0e | |
parent | 97b0be6b3da9df87e9026f880b0b0bffc7242450 (diff) | |
download | dexmaker-d6c77efc0b187577dd7956070adfc7c335f65698.tar.gz |
More documentation. Rename compare ops.
-rw-r--r-- | src/main/java/com/google/dexmaker/Code.java | 107 | ||||
-rw-r--r-- | src/main/java/com/google/dexmaker/Comparison.java | 12 | ||||
-rw-r--r-- | src/main/java/com/google/dexmaker/UnaryOp.java | 4 | ||||
-rw-r--r-- | src/test/java/com/google/dexmaker/DexMakerTest.java | 8 |
4 files changed, 98 insertions, 33 deletions
diff --git a/src/main/java/com/google/dexmaker/Code.java b/src/main/java/com/google/dexmaker/Code.java index b6f6b0b..0ddbf1c 100644 --- a/src/main/java/com/google/dexmaker/Code.java +++ b/src/main/java/com/google/dexmaker/Code.java @@ -42,23 +42,84 @@ import java.util.List; /** * Builds a sequence of instructions. + * + * <h3>Locals</h3> + * All data manipulation takes place in local variables. Each parameter gets its + * own local by default; access these using {@link #getParameter}. Non-static + * methods and constructors also have a {@code this} parameter; it's available + * as {@link #getThis}. Allocate a new local variable using {@link #newLocal}, + * and assign a default value to it with {@link #loadConstant}. 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. + * + * <h3>Math and Bit Operations</h3> + * Transform a single value into another related value using {@link + * #op(UnaryOp,Local,Local)}. Transform two values into a third value using + * {@link #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. + * + * <h3>Compare</h3> + * There are three different comparison operations each with different + * constraints: + * <ul> + * <li>{@link #compareLongs(Local,Local,Local)} 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.</li> + * <li>{@link #compareFloatingPoint(Local,Local,Local,int)} 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. + * <li>{@link #compare(Comparison,Label,Local,Local)} 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. + * </ul> + * 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. + * + * <h3>Branches and Labels</h3> + * All control flow is created with branches and labels. */ -/* - * TODO: documentation: - * UnaryOp, BinaryOp - * Try/catch - * Arrays - * Comparisons - * Locals - * Fields - * Type: Instanceof, cast - * Invoke - * Jump - * Constants - * NewInstance - * Return +/* TDODO: document these below + * + * new Label() + * jump() + * mark() + * return() * - * TODO: rename compareOps + * <h3>Try/Catch blocks</h3> + * addCatchClause() + * removeCatchClause() + * + * <h3>Invoke</h3> + * invokeXxx + * newInstance() + * + * <h3>Fields</h3> + * iget() + * iput() + * sget() + * sput() + * + * <h3>Arrays</h3> + * aget() + * aput() + * arrayLength() + * newArray() + * + * <h3>Types and Casts</h3> + * cast() + * instanceOfType() */ public final class Code { private final MethodId<?, ?> method; @@ -338,15 +399,13 @@ public final class Code { } } - // instructions: unary + // instructions: unary and binary public <T> void op(UnaryOp op, Local<T> target, Local<T> source) { addInstruction(new PlainInsn(op.rop(source.type), sourcePosition, target.spec(), source.spec())); } - // instructions: binary - public <T> void op(BinaryOp op, Local<T> target, Local<T> a, Local<T> b) { Rop rop = op.rop(StdTypeList.make(a.type.ropType, b.type.ropType)); RegisterSpecList sources = RegisterSpecList.make(a.spec(), b.spec()); @@ -362,11 +421,13 @@ public final class Code { // instructions: branches /** - * Compare ints. If the comparison is true, execution jumps to {@code - * trueLabel}. If it is false, execution continues to the next instruction. + * Compare ints or references. If the comparison is true, execution jumps to + * {@code trueLabel}. If it is false, execution continues to the next + * instruction. */ public <T> void compare(Comparison comparison, Label trueLabel, Local<T> a, Local<T> b) { adopt(trueLabel); + // TODO: ops to compare with zero/null: just omit the 2nd local in StdTypeList.make() Rop rop = comparison.rop(StdTypeList.make(a.type.ropType, b.type.ropType)); addInstruction(new PlainInsn(rop, sourcePosition, null, RegisterSpecList.make(a.spec(), b.spec())), trueLabel); @@ -375,8 +436,8 @@ public final class Code { /** * Compare floats or doubles. */ - public <T extends Number> void compare(Local<Integer> target, Local<T> a, Local<T> b, - int nanValue) { + public <T extends Number> void compareFloatingPoint( + Local<Integer> target, Local<T> a, Local<T> b, int nanValue) { Rop rop; if (nanValue == 1) { rop = Rops.opCmpg(a.type.ropType); @@ -392,7 +453,7 @@ public final class Code { /** * Compare longs. */ - public <T> void compare(Local<?> target, Local<T> a, Local<T> b) { + public void compareLongs(Local<Integer> target, Local<Long> a, Local<Long> b) { addInstruction(new PlainInsn(Rops.CMPL_LONG, sourcePosition, target.spec(), RegisterSpecList.make(a.spec(), b.spec()))); } diff --git a/src/main/java/com/google/dexmaker/Comparison.java b/src/main/java/com/google/dexmaker/Comparison.java index 4a6b649..06e3ca3 100644 --- a/src/main/java/com/google/dexmaker/Comparison.java +++ b/src/main/java/com/google/dexmaker/Comparison.java @@ -25,42 +25,42 @@ import com.android.dx.rop.type.TypeList; */ public enum Comparison { - /** {@code a < b} */ + /** {@code a < b}. Supports int only. */ LT() { @Override Rop rop(TypeList types) { return Rops.opIfLt(types); } }, - /** {@code a <= b} */ + /** {@code a <= b}. Supports int only. */ LE() { @Override Rop rop(TypeList types) { return Rops.opIfLe(types); } }, - /** {@code a == b} */ + /** {@code a == b}. Supports int and reference types. */ EQ() { @Override Rop rop(TypeList types) { return Rops.opIfEq(types); } }, - /** {@code a >= b} */ + /** {@code a >= b}. Supports int only. */ GE() { @Override Rop rop(TypeList types) { return Rops.opIfGe(types); } }, - /** {@code a > b} */ + /** {@code a > b}. Supports int only. */ GT() { @Override Rop rop(TypeList types) { return Rops.opIfGt(types); } }, - /** {@code a != b} */ + /** {@code a != b}. Supports int and reference types. */ NE() { @Override Rop rop(TypeList types) { return Rops.opIfNe(types); diff --git a/src/main/java/com/google/dexmaker/UnaryOp.java b/src/main/java/com/google/dexmaker/UnaryOp.java index 9d6f32e..cf565bb 100644 --- a/src/main/java/com/google/dexmaker/UnaryOp.java +++ b/src/main/java/com/google/dexmaker/UnaryOp.java @@ -24,14 +24,14 @@ import com.android.dx.rop.code.Rops; */ public enum UnaryOp { - /** {@code ~a}. Supports int or long. */ + /** {@code ~a}. Supports int and long. */ NOT() { @Override Rop rop(TypeId<?> type) { return Rops.opNot(type.ropType); } }, - /** {@code -a}. Supports int, long, float or double. */ + /** {@code -a}. Supports int, long, float and double. */ NEGATE() { @Override Rop rop(TypeId<?> type) { return Rops.opNeg(type.ropType); diff --git a/src/test/java/com/google/dexmaker/DexMakerTest.java b/src/test/java/com/google/dexmaker/DexMakerTest.java index f46fa7f..2c65503 100644 --- a/src/test/java/com/google/dexmaker/DexMakerTest.java +++ b/src/test/java/com/google/dexmaker/DexMakerTest.java @@ -1467,7 +1467,7 @@ public final class DexMakerTest extends TestCase { Local<T> localA = code.getParameter(0, valueType); Local<T> localB = code.getParameter(1, valueType); Local<Integer> localResult = code.newLocal(TypeId.INT); - code.compare(localResult, localA, localB, nanValue); + code.compareFloatingPoint(localResult, localA, localB, nanValue); code.returnValue(localResult); return getMethod(); } @@ -1484,7 +1484,7 @@ public final class DexMakerTest extends TestCase { Local<Long> localA = code.getParameter(0, TypeId.LONG); Local<Long> localB = code.getParameter(1, TypeId.LONG); Local<Integer> localResult = code.newLocal(TypeId.INT); - code.compare(localResult, localA, localB); + code.compareLongs(localResult, localA, localB); code.returnValue(localResult); Method method = getMethod(); @@ -1650,6 +1650,10 @@ public final class DexMakerTest extends TestCase { // TODO: synchronized or declared synchronized? + // TODO: get a thrown exception 'e' into a local + + // TODO: move a primitive or reference + private void addDefaultConstructor() { Code code = dexMaker.declareConstructor(GENERATED.getConstructor(), PUBLIC); Local<?> thisRef = code.getThis(GENERATED); |