Skip to content

Commit

Permalink
Merge pull request #174 from Ladicek/add-subtraction-division
Browse files Browse the repository at this point in the history
Add subtraction, division and remainder
  • Loading branch information
gsmet authored Jan 24, 2024
2 parents 39c7fc6 + e84f08f commit 4c9ccfa
Show file tree
Hide file tree
Showing 3 changed files with 178 additions and 9 deletions.
35 changes: 31 additions & 4 deletions src/main/java/io/quarkus/gizmo/BytecodeCreator.java
Original file line number Diff line number Diff line change
Expand Up @@ -1000,21 +1000,48 @@ default void breakScope() {
/**
* Adds the two result handles together and returns the result
*
* @param a1 The first number
* @param a2 The second number
* @param a1 The first number, aka the <em>augend</em>
* @param a2 The second number, aka the <em>addend</em>
* @return The result
*/
ResultHandle add(ResultHandle a1, ResultHandle a2);

/**
* Subtracts the second result handle from the first result and returns the result
*
* @param a1 The first number, aka the <em>minuend</em>
* @param a2 The second number, aka the <em>subtrahend</em>
* @return The result
*/
ResultHandle subtract(ResultHandle a1, ResultHandle a2);

/**
* Multiplies the two result handles together and returns the result
*
* @param a1 The first number
* @param a2 The second number
* @param a1 The first number, aka the <em>multiplier</em>
* @param a2 The second number, aka the <em>multiplicand</em>
* @return The result
*/
ResultHandle multiply(ResultHandle a1, ResultHandle a2);

/**
* Divides the first result handle by the second and returns the result
*
* @param a1 The first number, aka the <em>numerator</em>
* @param a2 The second number, aka the <em>denominator</em>
* @return The result
*/
ResultHandle divide(ResultHandle a1, ResultHandle a2);

/**
* Computes the remainder after division of the first result handle by the second and returns the result
*
* @param a1 The first number, aka the <em>numerator</em>
* @param a2 The second number, aka the <em>denominator</em>
* @return The result
*/
ResultHandle remainder(ResultHandle a1, ResultHandle a2);

/**
* Computes the bitwise AND of the two result handles and returns the result
*
Expand Down
15 changes: 15 additions & 0 deletions src/main/java/io/quarkus/gizmo/BytecodeCreatorImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -1441,11 +1441,26 @@ public ResultHandle add(ResultHandle a1, ResultHandle a2) {
return emitBinaryArithmetic(Opcodes.IADD, a1, a2);
}

@Override
public ResultHandle subtract(ResultHandle a1, ResultHandle a2) {
return emitBinaryArithmetic(Opcodes.ISUB, a1, a2);
}

@Override
public ResultHandle multiply(ResultHandle a1, ResultHandle a2) {
return emitBinaryArithmetic(Opcodes.IMUL, a1, a2);
}

@Override
public ResultHandle divide(ResultHandle a1, ResultHandle a2) {
return emitBinaryArithmetic(Opcodes.IDIV, a1, a2);
}

@Override
public ResultHandle remainder(ResultHandle a1, ResultHandle a2) {
return emitBinaryArithmetic(Opcodes.IREM, a1, a2);
}

@Override
public ResultHandle bitwiseAnd(ResultHandle a1, ResultHandle a2) {
return emitBinaryArithmetic(Opcodes.IAND, a1, a2);
Expand Down
137 changes: 132 additions & 5 deletions src/test/java/io/quarkus/gizmo/ArithmeticTestCase.java
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,38 @@ public void testAddition() throws Exception {
assertEquals(15.0, clazz.getMethod("addDoubles").invoke(null));
}

@Test
public void testSubtraction() throws Exception {
TestClassLoader cl = new TestClassLoader(getClass().getClassLoader());
try (ClassCreator creator = ClassCreator.builder().classOutput(cl).className("com.MyTest").build()) {
MethodCreator subInts = creator.getMethodCreator("subInts", Object.class).setModifiers(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC);
ResultHandle int1 = subInts.load(2);
ResultHandle int2 = subInts.load(1);
subInts.returnValue(subInts.subtract(int1, int2));

MethodCreator subLongs = creator.getMethodCreator("subLongs", Object.class).setModifiers(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC);
ResultHandle long1 = subLongs.load(5L);
ResultHandle long2 = subLongs.load(8L);
subLongs.returnValue(subLongs.subtract(long1, long2));

MethodCreator subFloats = creator.getMethodCreator("subFloats", Object.class).setModifiers(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC);
ResultHandle float1 = subFloats.load(3.0F);
ResultHandle float2 = subFloats.load(3.0F);
subFloats.returnValue(subFloats.subtract(float1, float2));

MethodCreator subDoubles = creator.getMethodCreator("subDoubles", Object.class).setModifiers(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC);
ResultHandle double1 = subDoubles.load(21.0);
ResultHandle double2 = subDoubles.load(6.0);
subDoubles.returnValue(subDoubles.subtract(double1, double2));
}

Class<?> clazz = cl.loadClass("com.MyTest");
assertEquals(1, clazz.getMethod("subInts").invoke(null));
assertEquals(-3L, clazz.getMethod("subLongs").invoke(null));
assertEquals(0.0F, clazz.getMethod("subFloats").invoke(null));
assertEquals(15.0, clazz.getMethod("subDoubles").invoke(null));
}

@Test
public void testMultiplication() throws Exception {
TestClassLoader cl = new TestClassLoader(getClass().getClassLoader());
Expand All @@ -70,19 +102,114 @@ public void testMultiplication() throws Exception {
multiplyLongs.returnValue(multiplyLongs.multiply(long1, long2));

MethodCreator multiplyFloats = creator.getMethodCreator("multiplyFloats", Object.class).setModifiers(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC);
ResultHandle float1 = multiplyLongs.load(6.0F);
ResultHandle float2 = multiplyLongs.load(7.0F);
ResultHandle float1 = multiplyFloats.load(6.0F);
ResultHandle float2 = multiplyFloats.load(7.0F);
multiplyFloats.returnValue(multiplyFloats.multiply(float1, float2));

MethodCreator multiplyDoubles = creator.getMethodCreator("multiplyDoubles", Object.class).setModifiers(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC);
ResultHandle double1 = multiplyLongs.load(8.0F);
ResultHandle double2 = multiplyLongs.load(9.0F);
ResultHandle double1 = multiplyDoubles.load(8.0D);
ResultHandle double2 = multiplyDoubles.load(9.0D);
multiplyDoubles.returnValue(multiplyDoubles.multiply(double1, double2));
}

Class<?> clazz = cl.loadClass("com.MyTest");
assertEquals(6, clazz.getMethod("multiplyInts").invoke(null));
assertEquals(20L, clazz.getMethod("multiplyLongs").invoke(null));
assertEquals(42.0F, clazz.getMethod("multiplyFloats").invoke(null));
assertEquals(72.0F, clazz.getMethod("multiplyDoubles").invoke(null));
assertEquals(72.0D, clazz.getMethod("multiplyDoubles").invoke(null));
}

@Test
public void testDivision() throws Exception {
TestClassLoader cl = new TestClassLoader(getClass().getClassLoader());
try (ClassCreator creator = ClassCreator.builder().classOutput(cl).className("com.MyTest").build()) {
MethodCreator divideInts = creator.getMethodCreator("divideInts", Object.class).setModifiers(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC);
ResultHandle int1 = divideInts.load(2);
ResultHandle int2 = divideInts.load(3);
divideInts.returnValue(divideInts.divide(int1, int2));

MethodCreator divideIntsImproper = creator.getMethodCreator("divideIntsImproper", Object.class).setModifiers(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC);
ResultHandle int1imp = divideIntsImproper.load(18);
ResultHandle int2imp = divideIntsImproper.load(5);
divideIntsImproper.returnValue(divideIntsImproper.divide(int1imp, int2imp));

MethodCreator divideLongs = creator.getMethodCreator("divideLongs", Object.class).setModifiers(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC);
ResultHandle long1 = divideLongs.load(5L);
ResultHandle long2 = divideLongs.load(4L);
divideLongs.returnValue(divideLongs.divide(long1, long2));

MethodCreator divideFloats = creator.getMethodCreator("divideFloats", Object.class).setModifiers(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC);
ResultHandle float1 = divideFloats.load(6.0F);
ResultHandle float2 = divideFloats.load(7.0F);
divideFloats.returnValue(divideFloats.divide(float1, float2));

MethodCreator divideDoubles = creator.getMethodCreator("divideDoubles", Object.class).setModifiers(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC);
ResultHandle double1 = divideDoubles.load(8.0D);
ResultHandle double2 = divideDoubles.load(9.0D);
divideDoubles.returnValue(divideDoubles.divide(double1, double2));
}

Class<?> clazz = cl.loadClass("com.MyTest");
assertEquals(0, clazz.getMethod("divideInts").invoke(null));
assertEquals(3, clazz.getMethod("divideIntsImproper").invoke(null));
assertEquals(1L, clazz.getMethod("divideLongs").invoke(null));
assertEquals(0.85714287F, clazz.getMethod("divideFloats").invoke(null));
assertEquals(0.8888888888888888D, clazz.getMethod("divideDoubles").invoke(null));
}

@Test
public void testRemainder() throws Exception {
TestClassLoader cl = new TestClassLoader(getClass().getClassLoader());
try (ClassCreator creator = ClassCreator.builder().classOutput(cl).className("com.MyTest").build()) {
MethodCreator remainderInts = creator.getMethodCreator("remainderInts", Object.class).setModifiers(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC);
ResultHandle int1 = remainderInts.load(2);
ResultHandle int2 = remainderInts.load(3);
remainderInts.returnValue(remainderInts.remainder(int1, int2));

MethodCreator remainderIntsImproper = creator.getMethodCreator("remainderIntsImproper", Object.class).setModifiers(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC);
ResultHandle int1imp = remainderIntsImproper.load(17);
ResultHandle int2imp = remainderIntsImproper.load(5);
remainderIntsImproper.returnValue(remainderIntsImproper.remainder(int1imp, int2imp));

MethodCreator remainderLongs = creator.getMethodCreator("remainderLongs", Object.class).setModifiers(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC);
ResultHandle long1 = remainderLongs.load(6L);
ResultHandle long2 = remainderLongs.load(4L);
remainderLongs.returnValue(remainderLongs.remainder(long1, long2));

MethodCreator remainderLongsNegative = creator.getMethodCreator("remainderLongsNegative", Object.class).setModifiers(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC);
ResultHandle long1Negative = remainderLongsNegative.load(-7L);
ResultHandle long2Negative = remainderLongsNegative.load(4L);
remainderLongsNegative.returnValue(remainderLongsNegative.remainder(long1Negative, long2Negative));

MethodCreator remainderFloats = creator.getMethodCreator("remainderFloats", Object.class).setModifiers(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC);
ResultHandle float1 = remainderFloats.load(12.0F);
ResultHandle float2 = remainderFloats.load(7.0F);
remainderFloats.returnValue(remainderFloats.remainder(float1, float2));

MethodCreator remainderFloatsNegative = creator.getMethodCreator("remainderFloatsNegative", Object.class).setModifiers(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC);
ResultHandle float1Negative = remainderFloatsNegative.load(8.0F);
ResultHandle float2Negative = remainderFloatsNegative.load(-3.0F);
remainderFloatsNegative.returnValue(remainderFloatsNegative.remainder(float1Negative, float2Negative));

MethodCreator remainderDoubles = creator.getMethodCreator("remainderDoubles", Object.class).setModifiers(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC);
ResultHandle double1 = remainderDoubles.load(10.0D);
ResultHandle double2 = remainderDoubles.load(8.0D);
remainderDoubles.returnValue(remainderDoubles.remainder(double1, double2));

MethodCreator remainderDoublesNegative = creator.getMethodCreator("remainderDoublesNegative", Object.class).setModifiers(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC);
ResultHandle double1Negative = remainderDoublesNegative.load(-13.0D);
ResultHandle double2Negative = remainderDoublesNegative.load(-5.0D);
remainderDoublesNegative.returnValue(remainderDoublesNegative.remainder(double1Negative, double2Negative));
}

Class<?> clazz = cl.loadClass("com.MyTest");
assertEquals(2, clazz.getMethod("remainderInts").invoke(null));
assertEquals(2, clazz.getMethod("remainderIntsImproper").invoke(null));
assertEquals(2L, clazz.getMethod("remainderLongs").invoke(null));
assertEquals(-3L, clazz.getMethod("remainderLongsNegative").invoke(null));
assertEquals(5.0F, clazz.getMethod("remainderFloats").invoke(null));
assertEquals(2.0F, clazz.getMethod("remainderFloatsNegative").invoke(null));
assertEquals(2.0, clazz.getMethod("remainderDoubles").invoke(null));
assertEquals(-3.0, clazz.getMethod("remainderDoublesNegative").invoke(null));
}
}

0 comments on commit 4c9ccfa

Please sign in to comment.