purego: SyscallN r2 return float (#67)
* purego: SyscallN r2 return float We originally discussed this change and decided against doing it because r2 usually returns the upper 64bits on 32bit platforms. However, on Windows amd64 r2 is actually the float return value. https://github.com/golang/go/blob/7717ac151ae1556541dddc6a817ac04733f1af44/src/runtime/sys_windows_amd64.s#L66 And there is a TODO for arm64 as well. https://github.com/golang/go/blob/2cea6cdb6016708e89c9472cdb0504731699681d/src/runtime/sys_windows_arm64.s#L91 Doing this makes supporting float returns easier without having to implement a full C calling convention for RegisterFunc * Add comment describing when r2 is a float
- commit
- c2f2945fb3c5d7013c1f9bb4fde65685a24eafab
- author
- TotallyGamerJet · · 2022-11-10 19:08 UTC
- committer
- GitHub · · 2022-11-10 19:08 UTC
- parent
- 54b6cdc
- signature
- GPG Unverified
4AEE18F83AFDEB23The key is unknown
3 files · +11 -6
M func_darwin.go +6 -1
| @@ -4,6 +4,7 @@ | |||
| 4 | 4 | package purego | |
| 5 | 5 | ||
| 6 | 6 | import ( | |
| 7 | + | "math" | |
| 7 | 8 | "reflect" | |
| 8 | 9 | "runtime" | |
| 9 | 10 | "unsafe" | |
| @@ -110,7 +111,7 @@ func RegisterFunc(fptr interface{}, cfn uintptr) { | |||
| 110 | 111 | panic("purego: unsupported kind: " + v.Kind().String()) | |
| 111 | 112 | } | |
| 112 | 113 | } | |
| 113 | - | r1, _, _ := SyscallN(cfn, sysargs...) //TODO: handle float32/64 and struct types | |
| 114 | + | r1, r2, _ := SyscallN(cfn, sysargs...) //TODO: handle float32/64 and struct types | |
| 114 | 115 | if ty.NumOut() == 0 { | |
| 115 | 116 | return nil | |
| 116 | 117 | } | |
| @@ -134,6 +135,10 @@ func RegisterFunc(fptr interface{}, cfn uintptr) { | |||
| 134 | 135 | RegisterFunc(v.Interface(), r1) | |
| 135 | 136 | case reflect.String: | |
| 136 | 137 | v.SetString(strings.GoString(r1)) | |
| 138 | + | case reflect.Float32, reflect.Float64: | |
| 139 | + | // NOTE: r2 is only the floating return value on 64bit platforms. | |
| 140 | + | // On 32bit platforms r2 is the upper part of a 64bit return. | |
| 141 | + | v.SetFloat(math.Float64frombits(uint64(r2))) | |
| 137 | 142 | default: | |
| 138 | 143 | panic("purego: unsupported return kind: " + outType.Kind().String()) | |
| 139 | 144 | } | |
| @@ -4,6 +4,7 @@ | |||||
| 4 | package purego | 4 | package purego | ||
| 5 | 5 | ||||
| 6 | import ( | 6 | import ( | ||
| 7 | + | "math" | |||
| 7 | "reflect" | 8 | "reflect" | ||
| 8 | "runtime" | 9 | "runtime" | ||
| 9 | "unsafe" | 10 | "unsafe" | ||
| @@ -110,7 +111,7 @@ func RegisterFunc(fptr interface{}, cfn uintptr) { | |||||
| 110 | panic("purego: unsupported kind: " + v.Kind().String()) | 111 | panic("purego: unsupported kind: " + v.Kind().String()) | ||
| 111 | } | 112 | } | ||
| 112 | } | 113 | } | ||
| 113 | - | r1, _, _ := SyscallN(cfn, sysargs...) //TODO: handle float32/64 and struct types | 114 | + | r1, r2, _ := SyscallN(cfn, sysargs...) //TODO: handle float32/64 and struct types |
| 114 | if ty.NumOut() == 0 { | 115 | if ty.NumOut() == 0 { | ||
| 115 | return nil | 116 | return nil | ||
| 116 | } | 117 | } | ||
| @@ -134,6 +135,10 @@ func RegisterFunc(fptr interface{}, cfn uintptr) { | |||||
| 134 | RegisterFunc(v.Interface(), r1) | 135 | RegisterFunc(v.Interface(), r1) | ||
| 135 | case reflect.String: | 136 | case reflect.String: | ||
| 136 | v.SetString(strings.GoString(r1)) | 137 | v.SetString(strings.GoString(r1)) | ||
| 138 | + | case reflect.Float32, reflect.Float64: | |||
| 139 | + | // NOTE: r2 is only the floating return value on 64bit platforms. | |||
| 140 | + | // On 32bit platforms r2 is the upper part of a 64bit return. | |||
| 141 | + | v.SetFloat(math.Float64frombits(uint64(r2))) | |||
| 137 | default: | 142 | default: | ||
| 138 | panic("purego: unsupported return kind: " + outType.Kind().String()) | 143 | panic("purego: unsupported return kind: " + outType.Kind().String()) | ||
| 139 | } | 144 | } | ||
M sys_darwin_amd64.s +1 -1
| @@ -64,7 +64,7 @@ TEXT syscall9X(SB), NOSPLIT, $0 | |||
| 64 | 64 | ||
| 65 | 65 | MOVQ 24(BP), DI // get the pointer back | |
| 66 | 66 | MOVQ AX, syscall9Args_r1(DI) // r1 | |
| 67 | - | MOVQ DX, syscall9Args_r2(DI) // r2 | |
| 67 | + | MOVQ X0, syscall9Args_r2(DI) // r2 | |
| 68 | 68 | ||
| 69 | 69 | XORL AX, AX // no error (it's ignored anyway) | |
| 70 | 70 | ADDQ $32, SP | |
| @@ -64,7 +64,7 @@ TEXT syscall9X(SB), NOSPLIT, $0 | |||||
| 64 | 64 | ||||
| 65 | MOVQ 24(BP), DI // get the pointer back | 65 | MOVQ 24(BP), DI // get the pointer back | ||
| 66 | MOVQ AX, syscall9Args_r1(DI) // r1 | 66 | MOVQ AX, syscall9Args_r1(DI) // r1 | ||
| 67 | - | MOVQ DX, syscall9Args_r2(DI) // r2 | 67 | + | MOVQ X0, syscall9Args_r2(DI) // r2 |
| 68 | 68 | ||||
| 69 | XORL AX, AX // no error (it's ignored anyway) | 69 | XORL AX, AX // no error (it's ignored anyway) | ||
| 70 | ADDQ $32, SP | 70 | ADDQ $32, SP | ||
M sys_darwin_arm64.s +4 -4
| @@ -57,10 +57,10 @@ TEXT syscall9X(SB), NOSPLIT, $0 | |||
| 57 | 57 | ||
| 58 | 58 | BL (R12) | |
| 59 | 59 | ||
| 60 | - | MOVD 8(RSP), R2 // pop structure pointer | |
| 61 | - | ADD $16, RSP | |
| 62 | - | MOVD R0, syscall9Args_r1(R2) // save r1 | |
| 63 | - | MOVD R1, syscall9Args_r2(R2) // save r2 | |
| 60 | + | MOVD 8(RSP), R2 // pop structure pointer | |
| 61 | + | ADD $16, RSP | |
| 62 | + | MOVD R0, syscall9Args_r1(R2) // save r1 | |
| 63 | + | FMOVD F0, syscall9Args_r2(R2) // save r2 | |
| 64 | 64 | RET | |
| 65 | 65 | ||
| 66 | 66 | // runtime·cgocallback expects a call to the ABIInternal function | |
| @@ -57,10 +57,10 @@ TEXT syscall9X(SB), NOSPLIT, $0 | |||||
| 57 | 57 | ||||
| 58 | BL (R12) | 58 | BL (R12) | ||
| 59 | 59 | ||||
| 60 | - | MOVD 8(RSP), R2 // pop structure pointer | 60 | + | MOVD 8(RSP), R2 // pop structure pointer |
| 61 | - | ADD $16, RSP | 61 | + | ADD $16, RSP |
| 62 | - | MOVD R0, syscall9Args_r1(R2) // save r1 | 62 | + | MOVD R0, syscall9Args_r1(R2) // save r1 |
| 63 | - | MOVD R1, syscall9Args_r2(R2) // save r2 | 63 | + | FMOVD F0, syscall9Args_r2(R2) // save r2 |
| 64 | RET | 64 | RET | ||
| 65 | 65 | ||||
| 66 | // runtime·cgocallback expects a call to the ABIInternal function | 66 | // runtime·cgocallback expects a call to the ABIInternal function | ||