[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[cinvoke-svn] r153 - in trunk/cinvoke: . lib lib/arch
From: |
will |
Subject: |
[cinvoke-svn] r153 - in trunk/cinvoke: . lib lib/arch |
Date: |
28 Jul 2008 20:29:39 -0700 |
Author: will
Date: 2008-07-28 20:29:39 -0700 (Mon, 28 Jul 2008)
New Revision: 153
Added:
trunk/cinvoke/lib/arch/gcc_x86_win.c
trunk/cinvoke/lib/arch/gcc_x86_win.h
Modified:
trunk/cinvoke/configure.pl
trunk/cinvoke/lib/cinvoke-arch.h
Log:
Adding GCC/Windows port, courtesy of Mooneer Salem
Modified: trunk/cinvoke/configure.pl
===================================================================
--- trunk/cinvoke/configure.pl 2007-09-01 18:59:08 UTC (rev 152)
+++ trunk/cinvoke/configure.pl 2008-07-29 03:29:39 UTC (rev 153)
@@ -50,6 +50,20 @@
$DYNCFLAGS = '-dynamic';
$BUILDSTATIC = 'libtool -static -o';
$RANLIB = 'echo';
+} else if ($platform =~ m/_WIN$/) {
+ $DYNEXT = 'dll';
+ $JNIDYNEXT = 'dll';
+ my $jni_include_dir = find_jni();
+ if ($jni_include_dir) {
+ $JNIINCLUDE = "-I$jni_include_dir";
+ } else {
+ $JNIINCLUDE = "";
+ }
+ $BUILDSHARED = 'gcc -shared -o';
+ $CXXBUILDSHARED = 'g++ -shared -o';
+ $DYNCFLAGS = ''; # PIC is the default on Windows.
+ $BUILDSTATIC = 'rm -f $(TARGET) && ar rs';
+ $RANLIB = 'ranlib';
} else {
$DYNEXT = 'so';
$JNIDYNEXT = 'so';
@@ -115,6 +129,8 @@
if ($? != 0) { die "error executing uname: $!"; }
if ($uname =~ m/Darwin/) {
$os = "OSX";
+ } elsif ($gccout =~ m/mingw|cygwin/) {
+ $os = "WIN"
} else {
$os = "UNIX"; # hey why not
Added: trunk/cinvoke/lib/arch/gcc_x86_win.c
===================================================================
--- trunk/cinvoke/lib/arch/gcc_x86_win.c (rev 0)
+++ trunk/cinvoke/lib/arch/gcc_x86_win.c 2008-07-29 03:29:39 UTC (rev
153)
@@ -0,0 +1,327 @@
+/*
+C/Invoke Source Code File
+
+Copyright (c) 2006 Will Weisser
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclaimer in the documentation
+and/or other materials provided with the distribution.
+ 3. The name of the author may not be used to endorse or promote products
+derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*/
+#ifdef CINVOKE_BUILD
+#include "../cinvoke.h"
+#include "../cinvoke-private.h"
+#else
+#include "cinvoke.h"
+#include "cinvoke-private.h"
+#endif
+
+char *GetWin32ErrMsg(DWORD err) {
+ char *str;
+ if (!FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM, NULL, err,
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ (LPTSTR)&str, 0, NULL)) {
+ str = NULL;
+ }
+ return str;
+}
+
+void context_set_win32_error(CInvContext *context) {
+ DWORD err = GetLastError();
+ char *str = GetWin32ErrMsg(err);
+
+ context_set_error(context, err, str, 1);
+}
+
+void arch_free_errstr(char *str) {
+ LocalFree(str);
+}
+
+cinv_status_t arch_library_create(CInvContext *context, const char *path,
+ ArchLibrary *library_out) {
+ HANDLE lib = LoadLibrary(path);
+ if (!lib) {
+ context_set_win32_error(context);
+ return CINV_ERROR;
+ }
+
+ library_out->dl = lib;
+
+ return CINV_SUCCESS;
+}
+cinv_status_t arch_library_get_entrypoint(CInvContext *context,
+ ArchLibrary *library, const char *name, void **entrypoint_out) {
+ void *sym = GetProcAddress(library->dl, name);
+ if (!sym) {
+ context_set_win32_error(context);
+ return CINV_ERROR;
+ }
+
+ *entrypoint_out = sym;
+
+ return CINV_SUCCESS;
+}
+cinv_status_t arch_library_delete(CInvContext *context, ArchLibrary *library) {
+ if (!FreeLibrary(library->dl)) {
+ context_set_win32_error(context);
+ return CINV_ERROR;
+ }
+
+ return CINV_SUCCESS;
+}
+const static int LEN = 4096;
+
+char *arch_callback_stub(void *functionp, void *param,
+ short stacksize, cinv_callconv_t cc, cinv_type_t types[], int
numparams) {
+ int codesize;
+ const char *code;
+ char *ret;
+
+ if (cc != CINV_CC_STDCALL && cc != CINV_CC_FASTCALL) {
+ // void f() { ((void (__cdecl *)(void *))0xAAAAAAAA)((void
*)0xBBBBBBBB); }
+ codesize = 31;
+ code = "\x55\x8b\xec\x83\xec\x40\x53\x56\x57\x68"
+ "\xbb\xbb\xbb\xbb\xb8\xaa\xaa\xaa\xaa\xff"
+ "\xd0\x83\xc4\x04\x5f\x5e\x5b\x8b\xe5\x5d"
+ "\xc3";
+ } else {
+ // same thing except with an additional stack-cleanup argument
placeholder
+ // note that the below code does not modify ecx or edx, so we
handle
+ // fastcall correctly
+ codesize = 33;
+ code = "\x55\x8b\xec\x83\xec\x40\x53\x56\x57\x68"
+ "\xbb\xbb\xbb\xbb\xb8\xaa\xaa\xaa\xaa\xff"
+ "\xd0\x83\xc4\x04\x5f\x5e\x5b\x8b\xe5\x5d"
+ "\xc2\xdd\xdd";
+ }
+
+ ret = VirtualAlloc(NULL, LEN, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
+ if (!ret)
+ return NULL;
+
+ memcpy(ret, code, codesize);
+
+ memcpy(ret + 10, ¶m, 4);
+ memcpy(ret + 15, &functionp, 4);
+
+ if (cc == CINV_CC_STDCALL || cc == CINV_CC_FASTCALL)
+ memcpy(ret + 31, &stacksize, 2);
+
+ return ret;
+}
+void arch_free_stub(char *stub) {
+ VirtualFree(stub, 0, MEM_RELEASE);
+}
+
+int is_ok_register(cinv_type_t type) {
+ return (type != CINV_T_FLOAT) &&
+ (type != CINV_T_DOUBLE) &&
+ (type != CINV_T_EXTRALONG);
+}
+
+int arch_is_register_parm(cinv_callconv_t callingconvention, int index,
+ int num_params, cinv_type_t types[]) {
+ int numeligible = 0, i;
+
+ if (callingconvention != CINV_CC_FASTCALL) return 0;
+
+ for (i = 0; i < index; i++) {
+ if (is_ok_register(types[i]))
+ numeligible++;
+ if (numeligible == 2) break;
+ }
+ return (numeligible < 2 && is_ok_register(types[i]));
+}
+int convert_to_int(void *ptr, cinv_type_t type) {
+ switch (type) {
+ case CINV_T_CHAR:
+ return (int)*(char *)ptr;
+ case CINV_T_SHORT:
+ return (int)*(short *)ptr;
+ case CINV_T_INT:
+ return *(int *)ptr;
+ case CINV_T_LONG:
+ return (int)*(long *)ptr;
+ case CINV_T_PTR:
+ return (int)*(void **)ptr;
+ default:
+ return -1;
+ }
+}
+void set_from_int(void *ptr_out, cinv_type_t type, int val) {
+ switch (type) {
+ case CINV_T_CHAR:
+ *(char *)ptr_out = (char)val;
+ break;
+ case CINV_T_SHORT:
+ *(short *)ptr_out = (short)val;
+ break;
+ case CINV_T_INT:
+ *(int *)ptr_out = val;
+ break;
+ case CINV_T_LONG:
+ *(long *)ptr_out = (long)val;
+ break;
+ case CINV_T_PTR:
+ *(void **)ptr_out = (void *)val;
+ break;
+ default:
+ break;
+ }
+}
+void arch_set_register_parms(ArchRegParms *regparms,
+ cinv_callconv_t callingconvention, int num_params, void *parameters[],
+ cinv_type_t types[]) {
+ int numeligible = 0, i;
+
+ if (callingconvention != CINV_CC_FASTCALL) return;
+
+ for (i = 0; i < num_params; i++) {
+ if (is_ok_register(types[i])) {
+ if (numeligible == 0)
+ regparms->first = convert_to_int(parameters[i],
types[i]);
+ else
+ regparms->second =
convert_to_int(parameters[i], types[i]);
+ numeligible++;
+ }
+ if (numeligible == 2) break;
+ }
+}
+
+void arch_get_register_parms(ArchRegParms *regparms,
+ cinv_callconv_t callingconvention, int num_params, void
*parameters_out[],
+ cinv_type_t types[]) {
+ int numeligible = 0, i;
+
+ if (callingconvention != CINV_CC_FASTCALL) return;
+
+ for (i = 0; i < num_params; i++) {
+ if (is_ok_register(types[i])) {
+ if (numeligible == 0)
+ set_from_int(parameters_out[i], types[i],
regparms->first);
+ else
+ set_from_int(parameters_out[i], types[i],
regparms->second);
+ numeligible++;
+ }
+ if (numeligible == 2) break;
+ }
+}
+
+void arch_getval_char(ArchRetValue *archval, char *outval) {
+ *outval = archval->ivallow;
+}
+void arch_getval_short(ArchRetValue *archval, short *outval) {
+ *outval = archval->ivallow;
+}
+void arch_getval_int(ArchRetValue *archval, int *outval) {
+ *outval = archval->ivallow;
+}
+void arch_getval_long(ArchRetValue *archval, long int *outval) {
+ *outval = archval->ivallow;
+}
+void arch_getval_extralong(ArchRetValue *archval, long long int *outval) {
+ *outval = archval->ivalhigh;
+ *outval <<= 32;
+ *outval |= archval->ivallow;
+}
+void arch_getval_float(ArchRetValue *archval, float *outval) {
+ *outval = (float)archval->dval;
+}
+void arch_getval_double(ArchRetValue *archval, double *outval) {
+ *outval = archval->dval;
+}
+void arch_getval_ptr(ArchRetValue *archval, void **outval) {
+ *outval = (void *)archval->ivallow;
+}
+
+void arch_setval_char(ArchRetValue *archval, char val) {
+ archval->ivallow = val;
+}
+void arch_setval_short(ArchRetValue *archval, short val) {
+ archval->ivallow = val;
+}
+void arch_setval_int(ArchRetValue *archval, int val) {
+ archval->ivallow = val;
+}
+void arch_setval_long(ArchRetValue *archval, long int val) {
+ archval->ivallow = val;
+}
+void arch_setval_extralong(ArchRetValue *archval, long long int val) {
+ archval->ivalhigh = (int)(val >> 32);
+ archval->ivallow = (int)val;
+}
+void arch_setval_float(ArchRetValue *archval, float val) {
+ archval->dval = val;
+}
+void arch_setval_double(ArchRetValue *archval, double val) {
+ archval->dval = val;
+}
+void arch_setval_ptr(ArchRetValue *archval, void *val) {
+ archval->ivallow = (int)val;
+}
+
+void arch_size_char(int *stacksize_out, int *structsize_out,
+ int *structalign_out) {
+ *stacksize_out = 4;
+ *structsize_out = 1;
+}
+void arch_size_short(int *stacksize_out, int *structsize_out,
+ int *structalign_out) {
+ *stacksize_out = 4;
+ *structsize_out = 2;
+ *structalign_out = 2;
+}
+void arch_size_int(int *stacksize_out, int *structsize_out,
+ int *structalign_out) {
+ *stacksize_out = 4;
+ *structsize_out = 4;
+ *structalign_out = 4;
+}
+void arch_size_long(int *stacksize_out, int *structsize_out,
+ int *structalign_out) {
+ *stacksize_out = 4;
+ *structsize_out = 4;
+ *structalign_out = 4;
+}
+void arch_size_extralong(int *stacksize_out, int *structsize_out,
+ int *structalign_out) {
+ *stacksize_out = 8;
+ *structsize_out = 8;
+ *structalign_out = 8;
+}
+void arch_size_float(int *stacksize_out, int *structsize_out,
+ int *structalign_out) {
+ *stacksize_out = 4;
+ *structsize_out = 4;
+ *structalign_out = 4;
+}
+void arch_size_double(int *stacksize_out, int *structsize_out,
+ int *structalign_out) {
+ *stacksize_out = 8;
+ *structsize_out = 8;
+ *structalign_out = 8;
+}
+void arch_size_ptr(int *stacksize_out, int *structsize_out,
+ int *structalign_out) {
+ *stacksize_out = 4;
+ *structsize_out = 4;
+ *structalign_out = 4;
+}
Added: trunk/cinvoke/lib/arch/gcc_x86_win.h
===================================================================
--- trunk/cinvoke/lib/arch/gcc_x86_win.h (rev 0)
+++ trunk/cinvoke/lib/arch/gcc_x86_win.h 2008-07-29 03:29:39 UTC (rev
153)
@@ -0,0 +1,136 @@
+/*
+C/Invoke Source Code File
+
+Copyright (c) 2006 Will Weisser
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclaimer in the documentation
+and/or other materials provided with the distribution.
+ 3. The name of the author may not be used to endorse or promote products
+derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*/
+#ifndef _ARCH_CL_X86_WIN_H
+#define _ARCH_CL_X86_WIN_H
+
+#include <windows.h>
+
+char *GetWin32ErrMsg(DWORD err);
+
+typedef struct _ArchLibrary {
+ HANDLE dl;
+} ArchLibrary;
+
+typedef struct _ArchRetValue {
+ int ivallow;
+ int ivalhigh;
+ double dval;
+} ArchRetValue;
+
+typedef struct _ArchRegParms {
+ int first;
+ int second;
+} ArchRegParms;
+
+typedef char cinv_int8_t;
+typedef short cinv_int16_t;
+typedef int cinv_int32_t;
+typedef long long cinv_int64_t;
+
+#define CINV_E_NOMEM ((cinv_int32_t)ERROR_NOT_ENOUGH_MEMORY)
+#define CINV_S_NOMEM (GetWin32ErrMsg(ERROR_NOT_ENOUGH_MEMORY))
+#define CINV_NOMEM_NEEDSFREE 1
+#define CINV_E_INVAL ((cinv_int32_t)ERROR_INVALID_PARAMETER)
+
+// setting this to stdcall makes the win32 api work, but user-compiled
+// dlls break; you can't win
+#define CINV_CC_DEFAULT CINV_CC_CDECL
+#define CINV_T_2BYTE CINV_T_SHORT
+#define CINV_T_4BYTE CINV_T_INT
+#define CINV_T_8BYTE CINV_T_EXTRALONG
+
+/////////////////////////////////////
+// macros
+/////////////////////////////////////
+#define ARCH_SAVE_REGPARMS(regparms) \
+ __asm__("mov %%ecx, %0; \
+ mov %%edx, %1" : \
+ "=m"((regparms).first), \
+ "=m"((regparms).second) \
+ );
+
+#define ARCH_CALL(regparms, ep) \
+ __asm__("mov %0, %%ecx; \
+ mov %1, %%edx; \
+ call %2" : \
+ : \
+ "m"((regparms).first), \
+ "m"((regparms).second), \
+ "m"(ep));
+
+#define ARCH_SAVE_RETURN(archvalue, type) \
+ __asm__("mov %%eax, %0; \
+ mov %%edx, %1" : \
+ "=m"((archvalue).ivallow), \
+ "=m"((archvalue).ivalhigh)); \
+ if (type == CINV_T_FLOAT || type == CINV_T_DOUBLE) { \
+ __asm__("fstp %0" : "=m"((archvalue).dval)); \
+ }
+
+#define ARCH_SET_RETURN(archvalue, type) \
+ if (type == CINV_T_FLOAT || type == CINV_T_DOUBLE) { \
+ __asm__("fld %0" : \
+ : \
+ "f"((archvalue).dval) \
+ ); \
+ } \
+ __asm__("mov %0, %%eax; \
+ mov %1, %%edx" : \
+ : "m"((archvalue).ivallow), \
+ "m"((archvalue).ivalhigh) \
+ );
+
+#define ARCH_PUT_STACK_BYTES(bcount) \
+ __asm__("sub %0, %%esp" \
+ : "=r"(bcount));
+
+#define ARCH_REMOVE_STACK_BYTES(bcount) \
+ __asm__("add %0, %%esp" \
+ : "=r"(bcount));
+
+#define ARCH_GET_STACK(stackp) \
+ __asm__("mov %%esp, %0" \
+ : "=r"(stackp));
+
+#define ARCH_GET_FRAME_PTR(framep) \
+ __asm__("mov %%ebp, %0" \
+ : "=r"(framep));
+
+#define ARCH_CALLBACK_ARG_OFFSET (96)
+
+#define ARCH_BIG_ENDIAN 0
+
+#define ARCH_STACK_GROWS_DOWN 1
+
+#define ARCH_STACK_SKIPTOP 0
+
+#define ARCH_REGPARMS_IN_STACKSIZE 0
+
+#define ARCH_CLAMP_NONFIRST_STRUCTALIGN 0
+
+#endif
Modified: trunk/cinvoke/lib/cinvoke-arch.h
===================================================================
--- trunk/cinvoke/lib/cinvoke-arch.h 2007-09-01 18:59:08 UTC (rev 152)
+++ trunk/cinvoke/lib/cinvoke-arch.h 2008-07-29 03:29:39 UTC (rev 153)
@@ -76,6 +76,9 @@
#ifdef ARCH_CL_X86_WIN
#include "arch/cl_x86_win.h"
#endif
+#ifdef ARCH_GCC_X86_WIN
+#include "arch/gcc_x86_win.h"
+#endif
#ifdef ARCH_GCC_PPC_OSX
#include "arch/gcc_ppc_osx.h"
#endif
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [cinvoke-svn] r153 - in trunk/cinvoke: . lib lib/arch,
will <=