https://github.com/koachan updated 
https://github.com/llvm/llvm-project/pull/155829

>From a8707a6452b77b75603dc780213835f6e5e4b582 Mon Sep 17 00:00:00 2001
From: Koakuma <koac...@protonmail.com>
Date: Thu, 28 Aug 2025 19:48:38 +0700
Subject: [PATCH 1/7] [clang][SPARC] Pass 16-aligned 16-byte structs as i128 in
 CC

This coerces 16-byte C structs that are 16-byte aligned as an i128 in LLVM IR.
Additionally, since i128 values will be lowered as split i64 pairs in the 
backend,
correctly set the alignment of such arguments as 16 bytes.

This should make it compliant with the ABI specification and fix 
https://github.com/llvm/llvm-project/issues/144709.
---
 clang/lib/CodeGen/Targets/Sparc.cpp         | 11 ++++++++---
 clang/test/CodeGen/sparcv9-abi.c            |  9 +++++++++
 llvm/lib/Target/Sparc/SparcISelLowering.cpp |  3 ++-
 llvm/test/CodeGen/SPARC/64abi.ll            | 15 ++++++++++++++-
 4 files changed, 33 insertions(+), 5 deletions(-)

diff --git a/clang/lib/CodeGen/Targets/Sparc.cpp 
b/clang/lib/CodeGen/Targets/Sparc.cpp
index 5f3c15d106eb6..300b5fdf35e37 100644
--- a/clang/lib/CodeGen/Targets/Sparc.cpp
+++ b/clang/lib/CodeGen/Targets/Sparc.cpp
@@ -228,6 +228,7 @@ SparcV9ABIInfo::classifyType(QualType Ty, unsigned 
SizeLimit) const {
     return ABIArgInfo::getIgnore();
 
   uint64_t Size = getContext().getTypeSize(Ty);
+  unsigned Alignment = getContext().getTypeAlign(Ty);
 
   // Anything too big to fit in registers is passed with an explicit indirect
   // pointer / sret pointer.
@@ -275,10 +276,14 @@ SparcV9ABIInfo::classifyType(QualType Ty, unsigned 
SizeLimit) const {
   // Try to use the original type for coercion.
   llvm::Type *CoerceTy = CB.isUsableType(StrTy) ? StrTy : CB.getType();
 
+  // We use a pair of i64 for 16-byte aggregate with 8-byte alignment.
+  // For 16-byte aggregates with 16-byte alignment, we use i128.
+  llvm::Type *WideTy = llvm::Type::getIntNTy(getVMContext(), 128);
+  bool UseI128 = (Size == 128) && (Alignment == 128);
+
   if (CB.InReg)
-    return ABIArgInfo::getDirectInReg(CoerceTy);
-  else
-    return ABIArgInfo::getDirect(CoerceTy);
+    return ABIArgInfo::getDirectInReg(UseI128 ? WideTy : CoerceTy);
+  return ABIArgInfo::getDirect(UseI128 ? WideTy : CoerceTy);
 }
 
 RValue SparcV9ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
diff --git a/clang/test/CodeGen/sparcv9-abi.c b/clang/test/CodeGen/sparcv9-abi.c
index 5a3d64fd37889..9819d07425274 100644
--- a/clang/test/CodeGen/sparcv9-abi.c
+++ b/clang/test/CodeGen/sparcv9-abi.c
@@ -25,12 +25,21 @@ long double f_ld(long double x) { return x; }
 struct empty {};
 struct emptyarr { struct empty a[10]; };
 
+// 16-byte structs with 16-byte alignment gets passed as if i128.
+struct align16 { _Alignas(16) int x; };
+
 // CHECK-LABEL: define{{.*}} i64 @f_empty(i64 %x.coerce)
 struct empty f_empty(struct empty x) { return x; }
 
 // CHECK-LABEL: define{{.*}} i64 @f_emptyarr(i64 %x.coerce)
 struct empty f_emptyarr(struct emptyarr x) { return x.a[0]; }
 
+// CHECK-LABEL: define{{.*}} void @f_aligncaller(i128 %a.coerce)
+void f_aligncallee(int pad, struct align16 a);
+void f_aligncaller(struct align16 a) {
+    f_aligncallee(0, a);
+}
+
 // CHECK-LABEL: define{{.*}} i64 @f_emptyvar(i32 noundef zeroext %count, ...)
 long f_emptyvar(unsigned count, ...) {
     long ret;
diff --git a/llvm/lib/Target/Sparc/SparcISelLowering.cpp 
b/llvm/lib/Target/Sparc/SparcISelLowering.cpp
index d01218f573dc2..e5ed9d267afed 100644
--- a/llvm/lib/Target/Sparc/SparcISelLowering.cpp
+++ b/llvm/lib/Target/Sparc/SparcISelLowering.cpp
@@ -115,7 +115,8 @@ static bool Analyze_CC_Sparc64_Full(bool IsReturn, unsigned 
&ValNo, MVT &ValVT,
 
   // Stack space is allocated for all arguments starting from [%fp+BIAS+128].
   unsigned size      = (LocVT == MVT::f128) ? 16 : 8;
-  Align alignment = (LocVT == MVT::f128) ? Align(16) : Align(8);
+  Align alignment =
+      (LocVT == MVT::f128 || ArgFlags.isSplit()) ? Align(16) : Align(8);
   unsigned Offset = State.AllocateStack(size, alignment);
   unsigned Reg = 0;
 
diff --git a/llvm/test/CodeGen/SPARC/64abi.ll b/llvm/test/CodeGen/SPARC/64abi.ll
index 6485a7f13e8d5..dc8c9af4a5185 100644
--- a/llvm/test/CodeGen/SPARC/64abi.ll
+++ b/llvm/test/CodeGen/SPARC/64abi.ll
@@ -473,8 +473,8 @@ declare i64 @receive_fp128(i64 %a, ...)
 ; HARD-DAG:   ldx [%sp+[[Offset0]]], %o2
 ; HARD-DAG:   ldx [%sp+[[Offset1]]], %o3
 ; SOFT-DAG:   mov  %i0, %o0
-; SOFT-DAG:   mov  %i1, %o1
 ; SOFT-DAG:   mov  %i2, %o2
+; SOFT-DAG:   mov  %i3, %o3
 ; CHECK:      call receive_fp128
 define i64 @test_fp128_variable_args(i64 %a, fp128 %b) {
 entry:
@@ -482,6 +482,19 @@ entry:
   ret i64 %0
 }
 
+declare i64 @receive_i128(i64 %a, i128 %b)
+
+; CHECK-LABEL: test_i128_args:
+; CHECK:   mov  %i3, %o3
+; CHECK:   mov  %i2, %o2
+; CHECK:   mov  %i0, %o0
+; CHECK:   call receive_i128
+define i64 @test_i128_args(i64 %a, i128 %b) {
+entry:
+  %0 = call i64 @receive_i128(i64 %a, i128 %b)
+  ret i64 %0
+}
+
 ; CHECK-LABEL: test_call_libfunc:
 ; HARD:   st %f1, [%fp+[[Offset0:[0-9]+]]]
 ; HARD:   fmovs %f3, %f1

>From 05f7e2b53693109818ccf789e4d059f8f3f5a79e Mon Sep 17 00:00:00 2001
From: Koakuma <koac...@protonmail.com>
Date: Thu, 28 Aug 2025 20:06:10 +0700
Subject: [PATCH 2/7] Fix comment and size checks

---
 clang/lib/CodeGen/Targets/Sparc.cpp | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/clang/lib/CodeGen/Targets/Sparc.cpp 
b/clang/lib/CodeGen/Targets/Sparc.cpp
index 300b5fdf35e37..b6c8fdcfe29b6 100644
--- a/clang/lib/CodeGen/Targets/Sparc.cpp
+++ b/clang/lib/CodeGen/Targets/Sparc.cpp
@@ -276,10 +276,10 @@ SparcV9ABIInfo::classifyType(QualType Ty, unsigned 
SizeLimit) const {
   // Try to use the original type for coercion.
   llvm::Type *CoerceTy = CB.isUsableType(StrTy) ? StrTy : CB.getType();
 
-  // We use a pair of i64 for 16-byte aggregate with 8-byte alignment.
-  // For 16-byte aggregates with 16-byte alignment, we use i128.
+  // We use a pair of i64 for 9-16 byte aggregate with 8 byte alignment.
+  // For 9-16 byte aggregates with 16 byte alignment, we use i128.
   llvm::Type *WideTy = llvm::Type::getIntNTy(getVMContext(), 128);
-  bool UseI128 = (Size == 128) && (Alignment == 128);
+  bool UseI128 = (Size > 64) && (Size <= 128) && (Alignment == 128);
 
   if (CB.InReg)
     return ABIArgInfo::getDirectInReg(UseI128 ? WideTy : CoerceTy);

>From ba36452117b8efae842b90a7900a449e96604e47 Mon Sep 17 00:00:00 2001
From: Koakuma <koac...@protonmail.com>
Date: Thu, 4 Sep 2025 08:37:23 +0700
Subject: [PATCH 3/7] Add medium_aligned test

---
 clang/test/CodeGen/sparcv9-abi.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/clang/test/CodeGen/sparcv9-abi.c b/clang/test/CodeGen/sparcv9-abi.c
index 9819d07425274..69c277290b538 100644
--- a/clang/test/CodeGen/sparcv9-abi.c
+++ b/clang/test/CodeGen/sparcv9-abi.c
@@ -89,6 +89,11 @@ struct medium {
   int *c, *d;
 };
 
+struct medium_aligned {
+  _Alignas(16) int *a;
+  int *b, *c, *d;
+};
+
 // CHECK-LABEL: define{{.*}} %struct.medium @f_medium(ptr dead_on_return 
noundef %x)
 struct medium f_medium(struct medium x) {
   x.a += *x.b;
@@ -96,6 +101,13 @@ struct medium f_medium(struct medium x) {
   return x;
 }
 
+// CHECK-LABEL: define{{.*}} %struct.medium_aligned @f_medium_aligned(ptr 
dead_on_return noundef %x)
+struct medium_aligned f_medium_aligned(struct medium_aligned x) {
+  x.a += *x.b;
+  x.b = 0;
+  return x;
+}
+
 // Large structs are also returned indirectly.
 struct large {
   int *a, *b;

>From fcfb1aabf3fc8399eb54c3d04193cbf08ffad66f Mon Sep 17 00:00:00 2001
From: Koakuma <koac...@protonmail.com>
Date: Sun, 14 Sep 2025 23:24:39 +0700
Subject: [PATCH 4/7] New impl and add tests

---
 clang/lib/CodeGen/Targets/Sparc.cpp | 71 +++++++++++++++++++----------
 clang/test/CodeGen/sparcv9-abi.c    | 24 ++++++++--
 2 files changed, 67 insertions(+), 28 deletions(-)

diff --git a/clang/lib/CodeGen/Targets/Sparc.cpp 
b/clang/lib/CodeGen/Targets/Sparc.cpp
index b6c8fdcfe29b6..b4257aec08007 100644
--- a/clang/lib/CodeGen/Targets/Sparc.cpp
+++ b/clang/lib/CodeGen/Targets/Sparc.cpp
@@ -109,7 +109,8 @@ class SparcV9ABIInfo : public ABIInfo {
   SparcV9ABIInfo(CodeGenTypes &CGT) : ABIInfo(CGT) {}
 
 private:
-  ABIArgInfo classifyType(QualType RetTy, unsigned SizeLimit) const;
+  ABIArgInfo classifyType(QualType RetTy, unsigned SizeLimit,
+                          unsigned &RegOffset) const;
   void computeInfo(CGFunctionInfo &FI) const override;
   RValue EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty,
                    AggValueSlot Slot) const override;
@@ -222,73 +223,94 @@ class SparcV9ABIInfo : public ABIInfo {
 };
 } // end anonymous namespace
 
-ABIArgInfo
-SparcV9ABIInfo::classifyType(QualType Ty, unsigned SizeLimit) const {
+ABIArgInfo SparcV9ABIInfo::classifyType(QualType Ty, unsigned SizeLimit,
+                                        unsigned &RegOffset) const {
   if (Ty->isVoidType())
     return ABIArgInfo::getIgnore();
 
-  uint64_t Size = getContext().getTypeSize(Ty);
-  unsigned Alignment = getContext().getTypeAlign(Ty);
+  auto &Context = getContext();
+  auto &VMContext = getVMContext();
+
+  uint64_t Size = Context.getTypeSize(Ty);
+  unsigned Alignment = Context.getTypeAlign(Ty);
+  bool NeedPadding = (Alignment > 64) && (RegOffset % 2 != 0);
 
   // Anything too big to fit in registers is passed with an explicit indirect
   // pointer / sret pointer.
-  if (Size > SizeLimit)
+  if (Size > SizeLimit) {
+    RegOffset += 1;
     return getNaturalAlignIndirect(
         Ty, /*AddrSpace=*/getDataLayout().getAllocaAddrSpace(),
         /*ByVal=*/false);
+  }
 
   // Treat an enum type as its underlying type.
   if (const auto *ED = Ty->getAsEnumDecl())
     Ty = ED->getIntegerType();
 
   // Integer types smaller than a register are extended.
-  if (Size < 64 && Ty->isIntegerType())
+  if (Size < 64 && Ty->isIntegerType()) {
+    RegOffset += 1;
     return ABIArgInfo::getExtend(Ty);
+  }
 
   if (const auto *EIT = Ty->getAs<BitIntType>())
-    if (EIT->getNumBits() < 64)
+    if (EIT->getNumBits() < 64) {
+      RegOffset += 1;
       return ABIArgInfo::getExtend(Ty);
+    }
 
   // Other non-aggregates go in registers.
-  if (!isAggregateTypeForABI(Ty))
+  if (!isAggregateTypeForABI(Ty)) {
+    RegOffset += Size / 64;
     return ABIArgInfo::getDirect();
+  }
 
   // If a C++ object has either a non-trivial copy constructor or a non-trivial
   // destructor, it is passed with an explicit indirect pointer / sret pointer.
-  if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI()))
+  if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI())) {
+    RegOffset += 1;
     return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(),
                                    RAA == CGCXXABI::RAA_DirectInMemory);
+  }
 
   // This is a small aggregate type that should be passed in registers.
   // Build a coercion type from the LLVM struct type.
   llvm::StructType *StrTy = dyn_cast<llvm::StructType>(CGT.ConvertType(Ty));
