From: Daniel Dunbar Date: Sat, 14 Feb 2009 02:09:24 +0000 (+0000) Subject: x86_64 ABI: Pass simple types directly when possible. This is X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=644f4c3fe4130c7be75d6191340ba8d857ba0730;p=clang x86_64 ABI: Pass simple types directly when possible. This is important for both keeping the generated LLVM simple and for ensuring that integer types are passed/promoted correctly. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@64529 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp index 808d9f2c46..debf131903 100644 --- a/lib/CodeGen/CGCall.cpp +++ b/lib/CodeGen/CGCall.cpp @@ -423,6 +423,20 @@ class X86_64ABIInfo : public ABIInfo { void classify(QualType T, ASTContext &Context, uint64_t OffsetBase, Class &Lo, Class &Hi) const; + /// getCoerceResult - Given a source type \arg Ty and an LLVM type + /// to coerce to, chose the best way to pass Ty in the same place + /// that \arg CoerceTo would be passed, but while keeping the + /// emitted code as simple as possible. + /// + /// FIXME: Note, this should be cleaned up to just take an + /// enumeration of all the ways we might want to pass things, + /// instead of constructing an LLVM type. This makes this code more + /// explicit, and it makes it clearer that we are also doing this + /// for correctness in the case of passing scalar types. + ABIArgInfo getCoerceResult(QualType Ty, + const llvm::Type *CoerceTo, + ASTContext &Context) const; + ABIArgInfo classifyReturnType(QualType RetTy, ASTContext &Context) const; @@ -647,6 +661,22 @@ void X86_64ABIInfo::classify(QualType Ty, } } +ABIArgInfo X86_64ABIInfo::getCoerceResult(QualType Ty, + const llvm::Type *CoerceTo, + ASTContext &Context) const { + if (CoerceTo == llvm::Type::Int64Ty) { + // Integer and pointer types will end up in a general purpose + // register. + if (Ty->isIntegerType() || Ty->isPointerType()) + return ABIArgInfo::getDirect(); + } else if (CoerceTo == llvm::Type::DoubleTy) { + // Float and double end up in a single SSE reg. + if (Ty == Context.FloatTy || Ty == Context.DoubleTy) + return ABIArgInfo::getDirect(); + } + + return ABIArgInfo::getCoerce(CoerceTo); +} ABIArgInfo X86_64ABIInfo::classifyReturnType(QualType RetTy, ASTContext &Context) const { @@ -733,7 +763,7 @@ ABIArgInfo X86_64ABIInfo::classifyReturnType(QualType RetTy, break; } - return ABIArgInfo::getCoerce(ResType); + return getCoerceResult(RetTy, ResType, Context); } ABIArgInfo X86_64ABIInfo::classifyArgumentType(QualType Ty, ASTContext &Context, @@ -819,7 +849,7 @@ ABIArgInfo X86_64ABIInfo::classifyArgumentType(QualType Ty, ASTContext &Context, break; } - return ABIArgInfo::getCoerce(ResType); + return getCoerceResult(Ty, ResType, Context); } void X86_64ABIInfo::computeInfo(CGFunctionInfo &FI, ASTContext &Context) const { diff --git a/test/CodeGen/x86_64-arguments.c b/test/CodeGen/x86_64-arguments.c new file mode 100644 index 0000000000..28e8788912 --- /dev/null +++ b/test/CodeGen/x86_64-arguments.c @@ -0,0 +1,29 @@ +// RUN: clang -triple x86_64-unknown-unknown -emit-llvm -o %t %s && +// RUN: grep 'define signext i8 @f0()' %t && +// RUN: grep 'define signext i16 @f1()' %t && +// RUN: grep 'define i32 @f2()' %t && +// RUN: grep 'define float @f3()' %t && +// RUN: grep 'define double @f4()' %t && +// RUN: grep 'define x86_fp80 @f5()' %t && +// RUN: grep 'define void @f6(i8 signext %a0, i16 signext %a1, i32 %a2, i64 %a3, i8\* %a4)' %t + +char f0(void) { +} + +short f1(void) { +} + +int f2(void) { +} + +float f3(void) { +} + +double f4(void) { +} + +long double f5(void) { +} + +void f6(char a0, short a1, int a2, long long a3, void *a4) { +}