From 18a4f389f92b4ea64e0d3c2f7172938384e06de2 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Tue, 11 Jan 2011 18:46:50 +0000 Subject: [PATCH] Update to support current Go releases. The Go foreign function interface changed. This changes SWIG accordingly, and also fixes a couple of bugs. git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@12389 626c5289-ae23-0410-ae9c-e8d60b6d4f22 --- Lib/go/cdata.i | 79 ++------------------- Lib/go/go.swg | 18 ++--- Lib/go/goruntime.swg | 158 ++++++++++++------------------------------ Source/Modules/go.cxx | 35 ++++------ configure.in | 2 +- 5 files changed, 68 insertions(+), 224 deletions(-) diff --git a/Lib/go/cdata.i b/Lib/go/cdata.i index 6cfdffea1..0dac6420c 100644 --- a/Lib/go/cdata.i +++ b/Lib/go/cdata.i @@ -12,83 +12,12 @@ typedef struct SWIGCDATA { %} %typemap(gotype) SWIGCDATA %{ []byte %} -%typemap(out) SWIGCDATA (swigcdata argp) { - argp = _swig_makegobyteslice($1.data, $1.len); - $result.data = (char*)argp.data; - $result.len = (int)argp.len; -} - -/* The makegobyteslice function. */ - -%insert(runtime) %{ -typedef struct { - char *data; - int len; -} swigcdata; - +%typemap(out) SWIGCDATA %{ + $result.data = (char*)_swig_goallocate($1.len); + memcpy($result.data, $1.data, $1.len); + $result.len = (int)$1.len; %} -#ifndef SWIGGO_GCCGO -%insert(runtime) %{ -extern -#ifdef __cplusplus -"C" -#endif -void _swig_gc_makegobyteslice(void *, int); -static swigcdata _swig_makegobyteslice(const char *data, int len) { - struct { - const char *data; - int len; - swigcdata ret; - } a; - a.data = data; - a.len = len; - crosscall2(_swig_gc_makegobyteslice, &a, (int) sizeof a); - return a.ret; -} -%} - -%insert(gc_header) %{ -typedef struct { - byte *data; - int32 len; -} swigcdata; -extern void ·_swig_internal_makegobyteslice(void); -#pragma dynexport _swig_gc_makegobyteslice _swig_gc_makegobyteslice -void _swig_gc_makegobyteslice(void *a, int32 n) { - cgocallback(·_swig_internal_makegobyteslice, a, n); -} -void ·_swig_allocategobyteslice(byte *data, int32 len, swigcdata ret) { - ret.data = runtime·mal(len); - runtime·mcpy(ret.data, data, len); - ret.len = len; - FLUSH(&ret); -} -%} - -%insert(go_header) %{ -type swigcdata struct { data *byte; len int } -func _swig_allocategobyteslice(*byte, int) swigcdata -func _swig_internal_makegobyteslice(data *byte, len int) swigcdata { - return _swig_allocategobyteslice(data, len) -} -%} - -#else - -%insert(runtime) %{ -static swigcdata _swig_makegobyteslice(const char *data, int len) { - swigcdata ret; - ret.data = (char*)__go_alloc(len); - memcpy(ret.data, data, len); - ret.len = (int)len; - return ret; -} - -%} - -#endif - /* ----------------------------------------------------------------------------- * %cdata(TYPE [, NAME]) * diff --git a/Lib/go/go.swg b/Lib/go/go.swg index 648e112e1..53a910221 100644 --- a/Lib/go/go.swg +++ b/Lib/go/go.swg @@ -157,8 +157,8 @@ const float &, const double & %{ - $result = ($1_ltype)_swig_allocate(sizeof($*1_ltype)); - *$result = *($1_ltype)$input; + $result = ($1_ltype)_swig_goallocate(sizeof($*1_ltype)); + *$result = *($1_ltype)&$input; %} /* The size_t type. */ @@ -192,7 +192,7 @@ %typemap(directorout) const size_t & %{ - $result = ($1_ltype)_swig_allocate(sizeof($*1_ltype)); + $result = ($1_ltype)_swig_goallocate(sizeof($*1_ltype)); *$result = *($1_ltype)$input; %} @@ -206,7 +206,7 @@ %typemap(out) SWIGTYPE (CLASS::*) %{ - $result = _swig_allocate(sizeof($1_ltype)); + $result = _swig_goallocate(sizeof($1_ltype)); *($&1_ltype)$result = $1; %} @@ -215,7 +215,7 @@ %typemap(directorout) SWIGTYPE (CLASS::*) %{ - $result = _swig_allocate(sizeof($1_ltype)); + $result = _swig_goallocate(sizeof($1_ltype)); *($&1_ltype)$result = $input; %} @@ -254,14 +254,6 @@ %typemap(out) SWIGTYPE *const& %{ *($1_ltype)&$result = *$1; %} -/* Function pointers are translated by the code in go.cxx into - _swig_fnptr. Member pointers are translated to _swig_memberptr. */ - -%insert(go_header) %{ -type _swig_fnptr *byte -type _swig_memberptr *byte -%} - /* References. */ /* Converting a C++ reference to Go has to be handled in the C++ diff --git a/Lib/go/goruntime.swg b/Lib/go/goruntime.swg index 6cde68f55..6aeeab730 100644 --- a/Lib/go/goruntime.swg +++ b/Lib/go/goruntime.swg @@ -30,57 +30,32 @@ swiggo_size_assert(swiggo_long_long, 8) swiggo_size_assert(float, 4) swiggo_size_assert(double, 8) -extern #ifdef __cplusplus -"C" +extern "C" { +#endif +extern void crosscall2(void (*fn)(void *, int), void *, int); +extern void _cgo_allocate(void *, int); +extern void _cgo_panic(void *, int); +#ifdef __cplusplus +} #endif -void crosscall2(void (*fn)(void *, int), void *, int); -extern -#ifdef __cplusplus -"C" -#endif -void _swig_gc_allocate(void *, int); -static void *_swig_allocate(int len) { +static void *_swig_goallocate(size_t len) { struct { - int len; + size_t len; void *ret; } a; a.len = len; - crosscall2(_swig_gc_allocate, &a, (int) sizeof a); + crosscall2(_cgo_allocate, &a, (int) sizeof a); return a.ret; } -extern -#ifdef __cplusplus -"C" -#endif -void _swig_gc_makegostring(void *, int); -static _gostring_ _swig_makegostring(const char *p, size_t l) { - struct { - const char *p; - int l; - _gostring_ ret; - } a; - a.p = p; - a.l = l; - crosscall2(_swig_gc_makegostring, &a, (int) sizeof a); - return a.ret; -} - -extern -#ifdef __cplusplus -"C" -#endif -void _swig_gc_gopanic(void *, int); static void _swig_gopanic(const char *p) { struct { const char *p; - int l; } a; a.p = p; - a.l = strlen(p); - crosscall2(_swig_gc_gopanic, &a, (int) sizeof a); + crosscall2(_cgo_panic, &a, (int) sizeof a); } %} @@ -91,10 +66,6 @@ static void _swig_gopanic(const char *p) { #include "runtime.h" #include "cgocall.h" -#pragma dynimport initcgo initcgo "libcgo.so" -#pragma dynimport libcgo_thread_start libcgo_thread_start "libcgo.so" -#pragma dynimport libcgo_set_scheduler libcgo_set_scheduler "libcgo.so" - #ifdef _64BIT #define SWIG_PARM_SIZE 8 #else @@ -102,97 +73,56 @@ static void _swig_gopanic(const char *p) { #endif %} -/* 6g/8g C boilerplate that is only needed once in a program. This - only gets added to the file if nothing is imported. */ -%insert(gc_once) %{ - -extern void ·_swig_internal_allocate(void); -#pragma dynexport _swig_gc_allocate _swig_gc_allocate -void _swig_gc_allocate(void *a, int32 n) { - runtime·cgocallback(·_swig_internal_allocate, a, n); -} - -void ·_swig_allocatememory(int32 len, byte *ret) { - ret = runtime·mal(len); - FLUSH(&ret); -} - -extern void ·_swig_internal_makegostring(void); -#pragma dynexport _swig_gc_makegostring _swig_gc_makegostring -void _swig_gc_makegostring(void *a, int32 n) { - runtime·cgocallback(·_swig_internal_makegostring, a, n); -} - -void ·_swig_allocatestring(byte *p, int32 l, String ret) { - ret.str = runtime·mal(l+1); - runtime·mcpy(ret.str, p, l); - ret.len = l; - FLUSH(&ret); -} - -extern void ·_swig_internal_gopanic(void); -#pragma dynexport _swig_gc_gopanic _swig_gc_gopanic -void _swig_gc_gopanic(void *a, int32 n) { - runtime·cgocallback(·_swig_internal_gopanic, a, n); -} - -%} - -/* Go code that is only needed once in a program. This is only added - to the file if nothing is imported. */ -%insert(go_once) %{ -func _swig_allocatememory(int) *byte -func _swig_internal_allocate(len int) *byte { - return _swig_allocatememory(len) -} - -func _swig_allocatestring(*byte, int) string -func _swig_internal_makegostring(p *byte, l int) string { - return _swig_allocatestring(p, l) -} - -func _swig_internal_gopanic(p *byte, l int) { - panic(_swig_allocatestring(p, l)) -} -%} - #else /* Boilerplate for C/C++ code when using gccgo. */ %insert(runtime) %{ #define SWIGGO_GCCGO -extern #ifdef __cplusplus -"C" +extern "C" { #endif -void *__go_alloc (size_t); - -static void *_swig_allocate(int len) { - return __go_alloc(len); -} - -static _gostring_ _swig_makegostring(const char *p, size_t l) { - _gostring_ ret; - ret.p = (char*)__go_alloc(l); - memcpy(ret.p, p, l); - ret.n = l; - return ret; -} - -extern +extern void *_cgo_allocate(size_t); +extern void _cgo_panic(const char *); #ifdef __cplusplus -"C" +} #endif -void __go_panic_msg(const char *); -#define _swig_gopanic __go_panic_msg + +#define _swig_goallocate _cgo_allocate +#define _swig_gopanic _cgo_panic %} #endif %insert(runtime) %{ + +static _gostring_ _swig_makegostring(const char *p, size_t l) { + _gostring_ ret; + ret.p = (char*)_swig_goallocate(l + 1); + memcpy(ret.p, p, l); + ret.n = l; + return ret; +} + #define SWIG_contract_assert(expr, msg) \ if (!(expr)) { _swig_gopanic(msg); } else %} +#ifndef SWIGGO_GCCGO + +%insert(go_header) %{ + +import _ "runtime/cgo" + +%} + +#endif + +/* Function pointers are translated by the code in go.cxx into + _swig_fnptr. Member pointers are translated to _swig_memberptr. */ + +%insert(go_header) %{ +type _swig_fnptr *byte +type _swig_memberptr *byte +%} diff --git a/Source/Modules/go.cxx b/Source/Modules/go.cxx index ac8ba333d..094b1dd5a 100644 --- a/Source/Modules/go.cxx +++ b/Source/Modules/go.cxx @@ -43,11 +43,9 @@ class GO:public Language { File *f_go_runtime; File *f_go_header; File *f_go_wrappers; - File *f_go_once; File *f_gc_runtime; File *f_gc_header; File *f_gc_wrappers; - File *f_gc_once; // True if we imported a module. bool saw_import; @@ -100,11 +98,9 @@ public: f_go_runtime(NULL), f_go_header(NULL), f_go_wrappers(NULL), - f_go_once(NULL), f_gc_runtime(NULL), f_gc_header(NULL), f_gc_wrappers(NULL), - f_gc_once(NULL), saw_import(false), imported_package(NULL), interfaces(NULL), @@ -303,12 +299,10 @@ private: f_go_runtime = NewString(""); f_go_header = NewString(""); f_go_wrappers = NewString(""); - f_go_once = NewString(""); if (!gccgo_flag) { f_gc_runtime = NewString(""); f_gc_header = NewString(""); f_gc_wrappers = NewString(""); - f_gc_once = NewString(""); } Swig_register_filebyname("begin", f_c_begin); @@ -322,13 +316,11 @@ private: Swig_register_filebyname("go_runtime", f_go_runtime); Swig_register_filebyname("go_header", f_go_header); Swig_register_filebyname("go_wrapper", f_go_wrappers); - Swig_register_filebyname("go_once", f_go_once); if (!gccgo_flag) { Swig_register_filebyname("gc_begin", f_gc_begin); Swig_register_filebyname("gc_runtime", f_gc_runtime); Swig_register_filebyname("gc_header", f_gc_header); Swig_register_filebyname("gc_wrapper", f_gc_wrappers); - Swig_register_filebyname("gc_once", f_gc_once); } Swig_banner(f_c_begin); @@ -349,6 +341,7 @@ private: if (!gccgo_flag) { Swig_banner(f_gc_begin); Printf(f_gc_begin, "\n/* This file should be compiled with 6c/8c. */\n"); + Printf(f_gc_begin, "#pragma dynimport _ _ \"%s\"\n", soname); } // Output module initialization code. @@ -414,16 +407,10 @@ private: Dump(f_c_wrappers, f_c_begin); Dump(f_c_init, f_c_begin); Dump(f_go_header, f_go_begin); - if (!saw_import) { - Dump(f_go_once, f_go_begin); - } Dump(f_go_runtime, f_go_begin); Dump(f_go_wrappers, f_go_begin); if (!gccgo_flag) { Dump(f_gc_header, f_gc_begin); - if (!saw_import) { - Dump(f_gc_once, f_gc_begin); - } Dump(f_gc_runtime, f_gc_begin); Dump(f_gc_wrappers, f_gc_begin); } @@ -1011,8 +998,9 @@ private: int gcFunctionWrapper(Node *n, String *name, String *go_name, String *overname, String *wname, ParmList *parms, SwigType *result, bool is_static, bool needs_wrapper) { Wrapper *f = NewWrapper(); - Printv(f->def, "#pragma dynimport ", wname, " ", wname, " \"", soname, "\"\n", NULL); - Printv(f->def, "void (*", wname, ")(void*);\n", NULL); + Printv(f->def, "#pragma dynimport ", wname, " ", wname, " \"\"\n", NULL); + Printv(f->def, "extern void (*", wname, ")(void*);\n", NULL); + Printv(f->def, "static void (*x", wname, ")(void*) = ", wname, ";\n", NULL); Printv(f->def, "\n", NULL); Printv(f->def, "void\n", NULL); @@ -1068,7 +1056,7 @@ private: Delete(parm_size); Printv(f->code, "{\n", NULL); - Printv(f->code, "\truntime\xc2\xb7" "cgocall(", wname, ", &p);\n", NULL); + Printv(f->code, "\truntime\xc2\xb7" "cgocall(x", wname, ", &p);\n", NULL); Printv(f->code, "}\n", NULL); Printv(f->code, "\n", NULL); @@ -1166,7 +1154,7 @@ private: p = nextParm(p); } if (SwigType_type(result) != T_VOID) { - Printv(f->code, "\t\tint : 0;\n", NULL); + Printv(f->code, "\t\tlong : 0;\n", NULL); String *ln = NewString("result"); String *ct = gcCTypeForGoValue(n, result, ln); Delete(ln); @@ -1270,7 +1258,11 @@ private: Parm *p = parms; for (int i = 0; i < parm_count; ++i) { p = getParm(p); - SwigType *pt = Getattr(p, "type"); + SwigType *pt = Copy(Getattr(p, "type")); + if (SwigType_isarray(pt)) { + SwigType_del_array(pt); + SwigType_add_pointer(pt); + } String *pn = NewString("g"); Append(pn, Getattr(p, "lname")); String *ct = gccgoCTypeForGoValue(p, pt, pn); @@ -1280,6 +1272,7 @@ private: Printv(fnname, ct, NULL); Delete(ct); Delete(pn); + Delete(pt); p = nextParm(p); } @@ -3415,7 +3408,7 @@ private: p = Getattr(p, "tmap:directorin:next"); } if (SwigType_type(result) != T_VOID) { - Printv(f->code, " int : 0;\n", NULL); + Printv(f->code, " long : 0;\n", NULL); String *rname = NewString("result"); String *cg = gcCTypeForGoValue(n, result, rname); Printv(f->code, " ", cg, ";\n", NULL); @@ -3545,7 +3538,7 @@ private: } } else { assert(is_pure_virtual); - Printv(f->code, " _swig_gopanic(\"call to pure virtual function ", Getattr(parent, "sym:name"), name, "\");\n"); + Printv(f->code, " _swig_gopanic(\"call to pure virtual function ", Getattr(parent, "sym:name"), name, "\");\n", NULL); if (SwigType_type(result) != T_VOID) { String *retstr = SwigType_rcaststr(Getattr(n, "returntype"), "c_result"); Printv(f->code, " return ", retstr, ";\n", NULL); diff --git a/configure.in b/configure.in index 50f396226..e783c7d3c 100644 --- a/configure.in +++ b/configure.in @@ -2013,7 +2013,7 @@ else else AC_MSG_CHECKING([whether Go ($GO) version is too old]) go_version=`$GO -V | sed -e 's/.*version \([[0-9]]*\).*/\1/'` - go_min_version=6707 + go_min_version=7077 if test "$go_version" -lt $go_min_version; then AC_MSG_RESULT([yes - minimum version is $go_min_version]) GO=