| CODENOTIFIER | HelpYou are not signed inSign in |
Project: JNA
Revision: 683
Author: twalljava
Date: 04 Sep 2008 11:04:34
Changes:merge win64 branch
Files:| ... | ...@@ -24,6 +24,10 @@ | |
| 24 | 24 | |
| 25 | 25 | public class LibraryLoadTest extends TestCase { |
| 26 | 26 | |
| 27 | private static final String BUILDDIR = | |
| 28 | System.getProperty("jna.builddir", "build" | |
| 29 | + (Native.POINTER_SIZE == 8 ? "-d64" : "")); | |
| 30 | ||
| 27 | 31 | public void testLoadJNALibrary() { |
| 28 | 32 | assertTrue("Point size should never be zero", Pointer.SIZE > 0); |
| 29 | 33 | } |
| ... | ...@@ -81,15 +85,10 @@ | |
| 81 | 85 | } |
| 82 | 86 | } |
| 83 | 87 | |
| 84 | /** System property name (set by Ant) when running with 64-bit JVM. */ | |
| 85 | static final String DIR_BUILD_SUFFIX = "dir.build.suffix"; | |
| 86 | ||
| 87 | 88 | public void testLoadLibraryWithUnicodeName() throws Exception { |
| 88 | 89 | String tmp = System.getProperty("java.io.tmpdir"); |
| 89 | 90 | String libName = System.mapLibraryName("jnidispatch"); |
| 90 | // use "build-d64" for 64-bit jvm's | |
| 91 | File src = new File("build" + System.getProperty(DIR_BUILD_SUFFIX, "") | |
| 92 | + "/native", libName); | |
| 91 | File src = new File(BUILDDIR + "/native", libName); | |
| 93 | 92 | String newLibName = UNICODE; |
| 94 | 93 | if (libName.startsWith("lib")) |
| 95 | 94 | newLibName = "lib" + newLibName; |
| ... | ...@@ -67,11 +67,6 @@ | |
| 67 | 67 | SimpleStructure returnStaticTestStructure(); |
| 68 | 68 | SimpleStructure returnNullTestStructure(); |
| 69 | 69 | TestStructure.ByValue returnStructureByValue(); |
| 70 | public interface Int32Callback extends Callback { | |
| 71 | public int callback(int arg); | |
| 72 | } | |
| 73 | Int32Callback returnCallback(); | |
| 74 | Int32Callback returnCallbackArgument(Int32Callback cb); | |
| 75 | 70 | } |
| 76 | 71 | |
| 77 | 72 | TestLibrary lib; |
| ... | ...@@ -194,22 +189,6 @@ | |
| 194 | 189 | assertNull("Expect null structure return", s); |
| 195 | 190 | } |
| 196 | 191 | |
| 197 | public void testInvokeCallback() { | |
| 198 | TestLibrary.Int32Callback cb = lib.returnCallback(); | |
| 199 | assertNotNull("Callback should not be null", cb); | |
| 200 | assertEquals("Callback should be callable", 1, cb.callback(1)); | |
| 201 | ||
| 202 | TestLibrary.Int32Callback cb2 = new TestLibrary.Int32Callback() { | |
| 203 | public int callback(int arg) { | |
| 204 | return 0; | |
| 205 | } | |
| 206 | }; | |
| 207 | assertSame("Java callback should be looked up", | |
| 208 | cb2, lib.returnCallbackArgument(cb2)); | |
| 209 | assertSame("Existing native function wrapper should be reused", | |
| 210 | cb, lib.returnCallbackArgument(cb)); | |
| 211 | } | |
| 212 | ||
| 213 | 192 | public void testReturnStructureByValue() { |
| 214 | 193 | TestStructure s = lib.returnStructureByValue(); |
| 215 | 194 | assertNotNull("Returned structure must not be null", s); |
| ... | ...@@ -0,0 +1,52 @@ | |
| 1 | #!/bin/sh | |
| 2 | # | |
| 3 | # ld-compatible wrapper for link.exe | |
| 4 | # | |
| 5 | #args="/pdbtype:sept" | |
| 6 | MSVC="/c/Program Files (x86)/Microsoft Visual Studio 9.0/vc/bin" | |
| 7 | args="/nologo /opt:REF /incremental:no /subsystem:console /nodefaultlib:msvcrtd" | |
| 8 | link="$MSVC/link" | |
| 9 | while [ $# -gt 0 ] | |
| 10 | do | |
| 11 | case $1 | |
| 12 | in | |
| 13 | -m32) | |
| 14 | link="$MSVC/link" | |
| 15 | args="$args /machine:X86" | |
| 16 | shift 1 | |
| 17 | ;; | |
| 18 | -m64) | |
| 19 | link="$MSVC/x86_amd64/link" | |
| 20 | args="$args /machine:X64" | |
| 21 | shift 1 | |
| 22 | ;; | |
| 23 | -g) | |
| 24 | args="$args /debug" | |
| 25 | shift 1 | |
| 26 | ;; | |
| 27 | -o) | |
| 28 | dir="$(dirname $2)" | |
| 29 | base="$(basename $2|sed 's/\.[^.]*//g')" | |
| 30 | args="$args /out:\"$2\" /pdb:$base.pdb /implib:$base.lib" | |
| 31 | shift 2 | |
| 32 | ;; | |
| 33 | -shared) | |
| 34 | args="$args /DLL" | |
| 35 | shift 1 | |
| 36 | ;; | |
| 37 | -static-libgcc) | |
| 38 | shift 1 | |
| 39 | ;; | |
| 40 | *.o|*.lib|*.a) | |
| 41 | args="$args $(echo $1|sed -e 's%\\%/%g')" | |
| 42 | shift 1 | |
| 43 | ;; | |
| 44 | *) | |
| 45 | echo "Unsupported argument '$1'" | |
| 46 | exit 1 | |
| 47 | ;; | |
| 48 | esac | |
| 49 | done | |
| 50 | ||
| 51 | echo "\"$link\" $args" | |
| 52 | eval "\"$link\" $args" | |
| 0 | 53 | \ No newline at end of file |
| ... | ...@@ -33,7 +33,6 @@ | |
| 33 | 33 | JAVA_INCLUDES=-I"$(JAVA_HOME)/include" \ |
| 34 | 34 | -I"$(JAVA_HOME)/include/$(OS)" |
| 35 | 35 | |
| 36 | LIBDIR=$(JAVA_HOME)/jre/lib/$(ARCH) | |
| 37 | 36 | BUILD=../build/native |
| 38 | 37 | JAVAH=$(BUILD) |
| 39 | 38 | INSTALLDIR=../build/$(OS) |
| ... | ...@@ -42,8 +41,9 @@ | |
| 42 | 41 | ifneq ($(DYNAMIC_LIBFFI),true) |
| 43 | 42 | FFI_SRC=$(shell pwd)/libffi |
| 44 | 43 | FFI_BUILD=$(BUILD)/libffi |
| 45 | FFI_LIB=$(FFI_BUILD)/.libs/libffi_convenience.a | |
| 46 | FFI_CONFIG=--disable-static --with-pic=yes | |
| 44 | FFI_LIB=$(FFI_BUILD)/.libs/libffi$(ARSFX) | |
| 45 | FFI_ENV=CC="$(CC)" CFLAGS="$(CDEBUG)" CPPFLAGS="$(CDEFINES)" | |
| 46 | FFI_CONFIG=--enable-static --disable-shared --with-pic=yes | |
| 47 | 47 | endif |
| 48 | 48 | LIBRARY=$(BUILD)/$(LIBPFX)jnidispatch$(JNISFX) |
| 49 | 49 | TESTLIB=$(BUILD)/$(LIBPFX)testlib$(LIBSFX) |
| ... | ...@@ -51,6 +51,7 @@ | |
| 51 | 51 | # Reasonable defaults based on GCC |
| 52 | 52 | LIBPFX=lib |
| 53 | 53 | LIBSFX=.so |
| 54 | ARSFX=.a | |
| 54 | 55 | JNISFX=$(LIBSFX) |
| 55 | 56 | CC=gcc |
| 56 | 57 | LD=gcc |
| ... | ...@@ -84,37 +85,41 @@ | |
| 84 | 85 | # end defaults |
| 85 | 86 | |
| 86 | 87 | ifeq ($(OS),win32) |
| 87 | # Uncomment this line to use MSVC (doesn't yet work with libffi) | |
| 88 | #CC=cl | |
| 89 | 88 | ARCH=$(shell uname -m | sed 's/i.86/i386/g') |
| 90 | 89 | CDEFINES=-DHAVE_PROTECTION |
| 91 | ||
| 92 | ifeq ($(CC),cl) | |
| 93 | LD=link | |
| 94 | COPT=-O1 -Op | |
| 95 | ifeq ($(DEBUG),true) | |
| 96 | COPT=-Od | |
| 97 | DBG=d | |
| 98 | CDEBUG=-D_DEBUG -GZ -Zi | |
| 99 | endif | |
| 100 | COUT=-Fo$@ | |
| 101 | PCFLAGS=-nologo -MD$(DBG) -W3 -WX -GX -YX -Fd$(@D)/$* -Fp$(@D)/$* | |
| 102 | CASM=-FAs | |
| 103 | ||
| 104 | LDFLAGS=/pdb:$(subst .dll,,$@).pdb /implib:$(subst .dll,,$@).lib /debug /machine:i386 /pdbtype:sept /dll /nologo /opt:REF /incremental:no /out:$@ | |
| 105 | LIBDIR=/libpath:"$(JAVA_HOME)/lib" | |
| 106 | #LIBS=$(LIBDIR) jawt.lib | |
| 90 | WINDRES=windres | |
| 91 | EXTRAOBJS=$(RSRC) | |
| 107 | 92 | STRIP=@echo |
| 108 | else | |
| 93 | LIBPFX= | |
| 94 | LIBSFX=.dll | |
| 95 | ||
| 96 | ifeq ($(CC),gcc) | |
| 109 | 97 | CC += -mno-cygwin |
| 110 | 98 | LD += -mno-cygwin -Wl,--add-stdcall-alias |
| 111 | LIBDIR="$(JAVA_HOME)/lib" | |
| 112 | #LIBS=$(LIBDIR)/jawt.lib | |
| 113 | 99 | endif |
| 114 | 100 | |
| 115 | LIBPFX= | |
| 116 | LIBSFX=.dll | |
| 117 | EXTRAOBJS=$(RSRC) | |
| 101 | ifeq ($(ARCH),amd64) | |
| 102 | ||
| 103 | WINDRES=x86_64-pc-mingw32-windres | |
| 104 | ||
| 105 | # Uncomment to enable MINGW64 cross compiler | |
| 106 | # Last build attempt has too many runtime problems (alloca broken) (080831) | |
| 107 | #MINGW = x86_64-pc-mingw32-gcc -m64 -mno-cygwin | |
| 108 | ifneq ($(MINGW),) | |
| 109 | CC = $(MINGW) | |
| 110 | LD = x86_64-pc-mingw32-ld | |
| 111 | LDFLAGS=-o $@ -shared | |
| 112 | LIBS= -lmingwex -lkernel32 -lmsvcrt | |
| 113 | FFI_CONFIG += --host=x86_64-pc-mingw32; rm -f include/ffitarget.h; cp $(FFI_SRC)/include/*.h $(FFI_SRC)/src/x86/ffitarget.h include | |
| 114 | else | |
| 115 | # MSVC (wrapper scripts) | |
| 116 | CC=$(FFI_SRC)/../cc.sh -m64 | |
| 117 | LD=$(FFI_SRC)/../ld.sh -m64 | |
| 118 | ARSFX=.lib | |
| 119 | FFI_CONFIG += --host=x86_64-pc-mingw32; rm -f include/ffitarget.h; cp $(FFI_SRC)/include/*.h $(FFI_SRC)/src/x86/ffitarget.h include | |
| 120 | FFI_ENV += LD="$(LD)" CPP=cpp | |
| 121 | endif | |
| 122 | endif | |
| 118 | 123 | endif |
| 119 | 124 | |
| 120 | 125 | ifeq ($(OS),linux) |
| ... | ...@@ -156,10 +161,12 @@ | |
| 156 | 161 | endif |
| 157 | 162 | |
| 158 | 163 | # Enable 64-bit builds if the arch demands it |
| 164 | ifeq ($(CC),gcc) | |
| 159 | 165 | ifeq ($(ARCH),amd64) |
| 160 | 166 | CC += -m64 |
| 161 | 167 | LD += -m64 |
| 162 | 168 | endif |
| 169 | endif | |
| 163 | 170 | |
| 164 | 171 | ifeq ($(OS),darwin) |
| 165 | 172 | ARCH=$(shell arch) |
| ... | ...@@ -175,8 +182,8 @@ | |
| 175 | 182 | ISYSROOT=-isysroot $(SDKROOT) |
| 176 | 183 | ARCHFLAGS=-arch ppc -arch i386 |
| 177 | 184 | ifneq ($(findstring 10.5,$(SDKROOT)),) |
| 178 | ALT_ARCHS+=x86_64 #ppc64 | |
| 179 | ARCHFLAGS+=-arch x86_64 #-arch ppc64 | |
| 185 | ALT_ARCHS+=x86_64 | |
| 186 | ARCHFLAGS+=-arch x86_64 | |
| 180 | 187 | endif |
| 181 | 188 | endif |
| 182 | 189 | PCFLAGS+=$(ISYSROOT) -x objective-c |
| ... | ...@@ -213,7 +220,8 @@ | |
| 213 | 220 | cp $(LIBRARY) $(INSTALLDIR) |
| 214 | 221 | |
| 215 | 222 | $(RSRC): $(BUILD)/jnidispatch.rc |
| 216 | windres -i $< -o $@ | |
| 223 | $(WINDRES) -i $< -o $@ \ | |
| 224 | || (echo > $@.c && $(CC) $(CFLAGS) -c $@.c $(COUT)) | |
| 217 | 225 | |
| 218 | 226 | $(LIBRARY): $(JNIDISPATCH_OBJS) $(FFI_LIB) |
| 219 | 227 | $(LD) $(LDFLAGS) $(JNIDISPATCH_OBJS) $(FFI_LIB) $(LIBS) |
| ... | ...@@ -227,7 +235,7 @@ | |
| 227 | 235 | @if [ ! -f $(FFI_BUILD)/Makefile ]; then \ |
| 228 | 236 | echo "Configuring libffi ($(ARCH))"; \ |
| 229 | 237 | (cd $(FFI_BUILD) \ |
| 230 | && CC="$(CC)" CFLAGS="$(CDEBUG)" CPPFLAGS="$(CDEFINES)" $(FFI_SRC)/configure $(FFI_CONFIG)); \ | |
| 238 | && $(FFI_ENV) $(FFI_SRC)/configure $(FFI_CONFIG)); \ | |
| 231 | 239 | fi |
| 232 | 240 | $(MAKE) -C $(FFI_BUILD) |
| 233 | 241 | ifneq ($(SDKROOT),) |
| ... | ...@@ -64,6 +64,10 @@ | |
| 64 | 64 | |
| 65 | 65 | #ifndef LIBFFI_ASM |
| 66 | 66 | |
| 67 | #ifdef _MSC_VER | |
| 68 | #define __attribute__(X) | |
| 69 | #endif | |
| 70 | ||
| 67 | 71 | #include <stddef.h> |
| 68 | 72 | #include <limits.h> |
| 69 | 73 |
| ... | ...@@ -0,0 +1,313 @@ | |
| 1 | #define LIBFFI_ASM | |
| 2 | #include <fficonfig.h> | |
| 3 | #include <ffi.h> | |
| 4 | ||
| 5 | /* Constants for ffi_call_win64 */ | |
| 6 | #define STACK 0 | |
| 7 | #define PREP_ARGS_FN 32 | |
| 8 | #define ECIF 40 | |
| 9 | #define CIF_BYTES 48 | |
| 10 | #define CIF_FLAGS 56 | |
| 11 | #define RVALUE 64 | |
| 12 | #define FN 72 | |
| 13 | ||
| 14 | /* ffi_call_win64 (void (*prep_args_fn)(char *, extended_cif *), | |
| 15 | extended_cif *ecif, unsigned bytes, unsigned flags, | |
| 16 | unsigned *rvalue, void (*fn)()); | |
| 17 | */ | |
| 18 | ||
| 19 | #ifdef _MSC_VER | |
| 20 | PUBLIC ffi_call_win64 | |
| 21 | ||
| 22 | EXTRN __chkstk:NEAR | |
| 23 | EXTRN ffi_closure_win64_inner:NEAR | |
| 24 | ||
| 25 | _TEXT SEGMENT | |
| 26 | ||
| 27 | ;;; ffi_closure_win64 will be called with these registers set: | |
| 28 | ;;; rax points to 'closure' | |
| 29 | ;;; r11 contains a bit mask that specifies which of the | |
| 30 | ;;; first four parameters are float or double | |
| 31 | ;;; | |
| 32 | ;;; It must move the parameters passed in registers to their stack location, | |
| 33 | ;;; call ffi_closure_win64_inner for the actual work, then return the result. | |
| 34 | ;;; | |
| 35 | ffi_closure_win64 PROC FRAME | |
| 36 | ;; copy register arguments onto stack | |
| 37 | test r11, 1 | |
| 38 | jne first_is_float | |
| 39 | mov QWORD PTR [rsp+8], rcx | |
| 40 | jmp second | |
| 41 | first_is_float: | |
| 42 | movlpd QWORD PTR [rsp+8], xmm0 | |
| 43 | ||
| 44 | second: | |
| 45 | test r11, 2 | |
| 46 | jne second_is_float | |
| 47 | mov QWORD PTR [rsp+16], rdx | |
| 48 | jmp third | |
| 49 | second_is_float: | |
| 50 | movlpd QWORD PTR [rsp+16], xmm1 | |
| 51 | ||
| 52 | third: | |
| 53 | test r11, 4 | |
| 54 | jne third_is_float | |
| 55 | mov QWORD PTR [rsp+24], r8 | |
| 56 | jmp fourth | |
| 57 | third_is_float: | |
| 58 | movlpd QWORD PTR [rsp+24], xmm2 | |
| 59 | ||
| 60 | fourth: | |
| 61 | test r11, 8 | |
| 62 | jne fourth_is_float | |
| 63 | mov QWORD PTR [rsp+32], r9 | |
| 64 | jmp done | |
| 65 | fourth_is_float: | |
| 66 | movlpd QWORD PTR [rsp+32], xmm3 | |
| 67 | ||
| 68 | done: | |
| 69 | .ALLOCSTACK 40 | |
| 70 | sub rsp, 40 | |
| 71 | .ENDPROLOG | |
| 72 | mov rcx, rax ; context is first parameter | |
| 73 | mov rdx, rsp ; stack is second parameter | |
| 74 | add rdx, 48 ; point to start of arguments | |
| 75 | mov rax, ffi_closure_win64_inner | |
| 76 | call rax ; call the real closure function | |
| 77 | add rsp, 40 | |
| 78 | movd xmm0, rax ; If the closure returned a float, | |
| 79 | ; ffi_closure_win64_inner wrote it to rax | |
| 80 | ret 0 | |
| 81 | ffi_closure_win64 ENDP | |
| 82 | ||
| 83 | ffi_call_win64 PROC FRAME | |
| 84 | ;; copy registers onto stack | |
| 85 | mov QWORD PTR [rsp+32], r9 | |
| 86 | mov QWORD PTR [rsp+24], r8 | |
| 87 | mov QWORD PTR [rsp+16], rdx | |
| 88 | mov QWORD PTR [rsp+8], rcx | |
| 89 | .PUSHREG rbp | |
| 90 | push rbp | |
| 91 | .ALLOCSTACK 48 | |
| 92 | sub rsp, 48 ; 00000030H | |
| 93 | .SETFRAME rbp, 32 | |
| 94 | lea rbp, QWORD PTR [rsp+32] | |
| 95 | .ENDPROLOG | |
| 96 | ||
| 97 | mov eax, DWORD PTR CIF_BYTES[rbp] | |
| 98 | add rax, 15 | |
| 99 | and rax, -16 | |
| 100 | call __chkstk | |
| 101 | sub rsp, rax | |
| 102 | lea rax, QWORD PTR [rsp+32] | |
| 103 | mov QWORD PTR STACK[rbp], rax | |
| 104 | ||
| 105 | mov rdx, QWORD PTR ECIF[rbp] | |
| 106 | mov rcx, QWORD PTR STACK[rbp] | |
| 107 | call QWORD PTR PREP_ARGS_FN[rbp] | |
| 108 | ||
| 109 | mov rsp, QWORD PTR STACK[rbp] | |
| 110 | ||
| 111 | movlpd xmm3, QWORD PTR [rsp+24] | |
| 112 | movd r9, xmm3 | |
| 113 | ||
| 114 | movlpd xmm2, QWORD PTR [rsp+16] | |
| 115 | movd r8, xmm2 | |
| 116 | ||
| 117 | movlpd xmm1, QWORD PTR [rsp+8] | |
| 118 | movd rdx, xmm1 | |
| 119 | ||
| 120 | movlpd xmm0, QWORD PTR [rsp] | |
| 121 | movd rcx, xmm0 | |
| 122 | ||
| 123 | call QWORD PTR FN[rbp] | |
| 124 | ret_int$: | |
| 125 | cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_INT | |
| 126 | jne ret_float$ | |
| 127 | ||
| 128 | mov rcx, QWORD PTR RVALUE[rbp] | |
| 129 | mov DWORD PTR [rcx], eax | |
| 130 | jmp SHORT ret_void$ | |
| 131 | ||
| 132 | ret_float$: | |
| 133 | cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_FLOAT | |
| 134 | jne SHORT ret_double$ | |
| 135 | ||
| 136 | mov rax, QWORD PTR RVALUE[rbp] | |
| 137 | movlpd QWORD PTR [rax], xmm0 | |
| 138 | jmp SHORT ret_void$ | |
| 139 | ||
| 140 | ret_double$: | |
| 141 | cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_DOUBLE | |
| 142 | jne SHORT ret_int64$ | |
| 143 | ||
| 144 | mov rax, QWORD PTR RVALUE[rbp] | |
| 145 | movlpd QWORD PTR [rax], xmm0 | |
| 146 | jmp SHORT ret_void$ | |
| 147 | ||
| 148 | ret_int64$: | |
| 149 | cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_SINT64 | |
| 150 | jne ret_void$ | |
| 151 | ||
| 152 | mov rcx, QWORD PTR RVALUE[rbp] | |
| 153 | mov QWORD PTR [rcx], rax | |
| 154 | jmp SHORT ret_void$ | |
| 155 | ||
| 156 | ret_void$: | |
| 157 | xor eax, eax | |
| 158 | ||
| 159 | lea rsp, QWORD PTR [rbp+16] | |
| 160 | pop rbp | |
| 161 | ret 0 | |
| 162 | ffi_call_win64 ENDP | |
| 163 | _TEXT ENDS | |
| 164 | END | |
| 165 | #else | |
| 166 | .text | |
| 167 | ||
| 168 | .extern ___chkstk | |
| 169 | .extern _ffi_closure_win64_inner | |
| 170 | ||
| 171 | # ffi_closure_win64 will be called with these registers set: | |
| 172 | # rax points to 'closure' | |
| 173 | # r11 contains a bit mask that specifies which of the | |
| 174 | # first four parameters are float or double | |
| 175 | # | |
| 176 | # It must move the parameters passed in registers to their stack location, | |
| 177 | # call ffi_closure_win64_inner for the actual work, then return the result. | |
| 178 | # | |
| 179 | .balign 16 | |
| 180 | .globl _ffi_closure_win64 | |
| 181 | .type _ffi_closure_win64,@function | |
| 182 | _ffi_closure_win64: | |
| 183 | # copy register arguments onto stack | |
| 184 | test $1,%r11 | |
| 185 | jne .Lfirst_is_float | |
| 186 | mov %rcx, 8(%rsp) | |
| 187 | jmp .Lsecond | |
| 188 | .Lfirst_is_float: | |
| 189 | movlpd %xmm0, 8(%rsp) | |
| 190 | ||
| 191 | .Lsecond: | |
| 192 | test $2, %r11 | |
| 193 | jne .Lsecond_is_float | |
| 194 | mov %rdx, 16(%rsp) | |
| 195 | jmp .Lthird | |
| 196 | .Lsecond_is_float: | |
| 197 | movlpd %xmm1, 16(%rsp) | |
| 198 | ||
| 199 | .Lthird: | |
| 200 | test $4, %r11 | |
| 201 | jne .Lthird_is_float | |
| 202 | mov %r8,24(%rsp) | |
| 203 | jmp .Lfourth | |
| 204 | .Lthird_is_float: | |
| 205 | movlpd %xmm2, 24(%rsp) | |
| 206 | ||
| 207 | .Lfourth: | |
| 208 | test $8, %r11 | |
| 209 | jne .Lfourth_is_float | |
| 210 | mov %r9, 32(%rsp) | |
| 211 | jmp .Ldone | |
| 212 | .Lfourth_is_float: | |
| 213 | movlpd %xmm3, 32(%rsp) | |
| 214 | ||
| 215 | .Ldone: | |
| 216 | #.ALLOCSTACK 40 | |
| 217 | sub $40, %rsp | |
| 218 | #.ENDPROLOG | |
| 219 | mov %rax, %rcx # context is first parameter | |
| 220 | mov %rsp, %rdx # stack is second parameter | |
| 221 | add $48, %rdx # point to start of arguments | |
| 222 | mov _ffi_closure_win64_inner, %rax | |
| 223 | callq *%rax # call the real closure function | |
| 224 | add $40, %rsp | |
| 225 | movq %rax, %xmm0 # If the closure returned a float, | |
| 226 | # ffi_closure_win64_inner wrote it to rax | |
| 227 | retq | |
| 228 | .ffi_closure_win64_end: | |
| 229 | ||
| 230 | .balign 16 | |
| 231 | .globl _ffi_call_win64 | |
| 232 | .type _ffi_call_win64,@function | |
| 233 | _ffi_call_win64: | |
| 234 | # copy registers onto stack | |
| 235 | mov %r9,32(%rsp) | |
| 236 | mov %r8,24(%rsp) | |
| 237 | mov %rdx,16(%rsp) | |
| 238 | mov %rcx,8(%rsp) | |
| 239 | #.PUSHREG rbp | |
| 240 | push %rbp | |
| 241 | #.ALLOCSTACK 48 | |
| 242 | sub $48,%rsp | |
| 243 | #.SETFRAME rbp, 32 | |
| 244 | lea 32(%rsp),%rbp | |
| 245 | #.ENDPROLOG | |
| 246 | ||
| 247 | mov CIF_BYTES(%rbp),%eax | |
| 248 | add $15, %rax | |
| 249 | and $-16, %rax | |
| 250 | callq ___chkstk | |
| 251 | sub %rax, %rsp | |
| 252 | lea 32(%rsp), %rax | |
| 253 | mov %rax, STACK(%rbp) | |
| 254 | ||
| 255 | mov ECIF(%rbp), %rdx | |
| 256 | mov STACK(%rbp), %rcx | |
| 257 | callq *PREP_ARGS_FN(%rbp) | |
| 258 | ||
| 259 | mov STACK(%rbp), %rsp | |
| 260 | ||
| 261 | movlpd 24(%rsp), %xmm3 | |
| 262 | movd %xmm3, %r9 | |
| 263 | ||
| 264 | movlpd 16(%rsp), %xmm2 | |
| 265 | movd %xmm2, %r8 | |
| 266 | ||
| 267 | movlpd 8(%rsp), %xmm1 | |
| 268 | movd %xmm1, %rdx | |
| 269 | ||
| 270 | movlpd (%rsp), %xmm0 | |
| 271 | movd %xmm0, %rcx | |
| 272 | ||
| 273 | callq *FN(%rbp) | |
| 274 | .Lret_int: | |
| 275 | cmpl $FFI_TYPE_INT, CIF_FLAGS(%rbp) | |
| 276 | jne .Lret_float | |
| 277 | ||
| 278 | mov RVALUE(%rbp), %rcx | |
| 279 | mov %eax, (%rcx) | |
| 280 | jmp .Lret_void | |
| 281 | ||
| 282 | .Lret_float: | |
| 283 | cmpl $FFI_TYPE_FLOAT, CIF_FLAGS(%rbp) | |
| 284 | jne .Lret_double | |
| 285 | ||
| 286 | mov RVALUE(%rbp), %rax | |
| 287 | movlpd %xmm0,(%rax) | |
| 288 | jmp .Lret_void | |
| 289 | ||
| 290 | .Lret_double: | |
| 291 | cmpl $FFI_TYPE_DOUBLE, CIF_FLAGS(%rbp) | |
| 292 | jne .Lret_int64 | |
| 293 | ||
| 294 | mov RVALUE(%rbp), %rax | |
| 295 | movlpd %xmm0, (%rax) | |
| 296 | jmp .Lret_void | |
| 297 | ||
| 298 | .Lret_int64: | |
| 299 | cmpl $FFI_TYPE_SINT64, (%rbp) | |
| 300 | jne .Lret_void | |
| 301 | ||
| 302 | mov RVALUE(%rbp), %rcx | |
| 303 | mov %rax, (%rcx) | |
| 304 | jmp .Lret_void | |
| 305 | ||
| 306 | .Lret_void: | |
| 307 | xor %eax, %eax | |
| 308 | ||
| 309 | lea 16(%rbp), %rsp | |
| 310 | pop %rbp | |
| 311 | retq | |
| 312 | .ffi_call_win64_end: | |
| 313 | #endif /* !_MSC_VER */ |
| ... | ...@@ -21,12 +21,14 @@ | |
| 21 | 21 | |
| 22 | 22 | public class JNAUnloadTest extends TestCase { |
| 23 | 23 | |
| 24 | private static final String BUILDDIR = | |
| 25 | System.getProperty("jna.builddir", "build" | |
| 26 | + (Native.POINTER_SIZE == 8 ? "-d64" : "")); | |
| 27 | ||
| 24 | 28 | private static class TestLoader extends URLClassLoader { |
| 25 | 29 | public TestLoader() throws MalformedURLException { |
| 26 | 30 | super(new URL[] { |
| 27 | // use "build-d64" for 64-bit jvm's | |
| 28 | new File("build" + System.getProperty(LibraryLoadTest.DIR_BUILD_SUFFIX, "") | |
| 29 | + "/classes").toURI().toURL(), | |
| 31 | new File(BUILDDIR + "/classes").toURI().toURL(), | |
| 30 | 32 | }, null); |
| 31 | 33 | } |
| 32 | 34 | } |
| ... | ...@@ -277,9 +277,9 @@ | |
| 277 | 277 | // ensure that even if the argument is ByValue, it's passed as ptr |
| 278 | 278 | struct = new TestLibrary.CheckFieldAlignment.ByValue(); |
| 279 | 279 | assertEquals("Structure argument should be passed according to method " |
| 280 | + "parameter type, not argument type", | |
| 281 | struct.getPointer(), | |
| 282 | lib.testStructurePointerArgument(struct)); | |
| 280 | + "parameter type, not argument type", | |
| 281 | struct.getPointer(), | |
| 282 | lib.testStructurePointerArgument(struct)); | |
| 283 | 283 | } |
| 284 | 284 | |
| 285 | 285 | public void testStructureByValueArgument() { |
| ... | ...@@ -356,7 +356,7 @@ | |
| 356 | 356 | public void testByteArrayArgument() { |
| 357 | 357 | byte[] buf = new byte[1024]; |
| 358 | 358 | final byte MAGIC = (byte)0xED; |
| 359 | assertEquals("Wrong return value", buf.length, + | |
| 359 | assertEquals("Wrong return value", buf.length, | |
| 360 | 360 | lib.fillInt8Buffer(buf, buf.length, MAGIC)); |
| 361 | 361 | for (int i=0;i < buf.length;i++) { |
| 362 | 362 | assertEquals("Bad value at index " + i, MAGIC, buf[i]); |
| ... | ...@@ -366,7 +366,7 @@ | |
| 366 | 366 | public void testShortArrayArgument() { |
| 367 | 367 | short[] buf = new short[1024]; |
| 368 | 368 | final short MAGIC = (short)0xABED; |
| 369 | assertEquals("Wrong return value", buf.length, + | |
| 369 | assertEquals("Wrong return value", buf.length, | |
| 370 | 370 | lib.fillInt16Buffer(buf, buf.length, MAGIC)); |
| 371 | 371 | for (int i=0;i < buf.length;i++) { |
| 372 | 372 | assertEquals("Bad value at index " + i, MAGIC, buf[i]); |
| ... | ...@@ -376,7 +376,7 @@ | |
| 376 | 376 | public void testIntArrayArgument() { |
| 377 | 377 | int[] buf = new int[1024]; |
| 378 | 378 | final int MAGIC = 0xABEDCF23; |
| 379 | assertEquals("Wrong return value", buf.length, + | |
| 379 | assertEquals("Wrong return value", buf.length, | |
| 380 | 380 | lib.fillInt32Buffer(buf, buf.length, MAGIC)); |
| 381 | 381 | for (int i=0;i < buf.length;i++) { |
| 382 | 382 | assertEquals("Bad value at index " + i, MAGIC, buf[i]); |
| ... | ...@@ -386,7 +386,7 @@ | |
| 386 | 386 | public void testLongArrayArgument() { |
| 387 | 387 | long[] buf = new long[1024]; |
| 388 | 388 | final long MAGIC = 0x1234567887654321L; |
| 389 | assertEquals("Wrong return value", buf.length, + | |
| 389 | assertEquals("Wrong return value", buf.length, | |
| 390 | 390 | lib.fillInt64Buffer(buf, buf.length, MAGIC)); |
| 391 | 391 | for (int i=0;i < buf.length;i++) { |
| 392 | 392 | assertEquals("Bad value at index " + i, MAGIC, buf[i]); |
| ... | ...@@ -291,7 +291,7 @@ | |
| 291 | 291 | finfo.overlapped, null)) { |
| 292 | 292 | int err = klib.GetLastError(); |
| 293 | 293 | throw new IOException("ReadDirectoryChangesW failed on " |
| 294 | + finfo.file | |
| 294 | + finfo.file + ", handle " + handle | |
| 295 | 295 | + ": '" + getSystemError(err) |
| 296 | 296 | + "' (" + err + ")"); |
| 297 | 297 | } |
| ... | ...@@ -356,6 +356,7 @@ | |
| 356 | 356 | null, code, |
| 357 | 357 | 0, pref, 0, null); |
| 358 | 358 | String s = pref.getValue().getString(0, !Boolean.getBoolean("w32.ascii")); |
| 359 | s = s.replace(".\r",".").replace(".\n","."); | |
| 359 | 360 | lib.LocalFree(pref.getValue()); |
| 360 | 361 | return s; |
| 361 | 362 | } |
| ... | ...@@ -2,6 +2,7 @@ | |
| 2 | 2 | <h2>Release 3.x.x</h2> |
| 3 | 3 | <b>Features</b><br> |
| 4 | 4 | <ul> |
| 5 | <li>Win64 support. | |
| 5 | 6 | </ul> |
| 6 | 7 | <b>Bug Fixes</b><br> |
| 7 | 8 | <ul> |
| ... | ...@@ -33,7 +33,7 @@ | |
| 33 | 33 | #define int64 long long |
| 34 | 34 | #define LONG(X) X ## LL |
| 35 | 35 | #else |
| 36 | #error 64-bit type not defined for this platform | |
| 36 | #error 64-bit type not defined for this compiler | |
| 37 | 37 | #endif |
| 38 | 38 | |
| 39 | 39 | #define MAGICSTRING "magic"; |
| ... | ...@@ -224,7 +224,6 @@ | |
| 224 | 224 | |
| 225 | 225 | EXPORT int |
| 226 | 226 | returnRotatedArgumentCount(char* args[]) { |
| 227 | int i=0; | |
| 228 | 227 | int count = 0; |
| 229 | 228 | char* first = args[0]; |
| 230 | 229 | while (args[count] != NULL) { |
| ... | ...@@ -358,6 +357,37 @@ | |
| 358 | 357 | + arg.int64Field + arg.floatField + arg.doubleField; |
| 359 | 358 | } |
| 360 | 359 | |
| 360 | typedef struct ByValue8 { int8 data; } ByValue9; | |
| 361 | typedef struct ByValue16 { int16 data; } ByValue16; | |
| 362 | typedef struct ByValue32 { int32 data; } ByValue32; | |
| 363 | typedef struct ByValue64 { int64 data; } ByValue64; | |
| 364 | typedef struct ByValue128 { int64 data, data1; } ByValue128; | |
| 365 | ||
| 366 | EXPORT int8 | |
| 367 | testStructureByValueArgument8(struct ByValue8 arg){ | |
| 368 | return arg.data; | |
| 369 | } | |
| 370 | ||
| 371 | EXPORT int16 | |
| 372 | testStructureByValueArgument16(struct ByValue16 arg){ | |
| 373 | return arg.data; | |
| 374 | } | |
| 375 | ||
| 376 | EXPORT int32 | |
| 377 | testStructureByValueArgument32(struct ByValue32 arg){ | |
| 378 | return arg.data; | |
| 379 | } | |
| 380 | ||
| 381 | EXPORT int64 | |
| 382 | testStructureByValueArgument64(struct ByValue64 arg){ | |
| 383 | return arg.data; | |
| 384 | } | |
| 385 | ||
| 386 | EXPORT int64 | |
| 387 | testStructureByValueArgument128(struct ByValue128 arg){ | |
| 388 | return arg.data + arg.data1; | |
| 389 | } | |
| 390 | ||
| 361 | 391 | typedef struct { |
| 362 | 392 | int8 field0; |
| 363 | 393 | int16 field1; |
| ... | ...@@ -400,9 +430,9 @@ | |
| 400 | 430 | return STRUCT_SIZES[index]; |
| 401 | 431 | } |
| 402 | 432 | |
| 403 | extern void exit(int); | |
| 433 | extern void exit(int); | |
| 404 | 434 | #define FIELD(T,X,N) (((T*)X)->field ## N) |
| 405 | #define OFFSET(T,X,N) (((char*)&FIELD(T,X,N))-((char*)&FIELD(T,X,0))) | |
| 435 | #define OFFSET(T,X,N) (int)(((char*)&FIELD(T,X,N))-((char*)&FIELD(T,X,0))) | |
| 406 | 436 | #define V8(N) (N+1) |
| 407 | 437 | #define V16(N) ((((int32)V8(N))<<8)|V8(N)) |
| 408 | 438 | #define V32(N) ((((int32)V16(N))<<16)|V16(N)) |
| ... | ...@@ -460,7 +490,7 @@ | |
| 460 | 490 | |
| 461 | 491 | |
| 462 | 492 | EXPORT void |
| 463 | callVoidCallback(void (*func)()) { | |
| 493 | callVoidCallback(void (*func)(void)) { | |
| 464 | 494 | (*func)(); |
| 465 | 495 | } |
| 466 | 496 | |
| ... | ...@@ -536,7 +566,7 @@ | |
| 536 | 566 | } |
| 537 | 567 | |
| 538 | 568 | struct cbstruct { |
| 539 | void (*func)(); | |
| 569 | void (*func)(void); | |
| 540 | 570 | }; |
| 541 | 571 | |
| 542 | 572 | EXPORT void |
| ... | ...@@ -562,13 +592,14 @@ | |
| 562 | 592 | |
| 563 | 593 | EXPORT void |
| 564 | 594 | setCallbackInStruct(struct cbstruct* cb) { |
| 565 | cb->func = (void (*)())structCallbackFunction; | |
| 595 | cb->func = (void (*)(void))structCallbackFunction; | |
| 566 | 596 | } |
| 567 | 597 | |
| 568 | 598 | |
| 569 | 599 | EXPORT int32 |
| 570 | 600 | fillInt8Buffer(char *buf, int len, char value) { |
| 571 | 601 | int i; |
| 602 | ||
| 572 | 603 | for (i=0;i < len;i++) { |
| 573 | 604 | buf[i] = value; |
| 574 | 605 | } |
| ... | ...@@ -652,14 +683,13 @@ | |
| 652 | 683 | returnStringVarArgs(const char *fmt, ...) { |
| 653 | 684 | char* cp; |
| 654 | 685 | va_list ap; |
| 655 | int32 sum = 0; | |
| 656 | 686 | va_start(ap, fmt); |
| 657 | 687 | cp = va_arg(ap, char *); |
| 658 | 688 | va_end(ap); |
| 659 | 689 | return cp; |
| 660 | 690 | } |
| 661 | 691 | |
| 662 | #ifdef _WIN32 | |
| 692 | #if defined(_WIN32) && !defined(_WIN64) | |
| 663 | 693 | /////////////////////////////////////////////////////////////////////// |
| 664 | 694 | // stdcall tests |
| 665 | 695 | /////////////////////////////////////////////////////////////////////// |
| ... | ...@@ -695,7 +725,7 @@ | |
| 695 | 725 | } |
| 696 | 726 | return value; |
| 697 | 727 | } |
| 698 | #endif /* _WIN32 */ | |
| 728 | #endif /* _WIN32 && !_WIN64 */ | |
| 699 | 729 | |
| 700 | 730 | #ifdef __cplusplus |
| 701 | 731 | } |
| ... | ...@@ -173,43 +173,6 @@ | |
| 173 | 173 | assertFalse("Wrong value read", s.data); |
| 174 | 174 | } |
| 175 | 175 | |
| 176 | public static interface CallbackTestLibrary extends Library { | |
| 177 | interface Int32Callback extends Callback { | |
| 178 | float callback(float arg, float arg2); | |
| 179 | } | |
| 180 | float callInt32Callback(Int32Callback c, float arg, float arg2); | |
| 181 | } | |
| 182 | ||
| 183 | public void testCallbackTypeMapping() throws Exception { | |
| 184 | final DefaultTypeMapper mapper = new DefaultTypeMapper(); | |
| 185 | Map options = new HashMap() { | |
| 186 | { put(Library.OPTION_TYPE_MAPPER, mapper); } | |
| 187 | }; | |
| 188 | CallbackTestLibrary lib = (CallbackTestLibrary) | |
| 189 | Native.loadLibrary("testlib", CallbackTestLibrary.class, options); | |
| 190 | // Convert java floats into native integers and back | |
| 191 | TypeConverter converter = new TypeConverter() { | |
| 192 | public Object fromNative(Object value, FromNativeContext context) { | |
| 193 | return new Float(((Integer)value).intValue()); | |
| 194 | } | |
| 195 | public Class nativeType() { | |
| 196 | return Integer.class; | |
| 197 | } | |
| 198 | public Object toNative(Object value, ToNativeContext ctx) { | |
| 199 | return new Integer(Math.round(((Float)value).floatValue())); | |
| 200 | } | |
| 201 | }; | |
| 202 | mapper.addTypeConverter(float.class, converter); | |
| 203 | CallbackTestLibrary.Int32Callback cb = new CallbackTestLibrary.Int32Callback() { | |
| 204 | public float callback(float arg, float arg2) { | |
| 205 | return arg + arg2; | |
| 206 | } | |
| 207 | }; | |
| 208 | assertEquals("Wrong result", 0, |