Skip to content

Instantly share code, notes, and snippets.

@retep998
Last active October 26, 2015 18:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save retep998/604861ea06aa984ee6c7 to your computer and use it in GitHub Desktop.
Save retep998/604861ea06aa984ee6c7 to your computer and use it in GitHub Desktop.
stdcall
(1:56:14 PM) Retep998: I'd still really like a calling convention for stdcall methods because they aren't the same as stdcall functions
(1:56:21 PM) Retep998: who should I talk to about getting something like that?
(2:02:40 PM) jroelofs: Retep998: rnk maybe?
rnk rnsanchez
(2:03:27 PM) Retep998: rnk: Someone said I should talk to you about stdcall calling conventions
(2:04:49 PM) jroelofs: it might help to describe what you think is different between the two
(2:05:21 PM) Retep998: How values are returned from stdcall functions differs from stdcall methods
(2:05:40 PM) Retep998: Like if I return a struct containing two 32-bit integers
(2:06:04 PM) Retep998: fn foo(self) -> ThatType
(2:06:39 PM) Retep998: the stdcall calling convention currently does the function style, but to get the method style I have to use a hacky workaround to get it right
(2:06:59 PM) Retep998: which looks like fn foo(self, ret: *mut ThatType) -> *mut ThatType
(2:07:06 PM) rnk: Retep998, what about?
(2:07:29 PM) Retep998: rnk: I ran into this issue due to COM interfaces in Windows API
(2:07:35 PM) rnk: right, this is sret vs. this
(2:07:47 PM) rnk: clang handles this by swapping the order of the arguments
(2:07:54 PM) rnk: and moving the sret attribute to the second parameter
(2:08:30 PM) rnk: Retep998, basically MSVC has the invariant that 'this' always goes first, any implicit struct return parameter goes second. In some sense, this is true even for 'thiscall'
(2:09:16 PM) Retep998: rnk: What I need is a way to be able to represent the function pointers of COM interfaces in Rust
(2:09:59 PM) Retep998: Since function pointers in Rust are always just functions, "stdcall" can never do what I want, so I have to do that hackish work around
(2:11:14 PM) Retep998: Which funnily enough, means the C versions of such COM interfaces in the windows headers is actually wrong :P
(2:12:24 PM) Retep998: I tested it with the GetAdapterLuid method of ID3D12Device, and using the C bindings instead of the C++ version caused incorrect behavior
(2:13:52 PM) rnk: Retep998, so it sounds like rust interops with COM by filling out a table of function pointers as you would for C?
(2:13:59 PM) Retep998: rnk: yep
(2:14:10 PM) Retep998: Well, that's how I write the COM interop since I have no other choice really
(2:14:46 PM) rnk: Retep998, and essentially the Rust programmer needs to "know" that struct return actually needs to be prototyped as Sret* myfun(void* this, Sret *sret);
(2:14:58 PM) rnk: for COM methods
(2:15:13 PM) Retep998: yep
(2:15:27 PM) rnk: Retep998, so for a while we went down the path of having an x86stdcallmethodcc calling convention, which would hypothetically paper over the difference
(2:15:46 PM) rnk: Retep998, but MSVC has too many calling conventions, I think we're at 5 now
(2:15:53 PM) rnk: cdecl, vectorcall, stdcall, thiscall, fastcall
(2:16:05 PM) Retep998: and you don't want to have variations of each as well?
(2:16:06 PM) rnk: they would all need to have "C++ method" variants
(2:16:26 PM) rnk: so we decided that the frontend just has to "know" what's a method and what isn't
(2:17:03 PM) rnk: and the frontend would lower methods with 'this' before 'sret'
(2:17:05 PM) Retep998: So then Rust's compiler would need to add syntax for specifying this and implementing the proper LLVM support?
(2:17:34 PM) rnk: I don't think you need changes to LLVM, you just need to change what IR Rust generates
(2:17:47 PM) rnk: you can either do what you're currently doing, where you change the source-level rust prototype (right?)
(2:18:06 PM) rnk: or you can add some tag for "hey, this is a COM method, rust compiler, please do something different for struct return"
(2:18:24 PM) Retep998: Well, even if support was added to the Rust compiler, I'd have to wait at least half a year for it to stabilize and proliferate
(2:19:00 PM) rnk: Retep998, in the meantime, what's the problem with teaching users of COM about this awkwardness?
(2:19:25 PM) Retep998: rnk: Not much, all the COM interfaces are defined in my library anyway
(2:19:50 PM) Retep998: it's just a minor hassle having to make sure all the COM interface methods are checked and use the correct signature for struct returns
(2:20:00 PM) rnk: definitely
(2:21:20 PM) Retep998: reviewing PRs that regularly add thousands of lines of boring bindings and definitions is really mind-numbing
(2:21:22 PM) ***Retep998 sighs
(2:22:02 PM) rnk: If your only usage of stdcall is for interoperating with COM, you could audit the LLVM IR for functions with stdcall convention that have sret on the first parameter
(2:22:32 PM) rnk: we can't add a generalized check for that, since obviously there are stdcall free functions
(2:22:41 PM) rnk: anyway, sorry about that :(
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment