[clang] [X86_64] Fix empty field error in vaarg of C++. (PR #90389)

2024-04-30 Thread Longsheng Mou via cfe-commits

https://github.com/CoTinker updated 
https://github.com/llvm/llvm-project/pull/90389

>From 1ce3de25b4ad1e6254eec5e84bf29816aafca6fb Mon Sep 17 00:00:00 2001
From: Longsheng Mou 
Date: Sun, 28 Apr 2024 17:14:29 +0800
Subject: [PATCH] [X86_64] Fix empty field error in vaarg of C++.

Such struct types:
```
struct {
  struct{} a;
  long long b;
};

stuct {
  struct{} a;
  double b;
};
```
For such structures, Lo is NoClass and Hi is Integer/SSE. And when
this structure argument is passed, the high part is passed at
offset 8 in memory. So we should do special handling for these types
in EmitVAArg.
---
 clang/lib/CodeGen/Targets/X86.cpp  | 30 
 clang/test/CodeGenCXX/x86_64-vaarg.cpp | 64 +++---
 2 files changed, 80 insertions(+), 14 deletions(-)

diff --git a/clang/lib/CodeGen/Targets/X86.cpp 
b/clang/lib/CodeGen/Targets/X86.cpp
index 94cf0d86f9bed7..c6a1f5272458f4 100644
--- a/clang/lib/CodeGen/Targets/X86.cpp
+++ b/clang/lib/CodeGen/Targets/X86.cpp
@@ -3122,9 +3122,25 @@ Address X86_64ABIInfo::EmitVAArg(CodeGenFunction , 
Address VAListAddr,
 CGF.Builder.CreateStore(V, CGF.Builder.CreateStructGEP(Tmp, 1));
 
 RegAddr = Tmp.withElementType(LTy);
-  } else if (neededInt) {
-RegAddr = Address(CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, 
gp_offset),
-  LTy, CharUnits::fromQuantity(8));
+  } else if (neededInt || neededSSE == 1) {
+llvm::Value *Offset = neededInt ? gp_offset : fp_offset;
+uint64_t Alignment = neededInt ? 8 : 16;
+Address Tmp = Address::invalid();
+if (AI.isDirect() && AI.getDirectOffset() == 8) {
+  Tmp = CGF.CreateMemTemp(Ty);
+  llvm::StructType *ST = cast(LTy);
+  Tmp = Tmp.withElementType(ST);
+  llvm::Type *TyHi = AI.getCoerceToType();
+  llvm::Value *Addr =
+  CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, Offset);
+  llvm::Value *V = CGF.Builder.CreateAlignedLoad(
+  TyHi, Addr,
+  CharUnits::fromQuantity(getDataLayout().getABITypeAlign(TyHi)));
+  CGF.Builder.CreateStore(V, CGF.Builder.CreateStructGEP(Tmp, 1));
+  RegAddr = Tmp.withElementType(LTy);
+} else
+  RegAddr = Address(CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, Offset),
+LTy, CharUnits::fromQuantity(Alignment));
 
 // Copy to a temporary if necessary to ensure the appropriate alignment.
 auto TInfo = getContext().getTypeInfoInChars(Ty);
