summaryrefslogtreecommitdiff
path: root/Source/Modules/go.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'Source/Modules/go.cxx')
-rw-r--r--Source/Modules/go.cxx961
1 files changed, 690 insertions, 271 deletions
diff --git a/Source/Modules/go.cxx b/Source/Modules/go.cxx
index e84109faf..eac83a5a5 100644
--- a/Source/Modules/go.cxx
+++ b/Source/Modules/go.cxx
@@ -822,14 +822,13 @@ private:
assert(result);
- bool needs_wrapper;
- int r = goFunctionWrapper(n, name, go_name, overname, wname, base, parms, result, is_static, &needs_wrapper);
+ int r = goFunctionWrapper(n, name, go_name, overname, wname, base, parms, result, is_static);
if (r != SWIG_OK) {
return r;
}
if (!gccgo_flag) {
- r = gcFunctionWrapper(n, name, go_name, overname, wname, parms, result, is_static, needs_wrapper);
+ r = gcFunctionWrapper(wname);
if (r != SWIG_OK) {
return r;
}
@@ -862,12 +861,24 @@ private:
* base class.
* ---------------------------------------------------------------------- */
- int goFunctionWrapper(Node *n, String *name, String *go_name, String *overname, String *wname, List *base, ParmList *parms, SwigType *result, bool is_static, bool *p_needs_wrapper) {
+ int goFunctionWrapper(Node *n, String *name, String *go_name, String *overname, String *wname, List *base, ParmList *parms, SwigType *result, bool is_static) {
Wrapper *dummy = NewWrapper();
emit_attach_parmmaps(parms, dummy);
+
+ Parm *p = parms;
+ int parm_count = emit_num_arguments(parms);
+ for (int i = 0; i < parm_count; ++i) {
+ p = getParm(p);
+ Swig_cparm_name(p, i);
+ p = nextParm(p);
+ }
+
Swig_typemap_attach_parms("default", parms, dummy);
Swig_typemap_attach_parms("gotype", parms, dummy);
- int parm_count = emit_num_arguments(parms);
+ Swig_typemap_attach_parms("goin", parms, dummy);
+ Swig_typemap_attach_parms("goargout", parms, dummy);
+ Swig_typemap_attach_parms("imtype", parms, dummy);
+
int required_count = emit_num_required(parms);
String *receiver = class_receiver;
@@ -884,30 +895,44 @@ private:
receiver = NULL;
}
+ String *goout = Swig_typemap_lookup("goout", n, "swig_r", NULL);
+
bool add_to_interface = (interfaces && !is_constructor && !is_destructor && !is_static && !overname && checkFunctionVisibility(n, NULL));
bool needs_wrapper = (gccgo_flag || receiver || is_constructor || is_destructor || parm_count > required_count);
+ bool has_goout = false;
+ if (goout) {
+ has_goout = true;
+ }
+
// See whether any of the function parameters are represented by
- // interface values When calling the C++ code, we need to convert
+ // interface values. When calling the C++ code, we need to convert
// back to a uintptr.
- if (!needs_wrapper) {
- Parm *p = parms;
- for (int i = 0; i < parm_count; ++i) {
- p = getParm(p);
- String *ty = Getattr(p, "type");
- if (goTypeIsInterface(p, ty)) {
- needs_wrapper = true;
- break;
- }
- p = nextParm(p);
+ p = parms;
+ for (int i = 0; i < parm_count; ++i) {
+ p = getParm(p);
+ String *ty = Getattr(p, "type");
+ if (Getattr(p, "tmap:goargout")) {
+ has_goout = true;
+ needs_wrapper = true;
+ } else if (goTypeIsInterface(p, ty) || Getattr(p, "tmap:goin")) {
+ needs_wrapper = true;
}
+
+ if (paramNeedsEscape(p)) {
+ needs_wrapper = true;
+ }
+
+ p = nextParm(p);
}
- if (goTypeIsInterface(n, result)) {
+ if (goTypeIsInterface(n, result) || goout != NULL) {
needs_wrapper = true;
}
- *p_needs_wrapper = needs_wrapper;
+ if (!gccgo_flag) {
+ Printv(f_go_wrappers, "var ", wname, " unsafe.Pointer\n\n", NULL);
+ }
// If this is a method, first declare the C function we will call.
// If we do not need a wrapper, then we will only be writing a
@@ -920,25 +945,25 @@ private:
Printv(f_go_wrappers, "//extern ", go_prefix, "_", wname, "\n", NULL);
}
+ bool arg = false;
Printv(f_go_wrappers, "func ", wrapper_name, "(", NULL);
if (parm_count > required_count) {
- Printv(f_go_wrappers, "int", NULL);
+ Printv(f_go_wrappers, argName(&arg), " int", NULL);
}
Parm *p = getParm(parms);
- Swig_cparm_name(p, 0);
int i = 0;
if (is_destructor) {
if (parm_count > required_count) {
Printv(f_go_wrappers, ", ", NULL);
}
- Printv(f_go_wrappers, "uintptr", NULL);
+ Printv(f_go_wrappers, argName(&arg), " uintptr", NULL);
++i;
p = nextParm(p);
} else if (receiver && (base || !is_constructor)) {
if (parm_count > required_count) {
Printv(f_go_wrappers, ", ", NULL);
}
- Printv(f_go_wrappers, receiver, NULL);
+ Printv(f_go_wrappers, argName(&arg), " ", receiver, NULL);
if (!base) {
++i;
p = nextParm(p);
@@ -946,27 +971,37 @@ private:
}
for (; i < parm_count; ++i) {
p = getParm(p);
- // Give the parameter a name we will use below.
- Swig_cparm_name(p, i);
if (i > 0 || (base && receiver) || parm_count > required_count) {
Printv(f_go_wrappers, ", ", NULL);
}
String *tm = goWrapperType(p, Getattr(p, "type"), false);
- Printv(f_go_wrappers, tm, NULL);
+ Printv(f_go_wrappers, argName(&arg), " ", tm, NULL);
Delete(tm);
p = nextParm(p);
}
Printv(f_go_wrappers, ")", NULL);
if (is_constructor) {
- Printv(f_go_wrappers, " ", class_receiver, NULL);
+ Printv(f_go_wrappers, " (", argName(&arg), " ", class_receiver, ")", NULL);
} else {
if (SwigType_type(result) != T_VOID) {
String *tm = goWrapperType(n, result, true);
- Printv(f_go_wrappers, " ", tm, NULL);
+ Printv(f_go_wrappers, " (", argName(&arg), " ", tm, ")", NULL);
Delete(tm);
}
}
+ if (!gccgo_flag) {
+ Printv(f_go_wrappers, " {\n", NULL);
+ if (arg) {
+ Printv(f_go_wrappers, "\t_swig_p := uintptr(unsafe.Pointer(&base))\n", NULL);
+ } else {
+ Printv(f_go_wrappers, "\tvar _swig_p uintptr\n", NULL);
+ }
+ Printv(f_go_wrappers, "\t_cgo_runtime_cgocall(", wname, ", _swig_p)\n", NULL);
+ Printv(f_go_wrappers, "\treturn\n", NULL);
+ Printv(f_go_wrappers, "}", NULL);
+ }
+
Printv(f_go_wrappers, "\n\n", NULL);
}
@@ -978,16 +1013,23 @@ private:
Printv(f_go_wrappers, "func ", NULL);
- Parm *p = parms;
+ p = parms;
int pi = 0;
// Add the receiver if this is a method.
+ String *first = NULL;
if (receiver) {
Printv(f_go_wrappers, "(", NULL);
if (base && receiver) {
Printv(f_go_wrappers, "_swig_base", NULL);
+ if (first == NULL) {
+ first = NewString("_swig_base");
+ }
} else {
Printv(f_go_wrappers, Getattr(p, "lname"), NULL);
+ if (first == NULL) {
+ first = Copy(Getattr(p, "lname"));
+ }
p = nextParm(p);
++pi;
}
@@ -1015,6 +1057,9 @@ private:
if (pi == 0 && is_destructor) {
String *cl = exportedName(class_name);
Printv(parm_print, Getattr(p, "lname"), " ", cl, NULL);
+ if (first == NULL) {
+ first = Copy(Getattr(p, "lname"));
+ }
Delete(cl);
} else {
if (pi > (receiver && !base ? 1 : 0)) {
@@ -1022,10 +1067,14 @@ private:
}
if (pi >= required_count) {
Printv(parm_print, "_swig_args ...interface{}", NULL);
+ if (first == NULL) {
+ first = NewString("_swig_args");
+ }
break;
}
- if (needs_wrapper) {
- Printv(parm_print, Getattr(p, "lname"), " ", NULL);
+ Printv(parm_print, Getattr(p, "lname"), " ", NULL);
+ if (first == NULL) {
+ first = Copy(Getattr(p, "lname"));
}
String *tm = goType(p, Getattr(p, "type"));
Printv(parm_print, tm, NULL);
@@ -1039,12 +1088,18 @@ private:
// Write out the result type.
if (is_constructor) {
String *cl = exportedName(class_name);
- Printv(parm_print, " ", cl, NULL);
+ Printv(parm_print, " (_swig_ret ", cl, ")", NULL);
+ if (first == NULL) {
+ first = NewString("_swig_ret");
+ }
Delete(cl);
} else {
if (SwigType_type(result) != T_VOID) {
String *tm = goType(n, result);
- Printv(parm_print, " ", tm, NULL);
+ Printv(parm_print, " (_swig_ret ", tm, ")", NULL);
+ if (first == NULL) {
+ first = NewString("_swig_ret");
+ }
Delete(tm);
}
}
@@ -1077,46 +1132,49 @@ private:
}
}
- if (gccgo_flag) {
- if (!is_constructor) {
- Printv(f_go_wrappers, "\tdefer SwigCgocallDone()\n", NULL);
- Printv(f_go_wrappers, "\tSwigCgocall()\n", NULL);
+ String *call = NewString("");
+
+ bool need_return_var = SwigType_type(result) != T_VOID && ((gccgo_flag && is_constructor) || has_goout);
+ if (need_return_var) {
+ Printv(f_go_wrappers, "\tvar swig_r ", NULL);
+ if (is_constructor) {
+ String *cl = exportedName(class_name);
+ Printv(f_go_wrappers, cl, NULL);
+ Delete(cl);
} else {
- // For a constructor the wrapper function will return a
- // uintptr but we will return an interface. We want to
- // convert the uintptr to the interface after calling
- // SwigCgocallDone, so that we don't try to allocate memory
- // while the Go scheduler can't see us.
- Printv(f_go_wrappers, "\tvar done bool\n", NULL);
- Printv(f_go_wrappers, "\tdefer func() {\n", NULL);
- Printv(f_go_wrappers, "\t\tif !done {\n", NULL);
- Printv(f_go_wrappers, "\t\t\tSwigCgocallDone()\n", NULL);
- Printv(f_go_wrappers, "\t\t}\n", NULL);
- Printv(f_go_wrappers, "\t}()\n", NULL);
- Printv(f_go_wrappers, "\tSwigCgocall()\n", NULL);
+ Printv(f_go_wrappers, goImType(n, result), NULL);
+ }
+ Printv(f_go_wrappers, "\n", NULL);
+ }
+
+ if (gccgo_flag) {
+ if (has_goout || is_constructor) {
+ Printv(call, "\tfunc() {\n", NULL);
}
+ Printv(call, "\tdefer SwigCgocallDone()\n", NULL);
+ Printv(call, "\tSwigCgocall()\n", NULL);
}
- Printv(f_go_wrappers, "\t", NULL);
+ Printv(call, "\t", NULL);
if (SwigType_type(result) != T_VOID) {
- if (gccgo_flag && is_constructor) {
- Printv(f_go_wrappers, "swig_r := ", NULL);
+ if (need_return_var) {
+ Printv(call, "swig_r = ", NULL);
} else {
- Printv(f_go_wrappers, "return ", NULL);
+ Printv(call, "return ", NULL);
}
}
- Printv(f_go_wrappers, wrapper_name, "(", NULL);
+ Printv(call, wrapper_name, "(", NULL);
if (parm_count > required_count) {
- Printv(f_go_wrappers, "len(_swig_args)", NULL);
+ Printv(call, "len(_swig_args)", NULL);
}
if (base && receiver) {
if (parm_count > required_count) {
- Printv(f_go_wrappers, ", ", NULL);
+ Printv(call, ", ", NULL);
}
- Printv(f_go_wrappers, "_swig_base", NULL);
+ Printv(call, "_swig_base", NULL);
}
Parm *p = parms;
@@ -1124,29 +1182,82 @@ private:
p = getParm(p);
if (i > 0 || (base && receiver)
|| parm_count > required_count) {
- Printv(f_go_wrappers, ", ", NULL);
+ Printv(call, ", ", NULL);
+ }
+
+ SwigType *pt = Getattr(p, "type");
+ String *ln = Getattr(p, "lname");
+
+ String *goin = Getattr(p, "tmap:goin");
+ if (goin == NULL) {
+ Printv(call, ln, NULL);
+ if ((i == 0 && is_destructor) || ((i > 0 || !receiver || base || is_constructor) && goTypeIsInterface(p, pt))) {
+ Printv(call, ".Swigcptr()", NULL);
+ }
+ Setattr(p, "emit:goinput", ln);
+ } else {
+ String *ivar = NewString("");
+ Printf(ivar, "_swig_i_%d", i);
+ String *itm = goImType(p, pt);
+ Printv(f_go_wrappers, "\tvar ", ivar, " ", itm, NULL);
+ goin = Copy(goin);
+ Replaceall(goin, "$input", ln);
+ Replaceall(goin, "$result", ivar);
+ Printv(f_go_wrappers, goin, NULL);
+ Delete(goin);
+ Printv(call, ivar, NULL);
+ Setattr(p, "emit:goinput", ivar);
}
- Printv(f_go_wrappers, Getattr(p, "lname"), NULL);
- // If this is a destructor, then the C function expects the
- // C++ value, and we have the interface. We need to get the
- // C++ value. The same is true for a type represented as an
- // interface.
- if ((i == 0 && is_destructor) || ((i > 0 || !receiver || base || is_constructor) && goTypeIsInterface(p, Getattr(p, "type")))) {
- Printv(f_go_wrappers, ".Swigcptr()", NULL);
+ // If the parameter has an argout or freearg typemap, make
+ // sure that it escapes.
+ if (paramNeedsEscape(p)) {
+ Printv(f_go_wrappers, "\tif Swig_escape_always_false {\n", NULL);
+ Printv(f_go_wrappers, "\t\tSwig_escape_val = ", Getattr(p, "emit:goinput"), "\n", NULL);
+ Printv(f_go_wrappers, "\t}\n", NULL);
}
p = nextParm(p);
}
- Printv(f_go_wrappers, ")\n", NULL);
+ Printv(call, ")\n", NULL);
+
+ if (gccgo_flag && (has_goout || is_constructor)) {
+ Printv(call, "\t}()\n", NULL);
+ }
- if (gccgo_flag && is_constructor) {
- Printv(f_go_wrappers, "\tSwigCgocallDone()\n", NULL);
- Printv(f_go_wrappers, "\tdone = true\n", NULL);
- Printv(f_go_wrappers, "\treturn swig_r\n", NULL);
+ Printv(f_go_wrappers, call, NULL);
+ Delete(call);
+
+ goargout(parms, parm_count);
+
+ if (need_return_var) {
+ if (goout == NULL) {
+ Printv(f_go_wrappers, "\treturn swig_r\n", NULL);
+ } else {
+ String *tm = goType(n, result);
+ Printv(f_go_wrappers, "\tvar swig_r_1 ", tm, "\n", NULL);
+ Replaceall(goout, "$input", "swig_r");
+ Replaceall(goout, "$result", "swig_r_1");
+ Printv(f_go_wrappers, goout, NULL);
+ Printv(f_go_wrappers, "\treturn swig_r_1\n", NULL);
+ }
}
Printv(f_go_wrappers, "}\n", NULL);
+ } else if (!gccgo_flag) {
+ // We don't need a wrapper. If we're using gccgo, the function
+ // declaration is all we need--it has a //extern comment to
+ // GCC-compiled wrapper. If we're not using gccgo, we need to
+ // call the GCC-compiled wrapper here.
+ Printv(f_go_wrappers, " {\n", NULL);
+ if (first == NULL) {
+ Printv(f_go_wrappers, "\tvar _swig_p uintptr\n", NULL);
+ } else {
+ Printv(f_go_wrappers, "\t_swig_p := uintptr(unsafe.Pointer(&", first, "))\n", NULL);
+ }
+ Printv(f_go_wrappers, "\t_cgo_runtime_cgocall(", wname, ", _swig_p)\n", NULL);
+ Printv(f_go_wrappers, "\treturn\n", NULL);
+ Printv(f_go_wrappers, "}", NULL);
}
Printv(f_go_wrappers, "\n", NULL);
@@ -1158,118 +1269,72 @@ private:
}
/* ----------------------------------------------------------------------
- * gcFunctionWrapper()
+ * argName()
*
- * This is used for 6g/8g, not for gccgo. Write out the function
- * wrapper which will be compiled with 6c/8c.
+ * A helper for goFunctionWrapper to output the first argument name
+ * as "base" and all others as "_".
* ---------------------------------------------------------------------- */
- 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, " \"\"\n", NULL);
- Printv(f->def, "#pragma cgo_import_static ", 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);
-
- Wrapper *dummy = NewWrapper();
- emit_attach_parmmaps(parms, dummy);
- Swig_typemap_attach_parms("default", parms, dummy);
- Swig_typemap_attach_parms("gosize", parms, dummy);
- int parm_count = emit_num_arguments(parms);
- int required_count = emit_num_required(parms);
-
- String *parm_size = NewString("");
-
- if (parm_count > required_count) {
- Append(parm_size, "SWIG_PARM_SIZE");
- }
-
- if (class_receiver && !is_static) {
- if (Len(parm_size) > 0) {
- Append(parm_size, " + ");
- }
- Append(parm_size, "SWIG_PARM_SIZE");
+ const char *argName(bool *arg) {
+ if (*arg) {
+ return "_";
}
+ *arg = true;
+ return "base";
+ }
- Parm *p = parms;
- for (int i = 0; i < parm_count; ++i) {
- p = getParm(p);
- addGcTypeSize(p, Getattr(p, "type"), parm_size);
- p = nextParm(p);
+ /* ----------------------------------------------------------------------
+ * paramNeedsEscape()
+ *
+ * A helper for goFunctionWrapper that returns whether a parameter
+ * needs to explicitly escape. This is true if the parameter has a
+ * non-empty argout or freearg typemap, because in those cases the
+ * Go argument might be or contain a pointer. We need to ensure
+ * that that pointer does not oint into the stack, which means that
+ * it needs to escape.
+ * ---------------------------------------------------------------------- */
+ bool paramNeedsEscape(Parm *p) {
+ String *argout = Getattr(p, "tmap:argout");
+ String *freearg = Getattr(p, "tmap:freearg");
+ if ((!argout || Len(argout) == 0) && (!freearg || Len(freearg) == 0)) {
+ return false;
}
-
- if (SwigType_type(result) != T_VOID) {
- addGcTypeSize(n, result, parm_size);
+ // If a C++ type is represented as an interface type in Go, then
+ // we don't care whether it escapes, because we know that the
+ // pointer is a C++ pointer.
+ if (goTypeIsInterface(p, Getattr(p, "type"))) {
+ return false;
}
+ return true;
+ }
- if (Len(parm_size) == 0) {
- Append(parm_size, "1");
- }
+ /* ----------------------------------------------------------------------
+ * gcFunctionWrapper()
+ *
+ * This is used for 6g/8g, not for gccgo. Write out the function
+ * redirector that will be compiled with 6c/8c. This used to write
+ * out a real function wrapper, but that has moved into Go code.
+ * ---------------------------------------------------------------------- */
- String *fn_name;
- if (!needs_wrapper) {
- fn_name = Copy(go_name);
- if (overname) {
- Append(fn_name, overname);
- }
- } else {
- fn_name = buildGoWrapperName(name, overname);
- }
+ int gcFunctionWrapper(String *wname) {
+ Wrapper *f = NewWrapper();
+ Printv(f->def, "#pragma dynimport ", wname, " ", wname, " \"\"\n", NULL);
+ Printv(f->def, "#pragma cgo_import_static ", wname, "\n", NULL);
+ Printv(f->def, "extern void ", wname, "(void*);\n", NULL);
+ // Declare this as a uintptr, since it is not a pointer into the
+ // Go heap.
// \xc2\xb7 is UTF-8 for U+00B7 which is Unicode 'Middle Dot'
- Printv(f->def, "\xc2\xb7", fn_name, "(struct { uint8 x[", parm_size, "];} p)", NULL);
-
- Delete(fn_name);
- Delete(parm_size);
-
- Printv(f->code, "{\n", NULL);
- Printv(f->code, "\truntime\xc2\xb7" "cgocall(x", wname, ", &p);\n", NULL);
- Printv(f->code, "}\n", NULL);
- Printv(f->code, "\n", NULL);
+ Printv(f->def, "uintptr \xc2\xb7", wname, " = (uintptr)", wname, ";\n", NULL);
Wrapper_print(f, f_gc_wrappers);
DelWrapper(f);
- DelWrapper(dummy);
return SWIG_OK;
}
/* ----------------------------------------------------------------------
- * getGcTypeSize()
- *
- * Return the size to use when passing a type from 6g/8g to 6c/8c.
- * ---------------------------------------------------------------------- */
-
- String *addGcTypeSize(Node *n, SwigType *type, String *orig) {
- if (Len(orig) > 0) {
- Append(orig, " + ");
- }
-
- String *go = goType(n, type);
- if (Cmp(go, "string") == 0) {
- // A string has a pointer and a length.
- Append(orig, "(2 * SWIG_PARM_SIZE)");
- } else if (Strncmp(go, "[]", 2) == 0) {
- // A slice has a pointer, a length, and a capacity.
- Append(orig, "(3 * SWIG_PARM_SIZE)");
- } else if (Strcmp(go, "float64") == 0) {
- Append(orig, "8");
- } else if (Strcmp(go, "complex64") == 0) {
- Append(orig, "8");
- } else if (Strcmp(go, "complex128") == 0) {
- Append(orig, "16");
- } else {
- Append(orig, "SWIG_PARM_SIZE");
- }
-
- return orig;
- }
-
- /* ----------------------------------------------------------------------
* gccFunctionWrapper()
*
* This is used for 6g/8g, not for gccgo. Write out the function
@@ -1315,11 +1380,19 @@ private:
Parm *p = parms;
for (int i = 0; i < parm_count; ++i) {
p = getParm(p);
+
String *ln = Getattr(p, "lname");
SwigType *pt = Getattr(p, "type");
String *ct = gcCTypeForGoValue(p, pt, ln);
Printv(f->code, "\t\t\t", ct, ";\n", NULL);
Delete(ct);
+
+ String *gn = NewStringf("_swig_go_%d", i);
+ ct = gcCTypeForGoValue(p, pt, gn);
+ Setattr(p, "emit:input", gn);
+ Wrapper_add_local(f, gn, ct);
+ Delete(ct);
+
p = nextParm(p);
}
if (SwigType_type(result) != T_VOID) {
@@ -1329,27 +1402,39 @@ private:
Delete(ln);
Printv(f->code, "\t\t", ct, ";\n", NULL);
Delete(ct);
+
+ ln = NewString("_swig_go_result");
+ ct = gcCTypeForGoValue(n, result, ln);
+ Wrapper_add_local(f, "_swig_go_result", ct);
+ Delete(ct);
+ Delete(ln);
}
Printv(f->code, "\t} *swig_a = (struct swigargs *) swig_v;\n", NULL);
Printv(f->code, "\n", NULL);
- // Copy the input arguments out of the structure into the
- // parameter variables.
-
+ // Copy the input arguments out of the structure into the Go local
+ // variables.
p = parms;
for (int i = 0; i < parm_count; ++i) {
p = getParm(p);
+ String *ln = Getattr(p, "lname");
+ String *gn = Getattr(p, "emit:input");
+ Printv(f->code, "\t", gn, " = swig_a->", ln, ";\n", NULL);
+ p = nextParm(p);
+ }
+ // Apply the in typemaps.
+ p = parms;
+ for (int i = 0; i < parm_count; ++i) {
+ p = getParm(p);
String *tm = Getattr(p, "tmap:in");
if (!tm) {
Swig_warning(WARN_TYPEMAP_IN_UNDEF, input_file, line_number, "Unable to use type %s as a function argument\n", SwigType_str(Getattr(p, "type"), 0));
} else {
- String *ln = Getattr(p, "lname");
- String *input = NewString("");
- Printv(input, "swig_a->", ln, NULL);
- Replaceall(tm, "$input", input);
- Setattr(p, "emit:input", input);
+ tm = Copy(tm);
+ String *gn = Getattr(p, "emit:input");
+ Replaceall(tm, "$input", gn);
if (i < required_count) {
Printv(f->code, "\t", tm, "\n", NULL);
} else {
@@ -1357,6 +1442,7 @@ private:
Printv(f->code, "\t\t", tm, "\n", NULL);
Printv(f->code, "\t}\n", NULL);
}
+ Delete(tm);
}
p = nextParm(p);
}
@@ -1464,9 +1550,9 @@ private:
Delete(fndef);
if (SwigType_type(result) != T_VOID) {
- String *ln = NewString("go_result");
+ String *ln = NewString("_swig_go_result");
String *ct = gccgoCTypeForGoValue(n, result, ln);
- Wrapper_add_local(f, "go_result", ct);
+ Wrapper_add_local(f, "_swig_go_result", ct);
Delete(ct);
Delete(ln);
}
@@ -1486,6 +1572,7 @@ private:
String *ln = Getattr(p, "lname");
String *pn = NewString("g");
Append(pn, ln);
+ tm = Copy(tm);
Replaceall(tm, "$input", pn);
Setattr(p, "emit:input", pn);
if (i < required_count) {
@@ -1495,6 +1582,7 @@ private:
Printv(f->code, " ", tm, "\n", NULL);
Printv(f->code, " }\n", NULL);
}
+ Delete(tm);
}
p = nextParm(p);
@@ -1513,7 +1601,7 @@ private:
cleanupFunction(n, f, parms);
if (SwigType_type(result) != T_VOID) {
- Printv(f->code, " return go_result;\n", NULL);
+ Printv(f->code, " return _swig_go_result;\n", NULL);
}
Printv(f->code, "}\n", NULL);
@@ -1543,20 +1631,26 @@ private:
if (!tm) {
p = nextSibling(p);
} else {
+ tm = Copy(tm);
Replaceall(tm, "$input", Getattr(p, "emit:input"));
Printv(f->code, tm, "\n\n", NULL);
+ Delete(tm);
p = Getattr(p, "tmap:check:next");
}
}
}
/* -----------------------------------------------------------------------
- * getGoAction()
+ * emitGoAction()
*
- * Get the action of the function. This is used for C/C++ function.
+ * Emit the action of the function. This is used for the C/C++ function.
* ----------------------------------------------------------------------- */
void emitGoAction(Node *n, List *base, ParmList *parms, SwigType *result, Wrapper *f) {
+ if (!gccgo_flag && SwigType_type(result) != T_VOID) {
+ Wrapper_add_local(f, "swig_stktop", "char *swig_stktop");
+ Printv(f->code, "\tswig_stktop = _swig_topofstack();\n", NULL);
+ }
String *actioncode;
if (!base || isStatic(n)) {
Swig_director_emit_dynamic_cast(n, f);
@@ -1593,12 +1687,7 @@ private:
if (!tm) {
Swig_warning(WARN_TYPEMAP_OUT_UNDEF, input_file, line_number, "Unable to use return type %s\n", SwigType_str(result, 0));
} else {
- if (!gccgo_flag) {
- static const String *swig_a_result = NewStringf("swig_a->%s", Swig_cresult_name());
- Replaceall(tm, "$result", swig_a_result);
- } else {
- Replaceall(tm, "$result", "go_result");
- }
+ Replaceall(tm, "$result", "_swig_go_result");
if (GetFlag(n, "feature:new")) {
Replaceall(tm, "$owner", "1");
} else {
@@ -1608,6 +1697,14 @@ private:
Delete(tm);
}
+ if (!gccgo_flag && SwigType_type(result) != T_VOID) {
+ // If the function called back into the Go code, the stack might
+ // have been copied. We need to adjust swig_a accordingly here.
+ // This is what cgo does.
+ Printv(f->code, "\tswig_a = (struct swigargs*)((char*)swig_a + (_swig_topofstack() - swig_stktop));\n", NULL);
+ Printv(f->code, "\tswig_a->", Swig_cresult_name(), " = ", "_swig_go_result;\n", NULL);
+ }
+
Swig_restore(n);
}
@@ -1626,15 +1723,43 @@ private:
if (!tm) {
p = nextSibling(p);
} else {
+ tm = Copy(tm);
Replaceall(tm, "$result", Swig_cresult_name());
Replaceall(tm, "$input", Getattr(p, "emit:input"));
Printv(f->code, tm, "\n", NULL);
+ Delete(tm);
p = Getattr(p, "tmap:argout:next");
}
}
}
/* -----------------------------------------------------------------------
+ * goargout()
+ *
+ * Handle Go argument output code if any. This is used for the Go
+ * function. This assumes that each parameter has an "emit:goinput"
+ * property with the name to use to refer to that parameter.
+ * ----------------------------------------------------------------------- */
+
+ void goargout(ParmList *parms, int parm_count) {
+ Parm *p = parms;
+ for (int i = 0; i < parm_count; ++i) {
+ p = getParm(p);
+ String *tm = Getattr(p, "tmap:goargout");
+ if (!tm) {
+ p = nextSibling(p);
+ } else {
+ tm = Copy(tm);
+ Replaceall(tm, "$result", "swig_r");
+ Replaceall(tm, "$input", Getattr(p, "emit:goinput"));
+ Printv(f_go_wrappers, tm, NULL);
+ Delete(tm);
+ p = Getattr(p, "tmap:goargout:next");
+ }
+ }
+ }
+
+ /* -----------------------------------------------------------------------
* freearg()
*
* Handle argument cleanup code if any. This is used for the C/C++
@@ -1650,8 +1775,10 @@ private:
if (!tm) {
p = nextSibling(p);
} else {
+ tm = Copy(tm);
Replaceall(tm, "$input", Getattr(p, "emit:input"));
Printv(ret, tm, "\n", NULL);
+ Delete(tm);
p = Getattr(p, "tmap:freearg:next");
}
}
@@ -1835,12 +1962,26 @@ private:
if (!is_public(n)) {
return SWIG_OK;
}
- if (Getattr(parentNode(n), "unnamed")) {
+
+ Swig_require("enumvalueDeclaration", n, "*sym:name", NIL);
+ Node *parent = parentNode(n);
+
+ if (Getattr(parent, "unnamed")) {
Setattr(n, "type", NewString("int"));
} else {
- Setattr(n, "type", Getattr(parentNode(n), "enumtype"));
+ Setattr(n, "type", Getattr(parent, "enumtype"));
}
- return goComplexConstant(n, Getattr(n, "type"));
+
+ if (GetFlag(parent, "scopedenum")) {
+ String *symname = Getattr(n, "sym:name");
+ symname = Swig_name_member(0, Getattr(parent, "sym:name"), symname);
+ Setattr(n, "sym:name", symname);
+ Delete(symname);
+ }
+
+ int ret = goComplexConstant(n, Getattr(n, "type"));
+ Swig_restore(n);
+ return ret;
}
/* -----------------------------------------------------------------------
@@ -2047,7 +2188,7 @@ private:
}
Append(f_go_wrappers, interfaces);
- Printf(f_go_wrappers, "}\n\n", NULL);
+ Printv(f_go_wrappers, "}\n\n", NULL);
Delete(interfaces);
interfaces = NULL;
@@ -2640,6 +2781,7 @@ private:
DelWrapper(dummy);
Swig_typemap_attach_parms("gotype", parms, NULL);
+ Swig_typemap_attach_parms("imtype", parms, NULL);
int parm_count = emit_num_arguments(parms);
String *func_name = NewString("NewDirector");
@@ -2666,7 +2808,9 @@ private:
if (!is_ignored) {
// Declare the C++ wrapper.
- if (gccgo_flag) {
+ if (!gccgo_flag) {
+ Printv(f_go_wrappers, "var ", wname, " unsafe.Pointer\n\n", NULL);
+ } else {
Printv(f_go_wrappers, "//extern ", go_prefix, "_", wname, "\n", NULL);
}
@@ -2674,18 +2818,28 @@ private:
if (overname) {
Printv(f_go_wrappers, overname, NULL);
}
- Printv(f_go_wrappers, "(*", director_struct_name, NULL);
+ Printv(f_go_wrappers, "(_swig_director *", director_struct_name, NULL);
p = parms;
for (int i = 0; i < parm_count; ++i) {
p = getParm(p);
String *tm = goType(p, Getattr(p, "type"));
- Printv(f_go_wrappers, ", ", tm, NULL);
+ Printv(f_go_wrappers, ", _ ", tm, NULL);
Delete(tm);
p = nextParm(p);
}
- Printv(f_go_wrappers, ") ", go_type_name, "\n\n", NULL);
+ Printv(f_go_wrappers, ") (_swig_ret ", go_type_name, ")", NULL);
+
+ if (!gccgo_flag) {
+ Printv(f_go_wrappers, " {\n", NULL);
+ Printv(f_go_wrappers, "\t_swig_p := uintptr(unsafe.Pointer(&_swig_director))\n", NULL);
+ Printv(f_go_wrappers, "\t_cgo_runtime_cgocall(", wname, ", _swig_p)\n", NULL);
+ Printv(f_go_wrappers, "\treturn\n", NULL);
+ Printv(f_go_wrappers, "}", NULL);
+ }
+
+ Printv(f_go_wrappers, "\n\n", NULL);
Printv(f_go_wrappers, "func ", func_with_over_name, "(v interface{}", NULL);
@@ -2754,8 +2908,7 @@ private:
Setattr(n, "wrap:action", action);
if (!gccgo_flag) {
- int r = gcFunctionWrapper(n, fn_name, fn_name, overname, wname,
- first_parm, result, is_static, false);
+ int r = gcFunctionWrapper(wname);
if (r != SWIG_OK) {
return r;
}
@@ -3075,6 +3228,7 @@ private:
DelWrapper(dummy);
Swig_typemap_attach_parms("gotype", parms, NULL);
+ Swig_typemap_attach_parms("imtype", parms, NULL);
int parm_count = emit_num_arguments(parms);
SwigType *result = Getattr(n, "type");
@@ -3122,6 +3276,9 @@ private:
Swig_typemap_attach_parms("directorin", parms, w);
Swig_typemap_attach_parms("directorargout", parms, w);
+ Swig_typemap_attach_parms("godirectorin", parms, w);
+ Swig_typemap_attach_parms("goin", parms, dummy);
+ Swig_typemap_attach_parms("goargout", parms, dummy);
if (!is_ignored) {
// We use an interface to see if this method is defined in Go.
@@ -3155,17 +3312,19 @@ private:
// Declare the upcall function, which calls the method on the
// parent class.
- if (gccgo_flag) {
+ if (!gccgo_flag) {
+ Printv(f_go_wrappers, "var ", upcall_wname, " unsafe.Pointer\n\n", NULL);
+ } else {
Printv(f_go_wrappers, "//extern ", go_prefix, "_", upcall_wname, "\n", NULL);
}
- Printv(f_go_wrappers, "func ", upcall_gc_name, "(", go_type_name, NULL);
+ Printv(f_go_wrappers, "func ", upcall_gc_name, "(_swig_ptr ", go_type_name, NULL);
p = parms;
for (int i = 0; i < parm_count; ++i) {
p = getParm(p);
String *tm = goWrapperType(p, Getattr(p, "type"), false);
- Printv(f_go_wrappers, ", ", tm, NULL);
+ Printv(f_go_wrappers, ", _ ", tm, NULL);
Delete(tm);
p = nextParm(p);
}
@@ -3174,11 +3333,19 @@ private:
if (SwigType_type(result) != T_VOID) {
String *tm = goWrapperType(n, result, true);
- Printv(f_go_wrappers, " ", tm, NULL);
+ Printv(f_go_wrappers, " (_swig_ret ", tm, ")", NULL);
Delete(tm);
}
- Printv(f_go_wrappers, "\n", NULL);
+ if (!gccgo_flag) {
+ Printv(f_go_wrappers, " {\n", NULL);
+ Printv(f_go_wrappers, "\t_swig_p := uintptr(unsafe.Pointer(&_swig_ptr))\n", NULL);
+ Printv(f_go_wrappers, "\t_cgo_runtime_cgocall(", upcall_wname, ", _swig_p)\n", NULL);
+ Printv(f_go_wrappers, "\treturn\n", NULL);
+ Printv(f_go_wrappers, "}", NULL);
+ }
+
+ Printv(f_go_wrappers, "\n\n", NULL);
}
// Define the method on the director class in Go.
@@ -3234,29 +3401,98 @@ private:
if (GetFlag(n, "abstract")) {
Printv(f_go_wrappers, "\tpanic(\"call to pure virtual method\")\n", NULL);
} else {
+ bool has_goout = false;
+ String *goout = NULL;
+ if (SwigType_type(result) != T_VOID) {
+ Printv(f_go_wrappers, "\tvar swig_r ", goImType(n, result), "\n", NULL);
+ goout = Swig_typemap_lookup("goout", n, "swig_r", NULL);
+ if (goout) {
+ has_goout = true;
+ }
+ }
+
+ p = parms;
+ for (int i = 0; i < parm_count; ++i) {
+ p = getParm(p);
+ if (Getattr(p, "tmap:goargout")) {
+ has_goout = true;
+ }
+ p = nextParm(p);
+ }
+
+ String *call = NewString("");
+
if (gccgo_flag) {
- Printv(f_go_wrappers, "\tdefer SwigCgocallDone()\n", NULL);
- Printv(f_go_wrappers, "\tSwigCgocall()\n", NULL);
+ if (has_goout) {
+ Printv(call, "\tfunc() {\n", NULL);
+ }
+ Printv(call, "\tdefer SwigCgocallDone()\n", NULL);
+ Printv(call, "\tSwigCgocall()\n", NULL);
}
- Printv(f_go_wrappers, "\t", NULL);
+ Printv(call, "\t", NULL);
if (SwigType_type(result) != T_VOID) {
- Printv(f_go_wrappers, "return ", NULL);
+ Printv(call, "swig_r = ", NULL);
}
- Printv(f_go_wrappers, upcall_gc_name, "(swig_p.", go_type_name, NULL);
+ Printv(call, upcall_gc_name, "(swig_p.", go_type_name, NULL);
p = parms;
for (int i = 0; i < parm_count; ++i) {
+ Printv(call, ", ", NULL);
p = getParm(p);
SwigType *pt = Getattr(p, "type");
- Printv(f_go_wrappers, ", ", Getattr(p, "lname"), NULL);
- if (goTypeIsInterface(p, pt)) {
- Printv(f_go_wrappers, ".Swigcptr()", NULL);
+
+ String *ln = Getattr(p, "lname");
+
+ // This is an ordinary call from Go to C++, so adjust using
+ // the goin typemap.
+ String *goin = Getattr(p, "tmap:goin");
+ if (goin == NULL) {
+ Printv(call, ln, NULL);
+ if (goTypeIsInterface(p, pt)) {
+ Printv(call, ".Swigcptr()", NULL);
+ }
+ Setattr(p, "emit:goinput", ln);
+ } else {
+ String *ivar = NewString("");
+ Printf(ivar, "_swig_i_%d", i);
+ String *itm = goImType(p, pt);
+ Printv(f_go_wrappers, "\tvar ", ivar, " ", itm, NULL);
+ goin = Copy(goin);
+ Replaceall(goin, "$input", ln);
+ Replaceall(goin, "$result", ivar);
+ Printv(f_go_wrappers, goin, NULL);
+ Delete(goin);
+ Printv(call, ivar, NULL);
+ Setattr(p, "emit:goinput", ivar);
}
+
p = nextParm(p);
}
- Printv(f_go_wrappers, ")\n", NULL);
+ Printv(call, ")\n", NULL);
+
+ if (gccgo_flag && has_goout) {
+ Printv(call, "\t}()\n", NULL);
+ }
+
+ Printv(f_go_wrappers, call, NULL);
+ Delete(call);
+
+ goargout(parms, parm_count);
+
+ if (SwigType_type(result) != T_VOID) {
+ if (goout == NULL) {
+ Printv(f_go_wrappers, "\treturn swig_r\n", NULL);
+ } else {
+ String *tm = goType(n, result);
+ Printv(f_go_wrappers, "\tvar swig_r_1 ", tm, "\n", NULL);
+ Replaceall(goout, "$input", "swig_r");
+ Replaceall(goout, "$result", "swig_r_1");
+ Printv(f_go_wrappers, goout, NULL);
+ Printv(f_go_wrappers, "\treturn swig_r_1\n", NULL);
+ }
+ }
}
Printv(f_go_wrappers, "}\n\n", NULL);
@@ -3341,7 +3577,7 @@ private:
if (!gccgo_flag) {
// Write the upcall wrapper function. This is compiled by gc
// and calls the C++ function.
- int r = gcFunctionWrapper(n, upcall_name, upcall_name, overname, upcall_wname, first_parm, result, is_static, true);
+ int r = gcFunctionWrapper(upcall_wname);
if (r != SWIG_OK) {
return r;
}
@@ -3389,29 +3625,86 @@ private:
Printv(f_go_wrappers, " {\n", NULL);
+ String *goout = NULL;
+ if (SwigType_type(result) != T_VOID) {
+ Printv(f_go_wrappers, "\tvar swig_r ", goImType(n, result), "\n", NULL);
+ goout = Swig_typemap_lookup("goout", n, "swig_r", NULL);
+ }
+
+ String *call = NewString("");
+
if (gccgo_flag) {
- Printv(f_go_wrappers, "\tdefer SwigCgocallDone()\n", NULL);
- Printv(f_go_wrappers, "\tSwigCgocall()\n", NULL);
+ if (goout != NULL) {
+ Printv(call, "\tfunc() {\n", NULL);
+ }
+ Printv(call, "\tdefer SwigCgocallDone()\n", NULL);
+ Printv(call, "\tSwigCgocall()\n", NULL);
}
- Printv(f_go_wrappers, "\t", NULL);
+ Printv(call, "\t", NULL);
if (SwigType_type(result) != T_VOID) {
- Printv(f_go_wrappers, "return ", NULL);
+ Printv(call, "swig_r = ", NULL);
}
- Printv(f_go_wrappers, upcall_gc_name, "(p.(*", director_struct_name, ").", go_type_name, NULL);
+ Printv(call, upcall_gc_name, "(p.(*", director_struct_name, ").", go_type_name, NULL);
p = parms;
for (int i = 0; i < parm_count; ++i) {
+ Printv(call, ", ", NULL);
p = getParm(p);
SwigType *pt = Getattr(p, "type");
- Printv(f_go_wrappers, ", ", Getattr(p, "lname"), NULL);
+
+ String *ln = Copy(Getattr(p, "lname"));
if (goTypeIsInterface(p, pt)) {
- Printv(f_go_wrappers, ".Swigcptr()", NULL);
+ Printv(ln, ".Swigcptr()", NULL);
+ }
+
+ String *goin = Getattr(p, "tmap:goin");
+ if (goin == NULL) {
+ Printv(call, ln, NULL);
+ Setattr(p, "emit:goinput", ln);
+ } else {
+ String *ivar = NewString("");
+ Printf(ivar, "_swig_i_%d", i);
+ String *itm = goImType(p, pt);
+ Printv(f_go_wrappers, "\tvar ", ivar, " ", itm, NULL);
+ goin = Copy(goin);
+ Replaceall(goin, "$input", ln);
+ Replaceall(goin, "$result", ivar);
+ Printv(f_go_wrappers, goin, NULL);
+ Delete(goin);
+ Printv(call, ivar, NULL);
+ Setattr(p, "emit:goinput", ivar);
}
+
+ Delete(ln);
+
p = nextParm(p);
}
- Printv(f_go_wrappers, ")\n", NULL);
+ Printv(call, ")\n", NULL);
+
+ if (gccgo_flag && goout != NULL) {
+ Printv(call, "\t}()\n", NULL);
+ }
+
+ Printv(f_go_wrappers, call, NULL);
+ Delete(call);
+
+ goargout(parms, parm_count);
+
+ if (SwigType_type(result) != T_VOID) {
+ if (goout == NULL) {
+ Printv(f_go_wrappers, "\treturn swig_r\n", NULL);
+ } else {
+ String *tm = goType(n, result);
+ Printv(f_go_wrappers, "\tvar swig_r_1 ", tm, "\n", NULL);
+ Replaceall(goout, "$input", "swig_r");
+ Replaceall(goout, "$result", "swig_r_1");
+ Printv(f_go_wrappers, goout, NULL);
+ Printv(f_go_wrappers, "\treturn swig_r_1\n", NULL);
+ }
+ }
+
Printv(f_go_wrappers, "}\n\n", NULL);
}
@@ -3437,34 +3730,53 @@ private:
}
Printv(f_go_wrappers, "{\n", NULL);
- if (gccgo_flag) {
- Printv(f_go_wrappers, "\tSwigCgocallBack()\n", NULL);
- Printv(f_go_wrappers, "\tdefer SwigCgocallBackDone()\n", NULL);
- }
-
- Printv(f_go_wrappers, "\t", NULL);
-
if (is_ignored) {
- Printv(f_go_wrappers, "return\n", NULL);
+ Printv(f_go_wrappers, "\treturn\n", NULL);
} else {
bool result_is_interface = false;
+ String *goout = NULL;
if (SwigType_type(result) != T_VOID) {
- Printv(f_go_wrappers, "return ", NULL);
result_is_interface = goTypeIsInterface(NULL, result);
+ Printv(f_go_wrappers, "\tvar swig_r ", NULL);
+ if (!result_is_interface) {
+ Printv(f_go_wrappers, goType(n, result), NULL);
+ } else {
+ Printv(f_go_wrappers, result_wrapper, NULL);
+ }
+ Printv(f_go_wrappers, "\n", NULL);
+ goout = Swig_typemap_lookup("godirectorout", n, "swig_r", NULL);
+ }
+
+ String *call = NewString("");
+
+ if (gccgo_flag) {
+ if (goout != NULL) {
+ Printv(call, "\tfunc() {\n", NULL);
+ }
+ Printv(call, "\tSwigCgocallBack()\n", NULL);
+ Printv(call, "\tdefer SwigCgocallBackDone()\n", NULL);
+ }
+
+ Printv(call, "\t", NULL);
+
+ if (SwigType_type(result) != T_VOID) {
+ Printv(call, "swig_r = ", NULL);
if (result_is_interface) {
- Printv(f_go_wrappers, result_wrapper, "(", NULL);
+ Printv(call, result_wrapper, "(", NULL);
}
}
- Printv(f_go_wrappers, "p.", go_with_over_name, "(", NULL);
+ Printv(call, "p.", go_with_over_name, "(", NULL);
p = parms;
for (int i = 0; i < parm_count; ++i) {
p = getParm(p);
if (i > 0) {
- Printv(f_go_wrappers, ", ", NULL);
+ Printv(call, ", ", NULL);
}
SwigType *pt = Getattr(p, "type");
+ String *ln = NewString("");
+
// If the Go representation is an interface type class, then
// we are receiving a uintptr, and must convert to the
// interface.
@@ -3473,26 +3785,64 @@ private:
// Passing is_result as true to goWrapperType gives us the
// name of the Go type we need to convert to an interface.
String *wt = goWrapperType(p, pt, true);
- Printv(f_go_wrappers, wt, "(", NULL);
+ Printv(ln, wt, "(", NULL);
Delete(wt);
}
- Printv(f_go_wrappers, Getattr(p, "lname"), NULL);
+ Printv(ln, Getattr(p, "lname"), NULL);
if (is_interface) {
- Printv(f_go_wrappers, ")", NULL);
+ Printv(ln, ")", NULL);
}
+ String *goin = Getattr(p, "tmap:godirectorin");
+ if (goin == NULL) {
+ Printv(call, ln, NULL);
+ } else {
+ String *ivar = NewString("");
+ Printf(ivar, "_swig_i_%d", i);
+ String *itm = goType(p, pt);
+ Printv(f_go_wrappers, "\tvar ", ivar, " ", itm, NULL);
+ goin = Copy(goin);
+ Replaceall(goin, "$input", ln);
+ Replaceall(goin, "$result", ivar);
+ Printv(f_go_wrappers, goin, NULL);
+ Delete(goin);
+ Printv(call, ivar, NULL);
+ Delete(ivar);
+ }
+
+ Delete(ln);
+
p = nextParm(p);
}
- Printv(f_go_wrappers, ")", NULL);
+ Printv(call, ")", NULL);
if (result_is_interface) {
- Printv(f_go_wrappers, ".Swigcptr())", NULL);
+ Printv(call, ".Swigcptr())", NULL);
}
+ Printv(call, "\n", NULL);
- Printv(f_go_wrappers, "\n", NULL);
+ if (gccgo_flag && goout != NULL) {
+ Printv(call, "\t}()\n", NULL);
+ }
+
+ Printv(f_go_wrappers, call, NULL);
+ Delete(call);
+
+ if (SwigType_type(result) != T_VOID) {
+ if (goout == NULL) {
+ Printv(f_go_wrappers, "\treturn swig_r\n", NULL);
+ } else {
+ String *tm = goImType(n, result);
+ Printv(f_go_wrappers, "\tvar swig_r_1 ", tm, "\n", NULL);
+ Replaceall(goout, "$input", "swig_r");
+ Replaceall(goout, "$result", "swig_r_1");
+ Printv(f_go_wrappers, goout, NULL);
+ Printv(f_go_wrappers, "\treturn swig_r_1\n", NULL);
+ }
+ }
}
Printv(f_go_wrappers, "}\n\n", NULL);
@@ -3610,6 +3960,7 @@ private:
Swig_warning(WARN_TYPEMAP_DIRECTORIN_UNDEF, input_file,
line_number, "Unable to use type %s as director method argument\n", SwigType_str(Getattr(p, "type"), 0));
} else {
+ tm = Copy(tm);
String *ln = Getattr(p, "lname");
String *input = NewString("");
Printv(input, "swig_a.", ln, NULL);
@@ -3618,12 +3969,28 @@ private:
Replaceall(tm, "$owner", "0");
Delete(input);
Printv(w->code, "\t", tm, "\n", NULL);
+ Delete(tm);
}
p = Getattr(p, "tmap:directorin:next");
}
Printv(w->code, " crosscall2(", callback_wname, ", &swig_a, (int) sizeof swig_a);\n", NULL);
+ /* Marshal outputs */
+ for (p = parms; p;) {
+ String *tm;
+ if ((tm = Getattr(p, "tmap:directorargout"))) {
+ tm = Copy(tm);
+ Replaceall(tm, "$result", "jresult");
+ Replaceall(tm, "$input", Getattr(p, "emit:directorinput"));
+ Printv(w->code, tm, "\n", NIL);
+ Delete(tm);
+ p = Getattr(p, "tmap:directorargout:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
if (SwigType_type(result) != T_VOID) {
String *result_str = NewString("c_result");
String *tm = Swig_typemap_lookup("directorout", n, result_str, NULL);
@@ -3672,7 +4039,7 @@ private:
String *pn = NewString("g");
Append(pn, Getattr(p, "lname"));
- Setattr(p, "emit:input", pn);
+ Setattr(p, "emit:directorinput", pn);
String *tm = gccgoCTypeForGoValue(n, Getattr(p, "type"), pn);
Wrapper_add_local(w, pn, tm);
@@ -3683,9 +4050,11 @@ private:
Swig_warning(WARN_TYPEMAP_DIRECTORIN_UNDEF, input_file,
line_number, "Unable to use type %s as director method argument\n", SwigType_str(Getattr(p, "type"), 0));
} else {
+ tm = Copy(tm);
Replaceall(tm, "$input", pn);
Replaceall(tm, "$owner", 0);
Printv(w->code, " ", tm, "\n", NULL);
+ Delete(tm);
Printv(args, ", ", pn, NULL);
}
@@ -3699,6 +4068,21 @@ private:
}
Printv(w->code, callback_wname, "(go_val", args, ");\n", NULL);
+ /* Marshal outputs */
+ for (p = parms; p;) {
+ String *tm;
+ if ((tm = Getattr(p, "tmap:directorargout"))) {
+ tm = Copy(tm);
+ Replaceall(tm, "$result", "jresult");
+ Replaceall(tm, "$input", Getattr(p, "emit:directorinput"));
+ Printv(w->code, tm, "\n", NIL);
+ Delete(tm);
+ p = Getattr(p, "tmap:directorargout:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
if (SwigType_type(result) != T_VOID) {
String *result_str = NewString("c_result");
String *tm = Swig_typemap_lookup("directorout", n, result_str, NULL);
@@ -3717,19 +4101,6 @@ private:
Delete(result_str);
}
}
-
- /* Marshal outputs */
- for (p = parms; p;) {
- String *tm;
- if ((tm = Getattr(p, "tmap:directorargout"))) {
- Replaceall(tm, "$result", "jresult");
- Replaceall(tm, "$input", Getattr(p, "emit:directorinput"));
- Printv(w->code, tm, "\n", NIL);
- p = Getattr(p, "tmap:directorargout:next");
- } else {
- p = nextSibling(p);
- }
- }
} else {
assert(is_pure_virtual);
Printv(w->code, " _swig_gopanic(\"call to pure virtual function ", Getattr(parent, "sym:name"), name, "\");\n", NULL);
@@ -4057,7 +4428,7 @@ private:
}
fn = i + 1;
- Printf(f_go_wrappers, "\t\tif _, ok := a[%d].(%s); !ok {\n", j, tm);
+ Printf(f_go_wrappers, "\t\tif _, ok := a[%d].(%s); !ok {\n", j, goType(pj, Getattr(pj, "type")));
Printf(f_go_wrappers, "\t\t\tgoto check_%d\n", fn);
Printv(f_go_wrappers, "\t\t}\n", NULL);
}
@@ -4462,7 +4833,19 @@ private:
* ---------------------------------------------------------------------- */
String *goType(Node *n, SwigType *type) {
- return goTypeWithInfo(n, type, NULL);
+ return goTypeWithInfo(n, type, false, NULL);
+ }
+
+ /* ----------------------------------------------------------------------
+ * goImType()
+ *
+ * Given a SWIG type, return a string for the intermediate Go type
+ * to pass to C/C++. This is like goType except that it looks for
+ * an imtype typemap entry first.
+ * ---------------------------------------------------------------------- */
+
+ String *goImType(Node *n, SwigType *type) {
+ return goTypeWithInfo(n, type, true, NULL);
}
/* ----------------------------------------------------------------------
@@ -4470,6 +4853,8 @@ private:
*
* Like goType, but return some more information.
*
+ * If use_imtype is true, this look for a imtype typemap entry.
+ *
* If the p_is_interface parameter is not NULL, this sets
* *p_is_interface to indicate whether this type is going to be
* represented by a Go interface type. These are cases where the Go
@@ -4477,24 +4862,39 @@ private:
* forth with C/C++.
* ---------------------------------------------------------------------- */
- String *goTypeWithInfo(Node *n, SwigType *type, bool *p_is_interface) {
+ String *goTypeWithInfo(Node *n, SwigType *type, bool use_imtype, bool *p_is_interface) {
if (p_is_interface) {
*p_is_interface = false;
}
- String *ret;
- if (n && Cmp(type, Getattr(n, "type")) == 0) {
- ret = NULL;
- if (Strcmp(Getattr(n, "nodeType"), "parm") == 0) {
- ret = Getattr(n, "tmap:gotype");
+ String *ret = NULL;
+ if (use_imtype) {
+ if (n && Cmp(type, Getattr(n, "type")) == 0) {
+ if (Strcmp(Getattr(n, "nodeType"), "parm") == 0) {
+ ret = Getattr(n, "tmap:imtype");
+ }
+ if (!ret) {
+ ret = Swig_typemap_lookup("imtype", n, "", NULL);
+ }
+ } else {
+ Parm *p = NewParm(type, "goImType", n);
+ ret = Swig_typemap_lookup("imtype", p, "", NULL);
+ Delete(p);
}
- if (!ret) {
- ret = Swig_typemap_lookup("gotype", n, "", NULL);
+ }
+ if (!ret) {
+ if (n && Cmp(type, Getattr(n, "type")) == 0) {
+ if (Strcmp(Getattr(n, "nodeType"), "parm") == 0) {
+ ret = Getattr(n, "tmap:gotype");
+ }
+ if (!ret) {
+ ret = Swig_typemap_lookup("gotype", n, "", NULL);
+ }
+ } else {
+ Parm *p = NewParm(type, "goType", n);
+ ret = Swig_typemap_lookup("gotype", p, "", NULL);
+ Delete(p);
}
- } else {
- Parm *p = NewParm(type, "goType", n);
- ret = Swig_typemap_lookup("gotype", p, "", NULL);
- Delete(p);
}
if (ret && Strstr(ret, "$gotypename") != 0) {
@@ -4563,7 +4963,7 @@ private:
ret = NewString("uintptr");
} else {
bool is_interface;
- String *base = goTypeWithInfo(n, r, &is_interface);
+ String *base = goTypeWithInfo(n, r, false, &is_interface);
// At the Go level, an unknown or class type is handled as an
// interface wrapping a pointer. This means that if a
@@ -4627,12 +5027,12 @@ private:
if (add_pointer) {
SwigType_add_pointer(r);
}
- ret = goTypeWithInfo(n, r, p_is_interface);
+ ret = goTypeWithInfo(n, r, false, p_is_interface);
Delete(r);
} else if (SwigType_isqualifier(t)) {
SwigType *r = Copy(t);
SwigType_del_qualifier(r);
- ret = goTypeWithInfo(n, r, p_is_interface);
+ ret = goTypeWithInfo(n, r, false, p_is_interface);
Delete(r);
} else if (SwigType_isvarargs(t)) {
ret = NewString("[]interface{}");
@@ -4658,7 +5058,7 @@ private:
String *goWrapperType(Node *n, SwigType *type, bool is_result) {
bool is_interface;
- String *ret = goTypeWithInfo(n, type, &is_interface);
+ String *ret = goTypeWithInfo(n, type, true, &is_interface);
// If this is an interface, we want to pass the real type.
if (is_interface) {
@@ -4742,7 +5142,18 @@ private:
String *gcCTypeForGoValue(Node *n, SwigType *type, String *name) {
bool is_interface;
- String *gt = goTypeWithInfo(n, type, &is_interface);
+ String *gt = goTypeWithInfo(n, type, true, &is_interface);
+
+ String *tail = NewString("");
+ SwigType *t = SwigType_typedef_resolve_all(type);
+ if (!SwigType_isreference(t)) {
+ while (Strncmp(gt, "*", 1) == 0) {
+ Replace(gt, "*", "", DOH_REPLACE_FIRST);
+ Printv(tail, "*", NULL);
+ }
+ }
+ Delete(t);
+
bool is_string = Strcmp(gt, "string") == 0;
bool is_slice = Strncmp(gt, "[]", 2) == 0;
bool is_function = Strcmp(gt, "_swig_fnptr") == 0;
@@ -4770,18 +5181,21 @@ private:
if (is_string) {
// Note that we don't turn a reference to a string into a
// pointer to a string. Strings are immutable anyhow.
- ret = NewString("_gostring_ ");
- Append(ret, name);
+ ret = NewString("");
+ Printv(ret, "_gostring_", tail, " ", name, NULL);
+ Delete(tail);
return ret;
} else if (is_slice) {
// Slices are always passed as a _goslice_, whether or not references
// are involved.
- ret = NewString("_goslice_ ");
- Append(ret, name);
+ ret = NewString("");
+ Printv(ret, "_goslice_", tail, " ", name, NULL);
+ Delete(tail);
return ret;
} else if (is_function || is_member) {
- ret = NewString("void *");
- Append(ret, name);
+ ret = NewString("");
+ Printv(ret, "void*", tail, " ", name, NULL);
+ Delete(tail);
return ret;
} else if (is_complex64) {
ret = NewString("_Complex float ");
@@ -4798,6 +5212,7 @@ private:
SwigType_add_pointer(t);
ret = SwigType_lstr(t, name);
Delete(t);
+ Delete(tail);
return ret;
} else {
SwigType *t = SwigType_typedef_resolve_all(type);
@@ -4821,6 +5236,7 @@ private:
}
Delete(q);
Delete(t);
+ Delete(tail);
return ret;
}
}
@@ -4853,14 +5269,17 @@ private:
} else if (is_float64) {
ret = NewString("double ");
} else {
+ Delete(tail);
return SwigType_lstr(type, name);
}
}
+ Append(ret, tail);
if (SwigType_isreference(type)) {
Append(ret, "* ");
}
Append(ret, name);
+ Delete(tail);
return ret;
}
@@ -4885,7 +5304,7 @@ private:
bool goTypeIsInterface(Node *n, SwigType *type) {
bool is_interface;
- Delete(goTypeWithInfo(n, type, &is_interface));
+ Delete(goTypeWithInfo(n, type, false, &is_interface));
return is_interface;
}