Appel [App02] very briefly mentions that C (and presumably C++) provide guarantees regarding the locations of actual parameters in contiguous memory as opposed to registers when the address-of operator is applied to one of formal parameters within the function block.
e.g.
void foo(int a, int b, int c, int d)
{
int* p = &a;
for(int k = 0; k < 4; k++)
{
std::cout << *p << " ";
p++;
}
std::cout << std::endl;
}
and an invocation such as...
foo(1,2,3,4);
will produce the following output "1 2 3 4"
My question is "How does this interact with calling conventions?"
For example __fastcall on GCC will try place the first two arguments in registers and the remainder on the stack. The two requirements are at odds with each other, is there any way to formally reason about what will happen or is it subject to the capricious nature of implementation defined behaviour?
[App02] Modern Compiler Implementation in Java, Andrew w. Appel, Chapter 6, Page 124
Update: I suppose that this question is answered. I think I was wrong to base the whole question on contiguous memory allocation when what I was looking for (and what the reference speaks of) is the apparent mismatch between the need for parameters being in memory due the use of address-of as opposed to in registers due to calling conventions, maybe that is a question for another day.
Someone on the internet is wrong and sometimes that someone is me.
First of all your code doesn't always produce 1, 2, 3, 4. Just check this one: http://ideone.com/ohtt0 Correct code is at least like this:
void foo(int a, int b, int c, int d)
{
int* p = &a;
for (int i = 0; i < 4; i++)
{
std::cout << *p;
p++;
}
}
So now let's try with fastcall
, here:
void __attribute__((fastcall)) foo(int a, int b, int c, int d)
{
int* p = &a;
for (int i = 0; i < 4; i++)
{
std::cout << *p << " ";
p++;
}
}
int main()
{
foo(1,2,3,4);
}
Result is messy: 1 -1216913420 134514560 134514524
So I really doubt that something can be guaranteed here.
The C++ standard has no concept of a calling convention. That's left for the compiler to deal with.
In this case, if the standard requires that parameters be contiguous when the address-of operator is applied, there's a conflict between what the standard requires of your compiler and what you require of it.
It's up to the compiler to decide what to do. I'd think most compilers would give your requirements priority over the standard's, however.
There is nothing in the standard about calling conventions or how parameters are passed.
It is true that if you take the address of one variable (or parameter) that one has to be stored in memory. It doesn't say that the value cannot be passed in a register and then stored to memory when its address is taken.
It definitely doesn't affect other variables, who's addresses are not taken.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With