[llvm-commits] [LLVMdev] x86 calling conventions refactoring
Gordon Henriksen
gordonhenriksen at mac.com
Fri Jan 4 06:54:03 PST 2008
Anton,
Going back to the list now that it's working. :)
On 2008-01-04, at 08:22, Anton Korobeynikov wrote:
> Hello, Gordon.
>
> Here goes quick review.
>
>
>> +// Determines whether a CALL node uses struct return semantics.
>> +static bool CallIsStructReturn(SDOperand Op)
> I like these predicates, because later we can move them to the
> autogenerated code.
Yes!
>> + // Decoarate the function name.
> Typo
Okay.
>> + if (Is64Bit && CC == CallingConv::X86_FastCall &&
>> + !Subtarget->isTargetCygMing() && !Subtarget-
>> >isTargetWindows() &&
>> + (StackSize & 7) == 0)
and
>> + if (!Is64Bit && CC == CallingConv::X86_FastCall &&
>> + !Subtarget->isTargetCygMing() && !Subtarget-
>> >isTargetWindows() &&
>> + (NumBytes & 7) == 0)
>> + NumBytes += 4;
The former is also a typo. It should definitely be !Is64Bit.
> That's pretty interesting.
Indeed. I made some mechanical transformations where the rationale or
invariants were unclear.
> The source code was:
> - if (!Subtarget->isTargetCygMing() && !Subtarget-
> >isTargetWindows()) {
> - // Make sure the instruction takes 8n+4 bytes to make sure the
> start of the
> - // arguments and the arguments after the retaddr has been
> pushed are
> - // aligned.
> - if ((NumBytes & 7) == 0)
> - NumBytes += 4;
> - }
> -
> Actually this is a hunk from the times, when fastcall and fastcc
> shared the same LowerFORMAL_ARGUMENTS call.
History tends to repeat itself. :)
> The "funny" thing is that fastcall can be seen only on windows (32
> bit!) targets, so the condition is twice bogus. Most probably the
> whole hunk should be just eliminated.
If you're sure, I'll happily delete the lot. But it doesn't look
necessarily inert to me once the typo is fixed.
I think this should be sunken into GetAlignedArgumentStackSize if it
remains, since it's always called something like this:
unsigned NumBytes = CCInfo.getNextStackOffset();
if (CC == CallingConv::Fast)
NumBytes = GetAlignedArgumentStackSize(NumBytes, DAG);
+ // Make sure the instruction takes 8n+4 bytes to make sure the
start of the
+ // arguments and the arguments after the retaddr has been pushed
are aligned.
+ if (!Is64Bit && CC == CallingConv::X86_FastCall &&
+ !Subtarget->isTargetCygMing() && !Subtarget->isTargetWindows() &&
+ (NumBytes & 7) == 0)
+ NumBytes += 4;
Where GetAlignedArgumentStackSize is documented to…
/// GetAlignedArgumentStackSize - Make the stack size align e.g 16n +
12 aligned
/// for a 16 byte align requirement.
And is coded fairly generically, although I didn't dig deep enough to
figure out whether GetAlignedArgumentStackSize would DTRT in this
particular case. (getNextStackOffset won't; it's just an accumulator.)
Ultimately, I think GetAlignedArgumentStackSize should do this bit's
job, and the lot should be sunk into getNextStackOffset—but I was
trying to be safe and incremental.
>> + if (IsCalleePop(Op)) {
>> + BytesToPopOnReturn = StackSize; // Callee pops everything.
> Maybe it will be better to make function return amount of bytes to
> pop and fold ArgsAreStructReturn() call there?
Maybe something like that. This logic is essentially duplicated in
LowerCALL and LowerFORMAL_ARGUMENTS, except for the SDNode passed to
IsStructReturn is of differing type. (IsCalleePop just happens to be
looking at bits of FORMAL_ARGUMENTS or CALL nodes which are
structurally identical; CallIsStructReturn and ArgsAreStructReturn
don't have that luxury, though they could consult the SDNode's type.)
The relevant passages:
// Some CCs need callee pop.
if (IsCalleePop(Op)) {
BytesToPopOnReturn = StackSize; // Callee pops everything.
BytesCallerReserves = 0;
} else {
BytesToPopOnReturn = 0; // Callee pops nothing.
// If this is an sret function, the return should pop the hidden
pointer.
if (!Is64Bit && ArgsAreStructReturn(Op))
BytesToPopOnReturn = 4;
BytesCallerReserves = StackSize;
}
-----------------------------------------------------------------------------
// Create the CALLSEQ_END node.
unsigned NumBytesForCalleeToPush;
if (IsCalleePop(Op))
NumBytesForCalleeToPush = NumBytes; // Callee pops everything
else if (!Is64Bit && CallIsStructReturn(Op))
// If this is is a call to a struct-return function, the callee
// pops the hidden struct pointer, so we have to push it back.
// This is common for Darwin/X86, Linux & Mingw32 targets.
NumBytesForCalleeToPush = 4;
else
NumBytesForCalleeToPush = 0; // Callee pops nothing.
>> + if (IsTailCall || !Is64Bit ||
>> + getTargetMachine().getCodeModel() != CodeModel::Large)
>> + Callee = DAG.getTargetExternalSymbol(S->getSymbol(),
>> getPointerTy());
> I myself feel somehow inconvenient to have such condition here
> (mixing predicates of different sorts).
I don't like repeatedly consulting either PerformTailCallOpt/
IsTailCall or !Subtarget->is64Bit(). Rather, I'd prefer to have a
table-driven system. I think that's a followup patch, though; this one
is already too large.
> Maybe it will be worth to keep 64 bit variant separate. I don't
> know. Evan?
The 64-bit code diverged only in a very few details.
— Gordon
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20080104/88990417/attachment.html>
More information about the llvm-commits
mailing list