-  if (!StrTy)
+  if (!StrTy) {
+    RegOffset += Size / 64;
     return ABIArgInfo::getDirect();
+  }
 
-  CoerceBuilder CB(getVMContext(), getDataLayout());
+  CoerceBuilder CB(VMContext, getDataLayout());
   CB.addStruct(0, StrTy);
   // All structs, even empty ones, should take up a register argument slot,
   // so pin the minimum struct size to one bit.
   CB.pad(llvm::alignTo(
       std::max(CB.DL.getTypeSizeInBits(StrTy).getKnownMinValue(), uint64_t(1)),
       64));
+  RegOffset += CB.Size / 64;
+
+  // If we're dealing with overaligned structs we may need to add a padding in
+  // the front, to preserve the correct register-memory mapping.
+  //
+  // See SCD 2.4.1, pages 3P-11 and 3P-12.
+  llvm::Type *Padding =
+      NeedPadding ? llvm::Type::getInt64Ty(VMContext) : nullptr;
+  RegOffset += NeedPadding ? 1 : 0;
 
   // Try to use the original type for coercion.
   llvm::Type *CoerceTy = CB.isUsableType(StrTy) ? StrTy : CB.getType();
 
-  // We use a pair of i64 for 9-16 byte aggregate with 8 byte alignment.
-  // For 9-16 byte aggregates with 16 byte alignment, we use i128.
-  llvm::Type *WideTy = llvm::Type::getIntNTy(getVMContext(), 128);
-  bool UseI128 = (Size > 64) && (Size <= 128) && (Alignment == 128);
-
-  if (CB.InReg)
-    return ABIArgInfo::getDirectInReg(UseI128 ? WideTy : CoerceTy);
-  return ABIArgInfo::getDirect(UseI128 ? WideTy : CoerceTy);
+  ABIArgInfo AAI = ABIArgInfo::getDirect(CoerceTy, 0, Padding);
+  AAI.setInReg(CB.InReg);
+  return AAI;
 }
 
 RValue SparcV9ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
                                  QualType Ty, AggValueSlot Slot) const {
-  ABIArgInfo AI = classifyType(Ty, 16 * 8);
+  unsigned ArgOffset = 0;
+  ABIArgInfo AI = classifyType(Ty, 16 * 8, ArgOffset);
   llvm::Type *ArgTy = CGT.ConvertType(Ty);
   if (AI.canHaveCoerceToType() && !AI.getCoerceToType())
     AI.setCoerceToType(ArgTy);
@@ -346,9 +368,12 @@ RValue SparcV9ABIInfo::EmitVAArg(CodeGenFunction &CGF, 
Address VAListAddr,
 }
 
 void SparcV9ABIInfo::computeInfo(CGFunctionInfo &FI) const {
-  FI.getReturnInfo() = classifyType(FI.getReturnType(), 32 * 8);
+  unsigned RetOffset = 0;
+  FI.getReturnInfo() = classifyType(FI.getReturnType(), 32 * 8, RetOffset);
+
+  unsigned ArgOffset = 0;
   for (auto &I : FI.arguments())
-    I.info = classifyType(I.type, 16 * 8);
+    I.info = classifyType(I.type, 16 * 8, ArgOffset);
 }
 
 namespace {
diff --git a/clang/test/CodeGen/sparcv9-abi.c b/clang/test/CodeGen/sparcv9-abi.c
index 69c277290b538..dc8d9ec50f76b 100644
--- a/clang/test/CodeGen/sparcv9-abi.c
+++ b/clang/test/CodeGen/sparcv9-abi.c
@@ -25,8 +25,11 @@ long double f_ld(long double x) { return x; }
 struct empty {};
 struct emptyarr { struct empty a[10]; };
 
-// 16-byte structs with 16-byte alignment gets passed as if i128.
-struct align16 { _Alignas(16) int x; };
+// In 16-byte structs, 16-byte aligned members are expanded
+// to their corresponding i128/f128 types.
+struct align16_int { _Alignas(16) int x; };
+struct align16_mixed { _Alignas(16) int x; double y; };
+struct align16_longdouble { long double x; };
 
 // CHECK-LABEL: define{{.*}} i64 @f_empty(i64 %x.coerce)
 struct empty f_empty(struct empty x) { return x; }
@@ -34,12 +37,23 @@ struct empty f_empty(struct empty x) { return x; }
 // CHECK-LABEL: define{{.*}} i64 @f_emptyarr(i64 %x.coerce)
 struct empty f_emptyarr(struct emptyarr x) { return x.a[0]; }
 
-// CHECK-LABEL: define{{.*}} void @f_aligncaller(i128 %a.coerce)
-void f_aligncallee(int pad, struct align16 a);
-void f_aligncaller(struct align16 a) {
+// CHECK-LABEL: define{{.*}} void @f_aligncaller(i64 %a.coerce0, i64 
%a.coerce1)
+// CHECK-LABEL: declare{{.*}} void @f_aligncallee(i32 noundef signext, i64, 
i64, i64)
+void f_aligncallee(int pad, struct align16_int a);
+void f_aligncaller(struct align16_int a) {
     f_aligncallee(0, a);
 }
 
+// CHECK-LABEL: define{{.*}} double @f_mixed_aligned(i64 noundef %a, i64 %0, 
i64 %b.coerce0, double %b.coerce1)
+double f_mixed_aligned(long a, struct align16_mixed b) {
+       return b.y;
+}
+
+// CHECK-LABEL: define{{.*}} fp128 @f_longdouble(i64 noundef %a, i64 %0, fp128 
%b.coerce)
+long double f_longdouble(long a, struct align16_longdouble b) {
+       return b.x;
+}
+
 // CHECK-LABEL: define{{.*}} i64 @f_emptyvar(i32 noundef zeroext %count, ...)
 long f_emptyvar(unsigned count, ...) {
     long ret;

>From fffdefb6eee46cc22b463cbf60fb25812e94a10c Mon Sep 17 00:00:00 2001
From: Koakuma <koac...@protonmail.com>
Date: Wed, 17 Sep 2025 13:04:04 +0700
Subject: [PATCH 5/7] Link RetOffset with ArgOffset in case of indirect returns

---
 clang/lib/CodeGen/Targets/Sparc.cpp | 7 +++++--
 clang/test/CodeGen/sparcv9-abi.c    | 9 +++++++++
 2 files changed, 14 insertions(+), 2 deletions(-)

diff --git a/clang/lib/CodeGen/Targets/Sparc.cpp 
b/clang/lib/CodeGen/Targets/Sparc.cpp
index b4257aec08007..a4a409fee5acf 100644
--- a/clang/lib/CodeGen/Targets/Sparc.cpp
+++ b/clang/lib/CodeGen/Targets/Sparc.cpp
@@ -8,6 +8,7 @@
 
 #include "ABIInfoImpl.h"
 #include "TargetInfo.h"
+#include "clang/CodeGen/CGFunctionInfo.h"
 
 using namespace clang;
 using namespace clang::CodeGen;
@@ -369,9 +370,11 @@ RValue SparcV9ABIInfo::EmitVAArg(CodeGenFunction &CGF, 
Address VAListAddr,
 
 void SparcV9ABIInfo::computeInfo(CGFunctionInfo &FI) const {
   unsigned RetOffset = 0;
-  FI.getReturnInfo() = classifyType(FI.getReturnType(), 32 * 8, RetOffset);
+  ABIArgInfo RetType = classifyType(FI.getReturnType(), 32 * 8, RetOffset);
+  FI.getReturnInfo() = RetType;
 
-  unsigned ArgOffset = 0;
+  // Indirect returns will have its pointer passed as an argument.
+  unsigned ArgOffset = RetType.isIndirect() ? RetOffset : 0;
   for (auto &I : FI.arguments())
     I.info = classifyType(I.type, 16 * 8, ArgOffset);
 }
diff --git a/clang/test/CodeGen/sparcv9-abi.c b/clang/test/CodeGen/sparcv9-abi.c
index dc8d9ec50f76b..42cc03eb9fdc6 100644
--- a/clang/test/CodeGen/sparcv9-abi.c
+++ b/clang/test/CodeGen/sparcv9-abi.c
@@ -136,6 +136,15 @@ struct large f_large(struct large x) {
   return x;
 }
 
+// Large returns are converted into a pointer argument.
+// Such conversion should preserve the alignment of overaligned arguments.
+// define{{.*}} void @f_largereturn_aligned(ptr dead_on_unwind noalias 
writable sret(%struct.large) align 8 %agg.result, i64 %0, i64 %x.coerce0, i64 
%x.coerce1)
+struct large f_largereturn_aligned(struct align16_int x) {
+  struct large ret;
+  ret.x = x.x;
+  return ret;
+}
+
 // A 64-bit struct fits in a register.
 struct reg {
   int a, b;

>From 60744a6f0b6ebf2b0a096a7cbeafe7e1c8d93b6c Mon Sep 17 00:00:00 2001
From: Koakuma <koac...@protonmail.com>
Date: Wed, 17 Sep 2025 13:23:45 +0700
Subject: [PATCH 6/7] Remove unused includes

---
 clang/lib/CodeGen/Targets/Sparc.cpp | 1 -
 1 file changed, 1 deletion(-)

diff --git a/clang/lib/CodeGen/Targets/Sparc.cpp 
b/clang/lib/CodeGen/Targets/Sparc.cpp
index a4a409fee5acf..9af6cbca16e11 100644
--- a/clang/lib/CodeGen/Targets/Sparc.cpp
+++ b/clang/lib/CodeGen/Targets/Sparc.cpp
@@ -8,7 +8,6 @@
 
 #include "ABIInfoImpl.h"
 #include "TargetInfo.h"
-#include "clang/CodeGen/CGFunctionInfo.h"
 
 using namespace clang;
 using namespace clang::CodeGen;

>From 364730fb25dfe91ed71b23f18a9a2cda43718bae Mon Sep 17 00:00:00 2001
From: Koakuma <koac...@protonmail.com>
Date: Sat, 20 Sep 2025 10:21:09 +0700
Subject: [PATCH 7/7] Use emitVoidPtrVAArg to implement va_arg

---
 clang/lib/CodeGen/Targets/Sparc.cpp | 62 +++++------------------------
 1 file changed, 9 insertions(+), 53 deletions(-)

diff --git a/clang/lib/CodeGen/Targets/Sparc.cpp 
b/clang/lib/CodeGen/Targets/Sparc.cpp
index 9af6cbca16e11..38dbebdec2429 100644
--- a/clang/lib/CodeGen/Targets/Sparc.cpp
+++ b/clang/lib/CodeGen/Targets/Sparc.cpp
@@ -8,6 +8,7 @@
 
 #include "ABIInfoImpl.h"
 #include "TargetInfo.h"
+#include <algorithm>
 
 using namespace clang;
 using namespace clang::CodeGen;
@@ -309,62 +310,17 @@ ABIArgInfo SparcV9ABIInfo::classifyType(QualType Ty, 
unsigned SizeLimit,
 
 RValue SparcV9ABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
                                  QualType Ty, AggValueSlot Slot) const {
-  unsigned ArgOffset = 0;
-  ABIArgInfo AI = classifyType(Ty, 16 * 8, ArgOffset);
-  llvm::Type *ArgTy = CGT.ConvertType(Ty);
-  if (AI.canHaveCoerceToType() && !AI.getCoerceToType())
-    AI.setCoerceToType(ArgTy);
-
   CharUnits SlotSize = CharUnits::fromQuantity(8);
+  auto TInfo = getContext().getTypeInfoInChars(Ty);
 
-  CGBuilderTy &Builder = CGF.Builder;
-  Address Addr = Address(Builder.CreateLoad(VAListAddr, "ap.cur"),
-                         getVAListElementType(CGF), SlotSize);
-  llvm::Type *ArgPtrTy = CGF.UnqualPtrTy;
-
-  auto TypeInfo = getContext().getTypeInfoInChars(Ty);
-
-  Address ArgAddr = Address::invalid();
-  CharUnits Stride;
-  switch (AI.getKind()) {
-  case ABIArgInfo::Expand:
-  case ABIArgInfo::CoerceAndExpand:
-  case ABIArgInfo::InAlloca:
-  case ABIArgInfo::TargetSpecific:
-    llvm_unreachable("Unsupported ABI kind for va_arg");
-
-  case ABIArgInfo::Extend: {
-    Stride = SlotSize;
-    CharUnits Offset = SlotSize - TypeInfo.Width;
-    ArgAddr = Builder.CreateConstInBoundsByteGEP(Addr, Offset, "extend");
-    break;
-  }
-
-  case ABIArgInfo::Direct: {
-    auto AllocSize = getDataLayout().getTypeAllocSize(AI.getCoerceToType());
-    Stride = CharUnits::fromQuantity(AllocSize).alignTo(SlotSize);
-    ArgAddr = Addr;
-    break;
-  }
-
-  case ABIArgInfo::Indirect:
-  case ABIArgInfo::IndirectAliased:
-    Stride = SlotSize;
-    ArgAddr = Addr.withElementType(ArgPtrTy);
-    ArgAddr = Address(Builder.CreateLoad(ArgAddr, "indirect.arg"), ArgTy,
-                      TypeInfo.Align);
-    break;
-
-  case ABIArgInfo::Ignore:
-    return Slot.asRValue();
-  }
-
-  // Update VAList.
-  Address NextPtr = Builder.CreateConstInBoundsByteGEP(Addr, Stride, 
"ap.next");
-  Builder.CreateStore(NextPtr.emitRawPointer(CGF), VAListAddr);
+  // Zero-sized types have a width of one byte for parameter passing purposes.
+  TInfo.Width = std::max(TInfo.Width, CharUnits::fromQuantity(1));
 
-  return CGF.EmitLoadOfAnyValue(
-      CGF.MakeAddrLValue(ArgAddr.withElementType(ArgTy), Ty), Slot);
+  // Arguments bigger than 2*SlotSize bytes are passed indirectly.
+  return emitVoidPtrVAArg(CGF, VAListAddr, Ty,
+                          /*IsIndirect=*/TInfo.Width > 2 * SlotSize, TInfo,
+                          SlotSize,
+                          /*AllowHigherAlign=*/true, Slot);
 }
 
 void SparcV9ABIInfo::computeInfo(CGFunctionInfo &FI) const {

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to