What is the state of the registers after a function call? - c++

I have limited knowledge in assembly, but I can at least read through it and match with the corresponding C or C++ code. I can see that the function arguments are passed either by pushing them to the stack or by registers, and the function body uses some registers to do its operations. But it also seems to use the same registers that were used in the caller. Does this mean that the caller has no guarantee that the state of the registers will be the same after a function call? What if the whole body of the function is unknown during compilation? How does the compiler deal with this?

The compiler-generated assembler code follows some calling convention. A calling convention typically specifies
how are arguments passed to the function
how return values are passed from the called function to the caller
which registers should be saved within a function call and which can be modified
If all functions being called follow the same calling convention, no problems with using the same registers should occur.

As the comments allude to, the fact is that there is no standard for this. It is left entirely to the implementors of the particular c++ compiler you are using.
A more explicit question, like this: "when compiling on version N of compiler A with compiler options B, calling a function signature of C, for target CPU D, using ABI E, what are the guarantees vis-a-vis register preservation?"
In which case an expert (or the manual) on that particular toolset can answer.
As you can probably infer, for any kind of industrial-strength project, it's the wrong question to ask, because as your compiler evolves the answer will change, and you don't want that fact to impact the reliability of your program.
It's a good question, because it's nice to know what the compiler is doing under the hood - it aids learning.
But on the whole, the golden rule is to express clear uncomplicated logic to the compiler in your program, and allow the compiler to handle the details of turning that logic into optimised machine code, at which modern compilers are excellent.

Related

Does C++ replace built-in operators with function calls?

