Skip to content

Commit

Permalink
Fix conversions
Browse files Browse the repository at this point in the history
  • Loading branch information
zhanhb committed Nov 9, 2017
1 parent a874103 commit cd16a10
Show file tree
Hide file tree
Showing 10 changed files with 189 additions and 39 deletions.
8 changes: 4 additions & 4 deletions src/main/java/jnr/ffi/Struct.java
Original file line number Diff line number Diff line change
Expand Up @@ -783,7 +783,7 @@ public Boolean() {
}

public final boolean get() {
return (getMemory().getByte(offset()) & 0x1) != 0;
return getMemory().getByte(offset()) != 0;
}

public final void set(boolean value) {
Expand All @@ -800,7 +800,7 @@ public WBOOL() {
}

public final boolean get() {
return (getMemory().getInt(offset()) & 0x1) != 0;
return getMemory().getInt(offset()) != 0;
}

public final void set(boolean value) {
Expand All @@ -814,7 +814,7 @@ public BOOL16() {
}

public final boolean get() {
return (getMemory().getShort(offset()) & 0x1) != 0;
return getMemory().getShort(offset()) != 0;
}

public final void set(boolean value) {
Expand Down Expand Up @@ -1657,7 +1657,7 @@ public UnsignedLong(Offset offset) {
*/
public final long get() {
long value = getMemory().getNativeLong(offset());
final long mask = getRuntime().findType(NativeType.SLONG).size() == 32 ? 0xffffffffL : 0xffffffffffffffffL;
final long mask = getRuntime().findType(NativeType.SLONG).size() == 4 ? 0xffffffffL : 0xffffffffffffffffL;
return value < 0
? (long) ((value & mask) + mask + 1)
: value;
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/jnr/ffi/StructLayout.java
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,7 @@ protected Boolean(Offset offset) {
}

public final boolean get(jnr.ffi.Pointer ptr) {
return (ptr.getByte(offset()) & 0x1) != 0;
return ptr.getByte(offset()) != 0;
}

public final void set(jnr.ffi.Pointer ptr, boolean value) {
Expand All @@ -333,7 +333,7 @@ protected WBOOL(Offset offset) {
}

public final boolean get(jnr.ffi.Pointer ptr) {
return (ptr.getInt(offset()) & 0x1) != 0;
return ptr.getInt(offset()) != 0;
}

public final void set(jnr.ffi.Pointer ptr, boolean value) {
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/jnr/ffi/byref/NumberByReference.java
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ public void fromNative(Runtime runtime, Pointer memory, long offset) {

case SLONG:
case ULONG:
value = memory.getLong(offset);
value = memory.getNativeLong(offset);
break;

case SLONGLONG:
Expand Down Expand Up @@ -146,7 +146,7 @@ public void toNative(Runtime runtime, Pointer memory, long offset) {

case SLONG:
case ULONG:
memory.putLong(offset, value.longValue());
memory.putNativeLong(offset, value.longValue());
break;

case SLONGLONG:
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/jnr/ffi/provider/jffi/AsmLibraryLoader.java
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,7 @@ private void generateVarargsInvocation(AsmBuilder builder, Method m, ObjectField
mv.iload(slot);
mv.i2b();
mv.invokestatic(Byte.class, "valueOf", Byte.class, byte.class);
} else if (parameterTypes[i].equals(char.class)) {
} else if (parameterTypes[i].equals(boolean.class)) {
mv.iload(slot);
mv.i2b();
mv.invokestatic(Boolean.class, "valueOf", Boolean.class, boolean.class);
Expand Down
11 changes: 10 additions & 1 deletion src/main/java/jnr/ffi/provider/jffi/AsmUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,9 @@ public static Class unboxedType(Class boxedType) {
} else if (boxedType == Short.class) {
return short.class;

} else if (boxedType == Character.class) {
return char.class;

} else if (boxedType == Integer.class) {
return int.class;

Expand Down Expand Up @@ -134,6 +137,8 @@ public static Class boxedType(Class type) {
return Byte.class;
} else if (type == short.class) {
return Short.class;
} else if (type == char.class) {
return Character.class;
} else if (type == int.class) {
return Integer.class;
} else if (type == long.class) {
Expand Down Expand Up @@ -341,7 +346,11 @@ static void boxValue(AsmBuilder builder, SkinnyMethodAdapter mv, Class boxedType
} else if (Address.class == boxedType) {
mv.invokestatic(boxedType, "valueOf", boxedType, unboxedType);

} else if (Number.class.isAssignableFrom(boxedType) && boxedType(unboxedType) == boxedType) {
} else if (Number.class.isAssignableFrom(boxedType) && boxedType(unboxedType) == boxedType) {
mv.invokestatic(boxedType, "valueOf", boxedType, unboxedType);

} else if (Character.class == boxedType) {
convertPrimitive(mv, unboxedType, char.class);
mv.invokestatic(boxedType, "valueOf", boxedType, unboxedType);

} else {
Expand Down
27 changes: 25 additions & 2 deletions src/main/java/jnr/ffi/provider/jffi/DefaultInvokerFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,9 @@ private static FunctionInvoker getFunctionInvoker(ResultType resultType) {
} else if (Boolean.class.isAssignableFrom(returnType) || boolean.class == returnType) {
return BooleanInvoker.INSTANCE;

} else if (Character.class.isAssignableFrom(returnType) || char.class == returnType) {
return CharacterInvoker.INSTANCE;

} else if (Number.class.isAssignableFrom(returnType) || returnType.isPrimitive()) {
return new ConvertingInvoker(getNumberResultConverter(resultType), null,
new ConvertingInvoker(getNumberDataConverter(resultType.getNativeType()), null, getNumberFunctionInvoker(resultType.getNativeType())));
Expand Down Expand Up @@ -241,6 +244,9 @@ static Marshaller getMarshaller(Class type, NativeType nativeType, Collection<An
} else if (Boolean.class.isAssignableFrom(type) || boolean.class == type) {
return BooleanMarshaller.INSTANCE;

} else if (Character.class.isAssignableFrom(type) || char.class == type) {
return CharacterMarshaller.INSTANCE;

} else if (Pointer.class.isAssignableFrom(type)) {
return new PointerMarshaller(annotations);

Expand Down Expand Up @@ -506,10 +512,20 @@ public final Object invoke(Runtime runtime, Function function, HeapInvocationBuf
static class BooleanInvoker extends BaseInvoker {
static FunctionInvoker INSTANCE = new BooleanInvoker();
public final Object invoke(Runtime runtime, Function function, HeapInvocationBuffer buffer) {
if (function.getReturnType().size() == 8) {
return invoker.invokeLong(function, buffer) != 0;
}
return invoker.invokeInt(function, buffer) != 0;
}
}

static class CharacterInvoker extends BaseInvoker {
static FunctionInvoker INSTANCE = new CharacterInvoker();
public final Object invoke(Runtime runtime, Function function, HeapInvocationBuffer buffer) {
return (char) invoker.invokeInt(function, buffer);
}
}

static class IntInvoker extends BaseInvoker {
static final FunctionInvoker INSTANCE = new IntInvoker();
public final Object invoke(Runtime runtime, Function function, HeapInvocationBuffer buffer) {
Expand Down Expand Up @@ -552,6 +568,13 @@ public void marshal(InvocationSession session, HeapInvocationBuffer buffer, Obje
}
}

static class CharacterMarshaller implements Marshaller {
static final CharacterMarshaller INSTANCE = new CharacterMarshaller();
public void marshal(InvocationSession session, HeapInvocationBuffer buffer, Object parameter) {
buffer.putInt(((Character) parameter).charValue());
}
}

static class Int8Marshaller implements Marshaller {
private final ToNativeConverter<Number, Number> toNativeConverter;

Expand Down Expand Up @@ -767,7 +790,7 @@ public Number fromNative(Number nativeValue, FromNativeContext context) {

@Override
public Number toNative(Number value, ToNativeContext context) {
return value.intValue() & 0xffff;
return value.byteValue() & 0xff;
}
}

Expand Down Expand Up @@ -868,7 +891,7 @@ static final class BooleanConverter implements DataConverter<Boolean, Number> {
static final DataConverter<Boolean, Number> INSTANCE = new BooleanConverter();
@Override
public Boolean fromNative(Number nativeValue, FromNativeContext context) {
return (nativeValue.intValue() & 0x1) != 0;
return nativeValue.longValue() != 0;
}

@Override
Expand Down
106 changes: 90 additions & 16 deletions src/main/java/jnr/ffi/provider/jffi/NumberUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

import jnr.ffi.NativeType;
import jnr.ffi.provider.SigType;
import org.objectweb.asm.Label;

public final class NumberUtil {
private NumberUtil() {}
Expand Down Expand Up @@ -107,11 +108,18 @@ public static void widen(SkinnyMethodAdapter mv, Class from, Class to) {

} else if (boolean.class == to && boolean.class != from && isPrimitiveInt(from)) {
// Ensure only 0x0 and 0x1 values are used for boolean
Label zero = new Label();
Label ret = new Label();
mv.ifeq(zero);
mv.iconst_1();
mv.iand();
mv.go_to(ret);
mv.label(zero);
mv.iconst_0();
mv.label(ret);
}
}

@SuppressWarnings("unused")
public static void widen(SkinnyMethodAdapter mv, Class from, Class to, NativeType nativeType) {
if (isPrimitiveInt(from)) {
if (nativeType == NativeType.UCHAR) {
Expand Down Expand Up @@ -144,23 +152,36 @@ public static void widen(SkinnyMethodAdapter mv, Class from, Class to, NativeTyp
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) {
mv.l2i();
}

if (byte.class == to) {
mv.i2b();
if (boolean.class == to) {
if (long.class == from) {
mv.lconst_0();
mv.lcmp();
}
/* Equivalent to
return result == 0 ? true : false;
*/
Label zero = new Label();
Label ret = new Label();
mv.ifeq(zero);
mv.iconst_1();
mv.go_to(ret);
mv.label(zero);
mv.iconst_0();
mv.label(ret);
} else {
if (long.class == from) {
mv.l2i();
}

} else if (short.class == to) {
mv.i2s();
if (byte.class == to) {
mv.i2b();

} else if (char.class == to) {
mv.i2c();
} else if (short.class == to) {
mv.i2s();

} else if (boolean.class == to) {
// Ensure only 0x0 and 0x1 values are used for boolean
mv.iconst_1();
mv.iand();
} else if (char.class == to) {
mv.i2c();
}
}
}
}
Expand All @@ -175,37 +196,85 @@ public static void convertPrimitive(SkinnyMethodAdapter mv, final Class from, fi

public static void convertPrimitive(SkinnyMethodAdapter mv, final Class from, final Class to, final NativeType nativeType) {
if (boolean.class == to) {
narrow(mv, from, to);
switch (nativeType) {
case SCHAR:
case UCHAR:
case SSHORT:
case USHORT:
case SINT:
case UINT:
case SLONG:
case ULONG:
case ADDRESS:
if (sizeof(nativeType) <= 4) {
narrow(mv, from, int.class);
switch (nativeType) {
// some compiler may not clean higher bits
// https://en.wikipedia.org/wiki/X86_calling_conventions#Microsoft_x64_calling_convention
// Parameters less than 64 bits long are not zero extended; the high bits are not zeroed.
// such as we can still get 0x80000000 from `u_int32_t2u_int8_t(0x80000000)`
case SCHAR:
case UCHAR:
narrow(mv, int.class, byte.class);
break;
case USHORT:
case SSHORT:
narrow(mv, int.class, short.class);
break;
}
narrow(mv, int.class, to);
} else {
narrow(mv, from, to);
}
break;
case FLOAT:
case DOUBLE:
// TODO
break;
default:
narrow(mv, from, to);
break;
}
return;
}

switch (nativeType) {
case SCHAR:
narrow(mv, from, byte.class);
// maybe to is char.class
narrow(mv, byte.class, to);
widen(mv, byte.class, to);
break;

case SSHORT:
narrow(mv, from, short.class);
// `to` may be byte.class
narrow(mv, short.class, to);
widen(mv, short.class, to);
break;

case SINT:
narrow(mv, from, int.class);
// `to` may be byte.class
narrow(mv, int.class, to);
widen(mv, int.class, to);
break;

case UCHAR:
narrow(mv, from, int.class);
mv.pushInt(0xff);
mv.iand();
// `to` may be byte.class
narrow(mv, int.class, to);
widen(mv, int.class, to);
break;

case USHORT:
narrow(mv, from, int.class);
mv.pushInt(0xffff);
mv.iand();
// `to` may be byte.class
narrow(mv, int.class, to);
widen(mv, int.class, to);
break;

Expand All @@ -219,8 +288,13 @@ public static void convertPrimitive(SkinnyMethodAdapter mv, final Class from, fi
// strip off bits 32:63
mv.ldc(0xffffffffL);
mv.land();
} else {
// `to` may be byte.class
narrow(mv, int.class, to);
}
} else {
// `to` may be byte.class
narrow(mv, from, to);
widen(mv, from, to);
}
break;
Expand Down
3 changes: 3 additions & 0 deletions src/main/java/jnr/ffi/provider/jffi/Types.java
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,9 @@ static Type lookupType(jnr.ffi.Runtime runtime, Class type, Collection<Annotatio
} else if (Short.class.isAssignableFrom(type) || short.class == type) {
return runtime.findType(NativeType.SSHORT);

} else if (Character.class.isAssignableFrom(type) || char.class == type) {
return runtime.findType(NativeType.USHORT);

} else if (Integer.class.isAssignableFrom(type) || int.class == type) {
return runtime.findType(NativeType.SINT);

Expand Down
Loading

0 comments on commit cd16a10

Please sign in to comment.