summaryrefslogtreecommitdiff
path: root/src/pkg/runtime/callback_windows_amd64.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/pkg/runtime/callback_windows_amd64.c')
-rw-r--r--src/pkg/runtime/callback_windows_amd64.c104
1 files changed, 104 insertions, 0 deletions
diff --git a/src/pkg/runtime/callback_windows_amd64.c b/src/pkg/runtime/callback_windows_amd64.c
new file mode 100644
index 000000000..99d7cb9e3
--- /dev/null
+++ b/src/pkg/runtime/callback_windows_amd64.c
@@ -0,0 +1,104 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "runtime.h"
+#include "type.h"
+#include "defs_GOOS_GOARCH.h"
+#include "os_GOOS.h"
+
+// Will keep all callbacks in a linked list, so they don't get garbage collected.
+typedef struct Callback Callback;
+struct Callback {
+ Callback* link;
+ void* gobody;
+ byte asmbody;
+};
+
+typedef struct Callbacks Callbacks;
+struct Callbacks {
+ Lock;
+ Callback* link;
+ int32 n;
+};
+
+static Callbacks cbs;
+
+// Call back from windows dll into go.
+byte *
+runtime·compilecallback(Eface fn, bool /*cleanstack*/)
+{
+ FuncType *ft;
+ Type *t;
+ int32 argsize, i, n;
+ byte *p;
+ Callback *c;
+
+ if(fn.type == nil || fn.type->kind != KindFunc)
+ runtime·panicstring("compilecallback: not a function");
+ ft = (FuncType*)fn.type;
+ if(ft->out.len != 1)
+ runtime·panicstring("compilecallback: function must have one output parameter");
+ if(((Type**)ft->out.array)[0]->size != sizeof(uintptr))
+ runtime·panicstring("compilecallback: output parameter size is wrong");
+ argsize = 0;
+ for(i=0; i<ft->in.len; i++) {
+ t = ((Type**)ft->in.array)[i];
+ if(t->size > sizeof(uintptr))
+ runtime·panicstring("compilecallback: input parameter size is wrong");
+ argsize += sizeof(uintptr);
+ }
+
+ // compute size of new fn.
+ // must match code laid out below.
+ n = 2+8+1; // MOVQ fn, AX / PUSHQ AX
+ n += 2+8+1; // MOVQ argsize, AX / PUSHQ AX
+ n += 2+8; // MOVQ callbackasm, AX
+ n += 2; // JMP AX
+
+ runtime·lock(&cbs);
+ for(c = cbs.link; c != nil; c = c->link) {
+ if(c->gobody == fn.data) {
+ runtime·unlock(&cbs);
+ return &c->asmbody;
+ }
+ }
+ if(cbs.n >= 2000)
+ runtime·throw("too many callback functions");
+ c = runtime·mal(sizeof *c + n);
+ c->gobody = fn.data;
+ c->link = cbs.link;
+ cbs.link = c;
+ cbs.n++;
+ runtime·unlock(&cbs);
+
+ p = &c->asmbody;
+
+ // MOVQ fn, AX
+ *p++ = 0x48;
+ *p++ = 0xb8;
+ *(uint64*)p = (uint64)fn.data;
+ p += 8;
+ // PUSH AX
+ *p++ = 0x50;
+
+ // MOVQ argsize, AX
+ *p++ = 0x48;
+ *p++ = 0xb8;
+ *(uint64*)p = argsize;
+ p += 8;
+ // PUSH AX
+ *p++ = 0x50;
+
+ // MOVQ callbackasm, AX
+ *p++ = 0x48;
+ *p++ = 0xb8;
+ *(uint64*)p = (uint64)runtime·callbackasm;
+ p += 8;
+
+ // JMP AX
+ *p++ = 0xFF;
+ *p = 0xE0;
+
+ return &c->asmbody;
+}