I was recently reading about operator overloading in C++. So, I was wondering whether the built-in operators are replaced by function calls behind the scenes.
For example, Is a + b(a and b are int types) replaced by a.operator+(b)? Or the compiler does something different?
There is no int::operator+. Whether the compiler chooses to compile a + b directly to assembly (likely) or replace it with some internal function like int __add_ints(int, int) (unlikely) is an implementation detail.
The internals of the compiler are complex. On a conceptual level, the answer is YES. Whenever a compiler sees a + b, it does have to check for known functions with the name operator+ and replace it with a call to the right function.
In practice, their are 2 important nuances to make:
The compiler knows about fundamental types (which you can't override), it doesn't need to insert a function call it can immediately insert the right 'instructions'
Inlining is an important optimization, which will remove the function call when interesting
Maybe. Many arithmetic operations map dir calypso into CPU instructions, and the compiler will just generate the appropriate code in place. If that’s not possible, the compiler will generate a call to an appropriate function, and the runtime library will have a definition of that function. Back in the olden days floating-point math was usually done with function calls. These days, CPUs for desktop systems have floating-point hardware, and floating-point math is generated as direct CPU instructions. But embedded systems often don’t have hardware for that, so the compiler generates function calls instead.
Back in the really early days, even integer math was sometimes done with function calls. Because of his, the IBM 1620 was sometimes referred to as the CADET: Can’t Add, Doesn’t Even Try.

Is the C++ calling convention constrained by the standard, since the return type of a function does not need to be defined when the fn is declared?

While studying the One Definition Rule in Wikipedia, I became stuck on the following example in the Examples section:
struct S; // declaration of S
...
S f(); // ok, no definition required
...
I know that space on the stack needs to be allotted for the return value, but seeing this example made me think that C++ calling conventions might dictate that stack management for the return value is handled by the code block in which the function is defined, rather than the code block in which it is called. So I investigated "C vs. C++ calling convention" (recalling that the issue of stack return value allocation might be a primary difference), and came across this answer, which indicates that "calling convention" is not defined by the standard.
However, given the apparent requirement that the above code snippet is valid, it seems to me that there must be some constraints on calling convention in order to support the above code snippet.
Am I right? Does the C++ standard implicitly require that stack management for the return value of a function be handled by the code that defines the function, in order to support the syntax above?
As mentioned in the comments
As you have written your example, Both Struct S and function f are forward declarations. The Compiler Will indeed complain if you attempt to use either
** EDIT as noted by Steven Sudit, function f is not a forward declaration but a function prototype**
and
Also, I believe that default calling convention ( and optional calling conventions ) are explicitly implementation dependent with the exception of those with external linkage. If you search the c++ standard for "calling convention". It is mentioned only once in section 7.5 Linkage Specifications
As to your specific question
Am I right? Does the C++ standard implicitly require that stack management for the return value of a function be handled by the code that defines the function, in order to support the syntax above?
Definitely not, as many compilers support calling conventions where the values are not even passed/returned on the stack (FASTCALL) or microsofts version of (thiscall) where the caller cleans the stack.
The C/C++ standard does not define calling conventions. That is the job of compiler vendors to implement on their own, as evident by the fact that calling convention keywords start with underscores indicating they are vendor-provided extensions.
The C/C++ standard defines the base rules (how to assign values to parameters and return values, pass by-value vs by-reference, etc), but the calling conventions dictate how to accomplish those rules in different ways (passing parameters via stack or registers, in which order, which registers, who cleans up the stack, etc).
In the casev of x86, vendors have agreed on the semantics of the __cdecl and __stdcall calling conventions for interoperability (although there are some slight variations in __cdecl implementations in some cases), but other calling conventions are vendor-specific (Microsoft's __fastcall/__thiscall, Borland's __fastcall/__safecall/__msfastcall, etc).
In the case of x64, there is only one calling convention, dictated by x64 itself. Calling convention keywords are silently ignored by x64 compiler so existing code will still compile and work correctly (as long as it is not using inline assembly to access/manipulate the call stack directly).

can compiler reorganize instructions over sleep call?

Is there a difference if it is the first use of the variable or not. For example are a and b treated differently?
void f(bool&a, bool& b)
{
...
a=false;
boost::this_thread::sleep...//1 sec sleep
a=true;
b=true;
...
}
EDIT: people asked why I want to know this.
1. I would like to have some way to tell the compiler not to optimize(swap the order of the execution of the instructions) in some function, and using atomic and or mutexes is much more complicated than using sleep(and in my case sleeping is not a performance problem).
2. Like I said this is generally important to know.
We can't really tell. On scenario could be that the compiler has full introspection to your function at the calling site (and possibly does inline it), in which case it can jumble your function with the caller, and then do optimizations appropriately.
It could then e.g. completely optimize away a and b because there is no code that depends on a and b. Or it might see that you violate aliasing rules so that a and b refer to the same entity, and then merge them according to your program flow.
But it could also be that you tell the compiler to not optimize at all, e.g. with g++'s -O0 flag, in which case not much will happen.
The only proof for your particular platform *, can be made by looking at the generated assembly, or by telling the compiler to please output some log about what it optimizes (g++ has many flags for that).
* compiler+flags used to compile compiler+version+add-ons, hardware, operating system; even the weather might be relevant if your compiler omits some optimizations if it takes to long [which would actually be cool feature for debug builds, imho]
They are not local (because they are references), so it can't, because it can't tell whether the called function sees them or not and has to assume that it does. If they were local variables, it could, because local variables are not visible to the called function unless pointer or reference to them was created.

In C++, do variadic functions (those with ... at the end of the parameter list) necessarily follow the __cdecl calling convention?

I know that __stdcall functions can't have ellipses, but I want to be sure there are no platforms that support the stdarg.h functions for calling conventions other than __cdecl or __stdcall.
The calling convention has to be one where the caller clears the arguments from the stack (because the callee doesn't know what will be passed).
That doesn't necessarily correspond to what Microsoft calls "__cdecl" though. Just for example, on a SPARC, it'll normally pass the arguments in registers, because that's how the SPARC is designed to work -- its registers basically act as a call stack that gets spilled to main memory if the calls get deep enough that they won't fit into register anymore.
Though I'm less certain about it, I'd expect roughly the same on IA64 (Itanium) -- it also has a huge register set (a couple hundred if memory serves). If I'm not mistaken, it's a bit more permissive about how you use the registers, but I'd expect it to be used similarly at least a lot of the time.
Why does this matter to you? The point of using stdarg.h and its macros is to hide differences in calling convention from your code, so it can work with variable arguments portably.
Edit, based on comments: Okay, now I understand what you're doing (at least enough to improve the answer). Given that you already (apparently) have code to handle the variations in the default ABI, things are simpler. That only leaves the question of whether variadic functions always use the "default ABI", whatever that happens to be for the platform at hand. With "stdcall" and "default" as the only options, I think the answer to that is yes. Just for example, on Windows, wsprintf and wprintf break the rule of thumb, and uses cdecl calling convention instead of stdcall.
The most definitive way that you can determine this is to analyze the calling conventions. For variadic functions to work, your calling convention needs a couple of attributes:
The callee must be able to access the parameters that aren't part of the variable argument list from a fixed offset from the top of the stack. This requires that the compiler push the parameters onto the stack from right to left. (This includes such things as the first parameter to printf, the format specification. Also, the address of the variable argument list itself must also be derived from a known location.)
The caller must be responsible for removing the parameters off the stack once the function has returned, because only the compiler, while generating the code for the caller, knows how many parameters were pushed onto the stack in the first place. The variadic function itself does not have this information.
stdcall won't work because the callee is responsible for popping parameters off the stack. In the old 16-bit Windows days, pascal wouldn't work because it pushed parameters onto the stack from left to right.
Of course, as the other answers have alluded to, many platforms don't give you any choice in terms of calling convention, making this question irrelevant for those ones.
Consider the following function on an x86 system:
void __stdcall something(char *, ...);
The function declares itself as __stdcall, which is a callee-clean convention. But a variadic function cannot be callee-clean since the callee does not know how many parameters were passed, so it doesn’t know how many it should clean.
The Microsoft Visual Studio C/C++ compiler resolves this conflict by silently converting the calling convention to __cdecl, which is the only supported variadic calling convention for functions that do not take a hidden this parameter.
Why does this conversion take place silently rather than generating a warning or error?
My guess is that it’s to make the compiler options /Gr (set default calling convention to __fastcall) and /Gz (set default calling convention to __stdcall) less annoying.
Automatic conversion of variadic functions to __cdecl means that you can just add the /Gr or /Gz command line switch to your compiler options, and everything will still compile and run (just with the new calling convention).
Another way of looking at this is not by thinking of the compiler as converting variadic __stdcall to __cdecl but rather by simply saying “for variadic functions, __stdcall is caller-clean.”
click here
AFAIK, the diversity of calling conventions is unique to DOS/Windows on x86. Most other platforms had compilers come with the OS and standardize the convention.
Do you mean 'platforms supported by MSVC" or as a general rule? Even if you confine yourself to the platforms supported by MSVC, you still have situations like IA64 and AMD64 where there is only "one" calling convention, and that calling convention is called __stdcall, but it's certainly not the same __stdcall you get on x86.

Switching callstack for C++ functions

Here's my previous question about switching C callstacks. However, C++ uses a different calling convention (thiscall) and may require some different asm code. Can someone explain the differences and point to or supply some code snippets that switch C++ callstacks (preferably in GCC inline asm)?
Thanks,
James
The code given in the previous question should work fine.
The thiscall calling convention differs only in who is responsible for popping the arguments off the stack. Under the thiscall calling convention, the callee pops the arguments (and additionally, the this pointer is passed in ecx); under the C calling convention, the caller pops the arguments. This does not affect context switches.
However, if you're going to do context switches yourself, note that you need to save and restore the registers as well (probably on the stack) in addition to switching stacks.
Note, by the way, that C++ doesn't always use thiscall -- it's only used for methods with a fixed number of arguments (and apart from that, it's a Microsoftism... g++ doesn't use it).
Note the ABI for C++ is not explicitly defined.
The idea was that compiler manufactures are able to use the optimal calling convention for the situation and thus make C++ faster.
The down side of this is that each compiler has its own calling convention thus code from different compilers are not compatable (even code form different versions (or even different optimization flags) of the same compiler can be incompatable).