diff options
author | Daniel Dunbar <daniel@zuster.org> | 2009-05-26 16:37:37 +0000 |
---|---|---|
committer | Daniel Dunbar <daniel@zuster.org> | 2009-05-26 16:37:37 +0000 |
commit | 86e13eeb65397f7b64173523a40c742b2702364b (patch) | |
tree | 5590bf0cadba6c1f2bc16113faa40d63e6e4a81c | |
parent | 8e6e70928adebea871389febd9b54ca82821dc87 (diff) |
When trying to pass an argument on the stack, assume LLVM will do the right
thing for non-aggregate types.
- Otherwise we unnecessarily pin values to the stack and currently end up
triggering a backend bug in one case.
- This loose cooperation with LLVM to implement the ABI is pretty ugly.
- <rdar://problem/6918722> [irgen] clang miscompile of many pointer varargs on
x86-64
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@72419 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/CodeGen/CGCall.cpp | 22 | ||||
-rw-r--r-- | test/CodeGen/x86_64-arguments.c | 13 |
2 files changed, 32 insertions, 3 deletions
diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp index ce98f8c256..ea0b887c64 100644 --- a/lib/CodeGen/CGCall.cpp +++ b/lib/CodeGen/CGCall.cpp @@ -571,6 +571,11 @@ class X86_64ABIInfo : public ABIInfo { const llvm::Type *CoerceTo, ASTContext &Context) const; + /// getIndirectResult - Give a source type \arg Ty, return a suitable result + /// such that the argument will be passed in memory. + ABIArgInfo getIndirectResult(QualType Ty, + ASTContext &Context) const; + ABIArgInfo classifyReturnType(QualType RetTy, ASTContext &Context) const; @@ -871,6 +876,17 @@ ABIArgInfo X86_64ABIInfo::getCoerceResult(QualType Ty, return ABIArgInfo::getCoerce(CoerceTo); } +ABIArgInfo X86_64ABIInfo::getIndirectResult(QualType Ty, + ASTContext &Context) const { + // If this is a scalar LLVM value then assume LLVM will pass it in the right + // place naturally. + if (!CodeGenFunction::hasAggregateLLVMType(Ty)) + return ABIArgInfo::getDirect(); + + // FIXME: Set alignment correctly. + return ABIArgInfo::getIndirect(0); +} + ABIArgInfo X86_64ABIInfo::classifyReturnType(QualType RetTy, ASTContext &Context) const { // AMD64-ABI 3.2.3p4: Rule 1. Classify the return type with the @@ -895,7 +911,7 @@ ABIArgInfo X86_64ABIInfo::classifyReturnType(QualType RetTy, // AMD64-ABI 3.2.3p4: Rule 2. Types of class memory are returned via // hidden argument. case Memory: - return ABIArgInfo::getIndirect(0); + return getIndirectResult(RetTy, Context); // AMD64-ABI 3.2.3p4: Rule 3. If the class is INTEGER, the next // available register of the sequence %rax, %rdx is used. @@ -991,7 +1007,7 @@ ABIArgInfo X86_64ABIInfo::classifyArgumentType(QualType Ty, ASTContext &Context, // COMPLEX_X87, it is passed in memory. case X87: case ComplexX87: - return ABIArgInfo::getIndirect(0); + return getIndirectResult(Ty, Context); case SSEUp: case X87Up: @@ -1076,7 +1092,7 @@ void X86_64ABIInfo::computeInfo(CGFunctionInfo &FI, ASTContext &Context) const { freeIntRegs -= neededInt; freeSSERegs -= neededSSE; } else { - it->info = ABIArgInfo::getIndirect(0); + it->info = getIndirectResult(it->type, Context); } } } diff --git a/test/CodeGen/x86_64-arguments.c b/test/CodeGen/x86_64-arguments.c index 3b4f5ff68f..6f7ec82872 100644 --- a/test/CodeGen/x86_64-arguments.c +++ b/test/CodeGen/x86_64-arguments.c @@ -69,4 +69,17 @@ struct s13_0 { long long f0[3]; }; struct s13_0 f13(int a, int b, int c, int d, struct s13_1 { long long f0[2]; } e, int f) {} +// RUN: grep 'define void @f14(.*, i8 signext .X)' %t && +void f14(int a, int b, int c, int d, int e, int f, + char X) {} +// RUN: grep 'define void @f15(.*, i8\* .X)' %t && +void f15(int a, int b, int c, int d, int e, int f, + void *X) {} +// RUN: grep 'define void @f16(.*, float .X)' %t && +void f16(float a, float b, float c, float d, float e, float f, float g, float h, + float X) {} +// RUN: grep 'define void @f17(.*, x86_fp80 .X)' %t && +void f17(float a, float b, float c, float d, float e, float f, float g, float h, + long double X) {} + // RUN: true |