@@ -3133,15 +3149,13 @@ Address X86_64ABIInfo::EmitVAArg(CodeGenFunction , 
Address VAListAddr,
 
 // Copy into a temporary if the type is more aligned than the
 // register save area.
-if (TyAlign.getQuantity() > 8) {
-  Address Tmp = CGF.CreateMemTemp(Ty);
+if (neededInt && TyAlign.getQuantity() > 8) {
+  if (!Tmp.isValid())
+Tmp = CGF.CreateMemTemp(Ty);
   CGF.Builder.CreateMemCpy(Tmp, RegAddr, TySize, false);
   RegAddr = Tmp;
 }
 
-  } else if (neededSSE == 1) {
-RegAddr = Address(CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, 
fp_offset),
-  LTy, CharUnits::fromQuantity(16));
   } else {
 assert(neededSSE == 2 && "Invalid number of needed registers!");
 // SSE registers are spaced 16 bytes apart in the register save
diff --git a/clang/test/CodeGenCXX/x86_64-vaarg.cpp 
b/clang/test/CodeGenCXX/x86_64-vaarg.cpp
index 985a0cc41a1410..dc6d9f070cf51f 100644
--- a/clang/test/CodeGenCXX/x86_64-vaarg.cpp
+++ b/clang/test/CodeGenCXX/x86_64-vaarg.cpp
@@ -32,6 +32,7 @@ typedef struct {
 // CHECK-NEXT:[[RETVAL:%.*]] = alloca [[STRUCT_S1:%.*]], align 8
 // CHECK-NEXT:[[Z_ADDR:%.*]] = alloca i32, align 4
 // CHECK-NEXT:[[LIST:%.*]] = alloca [1 x %struct.__va_list_tag], align 16
+// CHECK-NEXT:[[TMP:%.*]] = alloca [[STRUCT_S1]], align 8
 // CHECK-NEXT:store i32 [[Z:%.*]], ptr [[Z_ADDR]], align 4
 // CHECK-NEXT:[[ARRAYDECAY:%.*]] = getelementptr inbounds [1 x 
%struct.__va_list_tag], ptr [[LIST]], i64 0, i64 0
 // CHECK-NEXT:call void @llvm.va_start.p0(ptr [[ARRAYDECAY]])
@@ -44,8 +45,11 @@ typedef struct {
 // CHECK-NEXT:[[TMP0:%.*]] = getelementptr inbounds 
[[STRUCT___VA_LIST_TAG]], ptr [[ARRAYDECAY1]], i32 0, i32 3
 // CHECK-NEXT:[[REG_SAVE_AREA:%.*]] = load ptr, ptr [[TMP0]], align 16
 // CHECK-NEXT:[[TMP1:%.*]] = getelementptr i8, ptr [[REG_SAVE_AREA]], i32 
[[FP_OFFSET]]
-// CHECK-NEXT:[[TMP2:%.*]] = add i32 [[FP_OFFSET]], 16
-// CHECK-NEXT:store i32 [[TMP2]], ptr [[FP_OFFSET_P]], align 4
+// CHECK-NEXT:[[TMP2:%.*]] = load double, ptr [[TMP1]], align 8
+// CHECK-NEXT:[[TMP3:%.*]] = getelementptr inbounds [[STRUCT_S1]], ptr 
[[TMP]], i32 0, i32 1
+// CHECK-NEXT:store double [[TMP2]], ptr [[TMP3]], align 8
+// CHECK-NEXT:[[TMP4:%.*]] = add i32 [[FP_OFFSET]], 16
+// CHECK-NEXT:store i32 [[TMP4]], ptr [[FP_OFFSET_P]], align 4
 // CHECK-NEXT:br label [[VAARG_END:%.*]]
 // CHECK:   vaarg.in_mem:
 // CHECK-NEXT:[[OVERFLOW_ARG_AREA_P:%.*]] = getelementptr inbounds 

[clang] [X86_64] Fix empty field error in vaarg of C++. (PR #90389)

2024-04-29 Thread Longsheng Mou via cfe-commits

https://github.com/CoTinker updated 
https://github.com/llvm/llvm-project/pull/90389

>From db18c52f8fd5f397324505bcb2e07343794e5dce Mon Sep 17 00:00:00 2001
From: Longsheng Mou 
Date: Sun, 28 Apr 2024 17:14:29 +0800
Subject: [PATCH] [X86_64] Fix empty field error in vaarg of C++.

Such struct types:
```
struct {
  struct{} a;
  long long b;
};

stuct {
  struct{} a;
  double b;
};
```
For such structures, Lo is NoClass and Hi is Integer/SSE. And when
this structure argument is passed, the high part is passed at
offset 8 in memory. So we should do special handling for these types
in EmitVAArg.
---
 clang/lib/CodeGen/Targets/X86.cpp  | 27 +++
 clang/test/CodeGenCXX/x86_64-vaarg.cpp | 64 +++---
 2 files changed, 77 insertions(+), 14 deletions(-)

diff --git a/clang/lib/CodeGen/Targets/X86.cpp 
b/clang/lib/CodeGen/Targets/X86.cpp
index 94cf0d86f9bed7..eff54d12ce5496 100644
--- a/clang/lib/CodeGen/Targets/X86.cpp
+++ b/clang/lib/CodeGen/Targets/X86.cpp
@@ -3122,9 +3122,24 @@ Address X86_64ABIInfo::EmitVAArg(CodeGenFunction , 
Address VAListAddr,
 CGF.Builder.CreateStore(V, CGF.Builder.CreateStructGEP(Tmp, 1));
 
 RegAddr = Tmp.withElementType(LTy);
-  } else if (neededInt) {
-RegAddr = Address(CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, 
gp_offset),
-  LTy, CharUnits::fromQuantity(8));
+  } else if (neededInt || neededSSE == 1) {
+llvm::Value *Offset = neededInt ? gp_offset : fp_offset;
+uint64_t Alignment = neededInt ? 8 : 16;
+Address Tmp = CGF.CreateMemTemp(Ty);
+if (AI.isDirect() && AI.getDirectOffset() == 8) {
+  llvm::StructType *ST = cast(LTy);
+  Tmp = Tmp.withElementType(ST);
+  llvm::Type *TyHi = AI.getCoerceToType();
+  llvm::Value *Addr =
+  CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, Offset);
+  llvm::Value *V = CGF.Builder.CreateAlignedLoad(
+  TyHi, Addr,
+  CharUnits::fromQuantity(getDataLayout().getABITypeAlign(TyHi)));
+  CGF.Builder.CreateStore(V, CGF.Builder.CreateStructGEP(Tmp, 1));
+  RegAddr = Tmp.withElementType(LTy);
+} else
+  RegAddr = Address(CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, Offset),
+LTy, CharUnits::fromQuantity(Alignment));
 
 // Copy to a temporary if necessary to ensure the appropriate alignment.
 auto TInfo = getContext().getTypeInfoInChars(Ty);
@@ -3133,15 +3148,11 @@ Address X86_64ABIInfo::EmitVAArg(CodeGenFunction , 
Address VAListAddr,
 
 // Copy into a temporary if the type is more aligned than the
 // register save area.
-if (TyAlign.getQuantity() > 8) {
-  Address Tmp = CGF.CreateMemTemp(Ty);
+if (neededInt && TyAlign.getQuantity() > 8) {
   CGF.Builder.CreateMemCpy(Tmp, RegAddr, TySize, false);
   RegAddr = Tmp;
 }
 
-  } else if (neededSSE == 1) {
-RegAddr = Address(CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, 
fp_offset),
-  LTy, CharUnits::fromQuantity(16));
   } else {
 assert(neededSSE == 2 && "Invalid number of needed registers!");
 // SSE registers are spaced 16 bytes apart in the register save
diff --git a/clang/test/CodeGenCXX/x86_64-vaarg.cpp 
b/clang/test/CodeGenCXX/x86_64-vaarg.cpp
index 985a0cc41a1410..dc6d9f070cf51f 100644
--- a/clang/test/CodeGenCXX/x86_64-vaarg.cpp
+++ b/clang/test/CodeGenCXX/x86_64-vaarg.cpp
@@ -32,6 +32,7 @@ typedef struct {
 // CHECK-NEXT:[[RETVAL:%.*]] = alloca [[STRUCT_S1:%.*]], align 8
 // CHECK-NEXT:[[Z_ADDR:%.*]] = alloca i32, align 4
 // CHECK-NEXT:[[LIST:%.*]] = alloca [1 x %struct.__va_list_tag], align 16
+// CHECK-NEXT:[[TMP:%.*]] = alloca [[STRUCT_S1]], align 8
 // CHECK-NEXT:store i32 [[Z:%.*]], ptr [[Z_ADDR]], align 4
 // CHECK-NEXT:[[ARRAYDECAY:%.*]] = getelementptr inbounds [1 x 
%struct.__va_list_tag], ptr [[LIST]], i64 0, i64 0
 // CHECK-NEXT:call void @llvm.va_start.p0(ptr [[ARRAYDECAY]])
@@ -44,8 +45,11 @@ typedef struct {
 // CHECK-NEXT:[[TMP0:%.*]] = getelementptr inbounds 
[[STRUCT___VA_LIST_TAG]], ptr [[ARRAYDECAY1]], i32 0, i32 3
 // CHECK-NEXT:[[REG_SAVE_AREA:%.*]] = load ptr, ptr [[TMP0]], align 16
 // CHECK-NEXT:[[TMP1:%.*]] = getelementptr i8, ptr [[REG_SAVE_AREA]], i32 
[[FP_OFFSET]]
-// CHECK-NEXT:[[TMP2:%.*]] = add i32 [[FP_OFFSET]], 16
-// CHECK-NEXT:store i32 [[TMP2]], ptr [[FP_OFFSET_P]], align 4
+// CHECK-NEXT:[[TMP2:%.*]] = load double, ptr [[TMP1]], align 8
+// CHECK-NEXT:[[TMP3:%.*]] = getelementptr inbounds [[STRUCT_S1]], ptr 
[[TMP]], i32 0, i32 1
+// CHECK-NEXT:store double [[TMP2]], ptr [[TMP3]], align 8
+// CHECK-NEXT:[[TMP4:%.*]] = add i32 [[FP_OFFSET]], 16
+// CHECK-NEXT:store i32 [[TMP4]], ptr [[FP_OFFSET_P]], align 4
 // CHECK-NEXT:br label [[VAARG_END:%.*]]
 // CHECK:   vaarg.in_mem:
 // CHECK-NEXT:[[OVERFLOW_ARG_AREA_P:%.*]] = getelementptr inbounds 
[[STRUCT___VA_LIST_TAG]], ptr [[ARRAYDECAY1]], i32 0, i32 2
@@ -54,14 +58,62 @@ typedef struct {
 // 

[clang] [X86_64] Fix empty field error in vaarg of C++. (PR #90389)

2024-04-28 Thread Longsheng Mou via cfe-commits

https://github.com/CoTinker updated 
https://github.com/llvm/llvm-project/pull/90389

>From 3c1aac31d879ebf172d2b9b6c9a351d967f72606 Mon Sep 17 00:00:00 2001
From: Longsheng Mou 
Date: Sun, 28 Apr 2024 17:14:29 +0800
Subject: [PATCH] [X86_64] Fix empty field error in vaarg of C++.

Such struct types:
```
struct {
  struct{} a;
  long long b;
};

stuct {
  struct{} a;
  double b;
};
```
For such structures, Lo is NoClass and Hi is Integer/SSE. And when
this structure argument is passed, the high part is passed at
offset 8 in memory. So we should do special handling for these types
in EmitVAArg.
---
 clang/lib/CodeGen/Targets/X86.cpp  | 36 +--
 clang/test/CodeGenCXX/x86_64-vaarg.cpp | 64 +++---
 2 files changed, 90 insertions(+), 10 deletions(-)

diff --git a/clang/lib/CodeGen/Targets/X86.cpp 
b/clang/lib/CodeGen/Targets/X86.cpp
index 94cf0d86f9bed7..525e37d5097f58 100644
--- a/clang/lib/CodeGen/Targets/X86.cpp
+++ b/clang/lib/CodeGen/Targets/X86.cpp
@@ -3123,8 +3123,22 @@ Address X86_64ABIInfo::EmitVAArg(CodeGenFunction , 
Address VAListAddr,
 
 RegAddr = Tmp.withElementType(LTy);
   } else if (neededInt) {
-RegAddr = Address(CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, 
gp_offset),
-  LTy, CharUnits::fromQuantity(8));
+if (AI.isDirect() && AI.getDirectOffset() == 8) {
+  Address Tmp = CGF.CreateMemTemp(Ty);
+  llvm::StructType *ST = cast(LTy);
+  Tmp = Tmp.withElementType(ST);
+  llvm::Type *TyHi = ST->getElementType(1);
+  llvm::Value *GPAddr =
+  CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, gp_offset);
+  llvm::Value *V = CGF.Builder.CreateAlignedLoad(
+  TyHi, GPAddr,
+  CharUnits::fromQuantity(getDataLayout().getABITypeAlign(TyHi)));
+  CGF.Builder.CreateStore(V, CGF.Builder.CreateStructGEP(Tmp, 1));
+  RegAddr = Tmp.withElementType(LTy);
+} else
+  RegAddr =
+  Address(CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, gp_offset),
+  LTy, CharUnits::fromQuantity(8));
 
 // Copy to a temporary if necessary to ensure the appropriate alignment.
 auto TInfo = getContext().getTypeInfoInChars(Ty);
@@ -3140,8 +3154,22 @@ Address X86_64ABIInfo::EmitVAArg(CodeGenFunction , 
Address VAListAddr,
 }
 
   } else if (neededSSE == 1) {
-RegAddr = Address(CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, 
fp_offset),
-  LTy, CharUnits::fromQuantity(16));
+if (AI.isDirect() && AI.getDirectOffset() == 8) {
+  Address Tmp = CGF.CreateMemTemp(Ty);
+  llvm::StructType *ST = cast(LTy);
+  Tmp = Tmp.withElementType(ST);
+  llvm::Type *TyHi = ST->getElementType(1);
+  llvm::Value *FPAddr =
+  CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, fp_offset);
+  llvm::Value *V = CGF.Builder.CreateAlignedLoad(
+  TyHi, FPAddr,
+  CharUnits::fromQuantity(getDataLayout().getABITypeAlign(TyHi)));
+  CGF.Builder.CreateStore(V, CGF.Builder.CreateStructGEP(Tmp, 1));
+  RegAddr = Tmp.withElementType(LTy);
+} else
+  RegAddr =
+  Address(CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, fp_offset),
+  LTy, CharUnits::fromQuantity(16));
   } else {
 assert(neededSSE == 2 && "Invalid number of needed registers!");
 // SSE registers are spaced 16 bytes apart in the register save
diff --git a/clang/test/CodeGenCXX/x86_64-vaarg.cpp 
b/clang/test/CodeGenCXX/x86_64-vaarg.cpp
index 985a0cc41a1410..dc6d9f070cf51f 100644
--- a/clang/test/CodeGenCXX/x86_64-vaarg.cpp
+++ b/clang/test/CodeGenCXX/x86_64-vaarg.cpp
@@ -32,6 +32,7 @@ typedef struct {
 // CHECK-NEXT:[[RETVAL:%.*]] = alloca [[STRUCT_S1:%.*]], align 8
 // CHECK-NEXT:[[Z_ADDR:%.*]] = alloca i32, align 4
 // CHECK-NEXT:[[LIST:%.*]] = alloca [1 x %struct.__va_list_tag], align 16
+// CHECK-NEXT:[[TMP:%.*]] = alloca [[STRUCT_S1]], align 8
 // CHECK-NEXT:store i32 [[Z:%.*]], ptr [[Z_ADDR]], align 4
 // CHECK-NEXT:[[ARRAYDECAY:%.*]] = getelementptr inbounds [1 x 
%struct.__va_list_tag], ptr [[LIST]], i64 0, i64 0
 // CHECK-NEXT:call void @llvm.va_start.p0(ptr [[ARRAYDECAY]])
@@ -44,8 +45,11 @@ typedef struct {
 // CHECK-NEXT:[[TMP0:%.*]] = getelementptr inbounds 
[[STRUCT___VA_LIST_TAG]], ptr [[ARRAYDECAY1]], i32 0, i32 3
 // CHECK-NEXT:[[REG_SAVE_AREA:%.*]] = load ptr, ptr [[TMP0]], align 16
 // CHECK-NEXT:[[TMP1:%.*]] = getelementptr i8, ptr [[REG_SAVE_AREA]], i32 
[[FP_OFFSET]]
-// CHECK-NEXT:[[TMP2:%.*]] = add i32 [[FP_OFFSET]], 16
-// CHECK-NEXT:store i32 [[TMP2]], ptr [[FP_OFFSET_P]], align 4
+// CHECK-NEXT:[[TMP2:%.*]] = load double, ptr [[TMP1]], align 8
+// CHECK-NEXT:[[TMP3:%.*]] = getelementptr inbounds [[STRUCT_S1]], ptr 
[[TMP]], i32 0, i32 1
+// CHECK-NEXT:store double [[TMP2]], ptr [[TMP3]], align 8
+// CHECK-NEXT:[[TMP4:%.*]] = add i32 [[FP_OFFSET]], 16
+// CHECK-NEXT:store i32 [[TMP4]], ptr [[FP_OFFSET_P]], align 4
 // CHECK-NEXT:br 

[clang] [X86_64] Fix empty field error in vaarg of C++. (PR #90389)

2024-04-28 Thread Longsheng Mou via cfe-commits

https://github.com/CoTinker created 
https://github.com/llvm/llvm-project/pull/90389

Such struct types:
```
struct {
  struct{} a;
  long long b;
};

stuct {
  struct{} a;
  double b;
};
```
For such structures, Lo is NoClass and Hi is Integer/SSE. And when this 
structure argument is passed, the high part is passed at offset 8 in memory. So 
we should do special handling for these types in EmitVAArg. Fix #79790 and 
#86371.

>From 59439be8b4111a0295d42305475a0ac7980b44e7 Mon Sep 17 00:00:00 2001
From: Longsheng Mou 
Date: Sun, 28 Apr 2024 17:14:29 +0800
Subject: [PATCH] [X86_64] Fix empty field error in vaarg of C++.

Such struct types:
```
struct {
  struct{} a;
  long long b;
};

stuct {
  struct{} a;
  double b;
};
```
For such structures, Lo is NoClass and Hi is Integer/SSE. And when
this structure argument is passed, the high part is passed at
offset 8 in memory. So we should do special handling for these types
in EmitVAArg.
---
 clang/lib/CodeGen/Targets/X86.cpp  | 36 +--
 clang/test/CodeGenCXX/x86_64-vaarg.cpp | 64 +++---
 2 files changed, 90 insertions(+), 10 deletions(-)

diff --git a/clang/lib/CodeGen/Targets/X86.cpp 
b/clang/lib/CodeGen/Targets/X86.cpp
index 94cf0d86f9bed7..525e37d5097f58 100644
--- a/clang/lib/CodeGen/Targets/X86.cpp
+++ b/clang/lib/CodeGen/Targets/X86.cpp
@@ -3123,8 +3123,22 @@ Address X86_64ABIInfo::EmitVAArg(CodeGenFunction , 
Address VAListAddr,
 
 RegAddr = Tmp.withElementType(LTy);
   } else if (neededInt) {
-RegAddr = Address(CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, 
gp_offset),
-  LTy, CharUnits::fromQuantity(8));
+if (AI.isDirect() && AI.getDirectOffset() == 8) {
+  Address Tmp = CGF.CreateMemTemp(Ty);
+  llvm::StructType *ST = cast(LTy);
+  Tmp = Tmp.withElementType(ST);
+  llvm::Type *TyHi = ST->getElementType(1);
+  llvm::Value *GPAddr =
+  CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, gp_offset);
+  llvm::Value *V = CGF.Builder.CreateAlignedLoad(
+  TyHi, GPAddr,
+  CharUnits::fromQuantity(getDataLayout().getABITypeAlign(TyHi)));
+  CGF.Builder.CreateStore(V, CGF.Builder.CreateStructGEP(Tmp, 1));
+  RegAddr = Tmp.withElementType(LTy);
+} else
+  RegAddr =
+  Address(CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, gp_offset),
+  LTy, CharUnits::fromQuantity(8));
 
 // Copy to a temporary if necessary to ensure the appropriate alignment.
 auto TInfo = getContext().getTypeInfoInChars(Ty);
@@ -3140,8 +3154,22 @@ Address X86_64ABIInfo::EmitVAArg(CodeGenFunction , 
Address VAListAddr,
 }
 
   } else if (neededSSE == 1) {
-RegAddr = Address(CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, 
fp_offset),
-  LTy, CharUnits::fromQuantity(16));
+if (AI.isDirect() && AI.getDirectOffset() == 8) {
+  Address Tmp = CGF.CreateMemTemp(Ty);
+  llvm::StructType *ST = cast(LTy);
+  Tmp = Tmp.withElementType(ST);
+  llvm::Type *TyHi = ST->getElementType(1);
+  llvm::Value *FPAddr =
+  CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, fp_offset);
+  llvm::Value *V = CGF.Builder.CreateAlignedLoad(
+  TyHi, FPAddr,
+  CharUnits::fromQuantity(getDataLayout().getABITypeAlign(TyHi)));
+  CGF.Builder.CreateStore(V, CGF.Builder.CreateStructGEP(Tmp, 1));
+  RegAddr = Tmp.withElementType(LTy);
+} else
+  RegAddr =
+  Address(CGF.Builder.CreateGEP(CGF.Int8Ty, RegSaveArea, fp_offset),
+  LTy, CharUnits::fromQuantity(16));
   } else {
 assert(neededSSE == 2 && "Invalid number of needed registers!");
 // SSE registers are spaced 16 bytes apart in the register save
diff --git a/clang/test/CodeGenCXX/x86_64-vaarg.cpp 
b/clang/test/CodeGenCXX/x86_64-vaarg.cpp
index 985a0cc41a1410..dc6d9f070cf51f 100644
--- a/clang/test/CodeGenCXX/x86_64-vaarg.cpp
+++ b/clang/test/CodeGenCXX/x86_64-vaarg.cpp
@@ -32,6 +32,7 @@ typedef struct {
 // CHECK-NEXT:[[RETVAL:%.*]] = alloca [[STRUCT_S1:%.*]], align 8
 // CHECK-NEXT:[[Z_ADDR:%.*]] = alloca i32, align 4
 // CHECK-NEXT:[[LIST:%.*]] = alloca [1 x %struct.__va_list_tag], align 16
+// CHECK-NEXT:[[TMP:%.*]] = alloca [[STRUCT_S1]], align 8
 // CHECK-NEXT:store i32 [[Z:%.*]], ptr [[Z_ADDR]], align 4
 // CHECK-NEXT:[[ARRAYDECAY:%.*]] = getelementptr inbounds [1 x 
%struct.__va_list_tag], ptr [[LIST]], i64 0, i64 0
 // CHECK-NEXT:call void @llvm.va_start.p0(ptr [[ARRAYDECAY]])
@@ -44,8 +45,11 @@ typedef struct {
 // CHECK-NEXT:[[TMP0:%.*]] = getelementptr inbounds 
[[STRUCT___VA_LIST_TAG]], ptr [[ARRAYDECAY1]], i32 0, i32 3
 // CHECK-NEXT:[[REG_SAVE_AREA:%.*]] = load ptr, ptr [[TMP0]], align 16
 // CHECK-NEXT:[[TMP1:%.*]] = getelementptr i8, ptr [[REG_SAVE_AREA]], i32 
[[FP_OFFSET]]
-// CHECK-NEXT:[[TMP2:%.*]] = add i32 [[FP_OFFSET]], 16
-// CHECK-NEXT:store i32 [[TMP2]], ptr [[FP_OFFSET_P]], align 4
+// CHECK-NEXT:[[TMP2:%.*]] = 

[clang] [X86_64] fix arg pass error in struct. (PR #86902)

2024-04-07 Thread Longsheng Mou via cfe-commits

https://github.com/CoTinker updated 
https://github.com/llvm/llvm-project/pull/86902

>From eb425dbaed73a58b5f8e05e425a1972aa1288fa9 Mon Sep 17 00:00:00 2001
From: Longsheng Mou 
Date: Fri, 15 Mar 2024 20:50:54 +0800
Subject: [PATCH] [X86_64] fix arg pass error in struct.

In some struct like s67, only one i64 register is used when the structure
parameter is transferred, which is obviously incorrect.So we need
to treat the split case specially, using memory like gcc.
---
 clang/lib/CodeGen/Targets/X86.cpp |  5 -
 clang/test/CodeGen/X86/x86_64-arguments.c | 18 ++
 2 files changed, 22 insertions(+), 1 deletion(-)

diff --git a/clang/lib/CodeGen/Targets/X86.cpp 
b/clang/lib/CodeGen/Targets/X86.cpp
index 1146a851a7715d..535ee2464595d1 100644
--- a/clang/lib/CodeGen/Targets/X86.cpp
+++ b/clang/lib/CodeGen/Targets/X86.cpp
@@ -2100,8 +2100,11 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t 
OffsetBase, Class ,
 postMerge(Size, Lo, Hi);
 return;
   }
+
+  bool IsInMemory =
+  Offset % getContext().getTypeAlign(i->getType().getCanonicalType());
   // Note, skip this test for bit-fields, see below.
-  if (!BitField && Offset % getContext().getTypeAlign(i->getType())) {
+  if (!BitField && IsInMemory) {
 Lo = Memory;
 postMerge(Size, Lo, Hi);
 return;
diff --git a/clang/test/CodeGen/X86/x86_64-arguments.c 
b/clang/test/CodeGen/X86/x86_64-arguments.c
index cf5636cfd518b6..82845f0a2b31fd 100644
--- a/clang/test/CodeGen/X86/x86_64-arguments.c
+++ b/clang/test/CodeGen/X86/x86_64-arguments.c
@@ -533,6 +533,24 @@ typedef float t66 __attribute__((__vector_size__(128), 
__aligned__(128)));
 void f66(t66 a0) {
 }
 
+typedef long long t67 __attribute__((aligned (4)));
+struct s67 {
+  int a;
+  t67 b;
+};
+// CHECK-LABEL: define{{.*}} void @f67(ptr noundef byval(%struct.s67) align 8 
%x)
+void f67(struct s67 x) {
+}
+
+typedef double t68 __attribute__((aligned (4)));
+struct s68 {
+  int a;
+  t68 b;
+};
+// CHECK-LABEL: define{{.*}} void @f68(ptr noundef byval(%struct.s68) align 8 
%x)
+void f68(struct s68 x) {
+}
+
 /// The synthesized __va_list_tag does not have file/line fields.
 // CHECK:  = distinct !DICompositeType(tag: DW_TAG_structure_type, name: 
"__va_list_tag",
 // CHECK-NOT:  file:

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


[clang] [X86_64] fix arg pass error in struct. (PR #86902)

2024-04-06 Thread Longsheng Mou via cfe-commits


@@ -2100,8 +2100,12 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t 
OffsetBase, Class ,
 postMerge(Size, Lo, Hi);
 return;
   }
+
+  bool InMemory = Offset % getContext().getTypeAlign(i->getType()) ||
+  (i->getType()->getAs() &&

CoTinker wrote:

I think it's a really good idea.

https://github.com/llvm/llvm-project/pull/86902
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [X86_32] Teach X86_32 va_arg to ignore empty structs. (PR #86075)

2024-04-02 Thread Longsheng Mou via cfe-commits

https://github.com/CoTinker updated 
https://github.com/llvm/llvm-project/pull/86075

>From 85d829dcef3484892d6db8f6a0329cb9bc34c349 Mon Sep 17 00:00:00 2001
From: Longsheng Mou 
Date: Thu, 21 Mar 2024 11:23:56 +0800
Subject: [PATCH] [X86_32] Teach X86_32 va_arg to ignore empty structs.

Empty structs are ignored for parameter passing purposes, but va_arg was
incrementing the pointer anyway for that the size of empty struct in c++
is 1 byte, which could lead to va_list getting out of sync.
---
 clang/lib/CodeGen/Targets/X86.cpp  |  6 ++
 clang/test/CodeGenCXX/x86_32-vaarg.cpp | 21 +
 2 files changed, 27 insertions(+)
 create mode 100644 clang/test/CodeGenCXX/x86_32-vaarg.cpp

diff --git a/clang/lib/CodeGen/Targets/X86.cpp 
b/clang/lib/CodeGen/Targets/X86.cpp
index 1146a851a7715d..c831777699f627 100644
--- a/clang/lib/CodeGen/Targets/X86.cpp
+++ b/clang/lib/CodeGen/Targets/X86.cpp
@@ -1069,6 +1069,12 @@ Address X86_32ABIInfo::EmitVAArg(CodeGenFunction ,
 
   auto TypeInfo = getContext().getTypeInfoInChars(Ty);
 
+  CCState State(*const_cast(CGF.CurFnInfo));
+  ABIArgInfo AI = classifyArgumentType(Ty, State, /*ArgIndex*/ 0);
+  // Empty records are ignored for parameter passing purposes.
+  if (AI.isIgnore())
+return CGF.CreateMemTemp(Ty);
+
   // x86-32 changes the alignment of certain arguments on the stack.
   //
   // Just messing with TypeInfo like this works because we never pass
diff --git a/clang/test/CodeGenCXX/x86_32-vaarg.cpp 
b/clang/test/CodeGenCXX/x86_32-vaarg.cpp
new file mode 100644
index 00..dcc2f7f96a40f1
--- /dev/null
+++ b/clang/test/CodeGenCXX/x86_32-vaarg.cpp
@@ -0,0 +1,21 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
+// RUN: %clang_cc1 -triple i386-linux-gnu -emit-llvm -o - %s | FileCheck %s
+
+typedef struct {} empty;
+
+// CHECK-LABEL: @_Z17empty_record_testiz(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:[[RESULT_PTR:%.*]] = alloca ptr, align 4
+// CHECK-NEXT:[[Z_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[LIST:%.*]] = alloca ptr, align 4
+// CHECK-NEXT:[[TMP:%.*]] = alloca [[STRUCT_EMPTY:%.*]], align 1
+// CHECK-NEXT:store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4
+// CHECK-NEXT:store i32 [[Z:%.*]], ptr [[Z_ADDR]], align 4
+// CHECK-NEXT:call void @llvm.va_start.p0(ptr [[LIST]])
+// CHECK-NEXT:ret void
+//
+empty empty_record_test(int z, ...) {
+  __builtin_va_list list;
+  __builtin_va_start(list, z);
+  return __builtin_va_arg(list, empty);
+}

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


[clang] [X86_32] Teach X86_32 va_arg to ignore empty structs. (PR #86075)

2024-04-02 Thread Longsheng Mou via cfe-commits

https://github.com/CoTinker updated 
https://github.com/llvm/llvm-project/pull/86075

>From 95a11789d89a57cc96512bd180949164f89695d0 Mon Sep 17 00:00:00 2001
From: Longsheng Mou 
Date: Thu, 21 Mar 2024 11:23:56 +0800
Subject: [PATCH] [X86_32] Teach X86_32 va_arg to ignore empty structs.

Empty structs are ignored for parameter passing purposes, but va_arg was
incrementing the pointer anyway for that the size of empty struct in c++
is 1 byte, which could lead to va_list getting out of sync.
---
 clang/lib/CodeGen/Targets/X86.cpp  |  6 ++
 clang/test/CodeGenCXX/x86_32-vaarg.cpp | 20 
 2 files changed, 26 insertions(+)
 create mode 100644 clang/test/CodeGenCXX/x86_32-vaarg.cpp

diff --git a/clang/lib/CodeGen/Targets/X86.cpp 
b/clang/lib/CodeGen/Targets/X86.cpp
index 1146a851a7715d..c831777699f627 100644
--- a/clang/lib/CodeGen/Targets/X86.cpp
+++ b/clang/lib/CodeGen/Targets/X86.cpp
@@ -1069,6 +1069,12 @@ Address X86_32ABIInfo::EmitVAArg(CodeGenFunction ,
 
   auto TypeInfo = getContext().getTypeInfoInChars(Ty);
 
+  CCState State(*const_cast(CGF.CurFnInfo));
+  ABIArgInfo AI = classifyArgumentType(Ty, State, /*ArgIndex*/ 0);
+  // Empty records are ignored for parameter passing purposes.
+  if (AI.isIgnore())
+return CGF.CreateMemTemp(Ty);
+
   // x86-32 changes the alignment of certain arguments on the stack.
   //
   // Just messing with TypeInfo like this works because we never pass
diff --git a/clang/test/CodeGenCXX/x86_32-vaarg.cpp 
b/clang/test/CodeGenCXX/x86_32-vaarg.cpp
new file mode 100644
index 00..23eac1164118c6
--- /dev/null
+++ b/clang/test/CodeGenCXX/x86_32-vaarg.cpp
@@ -0,0 +1,20 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
+// RUN: %clang_cc1 -triple i386-linux-gnu -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple i386-linux-gnu -emit-llvm -x c -o - %s | FileCheck 
%s
+
+typedef struct {} empty;
+
+// CHECK-LABEL: @{{.*}}empty_record_test
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:[[RESULT_PTR:%.*]] = alloca ptr, align 4
+// CHECK-NEXT:[[Z_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[LIST:%.*]] = alloca ptr, align 4
+// CHECK-NEXT:[[TMP:%.*]] = alloca [[STRUCT_EMPTY:%.*]], align 1
+// CHECK-NEXT:store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4
+// CHECK-NEXT:store i32 [[Z:%.*]], ptr [[Z_ADDR]], align 4
+// CHECK-NEXT:call void @llvm.va_start(ptr [[LIST]])
+empty empty_record_test(int z, ...) {
+  __builtin_va_list list;
+  __builtin_va_start(list, z);
+  return __builtin_va_arg(list, empty);
+}

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


[clang] [X86_32] Teach X86_32 va_arg to ignore empty structs. (PR #86075)

2024-04-01 Thread Longsheng Mou via cfe-commits

https://github.com/CoTinker updated 
https://github.com/llvm/llvm-project/pull/86075

>From 355f540288d87ca35a8e5790e4eaff383d619201 Mon Sep 17 00:00:00 2001
From: Longsheng Mou 
Date: Thu, 21 Mar 2024 11:23:56 +0800
Subject: [PATCH] [X86_32] Teach X86_32 va_arg to ignore empty structs.

Empty structs are ignored for parameter passing purposes, but va_arg was
incrementing the pointer anyway for that the size of empty struct in c++
is 1 byte, which could lead to va_list getting out of sync.
---
 clang/lib/CodeGen/Targets/X86.cpp  |  6 ++
 clang/test/CodeGenCXX/x86_32-vaarg.cpp | 20 
 2 files changed, 26 insertions(+)
 create mode 100644 clang/test/CodeGenCXX/x86_32-vaarg.cpp

diff --git a/clang/lib/CodeGen/Targets/X86.cpp 
b/clang/lib/CodeGen/Targets/X86.cpp
index 1146a851a7715d..c831777699f627 100644
--- a/clang/lib/CodeGen/Targets/X86.cpp
+++ b/clang/lib/CodeGen/Targets/X86.cpp
@@ -1069,6 +1069,12 @@ Address X86_32ABIInfo::EmitVAArg(CodeGenFunction ,
 
   auto TypeInfo = getContext().getTypeInfoInChars(Ty);
 
+  CCState State(*const_cast(CGF.CurFnInfo));
+  ABIArgInfo AI = classifyArgumentType(Ty, State, /*ArgIndex*/ 0);
+  // Empty records are ignored for parameter passing purposes.
+  if (AI.isIgnore())
+return CGF.CreateMemTemp(Ty);
+
   // x86-32 changes the alignment of certain arguments on the stack.
   //
   // Just messing with TypeInfo like this works because we never pass
diff --git a/clang/test/CodeGenCXX/x86_32-vaarg.cpp 
b/clang/test/CodeGenCXX/x86_32-vaarg.cpp
new file mode 100644
index 00..23eac1164118c6
--- /dev/null
+++ b/clang/test/CodeGenCXX/x86_32-vaarg.cpp
@@ -0,0 +1,20 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
+// RUN: %clang_cc1 -triple i386-linux-gnu -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple i386-linux-gnu -emit-llvm -x c -o - %s | FileCheck 
%s
+
+typedef struct {} empty;
+
+// CHECK-LABEL: @{{.*}}empty_record_test
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:[[RESULT_PTR:%.*]] = alloca ptr, align 4
+// CHECK-NEXT:[[Z_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[LIST:%.*]] = alloca ptr, align 4
+// CHECK-NEXT:[[TMP:%.*]] = alloca [[STRUCT_EMPTY:%.*]], align 1
+// CHECK-NEXT:store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4
+// CHECK-NEXT:store i32 [[Z:%.*]], ptr [[Z_ADDR]], align 4
+// CHECK-NEXT:call void @llvm.va_start(ptr [[LIST]])
+empty empty_record_test(int z, ...) {
+  __builtin_va_list list;
+  __builtin_va_start(list, z);
+  return __builtin_va_arg(list, empty);
+}

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


[clang] [X86_64] fix arg pass error in struct. (PR #86902)

2024-04-01 Thread Longsheng Mou via cfe-commits

CoTinker wrote:

Thank you very much, I'll try it.

https://github.com/llvm/llvm-project/pull/86902
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [X86_64] fix arg pass error in struct. (PR #86902)

2024-04-01 Thread Longsheng Mou via cfe-commits

https://github.com/CoTinker updated 
https://github.com/llvm/llvm-project/pull/86902

>From 09596bbeeedecb312f8be40d153bb267abc2d659 Mon Sep 17 00:00:00 2001
From: Longsheng Mou 
Date: Fri, 15 Mar 2024 20:50:54 +0800
Subject: [PATCH] [X86_64] fix arg pass error in struct.

In some struct like s67, only one i64 register is used when the structure
parameter is transferred, which is obviously incorrect.So we need
to treat the split case specially, using memory like gcc.
---
 clang/lib/CodeGen/Targets/X86.cpp |  6 +-
 clang/test/CodeGen/X86/x86_64-arguments.c | 18 ++
 2 files changed, 23 insertions(+), 1 deletion(-)

diff --git a/clang/lib/CodeGen/Targets/X86.cpp 
b/clang/lib/CodeGen/Targets/X86.cpp
index 1146a851a7715d..8f4df98af117a0 100644
--- a/clang/lib/CodeGen/Targets/X86.cpp
+++ b/clang/lib/CodeGen/Targets/X86.cpp
@@ -2100,8 +2100,12 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t 
OffsetBase, Class ,
 postMerge(Size, Lo, Hi);
 return;
   }
+
+  bool InMemory = Offset % getContext().getTypeAlign(i->getType()) ||
+  (i->getType()->getAs() &&
+   Offset % getContext().getTypeSize(i->getType()));
   // Note, skip this test for bit-fields, see below.
-  if (!BitField && Offset % getContext().getTypeAlign(i->getType())) {
+  if (!BitField && InMemory) {
 Lo = Memory;
 postMerge(Size, Lo, Hi);
 return;
diff --git a/clang/test/CodeGen/X86/x86_64-arguments.c 
b/clang/test/CodeGen/X86/x86_64-arguments.c
index cf5636cfd518b6..82845f0a2b31fd 100644
--- a/clang/test/CodeGen/X86/x86_64-arguments.c
+++ b/clang/test/CodeGen/X86/x86_64-arguments.c
@@ -533,6 +533,24 @@ typedef float t66 __attribute__((__vector_size__(128), 
__aligned__(128)));
 void f66(t66 a0) {
 }
 
+typedef long long t67 __attribute__((aligned (4)));
+struct s67 {
+  int a;
+  t67 b;
+};
+// CHECK-LABEL: define{{.*}} void @f67(ptr noundef byval(%struct.s67) align 8 
%x)
+void f67(struct s67 x) {
+}
+
+typedef double t68 __attribute__((aligned (4)));
+struct s68 {
+  int a;
+  t68 b;
+};
+// CHECK-LABEL: define{{.*}} void @f68(ptr noundef byval(%struct.s68) align 8 
%x)
+void f68(struct s68 x) {
+}
+
 /// The synthesized __va_list_tag does not have file/line fields.
 // CHECK:  = distinct !DICompositeType(tag: DW_TAG_structure_type, name: 
"__va_list_tag",
 // CHECK-NOT:  file:

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


[clang] [X86_32] Teach X86_32 va_arg to ignore empty structs. (PR #86075)

2024-04-01 Thread Longsheng Mou via cfe-commits

https://github.com/CoTinker updated 
https://github.com/llvm/llvm-project/pull/86075

>From a4d9a6fefdbe7c0ee6a891af230438a10ddd7c5a Mon Sep 17 00:00:00 2001
From: Longsheng Mou 
Date: Thu, 21 Mar 2024 11:23:56 +0800
Subject: [PATCH] [X86_32] Teach X86_32 va_arg to ignore empty structs.

Empty structs are ignored for parameter passing purposes, but va_arg was
incrementing the pointer anyway for that the size of empty struct in c++
is 1 byte, which could lead to va_list getting out of sync.
---
 clang/lib/CodeGen/Targets/X86.cpp  |  6 ++
 clang/test/CodeGenCXX/x86_32-vaarg.cpp | 20 
 2 files changed, 26 insertions(+)
 create mode 100644 clang/test/CodeGenCXX/x86_32-vaarg.cpp

diff --git a/clang/lib/CodeGen/Targets/X86.cpp 
b/clang/lib/CodeGen/Targets/X86.cpp
index 1146a851a7715d..c831777699f627 100644
--- a/clang/lib/CodeGen/Targets/X86.cpp
+++ b/clang/lib/CodeGen/Targets/X86.cpp
@@ -1069,6 +1069,12 @@ Address X86_32ABIInfo::EmitVAArg(CodeGenFunction ,
 
   auto TypeInfo = getContext().getTypeInfoInChars(Ty);
 
+  CCState State(*const_cast(CGF.CurFnInfo));
+  ABIArgInfo AI = classifyArgumentType(Ty, State, /*ArgIndex*/ 0);
+  // Empty records are ignored for parameter passing purposes.
+  if (AI.isIgnore())
+return CGF.CreateMemTemp(Ty);
+
   // x86-32 changes the alignment of certain arguments on the stack.
   //
   // Just messing with TypeInfo like this works because we never pass
diff --git a/clang/test/CodeGenCXX/x86_32-vaarg.cpp 
b/clang/test/CodeGenCXX/x86_32-vaarg.cpp
new file mode 100644
index 00..23eac1164118c6
--- /dev/null
+++ b/clang/test/CodeGenCXX/x86_32-vaarg.cpp
@@ -0,0 +1,20 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
+// RUN: %clang_cc1 -triple i386-linux-gnu -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple i386-linux-gnu -emit-llvm -x c -o - %s | FileCheck 
%s
+
+typedef struct {} empty;
+
+// CHECK-LABEL: @{{.*}}empty_record_test
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:[[RESULT_PTR:%.*]] = alloca ptr, align 4
+// CHECK-NEXT:[[Z_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[LIST:%.*]] = alloca ptr, align 4
+// CHECK-NEXT:[[TMP:%.*]] = alloca [[STRUCT_EMPTY:%.*]], align 1
+// CHECK-NEXT:store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4
+// CHECK-NEXT:store i32 [[Z:%.*]], ptr [[Z_ADDR]], align 4
+// CHECK-NEXT:call void @llvm.va_start(ptr [[LIST]])
+empty empty_record_test(int z, ...) {
+  __builtin_va_list list;
+  __builtin_va_start(list, z);
+  return __builtin_va_arg(list, empty);
+}

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


[clang] [X86_32] Teach X86_32 va_arg to ignore empty structs. (PR #86075)

2024-04-01 Thread Longsheng Mou via cfe-commits

https://github.com/CoTinker updated 
https://github.com/llvm/llvm-project/pull/86075

>From 929fba43012209b74b654b8d9a017a43826063fe Mon Sep 17 00:00:00 2001
From: Longsheng Mou 
Date: Thu, 21 Mar 2024 11:23:56 +0800
Subject: [PATCH] [X86_32] Teach X86_32 va_arg to ignore empty structs.

Empty structs are ignored for parameter passing purposes, but va_arg was
incrementing the pointer anyway for that the size of empty struct in c++
is 1 byte, which could lead to va_list getting out of sync.
---
 clang/lib/CodeGen/Targets/X86.cpp  |  6 ++
 clang/test/CodeGenCXX/x86_32-vaarg.cpp | 20 
 2 files changed, 26 insertions(+)
 create mode 100644 clang/test/CodeGenCXX/x86_32-vaarg.cpp

diff --git a/clang/lib/CodeGen/Targets/X86.cpp 
b/clang/lib/CodeGen/Targets/X86.cpp
index 1ec0f159ebcb8a..38143d1eed21aa 100644
--- a/clang/lib/CodeGen/Targets/X86.cpp
+++ b/clang/lib/CodeGen/Targets/X86.cpp
@@ -1069,6 +1069,12 @@ Address X86_32ABIInfo::EmitVAArg(CodeGenFunction ,
 
   auto TypeInfo = getContext().getTypeInfoInChars(Ty);
 
+  CCState State(*const_cast(CGF.CurFnInfo));
+  ABIArgInfo AI = classifyArgumentType(Ty, State, /*ArgIndex*/ 0);
+  // Empty records are ignored for parameter passing purposes.
+  if (AI.isIgnore())
+return CGF.CreateMemTemp(Ty);
+
   // x86-32 changes the alignment of certain arguments on the stack.
   //
   // Just messing with TypeInfo like this works because we never pass
diff --git a/clang/test/CodeGenCXX/x86_32-vaarg.cpp 
b/clang/test/CodeGenCXX/x86_32-vaarg.cpp
new file mode 100644
index 00..23eac1164118c6
--- /dev/null
+++ b/clang/test/CodeGenCXX/x86_32-vaarg.cpp
@@ -0,0 +1,20 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
+// RUN: %clang_cc1 -triple i386-linux-gnu -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple i386-linux-gnu -emit-llvm -x c -o - %s | FileCheck 
%s
+
+typedef struct {} empty;
+
+// CHECK-LABEL: @{{.*}}empty_record_test
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:[[RESULT_PTR:%.*]] = alloca ptr, align 4
+// CHECK-NEXT:[[Z_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[LIST:%.*]] = alloca ptr, align 4
+// CHECK-NEXT:[[TMP:%.*]] = alloca [[STRUCT_EMPTY:%.*]], align 1
+// CHECK-NEXT:store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4
+// CHECK-NEXT:store i32 [[Z:%.*]], ptr [[Z_ADDR]], align 4
+// CHECK-NEXT:call void @llvm.va_start(ptr [[LIST]])
+empty empty_record_test(int z, ...) {
+  __builtin_va_list list;
+  __builtin_va_start(list, z);
+  return __builtin_va_arg(list, empty);
+}

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


[clang] [X86_32] Teach X86_32 va_arg to ignore empty structs. (PR #86075)

2024-03-30 Thread Longsheng Mou via cfe-commits

https://github.com/CoTinker updated 
https://github.com/llvm/llvm-project/pull/86075

>From 5178a001cc3ce765e3d29e91e24597fa1b0f42d6 Mon Sep 17 00:00:00 2001
From: Longsheng Mou 
Date: Thu, 21 Mar 2024 11:23:56 +0800
Subject: [PATCH] [X86_32] Teach X86_32 va_arg to ignore empty structs.

Empty structs are ignored for parameter passing purposes, but va_arg was
incrementing the pointer anyway for that the size of empty struct in c++
is 1 byte, which could lead to va_list getting out of sync.
---
 clang/lib/CodeGen/Targets/X86.cpp  |  6 ++
 clang/test/CodeGenCXX/x86_32-vaarg.cpp | 20 
 2 files changed, 26 insertions(+)
 create mode 100644 clang/test/CodeGenCXX/x86_32-vaarg.cpp

diff --git a/clang/lib/CodeGen/Targets/X86.cpp 
b/clang/lib/CodeGen/Targets/X86.cpp
index 1ec0f159ebcb8a..2cb880752de3ea 100644
--- a/clang/lib/CodeGen/Targets/X86.cpp
+++ b/clang/lib/CodeGen/Targets/X86.cpp
@@ -1069,6 +1069,12 @@ Address X86_32ABIInfo::EmitVAArg(CodeGenFunction ,
 
   auto TypeInfo = getContext().getTypeInfoInChars(Ty);
 
+  CCState State(*const_cast(CGF.CurFnInfo));
+  ABIArgInfo AI = classifyArgumentType(Ty, State, /*ArgIndex*/ 0);
+  // Empty records are ignored for parameter passing purposes.
+  if (AI.isIgnore())
+return CGF.CreateMemTemp(Ty);
+
   // x86-32 changes the alignment of certain arguments on the stack.
   //
   // Just messing with TypeInfo like this works because we never pass
diff --git a/clang/test/CodeGenCXX/x86_32-vaarg.cpp 
b/clang/test/CodeGenCXX/x86_32-vaarg.cpp
new file mode 100644
index 00..23eac1164118c6
--- /dev/null
+++ b/clang/test/CodeGenCXX/x86_32-vaarg.cpp
@@ -0,0 +1,20 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
+// RUN: %clang_cc1 -triple i386-linux-gnu -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple i386-linux-gnu -emit-llvm -x c -o - %s | FileCheck 
%s
+
+typedef struct {} empty;
+
+// CHECK-LABEL: @{{.*}}empty_record_test
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:[[RESULT_PTR:%.*]] = alloca ptr, align 4
+// CHECK-NEXT:[[Z_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[LIST:%.*]] = alloca ptr, align 4
+// CHECK-NEXT:[[TMP:%.*]] = alloca [[STRUCT_EMPTY:%.*]], align 1
+// CHECK-NEXT:store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4
+// CHECK-NEXT:store i32 [[Z:%.*]], ptr [[Z_ADDR]], align 4
+// CHECK-NEXT:call void @llvm.va_start(ptr [[LIST]])
+empty empty_record_test(int z, ...) {
+  __builtin_va_list list;
+  __builtin_va_start(list, z);
+  return __builtin_va_arg(list, empty);
+}

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


[clang] [X86_64] fix arg pass error in struct. (PR #86902)

2024-03-29 Thread Longsheng Mou via cfe-commits

CoTinker wrote:

@DavidSpickett why my buildkite always fail, while check-all success in local 
environment. Could you please take a look at it?

https://github.com/llvm/llvm-project/pull/86902
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [X86_64] fix arg pass error in struct. (PR #86902)

2024-03-27 Thread Longsheng Mou via cfe-commits

https://github.com/CoTinker created 
https://github.com/llvm/llvm-project/pull/86902

```
typedef long long t67 __attribute__((aligned (4)));
struct s67 {
  int a;
  t67 b;
};
void f67(struct s67 x) {
}
```
When classify:
a: Lo = Integer, Hi = NoClass
b: Lo = Integer, Hi = NoClass
struct S: Lo = Integer, Hi = NoClass

```
define dso_local void @f67(i64 %x.coerce) {
```
In this case, only one i64 register is used when the structure parameter is 
transferred, which is obviously incorrect.So we need to treat the split case 
specially. fix https://github.com/llvm/llvm-project/issues/85387.

>From ad805988f682030cd3ed6ff6b063488ed6f5707c Mon Sep 17 00:00:00 2001
From: Longsheng Mou 
Date: Fri, 15 Mar 2024 20:50:54 +0800
Subject: [PATCH] [X86_64] fix arg pass error in struct.

In some struct like s67, only one i64 register is used when the structure
parameter is transferred, which is obviously incorrect.So we need
to treat the split case specially, using memory like gcc.
---
 clang/lib/CodeGen/Targets/X86.cpp |  6 +-
 clang/test/CodeGen/X86/x86_64-arguments.c | 18 ++
 2 files changed, 23 insertions(+), 1 deletion(-)

diff --git a/clang/lib/CodeGen/Targets/X86.cpp 
b/clang/lib/CodeGen/Targets/X86.cpp
index 2291c991fb1107..de0dfe32a54d3a 100644
--- a/clang/lib/CodeGen/Targets/X86.cpp
+++ b/clang/lib/CodeGen/Targets/X86.cpp
@@ -2100,8 +2100,12 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t 
OffsetBase, Class ,
 postMerge(Size, Lo, Hi);
 return;
   }
+
+  bool InMemory = Offset % getContext().getTypeAlign(i->getType()) ||
+  (i->getType()->getAs() &&
+   Offset % getContext().getTypeSize(i->getType()));
   // Note, skip this test for bit-fields, see below.
-  if (!BitField && Offset % getContext().getTypeAlign(i->getType())) {
+  if (!BitField && InMemory) {
 Lo = Memory;
 postMerge(Size, Lo, Hi);
 return;
diff --git a/clang/test/CodeGen/X86/x86_64-arguments.c 
b/clang/test/CodeGen/X86/x86_64-arguments.c
index cf5636cfd518b6..82845f0a2b31fd 100644
--- a/clang/test/CodeGen/X86/x86_64-arguments.c
+++ b/clang/test/CodeGen/X86/x86_64-arguments.c
@@ -533,6 +533,24 @@ typedef float t66 __attribute__((__vector_size__(128), 
__aligned__(128)));
 void f66(t66 a0) {
 }
 
+typedef long long t67 __attribute__((aligned (4)));
+struct s67 {
+  int a;
+  t67 b;
+};
+// CHECK-LABEL: define{{.*}} void @f67(ptr noundef byval(%struct.s67) align 8 
%x)
+void f67(struct s67 x) {
+}
+
+typedef double t68 __attribute__((aligned (4)));
+struct s68 {
+  int a;
+  t68 b;
+};
+// CHECK-LABEL: define{{.*}} void @f68(ptr noundef byval(%struct.s68) align 8 
%x)
+void f68(struct s68 x) {
+}
+
 /// The synthesized __va_list_tag does not have file/line fields.
 // CHECK:  = distinct !DICompositeType(tag: DW_TAG_structure_type, name: 
"__va_list_tag",
 // CHECK-NOT:  file:

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


[clang] [X86_64] fix arg pass error in struct. (PR #85394)

2024-03-27 Thread Longsheng Mou via cfe-commits

https://github.com/CoTinker closed 
https://github.com/llvm/llvm-project/pull/85394
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [X86_64] fix arg pass error in struct. (PR #85394)

2024-03-27 Thread Longsheng Mou via cfe-commits

https://github.com/CoTinker updated 
https://github.com/llvm/llvm-project/pull/85394

>From ad805988f682030cd3ed6ff6b063488ed6f5707c Mon Sep 17 00:00:00 2001
From: Longsheng Mou 
Date: Fri, 15 Mar 2024 20:50:54 +0800
Subject: [PATCH] [X86_64] fix arg pass error in struct.

In some struct like s67, only one i64 register is used when the structure
parameter is transferred, which is obviously incorrect.So we need
to treat the split case specially, using memory like gcc.
---
 clang/lib/CodeGen/Targets/X86.cpp |  6 +-
 clang/test/CodeGen/X86/x86_64-arguments.c | 18 ++
 2 files changed, 23 insertions(+), 1 deletion(-)

diff --git a/clang/lib/CodeGen/Targets/X86.cpp 
b/clang/lib/CodeGen/Targets/X86.cpp
index 2291c991fb1107..de0dfe32a54d3a 100644
--- a/clang/lib/CodeGen/Targets/X86.cpp
+++ b/clang/lib/CodeGen/Targets/X86.cpp
@@ -2100,8 +2100,12 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t 
OffsetBase, Class ,
 postMerge(Size, Lo, Hi);
 return;
   }
+
+  bool InMemory = Offset % getContext().getTypeAlign(i->getType()) ||
+  (i->getType()->getAs() &&
+   Offset % getContext().getTypeSize(i->getType()));
   // Note, skip this test for bit-fields, see below.
-  if (!BitField && Offset % getContext().getTypeAlign(i->getType())) {
+  if (!BitField && InMemory) {
 Lo = Memory;
 postMerge(Size, Lo, Hi);
 return;
diff --git a/clang/test/CodeGen/X86/x86_64-arguments.c 
b/clang/test/CodeGen/X86/x86_64-arguments.c
index cf5636cfd518b6..82845f0a2b31fd 100644
--- a/clang/test/CodeGen/X86/x86_64-arguments.c
+++ b/clang/test/CodeGen/X86/x86_64-arguments.c
@@ -533,6 +533,24 @@ typedef float t66 __attribute__((__vector_size__(128), 
__aligned__(128)));
 void f66(t66 a0) {
 }
 
+typedef long long t67 __attribute__((aligned (4)));
+struct s67 {
+  int a;
+  t67 b;
+};
+// CHECK-LABEL: define{{.*}} void @f67(ptr noundef byval(%struct.s67) align 8 
%x)
+void f67(struct s67 x) {
+}
+
+typedef double t68 __attribute__((aligned (4)));
+struct s68 {
+  int a;
+  t68 b;
+};
+// CHECK-LABEL: define{{.*}} void @f68(ptr noundef byval(%struct.s68) align 8 
%x)
+void f68(struct s68 x) {
+}
+
 /// The synthesized __va_list_tag does not have file/line fields.
 // CHECK:  = distinct !DICompositeType(tag: DW_TAG_structure_type, name: 
"__va_list_tag",
 // CHECK-NOT:  file:

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


[clang] [X86_32][C++] fix 0 sized struct case in vaarg. (PR #86388)

2024-03-25 Thread Longsheng Mou via cfe-commits

https://github.com/CoTinker edited 
https://github.com/llvm/llvm-project/pull/86388
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [X86_64] fix SSE type error in vaarg. (PR #86377)

2024-03-25 Thread Longsheng Mou via cfe-commits


@@ -21,3 +21,18 @@ empty empty_record_test(int z, ...) {
   __builtin_va_start(list, z);
   return __builtin_va_arg(list, empty);
 }
+

CoTinker wrote:

done

https://github.com/llvm/llvm-project/pull/86377
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [X86_64] fix SSE type error in vaarg. (PR #86377)

2024-03-24 Thread Longsheng Mou via cfe-commits

https://github.com/CoTinker updated 
https://github.com/llvm/llvm-project/pull/86377

>From b494f2e7f59668678f95d4a739d810f6fd6944aa Mon Sep 17 00:00:00 2001
From: Longsheng Mou 
Date: Sat, 23 Mar 2024 11:52:04 +0800
Subject: [PATCH] [X86_64] fix SSE type error in vaarg.

tweak the position of the ++neededSSE when Lo is NoClass
and Hi is SSE.
---
 clang/lib/CodeGen/Targets/X86.cpp  |  3 +-
 clang/test/CodeGen/X86/x86_64-vaarg.c  | 69 ++
 clang/test/CodeGenCXX/x86_64-vaarg.cpp | 50 +--
 3 files changed, 117 insertions(+), 5 deletions(-)
 create mode 100644 clang/test/CodeGen/X86/x86_64-vaarg.c

diff --git a/clang/lib/CodeGen/Targets/X86.cpp 
b/clang/lib/CodeGen/Targets/X86.cpp
index 1ec0f159ebcb8a..6931768147a9b2 100644
--- a/clang/lib/CodeGen/Targets/X86.cpp
+++ b/clang/lib/CodeGen/Targets/X86.cpp
@@ -2788,12 +2788,11 @@ X86_64ABIInfo::classifyArgumentType(QualType Ty, 
unsigned freeIntRegs,
 // memory), except in situations involving unions.
   case X87Up:
   case SSE:
+++neededSSE;
 HighPart = GetSSETypeAtOffset(CGT.ConvertType(Ty), 8, Ty, 8);
 
 if (Lo == NoClass)  // Pass HighPart at offset 8 in memory.
   return ABIArgInfo::getDirect(HighPart, 8);
-
-++neededSSE;
 break;
 
 // AMD64-ABI 3.2.3p3: Rule 4. If the class is SSEUP, the
diff --git a/clang/test/CodeGen/X86/x86_64-vaarg.c 
b/clang/test/CodeGen/X86/x86_64-vaarg.c
new file mode 100644
index 00..a18ba836423881
--- /dev/null
+++ b/clang/test/CodeGen/X86/x86_64-vaarg.c
@@ -0,0 +1,69 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py 
UTC_ARGS: --version 4
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -o - %s | FileCheck %s
+
+
+typedef struct { struct {} a; } empty;
+
+// CHECK-LABEL: define dso_local void @empty_record_test(
+// CHECK-SAME: i32 noundef [[Z:%.*]], ...) #[[ATTR0:[0-9]+]] {
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:[[RETVAL:%.*]] = alloca [[STRUCT_EMPTY:%.*]], align 1
+// CHECK-NEXT:[[Z_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[LIST:%.*]] = alloca [1 x %struct.__va_list_tag], align 16
+// CHECK-NEXT:[[TMP:%.*]] = alloca [[STRUCT_EMPTY]], align 1
+// CHECK-NEXT:store i32 [[Z]], ptr [[Z_ADDR]], align 4
+// CHECK-NEXT:[[ARRAYDECAY:%.*]] = getelementptr inbounds [1 x 
%struct.__va_list_tag], ptr [[LIST]], i64 0, i64 0
+// CHECK-NEXT:call void @llvm.va_start(ptr [[ARRAYDECAY]])
+// CHECK-NEXT:[[ARRAYDECAY1:%.*]] = getelementptr inbounds [1 x 
%struct.__va_list_tag], ptr [[LIST]], i64 0, i64 0
+// CHECK-NEXT:call void @llvm.memcpy.p0.p0.i64(ptr align 1 [[RETVAL]], ptr 
align 1 [[TMP]], i64 0, i1 false)
+// CHECK-NEXT:ret void
+//
+empty empty_record_test(int z, ...) {
+  __builtin_va_list list;
+  __builtin_va_start(list, z);
+  return __builtin_va_arg(list, empty);
+}
+
+typedef struct {
+  struct{} a;
+  double b;
+} s1;
+
+// CHECK-LABEL: define dso_local double @f(
+// CHECK-SAME: i32 noundef [[Z:%.*]], ...) #[[ATTR0]] {
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:[[RETVAL:%.*]] = alloca [[STRUCT_S1:%.*]], align 8
+// CHECK-NEXT:[[Z_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[LIST:%.*]] = alloca [1 x %struct.__va_list_tag], align 16
+// CHECK-NEXT:store i32 [[Z]], ptr [[Z_ADDR]], align 4
+// CHECK-NEXT:[[ARRAYDECAY:%.*]] = getelementptr inbounds [1 x 
%struct.__va_list_tag], ptr [[LIST]], i64 0, i64 0
+// CHECK-NEXT:call void @llvm.va_start(ptr [[ARRAYDECAY]])
+// CHECK-NEXT:[[ARRAYDECAY1:%.*]] = getelementptr inbounds [1 x 
%struct.__va_list_tag], ptr [[LIST]], i64 0, i64 0
+// CHECK-NEXT:[[FP_OFFSET_P:%.*]] = getelementptr inbounds 
[[STRUCT___VA_LIST_TAG:%.*]], ptr [[ARRAYDECAY1]], i32 0, i32 1
+// CHECK-NEXT:[[FP_OFFSET:%.*]] = load i32, ptr [[FP_OFFSET_P]], align 4
+// CHECK-NEXT:[[FITS_IN_FP:%.*]] = icmp ule i32 [[FP_OFFSET]], 160
+// CHECK-NEXT:br i1 [[FITS_IN_FP]], label [[VAARG_IN_REG:%.*]], label 
[[VAARG_IN_MEM:%.*]]
+// CHECK:   vaarg.in_reg:
+// CHECK-NEXT:[[TMP0:%.*]] = getelementptr inbounds 
[[STRUCT___VA_LIST_TAG]], ptr [[ARRAYDECAY1]], i32 0, i32 3
+// CHECK-NEXT:[[REG_SAVE_AREA:%.*]] = load ptr, ptr [[TMP0]], align 16
+// CHECK-NEXT:[[TMP1:%.*]] = getelementptr i8, ptr [[REG_SAVE_AREA]], i32 
[[FP_OFFSET]]
+// CHECK-NEXT:[[TMP2:%.*]] = add i32 [[FP_OFFSET]], 16
+// CHECK-NEXT:store i32 [[TMP2]], ptr [[FP_OFFSET_P]], align 4
+// CHECK-NEXT:br label [[VAARG_END:%.*]]
+// CHECK:   vaarg.in_mem:
+// CHECK-NEXT:[[OVERFLOW_ARG_AREA_P:%.*]] = getelementptr inbounds 
[[STRUCT___VA_LIST_TAG]], ptr [[ARRAYDECAY1]], i32 0, i32 2
+// CHECK-NEXT:[[OVERFLOW_ARG_AREA:%.*]] = load ptr, ptr 
[[OVERFLOW_ARG_AREA_P]], align 8
+// CHECK-NEXT:[[OVERFLOW_ARG_AREA_NEXT:%.*]] = getelementptr i8, ptr 
[[OVERFLOW_ARG_AREA]], i32 8
+// CHECK-NEXT:store ptr [[OVERFLOW_ARG_AREA_NEXT]], ptr 
[[OVERFLOW_ARG_AREA_P]], align 8
+// CHECK-NEXT:br label [[VAARG_END]]
+// CHECK:   

[clang] [X86_32] fix 0 sized struct case in vaarg. (PR #86388)

2024-03-23 Thread Longsheng Mou via cfe-commits

https://github.com/CoTinker edited 
https://github.com/llvm/llvm-project/pull/86388
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [X86_32] fix 0 sized struct case in vaarg. (PR #86388)

2024-03-23 Thread Longsheng Mou via cfe-commits

https://github.com/CoTinker edited 
https://github.com/llvm/llvm-project/pull/86388
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [X86_32] fix weird edge case in vaarg. (PR #86388)

2024-03-23 Thread Longsheng Mou via cfe-commits

https://github.com/CoTinker updated 
https://github.com/llvm/llvm-project/pull/86388

>From 8752d9019851bd231f1777d20391af60f0b4365c Mon Sep 17 00:00:00 2001
From: Longsheng Mou 
Date: Sat, 23 Mar 2024 17:53:58 +0800
Subject: [PATCH] [X86_32] fix 0 sized struct case in vaarg.

struct SuperEmpty { struct{ int a[0];} b;};
Such 0 sized structs in c++ mode can not be ignored in i386 for
that c++ fields are never empty.But when EmitVAArg, its size is
0, so that va_list not increase.Maybe we can use direct in this
case.
---
 clang/lib/CodeGen/Targets/X86.cpp | 3 +++
 clang/test/CodeGenCXX/regparm.cpp | 2 +-
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/clang/lib/CodeGen/Targets/X86.cpp 
b/clang/lib/CodeGen/Targets/X86.cpp
index 1ec0f159ebcb8a..8e6e7c17452048 100644
--- a/clang/lib/CodeGen/Targets/X86.cpp
+++ b/clang/lib/CodeGen/Targets/X86.cpp
@@ -805,6 +805,9 @@ ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty, 
CCState ,
 if (!IsWin32StructABI && isEmptyRecord(getContext(), Ty, true))
   return ABIArgInfo::getIgnore();
 
+if (TI.Width == 0 && getContext().getLangOpts().CPlusPlus)
+  return ABIArgInfo::getDirect();
+
 llvm::LLVMContext  = getVMContext();
 llvm::IntegerType *Int32 = llvm::Type::getInt32Ty(LLVMContext);
 bool NeedsPadding = false;
diff --git a/clang/test/CodeGenCXX/regparm.cpp 
b/clang/test/CodeGenCXX/regparm.cpp
index 1fd471c2d0727b..559702a84c99e1 100644
--- a/clang/test/CodeGenCXX/regparm.cpp
+++ b/clang/test/CodeGenCXX/regparm.cpp
@@ -32,7 +32,7 @@ struct S3 {
   } a;
 };
 __attribute((regparm(2))) void foo4(S3 a, int b);
-// CHECK: declare void @_Z4foo42S3i(ptr noundef byval(%struct.S3) align 4, i32 
inreg noundef)
+// CHECK: declare void @_Z4foo42S3i(%struct.anon, i32 inreg noundef)
 void bar3(S3 a, int b) {
   foo4(a, b);
 }

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


[clang] [X86_32] fix weird edge case in vaarg. (PR #86388)

2024-03-23 Thread Longsheng Mou via cfe-commits

https://github.com/CoTinker edited 
https://github.com/llvm/llvm-project/pull/86388
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [X86_32] fix weird edge case in vaarg. (PR #86388)

2024-03-23 Thread Longsheng Mou via cfe-commits

https://github.com/CoTinker created 
https://github.com/llvm/llvm-project/pull/86388

struct SuperEmpty { struct{ int a[0];} b;};
Such 0 sized structs in c++ mode can not be ignored in i386 for that c++ fields 
are never empty.But when EmitVAArg, its size is 0, so that va_list not 
increase.Maybe we can use direct in this case.

https://github.com/llvm/llvm-project/blob/691b97c884a15a7eac641ddf67c9f2f30fb4e747/clang/lib/CodeGen/ABIInfoImpl.cpp#L202-L216

This case use indirect before and `DirectSize == 0`, now we use direct and 
`DirectSize == 4`.
Or we can just Ignore this kind of arguments, like X86_64 did. 

>From dda9d5ac87b05c71079b6ed3b5d4188ff22ce356 Mon Sep 17 00:00:00 2001
From: Longsheng Mou 
Date: Sat, 23 Mar 2024 17:53:58 +0800
Subject: [PATCH] [X86_32] fix weird edge case in vaarg.

struct SuperEmpty { struct{ int a[0];} b;};
Such 0 sized structs in c++ mode can not be ignored in i386 for
that c++ fields are never empty.But when EmitVAArg, its size is
0, so that va_list not increase.Maybe we can use direct in this
case.
---
 clang/lib/CodeGen/Targets/X86.cpp | 3 +++
 clang/test/CodeGenCXX/regparm.cpp | 2 +-
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/clang/lib/CodeGen/Targets/X86.cpp 
b/clang/lib/CodeGen/Targets/X86.cpp
index 1ec0f159ebcb8a..8e6e7c17452048 100644
--- a/clang/lib/CodeGen/Targets/X86.cpp
+++ b/clang/lib/CodeGen/Targets/X86.cpp
@@ -805,6 +805,9 @@ ABIArgInfo X86_32ABIInfo::classifyArgumentType(QualType Ty, 
CCState ,
 if (!IsWin32StructABI && isEmptyRecord(getContext(), Ty, true))
   return ABIArgInfo::getIgnore();
 
+if (TI.Width == 0 && getContext().getLangOpts().CPlusPlus)
+  return ABIArgInfo::getDirect();
+
 llvm::LLVMContext  = getVMContext();
 llvm::IntegerType *Int32 = llvm::Type::getInt32Ty(LLVMContext);
 bool NeedsPadding = false;
diff --git a/clang/test/CodeGenCXX/regparm.cpp 
b/clang/test/CodeGenCXX/regparm.cpp
index 1fd471c2d0727b..559702a84c99e1 100644
--- a/clang/test/CodeGenCXX/regparm.cpp
+++ b/clang/test/CodeGenCXX/regparm.cpp
@@ -32,7 +32,7 @@ struct S3 {
   } a;
 };
 __attribute((regparm(2))) void foo4(S3 a, int b);
-// CHECK: declare void @_Z4foo42S3i(ptr noundef byval(%struct.S3) align 4, i32 
inreg noundef)
+// CHECK: declare void @_Z4foo42S3i(%struct.anon, i32 inreg noundef)
 void bar3(S3 a, int b) {
   foo4(a, b);
 }

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


[clang] [X86_64] fix SSE type error in vaarg. (PR #86377)

2024-03-22 Thread Longsheng Mou via cfe-commits

https://github.com/CoTinker created 
https://github.com/llvm/llvm-project/pull/86377

tweak the position of the ++neededSSE when Lo is NoClass and Hi is SSE. Fix 
#86371.

>From 551d1cd574cdf66a73dbe4e384a21949013e0baa Mon Sep 17 00:00:00 2001
From: Longsheng Mou 
Date: Sat, 23 Mar 2024 11:52:04 +0800
Subject: [PATCH] [X86_64] fix SSE type error in vaarg.

tweak the position of the ++neededSSE when Lo is NoClass
and Hi is SSE.
---
 clang/lib/CodeGen/Targets/X86.cpp  |  3 +--
 clang/test/CodeGenCXX/x86_64-vaarg.cpp | 15 +++
 2 files changed, 16 insertions(+), 2 deletions(-)

diff --git a/clang/lib/CodeGen/Targets/X86.cpp 
b/clang/lib/CodeGen/Targets/X86.cpp
index 1ec0f159ebcb8a..6931768147a9b2 100644
--- a/clang/lib/CodeGen/Targets/X86.cpp
+++ b/clang/lib/CodeGen/Targets/X86.cpp
@@ -2788,12 +2788,11 @@ X86_64ABIInfo::classifyArgumentType(QualType Ty, 
unsigned freeIntRegs,
 // memory), except in situations involving unions.
   case X87Up:
   case SSE:
+++neededSSE;
 HighPart = GetSSETypeAtOffset(CGT.ConvertType(Ty), 8, Ty, 8);
 
 if (Lo == NoClass)  // Pass HighPart at offset 8 in memory.
   return ABIArgInfo::getDirect(HighPart, 8);
-
-++neededSSE;
 break;
 
 // AMD64-ABI 3.2.3p3: Rule 4. If the class is SSEUP, the
diff --git a/clang/test/CodeGenCXX/x86_64-vaarg.cpp 
b/clang/test/CodeGenCXX/x86_64-vaarg.cpp
index f0177906a09a81..82c32329502816 100644
--- a/clang/test/CodeGenCXX/x86_64-vaarg.cpp
+++ b/clang/test/CodeGenCXX/x86_64-vaarg.cpp
@@ -21,3 +21,18 @@ empty empty_record_test(int z, ...) {
   __builtin_va_start(list, z);
   return __builtin_va_arg(list, empty);
 }
+
+typedef struct {
+  struct{} a;
+  double b;
+} s1;
+
+// CHECK-LABEL: define{{.*}} double @{{.*}}f
+// CHECK: vaarg.in_reg:
+// CHECK: vaarg.in_mem:
+// CHECK: vaarg.end:
+s1 f(int z, ...) {
+  __builtin_va_list list;
+  __builtin_va_start(list, z);
+  return __builtin_va_arg(list, s1);
+}

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


[clang] [X86_64] fix arg pass error in struct. (PR #85394)

2024-03-22 Thread Longsheng Mou via cfe-commits

https://github.com/CoTinker updated 
https://github.com/llvm/llvm-project/pull/85394

>From 07e8b31dbe6eaa1a385d52160bf1913c9fa1c17e Mon Sep 17 00:00:00 2001
From: Longsheng Mou 
Date: Fri, 15 Mar 2024 20:50:54 +0800
Subject: [PATCH] [X86_64] fix arg pass error in struct.

In some struct like s67, only one i64 register is used when the structure
parameter is transferred, which is obviously incorrect.So we need
to treat the split case specially.
---
 clang/lib/CodeGen/Targets/X86.cpp |  6 +-
 clang/test/CodeGen/X86/x86_64-arguments.c | 18 ++
 2 files changed, 23 insertions(+), 1 deletion(-)

diff --git a/clang/lib/CodeGen/Targets/X86.cpp 
b/clang/lib/CodeGen/Targets/X86.cpp
index 2291c991fb1107..de0dfe32a54d3a 100644
--- a/clang/lib/CodeGen/Targets/X86.cpp
+++ b/clang/lib/CodeGen/Targets/X86.cpp
@@ -2100,8 +2100,12 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t 
OffsetBase, Class ,
 postMerge(Size, Lo, Hi);
 return;
   }
+
+  bool InMemory = Offset % getContext().getTypeAlign(i->getType()) ||
+  (i->getType()->getAs() &&
+   Offset % getContext().getTypeSize(i->getType()));
   // Note, skip this test for bit-fields, see below.
-  if (!BitField && Offset % getContext().getTypeAlign(i->getType())) {
+  if (!BitField && InMemory) {
 Lo = Memory;
 postMerge(Size, Lo, Hi);
 return;
diff --git a/clang/test/CodeGen/X86/x86_64-arguments.c 
b/clang/test/CodeGen/X86/x86_64-arguments.c
index cf5636cfd518b6..82845f0a2b31fd 100644
--- a/clang/test/CodeGen/X86/x86_64-arguments.c
+++ b/clang/test/CodeGen/X86/x86_64-arguments.c
@@ -533,6 +533,24 @@ typedef float t66 __attribute__((__vector_size__(128), 
__aligned__(128)));
 void f66(t66 a0) {
 }
 
+typedef long long t67 __attribute__((aligned (4)));
+struct s67 {
+  int a;
+  t67 b;
+};
+// CHECK-LABEL: define{{.*}} void @f67(ptr noundef byval(%struct.s67) align 8 
%x)
+void f67(struct s67 x) {
+}
+
+typedef double t68 __attribute__((aligned (4)));
+struct s68 {
+  int a;
+  t68 b;
+};
+// CHECK-LABEL: define{{.*}} void @f68(ptr noundef byval(%struct.s68) align 8 
%x)
+void f68(struct s68 x) {
+}
+
 /// The synthesized __va_list_tag does not have file/line fields.
 // CHECK:  = distinct !DICompositeType(tag: DW_TAG_structure_type, name: 
"__va_list_tag",
 // CHECK-NOT:  file:

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


[clang] [X86_64] fix arg pass error in struct. (PR #85394)

2024-03-22 Thread Longsheng Mou via cfe-commits

https://github.com/CoTinker updated 
https://github.com/llvm/llvm-project/pull/85394

>From 57cdbcab4ad13441a3f8731c4cdedc51acfbc7b1 Mon Sep 17 00:00:00 2001
From: Longsheng Mou 
Date: Fri, 15 Mar 2024 20:50:54 +0800
Subject: [PATCH] [X86_64] fix arg pass error in struct.

typedef long long ll __attribute__((aligned (4)));
struct S {
  int a;
  ll b;
};

when classify:
a: Lo = Integer, Hi = NoClass
b: Lo = Integer, Hi = NoClass
struct S: Lo = Integer, Hi = NoClass

In this case, only one i64 register is used when the structure
parameter is transferred, which is obviously incorrect.So we need
to treat the split case specially.
---
 clang/lib/CodeGen/Targets/X86.cpp |  6 +-
 clang/test/CodeGen/X86/x86_64-arguments.c | 18 ++
 2 files changed, 23 insertions(+), 1 deletion(-)

diff --git a/clang/lib/CodeGen/Targets/X86.cpp 
b/clang/lib/CodeGen/Targets/X86.cpp
index 2291c991fb1107..de0dfe32a54d3a 100644
--- a/clang/lib/CodeGen/Targets/X86.cpp
+++ b/clang/lib/CodeGen/Targets/X86.cpp
@@ -2100,8 +2100,12 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t 
OffsetBase, Class ,
 postMerge(Size, Lo, Hi);
 return;
   }
+
+  bool InMemory = Offset % getContext().getTypeAlign(i->getType()) ||
+  (i->getType()->getAs() &&
+   Offset % getContext().getTypeSize(i->getType()));
   // Note, skip this test for bit-fields, see below.
-  if (!BitField && Offset % getContext().getTypeAlign(i->getType())) {
+  if (!BitField && InMemory) {
 Lo = Memory;
 postMerge(Size, Lo, Hi);
 return;
diff --git a/clang/test/CodeGen/X86/x86_64-arguments.c 
b/clang/test/CodeGen/X86/x86_64-arguments.c
index cf5636cfd518b6..82845f0a2b31fd 100644
--- a/clang/test/CodeGen/X86/x86_64-arguments.c
+++ b/clang/test/CodeGen/X86/x86_64-arguments.c
@@ -533,6 +533,24 @@ typedef float t66 __attribute__((__vector_size__(128), 
__aligned__(128)));
 void f66(t66 a0) {
 }
 
+typedef long long t67 __attribute__((aligned (4)));
+struct s67 {
+  int a;
+  t67 b;
+};
+// CHECK-LABEL: define{{.*}} void @f67(ptr noundef byval(%struct.s67) align 8 
%x)
+void f67(struct s67 x) {
+}
+
+typedef double t68 __attribute__((aligned (4)));
+struct s68 {
+  int a;
+  t68 b;
+};
+// CHECK-LABEL: define{{.*}} void @f68(ptr noundef byval(%struct.s68) align 8 
%x)
+void f68(struct s68 x) {
+}
+
 /// The synthesized __va_list_tag does not have file/line fields.
 // CHECK:  = distinct !DICompositeType(tag: DW_TAG_structure_type, name: 
"__va_list_tag",
 // CHECK-NOT:  file:

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


[clang] [X86_32] Teach X86_32 va_arg to ignore empty structs. (PR #86075)

2024-03-21 Thread Longsheng Mou via cfe-commits


@@ -1069,6 +1069,10 @@ Address X86_32ABIInfo::EmitVAArg(CodeGenFunction ,
 
   auto TypeInfo = getContext().getTypeInfoInChars(Ty);
 
+  // Empty records are ignored for parameter passing purposes on non-Windows.
+  if (!IsWin32StructABI && isEmptyRecord(getContext(), Ty, true))
+return CGF.CreateMemTemp(Ty);

CoTinker wrote:

classifyArgumentType in X86_32 need CCState parameter, but we can not get it in 
this scope, because the CCState is temporarily calculated in 
X86_32ABIInfo::computeInfo.

https://github.com/llvm/llvm-project/pull/86075
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [X86_64] fix arg pass error in struct. (PR #85394)

2024-03-20 Thread Longsheng Mou via cfe-commits

CoTinker wrote:

Which is more appropriate to pass this structure through, memory or register?

https://github.com/llvm/llvm-project/pull/85394
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [X86_32] Teach X86_32 va_arg to ignore empty structs. (PR #86075)

2024-03-20 Thread Longsheng Mou via cfe-commits

https://github.com/CoTinker created 
https://github.com/llvm/llvm-project/pull/86075

Empty structs are ignored for parameter passing purposes, but va_arg was 
incrementing the pointer anyway for that the size of empty struct in c++ is 1 
byte, which could lead to va_list getting out of sync. Fix #86057.

>From 944259ba90fc13c04b6bbd44ec1737fbbb56b2d1 Mon Sep 17 00:00:00 2001
From: Longsheng Mou 
Date: Thu, 21 Mar 2024 11:23:56 +0800
Subject: [PATCH] [X86_32] Teach X86_32 va_arg to ignore empty structs.

Empty structs are ignored for parameter passing purposes, but va_arg was
incrementing the pointer anyway for that the size of empty struct in c++
is 1 byte, which could lead to va_list getting out of sync.
---
 clang/lib/CodeGen/Targets/X86.cpp  |  4 
 clang/test/CodeGenCXX/x86_32-vaarg.cpp | 20 
 2 files changed, 24 insertions(+)
 create mode 100644 clang/test/CodeGenCXX/x86_32-vaarg.cpp

diff --git a/clang/lib/CodeGen/Targets/X86.cpp 
b/clang/lib/CodeGen/Targets/X86.cpp
index 1ec0f159ebcb8a..7931f56ad6835f 100644
--- a/clang/lib/CodeGen/Targets/X86.cpp
+++ b/clang/lib/CodeGen/Targets/X86.cpp
@@ -1069,6 +1069,10 @@ Address X86_32ABIInfo::EmitVAArg(CodeGenFunction ,
 
   auto TypeInfo = getContext().getTypeInfoInChars(Ty);
 
+  // Empty records are ignored for parameter passing purposes on non-Windows.
+  if (!IsWin32StructABI && isEmptyRecord(getContext(), Ty, true))
+return CGF.CreateMemTemp(Ty);
+
   // x86-32 changes the alignment of certain arguments on the stack.
   //
   // Just messing with TypeInfo like this works because we never pass
diff --git a/clang/test/CodeGenCXX/x86_32-vaarg.cpp 
b/clang/test/CodeGenCXX/x86_32-vaarg.cpp
new file mode 100644
index 00..23eac1164118c6
--- /dev/null
+++ b/clang/test/CodeGenCXX/x86_32-vaarg.cpp
@@ -0,0 +1,20 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
+// RUN: %clang_cc1 -triple i386-linux-gnu -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple i386-linux-gnu -emit-llvm -x c -o - %s | FileCheck 
%s
+
+typedef struct {} empty;
+
+// CHECK-LABEL: @{{.*}}empty_record_test
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:[[RESULT_PTR:%.*]] = alloca ptr, align 4
+// CHECK-NEXT:[[Z_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[LIST:%.*]] = alloca ptr, align 4
+// CHECK-NEXT:[[TMP:%.*]] = alloca [[STRUCT_EMPTY:%.*]], align 1
+// CHECK-NEXT:store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4
+// CHECK-NEXT:store i32 [[Z:%.*]], ptr [[Z_ADDR]], align 4
+// CHECK-NEXT:call void @llvm.va_start(ptr [[LIST]])
+empty empty_record_test(int z, ...) {
+  __builtin_va_list list;
+  __builtin_va_start(list, z);
+  return __builtin_va_arg(list, empty);
+}

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


[clang] [X86_64] fix arg pass error in struct. (PR #85394)

2024-03-19 Thread Longsheng Mou via cfe-commits

CoTinker wrote:

Thanks, I'll modify it according to this.

https://github.com/llvm/llvm-project/pull/85394
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [X86_64] fix arg pass error in struct. (PR #85394)

2024-03-19 Thread Longsheng Mou via cfe-commits

https://github.com/CoTinker updated 
https://github.com/llvm/llvm-project/pull/85394

>From d344d20883a73ef1d273a4b74eb1b5df2893041e Mon Sep 17 00:00:00 2001
From: Longsheng Mou 
Date: Fri, 15 Mar 2024 20:50:54 +0800
Subject: [PATCH] [X86_64] fix arg pass error in struct.

typedef long long ll __attribute__((aligned (4)));
struct S {
  int a;
  ll b;
};

when classify:
a: Lo = Integer, Hi = NoClass
b: Lo = Integer, Hi = NoClass
struct S: Lo = Integer, Hi = NoClass

In this case, only one i64 register is used when the structure
parameter is transferred, which is obviously incorrect.So we need
to treat the split case specially.
---
 clang/lib/CodeGen/Targets/X86.cpp |  6 ++
 clang/test/CodeGen/X86/x86_64-arguments.c | 18 ++
 2 files changed, 24 insertions(+)

diff --git a/clang/lib/CodeGen/Targets/X86.cpp 
b/clang/lib/CodeGen/Targets/X86.cpp
index 2291c991fb1107..d91911ece69683 100644
--- a/clang/lib/CodeGen/Targets/X86.cpp
+++ b/clang/lib/CodeGen/Targets/X86.cpp
@@ -1787,6 +1787,8 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t 
OffsetBase, Class ,
   Lo = Hi = NoClass;
 
   Class  = OffsetBase < 64 ? Lo : Hi;
+  bool IsSplit =
+  OffsetBase < 64 && (OffsetBase + getContext().getTypeSize(Ty)) > 64;
   Current = Memory;
 
   if (const BuiltinType *BT = Ty->getAs()) {
@@ -1798,9 +1800,13 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t 
OffsetBase, Class ,
   Lo = Integer;
   Hi = Integer;
 } else if (k >= BuiltinType::Bool && k <= BuiltinType::LongLong) {
+  if (IsSplit)
+return;
   Current = Integer;
 } else if (k == BuiltinType::Float || k == BuiltinType::Double ||
k == BuiltinType::Float16 || k == BuiltinType::BFloat16) {
+  if (IsSplit)
+return;
   Current = SSE;
 } else if (k == BuiltinType::Float128) {
   Lo = SSE;
diff --git a/clang/test/CodeGen/X86/x86_64-arguments.c 
b/clang/test/CodeGen/X86/x86_64-arguments.c
index cf5636cfd518b6..82845f0a2b31fd 100644
--- a/clang/test/CodeGen/X86/x86_64-arguments.c
+++ b/clang/test/CodeGen/X86/x86_64-arguments.c
@@ -533,6 +533,24 @@ typedef float t66 __attribute__((__vector_size__(128), 
__aligned__(128)));
 void f66(t66 a0) {
 }
 
+typedef long long t67 __attribute__((aligned (4)));
+struct s67 {
+  int a;
+  t67 b;
+};
+// CHECK-LABEL: define{{.*}} void @f67(ptr noundef byval(%struct.s67) align 8 
%x)
+void f67(struct s67 x) {
+}
+
+typedef double t68 __attribute__((aligned (4)));
+struct s68 {
+  int a;
+  t68 b;
+};
+// CHECK-LABEL: define{{.*}} void @f68(ptr noundef byval(%struct.s68) align 8 
%x)
+void f68(struct s68 x) {
+}
+
 /// The synthesized __va_list_tag does not have file/line fields.
 // CHECK:  = distinct !DICompositeType(tag: DW_TAG_structure_type, name: 
"__va_list_tag",
 // CHECK-NOT:  file:

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


[clang] [X86_64] fix empty structure vaarg in c++ (PR #77907)

2024-03-19 Thread Longsheng Mou via cfe-commits

CoTinker wrote:

ping~

https://github.com/llvm/llvm-project/pull/77907
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [X86_64] fix arg pass error in struct. (PR #85394)

2024-03-18 Thread Longsheng Mou via cfe-commits

https://github.com/CoTinker updated 
https://github.com/llvm/llvm-project/pull/85394

>From 57760b2bfe87c689030975d5914393fd29d7d1f5 Mon Sep 17 00:00:00 2001
From: Longsheng Mou 
Date: Fri, 15 Mar 2024 20:50:54 +0800
Subject: [PATCH] [X86_64] fix arg pass error in struct.

typedef long long ll __attribute__((aligned (4)));
struct S {
  int a;
  ll b;
};

when classify:
a: Lo = Integer, Hi = NoClass
b: Lo = Integer, Hi = NoClass
struct S: Lo = Integer, Hi = NoClass

In this case, only one i64 register is used when the structure
parameter is transferred, which is obviously incorrect.So we need
to treat the split case specially.
---
 clang/lib/CodeGen/Targets/X86.cpp |  6 ++
 clang/test/CodeGen/X86/x86_64-arguments.c | 18 ++
 2 files changed, 24 insertions(+)

diff --git a/clang/lib/CodeGen/Targets/X86.cpp 
b/clang/lib/CodeGen/Targets/X86.cpp
index 2291c991fb1107..c3e32e5ed63a97 100644
--- a/clang/lib/CodeGen/Targets/X86.cpp
+++ b/clang/lib/CodeGen/Targets/X86.cpp
@@ -1787,6 +1787,8 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t 
OffsetBase, Class ,
   Lo = Hi = NoClass;
 
   Class  = OffsetBase < 64 ? Lo : Hi;
+  bool IsSplit =
+  OffsetBase < 64 && (OffsetBase + getContext().getTypeSize(Ty)) > 64;
   Current = Memory;
 
   if (const BuiltinType *BT = Ty->getAs()) {
@@ -1799,9 +1801,13 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t 
OffsetBase, Class ,
   Hi = Integer;
 } else if (k >= BuiltinType::Bool && k <= BuiltinType::LongLong) {
   Current = Integer;
+  if (IsSplit)
+Hi = Integer;
 } else if (k == BuiltinType::Float || k == BuiltinType::Double ||
k == BuiltinType::Float16 || k == BuiltinType::BFloat16) {
   Current = SSE;
+  if (IsSplit)
+Hi = SSE;
 } else if (k == BuiltinType::Float128) {
   Lo = SSE;
   Hi = SSEUp;
diff --git a/clang/test/CodeGen/X86/x86_64-arguments.c 
b/clang/test/CodeGen/X86/x86_64-arguments.c
index cf5636cfd518b6..92b0192658a555 100644
--- a/clang/test/CodeGen/X86/x86_64-arguments.c
+++ b/clang/test/CodeGen/X86/x86_64-arguments.c
@@ -533,6 +533,24 @@ typedef float t66 __attribute__((__vector_size__(128), 
__aligned__(128)));
 void f66(t66 a0) {
 }
 
+typedef long long t67 __attribute__((aligned (4)));
+struct s67 {
+  int a;
+  t67 b;
+};
+// CHECK-LABEL: define{{.*}} void @f67(i64 %x.coerce0, i32 %x.coerce1)
+void f67(struct s67 x) {
+}
+
+typedef double t68 __attribute__((aligned (4)));
+struct s68 {
+  int a;
+  t68 b;
+};
+// CHECK-LABEL: define{{.*}} void @f68(i64 %x.coerce0, double %x.coerce1)
+void f68(struct s68 x) {
+}
+
 /// The synthesized __va_list_tag does not have file/line fields.
 // CHECK:  = distinct !DICompositeType(tag: DW_TAG_structure_type, name: 
"__va_list_tag",
 // CHECK-NOT:  file:

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


[clang] [X86_64] fix arg pass error in struct. (PR #85394)

2024-03-17 Thread Longsheng Mou via cfe-commits

https://github.com/CoTinker updated 
https://github.com/llvm/llvm-project/pull/85394

>From 1ca19591fa11a53559fdfe7e4bf6b298b7658628 Mon Sep 17 00:00:00 2001
From: Longsheng Mou 
Date: Fri, 15 Mar 2024 20:50:54 +0800
Subject: [PATCH] [X86_64] fix arg pass error in struct.

typedef long long alignll __attribute__((aligned (4)));
struct S {
  int a;
  alignll b;
};

when classify:
a: Lo = Integer, Hi = NoClass
b: Lo = Integer, Hi = NoClass
struct S: Lo = Integer, Hi = NoClass

In this case, only one i64 register is used when the structure
parameter is transferred, which is obviously incorrect.So we need
to treat the split case specially.
---
 clang/lib/CodeGen/Targets/X86.cpp |  6 ++
 clang/test/CodeGen/X86/x86_64-arguments.c | 18 ++
 2 files changed, 24 insertions(+)

diff --git a/clang/lib/CodeGen/Targets/X86.cpp 
b/clang/lib/CodeGen/Targets/X86.cpp
index 2291c991fb1107..c3e32e5ed63a97 100644
--- a/clang/lib/CodeGen/Targets/X86.cpp
+++ b/clang/lib/CodeGen/Targets/X86.cpp
@@ -1787,6 +1787,8 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t 
OffsetBase, Class ,
   Lo = Hi = NoClass;
 
   Class  = OffsetBase < 64 ? Lo : Hi;
+  bool IsSplit =
+  OffsetBase < 64 && (OffsetBase + getContext().getTypeSize(Ty)) > 64;
   Current = Memory;
 
   if (const BuiltinType *BT = Ty->getAs()) {
@@ -1799,9 +1801,13 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t 
OffsetBase, Class ,
   Hi = Integer;
 } else if (k >= BuiltinType::Bool && k <= BuiltinType::LongLong) {
   Current = Integer;
+  if (IsSplit)
+Hi = Integer;
 } else if (k == BuiltinType::Float || k == BuiltinType::Double ||
k == BuiltinType::Float16 || k == BuiltinType::BFloat16) {
   Current = SSE;
+  if (IsSplit)
+Hi = SSE;
 } else if (k == BuiltinType::Float128) {
   Lo = SSE;
   Hi = SSEUp;
diff --git a/clang/test/CodeGen/X86/x86_64-arguments.c 
b/clang/test/CodeGen/X86/x86_64-arguments.c
index cf5636cfd518b6..92b0192658a555 100644
--- a/clang/test/CodeGen/X86/x86_64-arguments.c
+++ b/clang/test/CodeGen/X86/x86_64-arguments.c
@@ -533,6 +533,24 @@ typedef float t66 __attribute__((__vector_size__(128), 
__aligned__(128)));
 void f66(t66 a0) {
 }
 
+typedef long long t67 __attribute__((aligned (4)));
+struct s67 {
+  int a;
+  t67 b;
+};
+// CHECK-LABEL: define{{.*}} void @f67(i64 %x.coerce0, i32 %x.coerce1)
+void f67(struct s67 x) {
+}
+
+typedef double t68 __attribute__((aligned (4)));
+struct s68 {
+  int a;
+  t68 b;
+};
+// CHECK-LABEL: define{{.*}} void @f68(i64 %x.coerce0, double %x.coerce1)
+void f68(struct s68 x) {
+}
+
 /// The synthesized __va_list_tag does not have file/line fields.
 // CHECK:  = distinct !DICompositeType(tag: DW_TAG_structure_type, name: 
"__va_list_tag",
 // CHECK-NOT:  file:

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


[clang] [X86_64] fix arg pass error in struct. (PR #85394)

2024-03-15 Thread Longsheng Mou via cfe-commits

https://github.com/CoTinker updated 
https://github.com/llvm/llvm-project/pull/85394

>From be6b4bdd75554b9287092ab42063a9d4e260dd9c Mon Sep 17 00:00:00 2001
From: Longsheng Mou 
Date: Fri, 15 Mar 2024 20:50:54 +0800
Subject: [PATCH] [X86_64] fix arg pass error in struct.

typedef long long alignll __attribute__((aligned (4)));
struct S {
  int a;
  alignll b;
};

When classify:
a: Lo = Integer, Hi = NoClass
b: Lo = Integer, Hi = NoClass
struct S: Lo = Integer, Hi = NoClass

In this case, only one i64 register is used when the structure
parameter is transferred, which is obviously incorrect.So we need
to treat the split case specially.
---
 clang/lib/CodeGen/Targets/X86.cpp |  6 ++
 clang/test/CodeGen/X86/x86_64-arguments.c | 18 ++
 2 files changed, 24 insertions(+)

diff --git a/clang/lib/CodeGen/Targets/X86.cpp 
b/clang/lib/CodeGen/Targets/X86.cpp
index 2291c991fb1107..c3e32e5ed63a97 100644
--- a/clang/lib/CodeGen/Targets/X86.cpp
+++ b/clang/lib/CodeGen/Targets/X86.cpp
@@ -1787,6 +1787,8 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t 
OffsetBase, Class ,
   Lo = Hi = NoClass;
 
   Class  = OffsetBase < 64 ? Lo : Hi;
+  bool IsSplit =
+  OffsetBase < 64 && (OffsetBase + getContext().getTypeSize(Ty)) > 64;
   Current = Memory;
 
   if (const BuiltinType *BT = Ty->getAs()) {
@@ -1799,9 +1801,13 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t 
OffsetBase, Class ,
   Hi = Integer;
 } else if (k >= BuiltinType::Bool && k <= BuiltinType::LongLong) {
   Current = Integer;
+  if (IsSplit)
+Hi = Integer;
 } else if (k == BuiltinType::Float || k == BuiltinType::Double ||
k == BuiltinType::Float16 || k == BuiltinType::BFloat16) {
   Current = SSE;
+  if (IsSplit)
+Hi = SSE;
 } else if (k == BuiltinType::Float128) {
   Lo = SSE;
   Hi = SSEUp;
diff --git a/clang/test/CodeGen/X86/x86_64-arguments.c 
b/clang/test/CodeGen/X86/x86_64-arguments.c
index cf5636cfd518b6..92b0192658a555 100644
--- a/clang/test/CodeGen/X86/x86_64-arguments.c
+++ b/clang/test/CodeGen/X86/x86_64-arguments.c
@@ -533,6 +533,24 @@ typedef float t66 __attribute__((__vector_size__(128), 
__aligned__(128)));
 void f66(t66 a0) {
 }
 
+typedef long long t67 __attribute__((aligned (4)));
+struct s67 {
+  int a;
+  t67 b;
+};
+// CHECK-LABEL: define{{.*}} void @f67(i64 %x.coerce0, i32 %x.coerce1)
+void f67(struct s67 x) {
+}
+
+typedef double t68 __attribute__((aligned (4)));
+struct s68 {
+  int a;
+  t68 b;
+};
+// CHECK-LABEL: define{{.*}} void @f68(i64 %x.coerce0, double %x.coerce1)
+void f68(struct s68 x) {
+}
+
 /// The synthesized __va_list_tag does not have file/line fields.
 // CHECK:  = distinct !DICompositeType(tag: DW_TAG_structure_type, name: 
"__va_list_tag",
 // CHECK-NOT:  file:

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


[clang] [X86_64] fix arg pass error in struct. (PR #85394)

2024-03-15 Thread Longsheng Mou via cfe-commits

https://github.com/CoTinker edited 
https://github.com/llvm/llvm-project/pull/85394
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [X86_64] fix arg pass error in struct. (PR #85394)

2024-03-15 Thread Longsheng Mou via cfe-commits

https://github.com/CoTinker edited 
https://github.com/llvm/llvm-project/pull/85394
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [X86_64] fix arg pass error in struct. (PR #85394)

2024-03-15 Thread Longsheng Mou via cfe-commits

https://github.com/CoTinker updated 
https://github.com/llvm/llvm-project/pull/85394

>From b31780cba73ea39bf7f630a059a554914d804446 Mon Sep 17 00:00:00 2001
From: Longsheng Mou 
Date: Fri, 15 Mar 2024 20:50:54 +0800
Subject: [PATCH] [X86_64] fix arg pass error in struct.

typedef long long Alignll __attribute__((aligned (4)));
struct S {
  int a;
  Alignll b;
};

When classify:
a: Lo = Integer, Hi = NoClass
b: Lo = Integer, Hi = NoClass
struct S: Lo = Integer, Hi = NoClass

In this case, only one i64 register is used when the structure
parameter is transferred, which is obviously incorrect.So we need
to treat the split case specially.
---
 clang/lib/CodeGen/Targets/X86.cpp |  6 ++
 clang/test/CodeGen/X86/x86_64-arguments.c | 18 ++
 2 files changed, 24 insertions(+)

diff --git a/clang/lib/CodeGen/Targets/X86.cpp 
b/clang/lib/CodeGen/Targets/X86.cpp
index 2291c991fb1107..c3e32e5ed63a97 100644
--- a/clang/lib/CodeGen/Targets/X86.cpp
+++ b/clang/lib/CodeGen/Targets/X86.cpp
@@ -1787,6 +1787,8 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t 
OffsetBase, Class ,
   Lo = Hi = NoClass;
 
   Class  = OffsetBase < 64 ? Lo : Hi;
+  bool IsSplit =
+  OffsetBase < 64 && (OffsetBase + getContext().getTypeSize(Ty)) > 64;
   Current = Memory;
 
   if (const BuiltinType *BT = Ty->getAs()) {
@@ -1799,9 +1801,13 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t 
OffsetBase, Class ,
   Hi = Integer;
 } else if (k >= BuiltinType::Bool && k <= BuiltinType::LongLong) {
   Current = Integer;
+  if (IsSplit)
+Hi = Integer;
 } else if (k == BuiltinType::Float || k == BuiltinType::Double ||
k == BuiltinType::Float16 || k == BuiltinType::BFloat16) {
   Current = SSE;
+  if (IsSplit)
+Hi = SSE;
 } else if (k == BuiltinType::Float128) {
   Lo = SSE;
   Hi = SSEUp;
diff --git a/clang/test/CodeGen/X86/x86_64-arguments.c 
b/clang/test/CodeGen/X86/x86_64-arguments.c
index cf5636cfd518b6..92b0192658a555 100644
--- a/clang/test/CodeGen/X86/x86_64-arguments.c
+++ b/clang/test/CodeGen/X86/x86_64-arguments.c
@@ -533,6 +533,24 @@ typedef float t66 __attribute__((__vector_size__(128), 
__aligned__(128)));
 void f66(t66 a0) {
 }
 
+typedef long long t67 __attribute__((aligned (4)));
+struct s67 {
+  int a;
+  t67 b;
+};
+// CHECK-LABEL: define{{.*}} void @f67(i64 %x.coerce0, i32 %x.coerce1)
+void f67(struct s67 x) {
+}
+
+typedef double t68 __attribute__((aligned (4)));
+struct s68 {
+  int a;
+  t68 b;
+};
+// CHECK-LABEL: define{{.*}} void @f68(i64 %x.coerce0, double %x.coerce1)
+void f68(struct s68 x) {
+}
+
 /// The synthesized __va_list_tag does not have file/line fields.
 // CHECK:  = distinct !DICompositeType(tag: DW_TAG_structure_type, name: 
"__va_list_tag",
 // CHECK-NOT:  file:

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


[clang] [X86_64] fix arg pass error in struct. (PR #85394)

2024-03-15 Thread Longsheng Mou via cfe-commits

https://github.com/CoTinker edited 
https://github.com/llvm/llvm-project/pull/85394
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [X86_64] fix arg pass error in struct. (PR #85394)

2024-03-15 Thread Longsheng Mou via cfe-commits

https://github.com/CoTinker updated 
https://github.com/llvm/llvm-project/pull/85394

>From 30d8d0490b383b8b52fee7d8ddd591f8ed5b585e Mon Sep 17 00:00:00 2001
From: Longsheng Mou 
Date: Fri, 15 Mar 2024 20:50:54 +0800
Subject: [PATCH] [X86_64] fix arg pass error in struct.

typedef long long Alignll __attribute__((align (4)));
struct S {
  int a;
  Alignll b;
};

When classify:
a: Lo = Integer, Hi = NoClass
b: Lo = Integer, Hi = NoClass
struct S: Lo = Integer, Hi = NoClass

In this case, only one i64 register is used when the structure
parameter is transferred, which is obviously incorrect.So we need
to treat the split case specially.
---
 clang/lib/CodeGen/Targets/X86.cpp |  6 ++
 clang/test/CodeGen/X86/x86_64-arguments.c | 18 ++
 2 files changed, 24 insertions(+)

diff --git a/clang/lib/CodeGen/Targets/X86.cpp 
b/clang/lib/CodeGen/Targets/X86.cpp
index 2291c991fb1107..c3e32e5ed63a97 100644
--- a/clang/lib/CodeGen/Targets/X86.cpp
+++ b/clang/lib/CodeGen/Targets/X86.cpp
@@ -1787,6 +1787,8 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t 
OffsetBase, Class ,
   Lo = Hi = NoClass;
 
   Class  = OffsetBase < 64 ? Lo : Hi;
+  bool IsSplit =
+  OffsetBase < 64 && (OffsetBase + getContext().getTypeSize(Ty)) > 64;
   Current = Memory;
 
   if (const BuiltinType *BT = Ty->getAs()) {
@@ -1799,9 +1801,13 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t 
OffsetBase, Class ,
   Hi = Integer;
 } else if (k >= BuiltinType::Bool && k <= BuiltinType::LongLong) {
   Current = Integer;
+  if (IsSplit)
+Hi = Integer;
 } else if (k == BuiltinType::Float || k == BuiltinType::Double ||
k == BuiltinType::Float16 || k == BuiltinType::BFloat16) {
   Current = SSE;
+  if (IsSplit)
+Hi = SSE;
 } else if (k == BuiltinType::Float128) {
   Lo = SSE;
   Hi = SSEUp;
diff --git a/clang/test/CodeGen/X86/x86_64-arguments.c 
b/clang/test/CodeGen/X86/x86_64-arguments.c
index cf5636cfd518b6..c8a215989cf9fc 100644
--- a/clang/test/CodeGen/X86/x86_64-arguments.c
+++ b/clang/test/CodeGen/X86/x86_64-arguments.c
@@ -533,6 +533,24 @@ typedef float t66 __attribute__((__vector_size__(128), 
__aligned__(128)));
 void f66(t66 a0) {
 }
 
+typedef long long t67 __attribute__((align (4)));
+struct s67 {
+  int a;
+  t67 b;
+};
+// CHECK-LABEL: define{{.*}} void @f67(i64 %x.coerce0, i32 %x.coerce1)
+void f67(struct s67 x) {
+}
+
+typedef double t68 __attribute__((align (4)));
+struct s68 {
+  int a;
+  t68 b;
+};
+// CHECK-LABEL: define{{.*}} void @f68(i64 %x.coerce0, double %x.coerce1)
+void f68(struct s68 x) {
+}
+
 /// The synthesized __va_list_tag does not have file/line fields.
 // CHECK:  = distinct !DICompositeType(tag: DW_TAG_structure_type, name: 
"__va_list_tag",
 // CHECK-NOT:  file:

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


[clang] [X86_64] fix arg pass error in struct. (PR #85394)

2024-03-15 Thread Longsheng Mou via cfe-commits

https://github.com/CoTinker edited 
https://github.com/llvm/llvm-project/pull/85394
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [X86_64] fix arg pass error in struct. (PR #85394)

2024-03-15 Thread Longsheng Mou via cfe-commits

https://github.com/CoTinker edited 
https://github.com/llvm/llvm-project/pull/85394
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [X86_64] fix arg pass error in struct. (PR #85394)

2024-03-15 Thread Longsheng Mou via cfe-commits

https://github.com/CoTinker created 
https://github.com/llvm/llvm-project/pull/85394

typedef long long Alignll __attribute__((align (4))); struct S {
  int a;
  Alignll b;
};

When classify:
a: Lo = Integer, Hi = NoClass
b: Lo = Integer, Hi = NoClass
struct S: Lo = Integer, Hi = NoClass

In this case, only one i64 register is used when the structure parameter is 
transferred, which is obviously incorrect.So we need to treat the split case 
specially. fix #85387.

>From 8efa87d7b03ebf2cf304e97c5fcebdb4211350b4 Mon Sep 17 00:00:00 2001
From: Longsheng Mou 
Date: Fri, 15 Mar 2024 20:50:54 +0800
Subject: [PATCH] [X86_64] fix arg pass error in struct.

typedef long long Alignll __attribute__((align (4)));
struct S {
  int a;
  Alignll b;
};

When classify:
a: Lo = Integer, Hi = NoClass
b: Lo = Integer, Hi = NoClass
struct S: Lo = Integer, Hi = NoClass

In this case, only one i64 register is used when the structure
parameter is transferred, which is obviously incorrect.So we need
to treat the split case specially.
---
 clang/lib/CodeGen/Targets/X86.cpp |  5 +
 clang/test/CodeGen/X86/x86_64-arguments.c | 18 ++
 2 files changed, 23 insertions(+)

diff --git a/clang/lib/CodeGen/Targets/X86.cpp 
b/clang/lib/CodeGen/Targets/X86.cpp
index 2291c991fb1107..1a02d94a8eb530 100644
--- a/clang/lib/CodeGen/Targets/X86.cpp
+++ b/clang/lib/CodeGen/Targets/X86.cpp
@@ -1787,6 +1787,7 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t 
OffsetBase, Class ,
   Lo = Hi = NoClass;
 
   Class  = OffsetBase < 64 ? Lo : Hi;
+  bool IsSplit = OffsetBase < 64 && (OffsetBase + 
getContext().getTypeSize(Ty)) > 64;
   Current = Memory;
 
   if (const BuiltinType *BT = Ty->getAs()) {
@@ -1799,9 +1800,13 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t 
OffsetBase, Class ,
   Hi = Integer;
 } else if (k >= BuiltinType::Bool && k <= BuiltinType::LongLong) {
   Current = Integer;
+  if (IsSplit)
+Hi = Integer;
 } else if (k == BuiltinType::Float || k == BuiltinType::Double ||
k == BuiltinType::Float16 || k == BuiltinType::BFloat16) {
   Current = SSE;
+  if (IsSplit)
+Hi = SSE;
 } else if (k == BuiltinType::Float128) {
   Lo = SSE;
   Hi = SSEUp;
diff --git a/clang/test/CodeGen/X86/x86_64-arguments.c 
b/clang/test/CodeGen/X86/x86_64-arguments.c
index cf5636cfd518b6..c8a215989cf9fc 100644
--- a/clang/test/CodeGen/X86/x86_64-arguments.c
+++ b/clang/test/CodeGen/X86/x86_64-arguments.c
@@ -533,6 +533,24 @@ typedef float t66 __attribute__((__vector_size__(128), 
__aligned__(128)));
 void f66(t66 a0) {
 }
 
+typedef long long t67 __attribute__((align (4)));
+struct s67 {
+  int a;
+  t67 b;
+};
+// CHECK-LABEL: define{{.*}} void @f67(i64 %x.coerce0, i32 %x.coerce1)
+void f67(struct s67 x) {
+}
+
+typedef double t68 __attribute__((align (4)));
+struct s68 {
+  int a;
+  t68 b;
+};
+// CHECK-LABEL: define{{.*}} void @f68(i64 %x.coerce0, double %x.coerce1)
+void f68(struct s68 x) {
+}
+
 /// The synthesized __va_list_tag does not have file/line fields.
 // CHECK:  = distinct !DICompositeType(tag: DW_TAG_structure_type, name: 
"__va_list_tag",
 // CHECK-NOT:  file:

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


[clang] [X86_64] fix empty structure vaarg in c++ (PR #77907)

2024-03-05 Thread Longsheng Mou via cfe-commits


@@ -3014,6 +3014,16 @@ Address X86_64ABIInfo::EmitVAArg(CodeGenFunction , 
Address VAListAddr,
   ABIArgInfo AI = classifyArgumentType(Ty, 0, neededInt, neededSSE,
/*isNamedArg*/false);
 
+  // Empty records are ignored for parameter passing purposes.
+  if (AI.isIgnore()) {
+CharUnits Align = CGF.getContext().getTypeAlignInChars(Ty);
+VAListAddr = CGF.Builder.CreateStructGEP(VAListAddr, 2);
+llvm::Value *Load = CGF.Builder.CreateLoad(VAListAddr);
+llvm::Value *Offset = llvm::ConstantInt::get(CGF.Int32Ty, 0);
+Load = CGF.Builder.CreateGEP(CGF.Int8Ty, Load, Offset);
+return Address(Load, CGF.ConvertTypeForMem(Ty), Align);

CoTinker wrote:

how to create a temporary?

https://github.com/llvm/llvm-project/pull/77907
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [X86_64] fix empty structure vaarg in c++ (PR #77907)

2024-01-16 Thread Longsheng Mou via cfe-commits

CoTinker wrote:

I've revised it. Can you check it again? @phoebewang 

https://github.com/llvm/llvm-project/pull/77907
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [X86_64] fix empty structure vaarg in c++ (PR #77907)

2024-01-14 Thread Longsheng Mou via cfe-commits

CoTinker wrote:

> I checked it locally, the patch doesn't fix the reported problem:
> 
> ```
> $ clang pr77036.cpp && ./a.out
> -nan
> Fail
> ```

It seems that `struct S14{}` is empty record, but  `struct S14 { union{}a;}` is 
not.

https://github.com/llvm/llvm-project/pull/77907
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [X86_64] fix empty structure vaarg in c++ (PR #77907)

2024-01-14 Thread Longsheng Mou via cfe-commits

CoTinker wrote:

> I checked it locally, the patch doesn't fix the reported problem:
> 
> ```
> $ clang pr77036.cpp && ./a.out
> -nan
> Fail
> ```

isEmptyRecord return false here, I am checking it.

https://github.com/llvm/llvm-project/pull/77907
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [X86_64] fix empty structure vaarg in c++ (PR #77907)

2024-01-13 Thread Longsheng Mou via cfe-commits


@@ -2989,6 +2989,11 @@ static Address EmitX86_64VAArgFromMemory(CodeGenFunction 
,
   // an 8 byte boundary.
 
   uint64_t SizeInBytes = (CGF.getContext().getTypeSize(Ty) + 7) / 8;
+
+  if (isEmptyRecord(CGF.getContext(), Ty, true)) {
+SizeInBytes = 0;
+  }
+

CoTinker wrote:

done

https://github.com/llvm/llvm-project/pull/77907
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits