detached 2055de3

purego: get ABIInternal wrapper using closure (#75)

The function runtime.cgocallback takes an ABIInternal function pointer. However, the assembly tag <ABIInternal> is only allowed in the runtime. This PR gets the ABIInternal function pointer by using the closure technique from #73. It also removes the hacky trampoline.
commit
2055de312f95c0cf00acfb7857eec7bcbf64826f
author
TotallyGamerJet · · 2022-12-02 18:28 UTC
committer
GitHub · · 2022-12-02 18:28 UTC
parent
fcdb024
signature
GPG Unverified4AEE18F83AFDEB23 The key is unknown
3 files · +18 -24
M sys_darwin_amd64.s +6 -12
@@ -71,13 +71,6 @@ TEXT syscall9X(SB), NOSPLIT, $0
7171 POPQ BP
7272 RET
7373
74-// runtime·cgocallback expects a call to the ABIInternal function
75-// However, the tag <ABIInternal> is only available in the runtime :(
76-TEXT callbackWrapInternal<>(SB), NOSPLIT, $0-0
77- MOVQ AX, arg+8(SP)
78- JMP ·callbackWrap(SB)
79- RET
80-
8174 TEXT callbackasm1(SB), NOSPLIT, $0
8275 // remove return address from stack, we are not returning to callbackasm, but to its caller.
8376 MOVQ 0(SP), AX
@@ -118,11 +111,12 @@ TEXT callbackasm1(SB), NOSPLIT, $0
118111 LEAQ 24(SP), AX // take the address of callbackArgs
119112
120113 // Call cgocallback, which will call callbackWrap(frame).
121- MOVQ $0, 16(SP) // context
122- MOVQ AX, 8(SP) // frame (address of callbackArgs)
123- MOVQ $callbackWrapInternal<>(SB), BX
124- MOVQ BX, 0(SP) // PC of function value to call (callbackWrap)
125- CALL runtime·cgocallback(SB) // runtime.cgocallback(fn, frame, ctxt uintptr)
114+ MOVQ $0, 16(SP) // context
115+ MOVQ AX, 8(SP) // frame (address of callbackArgs)
116+ MOVQ ·callbackWrap_call(SB), DX // Get the ABIInternal function pointer
117+ MOVQ (DX), CX // without <ABIInternal> by using a closure.
118+ MOVQ CX, 0(SP) // PC of function value to call (callbackWrap)
119+ CALL runtime·cgocallback(SB) // runtime.cgocallback(fn, frame, ctxt uintptr)
126120
127121 // Get callback result.
128122 MOVQ (24+callbackArgs_result)(SP), AX
@@ -71,13 +71,6 @@ TEXT syscall9X(SB), NOSPLIT, $0
71 POPQ BP71 POPQ BP
72 RET72 RET
73 73
74-// runtime·cgocallback expects a call to the ABIInternal function
75-// However, the tag <ABIInternal> is only available in the runtime :(
76-TEXT callbackWrapInternal<>(SB), NOSPLIT, $0-0
77- MOVQ AX, arg+8(SP)
78- JMP ·callbackWrap(SB)
79- RET
80-
81 TEXT callbackasm1(SB), NOSPLIT, $074 TEXT callbackasm1(SB), NOSPLIT, $0
82 // remove return address from stack, we are not returning to callbackasm, but to its caller.75 // remove return address from stack, we are not returning to callbackasm, but to its caller.
83 MOVQ 0(SP), AX76 MOVQ 0(SP), AX
@@ -118,11 +111,12 @@ TEXT callbackasm1(SB), NOSPLIT, $0
118 LEAQ 24(SP), AX // take the address of callbackArgs111 LEAQ 24(SP), AX // take the address of callbackArgs
119 112
120 // Call cgocallback, which will call callbackWrap(frame).113 // Call cgocallback, which will call callbackWrap(frame).
121- MOVQ $0, 16(SP) // context114+ MOVQ $0, 16(SP) // context
122- MOVQ AX, 8(SP) // frame (address of callbackArgs)115+ MOVQ AX, 8(SP) // frame (address of callbackArgs)
123- MOVQ $callbackWrapInternal<>(SB), BX116+ MOVQ ·callbackWrap_call(SB), DX // Get the ABIInternal function pointer
124- MOVQ BX, 0(SP) // PC of function value to call (callbackWrap)117+ MOVQ (DX), CX // without <ABIInternal> by using a closure.
125- CALL runtime·cgocallback(SB) // runtime.cgocallback(fn, frame, ctxt uintptr)118+ MOVQ CX, 0(SP) // PC of function value to call (callbackWrap)
119+ CALL runtime·cgocallback(SB) // runtime.cgocallback(fn, frame, ctxt uintptr)
126 120
127 // Get callback result.121 // Get callback result.
128 MOVQ (24+callbackArgs_result)(SP), AX122 MOVQ (24+callbackArgs_result)(SP), AX
M sys_darwin_arm64.s +6 -12
@@ -61,15 +61,6 @@ TEXT syscall9X(SB), NOSPLIT, $0
6161 FMOVD F0, syscall9Args_r2(R2) // save r2
6262 RET
6363
64-// runtime·cgocallback expects a call to the ABIInternal function
65-// However, the tag <ABIInternal> is only available in the runtime :(
66-// This is a small wrapper function that moves the parameter from R0 to the stack
67-// where the Go function can find it. It then branches without link.
68-TEXT callbackWrapInternal<>(SB), NOSPLIT, $0-0
69- MOVD R0, 8(RSP)
70- B ·callbackWrap(SB)
71- RET
72-
7364 TEXT callbackasm1(SB), NOSPLIT, $208-0
7465 NO_LOCAL_POINTERS
7566
@@ -97,9 +88,12 @@ TEXT callbackasm1(SB), NOSPLIT, $208-0
9788 MOVD R0, callbackArgs_result(R13) // result
9889
9990 // Move parameters into registers
100- MOVD $callbackWrapInternal<>(SB), R0 // fn unsafe.Pointer
101- MOVD R13, R1 // frame (&callbackArgs{...})
102- MOVD $0, R3 // ctxt uintptr
91+ // Get the ABIInternal function pointer
92+ // without <ABIInternal> by using a closure.
93+ MOVD ·callbackWrap_call(SB), R26
94+ MOVD (R26), R0 // fn unsafe.Pointer
95+ MOVD R13, R1 // frame (&callbackArgs{...})
96+ MOVD $0, R3 // ctxt uintptr
10397
10498 // We still need to save all callee save register as before, and then
10599 // push 3 args for fn (R0, R1, R3), skipping R2.
@@ -61,15 +61,6 @@ TEXT syscall9X(SB), NOSPLIT, $0
61 FMOVD F0, syscall9Args_r2(R2) // save r261 FMOVD F0, syscall9Args_r2(R2) // save r2
62 RET62 RET
63 63
64-// runtime·cgocallback expects a call to the ABIInternal function
65-// However, the tag <ABIInternal> is only available in the runtime :(
66-// This is a small wrapper function that moves the parameter from R0 to the stack
67-// where the Go function can find it. It then branches without link.
68-TEXT callbackWrapInternal<>(SB), NOSPLIT, $0-0
69- MOVD R0, 8(RSP)
70- B ·callbackWrap(SB)
71- RET
72-
73 TEXT callbackasm1(SB), NOSPLIT, $208-064 TEXT callbackasm1(SB), NOSPLIT, $208-0
74 NO_LOCAL_POINTERS65 NO_LOCAL_POINTERS
75 66
@@ -97,9 +88,12 @@ TEXT callbackasm1(SB), NOSPLIT, $208-0
97 MOVD R0, callbackArgs_result(R13) // result88 MOVD R0, callbackArgs_result(R13) // result
98 89
99 // Move parameters into registers90 // Move parameters into registers
100- MOVD $callbackWrapInternal<>(SB), R0 // fn unsafe.Pointer91+ // Get the ABIInternal function pointer
101- MOVD R13, R1 // frame (&callbackArgs{...})92+ // without <ABIInternal> by using a closure.
102- MOVD $0, R3 // ctxt uintptr93+ MOVD ·callbackWrap_call(SB), R26
94+ MOVD (R26), R0 // fn unsafe.Pointer
95+ MOVD R13, R1 // frame (&callbackArgs{...})
96+ MOVD $0, R3 // ctxt uintptr
103 97
104 // We still need to save all callee save register as before, and then98 // We still need to save all callee save register as before, and then
105 // push 3 args for fn (R0, R1, R3), skipping R2.99 // push 3 args for fn (R0, R1, R3), skipping R2.
M syscall_darwin.go +6 -0
@@ -114,6 +114,12 @@ const callbackMaxFrame = 64 * ptrSize
114114 // callbackasmABI0 is implemented in zcallback_GOOS_GOARCH.s
115115 var callbackasmABI0 uintptr
116116
117+// callbackWrap_call allows the calling of the ABIInternal wrapper
118+// which is required for runtime.cgocallback without the
119+// <ABIInternal> tag which is only allowed in the runtime.
120+// This closure is used inside sys_darwin_GOARCH.s
121+var callbackWrap_call = callbackWrap
122+
117123 // callbackWrap is called by assembly code which determines which Go function to call.
118124 // This function takes the arguments and passes them to the Go function and returns the result.
119125 func callbackWrap(a *callbackArgs) {
@@ -114,6 +114,12 @@ const callbackMaxFrame = 64 * ptrSize
114 // callbackasmABI0 is implemented in zcallback_GOOS_GOARCH.s114 // callbackasmABI0 is implemented in zcallback_GOOS_GOARCH.s
115 var callbackasmABI0 uintptr115 var callbackasmABI0 uintptr
116 116
117+// callbackWrap_call allows the calling of the ABIInternal wrapper
118+// which is required for runtime.cgocallback without the
119+// <ABIInternal> tag which is only allowed in the runtime.
120+// This closure is used inside sys_darwin_GOARCH.s
121+var callbackWrap_call = callbackWrap
122+
117 // callbackWrap is called by assembly code which determines which Go function to call.123 // callbackWrap is called by assembly code which determines which Go function to call.
118 // This function takes the arguments and passes them to the Go function and returns the result.124 // This function takes the arguments and passes them to the Go function and returns the result.
119 func callbackWrap(a *callbackArgs) {125 func callbackWrap(a *callbackArgs) {

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 1

Tags 102

↑↓ moveenter openesc close