From: Daniel Dunbar Date: Tue, 26 May 2009 16:37:37 +0000 (+0000) Subject: When trying to pass an argument on the stack, assume LLVM will do the right X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=86e13eeb65397f7b64173523a40c742b2702364b;p=clang 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. - [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 --- 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