aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/CodeGen/CGCall.cpp5
-rw-r--r--test/CodeGen/x86_64-arguments.c8
2 files changed, 13 insertions, 0 deletions
diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp
index 356caa3f90..ce98f8c256 100644
--- a/lib/CodeGen/CGCall.cpp
+++ b/lib/CodeGen/CGCall.cpp
@@ -1055,6 +1055,11 @@ void X86_64ABIInfo::computeInfo(CGFunctionInfo &FI, ASTContext &Context) const {
// Keep track of the number of assigned registers.
unsigned freeIntRegs = 6, freeSSERegs = 8;
+
+ // If the return value is indirect, then the hidden argument is consuming one
+ // integer register.
+ if (FI.getReturnInfo().isIndirect())
+ --freeIntRegs;
// AMD64-ABI 3.2.3p3: Once arguments are classified, the registers
// get assigned (in left-to-right order) for passing as follows...
diff --git a/test/CodeGen/x86_64-arguments.c b/test/CodeGen/x86_64-arguments.c
index b28e064d35..3b4f5ff68f 100644
--- a/test/CodeGen/x86_64-arguments.c
+++ b/test/CodeGen/x86_64-arguments.c
@@ -61,4 +61,12 @@ struct s12 { int a __attribute__((aligned(16))); };
struct s12 f12_0(void) {}
void f12_1(struct s12 a0) {}
+// Check that sret parameter is accounted for when checking available integer
+// registers.
+// RUN: grep 'define void @f13(.struct.s13_0. noalias sret .agg.result, i32 .a, i32 .b, i32 .c, i32 .d, .struct.s13_1. byval .e, i32 .f)' %t &&
+
+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: true