Emulate thiscall in C to create structure functions without self-regulation

This applies to a flurry of C object oriented messages, but differs in that I don't want all the functions, only one:

The ability to do this:

struct foo { int (*bar)(void); char baz; }; 

Then has a back link. C has a calling convention cdecl; basically pushes arguments onto the stack, has a return pointer, then jumps to some address. The code at this address pushes arguments from the stack and continues to have fun.

Thiscall convention is somewhat different in that it adds one additional argument, the "this" pointer, implicitly.

Since you can easily run arbitrary byte code in C and because gcc supports the built-in templating assembler, it sounds as if you could just make some kind of macro so you can do something like:

 int bar(void) { GETTHIS; cThis->baz = 0; } int createFoo(struct Foo*pFoo) { ASSIGN(pFoo, bar); } 

Basically, what ASSIGN will do is sidestep cdecl to somehow emulate thiscall style convention, and then what GETTHIS will do is the other side of the accounting trick.

I was wondering if:

  • A solution to this exists and
  • If not, if there is a reason why this cannot be done

Just this; the convenience of the true "We all agree with adults here," the style features in style, would be just awesome. Thanks!

Notes:

  • I just say x86, linux, gcc here ... I know that the world is a wide and strange place.
  • This is out of sheer curiosity .
+7
source share
3 answers

In the end, my friend got: https://gist.github.com/1516195 ... requires an arity function and is limited to x86_64 ... but yes, this is a pretty nice compromise that makes things really unobtrusive.

+4
source

First minor correction:

C has a calling convention cdecl; basically pushes arguments onto the stack, has a return pointer, then goes to some address. the code at this address pushes arguments from the stack and the fun path continues.

The calling command does not pop arguments from the stack. It reads the parameters without unloading them from the stack. Instead, the stack is cleared by the caller. This is because in the cdecl convention the caller does not know the exact number of parameters.

Now about your question. There is no strictly defined thiscall calling convention. More details here .

Gcc specific:

thiscall is almost identical to cdecl: the calling function clears the stack, and the parameters are passed in order from right to left. the difference is adding this pointer, which is the last stack, as if it were the first parameter in the Prototype function

You cannot do your trick by hiding the extra this argument and retrieving it inside the function body, especially because this is the argument to the first function. If you hide it, all other parameters of the function will be shifted. Instead, you can (and should IMHO) declare it as the first argument to the function, and you will have direct access to it, without the need for additional tricks:

 int bar(struct foo *cThis) { cThis->baz = 0; } 

MSVC specific:

... this pointer is passed to ECX, and it is the caller who clears the stack that mirrors the stdcall convention used in C for this compiler and in the Windows API functions. When functions use a variable number of arguments, it is the caller that clears the stack (see Cdecl).

Here you can do your trick by copying the value of the ECX into your local variable. Something like that:

 #define GETTHIS \ struct foo *cThis; \ _asm { \ mov cThis, ecx \ }; 

This, however, is complex and may not always work. The reason for this is that, according to the calling conventions of thiscall / stdcall ECX reserved for using the function, so the compiler can generate code that overwrites the value of the ECX . This can happen before you call the GETTHIS macro.

+4
source

No, in C there is no support for "thiscall", it is simple for C ++.

This is not a secret trick, just some kind of syntactic sugar.

When you write

 class foo { public: int bar(); char baz; }; 

the compiler conceptually rewrites this as

 struct foo { char baz; }; int bar(struct foo* this); 

and then when you do

 foo F; F.bar(); 

it compiled as equivalent

 struct foo F; bar(&F); 

That’s all you need!

If you want to play with Linus, you just need to do it manually because it doesn’t trust you to not use virtual inheritance once you type g ++ instead of gcc.

+3
source

All Articles