[cfe-commits] r63654 - /cfe/trunk/lib/CodeGen/CGCall.cpp
Daniel Dunbar
daniel at zuster.org
Tue Feb 3 12:00:13 PST 2009
Author: ddunbar
Date: Tue Feb 3 14:00:13 2009
New Revision: 63654
URL: http://llvm.org/viewvc/llvm-project?rev=63654&view=rev
Log:
x86_64 ABI: Initial implementation of ABI compliant parameter passing.
- Now only 27/500 failures on ABITest single argument tests; from
350/500. :)
- As with return types, a large percentage of these are likely to be
gcc bugs, not yet reviewed.
Also, fix bug in handling of Ignore ABI type in argument lists.
Modified:
cfe/trunk/lib/CodeGen/CGCall.cpp
Modified: cfe/trunk/lib/CodeGen/CGCall.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCall.cpp?rev=63654&r1=63653&r2=63654&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGCall.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGCall.cpp Tue Feb 3 14:00:13 2009
@@ -360,19 +360,16 @@
void classify(QualType T, ASTContext &Context, uint64_t OffsetBase,
Class &Lo, Class &Hi) const;
-public:
ABIArgInfo classifyReturnType(QualType RetTy,
- ASTContext &Context) const;
-
- ABIArgInfo classifyArgumentType(QualType RetTy,
- ASTContext &Context) const;
-
- virtual void computeInfo(CGFunctionInfo &FI, ASTContext &Context) const {
- FI.getReturnInfo() = classifyReturnType(FI.getReturnType(), Context);
- for (CGFunctionInfo::arg_iterator it = FI.arg_begin(), ie = FI.arg_end();
- it != ie; ++it)
- it->info = classifyArgumentType(it->type, Context);
- }
+ ASTContext &Context) const;
+
+ ABIArgInfo classifyArgumentType(QualType Ty,
+ ASTContext &Context,
+ unsigned &freeIntRegs,
+ unsigned &freeSSERegs) const;
+
+public:
+ virtual void computeInfo(CGFunctionInfo &FI, ASTContext &Context) const;
};
}
@@ -673,15 +670,118 @@
return ABIArgInfo::getCoerce(ResType);
}
-ABIArgInfo X86_64ABIInfo::classifyArgumentType(QualType Ty,
- ASTContext &Context) const {
- if (CodeGenFunction::hasAggregateLLVMType(Ty)) {
- return ABIArgInfo::getByVal(0);
+ABIArgInfo X86_64ABIInfo::classifyArgumentType(QualType Ty, ASTContext &Context,
+ unsigned &freeIntRegs,
+ unsigned &freeSSERegs) const {
+ X86_64ABIInfo::Class Lo, Hi;
+ classify(Ty, Context, 0, Lo, Hi);
+
+ // Check some invariants.
+ // FIXME: Enforce these by construction.
+ assert((Hi != Memory || Lo == Memory) && "Invalid memory classification.");
+ assert((Lo != NoClass || Hi == NoClass) && "Invalid null classification.");
+ assert((Hi != SSEUp || Lo == SSE) && "Invalid SSEUp classification.");
+
+ unsigned neededInt = 0, neededSSE = 0;
+ const llvm::Type *ResType = 0;
+ switch (Lo) {
+ case NoClass:
+ return ABIArgInfo::getIgnore();
+
+ // AMD64-ABI 3.2.3p3: Rule 1. If the class is MEMORY, pass the argument
+ // on the stack.
+ case Memory:
+
+ // AMD64-ABI 3.2.3p3: Rule 5. If the class is X87, X87UP or
+ // COMPLEX_X87, it is passed in memory.
+ case X87:
+ case ComplexX87:
+ // Choose appropriate in memory type.
+ if (CodeGenFunction::hasAggregateLLVMType(Ty))
+ return ABIArgInfo::getByVal(0);
+ else
+ return ABIArgInfo::getDirect();
+
+ case SSEUp:
+ case X87Up:
+ assert(0 && "Invalid classification for lo word.");
+
+ // AMD64-ABI 3.2.3p3: Rule 2. If the class is INTEGER, the next
+ // available register of the sequence %rdi, %rsi, %rdx, %rcx, %r8
+ // and %r9 is used.
+ case Integer:
+ ++neededInt;
+ ResType = llvm::Type::Int64Ty;
+ break;
+
+ // AMD64-ABI 3.2.3p3: Rule 3. If the class is SSE, the next
+ // available SSE register is used, the registers are taken in the
+ // order from %xmm0 to %xmm7.
+ case SSE:
+ ++neededSSE;
+ ResType = llvm::Type::DoubleTy;
+ break;
+ }
+
+ switch (Hi) {
+ // Memory was handled previously, ComplexX87 and X87 should
+ // never occur as hi classes, and X87Up must be preceed by X87,
+ // which is passed in memory.
+ case Memory:
+ case X87:
+ case X87Up:
+ case ComplexX87:
+ assert(0 && "Invalid classification for hi word.");
+
+ case NoClass: break;
+ case Integer:
+ ResType = llvm::StructType::get(ResType, llvm::Type::Int64Ty, NULL);
+ ++neededInt;
+ break;
+ case SSE:
+ ResType = llvm::StructType::get(ResType, llvm::Type::DoubleTy, NULL);
+ ++neededSSE;
+ break;
+
+ // AMD64-ABI 3.2.3p3: Rule 4. If the class is SSEUP, the
+ // eightbyte is passed in the upper half of the last used SSE
+ // register.
+ case SSEUp:
+ assert(Lo == SSE && "Unexpected SSEUp classification.");
+ ResType = llvm::VectorType::get(llvm::Type::DoubleTy, 2);
+ break;
+ }
+
+ // AMD64-ABI 3.2.3p3: If there are no registers available for any
+ // eightbyte of an argument, the whole argument is passed on the
+ // stack. If registers have already been assigned for some
+ // eightbytes of such an argument, the assignments get reverted.
+ if (freeIntRegs >= neededInt && freeSSERegs >= neededSSE) {
+ freeIntRegs -= neededInt;
+ freeSSERegs -= neededSSE;
+ return ABIArgInfo::getCoerce(ResType);
} else {
- return ABIArgInfo::getDirect();
+ // Choose appropriate in memory type.
+ if (CodeGenFunction::hasAggregateLLVMType(Ty))
+ return ABIArgInfo::getByVal(0);
+ else
+ return ABIArgInfo::getDirect();
}
}
+void X86_64ABIInfo::computeInfo(CGFunctionInfo &FI, ASTContext &Context) const {
+ FI.getReturnInfo() = classifyReturnType(FI.getReturnType(), Context);
+
+ // Keep track of the number of assigned registers.
+ unsigned freeIntRegs = 6, freeSSERegs = 8;
+
+ // AMD64-ABI 3.2.3p3: Once arguments are classified, the registers
+ // get assigned (in left-to-right order) for passing as follows...
+ for (CGFunctionInfo::arg_iterator it = FI.arg_begin(), ie = FI.arg_end();
+ it != ie; ++it)
+ it->info = classifyArgumentType(it->type, Context, freeIntRegs, freeSSERegs);
+}
+
ABIArgInfo DefaultABIInfo::classifyReturnType(QualType RetTy,
ASTContext &Context) const {
if (RetTy->isVoidType()) {
@@ -1108,7 +1208,8 @@
}
case ABIArgInfo::Ignore:
- break;
+ // Skip increment, no matching LLVM parameter.
+ continue;
case ABIArgInfo::Coerce: {
assert(AI != Fn->arg_end() && "Argument mismatch!");
More information about the cfe-commits
mailing list