Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

runtime: support for system callbacks with float arguments on Windows #45300

Open
emarj opened this issue Mar 30, 2021 · 2 comments
Open

runtime: support for system callbacks with float arguments on Windows #45300

emarj opened this issue Mar 30, 2021 · 2 comments
Labels
Milestone

Comments

@emarj
Copy link

@emarj emarj commented Mar 30, 2021

Background

The Windows APIs use certain callbacks with floating point arguments, for example:
HRESULT IAudioSessionEvents::OnSimpleVolumeChanged( float NewVolume, BOOL NewMute, LPCGUID EventContext );

To register those from Go code, the syscall.NewCallback is needed. This in turn runs syscall.compileCallback which is implemented for Windows, in /runtime/syscall_windows.go. This function explicitly does not support floats as arguments and panics (link) with message compileCallback: float arguments not supported.

This originated from a conversation here and some comments in this issue.

Since the Go calling convention is being reworked (#40724) entirely, this may be a good moment to (try) to address this.

Proposal

Would be nice to have the support for callbacks with floating point arguments. In this way would be possible to interact with the system using pure Go, without the need of CGo.

I don't know if there are other issues in interacting with Windows APIs, but ideally a full support for interacting with Windows would be great.

Maybe it is worth mentioning that there is a project lead by Microsoft that aims at making WinAPIs more accessible to other languages, by precisely describing them in a metadata format that can be machine processed to get specific language implementations, called projections. With full support of Windows syscall/callbacks, would be possible to make a projection for Go in order to have access to the complete Windows APIs. This is probably best to be discussed in another issue (or elsewhere), but I thought was important to mention here.

Comments

As far as I understand, as the comment in the code says, in order for this to work we need to "spill" the floating point registers in order to retrieve the values. This is done in the file runtime/sys_windows_amd64.s.

I am (very) far from being an expert so I don't understand if this is a relatively easy task or a complicated one.

Also I don't really understand why in the C code in Windows SDK headers, callbacks are flagged as stdcall but here they are treated as fastcall here. In the first case the values should be in the stack as per documentation, but surely I am missing something.

Any thoughts?

@gopherbot gopherbot added this to the Proposal milestone Mar 30, 2021
@gopherbot gopherbot added the Proposal label Mar 30, 2021
@aclements aclements changed the title proposal: runtime: support for system callbacks with float arguments on Windows runtime: support for system callbacks with float arguments on Windows Mar 30, 2021
@aclements aclements added NeedsFix and removed Proposal labels Mar 30, 2021
@aclements aclements modified the milestones: Proposal, Unplanned, Go1.17 Mar 30, 2021
@aclements
Copy link
Member

@aclements aclements commented Mar 30, 2021

Thanks for filing this. I don't think it really needs to go through the proposal process. This is something we should just do. We're a bit swamped for 1.17, so it may not happen in the next release, but I've added it to the 1.17 milestone because we already have our hands in that code.

I think this would be relatively easy to do now that we've had to teach NewCallback a lot more about the Go and Windows ABIs in order to support Go's register-based calling convention.

Also I don't really understand why in the C code in windows headers, callbacks are flagged as stdcall but here they are treated as fastcall here.

I'm not an expert on Windows calling conventions, but my understanding is that stdcall only matters for 32-bit x86, which has two calling conventions: stdcall and (the default) cdecl. On 64-bit x86, everything is fastcall.

/cc @mknyszek

@emarj
Copy link
Author

@emarj emarj commented Mar 31, 2021

Thank you for your support.

Also I don't really understand why in the C code in windows headers, callbacks are flagged as stdcall but here they are treated as fastcall here.

I'm not an expert on Windows calling conventions, but my understanding is that stdcall only matters for 32-bit x86, which has two calling conventions: stdcall and (the default) cdecl. On 64-bit x86, everything is fastcall.

I was missing something indeed. That link is just for 32 bit systems, the 64 bit section explains the use of fastcall in the first paragraph:

Given the expanded register set, x64 uses the __fastcall calling convention and a RISC-based exception-handling model
I was confused by the C headers in my (64 bit) system.

Thanks again

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
3 participants