diff --git a/src/main/java/jnr/ffi/provider/jffi/NumberUtil.java b/src/main/java/jnr/ffi/provider/jffi/NumberUtil.java index 3ca02c51c..c971442fc 100644 --- a/src/main/java/jnr/ffi/provider/jffi/NumberUtil.java +++ b/src/main/java/jnr/ffi/provider/jffi/NumberUtil.java @@ -20,6 +20,7 @@ import jnr.ffi.NativeType; import jnr.ffi.provider.SigType; +import org.objectweb.asm.Label; public final class NumberUtil { private NumberUtil() {} @@ -145,6 +146,22 @@ public static void narrow(SkinnyMethodAdapter mv, Class from, Class to) { if (!from.equals(to)) { if (byte.class == to || short.class == to || char.class == to || int.class == to || boolean.class == to) { if (long.class == from) { + // long x = 0x100000000LL; + // boolean b = x != 0; + // IMO, return false only if the long is zero. + if (boolean.class == to) { + mv.lconst_0(); + mv.lcmp(); + Label a = new Label(); + mv.ifeq(a); + mv.iconst_1(); + Label b = new Label(); + mv.go_to(b); + mv.label(a); + mv.iconst_0(); + mv.label(b); + return; + } mv.l2i(); } @@ -159,8 +176,14 @@ public static void narrow(SkinnyMethodAdapter mv, Class from, Class to) { } else if (boolean.class == to) { // Ensure only 0x0 and 0x1 values are used for boolean + Label l0 = new Label(); + mv.ifeq(l0); mv.iconst_1(); - mv.iand(); + Label l1 = new Label(); + mv.go_to(l1); + mv.label(l0); + mv.iconst_0(); + mv.label(l1); } } } diff --git a/src/test/java/jnr/ffi/NumberTest.java b/src/test/java/jnr/ffi/NumberTest.java index 10f1c506f..3d6e17804 100644 --- a/src/test/java/jnr/ffi/NumberTest.java +++ b/src/test/java/jnr/ffi/NumberTest.java @@ -21,6 +21,7 @@ import java.util.Random; import jnr.ffi.annotations.LongLong; +import jnr.ffi.provider.jffi.NoX86; import jnr.ffi.types.*; import org.junit.After; import org.junit.AfterClass; @@ -73,10 +74,18 @@ public static interface TestBoolean { } static TestBoolean testboolean; + @NoX86 + public static interface TestBooleanNoX86 { + public @int32_t boolean ret_int32_t(@int32_t int l); + public @int64_t boolean ret_int64_t(@int64_t long l); + } + static TestBooleanNoX86 testBooleanNoX86; + @BeforeClass public static void setUpClass() throws Exception { testlib = TstUtil.loadTestLib(TestLib.class); testboolean = TstUtil.loadTestLib(TestBoolean.class); + testBooleanNoX86 = TstUtil.loadTestLib(TestBooleanNoX86.class); } @AfterClass @@ -357,4 +366,21 @@ public long n(long i1, long i2) { assertEquals(true, testboolean.ret_int32_t(1)); assertEquals(true, testboolean.ret_int32_t(2)); } + + @Test public void testBooleanFromIntNoX86() { + for (int i = -3; i <= 3; ++i) { + boolean expectResult = i != 0; + assertEquals("expect to boolean from '" + i + "'", expectResult, testBooleanNoX86.ret_int32_t(i)); + } + } + + @Test public void testBooleanFromLongNoX86() { + for (long i = -3; i <= 3; ++i) { + boolean expectResult = i != 0; + assertEquals("expect to boolean from '" + i + "'", expectResult, testBooleanNoX86.ret_int64_t(i)); + } + long x = 0x100000000L; + assertEquals("expect to boolean from '" + x + "'", true, testBooleanNoX86.ret_int64_t(x)); + } + }