[clang] [llvm] [SystemZ] Add support for half (fp16) (PR #109164)

2024-09-30 Thread Ulrich Weigand via cfe-commits

uweigand wrote:

I think we should define and implement a proper ABI for the half type as well.

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


[clang] [llvm] [BPF] Do atomic_fetch_*() pattern matching with memory ordering (PR #107343)

2024-09-26 Thread Ulrich Weigand via cfe-commits

uweigand wrote:

Looks like the new test case is failing on SystemZ: 
https://lab.llvm.org/buildbot/#/builders/42/builds/1192
```
struct.error: unpack_from requires a buffer of at least 402653196 bytes for 
unpacking 12 bytes at offset 402653184 (actual buffer size is 479)
```
At first glance, this might be an endian problem (SystemZ is big-endian; 
402653196 is 0x180c).


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


[clang] [SystemZ][z/OS] Implement z/OS XPLINK ABI (PR #101024)

2024-09-19 Thread Ulrich Weigand via cfe-commits


@@ -532,9 +532,371 @@ bool SystemZTargetCodeGenInfo::isVectorTypeBased(const 
Type *Ty,
   return false;
 }
 
+//===--===//
+// z/OS XPLINK ABI Implementation
+//===--===//
+
+namespace {
+
+class ZOSXPLinkABIInfo : public ABIInfo {
+  const unsigned GPRBits = 64;
+  bool HasVector;
+
+public:
+  ZOSXPLinkABIInfo(CodeGenTypes &CGT, bool HV) : ABIInfo(CGT), HasVector(HV) {}
+
+  bool isPromotableIntegerType(QualType Ty) const;
+  bool isVectorArgumentType(QualType Ty) const;
+  bool isFPArgumentType(QualType Ty) const;
+  QualType getSingleElementType(QualType Ty) const;
+  QualType getFPTypeOfComplexLikeType(QualType Ty) const;
+
+  ABIArgInfo classifyReturnType(QualType RetTy) const;
+  ABIArgInfo classifyArgumentType(QualType ArgTy, bool IsNamedArg) const;
+
+  void computeInfo(CGFunctionInfo &FI) const override {
+if (!getCXXABI().classifyReturnType(FI))
+  FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
+
+unsigned NumRequiredArgs = FI.getNumRequiredArgs();
+unsigned ArgNo = 0;
+
+for (auto &I : FI.arguments()) {
+  bool IsNamedArg = ArgNo < NumRequiredArgs;
+  I.info = classifyArgumentType(I.type, IsNamedArg);
+  ++ArgNo;
+}
+  }
+
+  RValue EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty,
+   AggValueSlot Slot) const override;
+};
+
+class ZOSXPLinkTargetCodeGenInfo : public TargetCodeGenInfo {
+public:
+  ZOSXPLinkTargetCodeGenInfo(CodeGenTypes &CGT, bool HasVector)
+  : TargetCodeGenInfo(std::make_unique(CGT, HasVector)) {
+SwiftInfo =
+std::make_unique(CGT, /*SwiftErrorInRegister=*/false);
+  }
+};
+
+} // namespace
+
+// Return true if the ABI requires Ty to be passed sign- or zero-
+// extended to 64 bits.
+bool ZOSXPLinkABIInfo::isPromotableIntegerType(QualType Ty) const {
+  // Treat an enum type as its underlying type.
+  if (const EnumType *EnumTy = Ty->getAs())
+Ty = EnumTy->getDecl()->getIntegerType();
+
+  // Promotable integer types are required to be promoted by the ABI.
+  if (getContext().isPromotableIntegerType(Ty))
+return true;
+
+  if (const auto *EIT = Ty->getAs())
+if (EIT->getNumBits() < 64)
+  return true;
+
+  // In addition to the usual promotable integer types, we also need to
+  // extend all 32-bit types, since the ABI requires promotion to 64 bits.
+  if (const BuiltinType *BT = Ty->getAs())
+switch (BT->getKind()) {
+case BuiltinType::Int:
+case BuiltinType::UInt:
+  return true;
+default:
+  break;
+}
+
+  return false;
+}
+
+bool ZOSXPLinkABIInfo::isVectorArgumentType(QualType Ty) const {
+  return (HasVector && Ty->isVectorType() &&
+  getContext().getTypeSize(Ty) <= 128);
+}
+
+bool ZOSXPLinkABIInfo::isFPArgumentType(QualType Ty) const {
+  if (const BuiltinType *BT = Ty->getAs())
+switch (BT->getKind()) {
+case BuiltinType::Float:
+case BuiltinType::Double:
+case BuiltinType::LongDouble:
+  return true;
+default:
+  return false;
+}
+
+  return false;
+}
+
+QualType ZOSXPLinkABIInfo::getSingleElementType(QualType Ty) const {
+  // Unions just containing a floating point type, e.g. union { float f1, f2; 
};
+  // are treated as a single floating point number. Check if the union only
+  // consists of a single type (handling embedded unions recursively), and
+  // return that type.
+  if (const RecordType *RT = Ty->getAsUnionType()) {
+QualType Found;
+// Check the fields.
+const RecordDecl *RD = RT->getDecl();
+for (const auto *FD : RD->fields()) {
+  if (Found.isNull())
+Found = getSingleElementType(FD->getType());
+  else if (Found != getSingleElementType(FD->getType()))
+return Ty;
+}
+return Found.isNull() ? Ty : Found;
+  }
+
+  const RecordType *RT = Ty->getAs();
+
+  if (RT && RT->isStructureOrClassType()) {
+const RecordDecl *RD = RT->getDecl();
+QualType Found;
+
+// If this is a C++ record, check the bases first.
+if (const CXXRecordDecl *CXXRD = dyn_cast(RD))
+  if (CXXRD->hasDefinition())
+for (const auto &I : CXXRD->bases()) {
+  QualType Base = I.getType();
+
+  // Empty bases don't affect things either way.
+  if (isEmptyRecord(getContext(), Base, true))
+continue;
+
+  if (!Found.isNull())
+return Ty;
+  Found = getSingleElementType(Base);
+}
+
+// Check the fields.
+for (const auto *FD : RD->fields()) {
+  QualType FT = FD->getType();
+
+  // Ignore empty fields.
+  if (isEmptyField(getContext(), FD, true))
+continue;
+
+  if (!Found.isNull())
+return Ty;
+
+  // Treat single element arrays as the element.
+  while (const ConstantArrayType *AT =
+ getContext().getAsConstantArrayType(FT)) {
+if (AT->getZEx

[clang] [llvm] target ABI: improve call parameters extensions handling (PR #100757)

2024-09-19 Thread Ulrich Weigand via cfe-commits

uweigand wrote:

LGTM as well, thanks.

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


[clang] baf9b7d - [SystemZ] Fix codegen for _[u]128 intrinsics

2024-09-19 Thread Ulrich Weigand via cfe-commits

Author: Ulrich Weigand
Date: 2024-09-19T13:19:03+02:00
New Revision: baf9b7da81025c1e3b0704d7ecf667e06f95642b

URL: 
https://github.com/llvm/llvm-project/commit/baf9b7da81025c1e3b0704d7ecf667e06f95642b
DIFF: 
https://github.com/llvm/llvm-project/commit/baf9b7da81025c1e3b0704d7ecf667e06f95642b.diff

LOG: [SystemZ] Fix codegen for _[u]128 intrinsics

PR #74625 introduced a regression in the code generated for the
following set of intrinsic:
  vec_add_u128, vec_addc_u128, vec_adde_u128, vec_addec_u128
  vec_sub_u128, vec_subc_u128, vec_sube_u128, vec_subec_u128
  vec_sum_u128, vec_msum_u128
  vec_gfmsum_128, vec_gfmsum_accum_128

This is because the new code incorrectly assumed that a cast
from "unsigned __int128" to "vector unsigned char" would simply
be a bitcast re-interpretation; instead, this cast actually
truncates the __int128 to char and splats the result.

Fixed by adding an intermediate cast via a single-element
128-bit integer vector.

Fixes: https://github.com/llvm/llvm-project/issues/109113

Added: 
clang/test/CodeGen/SystemZ/builtins-systemz-i128.c

Modified: 
clang/lib/Headers/vecintrin.h

Removed: 




diff  --git a/clang/lib/Headers/vecintrin.h b/clang/lib/Headers/vecintrin.h
index 1f51e32c0d136d..609c7cf0b7a6f9 100644
--- a/clang/lib/Headers/vecintrin.h
+++ b/clang/lib/Headers/vecintrin.h
@@ -8359,7 +8359,9 @@ vec_min(__vector double __a, __vector double __b) {
 
 static inline __ATTRS_ai __vector unsigned char
 vec_add_u128(__vector unsigned char __a, __vector unsigned char __b) {
-  return (__vector unsigned char)((__int128)__a + (__int128)__b);
+  return (__vector unsigned char)
+ (unsigned __int128 __attribute__((__vector_size__(16
+ ((__int128)__a + (__int128)__b);
 }
 
 /*-- vec_addc ---*/
@@ -8389,6 +8391,7 @@ vec_addc(__vector unsigned long long __a, __vector 
unsigned long long __b) {
 static inline __ATTRS_ai __vector unsigned char
 vec_addc_u128(__vector unsigned char __a, __vector unsigned char __b) {
   return (__vector unsigned char)
+ (unsigned __int128 __attribute__((__vector_size__(16
  __builtin_s390_vaccq((unsigned __int128)__a, (unsigned __int128)__b);
 }
 
@@ -8398,6 +8401,7 @@ static inline __ATTRS_ai __vector unsigned char
 vec_adde_u128(__vector unsigned char __a, __vector unsigned char __b,
   __vector unsigned char __c) {
   return (__vector unsigned char)
+ (unsigned __int128 __attribute__((__vector_size__(16
  __builtin_s390_vacq((unsigned __int128)__a, (unsigned __int128)__b,
  (unsigned __int128)__c);
 }
@@ -8408,6 +8412,7 @@ static inline __ATTRS_ai __vector unsigned char
 vec_addec_u128(__vector unsigned char __a, __vector unsigned char __b,
__vector unsigned char __c) {
   return (__vector unsigned char)
+ (unsigned __int128 __attribute__((__vector_size__(16
  __builtin_s390_vacccq((unsigned __int128)__a, (unsigned __int128)__b,
(unsigned __int128)__c);
 }
@@ -8483,7 +8488,9 @@ vec_gfmsum(__vector unsigned int __a, __vector unsigned 
int __b) {
 static inline __ATTRS_o_ai __vector unsigned char
 vec_gfmsum_128(__vector unsigned long long __a,
__vector unsigned long long __b) {
-  return (__vector unsigned char)__builtin_s390_vgfmg(__a, __b);
+  return (__vector unsigned char)
+ (unsigned __int128 __attribute__((__vector_size__(16
+ __builtin_s390_vgfmg(__a, __b);
 }
 
 /*-- vec_gfmsum_accum ---*/
@@ -8513,6 +8520,7 @@ vec_gfmsum_accum_128(__vector unsigned long long __a,
  __vector unsigned long long __b,
  __vector unsigned char __c) {
   return (__vector unsigned char)
+ (unsigned __int128 __attribute__((__vector_size__(16
  __builtin_s390_vgfmag(__a, __b, (unsigned __int128)__c);
 }
 
@@ -8810,6 +8818,7 @@ vec_msum_u128(__vector unsigned long long __a, __vector 
unsigned long long __b,
 
 #define vec_msum_u128(X, Y, Z, W) \
   ((__typeof__((vec_msum_u128)((X), (Y), (Z), (W \
+   (unsigned __int128 __attribute__((__vector_size__(16 \
__builtin_s390_vmslg((X), (Y), (unsigned __int128)(Z), (W)))
 #endif
 
@@ -8817,7 +8826,9 @@ vec_msum_u128(__vector unsigned long long __a, __vector 
unsigned long long __b,
 
 static inline __ATTRS_ai __vector unsigned char
 vec_sub_u128(__vector unsigned char __a, __vector unsigned char __b) {
-  return (__vector unsigned char)((__int128)__a - (__int128)__b);
+  return (__vector unsigned char)
+ (unsigned __int128 __attribute__((__vector_size__(16
+ ((__int128)__a - (__int128)__b);
 }
 
 /*-- vec_subc ---*/
@@ -8847,6 +8858,7 @@ vec_subc(__vector unsigned long long __a, __vec

[clang] [clang][powerpc][wasm][systemz][x86] Replace target vector popcount intrinsics with __builtin_elementwise_popcount (PR #109160)

2024-09-19 Thread Ulrich Weigand via cfe-commits

uweigand wrote:

SystemZ changes LGTM.

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


[clang] [SystemZ][z/OS] Implement z/OS XPLINK ABI (PR #101024)

2024-08-06 Thread Ulrich Weigand via cfe-commits


@@ -532,9 +532,371 @@ bool SystemZTargetCodeGenInfo::isVectorTypeBased(const 
Type *Ty,
   return false;
 }
 
+//===--===//
+// z/OS XPLINK ABI Implementation
+//===--===//
+
+namespace {
+
+class ZOSXPLinkABIInfo : public ABIInfo {
+  const unsigned GPRBits = 64;
+  bool HasVector;
+
+public:
+  ZOSXPLinkABIInfo(CodeGenTypes &CGT, bool HV) : ABIInfo(CGT), HasVector(HV) {}
+
+  bool isPromotableIntegerType(QualType Ty) const;
+  bool isVectorArgumentType(QualType Ty) const;
+  bool isFPArgumentType(QualType Ty) const;
+  QualType getSingleElementType(QualType Ty) const;
+  QualType getFPTypeOfComplexLikeType(QualType Ty) const;
+
+  ABIArgInfo classifyReturnType(QualType RetTy) const;
+  ABIArgInfo classifyArgumentType(QualType ArgTy, bool IsNamedArg) const;
+
+  void computeInfo(CGFunctionInfo &FI) const override {
+if (!getCXXABI().classifyReturnType(FI))
+  FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
+
+unsigned NumRequiredArgs = FI.getNumRequiredArgs();
+unsigned ArgNo = 0;
+
+for (auto &I : FI.arguments()) {
+  bool IsNamedArg = ArgNo < NumRequiredArgs;
+  I.info = classifyArgumentType(I.type, IsNamedArg);
+  ++ArgNo;
+}
+  }
+
+  RValue EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty,
+   AggValueSlot Slot) const override;
+};
+
+class ZOSXPLinkTargetCodeGenInfo : public TargetCodeGenInfo {
+public:
+  ZOSXPLinkTargetCodeGenInfo(CodeGenTypes &CGT, bool HasVector)
+  : TargetCodeGenInfo(std::make_unique(CGT, HasVector)) {
+SwiftInfo =
+std::make_unique(CGT, /*SwiftErrorInRegister=*/false);
+  }
+};
+
+} // namespace
+
+// Return true if the ABI requires Ty to be passed sign- or zero-
+// extended to 64 bits.
+bool ZOSXPLinkABIInfo::isPromotableIntegerType(QualType Ty) const {
+  // Treat an enum type as its underlying type.
+  if (const EnumType *EnumTy = Ty->getAs())
+Ty = EnumTy->getDecl()->getIntegerType();
+
+  // Promotable integer types are required to be promoted by the ABI.
+  if (getContext().isPromotableIntegerType(Ty))
+return true;
+
+  if (const auto *EIT = Ty->getAs())
+if (EIT->getNumBits() < 64)
+  return true;
+
+  // In addition to the usual promotable integer types, we also need to
+  // extend all 32-bit types, since the ABI requires promotion to 64 bits.
+  if (const BuiltinType *BT = Ty->getAs())
+switch (BT->getKind()) {
+case BuiltinType::Int:
+case BuiltinType::UInt:
+  return true;
+default:
+  break;
+}
+
+  return false;
+}
+
+bool ZOSXPLinkABIInfo::isVectorArgumentType(QualType Ty) const {
+  return (HasVector && Ty->isVectorType() &&
+  getContext().getTypeSize(Ty) <= 128);
+}
+
+bool ZOSXPLinkABIInfo::isFPArgumentType(QualType Ty) const {
+  if (const BuiltinType *BT = Ty->getAs())
+switch (BT->getKind()) {
+case BuiltinType::Float:
+case BuiltinType::Double:
+case BuiltinType::LongDouble:
+  return true;
+default:
+  return false;
+}
+
+  return false;
+}
+
+QualType ZOSXPLinkABIInfo::getSingleElementType(QualType Ty) const {
+  // Unions just containing a floating point type, e.g. union { float f1, f2; 
};
+  // are treated as a single floating point number. Check if the union only
+  // consists of a single type (handling embedded unions recursively), and
+  // return that type.
+  if (const RecordType *RT = Ty->getAsUnionType()) {
+QualType Found;
+// Check the fields.
+const RecordDecl *RD = RT->getDecl();
+for (const auto *FD : RD->fields()) {
+  if (Found.isNull())
+Found = getSingleElementType(FD->getType());
+  else if (Found != getSingleElementType(FD->getType()))
+return Ty;
+}
+return Found.isNull() ? Ty : Found;
+  }
+
+  const RecordType *RT = Ty->getAs();
+
+  if (RT && RT->isStructureOrClassType()) {
+const RecordDecl *RD = RT->getDecl();
+QualType Found;
+
+// If this is a C++ record, check the bases first.
+if (const CXXRecordDecl *CXXRD = dyn_cast(RD))
+  if (CXXRD->hasDefinition())
+for (const auto &I : CXXRD->bases()) {
+  QualType Base = I.getType();
+
+  // Empty bases don't affect things either way.
+  if (isEmptyRecord(getContext(), Base, true))
+continue;
+
+  if (!Found.isNull())
+return Ty;
+  Found = getSingleElementType(Base);
+}
+
+// Check the fields.
+for (const auto *FD : RD->fields()) {
+  QualType FT = FD->getType();
+
+  // Ignore empty fields.
+  if (isEmptyField(getContext(), FD, true))
+continue;
+
+  if (!Found.isNull())
+return Ty;
+
+  // Treat single element arrays as the element.
+  while (const ConstantArrayType *AT =
+ getContext().getAsConstantArrayType(FT)) {
+if (AT->getZEx

[clang] [SystemZ][z/OS] Implement z/OS XPLINK ABI (PR #101024)

2024-08-06 Thread Ulrich Weigand via cfe-commits


@@ -532,9 +532,371 @@ bool SystemZTargetCodeGenInfo::isVectorTypeBased(const 
Type *Ty,
   return false;
 }
 
+//===--===//
+// z/OS XPLINK ABI Implementation
+//===--===//
+
+namespace {
+
+class ZOSXPLinkABIInfo : public ABIInfo {
+  const unsigned GPRBits = 64;
+  bool HasVector;
+
+public:
+  ZOSXPLinkABIInfo(CodeGenTypes &CGT, bool HV) : ABIInfo(CGT), HasVector(HV) {}
+
+  bool isPromotableIntegerType(QualType Ty) const;
+  bool isVectorArgumentType(QualType Ty) const;
+  bool isFPArgumentType(QualType Ty) const;
+  QualType getSingleElementType(QualType Ty) const;
+  QualType getFPTypeOfComplexLikeType(QualType Ty) const;
+
+  ABIArgInfo classifyReturnType(QualType RetTy) const;
+  ABIArgInfo classifyArgumentType(QualType ArgTy, bool IsNamedArg) const;
+
+  void computeInfo(CGFunctionInfo &FI) const override {
+if (!getCXXABI().classifyReturnType(FI))
+  FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
+
+unsigned NumRequiredArgs = FI.getNumRequiredArgs();
+unsigned ArgNo = 0;
+
+for (auto &I : FI.arguments()) {
+  bool IsNamedArg = ArgNo < NumRequiredArgs;
+  I.info = classifyArgumentType(I.type, IsNamedArg);
+  ++ArgNo;
+}
+  }
+
+  RValue EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty,
+   AggValueSlot Slot) const override;
+};
+
+class ZOSXPLinkTargetCodeGenInfo : public TargetCodeGenInfo {
+public:
+  ZOSXPLinkTargetCodeGenInfo(CodeGenTypes &CGT, bool HasVector)
+  : TargetCodeGenInfo(std::make_unique(CGT, HasVector)) {
+SwiftInfo =
+std::make_unique(CGT, /*SwiftErrorInRegister=*/false);
+  }
+};
+
+} // namespace
+
+// Return true if the ABI requires Ty to be passed sign- or zero-
+// extended to 64 bits.
+bool ZOSXPLinkABIInfo::isPromotableIntegerType(QualType Ty) const {
+  // Treat an enum type as its underlying type.
+  if (const EnumType *EnumTy = Ty->getAs())
+Ty = EnumTy->getDecl()->getIntegerType();
+
+  // Promotable integer types are required to be promoted by the ABI.
+  if (getContext().isPromotableIntegerType(Ty))
+return true;
+
+  if (const auto *EIT = Ty->getAs())
+if (EIT->getNumBits() < 64)
+  return true;
+
+  // In addition to the usual promotable integer types, we also need to
+  // extend all 32-bit types, since the ABI requires promotion to 64 bits.
+  if (const BuiltinType *BT = Ty->getAs())
+switch (BT->getKind()) {
+case BuiltinType::Int:
+case BuiltinType::UInt:
+  return true;
+default:
+  break;
+}
+
+  return false;
+}
+
+bool ZOSXPLinkABIInfo::isVectorArgumentType(QualType Ty) const {
+  return (HasVector && Ty->isVectorType() &&
+  getContext().getTypeSize(Ty) <= 128);
+}
+
+bool ZOSXPLinkABIInfo::isFPArgumentType(QualType Ty) const {
+  if (const BuiltinType *BT = Ty->getAs())
+switch (BT->getKind()) {
+case BuiltinType::Float:
+case BuiltinType::Double:
+case BuiltinType::LongDouble:
+  return true;
+default:
+  return false;
+}
+
+  return false;
+}
+
+QualType ZOSXPLinkABIInfo::getSingleElementType(QualType Ty) const {
+  // Unions just containing a floating point type, e.g. union { float f1, f2; 
};
+  // are treated as a single floating point number. Check if the union only
+  // consists of a single type (handling embedded unions recursively), and
+  // return that type.
+  if (const RecordType *RT = Ty->getAsUnionType()) {
+QualType Found;
+// Check the fields.
+const RecordDecl *RD = RT->getDecl();
+for (const auto *FD : RD->fields()) {
+  if (Found.isNull())
+Found = getSingleElementType(FD->getType());
+  else if (Found != getSingleElementType(FD->getType()))
+return Ty;
+}
+return Found.isNull() ? Ty : Found;
+  }
+
+  const RecordType *RT = Ty->getAs();
+
+  if (RT && RT->isStructureOrClassType()) {
+const RecordDecl *RD = RT->getDecl();
+QualType Found;
+
+// If this is a C++ record, check the bases first.
+if (const CXXRecordDecl *CXXRD = dyn_cast(RD))
+  if (CXXRD->hasDefinition())
+for (const auto &I : CXXRD->bases()) {
+  QualType Base = I.getType();
+
+  // Empty bases don't affect things either way.
+  if (isEmptyRecord(getContext(), Base, true))
+continue;
+
+  if (!Found.isNull())
+return Ty;
+  Found = getSingleElementType(Base);
+}
+
+// Check the fields.
+for (const auto *FD : RD->fields()) {
+  QualType FT = FD->getType();
+
+  // Ignore empty fields.
+  if (isEmptyField(getContext(), FD, true))
+continue;
+
+  if (!Found.isNull())
+return Ty;
+
+  // Treat single element arrays as the element.
+  while (const ConstantArrayType *AT =
+ getContext().getAsConstantArrayType(FT)) {
+if (AT->getZEx

[clang] [SystemZ][z/OS] Implement z/OS XPLINK ABI (PR #101024)

2024-08-06 Thread Ulrich Weigand via cfe-commits

https://github.com/uweigand requested changes to this pull request.


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


[clang] [SystemZ][z/OS] Implement z/OS XPLINK ABI (PR #91384)

2024-07-23 Thread Ulrich Weigand via cfe-commits

https://github.com/uweigand approved this pull request.

LGTM now, thanks!

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


[clang] [SystemZ][z/OS] Implement z/OS XPLINK ABI (PR #91384)

2024-07-18 Thread Ulrich Weigand via cfe-commits

uweigand wrote:

Turns out transparent union handling was indeed broken in the SystemZ ELF ABI 
as well.  I've now checked in a fix here: 
https://github.com/llvm/llvm-project/commit/9af3628ce7400a96205a4c4468867c3c11dd4b2f

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


[clang] 9af3628 - [SystemZ] Fix transparent_union calling convention

2024-07-18 Thread Ulrich Weigand via cfe-commits

Author: Ulrich Weigand
Date: 2024-07-18T17:43:28+02:00
New Revision: 9af3628ce7400a96205a4c4468867c3c11dd4b2f

URL: 
https://github.com/llvm/llvm-project/commit/9af3628ce7400a96205a4c4468867c3c11dd4b2f
DIFF: 
https://github.com/llvm/llvm-project/commit/9af3628ce7400a96205a4c4468867c3c11dd4b2f.diff

LOG: [SystemZ] Fix transparent_union calling convention

The SystemZ ABI code was missing code to handle the transparent_union
extension.  Arguments of such types are specified to be passed like
the first member of the union, instead of according to the usual
ABI calling convention for aggregates.

This did not make much difference in practice as the SystemZ ABI
already specifies that 1-, 2-, 4- or 8-byte aggregates are passed
in registers.  However, there *is* a difference if the first member
of the transparent union is a scalar integer type smaller than word
size - if passed as a scalar, it needs to be zero- or sign-extended
to word size, while if passed as aggregate, it is not.

Fixed by adding code to handle transparent_union similar to what
is done on other targets.

Added: 


Modified: 
clang/lib/CodeGen/Targets/SystemZ.cpp
clang/test/CodeGen/SystemZ/systemz-abi.c

Removed: 




diff  --git a/clang/lib/CodeGen/Targets/SystemZ.cpp 
b/clang/lib/CodeGen/Targets/SystemZ.cpp
index e6b63b6fe093f..4d61f51379346 100644
--- a/clang/lib/CodeGen/Targets/SystemZ.cpp
+++ b/clang/lib/CodeGen/Targets/SystemZ.cpp
@@ -412,13 +412,16 @@ ABIArgInfo SystemZABIInfo::classifyReturnType(QualType 
RetTy) const {
 }
 
 ABIArgInfo SystemZABIInfo::classifyArgumentType(QualType Ty) const {
+  // Handle transparent union types.
+  Ty = useFirstFieldIfTransparentUnion(Ty);
+
   // Handle the generic C++ ABI.
   if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI()))
 return getNaturalAlignIndirect(Ty, RAA == CGCXXABI::RAA_DirectInMemory);
 
   // Integers and enums are extended to full register width.
   if (isPromotableIntegerTypeForABI(Ty))
-return ABIArgInfo::getExtend(Ty);
+return ABIArgInfo::getExtend(Ty, CGT.ConvertType(Ty));
 
   // Handle vector types and vector-like structure types.  Note that
   // as opposed to float-like structure types, we do not allow any

diff  --git a/clang/test/CodeGen/SystemZ/systemz-abi.c 
b/clang/test/CodeGen/SystemZ/systemz-abi.c
index 65a2bc9bbb680..3e39425e57f17 100644
--- a/clang/test/CodeGen/SystemZ/systemz-abi.c
+++ b/clang/test/CodeGen/SystemZ/systemz-abi.c
@@ -173,6 +173,29 @@ union union_double pass_union_double(union union_double 
arg) { return arg; }
 // CHECK-LABEL: define{{.*}} void @pass_union_double(ptr dead_on_unwind 
noalias writable sret(%union.union_double) align 8 %{{.*}}, i64 %{{.*}})
 
 
+// Verify that transparent unions are passed like their first member (but 
returned like a union)
+
+union tu_char { char a; } __attribute__((transparent_union));
+union tu_char pass_tu_char(union tu_char arg) { return arg; }
+// CHECK-LABEL: define{{.*}} void @pass_tu_char(ptr dead_on_unwind noalias 
writable sret(%union.tu_char) align 1 %{{.*}}, i8 signext %{{.*}})
+
+union tu_short { short a; } __attribute__((transparent_union));
+union tu_short pass_tu_short(union tu_short arg) { return arg; }
+// CHECK-LABEL: define{{.*}} void @pass_tu_short(ptr dead_on_unwind noalias 
writable sret(%union.tu_short) align 2 %{{.*}}, i16 signext %{{.*}})
+
+union tu_int { int a; } __attribute__((transparent_union));
+union tu_int pass_tu_int(union tu_int arg) { return arg; }
+// CHECK-LABEL: define{{.*}} void @pass_tu_int(ptr dead_on_unwind noalias 
writable sret(%union.tu_int) align 4 %{{.*}}, i32 signext %{{.*}})
+
+union tu_long { long a; } __attribute__((transparent_union));
+union tu_long pass_tu_long(union tu_long arg) { return arg; }
+// CHECK-LABEL: define{{.*}} void @pass_tu_long(ptr dead_on_unwind noalias 
writable sret(%union.tu_long) align 8 %{{.*}}, i64 %{{.*}})
+
+union tu_ptr { void *a; } __attribute__((transparent_union));
+union tu_ptr pass_tu_ptr(union tu_ptr arg) { return arg; }
+// CHECK-LABEL: define{{.*}} void @pass_tu_ptr(ptr dead_on_unwind noalias 
writable sret(%union.tu_ptr) align 8 %{{.*}}, ptr %{{.*}})
+
+
 // Accessing variable argument lists
 
 int va_int(__builtin_va_list l) { return __builtin_va_arg(l, int); }



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


[clang] [SystemZ][z/OS] Implement z/OS XPLINK ABI (PR #91384)

2024-07-18 Thread Ulrich Weigand via cfe-commits

https://github.com/uweigand commented:

This version LGTM now, I think once the transparent-union thing is resolved, 
this should be ready to commit.  Thanks!

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


[clang] [SystemZ][z/OS] Implement z/OS XPLINK ABI (PR #91384)

2024-07-18 Thread Ulrich Weigand via cfe-commits


@@ -529,9 +530,355 @@ bool SystemZTargetCodeGenInfo::isVectorTypeBased(const 
Type *Ty,
   return false;
 }
 
+//===--===//
+// z/OS XPLINK ABI Implementation
+//===--===//
+
+namespace {
+
+class ZOSXPLinkABIInfo : public ABIInfo {
+  const unsigned GPRBits = 64;
+  bool HasVector;
+
+public:
+  ZOSXPLinkABIInfo(CodeGenTypes &CGT, bool HV) : ABIInfo(CGT), HasVector(HV) {}
+
+  bool isPromotableIntegerType(QualType Ty) const;
+  bool isVectorArgumentType(QualType Ty) const;
+  bool isFPArgumentType(QualType Ty) const;
+  QualType getSingleElementType(QualType Ty) const;
+  std::optional getFPTypeOfComplexLikeType(QualType Ty) const;
+
+  ABIArgInfo classifyReturnType(QualType RetTy) const;
+  ABIArgInfo classifyArgumentType(QualType ArgTy, bool IsNamedArg) const;
+
+  void computeInfo(CGFunctionInfo &FI) const override {
+if (!getCXXABI().classifyReturnType(FI))
+  FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
+
+unsigned NumRequiredArgs = FI.getNumRequiredArgs();
+unsigned ArgNo = 0;
+
+for (auto &I : FI.arguments()) {
+  bool IsNamedArg = ArgNo < NumRequiredArgs;
+  I.info = classifyArgumentType(I.type, IsNamedArg);
+  ++ArgNo;
+}
+  }
+
+  Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
+QualType Ty) const override;
+};
+
+class ZOSXPLinkTargetCodeGenInfo : public TargetCodeGenInfo {
+public:
+  ZOSXPLinkTargetCodeGenInfo(CodeGenTypes &CGT, bool HasVector)
+  : TargetCodeGenInfo(std::make_unique(CGT, HasVector)) {
+SwiftInfo =
+std::make_unique(CGT, /*SwiftErrorInRegister=*/false);
+  }
+};
+
+} // namespace
+
+// Return true if the ABI requires Ty to be passed sign- or zero-
+// extended to 64 bits.
+bool ZOSXPLinkABIInfo::isPromotableIntegerType(QualType Ty) const {
+  // Treat an enum type as its underlying type.
+  if (const EnumType *EnumTy = Ty->getAs())
+Ty = EnumTy->getDecl()->getIntegerType();
+
+  // Promotable integer types are required to be promoted by the ABI.
+  if (getContext().isPromotableIntegerType(Ty))
+return true;
+
+  if (const auto *EIT = Ty->getAs())
+if (EIT->getNumBits() < 64)
+  return true;
+
+  // In addition to the usual promotable integer types, we also need to
+  // extend all 32-bit types, since the ABI requires promotion to 64 bits.
+  if (const BuiltinType *BT = Ty->getAs())
+switch (BT->getKind()) {
+case BuiltinType::Int:
+case BuiltinType::UInt:
+  return true;
+default:
+  break;
+}
+
+  return false;
+}
+
+bool ZOSXPLinkABIInfo::isVectorArgumentType(QualType Ty) const {
+  return (HasVector && Ty->isVectorType() &&
+  getContext().getTypeSize(Ty) <= 128);
+}
+
+bool ZOSXPLinkABIInfo::isFPArgumentType(QualType Ty) const {
+  if (const BuiltinType *BT = Ty->getAs())
+switch (BT->getKind()) {
+case BuiltinType::Float:
+case BuiltinType::Double:
+case BuiltinType::LongDouble:
+  return true;
+default:
+  return false;
+}
+
+  return false;
+}
+
+QualType ZOSXPLinkABIInfo::getSingleElementType(QualType Ty) const {
+  const RecordType *RT = Ty->getAs();
+
+  if (RT && RT->isStructureOrClassType()) {
+const RecordDecl *RD = RT->getDecl();
+QualType Found;
+
+// If this is a C++ record, check the bases first.
+if (const CXXRecordDecl *CXXRD = dyn_cast(RD))
+  if (CXXRD->hasDefinition())
+for (const auto &I : CXXRD->bases()) {
+  QualType Base = I.getType();
+
+  // Empty bases don't affect things either way.
+  if (isEmptyRecord(getContext(), Base, true))
+continue;
+
+  if (!Found.isNull())
+return Ty;
+  Found = getSingleElementType(Base);
+}
+
+// Check the fields.
+for (const auto *FD : RD->fields()) {
+  QualType FT = FD->getType();
+
+  // Ignore empty fields.
+  if (isEmptyField(getContext(), FD, true))
+continue;
+
+  if (!Found.isNull())
+return Ty;
+
+  // Treat single element arrays as the element.
+  while (const ConstantArrayType *AT =
+ getContext().getAsConstantArrayType(FT)) {
+if (AT->getZExtSize() != 1)
+  break;
+FT = AT->getElementType();
+  }
+
+  Found = getSingleElementType(FT);
+}
+
+// Unlike isSingleElementStruct(), trailing padding is allowed.
+if (!Found.isNull())
+  return Found;
+  }
+
+  return Ty;
+}
+
+std::optional
+ZOSXPLinkABIInfo::getFPTypeOfComplexLikeType(QualType Ty) const {
+  if (const RecordType *RT = Ty->getAsStructureType()) {
+const RecordDecl *RD = RT->getDecl();
+
+// Check for non-empty base classes.
+if (const CXXRecordDecl *CXXRD = dyn_cast(RD))
+  if (CXXRD->hasDefinition())
+for (const auto &I : CXXRD->bases()) {
+  QualType Base = I.getType();
+   

[clang] [SystemZ][z/OS] Implement z/OS XPLINK ABI (PR #91384)

2024-07-18 Thread Ulrich Weigand via cfe-commits

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


[clang] [SystemZ][z/OS] Implement z/OS XPLINK ABI (PR #91384)

2024-07-17 Thread Ulrich Weigand via cfe-commits


@@ -529,9 +530,355 @@ bool SystemZTargetCodeGenInfo::isVectorTypeBased(const 
Type *Ty,
   return false;
 }
 
+//===--===//
+// z/OS XPLINK ABI Implementation
+//===--===//
+
+namespace {
+
+class ZOSXPLinkABIInfo : public ABIInfo {
+  const unsigned GPRBits = 64;
+  bool HasVector;
+
+public:
+  ZOSXPLinkABIInfo(CodeGenTypes &CGT, bool HV) : ABIInfo(CGT), HasVector(HV) {}
+
+  bool isPromotableIntegerType(QualType Ty) const;
+  bool isVectorArgumentType(QualType Ty) const;
+  bool isFPArgumentType(QualType Ty) const;
+  QualType getSingleElementType(QualType Ty) const;
+  std::optional getFPTypeOfComplexLikeType(QualType Ty) const;
+
+  ABIArgInfo classifyReturnType(QualType RetTy) const;
+  ABIArgInfo classifyArgumentType(QualType ArgTy, bool IsNamedArg) const;
+
+  void computeInfo(CGFunctionInfo &FI) const override {
+if (!getCXXABI().classifyReturnType(FI))
+  FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
+
+unsigned NumRequiredArgs = FI.getNumRequiredArgs();
+unsigned ArgNo = 0;
+
+for (auto &I : FI.arguments()) {
+  bool IsNamedArg = ArgNo < NumRequiredArgs;
+  I.info = classifyArgumentType(I.type, IsNamedArg);
+  ++ArgNo;
+}
+  }
+
+  Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
+QualType Ty) const override;
+};
+
+class ZOSXPLinkTargetCodeGenInfo : public TargetCodeGenInfo {
+public:
+  ZOSXPLinkTargetCodeGenInfo(CodeGenTypes &CGT, bool HasVector)
+  : TargetCodeGenInfo(std::make_unique(CGT, HasVector)) {
+SwiftInfo =
+std::make_unique(CGT, /*SwiftErrorInRegister=*/false);
+  }
+};
+
+} // namespace
+
+// Return true if the ABI requires Ty to be passed sign- or zero-
+// extended to 64 bits.
+bool ZOSXPLinkABIInfo::isPromotableIntegerType(QualType Ty) const {
+  // Treat an enum type as its underlying type.
+  if (const EnumType *EnumTy = Ty->getAs())
+Ty = EnumTy->getDecl()->getIntegerType();
+
+  // Promotable integer types are required to be promoted by the ABI.
+  if (getContext().isPromotableIntegerType(Ty))
+return true;
+
+  if (const auto *EIT = Ty->getAs())
+if (EIT->getNumBits() < 64)
+  return true;
+
+  // In addition to the usual promotable integer types, we also need to
+  // extend all 32-bit types, since the ABI requires promotion to 64 bits.
+  if (const BuiltinType *BT = Ty->getAs())
+switch (BT->getKind()) {
+case BuiltinType::Int:
+case BuiltinType::UInt:
+  return true;
+default:
+  break;
+}
+
+  return false;
+}
+
+bool ZOSXPLinkABIInfo::isVectorArgumentType(QualType Ty) const {
+  return (HasVector && Ty->isVectorType() &&
+  getContext().getTypeSize(Ty) <= 128);
+}
+
+bool ZOSXPLinkABIInfo::isFPArgumentType(QualType Ty) const {
+  if (const BuiltinType *BT = Ty->getAs())
+switch (BT->getKind()) {
+case BuiltinType::Float:
+case BuiltinType::Double:
+case BuiltinType::LongDouble:
+  return true;
+default:
+  return false;
+}
+
+  return false;
+}
+
+QualType ZOSXPLinkABIInfo::getSingleElementType(QualType Ty) const {
+  const RecordType *RT = Ty->getAs();
+
+  if (RT && RT->isStructureOrClassType()) {
+const RecordDecl *RD = RT->getDecl();
+QualType Found;
+
+// If this is a C++ record, check the bases first.
+if (const CXXRecordDecl *CXXRD = dyn_cast(RD))
+  if (CXXRD->hasDefinition())
+for (const auto &I : CXXRD->bases()) {
+  QualType Base = I.getType();
+
+  // Empty bases don't affect things either way.
+  if (isEmptyRecord(getContext(), Base, true))
+continue;
+
+  if (!Found.isNull())
+return Ty;
+  Found = getSingleElementType(Base);
+}
+
+// Check the fields.
+for (const auto *FD : RD->fields()) {
+  QualType FT = FD->getType();
+
+  // Ignore empty fields.
+  if (isEmptyField(getContext(), FD, true))
+continue;
+
+  if (!Found.isNull())
+return Ty;
+
+  // Treat single element arrays as the element.
+  while (const ConstantArrayType *AT =
+ getContext().getAsConstantArrayType(FT)) {
+if (AT->getZExtSize() != 1)
+  break;
+FT = AT->getElementType();
+  }
+
+  Found = getSingleElementType(FT);
+}
+
+// Unlike isSingleElementStruct(), trailing padding is allowed.
+if (!Found.isNull())
+  return Found;
+  }
+
+  return Ty;
+}
+
+std::optional
+ZOSXPLinkABIInfo::getFPTypeOfComplexLikeType(QualType Ty) const {
+  if (const RecordType *RT = Ty->getAsStructureType()) {
+const RecordDecl *RD = RT->getDecl();
+
+// Check for non-empty base classes.
+if (const CXXRecordDecl *CXXRD = dyn_cast(RD))
+  if (CXXRD->hasDefinition())
+for (const auto &I : CXXRD->bases()) {
+  QualType Base = I.getType();
+   

[clang] [SystemZ][z/OS] Implement z/OS XPLINK ABI (PR #91384)

2024-07-15 Thread Ulrich Weigand via cfe-commits


@@ -529,9 +530,355 @@ bool SystemZTargetCodeGenInfo::isVectorTypeBased(const 
Type *Ty,
   return false;
 }
 
+//===--===//
+// z/OS XPLINK ABI Implementation
+//===--===//
+
+namespace {
+
+class ZOSXPLinkABIInfo : public ABIInfo {
+  const unsigned GPRBits = 64;
+  bool HasVector;
+
+public:
+  ZOSXPLinkABIInfo(CodeGenTypes &CGT, bool HV) : ABIInfo(CGT), HasVector(HV) {}
+
+  bool isPromotableIntegerType(QualType Ty) const;
+  bool isVectorArgumentType(QualType Ty) const;
+  bool isFPArgumentType(QualType Ty) const;
+  QualType getSingleElementType(QualType Ty) const;
+  std::optional getFPTypeOfComplexLikeType(QualType Ty) const;
+
+  ABIArgInfo classifyReturnType(QualType RetTy) const;
+  ABIArgInfo classifyArgumentType(QualType ArgTy, bool IsNamedArg) const;
+
+  void computeInfo(CGFunctionInfo &FI) const override {
+if (!getCXXABI().classifyReturnType(FI))
+  FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
+
+unsigned NumRequiredArgs = FI.getNumRequiredArgs();
+unsigned ArgNo = 0;
+
+for (auto &I : FI.arguments()) {
+  bool IsNamedArg = ArgNo < NumRequiredArgs;
+  I.info = classifyArgumentType(I.type, IsNamedArg);
+  ++ArgNo;
+}
+  }
+
+  Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
+QualType Ty) const override;
+};
+
+class ZOSXPLinkTargetCodeGenInfo : public TargetCodeGenInfo {
+public:
+  ZOSXPLinkTargetCodeGenInfo(CodeGenTypes &CGT, bool HasVector)
+  : TargetCodeGenInfo(std::make_unique(CGT, HasVector)) {
+SwiftInfo =
+std::make_unique(CGT, /*SwiftErrorInRegister=*/false);
+  }
+};
+
+} // namespace
+
+// Return true if the ABI requires Ty to be passed sign- or zero-
+// extended to 64 bits.
+bool ZOSXPLinkABIInfo::isPromotableIntegerType(QualType Ty) const {
+  // Treat an enum type as its underlying type.
+  if (const EnumType *EnumTy = Ty->getAs())
+Ty = EnumTy->getDecl()->getIntegerType();
+
+  // Promotable integer types are required to be promoted by the ABI.
+  if (getContext().isPromotableIntegerType(Ty))
+return true;
+
+  if (const auto *EIT = Ty->getAs())
+if (EIT->getNumBits() < 64)
+  return true;
+
+  // In addition to the usual promotable integer types, we also need to
+  // extend all 32-bit types, since the ABI requires promotion to 64 bits.
+  if (const BuiltinType *BT = Ty->getAs())
+switch (BT->getKind()) {
+case BuiltinType::Int:
+case BuiltinType::UInt:
+  return true;
+default:
+  break;
+}
+
+  return false;
+}
+
+bool ZOSXPLinkABIInfo::isVectorArgumentType(QualType Ty) const {
+  return (HasVector && Ty->isVectorType() &&
+  getContext().getTypeSize(Ty) <= 128);
+}
+
+bool ZOSXPLinkABIInfo::isFPArgumentType(QualType Ty) const {
+  if (const BuiltinType *BT = Ty->getAs())
+switch (BT->getKind()) {
+case BuiltinType::Float:
+case BuiltinType::Double:
+case BuiltinType::LongDouble:
+  return true;
+default:
+  return false;
+}
+
+  return false;
+}
+
+QualType ZOSXPLinkABIInfo::getSingleElementType(QualType Ty) const {
+  const RecordType *RT = Ty->getAs();
+
+  if (RT && RT->isStructureOrClassType()) {
+const RecordDecl *RD = RT->getDecl();
+QualType Found;
+
+// If this is a C++ record, check the bases first.
+if (const CXXRecordDecl *CXXRD = dyn_cast(RD))
+  if (CXXRD->hasDefinition())
+for (const auto &I : CXXRD->bases()) {
+  QualType Base = I.getType();
+
+  // Empty bases don't affect things either way.
+  if (isEmptyRecord(getContext(), Base, true))
+continue;
+
+  if (!Found.isNull())
+return Ty;
+  Found = getSingleElementType(Base);
+}
+
+// Check the fields.
+for (const auto *FD : RD->fields()) {
+  QualType FT = FD->getType();
+
+  // Ignore empty fields.
+  if (isEmptyField(getContext(), FD, true))
+continue;
+
+  if (!Found.isNull())
+return Ty;
+
+  // Treat single element arrays as the element.
+  while (const ConstantArrayType *AT =
+ getContext().getAsConstantArrayType(FT)) {
+if (AT->getZExtSize() != 1)
+  break;
+FT = AT->getElementType();
+  }
+
+  Found = getSingleElementType(FT);
+}
+
+// Unlike isSingleElementStruct(), trailing padding is allowed.
+if (!Found.isNull())
+  return Found;
+  }
+
+  return Ty;
+}
+
+std::optional
+ZOSXPLinkABIInfo::getFPTypeOfComplexLikeType(QualType Ty) const {
+  if (const RecordType *RT = Ty->getAsStructureType()) {
+const RecordDecl *RD = RT->getDecl();
+
+// Check for non-empty base classes.
+if (const CXXRecordDecl *CXXRD = dyn_cast(RD))
+  if (CXXRD->hasDefinition())
+for (const auto &I : CXXRD->bases()) {
+  QualType Base = I.getType();
+   

[clang] [SystemZ][z/OS] Implement z/OS XPLINK ABI (PR #91384)

2024-07-15 Thread Ulrich Weigand via cfe-commits


@@ -529,9 +530,355 @@ bool SystemZTargetCodeGenInfo::isVectorTypeBased(const 
Type *Ty,
   return false;
 }
 
+//===--===//
+// z/OS XPLINK ABI Implementation
+//===--===//
+
+namespace {
+
+class ZOSXPLinkABIInfo : public ABIInfo {
+  const unsigned GPRBits = 64;
+  bool HasVector;
+
+public:
+  ZOSXPLinkABIInfo(CodeGenTypes &CGT, bool HV) : ABIInfo(CGT), HasVector(HV) {}
+
+  bool isPromotableIntegerType(QualType Ty) const;
+  bool isVectorArgumentType(QualType Ty) const;
+  bool isFPArgumentType(QualType Ty) const;
+  QualType getSingleElementType(QualType Ty) const;
+  std::optional getFPTypeOfComplexLikeType(QualType Ty) const;
+
+  ABIArgInfo classifyReturnType(QualType RetTy) const;
+  ABIArgInfo classifyArgumentType(QualType ArgTy, bool IsNamedArg) const;
+
+  void computeInfo(CGFunctionInfo &FI) const override {
+if (!getCXXABI().classifyReturnType(FI))
+  FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
+
+unsigned NumRequiredArgs = FI.getNumRequiredArgs();
+unsigned ArgNo = 0;
+
+for (auto &I : FI.arguments()) {
+  bool IsNamedArg = ArgNo < NumRequiredArgs;
+  I.info = classifyArgumentType(I.type, IsNamedArg);
+  ++ArgNo;
+}
+  }
+
+  Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
+QualType Ty) const override;
+};
+
+class ZOSXPLinkTargetCodeGenInfo : public TargetCodeGenInfo {
+public:
+  ZOSXPLinkTargetCodeGenInfo(CodeGenTypes &CGT, bool HasVector)
+  : TargetCodeGenInfo(std::make_unique(CGT, HasVector)) {
+SwiftInfo =
+std::make_unique(CGT, /*SwiftErrorInRegister=*/false);
+  }
+};
+
+} // namespace
+
+// Return true if the ABI requires Ty to be passed sign- or zero-
+// extended to 64 bits.
+bool ZOSXPLinkABIInfo::isPromotableIntegerType(QualType Ty) const {
+  // Treat an enum type as its underlying type.
+  if (const EnumType *EnumTy = Ty->getAs())
+Ty = EnumTy->getDecl()->getIntegerType();
+
+  // Promotable integer types are required to be promoted by the ABI.
+  if (getContext().isPromotableIntegerType(Ty))
+return true;
+
+  if (const auto *EIT = Ty->getAs())
+if (EIT->getNumBits() < 64)
+  return true;
+
+  // In addition to the usual promotable integer types, we also need to
+  // extend all 32-bit types, since the ABI requires promotion to 64 bits.
+  if (const BuiltinType *BT = Ty->getAs())
+switch (BT->getKind()) {
+case BuiltinType::Int:
+case BuiltinType::UInt:
+  return true;
+default:
+  break;
+}
+
+  return false;
+}
+
+bool ZOSXPLinkABIInfo::isVectorArgumentType(QualType Ty) const {
+  return (HasVector && Ty->isVectorType() &&
+  getContext().getTypeSize(Ty) <= 128);
+}
+
+bool ZOSXPLinkABIInfo::isFPArgumentType(QualType Ty) const {
+  if (const BuiltinType *BT = Ty->getAs())
+switch (BT->getKind()) {
+case BuiltinType::Float:
+case BuiltinType::Double:
+case BuiltinType::LongDouble:
+  return true;
+default:
+  return false;
+}
+
+  return false;
+}
+
+QualType ZOSXPLinkABIInfo::getSingleElementType(QualType Ty) const {
+  const RecordType *RT = Ty->getAs();
+
+  if (RT && RT->isStructureOrClassType()) {
+const RecordDecl *RD = RT->getDecl();
+QualType Found;
+
+// If this is a C++ record, check the bases first.
+if (const CXXRecordDecl *CXXRD = dyn_cast(RD))
+  if (CXXRD->hasDefinition())
+for (const auto &I : CXXRD->bases()) {
+  QualType Base = I.getType();
+
+  // Empty bases don't affect things either way.
+  if (isEmptyRecord(getContext(), Base, true))
+continue;
+
+  if (!Found.isNull())
+return Ty;
+  Found = getSingleElementType(Base);
+}
+
+// Check the fields.
+for (const auto *FD : RD->fields()) {
+  QualType FT = FD->getType();
+
+  // Ignore empty fields.
+  if (isEmptyField(getContext(), FD, true))
+continue;
+
+  if (!Found.isNull())
+return Ty;
+
+  // Treat single element arrays as the element.
+  while (const ConstantArrayType *AT =
+ getContext().getAsConstantArrayType(FT)) {
+if (AT->getZExtSize() != 1)
+  break;
+FT = AT->getElementType();
+  }
+
+  Found = getSingleElementType(FT);
+}
+
+// Unlike isSingleElementStruct(), trailing padding is allowed.
+if (!Found.isNull())
+  return Found;
+  }
+
+  return Ty;
+}
+
+std::optional
+ZOSXPLinkABIInfo::getFPTypeOfComplexLikeType(QualType Ty) const {
+  if (const RecordType *RT = Ty->getAsStructureType()) {
+const RecordDecl *RD = RT->getDecl();
+
+// Check for non-empty base classes.
+if (const CXXRecordDecl *CXXRD = dyn_cast(RD))
+  if (CXXRD->hasDefinition())
+for (const auto &I : CXXRD->bases()) {
+  QualType Base = I.getType();
+   

[clang] [SystemZ][z/OS] Implement z/OS XPLINK ABI (PR #91384)

2024-07-15 Thread Ulrich Weigand via cfe-commits

https://github.com/uweigand commented:

This version looks mostly good to me - just a few remaining questions inline.  
Thanks!

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


[clang] [SystemZ][z/OS] Implement z/OS XPLINK ABI (PR #91384)

2024-07-15 Thread Ulrich Weigand via cfe-commits


@@ -529,9 +530,355 @@ bool SystemZTargetCodeGenInfo::isVectorTypeBased(const 
Type *Ty,
   return false;
 }
 
+//===--===//
+// z/OS XPLINK ABI Implementation
+//===--===//
+
+namespace {
+
+class ZOSXPLinkABIInfo : public ABIInfo {
+  const unsigned GPRBits = 64;
+  bool HasVector;
+
+public:
+  ZOSXPLinkABIInfo(CodeGenTypes &CGT, bool HV) : ABIInfo(CGT), HasVector(HV) {}
+
+  bool isPromotableIntegerType(QualType Ty) const;
+  bool isVectorArgumentType(QualType Ty) const;
+  bool isFPArgumentType(QualType Ty) const;
+  QualType getSingleElementType(QualType Ty) const;
+  std::optional getFPTypeOfComplexLikeType(QualType Ty) const;
+
+  ABIArgInfo classifyReturnType(QualType RetTy) const;
+  ABIArgInfo classifyArgumentType(QualType ArgTy, bool IsNamedArg) const;
+
+  void computeInfo(CGFunctionInfo &FI) const override {
+if (!getCXXABI().classifyReturnType(FI))
+  FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
+
+unsigned NumRequiredArgs = FI.getNumRequiredArgs();
+unsigned ArgNo = 0;
+
+for (auto &I : FI.arguments()) {
+  bool IsNamedArg = ArgNo < NumRequiredArgs;
+  I.info = classifyArgumentType(I.type, IsNamedArg);
+  ++ArgNo;
+}
+  }
+
+  Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
+QualType Ty) const override;
+};
+
+class ZOSXPLinkTargetCodeGenInfo : public TargetCodeGenInfo {
+public:
+  ZOSXPLinkTargetCodeGenInfo(CodeGenTypes &CGT, bool HasVector)
+  : TargetCodeGenInfo(std::make_unique(CGT, HasVector)) {
+SwiftInfo =
+std::make_unique(CGT, /*SwiftErrorInRegister=*/false);
+  }
+};
+
+} // namespace
+
+// Return true if the ABI requires Ty to be passed sign- or zero-
+// extended to 64 bits.
+bool ZOSXPLinkABIInfo::isPromotableIntegerType(QualType Ty) const {
+  // Treat an enum type as its underlying type.
+  if (const EnumType *EnumTy = Ty->getAs())
+Ty = EnumTy->getDecl()->getIntegerType();
+
+  // Promotable integer types are required to be promoted by the ABI.
+  if (getContext().isPromotableIntegerType(Ty))
+return true;
+
+  if (const auto *EIT = Ty->getAs())
+if (EIT->getNumBits() < 64)
+  return true;
+
+  // In addition to the usual promotable integer types, we also need to
+  // extend all 32-bit types, since the ABI requires promotion to 64 bits.
+  if (const BuiltinType *BT = Ty->getAs())
+switch (BT->getKind()) {
+case BuiltinType::Int:
+case BuiltinType::UInt:
+  return true;
+default:
+  break;
+}
+
+  return false;
+}
+
+bool ZOSXPLinkABIInfo::isVectorArgumentType(QualType Ty) const {
+  return (HasVector && Ty->isVectorType() &&
+  getContext().getTypeSize(Ty) <= 128);
+}
+
+bool ZOSXPLinkABIInfo::isFPArgumentType(QualType Ty) const {
+  if (const BuiltinType *BT = Ty->getAs())
+switch (BT->getKind()) {
+case BuiltinType::Float:
+case BuiltinType::Double:
+case BuiltinType::LongDouble:
+  return true;
+default:
+  return false;
+}
+
+  return false;
+}
+
+QualType ZOSXPLinkABIInfo::getSingleElementType(QualType Ty) const {
+  const RecordType *RT = Ty->getAs();
+
+  if (RT && RT->isStructureOrClassType()) {
+const RecordDecl *RD = RT->getDecl();
+QualType Found;
+
+// If this is a C++ record, check the bases first.
+if (const CXXRecordDecl *CXXRD = dyn_cast(RD))
+  if (CXXRD->hasDefinition())
+for (const auto &I : CXXRD->bases()) {
+  QualType Base = I.getType();
+
+  // Empty bases don't affect things either way.
+  if (isEmptyRecord(getContext(), Base, true))
+continue;
+
+  if (!Found.isNull())
+return Ty;
+  Found = getSingleElementType(Base);
+}
+
+// Check the fields.
+for (const auto *FD : RD->fields()) {
+  QualType FT = FD->getType();
+
+  // Ignore empty fields.
+  if (isEmptyField(getContext(), FD, true))
+continue;
+
+  if (!Found.isNull())
+return Ty;
+
+  // Treat single element arrays as the element.
+  while (const ConstantArrayType *AT =
+ getContext().getAsConstantArrayType(FT)) {
+if (AT->getZExtSize() != 1)
+  break;
+FT = AT->getElementType();
+  }
+
+  Found = getSingleElementType(FT);
+}
+
+// Unlike isSingleElementStruct(), trailing padding is allowed.
+if (!Found.isNull())
+  return Found;
+  }
+
+  return Ty;
+}
+
+std::optional
+ZOSXPLinkABIInfo::getFPTypeOfComplexLikeType(QualType Ty) const {
+  if (const RecordType *RT = Ty->getAsStructureType()) {
+const RecordDecl *RD = RT->getDecl();
+
+// Check for non-empty base classes.
+if (const CXXRecordDecl *CXXRD = dyn_cast(RD))
+  if (CXXRD->hasDefinition())
+for (const auto &I : CXXRD->bases()) {
+  QualType Base = I.getType();
+   

[clang] [SystemZ][z/OS] Implement z/OS XPLINK ABI (PR #91384)

2024-07-15 Thread Ulrich Weigand via cfe-commits

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


[clang] [llvm] Revert changes in AddDefaultGCCPrefixes() for SystemZTriples. (PR #94729)

2024-07-02 Thread Ulrich Weigand via cfe-commits

uweigand wrote:

This `/etc/lsb-release` test looks a bit weird to me.  Why can't it simply do:
```
echo ${UNAME_MACHINE}-ibm-linux-${LIBC}
```
like the upstream `config.guess` does?

That should properly match the other variants that are simply missing one of 
the triple fields.


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


[clang] [llvm] [clang] Introduce target-specific `Sema` components (PR #93179)

2024-05-24 Thread Ulrich Weigand via cfe-commits


@@ -0,0 +1,94 @@
+//===-- SemaSystemZ.cpp -- SystemZ target-specific routines 
---===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+//
+//  This file implements semantic analysis functions specific to AIX.

uweigand wrote:

Comment should read SystemZ instead of AIX.

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


[clang] [llvm] [clang] Introduce target-specific `Sema` components (PR #93179)

2024-05-24 Thread Ulrich Weigand via cfe-commits

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


[clang] [llvm] [clang] Introduce target-specific `Sema` components (PR #93179)

2024-05-24 Thread Ulrich Weigand via cfe-commits

https://github.com/uweigand commented:

See comment fix - otherwise SystemZ part LGTM.

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


[clang] [Serialization] Read the initializer for interesting static variables before consuming it (PR #92353)

2024-05-16 Thread Ulrich Weigand via cfe-commits

uweigand wrote:

I'm not seeing any failures with this patch on s390x with the regular check-all 
and check-openmp tests.  Do you have a link to the failures you were seeing in 
the past (was that on the build bot?)?

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


[clang] [SystemZ][z/OS] Implement z/OS XPLINK ABI (PR #91384)

2024-05-15 Thread Ulrich Weigand via cfe-commits


@@ -0,0 +1,137 @@
+// RUN: %clang_cc1 -triple s390x-ibm-zos \
+// RUN:   -emit-llvm -no-enable-noundef-analysis -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple s390x-ibm-zos -target-feature +vector \
+// RUN:   -emit-llvm -no-enable-noundef-analysis -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple s390x-ibm-zos -target-cpu z13 \
+// RUN:   -emit-llvm -no-enable-noundef-analysis -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple s390x-ibm-zos -target-cpu arch11 \
+// RUN:   -emit-llvm -no-enable-noundef-analysis -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple s390x-ibm-zos -target-cpu z14 \
+// RUN:   -emit-llvm -no-enable-noundef-analysis -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple s390x-ibm-zos -target-cpu arch12 \
+// RUN:   -emit-llvm -no-enable-noundef-analysis -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple s390x-ibm-zos -target-cpu z15 \
+// RUN:   -emit-llvm -no-enable-noundef-analysis -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple s390x-ibm-zos -target-cpu arch13 \
+// RUN:   -emit-llvm -no-enable-noundef-analysis -o - %s | FileCheck %s
+
+// Scalar types
+
+char pass_char(char arg) { return arg; }
+// CHECK-LABEL: define signext i8 @pass_char(i8 signext %{{.*}})
+
+short pass_short(short arg) { return arg; }
+// CHECK-LABEL: define signext i16 @pass_short(i16 signext %{{.*}})
+
+int pass_int(int arg) { return arg; }
+// CHECK-LABEL: define signext i32 @pass_int(i32 signext %{{.*}})
+
+long pass_long(long arg) { return arg; }
+// CHECK-LABEL: define i64 @pass_long(i64 %{{.*}})
+
+long long pass_longlong(long long arg) { return arg; }
+// CHECK-LABEL: define i64 @pass_longlong(i64 %{{.*}})
+
+float pass_float(float arg) { return arg; }
+// CHECK-LABEL: define float @pass_float(float %{{.*}})
+
+double pass_double(double arg) { return arg; }
+// CHECK-LABEL: define double @pass_double(double %{{.*}})
+
+long double pass_longdouble(long double arg) { return arg; }
+// CHECK-LABEL: define fp128 @pass_longdouble(fp128 %{{.*}})
+
+enum Color { Red, Blue };
+enum Color pass_enum(enum Color arg) { return arg; }
+// CHECK-LABEL: define zeroext i32 @pass_enum(i32 zeroext %{{.*}})
+
+// Complex types
+
+// TODO: Add tests for complex integer types
+
+_Complex float pass_complex_float(_Complex float arg) { return arg; }
+// CHECK-LABEL: define { float, float } @pass_complex_float(float %{{.*}}, 
float %{{.*}})
+
+_Complex double pass_complex_double(_Complex double arg) { return arg; }
+// CHECK-LABEL: define { double, double } @pass_complex_double(double %{{.*}}, 
double %{{.*}})
+
+_Complex long double pass_complex_longdouble(_Complex long double arg) { 
return arg; }
+// CHECK-LABEL: define { fp128, fp128 } @pass_complex_longdouble(fp128 
%{{.*}}, fp128 %{{.*}})
+
+// Verify that the following are complex-like types
+struct complexlike_float { float re, im; };
+struct complexlike_float pass_complexlike_float(struct complexlike_float arg) 
{ return arg; }
+// CHECK-LABEL: define %struct.complexlike_float @pass_complexlike_float(float 
%{{.*}}, float %{{.*}})
+
+struct complexlike_double { double re, im; };
+struct complexlike_double pass_complexlike_double(struct complexlike_double 
arg) { return arg; }
+// CHECK-LABEL: define %struct.complexlike_double 
@pass_complexlike_double(double %{{.*}}, double %{{.*}})
+
+struct complexlike_longdouble { long double re, im; };
+struct complexlike_longdouble pass_complexlike_longdouble(struct 
complexlike_longdouble arg) { return arg; }
+// CHECK-LABEL: define %struct.complexlike_longdouble 
@pass_complexlike_longdouble(fp128 %{{.*}}, fp128 %{{.*}})
+
+// Aggregate types
+

uweigand wrote:

That's not what unnamed means here.  "Unnamed" refers to those arguments passed 
to a vararg routine after the named arguments.

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


[clang] [SystemZ][z/OS] Implement z/OS XPLINK ABI (PR #91384)

2024-05-15 Thread Ulrich Weigand via cfe-commits


@@ -529,9 +530,401 @@ bool SystemZTargetCodeGenInfo::isVectorTypeBased(const 
Type *Ty,
   return false;
 }
 
+//===--===//
+// z/OS XPLINK ABI Implementation
+//===--===//
+
+namespace {
+
+class ZOSXPLinkABIInfo : public ABIInfo {
+  const unsigned GPRBits = 64;
+  bool HasVector;
+
+public:
+  ZOSXPLinkABIInfo(CodeGenTypes &CGT, bool HV) : ABIInfo(CGT), HasVector(HV) {}
+
+  bool isPromotableIntegerType(QualType Ty) const;
+  bool isCompoundType(QualType Ty) const;
+  bool isVectorArgumentType(QualType Ty) const;
+  bool isFPArgumentType(QualType Ty) const;
+  QualType getSingleElementType(QualType Ty) const;
+  unsigned getMaxAlignFromTypeDefs(QualType Ty) const;
+  std::optional getFPTypeOfComplexLikeType(QualType Ty) const;
+
+  ABIArgInfo classifyReturnType(QualType RetTy,
+unsigned functionCallConv) const;
+  ABIArgInfo classifyArgumentType(QualType ArgTy, bool IsNamedArg,
+  unsigned functionCallConv) const;
+
+  void computeInfo(CGFunctionInfo &FI) const override {
+if (!getCXXABI().classifyReturnType(FI))
+  FI.getReturnInfo() =
+  classifyReturnType(FI.getReturnType(), FI.getCallingConvention());
+
+unsigned NumRequiredArgs = FI.getNumRequiredArgs();
+unsigned ArgNo = 0;
+
+for (auto &I : FI.arguments()) {
+  bool IsNamedArg = ArgNo < NumRequiredArgs;
+  I.info =
+  classifyArgumentType(I.type, IsNamedArg, FI.getCallingConvention());
+  ++ArgNo;
+}
+  }
+
+  Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
+QualType Ty) const override;
+};
+
+class ZOSXPLinkTargetCodeGenInfo : public TargetCodeGenInfo {
+public:
+  ZOSXPLinkTargetCodeGenInfo(CodeGenTypes &CGT, bool HasVector)
+  : TargetCodeGenInfo(std::make_unique(CGT, HasVector)) {
+SwiftInfo =
+std::make_unique(CGT, /*SwiftErrorInRegister=*/false);
+  }
+};
+
+} // namespace
+
+// Return true if the ABI requires Ty to be passed sign- or zero-
+// extended to 64 bits.
+bool ZOSXPLinkABIInfo::isPromotableIntegerType(QualType Ty) const {
+  // Treat an enum type as its underlying type.
+  if (const EnumType *EnumTy = Ty->getAs())
+Ty = EnumTy->getDecl()->getIntegerType();
+
+  // Promotable integer types are required to be promoted by the ABI.
+  if (getContext().isPromotableIntegerType(Ty))
+return true;
+
+  if (const auto *EIT = Ty->getAs())
+if (EIT->getNumBits() < 64)
+  return true;
+
+  // In addition to the usual promotable integer types, we also need to
+  // extend all 32-bit types, since the ABI requires promotion to 64 bits.
+  if (const BuiltinType *BT = Ty->getAs())
+switch (BT->getKind()) {
+case BuiltinType::Int:
+case BuiltinType::UInt:
+  return true;
+default:
+  break;
+}
+
+  return false;
+}
+
+bool ZOSXPLinkABIInfo::isCompoundType(QualType Ty) const {
+  return (Ty->isAnyComplexType() || Ty->isVectorType() ||
+  isAggregateTypeForABI(Ty));
+}
+
+bool ZOSXPLinkABIInfo::isVectorArgumentType(QualType Ty) const {
+  return (HasVector && Ty->isVectorType() &&
+  getContext().getTypeSize(Ty) <= 128);
+}
+
+bool ZOSXPLinkABIInfo::isFPArgumentType(QualType Ty) const {
+  if (const BuiltinType *BT = Ty->getAs())
+switch (BT->getKind()) {
+case BuiltinType::Float:
+case BuiltinType::Double:
+case BuiltinType::LongDouble:
+  return true;
+default:
+  return false;
+}
+
+  return false;
+}
+
+QualType ZOSXPLinkABIInfo::getSingleElementType(QualType Ty) const {
+  if (const RecordType *RT = Ty->getAsStructureType()) {
+const RecordDecl *RD = RT->getDecl();
+QualType Found;
+
+// If this is a C++ record, check the bases first.
+if (const CXXRecordDecl *CXXRD = dyn_cast(RD))
+  for (const auto &I : CXXRD->bases()) {
+QualType Base = I.getType();
+
+// Empty bases don't affect things either way.
+if (isEmptyRecord(getContext(), Base, true))
+  continue;
+
+if (!Found.isNull())
+  return Ty;
+Found = getSingleElementType(Base);
+  }
+
+// Check the fields.
+for (const auto *FD : RD->fields()) {
+  // Unlike isSingleElementStruct(), empty structure and array fields
+  // do count.  So do anonymous bitfields that aren't zero-sized.
+  if (getContext().getLangOpts().CPlusPlus &&
+  FD->isZeroLengthBitField(getContext()))
+continue;
+
+  // Unlike isSingleElementStruct(), arrays do not count.
+  // Nested structures still do though.
+  if (!Found.isNull())
+return Ty;
+  Found = getSingleElementType(FD->getType());
+}
+
+// Unlike isSingleElementStruct(), trailing padding is allowed.
+if (!Found.isNull())
+  return Found;
+  }
+
+  return Ty;
+}
+
+unsigned ZOSXPLinkABIInfo::getMaxAlignFr

[clang] [SystemZ][z/OS] Implement z/OS XPLINK ABI (PR #91384)

2024-05-15 Thread Ulrich Weigand via cfe-commits


@@ -529,9 +530,401 @@ bool SystemZTargetCodeGenInfo::isVectorTypeBased(const 
Type *Ty,
   return false;
 }
 
+//===--===//
+// z/OS XPLINK ABI Implementation
+//===--===//
+
+namespace {
+
+class ZOSXPLinkABIInfo : public ABIInfo {
+  const unsigned GPRBits = 64;
+  bool HasVector;
+
+public:
+  ZOSXPLinkABIInfo(CodeGenTypes &CGT, bool HV) : ABIInfo(CGT), HasVector(HV) {}
+
+  bool isPromotableIntegerType(QualType Ty) const;
+  bool isCompoundType(QualType Ty) const;
+  bool isVectorArgumentType(QualType Ty) const;
+  bool isFPArgumentType(QualType Ty) const;
+  QualType getSingleElementType(QualType Ty) const;
+  unsigned getMaxAlignFromTypeDefs(QualType Ty) const;
+  std::optional getFPTypeOfComplexLikeType(QualType Ty) const;
+
+  ABIArgInfo classifyReturnType(QualType RetTy,
+unsigned functionCallConv) const;
+  ABIArgInfo classifyArgumentType(QualType ArgTy, bool IsNamedArg,
+  unsigned functionCallConv) const;
+
+  void computeInfo(CGFunctionInfo &FI) const override {
+if (!getCXXABI().classifyReturnType(FI))
+  FI.getReturnInfo() =
+  classifyReturnType(FI.getReturnType(), FI.getCallingConvention());
+
+unsigned NumRequiredArgs = FI.getNumRequiredArgs();
+unsigned ArgNo = 0;
+
+for (auto &I : FI.arguments()) {
+  bool IsNamedArg = ArgNo < NumRequiredArgs;
+  I.info =
+  classifyArgumentType(I.type, IsNamedArg, FI.getCallingConvention());
+  ++ArgNo;
+}
+  }
+
+  Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
+QualType Ty) const override;
+};
+
+class ZOSXPLinkTargetCodeGenInfo : public TargetCodeGenInfo {
+public:
+  ZOSXPLinkTargetCodeGenInfo(CodeGenTypes &CGT, bool HasVector)
+  : TargetCodeGenInfo(std::make_unique(CGT, HasVector)) {
+SwiftInfo =
+std::make_unique(CGT, /*SwiftErrorInRegister=*/false);
+  }
+};
+
+} // namespace
+
+// Return true if the ABI requires Ty to be passed sign- or zero-
+// extended to 64 bits.
+bool ZOSXPLinkABIInfo::isPromotableIntegerType(QualType Ty) const {
+  // Treat an enum type as its underlying type.
+  if (const EnumType *EnumTy = Ty->getAs())
+Ty = EnumTy->getDecl()->getIntegerType();
+
+  // Promotable integer types are required to be promoted by the ABI.
+  if (getContext().isPromotableIntegerType(Ty))
+return true;
+
+  if (const auto *EIT = Ty->getAs())
+if (EIT->getNumBits() < 64)
+  return true;
+
+  // In addition to the usual promotable integer types, we also need to
+  // extend all 32-bit types, since the ABI requires promotion to 64 bits.
+  if (const BuiltinType *BT = Ty->getAs())
+switch (BT->getKind()) {
+case BuiltinType::Int:
+case BuiltinType::UInt:
+  return true;
+default:
+  break;
+}
+
+  return false;
+}
+
+bool ZOSXPLinkABIInfo::isCompoundType(QualType Ty) const {
+  return (Ty->isAnyComplexType() || Ty->isVectorType() ||
+  isAggregateTypeForABI(Ty));
+}
+
+bool ZOSXPLinkABIInfo::isVectorArgumentType(QualType Ty) const {
+  return (HasVector && Ty->isVectorType() &&
+  getContext().getTypeSize(Ty) <= 128);
+}
+
+bool ZOSXPLinkABIInfo::isFPArgumentType(QualType Ty) const {
+  if (const BuiltinType *BT = Ty->getAs())
+switch (BT->getKind()) {
+case BuiltinType::Float:
+case BuiltinType::Double:
+case BuiltinType::LongDouble:
+  return true;
+default:
+  return false;
+}
+
+  return false;
+}
+
+QualType ZOSXPLinkABIInfo::getSingleElementType(QualType Ty) const {
+  if (const RecordType *RT = Ty->getAsStructureType()) {
+const RecordDecl *RD = RT->getDecl();
+QualType Found;
+
+// If this is a C++ record, check the bases first.
+if (const CXXRecordDecl *CXXRD = dyn_cast(RD))
+  for (const auto &I : CXXRD->bases()) {
+QualType Base = I.getType();
+
+// Empty bases don't affect things either way.
+if (isEmptyRecord(getContext(), Base, true))
+  continue;
+
+if (!Found.isNull())
+  return Ty;
+Found = getSingleElementType(Base);
+  }
+
+// Check the fields.
+for (const auto *FD : RD->fields()) {
+  // Unlike isSingleElementStruct(), empty structure and array fields
+  // do count.  So do anonymous bitfields that aren't zero-sized.
+  if (getContext().getLangOpts().CPlusPlus &&
+  FD->isZeroLengthBitField(getContext()))
+continue;
+
+  // Unlike isSingleElementStruct(), arrays do not count.
+  // Nested structures still do though.
+  if (!Found.isNull())
+return Ty;
+  Found = getSingleElementType(FD->getType());
+}
+
+// Unlike isSingleElementStruct(), trailing padding is allowed.
+if (!Found.isNull())
+  return Found;
+  }
+
+  return Ty;
+}
+
+unsigned ZOSXPLinkABIInfo::getMaxAlignFr

[clang] [SystemZ][z/OS] Implement z/OS XPLINK ABI (PR #91384)

2024-05-15 Thread Ulrich Weigand via cfe-commits


@@ -529,9 +530,401 @@ bool SystemZTargetCodeGenInfo::isVectorTypeBased(const 
Type *Ty,
   return false;
 }
 
+//===--===//
+// z/OS XPLINK ABI Implementation
+//===--===//
+
+namespace {
+
+class ZOSXPLinkABIInfo : public ABIInfo {
+  const unsigned GPRBits = 64;
+  bool HasVector;
+
+public:
+  ZOSXPLinkABIInfo(CodeGenTypes &CGT, bool HV) : ABIInfo(CGT), HasVector(HV) {}
+
+  bool isPromotableIntegerType(QualType Ty) const;
+  bool isCompoundType(QualType Ty) const;
+  bool isVectorArgumentType(QualType Ty) const;
+  bool isFPArgumentType(QualType Ty) const;
+  QualType getSingleElementType(QualType Ty) const;
+  unsigned getMaxAlignFromTypeDefs(QualType Ty) const;
+  std::optional getFPTypeOfComplexLikeType(QualType Ty) const;
+
+  ABIArgInfo classifyReturnType(QualType RetTy,
+unsigned functionCallConv) const;
+  ABIArgInfo classifyArgumentType(QualType ArgTy, bool IsNamedArg,
+  unsigned functionCallConv) const;
+
+  void computeInfo(CGFunctionInfo &FI) const override {
+if (!getCXXABI().classifyReturnType(FI))
+  FI.getReturnInfo() =
+  classifyReturnType(FI.getReturnType(), FI.getCallingConvention());
+
+unsigned NumRequiredArgs = FI.getNumRequiredArgs();
+unsigned ArgNo = 0;
+
+for (auto &I : FI.arguments()) {
+  bool IsNamedArg = ArgNo < NumRequiredArgs;
+  I.info =
+  classifyArgumentType(I.type, IsNamedArg, FI.getCallingConvention());
+  ++ArgNo;
+}
+  }
+
+  Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
+QualType Ty) const override;
+};
+
+class ZOSXPLinkTargetCodeGenInfo : public TargetCodeGenInfo {
+public:
+  ZOSXPLinkTargetCodeGenInfo(CodeGenTypes &CGT, bool HasVector)
+  : TargetCodeGenInfo(std::make_unique(CGT, HasVector)) {
+SwiftInfo =
+std::make_unique(CGT, /*SwiftErrorInRegister=*/false);
+  }
+};
+
+} // namespace
+
+// Return true if the ABI requires Ty to be passed sign- or zero-
+// extended to 64 bits.
+bool ZOSXPLinkABIInfo::isPromotableIntegerType(QualType Ty) const {
+  // Treat an enum type as its underlying type.
+  if (const EnumType *EnumTy = Ty->getAs())
+Ty = EnumTy->getDecl()->getIntegerType();
+
+  // Promotable integer types are required to be promoted by the ABI.
+  if (getContext().isPromotableIntegerType(Ty))
+return true;
+
+  if (const auto *EIT = Ty->getAs())
+if (EIT->getNumBits() < 64)
+  return true;
+
+  // In addition to the usual promotable integer types, we also need to
+  // extend all 32-bit types, since the ABI requires promotion to 64 bits.
+  if (const BuiltinType *BT = Ty->getAs())
+switch (BT->getKind()) {
+case BuiltinType::Int:
+case BuiltinType::UInt:
+  return true;
+default:
+  break;
+}
+
+  return false;
+}
+
+bool ZOSXPLinkABIInfo::isCompoundType(QualType Ty) const {
+  return (Ty->isAnyComplexType() || Ty->isVectorType() ||
+  isAggregateTypeForABI(Ty));
+}
+
+bool ZOSXPLinkABIInfo::isVectorArgumentType(QualType Ty) const {
+  return (HasVector && Ty->isVectorType() &&
+  getContext().getTypeSize(Ty) <= 128);
+}
+
+bool ZOSXPLinkABIInfo::isFPArgumentType(QualType Ty) const {
+  if (const BuiltinType *BT = Ty->getAs())
+switch (BT->getKind()) {
+case BuiltinType::Float:
+case BuiltinType::Double:
+case BuiltinType::LongDouble:
+  return true;
+default:
+  return false;
+}
+
+  return false;
+}
+
+QualType ZOSXPLinkABIInfo::getSingleElementType(QualType Ty) const {
+  if (const RecordType *RT = Ty->getAsStructureType()) {
+const RecordDecl *RD = RT->getDecl();
+QualType Found;
+
+// If this is a C++ record, check the bases first.
+if (const CXXRecordDecl *CXXRD = dyn_cast(RD))
+  for (const auto &I : CXXRD->bases()) {
+QualType Base = I.getType();
+
+// Empty bases don't affect things either way.
+if (isEmptyRecord(getContext(), Base, true))
+  continue;
+
+if (!Found.isNull())
+  return Ty;
+Found = getSingleElementType(Base);
+  }
+
+// Check the fields.
+for (const auto *FD : RD->fields()) {
+  // Unlike isSingleElementStruct(), empty structure and array fields
+  // do count.  So do anonymous bitfields that aren't zero-sized.
+  if (getContext().getLangOpts().CPlusPlus &&
+  FD->isZeroLengthBitField(getContext()))
+continue;
+
+  // Unlike isSingleElementStruct(), arrays do not count.
+  // Nested structures still do though.
+  if (!Found.isNull())
+return Ty;
+  Found = getSingleElementType(FD->getType());
+}
+
+// Unlike isSingleElementStruct(), trailing padding is allowed.
+if (!Found.isNull())
+  return Found;
+  }
+
+  return Ty;
+}
+
+unsigned ZOSXPLinkABIInfo::getMaxAlignFr

[clang] [SystemZ][z/OS] Implement z/OS XPLINK ABI (PR #91384)

2024-05-15 Thread Ulrich Weigand via cfe-commits


@@ -529,9 +530,401 @@ bool SystemZTargetCodeGenInfo::isVectorTypeBased(const 
Type *Ty,
   return false;
 }
 
+//===--===//
+// z/OS XPLINK ABI Implementation
+//===--===//
+
+namespace {
+
+class ZOSXPLinkABIInfo : public ABIInfo {
+  const unsigned GPRBits = 64;
+  bool HasVector;
+
+public:
+  ZOSXPLinkABIInfo(CodeGenTypes &CGT, bool HV) : ABIInfo(CGT), HasVector(HV) {}
+
+  bool isPromotableIntegerType(QualType Ty) const;
+  bool isCompoundType(QualType Ty) const;
+  bool isVectorArgumentType(QualType Ty) const;
+  bool isFPArgumentType(QualType Ty) const;
+  QualType getSingleElementType(QualType Ty) const;
+  unsigned getMaxAlignFromTypeDefs(QualType Ty) const;
+  std::optional getFPTypeOfComplexLikeType(QualType Ty) const;
+
+  ABIArgInfo classifyReturnType(QualType RetTy,
+unsigned functionCallConv) const;
+  ABIArgInfo classifyArgumentType(QualType ArgTy, bool IsNamedArg,
+  unsigned functionCallConv) const;
+
+  void computeInfo(CGFunctionInfo &FI) const override {
+if (!getCXXABI().classifyReturnType(FI))
+  FI.getReturnInfo() =
+  classifyReturnType(FI.getReturnType(), FI.getCallingConvention());
+
+unsigned NumRequiredArgs = FI.getNumRequiredArgs();
+unsigned ArgNo = 0;
+
+for (auto &I : FI.arguments()) {
+  bool IsNamedArg = ArgNo < NumRequiredArgs;
+  I.info =
+  classifyArgumentType(I.type, IsNamedArg, FI.getCallingConvention());
+  ++ArgNo;
+}
+  }
+
+  Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
+QualType Ty) const override;
+};
+
+class ZOSXPLinkTargetCodeGenInfo : public TargetCodeGenInfo {
+public:
+  ZOSXPLinkTargetCodeGenInfo(CodeGenTypes &CGT, bool HasVector)
+  : TargetCodeGenInfo(std::make_unique(CGT, HasVector)) {
+SwiftInfo =
+std::make_unique(CGT, /*SwiftErrorInRegister=*/false);
+  }
+};
+
+} // namespace
+
+// Return true if the ABI requires Ty to be passed sign- or zero-
+// extended to 64 bits.
+bool ZOSXPLinkABIInfo::isPromotableIntegerType(QualType Ty) const {
+  // Treat an enum type as its underlying type.
+  if (const EnumType *EnumTy = Ty->getAs())
+Ty = EnumTy->getDecl()->getIntegerType();
+
+  // Promotable integer types are required to be promoted by the ABI.
+  if (getContext().isPromotableIntegerType(Ty))
+return true;
+
+  if (const auto *EIT = Ty->getAs())
+if (EIT->getNumBits() < 64)
+  return true;
+
+  // In addition to the usual promotable integer types, we also need to
+  // extend all 32-bit types, since the ABI requires promotion to 64 bits.
+  if (const BuiltinType *BT = Ty->getAs())
+switch (BT->getKind()) {
+case BuiltinType::Int:
+case BuiltinType::UInt:
+  return true;
+default:
+  break;
+}
+
+  return false;
+}
+
+bool ZOSXPLinkABIInfo::isCompoundType(QualType Ty) const {
+  return (Ty->isAnyComplexType() || Ty->isVectorType() ||
+  isAggregateTypeForABI(Ty));
+}
+
+bool ZOSXPLinkABIInfo::isVectorArgumentType(QualType Ty) const {
+  return (HasVector && Ty->isVectorType() &&
+  getContext().getTypeSize(Ty) <= 128);
+}
+
+bool ZOSXPLinkABIInfo::isFPArgumentType(QualType Ty) const {
+  if (const BuiltinType *BT = Ty->getAs())
+switch (BT->getKind()) {
+case BuiltinType::Float:
+case BuiltinType::Double:
+case BuiltinType::LongDouble:
+  return true;
+default:
+  return false;
+}
+
+  return false;
+}
+
+QualType ZOSXPLinkABIInfo::getSingleElementType(QualType Ty) const {
+  if (const RecordType *RT = Ty->getAsStructureType()) {
+const RecordDecl *RD = RT->getDecl();
+QualType Found;
+
+// If this is a C++ record, check the bases first.
+if (const CXXRecordDecl *CXXRD = dyn_cast(RD))
+  for (const auto &I : CXXRD->bases()) {
+QualType Base = I.getType();
+
+// Empty bases don't affect things either way.
+if (isEmptyRecord(getContext(), Base, true))
+  continue;
+
+if (!Found.isNull())
+  return Ty;
+Found = getSingleElementType(Base);
+  }
+
+// Check the fields.
+for (const auto *FD : RD->fields()) {
+  // Unlike isSingleElementStruct(), empty structure and array fields
+  // do count.  So do anonymous bitfields that aren't zero-sized.
+  if (getContext().getLangOpts().CPlusPlus &&
+  FD->isZeroLengthBitField(getContext()))
+continue;
+
+  // Unlike isSingleElementStruct(), arrays do not count.
+  // Nested structures still do though.
+  if (!Found.isNull())
+return Ty;
+  Found = getSingleElementType(FD->getType());
+}
+
+// Unlike isSingleElementStruct(), trailing padding is allowed.
+if (!Found.isNull())
+  return Found;
+  }
+
+  return Ty;
+}
+
+unsigned ZOSXPLinkABIInfo::getMaxAlignFr

[clang] [SystemZ][z/OS] Implement z/OS XPLINK ABI (PR #91384)

2024-05-15 Thread Ulrich Weigand via cfe-commits


@@ -529,9 +530,401 @@ bool SystemZTargetCodeGenInfo::isVectorTypeBased(const 
Type *Ty,
   return false;
 }
 
+//===--===//
+// z/OS XPLINK ABI Implementation
+//===--===//
+
+namespace {
+
+class ZOSXPLinkABIInfo : public ABIInfo {
+  const unsigned GPRBits = 64;
+  bool HasVector;
+
+public:
+  ZOSXPLinkABIInfo(CodeGenTypes &CGT, bool HV) : ABIInfo(CGT), HasVector(HV) {}
+
+  bool isPromotableIntegerType(QualType Ty) const;
+  bool isCompoundType(QualType Ty) const;
+  bool isVectorArgumentType(QualType Ty) const;
+  bool isFPArgumentType(QualType Ty) const;
+  QualType getSingleElementType(QualType Ty) const;
+  unsigned getMaxAlignFromTypeDefs(QualType Ty) const;
+  std::optional getFPTypeOfComplexLikeType(QualType Ty) const;
+
+  ABIArgInfo classifyReturnType(QualType RetTy,
+unsigned functionCallConv) const;
+  ABIArgInfo classifyArgumentType(QualType ArgTy, bool IsNamedArg,
+  unsigned functionCallConv) const;
+
+  void computeInfo(CGFunctionInfo &FI) const override {
+if (!getCXXABI().classifyReturnType(FI))
+  FI.getReturnInfo() =
+  classifyReturnType(FI.getReturnType(), FI.getCallingConvention());
+
+unsigned NumRequiredArgs = FI.getNumRequiredArgs();
+unsigned ArgNo = 0;
+
+for (auto &I : FI.arguments()) {
+  bool IsNamedArg = ArgNo < NumRequiredArgs;
+  I.info =
+  classifyArgumentType(I.type, IsNamedArg, FI.getCallingConvention());
+  ++ArgNo;
+}
+  }
+
+  Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
+QualType Ty) const override;
+};
+
+class ZOSXPLinkTargetCodeGenInfo : public TargetCodeGenInfo {
+public:
+  ZOSXPLinkTargetCodeGenInfo(CodeGenTypes &CGT, bool HasVector)
+  : TargetCodeGenInfo(std::make_unique(CGT, HasVector)) {
+SwiftInfo =
+std::make_unique(CGT, /*SwiftErrorInRegister=*/false);
+  }
+};
+
+} // namespace
+
+// Return true if the ABI requires Ty to be passed sign- or zero-
+// extended to 64 bits.
+bool ZOSXPLinkABIInfo::isPromotableIntegerType(QualType Ty) const {
+  // Treat an enum type as its underlying type.
+  if (const EnumType *EnumTy = Ty->getAs())
+Ty = EnumTy->getDecl()->getIntegerType();
+
+  // Promotable integer types are required to be promoted by the ABI.
+  if (getContext().isPromotableIntegerType(Ty))
+return true;
+
+  if (const auto *EIT = Ty->getAs())
+if (EIT->getNumBits() < 64)
+  return true;
+
+  // In addition to the usual promotable integer types, we also need to
+  // extend all 32-bit types, since the ABI requires promotion to 64 bits.
+  if (const BuiltinType *BT = Ty->getAs())
+switch (BT->getKind()) {
+case BuiltinType::Int:
+case BuiltinType::UInt:
+  return true;
+default:
+  break;
+}
+
+  return false;
+}
+
+bool ZOSXPLinkABIInfo::isCompoundType(QualType Ty) const {
+  return (Ty->isAnyComplexType() || Ty->isVectorType() ||
+  isAggregateTypeForABI(Ty));
+}
+
+bool ZOSXPLinkABIInfo::isVectorArgumentType(QualType Ty) const {
+  return (HasVector && Ty->isVectorType() &&
+  getContext().getTypeSize(Ty) <= 128);
+}
+
+bool ZOSXPLinkABIInfo::isFPArgumentType(QualType Ty) const {
+  if (const BuiltinType *BT = Ty->getAs())
+switch (BT->getKind()) {
+case BuiltinType::Float:
+case BuiltinType::Double:
+case BuiltinType::LongDouble:
+  return true;
+default:
+  return false;
+}
+
+  return false;
+}
+
+QualType ZOSXPLinkABIInfo::getSingleElementType(QualType Ty) const {
+  if (const RecordType *RT = Ty->getAsStructureType()) {
+const RecordDecl *RD = RT->getDecl();
+QualType Found;
+
+// If this is a C++ record, check the bases first.
+if (const CXXRecordDecl *CXXRD = dyn_cast(RD))
+  for (const auto &I : CXXRD->bases()) {
+QualType Base = I.getType();
+
+// Empty bases don't affect things either way.
+if (isEmptyRecord(getContext(), Base, true))
+  continue;
+
+if (!Found.isNull())
+  return Ty;
+Found = getSingleElementType(Base);
+  }
+
+// Check the fields.
+for (const auto *FD : RD->fields()) {
+  // Unlike isSingleElementStruct(), empty structure and array fields
+  // do count.  So do anonymous bitfields that aren't zero-sized.
+  if (getContext().getLangOpts().CPlusPlus &&
+  FD->isZeroLengthBitField(getContext()))
+continue;
+
+  // Unlike isSingleElementStruct(), arrays do not count.
+  // Nested structures still do though.
+  if (!Found.isNull())
+return Ty;
+  Found = getSingleElementType(FD->getType());
+}
+
+// Unlike isSingleElementStruct(), trailing padding is allowed.
+if (!Found.isNull())
+  return Found;
+  }
+
+  return Ty;
+}
+
+unsigned ZOSXPLinkABIInfo::getMaxAlignFr

[clang] [SystemZ][z/OS] Implement z/OS XPLINK ABI (PR #91384)

2024-05-15 Thread Ulrich Weigand via cfe-commits


@@ -529,9 +530,401 @@ bool SystemZTargetCodeGenInfo::isVectorTypeBased(const 
Type *Ty,
   return false;
 }
 
+//===--===//
+// z/OS XPLINK ABI Implementation
+//===--===//
+
+namespace {
+
+class ZOSXPLinkABIInfo : public ABIInfo {
+  const unsigned GPRBits = 64;
+  bool HasVector;
+
+public:
+  ZOSXPLinkABIInfo(CodeGenTypes &CGT, bool HV) : ABIInfo(CGT), HasVector(HV) {}
+
+  bool isPromotableIntegerType(QualType Ty) const;
+  bool isCompoundType(QualType Ty) const;
+  bool isVectorArgumentType(QualType Ty) const;
+  bool isFPArgumentType(QualType Ty) const;
+  QualType getSingleElementType(QualType Ty) const;
+  unsigned getMaxAlignFromTypeDefs(QualType Ty) const;
+  std::optional getFPTypeOfComplexLikeType(QualType Ty) const;
+
+  ABIArgInfo classifyReturnType(QualType RetTy,
+unsigned functionCallConv) const;
+  ABIArgInfo classifyArgumentType(QualType ArgTy, bool IsNamedArg,
+  unsigned functionCallConv) const;
+
+  void computeInfo(CGFunctionInfo &FI) const override {
+if (!getCXXABI().classifyReturnType(FI))
+  FI.getReturnInfo() =
+  classifyReturnType(FI.getReturnType(), FI.getCallingConvention());
+
+unsigned NumRequiredArgs = FI.getNumRequiredArgs();
+unsigned ArgNo = 0;
+
+for (auto &I : FI.arguments()) {
+  bool IsNamedArg = ArgNo < NumRequiredArgs;
+  I.info =
+  classifyArgumentType(I.type, IsNamedArg, FI.getCallingConvention());
+  ++ArgNo;
+}
+  }
+
+  Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
+QualType Ty) const override;
+};
+
+class ZOSXPLinkTargetCodeGenInfo : public TargetCodeGenInfo {
+public:
+  ZOSXPLinkTargetCodeGenInfo(CodeGenTypes &CGT, bool HasVector)
+  : TargetCodeGenInfo(std::make_unique(CGT, HasVector)) {
+SwiftInfo =
+std::make_unique(CGT, /*SwiftErrorInRegister=*/false);
+  }
+};
+
+} // namespace
+
+// Return true if the ABI requires Ty to be passed sign- or zero-
+// extended to 64 bits.
+bool ZOSXPLinkABIInfo::isPromotableIntegerType(QualType Ty) const {
+  // Treat an enum type as its underlying type.
+  if (const EnumType *EnumTy = Ty->getAs())
+Ty = EnumTy->getDecl()->getIntegerType();
+
+  // Promotable integer types are required to be promoted by the ABI.
+  if (getContext().isPromotableIntegerType(Ty))
+return true;
+
+  if (const auto *EIT = Ty->getAs())
+if (EIT->getNumBits() < 64)
+  return true;
+
+  // In addition to the usual promotable integer types, we also need to
+  // extend all 32-bit types, since the ABI requires promotion to 64 bits.
+  if (const BuiltinType *BT = Ty->getAs())
+switch (BT->getKind()) {
+case BuiltinType::Int:
+case BuiltinType::UInt:
+  return true;
+default:
+  break;
+}
+
+  return false;
+}
+
+bool ZOSXPLinkABIInfo::isCompoundType(QualType Ty) const {
+  return (Ty->isAnyComplexType() || Ty->isVectorType() ||
+  isAggregateTypeForABI(Ty));
+}
+
+bool ZOSXPLinkABIInfo::isVectorArgumentType(QualType Ty) const {
+  return (HasVector && Ty->isVectorType() &&
+  getContext().getTypeSize(Ty) <= 128);
+}
+
+bool ZOSXPLinkABIInfo::isFPArgumentType(QualType Ty) const {
+  if (const BuiltinType *BT = Ty->getAs())
+switch (BT->getKind()) {
+case BuiltinType::Float:
+case BuiltinType::Double:
+case BuiltinType::LongDouble:
+  return true;
+default:
+  return false;
+}
+
+  return false;
+}
+
+QualType ZOSXPLinkABIInfo::getSingleElementType(QualType Ty) const {
+  if (const RecordType *RT = Ty->getAsStructureType()) {
+const RecordDecl *RD = RT->getDecl();
+QualType Found;
+
+// If this is a C++ record, check the bases first.
+if (const CXXRecordDecl *CXXRD = dyn_cast(RD))
+  for (const auto &I : CXXRD->bases()) {
+QualType Base = I.getType();
+
+// Empty bases don't affect things either way.
+if (isEmptyRecord(getContext(), Base, true))
+  continue;
+
+if (!Found.isNull())
+  return Ty;
+Found = getSingleElementType(Base);
+  }
+
+// Check the fields.
+for (const auto *FD : RD->fields()) {
+  // Unlike isSingleElementStruct(), empty structure and array fields
+  // do count.  So do anonymous bitfields that aren't zero-sized.
+  if (getContext().getLangOpts().CPlusPlus &&
+  FD->isZeroLengthBitField(getContext()))
+continue;
+
+  // Unlike isSingleElementStruct(), arrays do not count.
+  // Nested structures still do though.
+  if (!Found.isNull())
+return Ty;
+  Found = getSingleElementType(FD->getType());
+}
+
+// Unlike isSingleElementStruct(), trailing padding is allowed.
+if (!Found.isNull())
+  return Found;
+  }
+
+  return Ty;
+}
+
+unsigned ZOSXPLinkABIInfo::getMaxAlignFr

[clang] [SystemZ][z/OS] Implement z/OS XPLINK ABI (PR #91384)

2024-05-15 Thread Ulrich Weigand via cfe-commits


@@ -0,0 +1,137 @@
+// RUN: %clang_cc1 -triple s390x-ibm-zos \
+// RUN:   -emit-llvm -no-enable-noundef-analysis -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple s390x-ibm-zos -target-feature +vector \
+// RUN:   -emit-llvm -no-enable-noundef-analysis -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple s390x-ibm-zos -target-cpu z13 \
+// RUN:   -emit-llvm -no-enable-noundef-analysis -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple s390x-ibm-zos -target-cpu arch11 \
+// RUN:   -emit-llvm -no-enable-noundef-analysis -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple s390x-ibm-zos -target-cpu z14 \
+// RUN:   -emit-llvm -no-enable-noundef-analysis -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple s390x-ibm-zos -target-cpu arch12 \
+// RUN:   -emit-llvm -no-enable-noundef-analysis -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple s390x-ibm-zos -target-cpu z15 \
+// RUN:   -emit-llvm -no-enable-noundef-analysis -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple s390x-ibm-zos -target-cpu arch13 \
+// RUN:   -emit-llvm -no-enable-noundef-analysis -o - %s | FileCheck %s
+
+// Scalar types
+
+char pass_char(char arg) { return arg; }
+// CHECK-LABEL: define signext i8 @pass_char(i8 signext %{{.*}})
+
+short pass_short(short arg) { return arg; }
+// CHECK-LABEL: define signext i16 @pass_short(i16 signext %{{.*}})
+
+int pass_int(int arg) { return arg; }
+// CHECK-LABEL: define signext i32 @pass_int(i32 signext %{{.*}})
+
+long pass_long(long arg) { return arg; }
+// CHECK-LABEL: define i64 @pass_long(i64 %{{.*}})
+
+long long pass_longlong(long long arg) { return arg; }
+// CHECK-LABEL: define i64 @pass_longlong(i64 %{{.*}})
+
+float pass_float(float arg) { return arg; }
+// CHECK-LABEL: define float @pass_float(float %{{.*}})
+
+double pass_double(double arg) { return arg; }
+// CHECK-LABEL: define double @pass_double(double %{{.*}})
+
+long double pass_longdouble(long double arg) { return arg; }
+// CHECK-LABEL: define fp128 @pass_longdouble(fp128 %{{.*}})
+
+enum Color { Red, Blue };
+enum Color pass_enum(enum Color arg) { return arg; }
+// CHECK-LABEL: define zeroext i32 @pass_enum(i32 zeroext %{{.*}})
+
+// Complex types
+
+// TODO: Add tests for complex integer types
+
+_Complex float pass_complex_float(_Complex float arg) { return arg; }
+// CHECK-LABEL: define { float, float } @pass_complex_float(float %{{.*}}, 
float %{{.*}})
+
+_Complex double pass_complex_double(_Complex double arg) { return arg; }
+// CHECK-LABEL: define { double, double } @pass_complex_double(double %{{.*}}, 
double %{{.*}})
+
+_Complex long double pass_complex_longdouble(_Complex long double arg) { 
return arg; }
+// CHECK-LABEL: define { fp128, fp128 } @pass_complex_longdouble(fp128 
%{{.*}}, fp128 %{{.*}})
+
+// Verify that the following are complex-like types
+struct complexlike_float { float re, im; };
+struct complexlike_float pass_complexlike_float(struct complexlike_float arg) 
{ return arg; }
+// CHECK-LABEL: define %struct.complexlike_float @pass_complexlike_float(float 
%{{.*}}, float %{{.*}})
+
+struct complexlike_double { double re, im; };
+struct complexlike_double pass_complexlike_double(struct complexlike_double 
arg) { return arg; }
+// CHECK-LABEL: define %struct.complexlike_double 
@pass_complexlike_double(double %{{.*}}, double %{{.*}})
+
+struct complexlike_longdouble { long double re, im; };
+struct complexlike_longdouble pass_complexlike_longdouble(struct 
complexlike_longdouble arg) { return arg; }
+// CHECK-LABEL: define %struct.complexlike_longdouble 
@pass_complexlike_longdouble(fp128 %{{.*}}, fp128 %{{.*}})
+
+// Aggregate types
+

uweigand wrote:

As to single-element struct, I'm refering to all the various special cases the 
code checks for.  They should have tests that verify the intended behaviour.  
(And those tests should also be verified against the actual behavior of the 
legacy compilers.)  In particular, does it count as single-element struct if:
- we have any padding
- we have a single element that is itself a single-element struct
- we have a single element that is a single-element array
- we have an element that is a bitfield of size zero (named or unnamed)
- we have an element that is a bitfield of nonzero size
- we have an element that is an empty struct
- we have an element that is an empty array
- it's a C++ class that has a C++20 empty data member (NoUniqueAddressAttr)
- it's a C++ class that has an empty base class
- it's a C++ class that has a non-empty base class


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


[clang] [SystemZ][z/OS] Implement z/OS XPLINK ABI (PR #91384)

2024-05-15 Thread Ulrich Weigand via cfe-commits


@@ -529,9 +530,401 @@ bool SystemZTargetCodeGenInfo::isVectorTypeBased(const 
Type *Ty,
   return false;
 }
 
+//===--===//
+// z/OS XPLINK ABI Implementation
+//===--===//
+
+namespace {
+
+class ZOSXPLinkABIInfo : public ABIInfo {
+  const unsigned GPRBits = 64;
+  bool HasVector;
+
+public:
+  ZOSXPLinkABIInfo(CodeGenTypes &CGT, bool HV) : ABIInfo(CGT), HasVector(HV) {}
+
+  bool isPromotableIntegerType(QualType Ty) const;
+  bool isCompoundType(QualType Ty) const;
+  bool isVectorArgumentType(QualType Ty) const;
+  bool isFPArgumentType(QualType Ty) const;
+  QualType getSingleElementType(QualType Ty) const;
+  unsigned getMaxAlignFromTypeDefs(QualType Ty) const;
+  std::optional getFPTypeOfComplexLikeType(QualType Ty) const;
+
+  ABIArgInfo classifyReturnType(QualType RetTy,
+unsigned functionCallConv) const;
+  ABIArgInfo classifyArgumentType(QualType ArgTy, bool IsNamedArg,
+  unsigned functionCallConv) const;
+
+  void computeInfo(CGFunctionInfo &FI) const override {
+if (!getCXXABI().classifyReturnType(FI))
+  FI.getReturnInfo() =
+  classifyReturnType(FI.getReturnType(), FI.getCallingConvention());
+
+unsigned NumRequiredArgs = FI.getNumRequiredArgs();
+unsigned ArgNo = 0;
+
+for (auto &I : FI.arguments()) {
+  bool IsNamedArg = ArgNo < NumRequiredArgs;
+  I.info =
+  classifyArgumentType(I.type, IsNamedArg, FI.getCallingConvention());
+  ++ArgNo;
+}
+  }
+
+  Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
+QualType Ty) const override;
+};
+
+class ZOSXPLinkTargetCodeGenInfo : public TargetCodeGenInfo {
+public:
+  ZOSXPLinkTargetCodeGenInfo(CodeGenTypes &CGT, bool HasVector)
+  : TargetCodeGenInfo(std::make_unique(CGT, HasVector)) {
+SwiftInfo =
+std::make_unique(CGT, /*SwiftErrorInRegister=*/false);
+  }
+};
+
+} // namespace
+
+// Return true if the ABI requires Ty to be passed sign- or zero-
+// extended to 64 bits.
+bool ZOSXPLinkABIInfo::isPromotableIntegerType(QualType Ty) const {
+  // Treat an enum type as its underlying type.
+  if (const EnumType *EnumTy = Ty->getAs())
+Ty = EnumTy->getDecl()->getIntegerType();
+
+  // Promotable integer types are required to be promoted by the ABI.
+  if (getContext().isPromotableIntegerType(Ty))
+return true;
+
+  if (const auto *EIT = Ty->getAs())
+if (EIT->getNumBits() < 64)
+  return true;
+
+  // In addition to the usual promotable integer types, we also need to
+  // extend all 32-bit types, since the ABI requires promotion to 64 bits.
+  if (const BuiltinType *BT = Ty->getAs())
+switch (BT->getKind()) {
+case BuiltinType::Int:
+case BuiltinType::UInt:
+  return true;
+default:
+  break;
+}
+
+  return false;
+}
+
+bool ZOSXPLinkABIInfo::isCompoundType(QualType Ty) const {
+  return (Ty->isAnyComplexType() || Ty->isVectorType() ||
+  isAggregateTypeForABI(Ty));
+}
+
+bool ZOSXPLinkABIInfo::isVectorArgumentType(QualType Ty) const {
+  return (HasVector && Ty->isVectorType() &&
+  getContext().getTypeSize(Ty) <= 128);
+}
+
+bool ZOSXPLinkABIInfo::isFPArgumentType(QualType Ty) const {
+  if (const BuiltinType *BT = Ty->getAs())
+switch (BT->getKind()) {
+case BuiltinType::Float:
+case BuiltinType::Double:
+case BuiltinType::LongDouble:
+  return true;
+default:
+  return false;
+}
+
+  return false;
+}
+
+QualType ZOSXPLinkABIInfo::getSingleElementType(QualType Ty) const {
+  if (const RecordType *RT = Ty->getAsStructureType()) {
+const RecordDecl *RD = RT->getDecl();
+QualType Found;
+
+// If this is a C++ record, check the bases first.
+if (const CXXRecordDecl *CXXRD = dyn_cast(RD))
+  for (const auto &I : CXXRD->bases()) {
+QualType Base = I.getType();
+
+// Empty bases don't affect things either way.
+if (isEmptyRecord(getContext(), Base, true))
+  continue;
+
+if (!Found.isNull())
+  return Ty;
+Found = getSingleElementType(Base);
+  }
+
+// Check the fields.
+for (const auto *FD : RD->fields()) {
+  // Unlike isSingleElementStruct(), empty structure and array fields
+  // do count.  So do anonymous bitfields that aren't zero-sized.
+  if (getContext().getLangOpts().CPlusPlus &&
+  FD->isZeroLengthBitField(getContext()))
+continue;
+
+  // Unlike isSingleElementStruct(), arrays do not count.
+  // Nested structures still do though.
+  if (!Found.isNull())
+return Ty;
+  Found = getSingleElementType(FD->getType());
+}
+
+// Unlike isSingleElementStruct(), trailing padding is allowed.
+if (!Found.isNull())
+  return Found;
+  }
+
+  return Ty;
+}
+
+unsigned ZOSXPLinkABIInfo::getMaxAlignFr

[clang] [SystemZ][z/OS] Implement z/OS XPLINK ABI (PR #91384)

2024-05-15 Thread Ulrich Weigand via cfe-commits


@@ -529,9 +529,324 @@ bool SystemZTargetCodeGenInfo::isVectorTypeBased(const 
Type *Ty,
   return false;
 }
 
+//===--===//
+// z/OS XPLINK ABI Implementation
+//===--===//
+
+namespace {
+
+class ZOSXPLinkABIInfo : public ABIInfo {
+  static const unsigned GPRBits = 64;
+  bool HasVector;
+
+public:
+  ZOSXPLinkABIInfo(CodeGenTypes &CGT, bool HV) : ABIInfo(CGT), HasVector(HV) {}
+
+  bool isPromotableIntegerType(QualType Ty) const;
+  bool isCompoundType(QualType Ty) const;
+  bool isVectorArgumentType(QualType Ty) const;
+  bool isFPArgumentType(QualType Ty) const;
+  QualType GetSingleElementType(QualType Ty) const;
+  bool IsLikeComplexType(QualType Ty) const;
+
+  ABIArgInfo classifyReturnType(QualType RetTy) const;
+  ABIArgInfo classifyArgumentType(QualType ArgTy, bool IsNamedArg) const;
+
+  void computeInfo(CGFunctionInfo &FI) const override {
+if (!getCXXABI().classifyReturnType(FI))
+  FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
+
+unsigned NumRequiredArgs = FI.getNumRequiredArgs();
+unsigned ArgNo = 0;
+
+for (auto &I : FI.arguments()) {
+  bool IsNamedArg = ArgNo < NumRequiredArgs;
+  I.info = classifyArgumentType(I.type, IsNamedArg);
+  ++ArgNo;
+}
+  }
+
+  Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
+QualType Ty) const override;
+};
+
+class ZOSXPLinkTargetCodeGenInfo : public TargetCodeGenInfo {
+public:
+  ZOSXPLinkTargetCodeGenInfo(CodeGenTypes &CGT, bool HasVector)
+  : TargetCodeGenInfo(std::make_unique(CGT, HasVector)) {
+SwiftInfo =
+std::make_unique(CGT, /*SwiftErrorInRegister=*/false);
+  }
+};
+
+} // namespace
+
+// Return true if the ABI requires Ty to be passed sign- or zero-
+// extended to 64 bits.
+bool ZOSXPLinkABIInfo::isPromotableIntegerType(QualType Ty) const {
+  // Treat an enum type as its underlying type.
+  if (const EnumType *EnumTy = Ty->getAs())
+Ty = EnumTy->getDecl()->getIntegerType();
+
+  // Promotable integer types are required to be promoted by the ABI.
+  if (getContext().isPromotableIntegerType(Ty))
+return true;
+
+  // In addition to the usual promotable integer types, we also need to
+  // extend all 32-bit types, since the ABI requires promotion to 64 bits.
+  if (const BuiltinType *BT = Ty->getAs())
+switch (BT->getKind()) {
+case BuiltinType::Int:
+case BuiltinType::UInt:
+  return true;
+default:
+  break;
+}
+
+  return false;
+}
+
+bool ZOSXPLinkABIInfo::isCompoundType(QualType Ty) const {
+  return (Ty->isAnyComplexType() || Ty->isVectorType() ||
+  isAggregateTypeForABI(Ty));
+}
+
+bool ZOSXPLinkABIInfo::isVectorArgumentType(QualType Ty) const {
+  return (HasVector && Ty->isVectorType() &&
+  getContext().getTypeSize(Ty) <= 128);
+}
+
+bool ZOSXPLinkABIInfo::isFPArgumentType(QualType Ty) const {
+  if (const BuiltinType *BT = Ty->getAs())
+switch (BT->getKind()) {
+case BuiltinType::Float:
+case BuiltinType::Double:
+case BuiltinType::LongDouble:
+  return true;
+default:
+  return false;
+}
+
+  return false;
+}
+
+QualType ZOSXPLinkABIInfo::GetSingleElementType(QualType Ty) const {
+  if (const RecordType *RT = Ty->getAsStructureType()) {
+const RecordDecl *RD = RT->getDecl();
+QualType Found;
+
+// If this is a C++ record, check the bases first.
+if (const CXXRecordDecl *CXXRD = dyn_cast(RD))
+  for (const auto &I : CXXRD->bases()) {
+QualType Base = I.getType();
+
+// Empty bases don't affect things either way.
+if (isEmptyRecord(getContext(), Base, true))
+  continue;
+
+if (!Found.isNull())
+  return Ty;
+Found = GetSingleElementType(Base);
+  }
+
+// Check the fields.
+for (const auto *FD : RD->fields()) {
+  // For compatibility with GCC, ignore empty bitfields in C++ mode.
+  // Unlike isSingleElementStruct(), empty structure and array fields
+  // do count.  So do anonymous bitfields that aren't zero-sized.
+  if (getContext().getLangOpts().CPlusPlus &&
+  FD->isZeroLengthBitField(getContext()))
+continue;
+
+  // Unlike isSingleElementStruct(), arrays do not count.
+  // Nested structures still do though.
+  if (!Found.isNull())
+return Ty;
+  Found = GetSingleElementType(FD->getType());
+}
+
+// Unlike isSingleElementStruct(), trailing padding is allowed.
+// An 8-byte aligned struct s { float f; } is passed as a double.

uweigand wrote:

Well, is it *true* in your ABI that trailing padding is allowed here?  If not, 
then the code to reject it needs to be added back as isSingleElementStruct does 
...

https://github.com/llvm/llvm-project/pull/91384
___
cfe-commits mailing list
cfe-co

[clang] [SystemZ][z/OS] Implement z/OS XPLINK ABI (PR #91384)

2024-05-08 Thread Ulrich Weigand via cfe-commits


@@ -529,9 +529,324 @@ bool SystemZTargetCodeGenInfo::isVectorTypeBased(const 
Type *Ty,
   return false;
 }
 
+//===--===//
+// z/OS XPLINK ABI Implementation
+//===--===//
+
+namespace {
+
+class ZOSXPLinkABIInfo : public ABIInfo {
+  static const unsigned GPRBits = 64;
+  bool HasVector;
+
+public:
+  ZOSXPLinkABIInfo(CodeGenTypes &CGT, bool HV) : ABIInfo(CGT), HasVector(HV) {}
+
+  bool isPromotableIntegerType(QualType Ty) const;
+  bool isCompoundType(QualType Ty) const;
+  bool isVectorArgumentType(QualType Ty) const;
+  bool isFPArgumentType(QualType Ty) const;
+  QualType GetSingleElementType(QualType Ty) const;
+  bool IsLikeComplexType(QualType Ty) const;
+
+  ABIArgInfo classifyReturnType(QualType RetTy) const;
+  ABIArgInfo classifyArgumentType(QualType ArgTy, bool IsNamedArg) const;
+
+  void computeInfo(CGFunctionInfo &FI) const override {
+if (!getCXXABI().classifyReturnType(FI))
+  FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
+
+unsigned NumRequiredArgs = FI.getNumRequiredArgs();
+unsigned ArgNo = 0;
+
+for (auto &I : FI.arguments()) {
+  bool IsNamedArg = ArgNo < NumRequiredArgs;
+  I.info = classifyArgumentType(I.type, IsNamedArg);
+  ++ArgNo;
+}
+  }
+
+  Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
+QualType Ty) const override;
+};
+
+class ZOSXPLinkTargetCodeGenInfo : public TargetCodeGenInfo {
+public:
+  ZOSXPLinkTargetCodeGenInfo(CodeGenTypes &CGT, bool HasVector)
+  : TargetCodeGenInfo(std::make_unique(CGT, HasVector)) {
+SwiftInfo =
+std::make_unique(CGT, /*SwiftErrorInRegister=*/false);
+  }
+};
+
+} // namespace
+
+// Return true if the ABI requires Ty to be passed sign- or zero-
+// extended to 64 bits.
+bool ZOSXPLinkABIInfo::isPromotableIntegerType(QualType Ty) const {
+  // Treat an enum type as its underlying type.
+  if (const EnumType *EnumTy = Ty->getAs())
+Ty = EnumTy->getDecl()->getIntegerType();
+
+  // Promotable integer types are required to be promoted by the ABI.
+  if (getContext().isPromotableIntegerType(Ty))
+return true;
+
+  // In addition to the usual promotable integer types, we also need to
+  // extend all 32-bit types, since the ABI requires promotion to 64 bits.
+  if (const BuiltinType *BT = Ty->getAs())
+switch (BT->getKind()) {
+case BuiltinType::Int:
+case BuiltinType::UInt:
+  return true;
+default:
+  break;
+}
+
+  return false;
+}
+
+bool ZOSXPLinkABIInfo::isCompoundType(QualType Ty) const {
+  return (Ty->isAnyComplexType() || Ty->isVectorType() ||
+  isAggregateTypeForABI(Ty));
+}
+
+bool ZOSXPLinkABIInfo::isVectorArgumentType(QualType Ty) const {
+  return (HasVector && Ty->isVectorType() &&
+  getContext().getTypeSize(Ty) <= 128);
+}
+
+bool ZOSXPLinkABIInfo::isFPArgumentType(QualType Ty) const {
+  if (const BuiltinType *BT = Ty->getAs())
+switch (BT->getKind()) {
+case BuiltinType::Float:
+case BuiltinType::Double:
+case BuiltinType::LongDouble:
+  return true;
+default:
+  return false;
+}
+
+  return false;
+}
+
+QualType ZOSXPLinkABIInfo::GetSingleElementType(QualType Ty) const {
+  if (const RecordType *RT = Ty->getAsStructureType()) {
+const RecordDecl *RD = RT->getDecl();
+QualType Found;
+
+// If this is a C++ record, check the bases first.
+if (const CXXRecordDecl *CXXRD = dyn_cast(RD))
+  for (const auto &I : CXXRD->bases()) {
+QualType Base = I.getType();
+
+// Empty bases don't affect things either way.
+if (isEmptyRecord(getContext(), Base, true))
+  continue;
+
+if (!Found.isNull())
+  return Ty;
+Found = GetSingleElementType(Base);
+  }
+
+// Check the fields.
+for (const auto *FD : RD->fields()) {
+  // For compatibility with GCC, ignore empty bitfields in C++ mode.
+  // Unlike isSingleElementStruct(), empty structure and array fields
+  // do count.  So do anonymous bitfields that aren't zero-sized.
+  if (getContext().getLangOpts().CPlusPlus &&
+  FD->isZeroLengthBitField(getContext()))
+continue;
+
+  // Unlike isSingleElementStruct(), arrays do not count.
+  // Nested structures still do though.
+  if (!Found.isNull())
+return Ty;
+  Found = GetSingleElementType(FD->getType());
+}
+
+// Unlike isSingleElementStruct(), trailing padding is allowed.
+// An 8-byte aligned struct s { float f; } is passed as a double.
+if (!Found.isNull())
+  return Found;
+  }
+
+  return Ty;
+}
+
+bool ZOSXPLinkABIInfo::IsLikeComplexType(QualType Ty) const {
+  if (const RecordType *RT = Ty->getAsStructureType()) {
+const RecordDecl *RD = RT->getDecl();
+int i = 0;
+clang::BuiltinType::Kind elemKind;
+
+// Check for exactly two el

[clang] [SystemZ][z/OS] Implement z/OS XPLINK ABI (PR #91384)

2024-05-08 Thread Ulrich Weigand via cfe-commits


@@ -529,9 +529,324 @@ bool SystemZTargetCodeGenInfo::isVectorTypeBased(const 
Type *Ty,
   return false;
 }
 
+//===--===//
+// z/OS XPLINK ABI Implementation
+//===--===//
+
+namespace {
+
+class ZOSXPLinkABIInfo : public ABIInfo {
+  static const unsigned GPRBits = 64;
+  bool HasVector;
+
+public:
+  ZOSXPLinkABIInfo(CodeGenTypes &CGT, bool HV) : ABIInfo(CGT), HasVector(HV) {}
+
+  bool isPromotableIntegerType(QualType Ty) const;
+  bool isCompoundType(QualType Ty) const;
+  bool isVectorArgumentType(QualType Ty) const;
+  bool isFPArgumentType(QualType Ty) const;
+  QualType GetSingleElementType(QualType Ty) const;
+  bool IsLikeComplexType(QualType Ty) const;
+
+  ABIArgInfo classifyReturnType(QualType RetTy) const;
+  ABIArgInfo classifyArgumentType(QualType ArgTy, bool IsNamedArg) const;
+
+  void computeInfo(CGFunctionInfo &FI) const override {
+if (!getCXXABI().classifyReturnType(FI))
+  FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
+
+unsigned NumRequiredArgs = FI.getNumRequiredArgs();
+unsigned ArgNo = 0;
+
+for (auto &I : FI.arguments()) {
+  bool IsNamedArg = ArgNo < NumRequiredArgs;
+  I.info = classifyArgumentType(I.type, IsNamedArg);
+  ++ArgNo;
+}
+  }
+
+  Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
+QualType Ty) const override;
+};
+
+class ZOSXPLinkTargetCodeGenInfo : public TargetCodeGenInfo {
+public:
+  ZOSXPLinkTargetCodeGenInfo(CodeGenTypes &CGT, bool HasVector)
+  : TargetCodeGenInfo(std::make_unique(CGT, HasVector)) {
+SwiftInfo =
+std::make_unique(CGT, /*SwiftErrorInRegister=*/false);
+  }
+};
+
+} // namespace
+
+// Return true if the ABI requires Ty to be passed sign- or zero-
+// extended to 64 bits.
+bool ZOSXPLinkABIInfo::isPromotableIntegerType(QualType Ty) const {
+  // Treat an enum type as its underlying type.
+  if (const EnumType *EnumTy = Ty->getAs())
+Ty = EnumTy->getDecl()->getIntegerType();
+
+  // Promotable integer types are required to be promoted by the ABI.
+  if (getContext().isPromotableIntegerType(Ty))
+return true;
+
+  // In addition to the usual promotable integer types, we also need to
+  // extend all 32-bit types, since the ABI requires promotion to 64 bits.
+  if (const BuiltinType *BT = Ty->getAs())
+switch (BT->getKind()) {
+case BuiltinType::Int:
+case BuiltinType::UInt:
+  return true;
+default:
+  break;
+}
+
+  return false;
+}
+
+bool ZOSXPLinkABIInfo::isCompoundType(QualType Ty) const {
+  return (Ty->isAnyComplexType() || Ty->isVectorType() ||
+  isAggregateTypeForABI(Ty));
+}
+
+bool ZOSXPLinkABIInfo::isVectorArgumentType(QualType Ty) const {
+  return (HasVector && Ty->isVectorType() &&
+  getContext().getTypeSize(Ty) <= 128);
+}
+
+bool ZOSXPLinkABIInfo::isFPArgumentType(QualType Ty) const {
+  if (const BuiltinType *BT = Ty->getAs())
+switch (BT->getKind()) {
+case BuiltinType::Float:
+case BuiltinType::Double:
+case BuiltinType::LongDouble:
+  return true;
+default:
+  return false;
+}
+
+  return false;
+}
+
+QualType ZOSXPLinkABIInfo::GetSingleElementType(QualType Ty) const {
+  if (const RecordType *RT = Ty->getAsStructureType()) {
+const RecordDecl *RD = RT->getDecl();
+QualType Found;
+
+// If this is a C++ record, check the bases first.
+if (const CXXRecordDecl *CXXRD = dyn_cast(RD))
+  for (const auto &I : CXXRD->bases()) {
+QualType Base = I.getType();
+
+// Empty bases don't affect things either way.
+if (isEmptyRecord(getContext(), Base, true))
+  continue;
+
+if (!Found.isNull())
+  return Ty;
+Found = GetSingleElementType(Base);
+  }
+
+// Check the fields.
+for (const auto *FD : RD->fields()) {
+  // For compatibility with GCC, ignore empty bitfields in C++ mode.
+  // Unlike isSingleElementStruct(), empty structure and array fields
+  // do count.  So do anonymous bitfields that aren't zero-sized.
+  if (getContext().getLangOpts().CPlusPlus &&
+  FD->isZeroLengthBitField(getContext()))
+continue;
+
+  // Unlike isSingleElementStruct(), arrays do not count.
+  // Nested structures still do though.
+  if (!Found.isNull())
+return Ty;
+  Found = GetSingleElementType(FD->getType());
+}
+
+// Unlike isSingleElementStruct(), trailing padding is allowed.
+// An 8-byte aligned struct s { float f; } is passed as a double.
+if (!Found.isNull())
+  return Found;
+  }
+
+  return Ty;
+}
+
+bool ZOSXPLinkABIInfo::IsLikeComplexType(QualType Ty) const {
+  if (const RecordType *RT = Ty->getAsStructureType()) {
+const RecordDecl *RD = RT->getDecl();
+int i = 0;
+clang::BuiltinType::Kind elemKind;
+
+// Check for exactly two el

[clang] [SystemZ][z/OS] Implement z/OS XPLINK ABI (PR #91384)

2024-05-08 Thread Ulrich Weigand via cfe-commits


@@ -529,9 +529,324 @@ bool SystemZTargetCodeGenInfo::isVectorTypeBased(const 
Type *Ty,
   return false;
 }
 
+//===--===//
+// z/OS XPLINK ABI Implementation
+//===--===//
+
+namespace {
+
+class ZOSXPLinkABIInfo : public ABIInfo {
+  static const unsigned GPRBits = 64;
+  bool HasVector;
+
+public:
+  ZOSXPLinkABIInfo(CodeGenTypes &CGT, bool HV) : ABIInfo(CGT), HasVector(HV) {}
+
+  bool isPromotableIntegerType(QualType Ty) const;
+  bool isCompoundType(QualType Ty) const;
+  bool isVectorArgumentType(QualType Ty) const;
+  bool isFPArgumentType(QualType Ty) const;
+  QualType GetSingleElementType(QualType Ty) const;
+  bool IsLikeComplexType(QualType Ty) const;
+
+  ABIArgInfo classifyReturnType(QualType RetTy) const;
+  ABIArgInfo classifyArgumentType(QualType ArgTy, bool IsNamedArg) const;
+
+  void computeInfo(CGFunctionInfo &FI) const override {
+if (!getCXXABI().classifyReturnType(FI))
+  FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
+
+unsigned NumRequiredArgs = FI.getNumRequiredArgs();
+unsigned ArgNo = 0;
+
+for (auto &I : FI.arguments()) {
+  bool IsNamedArg = ArgNo < NumRequiredArgs;
+  I.info = classifyArgumentType(I.type, IsNamedArg);
+  ++ArgNo;
+}
+  }
+
+  Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
+QualType Ty) const override;
+};
+
+class ZOSXPLinkTargetCodeGenInfo : public TargetCodeGenInfo {
+public:
+  ZOSXPLinkTargetCodeGenInfo(CodeGenTypes &CGT, bool HasVector)
+  : TargetCodeGenInfo(std::make_unique(CGT, HasVector)) {
+SwiftInfo =
+std::make_unique(CGT, /*SwiftErrorInRegister=*/false);
+  }
+};
+
+} // namespace
+
+// Return true if the ABI requires Ty to be passed sign- or zero-
+// extended to 64 bits.
+bool ZOSXPLinkABIInfo::isPromotableIntegerType(QualType Ty) const {
+  // Treat an enum type as its underlying type.
+  if (const EnumType *EnumTy = Ty->getAs())
+Ty = EnumTy->getDecl()->getIntegerType();
+
+  // Promotable integer types are required to be promoted by the ABI.
+  if (getContext().isPromotableIntegerType(Ty))
+return true;
+
+  // In addition to the usual promotable integer types, we also need to
+  // extend all 32-bit types, since the ABI requires promotion to 64 bits.
+  if (const BuiltinType *BT = Ty->getAs())
+switch (BT->getKind()) {
+case BuiltinType::Int:
+case BuiltinType::UInt:
+  return true;
+default:
+  break;
+}
+
+  return false;
+}
+
+bool ZOSXPLinkABIInfo::isCompoundType(QualType Ty) const {
+  return (Ty->isAnyComplexType() || Ty->isVectorType() ||
+  isAggregateTypeForABI(Ty));
+}
+
+bool ZOSXPLinkABIInfo::isVectorArgumentType(QualType Ty) const {
+  return (HasVector && Ty->isVectorType() &&
+  getContext().getTypeSize(Ty) <= 128);
+}
+
+bool ZOSXPLinkABIInfo::isFPArgumentType(QualType Ty) const {
+  if (const BuiltinType *BT = Ty->getAs())
+switch (BT->getKind()) {
+case BuiltinType::Float:
+case BuiltinType::Double:
+case BuiltinType::LongDouble:
+  return true;
+default:
+  return false;
+}
+
+  return false;
+}
+
+QualType ZOSXPLinkABIInfo::GetSingleElementType(QualType Ty) const {
+  if (const RecordType *RT = Ty->getAsStructureType()) {
+const RecordDecl *RD = RT->getDecl();
+QualType Found;
+
+// If this is a C++ record, check the bases first.
+if (const CXXRecordDecl *CXXRD = dyn_cast(RD))
+  for (const auto &I : CXXRD->bases()) {
+QualType Base = I.getType();
+
+// Empty bases don't affect things either way.
+if (isEmptyRecord(getContext(), Base, true))
+  continue;
+
+if (!Found.isNull())
+  return Ty;
+Found = GetSingleElementType(Base);
+  }
+
+// Check the fields.
+for (const auto *FD : RD->fields()) {
+  // For compatibility with GCC, ignore empty bitfields in C++ mode.
+  // Unlike isSingleElementStruct(), empty structure and array fields
+  // do count.  So do anonymous bitfields that aren't zero-sized.
+  if (getContext().getLangOpts().CPlusPlus &&
+  FD->isZeroLengthBitField(getContext()))
+continue;
+
+  // Unlike isSingleElementStruct(), arrays do not count.
+  // Nested structures still do though.
+  if (!Found.isNull())
+return Ty;
+  Found = GetSingleElementType(FD->getType());
+}
+
+// Unlike isSingleElementStruct(), trailing padding is allowed.
+// An 8-byte aligned struct s { float f; } is passed as a double.
+if (!Found.isNull())
+  return Found;
+  }
+
+  return Ty;
+}
+
+bool ZOSXPLinkABIInfo::IsLikeComplexType(QualType Ty) const {
+  if (const RecordType *RT = Ty->getAsStructureType()) {
+const RecordDecl *RD = RT->getDecl();
+int i = 0;
+clang::BuiltinType::Kind elemKind;
+
+// Check for exactly two el

[clang] [SystemZ][z/OS] Implement z/OS XPLINK ABI (PR #91384)

2024-05-08 Thread Ulrich Weigand via cfe-commits


@@ -0,0 +1,137 @@
+// RUN: %clang_cc1 -triple s390x-ibm-zos \
+// RUN:   -emit-llvm -no-enable-noundef-analysis -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple s390x-ibm-zos -target-feature +vector \
+// RUN:   -emit-llvm -no-enable-noundef-analysis -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple s390x-ibm-zos -target-cpu z13 \
+// RUN:   -emit-llvm -no-enable-noundef-analysis -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple s390x-ibm-zos -target-cpu arch11 \
+// RUN:   -emit-llvm -no-enable-noundef-analysis -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple s390x-ibm-zos -target-cpu z14 \
+// RUN:   -emit-llvm -no-enable-noundef-analysis -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple s390x-ibm-zos -target-cpu arch12 \
+// RUN:   -emit-llvm -no-enable-noundef-analysis -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple s390x-ibm-zos -target-cpu z15 \
+// RUN:   -emit-llvm -no-enable-noundef-analysis -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple s390x-ibm-zos -target-cpu arch13 \
+// RUN:   -emit-llvm -no-enable-noundef-analysis -o - %s | FileCheck %s
+
+// Scalar types
+
+char pass_char(char arg) { return arg; }
+// CHECK-LABEL: define signext i8 @pass_char(i8 signext %{{.*}})
+
+short pass_short(short arg) { return arg; }
+// CHECK-LABEL: define signext i16 @pass_short(i16 signext %{{.*}})
+
+int pass_int(int arg) { return arg; }
+// CHECK-LABEL: define signext i32 @pass_int(i32 signext %{{.*}})
+
+long pass_long(long arg) { return arg; }
+// CHECK-LABEL: define i64 @pass_long(i64 %{{.*}})
+
+long long pass_longlong(long long arg) { return arg; }
+// CHECK-LABEL: define i64 @pass_longlong(i64 %{{.*}})
+
+float pass_float(float arg) { return arg; }
+// CHECK-LABEL: define float @pass_float(float %{{.*}})
+
+double pass_double(double arg) { return arg; }
+// CHECK-LABEL: define double @pass_double(double %{{.*}})
+
+long double pass_longdouble(long double arg) { return arg; }
+// CHECK-LABEL: define fp128 @pass_longdouble(fp128 %{{.*}})
+
+enum Color { Red, Blue };
+enum Color pass_enum(enum Color arg) { return arg; }
+// CHECK-LABEL: define zeroext i32 @pass_enum(i32 zeroext %{{.*}})
+
+// Complex types
+
+// TODO: Add tests for complex integer types
+
+_Complex float pass_complex_float(_Complex float arg) { return arg; }
+// CHECK-LABEL: define { float, float } @pass_complex_float(float %{{.*}}, 
float %{{.*}})
+
+_Complex double pass_complex_double(_Complex double arg) { return arg; }
+// CHECK-LABEL: define { double, double } @pass_complex_double(double %{{.*}}, 
double %{{.*}})
+
+_Complex long double pass_complex_longdouble(_Complex long double arg) { 
return arg; }
+// CHECK-LABEL: define { fp128, fp128 } @pass_complex_longdouble(fp128 
%{{.*}}, fp128 %{{.*}})
+
+// Verify that the following are complex-like types
+struct complexlike_float { float re, im; };
+struct complexlike_float pass_complexlike_float(struct complexlike_float arg) 
{ return arg; }
+// CHECK-LABEL: define %struct.complexlike_float @pass_complexlike_float(float 
%{{.*}}, float %{{.*}})
+
+struct complexlike_double { double re, im; };
+struct complexlike_double pass_complexlike_double(struct complexlike_double 
arg) { return arg; }
+// CHECK-LABEL: define %struct.complexlike_double 
@pass_complexlike_double(double %{{.*}}, double %{{.*}})
+
+struct complexlike_longdouble { long double re, im; };
+struct complexlike_longdouble pass_complexlike_longdouble(struct 
complexlike_longdouble arg) { return arg; }
+// CHECK-LABEL: define %struct.complexlike_longdouble 
@pass_complexlike_longdouble(fp128 %{{.*}}, fp128 %{{.*}})
+
+// Aggregate types
+

uweigand wrote:

We probably ought to increase test coverage to handle more cases, in particular 
unnamed arguments, and some of the special cases of what counts and does not 
count as "single-element struct".

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


[clang] [SystemZ][z/OS] Implement z/OS XPLINK ABI (PR #91384)

2024-05-08 Thread Ulrich Weigand via cfe-commits


@@ -529,9 +529,324 @@ bool SystemZTargetCodeGenInfo::isVectorTypeBased(const 
Type *Ty,
   return false;
 }
 
+//===--===//
+// z/OS XPLINK ABI Implementation
+//===--===//
+
+namespace {
+
+class ZOSXPLinkABIInfo : public ABIInfo {
+  static const unsigned GPRBits = 64;
+  bool HasVector;
+
+public:
+  ZOSXPLinkABIInfo(CodeGenTypes &CGT, bool HV) : ABIInfo(CGT), HasVector(HV) {}
+
+  bool isPromotableIntegerType(QualType Ty) const;
+  bool isCompoundType(QualType Ty) const;
+  bool isVectorArgumentType(QualType Ty) const;
+  bool isFPArgumentType(QualType Ty) const;
+  QualType GetSingleElementType(QualType Ty) const;
+  bool IsLikeComplexType(QualType Ty) const;
+
+  ABIArgInfo classifyReturnType(QualType RetTy) const;
+  ABIArgInfo classifyArgumentType(QualType ArgTy, bool IsNamedArg) const;
+
+  void computeInfo(CGFunctionInfo &FI) const override {
+if (!getCXXABI().classifyReturnType(FI))
+  FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
+
+unsigned NumRequiredArgs = FI.getNumRequiredArgs();
+unsigned ArgNo = 0;
+
+for (auto &I : FI.arguments()) {
+  bool IsNamedArg = ArgNo < NumRequiredArgs;
+  I.info = classifyArgumentType(I.type, IsNamedArg);
+  ++ArgNo;
+}
+  }
+
+  Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
+QualType Ty) const override;
+};
+
+class ZOSXPLinkTargetCodeGenInfo : public TargetCodeGenInfo {
+public:
+  ZOSXPLinkTargetCodeGenInfo(CodeGenTypes &CGT, bool HasVector)
+  : TargetCodeGenInfo(std::make_unique(CGT, HasVector)) {
+SwiftInfo =
+std::make_unique(CGT, /*SwiftErrorInRegister=*/false);
+  }
+};
+
+} // namespace
+
+// Return true if the ABI requires Ty to be passed sign- or zero-
+// extended to 64 bits.
+bool ZOSXPLinkABIInfo::isPromotableIntegerType(QualType Ty) const {
+  // Treat an enum type as its underlying type.
+  if (const EnumType *EnumTy = Ty->getAs())
+Ty = EnumTy->getDecl()->getIntegerType();
+
+  // Promotable integer types are required to be promoted by the ABI.
+  if (getContext().isPromotableIntegerType(Ty))
+return true;
+
+  // In addition to the usual promotable integer types, we also need to
+  // extend all 32-bit types, since the ABI requires promotion to 64 bits.
+  if (const BuiltinType *BT = Ty->getAs())
+switch (BT->getKind()) {
+case BuiltinType::Int:
+case BuiltinType::UInt:
+  return true;
+default:
+  break;
+}
+
+  return false;
+}
+
+bool ZOSXPLinkABIInfo::isCompoundType(QualType Ty) const {
+  return (Ty->isAnyComplexType() || Ty->isVectorType() ||
+  isAggregateTypeForABI(Ty));
+}
+
+bool ZOSXPLinkABIInfo::isVectorArgumentType(QualType Ty) const {
+  return (HasVector && Ty->isVectorType() &&
+  getContext().getTypeSize(Ty) <= 128);
+}
+
+bool ZOSXPLinkABIInfo::isFPArgumentType(QualType Ty) const {
+  if (const BuiltinType *BT = Ty->getAs())
+switch (BT->getKind()) {
+case BuiltinType::Float:
+case BuiltinType::Double:
+case BuiltinType::LongDouble:
+  return true;
+default:
+  return false;
+}
+
+  return false;
+}
+
+QualType ZOSXPLinkABIInfo::GetSingleElementType(QualType Ty) const {
+  if (const RecordType *RT = Ty->getAsStructureType()) {
+const RecordDecl *RD = RT->getDecl();
+QualType Found;
+
+// If this is a C++ record, check the bases first.
+if (const CXXRecordDecl *CXXRD = dyn_cast(RD))
+  for (const auto &I : CXXRD->bases()) {
+QualType Base = I.getType();
+
+// Empty bases don't affect things either way.
+if (isEmptyRecord(getContext(), Base, true))
+  continue;
+
+if (!Found.isNull())
+  return Ty;
+Found = GetSingleElementType(Base);
+  }
+
+// Check the fields.
+for (const auto *FD : RD->fields()) {
+  // For compatibility with GCC, ignore empty bitfields in C++ mode.
+  // Unlike isSingleElementStruct(), empty structure and array fields
+  // do count.  So do anonymous bitfields that aren't zero-sized.
+  if (getContext().getLangOpts().CPlusPlus &&
+  FD->isZeroLengthBitField(getContext()))
+continue;
+
+  // Unlike isSingleElementStruct(), arrays do not count.
+  // Nested structures still do though.
+  if (!Found.isNull())
+return Ty;
+  Found = GetSingleElementType(FD->getType());
+}
+
+// Unlike isSingleElementStruct(), trailing padding is allowed.
+// An 8-byte aligned struct s { float f; } is passed as a double.
+if (!Found.isNull())
+  return Found;
+  }
+
+  return Ty;
+}
+
+bool ZOSXPLinkABIInfo::IsLikeComplexType(QualType Ty) const {
+  if (const RecordType *RT = Ty->getAsStructureType()) {
+const RecordDecl *RD = RT->getDecl();
+int i = 0;
+clang::BuiltinType::Kind elemKind;
+
+// Check for exactly two el

[clang] [SystemZ][z/OS] Implement z/OS XPLINK ABI (PR #91384)

2024-05-08 Thread Ulrich Weigand via cfe-commits


@@ -529,9 +529,324 @@ bool SystemZTargetCodeGenInfo::isVectorTypeBased(const 
Type *Ty,
   return false;
 }
 
+//===--===//
+// z/OS XPLINK ABI Implementation
+//===--===//
+
+namespace {
+
+class ZOSXPLinkABIInfo : public ABIInfo {
+  static const unsigned GPRBits = 64;
+  bool HasVector;
+
+public:
+  ZOSXPLinkABIInfo(CodeGenTypes &CGT, bool HV) : ABIInfo(CGT), HasVector(HV) {}
+
+  bool isPromotableIntegerType(QualType Ty) const;
+  bool isCompoundType(QualType Ty) const;
+  bool isVectorArgumentType(QualType Ty) const;
+  bool isFPArgumentType(QualType Ty) const;
+  QualType GetSingleElementType(QualType Ty) const;
+  bool IsLikeComplexType(QualType Ty) const;
+
+  ABIArgInfo classifyReturnType(QualType RetTy) const;
+  ABIArgInfo classifyArgumentType(QualType ArgTy, bool IsNamedArg) const;
+
+  void computeInfo(CGFunctionInfo &FI) const override {
+if (!getCXXABI().classifyReturnType(FI))
+  FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
+
+unsigned NumRequiredArgs = FI.getNumRequiredArgs();
+unsigned ArgNo = 0;
+
+for (auto &I : FI.arguments()) {
+  bool IsNamedArg = ArgNo < NumRequiredArgs;
+  I.info = classifyArgumentType(I.type, IsNamedArg);
+  ++ArgNo;
+}
+  }
+
+  Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
+QualType Ty) const override;
+};
+
+class ZOSXPLinkTargetCodeGenInfo : public TargetCodeGenInfo {
+public:
+  ZOSXPLinkTargetCodeGenInfo(CodeGenTypes &CGT, bool HasVector)
+  : TargetCodeGenInfo(std::make_unique(CGT, HasVector)) {
+SwiftInfo =
+std::make_unique(CGT, /*SwiftErrorInRegister=*/false);
+  }
+};
+
+} // namespace
+
+// Return true if the ABI requires Ty to be passed sign- or zero-
+// extended to 64 bits.
+bool ZOSXPLinkABIInfo::isPromotableIntegerType(QualType Ty) const {
+  // Treat an enum type as its underlying type.
+  if (const EnumType *EnumTy = Ty->getAs())
+Ty = EnumTy->getDecl()->getIntegerType();
+
+  // Promotable integer types are required to be promoted by the ABI.
+  if (getContext().isPromotableIntegerType(Ty))
+return true;
+
+  // In addition to the usual promotable integer types, we also need to
+  // extend all 32-bit types, since the ABI requires promotion to 64 bits.
+  if (const BuiltinType *BT = Ty->getAs())
+switch (BT->getKind()) {
+case BuiltinType::Int:
+case BuiltinType::UInt:
+  return true;
+default:
+  break;
+}
+
+  return false;
+}
+
+bool ZOSXPLinkABIInfo::isCompoundType(QualType Ty) const {
+  return (Ty->isAnyComplexType() || Ty->isVectorType() ||
+  isAggregateTypeForABI(Ty));
+}
+
+bool ZOSXPLinkABIInfo::isVectorArgumentType(QualType Ty) const {
+  return (HasVector && Ty->isVectorType() &&
+  getContext().getTypeSize(Ty) <= 128);
+}
+
+bool ZOSXPLinkABIInfo::isFPArgumentType(QualType Ty) const {
+  if (const BuiltinType *BT = Ty->getAs())
+switch (BT->getKind()) {
+case BuiltinType::Float:
+case BuiltinType::Double:
+case BuiltinType::LongDouble:
+  return true;
+default:
+  return false;
+}
+
+  return false;
+}
+
+QualType ZOSXPLinkABIInfo::GetSingleElementType(QualType Ty) const {
+  if (const RecordType *RT = Ty->getAsStructureType()) {
+const RecordDecl *RD = RT->getDecl();
+QualType Found;
+
+// If this is a C++ record, check the bases first.
+if (const CXXRecordDecl *CXXRD = dyn_cast(RD))
+  for (const auto &I : CXXRD->bases()) {
+QualType Base = I.getType();
+
+// Empty bases don't affect things either way.
+if (isEmptyRecord(getContext(), Base, true))
+  continue;
+
+if (!Found.isNull())
+  return Ty;
+Found = GetSingleElementType(Base);
+  }
+
+// Check the fields.
+for (const auto *FD : RD->fields()) {
+  // For compatibility with GCC, ignore empty bitfields in C++ mode.
+  // Unlike isSingleElementStruct(), empty structure and array fields
+  // do count.  So do anonymous bitfields that aren't zero-sized.
+  if (getContext().getLangOpts().CPlusPlus &&
+  FD->isZeroLengthBitField(getContext()))
+continue;
+
+  // Unlike isSingleElementStruct(), arrays do not count.
+  // Nested structures still do though.
+  if (!Found.isNull())
+return Ty;
+  Found = GetSingleElementType(FD->getType());
+}
+
+// Unlike isSingleElementStruct(), trailing padding is allowed.
+// An 8-byte aligned struct s { float f; } is passed as a double.

uweigand wrote:

Just checking as this seems to be copied from Linux - is this same quirk really 
true for XPLINK as well?

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

[clang] [SystemZ][z/OS] Implement z/OS XPLINK ABI (PR #91384)

2024-05-08 Thread Ulrich Weigand via cfe-commits


@@ -529,9 +529,324 @@ bool SystemZTargetCodeGenInfo::isVectorTypeBased(const 
Type *Ty,
   return false;
 }
 
+//===--===//
+// z/OS XPLINK ABI Implementation
+//===--===//
+
+namespace {
+
+class ZOSXPLinkABIInfo : public ABIInfo {
+  static const unsigned GPRBits = 64;
+  bool HasVector;
+
+public:
+  ZOSXPLinkABIInfo(CodeGenTypes &CGT, bool HV) : ABIInfo(CGT), HasVector(HV) {}
+
+  bool isPromotableIntegerType(QualType Ty) const;
+  bool isCompoundType(QualType Ty) const;
+  bool isVectorArgumentType(QualType Ty) const;
+  bool isFPArgumentType(QualType Ty) const;
+  QualType GetSingleElementType(QualType Ty) const;
+  bool IsLikeComplexType(QualType Ty) const;
+
+  ABIArgInfo classifyReturnType(QualType RetTy) const;
+  ABIArgInfo classifyArgumentType(QualType ArgTy, bool IsNamedArg) const;
+
+  void computeInfo(CGFunctionInfo &FI) const override {
+if (!getCXXABI().classifyReturnType(FI))
+  FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
+
+unsigned NumRequiredArgs = FI.getNumRequiredArgs();
+unsigned ArgNo = 0;
+
+for (auto &I : FI.arguments()) {
+  bool IsNamedArg = ArgNo < NumRequiredArgs;
+  I.info = classifyArgumentType(I.type, IsNamedArg);
+  ++ArgNo;
+}
+  }
+
+  Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
+QualType Ty) const override;
+};
+
+class ZOSXPLinkTargetCodeGenInfo : public TargetCodeGenInfo {
+public:
+  ZOSXPLinkTargetCodeGenInfo(CodeGenTypes &CGT, bool HasVector)
+  : TargetCodeGenInfo(std::make_unique(CGT, HasVector)) {
+SwiftInfo =
+std::make_unique(CGT, /*SwiftErrorInRegister=*/false);
+  }
+};
+
+} // namespace
+
+// Return true if the ABI requires Ty to be passed sign- or zero-
+// extended to 64 bits.
+bool ZOSXPLinkABIInfo::isPromotableIntegerType(QualType Ty) const {
+  // Treat an enum type as its underlying type.
+  if (const EnumType *EnumTy = Ty->getAs())
+Ty = EnumTy->getDecl()->getIntegerType();
+
+  // Promotable integer types are required to be promoted by the ABI.
+  if (getContext().isPromotableIntegerType(Ty))
+return true;

uweigand wrote:

The Linux ABI promotes the new `BitInt` types as well.  Do you need that for 
XPLINK too?

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


[clang] [Clang][Sema] Do not accept "vector _Complex" for AltiVec/ZVector (PR #90467)

2024-04-30 Thread Ulrich Weigand via cfe-commits

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


[clang] [Clang][Sema] Do not accept "vector _Complex" for AltiVec/ZVector (PR #90467)

2024-04-29 Thread Ulrich Weigand via cfe-commits


@@ -1191,6 +1191,10 @@ void DeclSpec::Finish(Sema &S, const PrintingPolicy 
&Policy) {
 
   // Validate and finalize AltiVec vector declspec.
   if (TypeAltiVecVector) {
+// Complex vector types are not supported.
+if (TypeSpecComplex != TSC_unspecified)
+  S.Diag(TSCLoc, diag::err_invalid_vector_complex_decl_spec);

uweigand wrote:

Makes sense.  I've updated the patches.

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


[clang] [Clang][Sema] Do not accept "vector _Complex" for AltiVec/ZVector (PR #90467)

2024-04-29 Thread Ulrich Weigand via cfe-commits

https://github.com/uweigand updated 
https://github.com/llvm/llvm-project/pull/90467

>From 7f13179745ccc31ceca223c03c6b75fa46b4fe37 Mon Sep 17 00:00:00 2001
From: Ulrich Weigand 
Date: Mon, 29 Apr 2024 15:04:31 +0200
Subject: [PATCH] [Clang][Sema] Do not accept "vector _Complex" for
 AltiVec/ZVector

The AltiVec (POWER) and ZVector (IBM Z) language extensions do
not support using the "vector" keyword when the element type is
a complex type, but current code does not verify this.

Add a Sema check and diagnostic for this case.

Fixes: https://github.com/llvm/llvm-project/issues/88399
---
 clang/include/clang/Basic/DiagnosticSemaKinds.td | 2 ++
 clang/lib/Sema/DeclSpec.cpp  | 5 -
 clang/test/Parser/altivec.c  | 6 ++
 clang/test/Parser/cxx-altivec.cpp| 6 ++
 clang/test/Sema/zvector.c| 8 
 clang/test/Sema/zvector2.c   | 4 
 6 files changed, 30 insertions(+), 1 deletion(-)

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index fdca82934cb4dc..8853739969a4ca 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -307,6 +307,8 @@ def err_invalid_vector_long_long_decl_spec : Error <
   "POWER7 or later) to be enabled">;
 def err_invalid_vector_long_double_decl_spec : Error<
   "cannot use 'long double' with '__vector'">;
+def err_invalid_vector_complex_decl_spec : Error<
+  "cannot use '_Complex' with '__vector'">;
 def warn_vector_long_decl_spec_combination : Warning<
   "Use of 'long' with '__vector' is deprecated">, InGroup;
 
diff --git a/clang/lib/Sema/DeclSpec.cpp b/clang/lib/Sema/DeclSpec.cpp
index 5f63c857c43067..60e81890257002 100644
--- a/clang/lib/Sema/DeclSpec.cpp
+++ b/clang/lib/Sema/DeclSpec.cpp
@@ -1202,7 +1202,10 @@ void DeclSpec::Finish(Sema &S, const PrintingPolicy 
&Policy) {
 !S.Context.getTargetInfo().hasFeature("power8-vector"))
   S.Diag(TSTLoc, diag::err_invalid_vector_int128_decl_spec);
 
-if (TypeAltiVecBool) {
+// Complex vector types are not supported.
+if (TypeSpecComplex != TSC_unspecified)
+  S.Diag(TSCLoc, diag::err_invalid_vector_complex_decl_spec);
+else if (TypeAltiVecBool) {
   // Sign specifiers are not allowed with vector bool. (PIM 2.1)
   if (getTypeSpecSign() != TypeSpecifierSign::Unspecified) {
 S.Diag(TSSLoc, diag::err_invalid_vector_bool_decl_spec)
diff --git a/clang/test/Parser/altivec.c b/clang/test/Parser/altivec.c
index daee5eae4d8430..445369f0dc0660 100644
--- a/clang/test/Parser/altivec.c
+++ b/clang/test/Parser/altivec.c
@@ -110,6 +110,12 @@ vector __bool long long v_bll4;  // expected-error 
{{use of 'long long' with
 #endif
 __vector long double  vv_ld3;// expected-error {{cannot use 'long 
double' with '__vector'}}
 vector long double  v_ld4;   // expected-error {{cannot use 'long 
double' with '__vector'}}
+vector float _Complex v_cf;  // expected-error {{cannot use '_Complex' 
with '__vector'}}
+vector double _Complex v_cd; // expected-error {{cannot use '_Complex' 
with '__vector'}}
+vector long double _Complex v_cld;   // expected-error {{cannot use '_Complex' 
with '__vector'}}
+__vector float _Complex v_cf2;   // expected-error {{cannot use '_Complex' 
with '__vector'}}
+__vector double _Complex v_cd2;  // expected-error {{cannot use '_Complex' 
with '__vector'}}
+__vector long double _Complex v_cld2;// expected-error {{cannot use '_Complex' 
with '__vector'}}
 vector bool float v_bf;  // expected-error {{cannot use 'float' 
with '__vector bool'}}
 vector bool double v_bd; // expected-error {{cannot use 'double' 
with '__vector bool'}}
 vector bool pixel v_bp;  // expected-error {{cannot use '__pixel' 
with '__vector bool'}}
diff --git a/clang/test/Parser/cxx-altivec.cpp 
b/clang/test/Parser/cxx-altivec.cpp
index 6da36663422b49..5cb760dababbb6 100644
--- a/clang/test/Parser/cxx-altivec.cpp
+++ b/clang/test/Parser/cxx-altivec.cpp
@@ -111,6 +111,12 @@ vector __bool long long v_bll4;  // expected-error 
{{use of 'long long' with
 #endif
 __vector long double  vv_ld3;// expected-error {{cannot use 'long 
double' with '__vector'}}
 vector long double  v_ld4;   // expected-error {{cannot use 'long 
double' with '__vector'}}
+vector float _Complex v_cf;  // expected-error {{cannot use '_Complex' 
with '__vector'}}
+vector double _Complex v_cd; // expected-error {{cannot use '_Complex' 
with '__vector'}}
+vector long double _Complex v_cld;   // expected-error {{cannot use '_Complex' 
with '__vector'}}
+__vector float _Complex v_cf2;   // expected-error {{cannot use '_Complex' 
with '__vector'}}
+__vector double _Complex v_cd2;  // expected-error {{cannot use '_Complex' 
with '__vector'}}
+__vector long double _Complex v_cld2;// expected-error

[clang] [Clang][Sema] Do not accept "vector _Complex" for AltiVec/ZVector (PR #90467)

2024-04-29 Thread Ulrich Weigand via cfe-commits

https://github.com/uweigand created 
https://github.com/llvm/llvm-project/pull/90467

The AltiVec (POWER) and ZVector (IBM Z) language extensions do not support 
using the "vector" keyword when the element type is a complex type, but current 
code does not verify this.

Add a Sema check and diagnostic for this case.

Fixes: https://github.com/llvm/llvm-project/issues/88399

>From ad881f8d30484088a960528df52cfbf5cbd9d210 Mon Sep 17 00:00:00 2001
From: Ulrich Weigand 
Date: Mon, 29 Apr 2024 15:04:31 +0200
Subject: [PATCH] [Clang][Sema] Do not accept "vector _Complex" for
 AltiVec/ZVector

The AltiVec (POWER) and ZVector (IBM Z) language extensions do
not support using the "vector" keyword when the element type is
a complex type, but current code does not verify this.

Add a Sema check and diagnostic for this case.

Fixes: https://github.com/llvm/llvm-project/issues/88399
---
 clang/include/clang/Basic/DiagnosticSemaKinds.td |  2 ++
 clang/lib/Sema/DeclSpec.cpp  |  4 
 clang/test/Parser/altivec.c  | 14 ++
 clang/test/Parser/cxx-altivec.cpp| 14 ++
 clang/test/Sema/zvector.c| 12 
 clang/test/Sema/zvector2.c   |  4 
 6 files changed, 50 insertions(+)

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index fdca82934cb4dc..8853739969a4ca 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -307,6 +307,8 @@ def err_invalid_vector_long_long_decl_spec : Error <
   "POWER7 or later) to be enabled">;
 def err_invalid_vector_long_double_decl_spec : Error<
   "cannot use 'long double' with '__vector'">;
+def err_invalid_vector_complex_decl_spec : Error<
+  "cannot use '_Complex' with '__vector'">;
 def warn_vector_long_decl_spec_combination : Warning<
   "Use of 'long' with '__vector' is deprecated">, InGroup;
 
diff --git a/clang/lib/Sema/DeclSpec.cpp b/clang/lib/Sema/DeclSpec.cpp
index 5f63c857c43067..71225a7ed5ee62 100644
--- a/clang/lib/Sema/DeclSpec.cpp
+++ b/clang/lib/Sema/DeclSpec.cpp
@@ -1191,6 +1191,10 @@ void DeclSpec::Finish(Sema &S, const PrintingPolicy 
&Policy) {
 
   // Validate and finalize AltiVec vector declspec.
   if (TypeAltiVecVector) {
+// Complex vector types are not supported.
+if (TypeSpecComplex != TSC_unspecified)
+  S.Diag(TSCLoc, diag::err_invalid_vector_complex_decl_spec);
+
 // No vector long long without VSX (or ZVector).
 if ((getTypeSpecWidth() == TypeSpecifierWidth::LongLong) &&
 !S.Context.getTargetInfo().hasFeature("vsx") &&
diff --git a/clang/test/Parser/altivec.c b/clang/test/Parser/altivec.c
index daee5eae4d8430..f63a2bfa6abdc3 100644
--- a/clang/test/Parser/altivec.c
+++ b/clang/test/Parser/altivec.c
@@ -110,6 +110,20 @@ vector __bool long long v_bll4;  // expected-error 
{{use of 'long long' with
 #endif
 __vector long double  vv_ld3;// expected-error {{cannot use 'long 
double' with '__vector'}}
 vector long double  v_ld4;   // expected-error {{cannot use 'long 
double' with '__vector'}}
+vector float _Complex v_cf;  // expected-error {{cannot use '_Complex' 
with '__vector'}}
+vector double _Complex v_cd; // expected-error {{cannot use '_Complex' 
with '__vector'}}
+#ifndef __VSX__
+ // expected-error@-2 {{use of 'double' 
with '__vector' requires VSX support to be enabled (available on POWER7 or 
later)}}
+#endif
+vector long double _Complex v_cld;   // expected-error {{cannot use '_Complex' 
with '__vector'}}
+ // expected-error@-1 {{cannot use 'long 
double' with '__vector'}}
+__vector float _Complex v_cf2;   // expected-error {{cannot use '_Complex' 
with '__vector'}}
+__vector double _Complex v_cd2;  // expected-error {{cannot use '_Complex' 
with '__vector'}}
+#ifndef __VSX__
+ // expected-error@-2 {{use of 'double' 
with '__vector' requires VSX support to be enabled (available on POWER7 or 
later)}}
+#endif
+__vector long double _Complex v_cld2;// expected-error {{cannot use '_Complex' 
with '__vector'}}
+ // expected-error@-1 {{cannot use 'long 
double' with '__vector'}}
 vector bool float v_bf;  // expected-error {{cannot use 'float' 
with '__vector bool'}}
 vector bool double v_bd; // expected-error {{cannot use 'double' 
with '__vector bool'}}
 vector bool pixel v_bp;  // expected-error {{cannot use '__pixel' 
with '__vector bool'}}
diff --git a/clang/test/Parser/cxx-altivec.cpp 
b/clang/test/Parser/cxx-altivec.cpp
index 6da36663422b49..c071f333e2206f 100644
--- a/clang/test/Parser/cxx-altivec.cpp
+++ b/clang/test/Parser/cxx-altivec.cpp
@@ -111,6 +111,20 @@ vector __bool long long v_bll4;  // expected-error 
{{use of 'long long' with
 #endif
 

[clang] [C++17] Support __GCC_[CON|DE]STRUCTIVE_SIZE (PR #89446)

2024-04-22 Thread Ulrich Weigand via cfe-commits

uweigand wrote:

> > For SystemZ the correct value is 256.
> 
> Thanks! Double-checking: for both constructive and destructive?

Yes, for both.  Every SystemZ model (supported by GCC/LLVM) has a L1 cache line 
size of 256 bytes.

> > In general I agree it makes sense to look at the GCC implementation as a 
> > source of reasonable values. Also, I think there probably should be no 
> > generic default value at all - it there is no platform-specific value 
> > known, it seems better to not define those values rather than define them 
> > to some incorrect value ...
> 
> On the one hand, I agree. But then libc++ will still have to pick default 
> values to expose (these are `constexpr size_t` variables in libc++ rather 
> than macros or `std::optional` values), so that just moves the problem 
> elsewhere. Also, as best I can tell, that doesn't seem to be how GCC behaves 
> (at least, from trying various GCC flavors on Compiler Explorer).

Looks like GCC's libstdc++ will simply not provide those variables either if 
GCC does not know those values for the current target:
```
#ifdef __cpp_lib_hardware_interference_size // C++ >= 17 && defined(gcc_dest_sz)
  inline constexpr size_t hardware_destructive_interference_size = 
__GCC_DESTRUCTIVE_SIZE;
  inline constexpr size_t hardware_constructive_interference_size = 
__GCC_CONSTRUCTIVE_SIZE;
#endif // __cpp_lib_hardware_interference_size
```


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


[clang] [C++17] Support __GCC_[CON|DE]STRUCTIVE_SIZE (PR #89446)

2024-04-21 Thread Ulrich Weigand via cfe-commits

uweigand wrote:

For SystemZ the correct value is 256.   In general I agree it makes sense to 
look at the GCC implementation as a source of reasonable values.   Also, I 
think there probably should be no generic default value at all - it there is no 
platform-specific value known, it seems better to not define those values 
rather than define them to some incorrect value ...

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


[clang] [llvm] [GOFF][z/OS] Change PrivateGlobalPrefix and PrivateLabelPrefix to be L# (PR #85730)

2024-03-20 Thread Ulrich Weigand via cfe-commits

https://github.com/uweigand approved this pull request.

LGTM, thanks!

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


[clang] c9062e8 - Reapply [libomptarget] Build plugins-nextgen for SystemZ (#83978)

2024-03-15 Thread Ulrich Weigand via cfe-commits

Author: Ulrich Weigand
Date: 2024-03-15T19:06:43+01:00
New Revision: c9062e8f786864f86d330babce78a1926cc5b072

URL: 
https://github.com/llvm/llvm-project/commit/c9062e8f786864f86d330babce78a1926cc5b072
DIFF: 
https://github.com/llvm/llvm-project/commit/c9062e8f786864f86d330babce78a1926cc5b072.diff

LOG: Reapply [libomptarget] Build plugins-nextgen for SystemZ (#83978)

The plugin was not getting built as the build_generic_elf64 macro
assumes the LLVM triple processor name matches the CMake processor name,
which is unfortunately not the case for SystemZ.

Fix this by providing two separate arguments instead.

Actually building the plugin exposed a number of other issues causing
various test failures. Specifically, I've had to add the SystemZ target
to
- CompilerInvocation::ParseLangArgs
- linkDevice in ClangLinuxWrapper.cpp
- OMPContext::OMPContext (to set the device_kind_cpu trait)
- LIBOMPTARGET_ALL_TARGETS in libomptarget/CMakeLists.txt
- a check_plugin_target call in libomptarget/src/CMakeLists.txt

Finally, I've had to set a number of test cases to UNSUPPORTED on
s390x-ibm-linux-gnu; all these tests were already marked as UNSUPPORTED
for x86_64-pc-linux-gnu and aarch64-unknown-linux-gnu and are failing on
s390x for what seem to be the same reason.

In addition, this also requires support for BE ELF files in
plugins-nextgen: https://github.com/llvm/llvm-project/pull/85246

Added: 


Modified: 
clang/lib/Frontend/CompilerInvocation.cpp
clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp
llvm/lib/Frontend/OpenMP/OMPContext.cpp
openmp/libomptarget/CMakeLists.txt
openmp/libomptarget/plugins-nextgen/CMakeLists.txt
openmp/libomptarget/plugins-nextgen/aarch64/CMakeLists.txt
openmp/libomptarget/plugins-nextgen/ppc64/CMakeLists.txt
openmp/libomptarget/plugins-nextgen/ppc64le/CMakeLists.txt
openmp/libomptarget/plugins-nextgen/s390x/CMakeLists.txt
openmp/libomptarget/plugins-nextgen/x86_64/CMakeLists.txt
openmp/libomptarget/src/CMakeLists.txt
openmp/libomptarget/test/api/omp_dynamic_shared_memory.c
openmp/libomptarget/test/jit/empty_kernel_lvl1.c
openmp/libomptarget/test/jit/empty_kernel_lvl2.c
openmp/libomptarget/test/jit/type_punning.c
openmp/libomptarget/test/mapping/auto_zero_copy.cpp
openmp/libomptarget/test/mapping/auto_zero_copy_globals.cpp
openmp/libomptarget/test/offloading/barrier_fence.c
openmp/libomptarget/test/offloading/bug49334.cpp
openmp/libomptarget/test/offloading/default_thread_limit.c
openmp/libomptarget/test/offloading/ompx_bare.c
openmp/libomptarget/test/offloading/ompx_coords.c
openmp/libomptarget/test/offloading/ompx_saxpy_mixed.c
openmp/libomptarget/test/offloading/parallel_target_teams_reduction.cpp
openmp/libomptarget/test/offloading/small_trip_count.c
openmp/libomptarget/test/offloading/small_trip_count_thread_limit.cpp
openmp/libomptarget/test/offloading/spmdization.c
openmp/libomptarget/test/offloading/target_critical_region.cpp
openmp/libomptarget/test/offloading/thread_limit.c
openmp/libomptarget/test/ompt/target_memcpy.c
openmp/libomptarget/test/ompt/target_memcpy_emi.c
openmp/libomptarget/test/ompt/veccopy.c
openmp/libomptarget/test/ompt/veccopy_data.c
openmp/libomptarget/test/ompt/veccopy_disallow_both.c
openmp/libomptarget/test/ompt/veccopy_emi.c
openmp/libomptarget/test/ompt/veccopy_emi_map.c
openmp/libomptarget/test/ompt/veccopy_map.c

Removed: 




diff  --git a/clang/lib/Frontend/CompilerInvocation.cpp 
b/clang/lib/Frontend/CompilerInvocation.cpp
index 451bdb9386f587..2d3cbb98efcb57 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -4014,6 +4014,7 @@ bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, 
ArgList &Args,
 
   if (TT.getArch() == llvm::Triple::UnknownArch ||
   !(TT.getArch() == llvm::Triple::aarch64 || TT.isPPC() ||
+TT.getArch() == llvm::Triple::systemz ||
 TT.getArch() == llvm::Triple::nvptx ||
 TT.getArch() == llvm::Triple::nvptx64 ||
 TT.getArch() == llvm::Triple::amdgcn ||

diff  --git a/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp 
b/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp
index 535ef42c78c463..c60be2789bd61e 100644
--- a/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp
+++ b/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp
@@ -562,6 +562,7 @@ Expected linkDevice(ArrayRef 
InputFiles,
   case Triple::aarch64_be:
   case Triple::ppc64:
   case Triple::ppc64le:
+  case Triple::systemz:
 return generic::clang(InputFiles, Args);
   default:
 return createStringError(inconvertibleErrorCode(),

diff  --git a/llvm/lib/Frontend/OpenMP/OMPContext.cpp 
b/llvm/lib/Frontend/OpenMP/OMPContext.cpp
index e870c5aa2ba6b8..37936d6000c891 100644
--- a/llvm/lib/Frontend/O

[clang] 70677c8 - Revert "[libomptarget] Build plugins-nextgen for SystemZ (#83978)"

2024-03-06 Thread Ulrich Weigand via cfe-commits

Author: Ulrich Weigand
Date: 2024-03-06T21:37:43+01:00
New Revision: 70677c81debbeacfc2a2fe968e632522ea1b53e1

URL: 
https://github.com/llvm/llvm-project/commit/70677c81debbeacfc2a2fe968e632522ea1b53e1
DIFF: 
https://github.com/llvm/llvm-project/commit/70677c81debbeacfc2a2fe968e632522ea1b53e1.diff

LOG: Revert "[libomptarget] Build plugins-nextgen for SystemZ (#83978)"

This reverts commit 3ecd38c8e1d34b1e4639a1de9f0cb56c7957cbd2.

Added: 


Modified: 
clang/lib/Frontend/CompilerInvocation.cpp
clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp
llvm/lib/Frontend/OpenMP/OMPContext.cpp
openmp/libomptarget/CMakeLists.txt
openmp/libomptarget/plugins-nextgen/CMakeLists.txt
openmp/libomptarget/plugins-nextgen/aarch64/CMakeLists.txt
openmp/libomptarget/plugins-nextgen/ppc64/CMakeLists.txt
openmp/libomptarget/plugins-nextgen/ppc64le/CMakeLists.txt
openmp/libomptarget/plugins-nextgen/s390x/CMakeLists.txt
openmp/libomptarget/plugins-nextgen/x86_64/CMakeLists.txt
openmp/libomptarget/src/CMakeLists.txt
openmp/libomptarget/test/api/omp_dynamic_shared_memory.c
openmp/libomptarget/test/jit/empty_kernel_lvl1.c
openmp/libomptarget/test/jit/empty_kernel_lvl2.c
openmp/libomptarget/test/jit/type_punning.c
openmp/libomptarget/test/mapping/auto_zero_copy.cpp
openmp/libomptarget/test/mapping/auto_zero_copy_globals.cpp
openmp/libomptarget/test/offloading/barrier_fence.c
openmp/libomptarget/test/offloading/bug49334.cpp
openmp/libomptarget/test/offloading/default_thread_limit.c
openmp/libomptarget/test/offloading/ompx_bare.c
openmp/libomptarget/test/offloading/ompx_coords.c
openmp/libomptarget/test/offloading/ompx_saxpy_mixed.c
openmp/libomptarget/test/offloading/parallel_target_teams_reduction.cpp
openmp/libomptarget/test/offloading/small_trip_count.c
openmp/libomptarget/test/offloading/small_trip_count_thread_limit.cpp
openmp/libomptarget/test/offloading/spmdization.c
openmp/libomptarget/test/offloading/target_critical_region.cpp
openmp/libomptarget/test/offloading/thread_limit.c
openmp/libomptarget/test/ompt/target_memcpy.c
openmp/libomptarget/test/ompt/target_memcpy_emi.c
openmp/libomptarget/test/ompt/veccopy.c
openmp/libomptarget/test/ompt/veccopy_data.c
openmp/libomptarget/test/ompt/veccopy_disallow_both.c
openmp/libomptarget/test/ompt/veccopy_emi.c
openmp/libomptarget/test/ompt/veccopy_emi_map.c
openmp/libomptarget/test/ompt/veccopy_map.c

Removed: 




diff  --git a/clang/lib/Frontend/CompilerInvocation.cpp 
b/clang/lib/Frontend/CompilerInvocation.cpp
index 7e17c3e49acaf6..691f3b989b81e5 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -4012,7 +4012,6 @@ bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, 
ArgList &Args,
 
   if (TT.getArch() == llvm::Triple::UnknownArch ||
   !(TT.getArch() == llvm::Triple::aarch64 || TT.isPPC() ||
-TT.getArch() == llvm::Triple::systemz ||
 TT.getArch() == llvm::Triple::nvptx ||
 TT.getArch() == llvm::Triple::nvptx64 ||
 TT.getArch() == llvm::Triple::amdgcn ||

diff  --git a/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp 
b/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp
index b3efa56b33021a..576e8f2cd7f8fd 100644
--- a/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp
+++ b/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp
@@ -552,7 +552,6 @@ Expected linkDevice(ArrayRef 
InputFiles,
   case Triple::aarch64_be:
   case Triple::ppc64:
   case Triple::ppc64le:
-  case Triple::systemz:
 return generic::clang(InputFiles, Args);
   default:
 return createStringError(inconvertibleErrorCode(),

diff  --git a/llvm/lib/Frontend/OpenMP/OMPContext.cpp 
b/llvm/lib/Frontend/OpenMP/OMPContext.cpp
index 37936d6000c891..e870c5aa2ba6b8 100644
--- a/llvm/lib/Frontend/OpenMP/OMPContext.cpp
+++ b/llvm/lib/Frontend/OpenMP/OMPContext.cpp
@@ -44,7 +44,6 @@ OMPContext::OMPContext(bool IsDeviceCompilation, Triple 
TargetTriple) {
   case Triple::ppcle:
   case Triple::ppc64:
   case Triple::ppc64le:
-  case Triple::systemz:
   case Triple::x86:
   case Triple::x86_64:
 ActiveTraits.set(unsigned(TraitProperty::device_kind_cpu));

diff  --git a/openmp/libomptarget/CMakeLists.txt 
b/openmp/libomptarget/CMakeLists.txt
index b382137b70ee2a..a74eff0c0bebf3 100644
--- a/openmp/libomptarget/CMakeLists.txt
+++ b/openmp/libomptarget/CMakeLists.txt
@@ -56,8 +56,6 @@ set (LIBOMPTARGET_ALL_TARGETS "${LIBOMPTARGET_ALL_TARGETS} 
x86_64-pc-linux-gnu-L
 set (LIBOMPTARGET_ALL_TARGETS "${LIBOMPTARGET_ALL_TARGETS} 
nvptx64-nvidia-cuda")
 set (LIBOMPTARGET_ALL_TARGETS "${LIBOMPTARGET_ALL_TARGETS} 
nvptx64-nvidia-cuda-LTO")
 set (LIBOMPTARGET_ALL_TARGETS "${LIBOMPTARGET_ALL_TARGETS} 
nvptx64-nvidia-cuda-JIT-LTO")
-set (LIBOMPTARGET_ALL_T

[clang] [llvm] [openmp] [libomptarget] Build plugins-nextgen for SystemZ (PR #83978)

2024-03-06 Thread Ulrich Weigand via cfe-commits

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


[clang] [llvm] [openmp] [libomptarget] Build plugins-nextgen for SystemZ (PR #83978)

2024-03-06 Thread Ulrich Weigand via cfe-commits

https://github.com/uweigand updated 
https://github.com/llvm/llvm-project/pull/83978

>From e0cca3ddec75c7624c27a75ae6741dee3b0044fa Mon Sep 17 00:00:00 2001
From: Ulrich Weigand 
Date: Tue, 5 Mar 2024 10:03:55 +0100
Subject: [PATCH] [libomptarget] Build plugins-nextgen for SystemZ

The plugin was not getting built as the build_generic_elf64
macro assumes the LLVM triple processor name matches the
CMake processor name, which is unfortunately not the case
for SystemZ.

Fix this by providing two separate arguments instead.

Actually building the plugin exposed a number of other issues
causing various test failures.  Specifically, I've had to add
the SystemZ target to
- CompilerInvocation::ParseLangArgs
- linkDevice in ClangLinuxWrapper.cpp
- OMPContext::OMPContext (to set the device_kind_cpu trait)
- LIBOMPTARGET_ALL_TARGETS in libomptarget/CMakeLists.txt
- a check_plugin_target call in libomptarget/src/CMakeLists.txt

Finally, I've had to set a number of test cases to UNSUPPORTED
on s390x-ibm-linux-gnu; all these tests were already marked as
UNSUPPORTED for x86_64-pc-linux-gnu and aarch64-unknown-linux-gnu
and are failing on s390x for what seem to be the same reason.

In addition, this also requires support for BE ELF files in
plugins-nextgen: https://github.com/llvm/llvm-project/pull/83976
---
 clang/lib/Frontend/CompilerInvocation.cpp| 1 +
 clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp  | 1 +
 llvm/lib/Frontend/OpenMP/OMPContext.cpp  | 1 +
 openmp/libomptarget/CMakeLists.txt   | 2 ++
 openmp/libomptarget/plugins-nextgen/CMakeLists.txt   | 9 ++---
 .../libomptarget/plugins-nextgen/aarch64/CMakeLists.txt  | 2 +-
 openmp/libomptarget/plugins-nextgen/ppc64/CMakeLists.txt | 2 +-
 .../libomptarget/plugins-nextgen/ppc64le/CMakeLists.txt  | 2 +-
 openmp/libomptarget/plugins-nextgen/s390x/CMakeLists.txt | 2 +-
 .../libomptarget/plugins-nextgen/x86_64/CMakeLists.txt   | 2 +-
 openmp/libomptarget/src/CMakeLists.txt   | 1 +
 openmp/libomptarget/test/api/omp_dynamic_shared_memory.c | 2 ++
 openmp/libomptarget/test/jit/empty_kernel_lvl1.c | 2 ++
 openmp/libomptarget/test/jit/empty_kernel_lvl2.c | 2 ++
 openmp/libomptarget/test/jit/type_punning.c  | 2 ++
 openmp/libomptarget/test/mapping/auto_zero_copy.cpp  | 2 ++
 .../libomptarget/test/mapping/auto_zero_copy_globals.cpp | 2 ++
 openmp/libomptarget/test/offloading/barrier_fence.c  | 2 ++
 openmp/libomptarget/test/offloading/bug49334.cpp | 2 ++
 .../libomptarget/test/offloading/default_thread_limit.c  | 2 ++
 openmp/libomptarget/test/offloading/ompx_bare.c  | 5 -
 openmp/libomptarget/test/offloading/ompx_coords.c| 2 ++
 openmp/libomptarget/test/offloading/ompx_saxpy_mixed.c   | 2 ++
 .../test/offloading/parallel_target_teams_reduction.cpp  | 2 ++
 openmp/libomptarget/test/offloading/small_trip_count.c   | 2 ++
 .../test/offloading/small_trip_count_thread_limit.cpp| 2 ++
 openmp/libomptarget/test/offloading/spmdization.c| 2 ++
 .../test/offloading/target_critical_region.cpp   | 2 ++
 openmp/libomptarget/test/offloading/thread_limit.c   | 2 ++
 openmp/libomptarget/test/ompt/target_memcpy.c| 2 ++
 openmp/libomptarget/test/ompt/target_memcpy_emi.c| 2 ++
 openmp/libomptarget/test/ompt/veccopy.c  | 2 ++
 openmp/libomptarget/test/ompt/veccopy_data.c | 2 ++
 openmp/libomptarget/test/ompt/veccopy_disallow_both.c| 2 ++
 openmp/libomptarget/test/ompt/veccopy_emi.c  | 2 ++
 openmp/libomptarget/test/ompt/veccopy_emi_map.c  | 2 ++
 openmp/libomptarget/test/ompt/veccopy_map.c  | 2 ++
 37 files changed, 71 insertions(+), 9 deletions(-)

diff --git a/clang/lib/Frontend/CompilerInvocation.cpp 
b/clang/lib/Frontend/CompilerInvocation.cpp
index 691f3b989b81e5..7e17c3e49acaf6 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -4012,6 +4012,7 @@ bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, 
ArgList &Args,
 
   if (TT.getArch() == llvm::Triple::UnknownArch ||
   !(TT.getArch() == llvm::Triple::aarch64 || TT.isPPC() ||
+TT.getArch() == llvm::Triple::systemz ||
 TT.getArch() == llvm::Triple::nvptx ||
 TT.getArch() == llvm::Triple::nvptx64 ||
 TT.getArch() == llvm::Triple::amdgcn ||
diff --git a/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp 
b/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp
index 576e8f2cd7f8fd..b3efa56b33021a 100644
--- a/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp
+++ b/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp
@@ -552,6 +552,7 @@ Expected linkDevice(ArrayRef 
InputFiles,
   case Triple::aarch64_be:
   case Triple::ppc64:
   case Triple::ppc64le:
+  case Triple::systemz:
 return generic::clang(InputFiles, Args);
   default:
 return createStringErr

[clang] [llvm] [openmp] [libomptarget] Build plugins-nextgen for SystemZ (PR #83978)

2024-03-05 Thread Ulrich Weigand via cfe-commits

https://github.com/uweigand created 
https://github.com/llvm/llvm-project/pull/83978

The plugin was not getting built as the build_generic_elf64 macro assumes the 
LLVM triple processor name matches the CMake processor name, which is 
unfortunately not the case for SystemZ.

Fix this by providing two separate arguments instead.

Actually building the plugin exposed a number of other issues causing various 
test failures.  Specifically, I've had to add the SystemZ target to
- CompilerInvocation::ParseLangArgs
- linkDevice in ClangLinuxWrapper.cpp
- OMPContext::OMPContext (to set the device_kind_cpu trait)
- LIBOMPTARGET_ALL_TARGETS in libomptarget/CMakeLists.txt
- a check_plugin_target call in libomptarget/src/CMakeLists.txt

Finally, I've had to set a number of test cases to UNSUPPORTED on 
s390x-ibm-linux-gnu; all these tests were already marked as UNSUPPORTED for 
x86_64-pc-linux-gnu and aarch64-unknown-linux-gnu and are failing on s390x for 
what seem to be the same reason.

In addition, this also requires support for BE ELF files in plugins-nextgen: 
https://github.com/llvm/llvm-project/pull/83976

>From 0ab19aae09cfdc1c0213ce1365d8a47a32d6ec9c Mon Sep 17 00:00:00 2001
From: Ulrich Weigand 
Date: Tue, 5 Mar 2024 10:03:55 +0100
Subject: [PATCH] [libomptarget] Build plugins-nextgen for SystemZ

The plugin was not getting built as the build_generic_elf64
macro assumes the LLVM triple processor name matches the
CMake processor name, which is unfortunately not the case
for SystemZ.

Fix this by providing two separate arguments instead.

Actually building the plugin exposed a number of other issues
causing various test failures.  Specifically, I've had to add
the SystemZ target to
- CompilerInvocation::ParseLangArgs
- linkDevice in ClangLinuxWrapper.cpp
- OMPContext::OMPContext (to set the device_kind_cpu trait)
- LIBOMPTARGET_ALL_TARGETS in libomptarget/CMakeLists.txt
- a check_plugin_target call in libomptarget/src/CMakeLists.txt

Finally, I've had to set a number of test cases to UNSUPPORTED
on s390x-ibm-linux-gnu; all these tests were already marked as
UNSUPPORTED for x86_64-pc-linux-gnu and aarch64-unknown-linux-gnu
and are failing on s390x for what seem to be the same reason.

In addition, this also requires support for BE ELF files in
plugins-nextgen: https://github.com/llvm/llvm-project/pull/83976
---
 clang/lib/Frontend/CompilerInvocation.cpp| 1 +
 clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp  | 1 +
 llvm/lib/Frontend/OpenMP/OMPContext.cpp  | 1 +
 openmp/libomptarget/CMakeLists.txt   | 2 ++
 openmp/libomptarget/plugins-nextgen/CMakeLists.txt   | 9 ++---
 .../libomptarget/plugins-nextgen/aarch64/CMakeLists.txt  | 2 +-
 openmp/libomptarget/plugins-nextgen/ppc64/CMakeLists.txt | 2 +-
 .../libomptarget/plugins-nextgen/ppc64le/CMakeLists.txt  | 2 +-
 openmp/libomptarget/plugins-nextgen/s390x/CMakeLists.txt | 2 +-
 .../libomptarget/plugins-nextgen/x86_64/CMakeLists.txt   | 2 +-
 openmp/libomptarget/src/CMakeLists.txt   | 1 +
 openmp/libomptarget/test/api/omp_dynamic_shared_memory.c | 2 ++
 openmp/libomptarget/test/jit/empty_kernel_lvl1.c | 2 ++
 openmp/libomptarget/test/jit/empty_kernel_lvl2.c | 2 ++
 openmp/libomptarget/test/jit/type_punning.c  | 2 ++
 openmp/libomptarget/test/mapping/auto_zero_copy.cpp  | 2 ++
 .../libomptarget/test/mapping/auto_zero_copy_globals.cpp | 2 ++
 openmp/libomptarget/test/offloading/barrier_fence.c  | 2 ++
 openmp/libomptarget/test/offloading/bug49334.cpp | 2 ++
 .../libomptarget/test/offloading/default_thread_limit.c  | 2 ++
 openmp/libomptarget/test/offloading/ompx_bare.c  | 2 ++
 openmp/libomptarget/test/offloading/ompx_coords.c| 2 ++
 openmp/libomptarget/test/offloading/ompx_saxpy_mixed.c   | 2 ++
 .../test/offloading/parallel_target_teams_reduction.cpp  | 2 ++
 openmp/libomptarget/test/offloading/small_trip_count.c   | 2 ++
 .../test/offloading/small_trip_count_thread_limit.cpp| 2 ++
 openmp/libomptarget/test/offloading/spmdization.c| 2 ++
 .../test/offloading/target_critical_region.cpp   | 2 ++
 openmp/libomptarget/test/offloading/thread_limit.c   | 2 ++
 openmp/libomptarget/test/ompt/target_memcpy.c| 2 ++
 openmp/libomptarget/test/ompt/target_memcpy_emi.c| 2 ++
 openmp/libomptarget/test/ompt/veccopy.c  | 2 ++
 openmp/libomptarget/test/ompt/veccopy_data.c | 2 ++
 openmp/libomptarget/test/ompt/veccopy_disallow_both.c| 2 ++
 openmp/libomptarget/test/ompt/veccopy_emi.c  | 2 ++
 openmp/libomptarget/test/ompt/veccopy_emi_map.c  | 2 ++
 openmp/libomptarget/test/ompt/veccopy_map.c  | 2 ++
 37 files changed, 69 insertions(+), 8 deletions(-)

diff --git a/clang/lib/Frontend/CompilerInvocation.cpp 
b/clang/lib/Frontend/CompilerInvocation.cpp
index 691f3b989b81e5..7e17c3e49acaf6 100644
--- a/clang/lib/Frontend/CompilerInvocation

[libcxx] [mlir] [llvm] [compiler-rt] [clang] [asan] Enable StackSafetyAnalysis by default (PR #77210)

2024-01-19 Thread Ulrich Weigand via cfe-commits

uweigand wrote:

@MaskRay I've done a bit more analysis now, and what seems to be going on is 
that with stack safety analysis off, this check:
```
  char array[len];
  assert(!(reinterpret_cast(array) & 31L));
```
succeeds because the VLA allocation gets instrumented, and therefore the VLA 
address is guaranteed to be 32-byte aligned.

However, with stack safety analysis *on*, that analysis (correctly) detects 
that the VLA is actually never accessed, and therefore the allocation does not 
need be instrumented.  Because it is isn't instrumented, it remains a regular 
alloca without special alignment requirements.

Therefore, there is no guarantee that the assert will succeed.  If the incoming 
stack pointer happened to already be 32-byte aligned, it will succeed - 
otherwise (and that's the cases where we're seeing failures on s390x), it will 
not.

This seems to be a platform-independent bug that just happens to be visible 
only on some platforms sometimes.


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


[llvm] [compiler-rt] [libcxx] [clang] [mlir] [asan] Enable StackSafetyAnalysis by default (PR #77210)

2024-01-16 Thread Ulrich Weigand via cfe-commits

uweigand wrote:

> This now causes failures in the SystemZ build bot: 
> https://lab.llvm.org/buildbot/#/builders/94/builds/18295

Looking at this a bit more, before this patch the stack alignment test passes 
because the IR is instrumented to include a call to `__asan_alloca_poison` 
using a 32-byte aligned alloca.  *With* this patch, that code is missing 
completely and there is no 32-byte aligned alloca, and therefore the whole 
stack is never re-aligned to a 32-byte boundary.

Not sure why the `__asan_alloca_poison` call is missing now ...


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


[libcxx] [clang] [mlir] [compiler-rt] [llvm] [asan] Enable StackSafetyAnalysis by default (PR #77210)

2024-01-15 Thread Ulrich Weigand via cfe-commits

uweigand wrote:

This now causes failures in the SystemZ build bot:
https://lab.llvm.org/buildbot/#/builders/94/builds/18295


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


[clang] [SystemZ][z/OS] Add support for recognizing z/OS personality function in Clang (PR #76073)

2024-01-15 Thread Ulrich Weigand via cfe-commits

https://github.com/uweigand approved this pull request.

LGTM

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


[llvm] [clang] [SystemZ] Support i128 as legal type in VRs (PR #74625)

2023-12-15 Thread Ulrich Weigand via cfe-commits

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


[clang] [llvm] [SystemZ] Support i128 as legal type in VRs (PR #74625)

2023-12-14 Thread Ulrich Weigand via cfe-commits

uweigand wrote:

Fixed merge conflicts, updated as described above, and fixed support for i128 
parameters in the z/OS XPLINK ABI.

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


[clang] [llvm] [SystemZ] Support i128 as legal type in VRs (PR #74625)

2023-12-14 Thread Ulrich Weigand via cfe-commits

uweigand wrote:

> I have looked through the changes and made some comments inline.

Thanks for the review!

> Commenting:

Fixed, thanks!

> I happened to notice some cases with room for improvement:

Good catch.  I've not addressed these right now, this can be done as a 
follow-up.  (The memory case is a bit tedious due to TableGen pattern 
limitations ...)

> As a side question: I forgot why we can get CCMask '5' here: it seems it 
> should be CCMASK_CMP_NE ('6'), if we reverse the LOC operation..?

No, 5 is correct here.  Reversing XORs the mask with the set of valid bits, so 
we have 13 ^ 8 == 5.

Looking at the VTM instruction, we have the following valid condition codes 
(making up the 13, i.e. 0, 1, or 3):
0 - Selected bits all zeros; or all mask bits zero
1 - Selected bits a mix of zeros and ones
2 - n/a
3 - Selected bits all ones

The original mask is 8, i.e. condition code 0 ("selected bits all zeros").  
Reversing this needs to check for condition codes 1 or 3, i.e. mask 5 
("selected bits a mix of zeros and ones" or "selected bits all ones").


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


[clang] [llvm] [SystemZ] Support i128 as legal type in VRs (PR #74625)

2023-12-14 Thread Ulrich Weigand via cfe-commits


@@ -1516,48 +1536,206 @@ let Predicates = [FeatureVector] in {
   }
 }
 
+//===--===//
+// Support for 128-bit integer values in vector registers
+//===--===//
+
+// Loads and stores.
+let Predicates = [FeatureVector] in {
+  def : Pat<(i128 (load bdxaddr12only:$addr)),
+(VL bdxaddr12only:$addr)>;
+  def : Pat<(store (i128 VR128:$src), bdxaddr12only:$addr),
+(VST VR128:$src, bdxaddr12only:$addr)>;
+}
+
+// Full i128 move from GPR pair.
+let Predicates = [FeatureVector] in
+  def : Pat<(i128 (or (zext GR64:$x), (shl (anyext GR64:$y), (i32 64,
+(VLVGP GR64:$y, GR64:$x)>;
+
+// Any-extensions from GPR to i128.
+let Predicates = [FeatureVector] in {
+  def : Pat<(i128 (anyext GR32:$x)), (VLVGP32 GR32:$x, GR32:$x)>;
+  def : Pat<(i128 (anyext GR64:$x)), (VLVGP GR64:$x, GR64:$x)>;
+}
+
+// Any-extending loads into i128.
+let Predicates = [FeatureVector] in {
+  def : Pat<(i128 (extloadi8 bdxaddr12only:$addr)),
+(VLREPB bdxaddr12only:$addr)>;
+  def : Pat<(i128 (extloadi16 bdxaddr12only:$addr)),
+(VLREPH bdxaddr12only:$addr)>;
+  def : Pat<(i128 (extloadi32 bdxaddr12only:$addr)),
+(VLREPF bdxaddr12only:$addr)>;
+  def : Pat<(i128 (extloadi64 bdxaddr12only:$addr)),
+(VLREPG bdxaddr12only:$addr)>;
+}
+
+// Truncations from i128 to GPR.
+let Predicates = [FeatureVector] in {
+  def : Pat<(i32 (trunc (i128 VR128:$vec))),
+(EXTRACT_SUBREG (VLGVF VR128:$vec, zero_reg, 3), subreg_l32)>;
+  def : Pat<(i32 (trunc (srl (i128 VR128:$vec), (i32 32,
+(EXTRACT_SUBREG (VLGVF VR128:$vec, zero_reg, 2), subreg_l32)>;
+  def : Pat<(i32 (trunc (srl (i128 VR128:$vec), (i32 64,
+(EXTRACT_SUBREG (VLGVF VR128:$vec, zero_reg, 1), subreg_l32)>;
+  def : Pat<(i32 (trunc (srl (i128 VR128:$vec), (i32 96,
+(EXTRACT_SUBREG (VLGVF VR128:$vec, zero_reg, 0), subreg_l32)>;
+  def : Pat<(i64 (trunc (i128 VR128:$vec))),
+(VLGVG VR128:$vec, zero_reg, 1)>;
+  def : Pat<(i64 (trunc (srl (i128 VR128:$vec), (i32 64,
+(VLGVG VR128:$vec, zero_reg, 0)>;
+}
+
+// Truncating stores from i128.
+let Predicates = [FeatureVector] in {
+  def : Pat<(truncstorei8 (i128 VR128:$x), bdxaddr12only:$addr),
+(VSTEB VR128:$x, bdxaddr12only:$addr, 15)>;
+  def : Pat<(truncstorei16 (i128 VR128:$x), bdxaddr12only:$addr),
+(VSTEH VR128:$x, bdxaddr12only:$addr, 7)>;
+  def : Pat<(truncstorei32 (i128 VR128:$x), bdxaddr12only:$addr),
+(VSTEF VR128:$x, bdxaddr12only:$addr, 3)>;
+  def : Pat<(truncstorei32 (srl (i128 VR128:$x), (i32 32)), 
bdxaddr12only:$addr),
+(VSTEF VR128:$x, bdxaddr12only:$addr, 2)>;
+  def : Pat<(truncstorei32 (srl (i128 VR128:$x), (i32 64)), 
bdxaddr12only:$addr),
+(VSTEF VR128:$x, bdxaddr12only:$addr, 1)>;
+  def : Pat<(truncstorei32 (srl (i128 VR128:$x), (i32 96)), 
bdxaddr12only:$addr),
+(VSTEF VR128:$x, bdxaddr12only:$addr, 0)>;
+  def : Pat<(truncstorei64 (i128 VR128:$x), bdxaddr12only:$addr),
+(VSTEG VR128:$x, bdxaddr12only:$addr, 1)>;
+  def : Pat<(truncstorei64 (srl (i128 VR128:$x), (i32 64)), 
bdxaddr12only:$addr),
+(VSTEG VR128:$x, bdxaddr12only:$addr, 0)>;
+}
+
+// Zero-extensions from GPR to i128.
+let Predicates = [FeatureVector] in {
+  def : Pat<(i128 (zext8 (anyext GR32:$x))),
+(VLVGB (VGBM 0), GR32:$x, zero_reg, 15)>;
+  def : Pat<(i128 (zext16 (anyext GR32:$x))),
+(VLVGH (VGBM 0), GR32:$x, zero_reg, 7)>;
+  def : Pat<(i128 (zext GR32:$x)),
+(VLVGF (VGBM 0), GR32:$x, zero_reg, 3)>;
+  def : Pat<(i128 (zext GR64:$x)),
+(VLVGG (VGBM 0), GR64:$x, zero_reg, 1)>;
+}
+
+// Zero-extending loads into i128.
+let Predicates = [FeatureVector] in {
+  def : Pat<(i128 (zextloadi8 bdxaddr12only:$addr)),
+(VLEB (VGBM 0), bdxaddr12only:$addr, 15)>;
+  def : Pat<(i128 (zextloadi16 bdxaddr12only:$addr)),
+(VLEH (VGBM 0), bdxaddr12only:$addr, 7)>;
+  def : Pat<(i128 (zextloadi32 bdxaddr12only:$addr)),
+(VLEF (VGBM 0), bdxaddr12only:$addr, 3)>;
+  def : Pat<(i128 (zextloadi64 bdxaddr12only:$addr)),
+(VLEG (VGBM 0), bdxaddr12only:$addr, 1)>;
+}
+
+// In-register i128 sign-extensions.
+let Predicates = [FeatureVector] in {
+  def : Pat<(i128 (sext_inreg VR128:$x, i8)),
+(VSRAB (VREPB VR128:$x, 15), (VREPIB 120))>;
+  def : Pat<(i128 (sext_inreg VR128:$x, i16)),
+(VSRAB (VREPH VR128:$x, 7), (VREPIB 112))>;
+  def : Pat<(i128 (sext_inreg VR128:$x, i32)),
+(VSRAB (VREPF VR128:$x, 3), (VREPIB 96))>;
+  def : Pat<(i128 (sext_inreg VR128:$x, i64)),
+(VSRAB (VREPG VR128:$x, 1), (VREPIB 64))>;
+}
+
+// Sign-extensions from GPR to i128.
+let Predicates = [FeatureVector] in {
+  def : Pat<(i128 (sext_inreg (anyext

[clang] [llvm] [SystemZ] Support i128 as legal type in VRs (PR #74625)

2023-12-14 Thread Ulrich Weigand via cfe-commits


@@ -6481,6 +6737,71 @@ SDValue SystemZTargetLowering::combineLOAD(
 SDNode *N, DAGCombinerInfo &DCI) const {
   SelectionDAG &DAG = DCI.DAG;
   EVT LdVT = N->getValueType(0);
+  SDLoc DL(N);
+
+  // Replace an i128 load that is used solely to move its value into GPRs
+  // by separate loads of both halves.
+  if (LdVT == MVT::i128) {
+LoadSDNode *LD = cast(N);
+if (!LD->isSimple() || !ISD::isNormalLoad(LD))
+  return SDValue();
+
+// Scan through all users.
+SmallVector, 2> Users;
+int UsedElements = 0;
+for (SDNode::use_iterator UI = LD->use_begin(), UIEnd = LD->use_end();
+ UI != UIEnd; ++UI) {
+  // Skip the uses of the chain.
+  if (UI.getUse().getResNo() != 0)
+continue;
+
+  // Verify every user is a TRUNCATE to i64 of the low or high half ...
+  SDNode *User = *UI;
+  int Index = 1;
+  if (User->getOpcode() == ISD::SRL &&
+  User->getOperand(1).getOpcode() == ISD::Constant &&
+  cast(User->getOperand(1))->getZExtValue() == 64 &&
+  User->hasOneUse()) {
+User = *User->use_begin();
+Index = 0;
+  }
+  if (User->getOpcode() != ISD::TRUNCATE ||
+  User->getValueType(0) != MVT::i64)
+return SDValue();
+
+  // ... and no half is extracted twice.
+  if (UsedElements & (1 << Index))
+return SDValue();
+
+  UsedElements |= 1 << Index;
+  Users.push_back(std::make_pair(User, Index));
+}
+
+// Rewrite each extraction as an independent load.
+SmallVector ArgChains;
+for (auto UserAndIndex : Users) {
+  SDNode *User = UserAndIndex.first;
+  unsigned Offset = User->getValueType(0).getStoreSize() * 
UserAndIndex.second;
+  SDValue Ptr =

uweigand wrote:

Well, `getStoreSize` should be 8 here, but seems clearer to refer to it 
symbolically.

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


[clang] [llvm] [SystemZ] Support i128 as legal type in VRs (PR #74625)

2023-12-14 Thread Ulrich Weigand via cfe-commits


@@ -2918,16 +3049,17 @@ static Comparison getCmp(SelectionDAG &DAG, SDValue 
CmpOp0, SDValue CmpOp1,
  bool IsSignaling = false) {
   if (CmpOp1.getOpcode() == ISD::Constant) {
 assert(!Chain);
-uint64_t Constant = cast(CmpOp1)->getZExtValue();
 unsigned Opcode, CCValid;

uweigand wrote:

`getZExtValue` will crash when the constant is 128-bit, which can now happen.  
Therefore I'm now only evaluating it in code paths where we know the constant 
cannot be 128-bit.

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


[clang] [llvm] [SystemZ] Support i128 as legal type in VRs (PR #74625)

2023-12-14 Thread Ulrich Weigand via cfe-commits


@@ -2772,6 +2837,27 @@ static unsigned getTestUnderMaskCond(unsigned BitSize, 
unsigned CCMask,
 // Update the arguments with the TM version if so.
 static void adjustForTestUnderMask(SelectionDAG &DAG, const SDLoc &DL,
Comparison &C) {
+  // Use VECTOR TEST UNDER MASK for i128 operations.
+  if (C.Op0.getValueType() == MVT::i128) {

uweigand wrote:

Well, we need `VCEQS` to set CC which takes an extra cycle, so it should both 
be three cycles, but then VTM is shorter.

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


[clang] [llvm] [SystemZ] Support i128 as legal type in VRs (PR #74625)

2023-12-14 Thread Ulrich Weigand via cfe-commits


@@ -1466,7 +1509,15 @@ static SDValue convertValVTToLocVT(SelectionDAG &DAG, 
const SDLoc &DL,
 static SDValue lowerI128ToGR128(SelectionDAG &DAG, SDValue In) {
   SDLoc DL(In);
   SDValue Lo, Hi;
-  std::tie(Lo, Hi) = DAG.SplitScalar(In, DL, MVT::i64, MVT::i64);
+  if (DAG.getTargetLoweringInfo().isTypeLegal(MVT::i128)) {
+Lo = DAG.getNode(ISD::TRUNCATE, DL, MVT::i64, In);

uweigand wrote:

Hmmm.  According to the specs, `EXTRACT_ELEMENT` (and therefore `SplitScalar`) 
is only supposed to be used on non-legal types, for values that will be broken 
up into multiple registers.   However, the actual implementation doesn't appear 
to verify this, and expands `EXTRACT_ELEMENT` even for a legal `i128`, to the 
same code ...

I would still prefer to not rely on that undocumented behavior, and use the 
explicit expansion.  Also, this keeps the implementation symmetrical to 
`lowerGR128ToI128`, and may be slightly more efficient as it omits generating 
and then immediately eliminating the `EXTRACT_ELEMENT` nodes.

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


[clang] [llvm] [SystemZ] Support i128 as legal type in VRs (PR #74625)

2023-12-14 Thread Ulrich Weigand via cfe-commits


@@ -1183,6 +1187,35 @@ void SystemZDAGToDAGISel::loadVectorConstant(
   SelectCode(Op.getNode());
 }
 
+SDNode *SystemZDAGToDAGISel::loadPoolVectorConstant(APInt Val, EVT VT, SDLoc 
DL) {
+  SDNode *ResNode;
+  assert (VT.getSizeInBits() == 128);
+
+  SDValue CP = CurDAG->getTargetConstantPool(
+  ConstantInt::get(Type::getInt128Ty(*CurDAG->getContext()), Val),
+  TLI->getPointerTy(CurDAG->getDataLayout()));
+
+  EVT PtrVT = CP.getValueType();
+  SDValue Ops[] = {
+SDValue(CurDAG->getMachineNode(SystemZ::LARL, DL, PtrVT, CP), 0),
+CurDAG->getTargetConstant(0, DL, PtrVT),
+CurDAG->getRegister(0, PtrVT),
+CurDAG->getEntryNode()
+  };
+  ResNode = CurDAG->getMachineNode(SystemZ::VL, DL, VT, MVT::Other, Ops);
+
+  // Annotate ResNode with memory operand information so that MachineInstr
+  // queries work properly. This e.g. gives the register allocation the
+  // required information for rematerialization.
+  MachineFunction& MF = CurDAG->getMachineFunction();
+  MachineMemOperand *MemOp =
+  MF.getMachineMemOperand(MachinePointerInfo::getConstantPool(MF),
+  MachineMemOperand::MOLoad, 8, Align(8));
+

uweigand wrote:

Fixed, thanks!

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


[llvm] [clang] [SystemZ] Support i128 as legal type in VRs (PR #74625)

2023-12-06 Thread Ulrich Weigand via cfe-commits

uweigand wrote:

@JonPsson1 - please have a look at the effects of i128 support in particular on 
atomics
@redstar - can you check impact on the z/OS ABI?  we may need to handle legal 
i128 there too, but there doesn't appear to be any in-tree test case for 
passing i128 on z/OS

Any other comments welcome as well!

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


[llvm] [clang] [SystemZ] Properly support 16 byte atomic int/fp types and ops. (PR #73134)

2023-12-04 Thread Ulrich Weigand via cfe-commits

https://github.com/uweigand approved this pull request.

This version LGTM now.

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


[clang] 9d27139 - [SystemZ] Fix __builtin_s390_vceq* inconsistency

2023-12-04 Thread Ulrich Weigand via cfe-commits

Author: Ulrich Weigand
Date: 2023-12-04T17:00:05+01:00
New Revision: 9d27139293890a18b903c62f2c43954cc2bc302d

URL: 
https://github.com/llvm/llvm-project/commit/9d27139293890a18b903c62f2c43954cc2bc302d
DIFF: 
https://github.com/llvm/llvm-project/commit/9d27139293890a18b903c62f2c43954cc2bc302d.diff

LOG: [SystemZ] Fix __builtin_s390_vceq* inconsistency

The __builtin_s390_vceq* family of builtins currently take
signed arguments with clang, but unsigned with GCC.  Update
clang to match existing GCC precendent.

Added: 


Modified: 
clang/include/clang/Basic/BuiltinsSystemZ.def
clang/lib/Headers/vecintrin.h
clang/test/CodeGen/SystemZ/builtins-systemz-vector.c

Removed: 




diff  --git a/clang/include/clang/Basic/BuiltinsSystemZ.def 
b/clang/include/clang/Basic/BuiltinsSystemZ.def
index 02171d29ffd91..4cfc52ae42168 100644
--- a/clang/include/clang/Basic/BuiltinsSystemZ.def
+++ b/clang/include/clang/Basic/BuiltinsSystemZ.def
@@ -80,10 +80,10 @@ TARGET_BUILTIN(__builtin_s390_vavglb, "V16UcV16UcV16Uc", 
"nc", "vector")
 TARGET_BUILTIN(__builtin_s390_vavglh, "V8UsV8UsV8Us", "nc", "vector")
 TARGET_BUILTIN(__builtin_s390_vavglf, "V4UiV4UiV4Ui", "nc", "vector")
 TARGET_BUILTIN(__builtin_s390_vavglg, "V2ULLiV2ULLiV2ULLi", "nc", "vector")
-TARGET_BUILTIN(__builtin_s390_vceqbs, "V16ScV16ScV16Sci*", "nc", "vector")
-TARGET_BUILTIN(__builtin_s390_vceqhs, "V8SsV8SsV8Ssi*", "nc", "vector")
-TARGET_BUILTIN(__builtin_s390_vceqfs, "V4SiV4SiV4Sii*", "nc", "vector")
-TARGET_BUILTIN(__builtin_s390_vceqgs, "V2SLLiV2SLLiV2SLLii*", "nc", "vector")
+TARGET_BUILTIN(__builtin_s390_vceqbs, "V16ScV16UcV16Uci*", "nc", "vector")
+TARGET_BUILTIN(__builtin_s390_vceqhs, "V8SsV8UsV8Usi*", "nc", "vector")
+TARGET_BUILTIN(__builtin_s390_vceqfs, "V4SiV4UiV4Uii*", "nc", "vector")
+TARGET_BUILTIN(__builtin_s390_vceqgs, "V2SLLiV2ULLiV2ULLii*", "nc", "vector")
 TARGET_BUILTIN(__builtin_s390_vchbs, "V16ScV16ScV16Sci*", "nc", "vector")
 TARGET_BUILTIN(__builtin_s390_vchhs, "V8SsV8SsV8Ssi*", "nc", "vector")
 TARGET_BUILTIN(__builtin_s390_vchfs, "V4SiV4SiV4Sii*", "nc", "vector")

diff  --git a/clang/lib/Headers/vecintrin.h b/clang/lib/Headers/vecintrin.h
index 0ea411f40218e..ecfd6cd1a2f87 100644
--- a/clang/lib/Headers/vecintrin.h
+++ b/clang/lib/Headers/vecintrin.h
@@ -2689,7 +2689,8 @@ vec_cmplt(__vector double __a, __vector double __b) {
 static inline __ATTRS_o_ai int
 vec_all_eq(__vector signed char __a, __vector signed char __b) {
   int __cc;
-  __builtin_s390_vceqbs(__a, __b, &__cc);
+  __builtin_s390_vceqbs((__vector unsigned char)__a,
+(__vector unsigned char)__b, &__cc);
   return __cc == 0;
 }
 
@@ -2697,7 +2698,8 @@ vec_all_eq(__vector signed char __a, __vector signed char 
__b) {
 static inline __ATTRS_o_ai int
 vec_all_eq(__vector signed char __a, __vector __bool char __b) {
   int __cc;
-  __builtin_s390_vceqbs(__a, (__vector signed char)__b, &__cc);
+  __builtin_s390_vceqbs((__vector unsigned char)__a,
+(__vector unsigned char)__b, &__cc);
   return __cc == 0;
 }
 
@@ -2705,15 +2707,15 @@ vec_all_eq(__vector signed char __a, __vector __bool 
char __b) {
 static inline __ATTRS_o_ai int
 vec_all_eq(__vector __bool char __a, __vector signed char __b) {
   int __cc;
-  __builtin_s390_vceqbs((__vector signed char)__a, __b, &__cc);
+  __builtin_s390_vceqbs((__vector unsigned char)__a,
+(__vector unsigned char)__b, &__cc);
   return __cc == 0;
 }
 
 static inline __ATTRS_o_ai int
 vec_all_eq(__vector unsigned char __a, __vector unsigned char __b) {
   int __cc;
-  __builtin_s390_vceqbs((__vector signed char)__a,
-(__vector signed char)__b, &__cc);
+  __builtin_s390_vceqbs(__a, __b, &__cc);
   return __cc == 0;
 }
 
@@ -2721,8 +2723,7 @@ vec_all_eq(__vector unsigned char __a, __vector unsigned 
char __b) {
 static inline __ATTRS_o_ai int
 vec_all_eq(__vector unsigned char __a, __vector __bool char __b) {
   int __cc;
-  __builtin_s390_vceqbs((__vector signed char)__a,
-(__vector signed char)__b, &__cc);
+  __builtin_s390_vceqbs(__a, (__vector unsigned char)__b, &__cc);
   return __cc == 0;
 }
 
@@ -2730,23 +2731,23 @@ vec_all_eq(__vector unsigned char __a, __vector __bool 
char __b) {
 static inline __ATTRS_o_ai int
 vec_all_eq(__vector __bool char __a, __vector unsigned char __b) {
   int __cc;
-  __builtin_s390_vceqbs((__vector signed char)__a,
-(__vector signed char)__b, &__cc);
+  __builtin_s390_vceqbs((__vector unsigned char)__a, __b, &__cc);
   return __cc == 0;
 }
 
 static inline __ATTRS_o_ai int
 vec_all_eq(__vector __bool char __a, __vector __bool char __b) {
   int __cc;
-  __builtin_s390_vceqbs((__vector signed char)__a,
-(__vector signed char)__b, &__cc);
+  __builtin_s390_vceqbs((__vector unsigned char)__a,
+(__vector unsigned char)__b, &__cc

[clang] dca432c - [SystemZ] Fix naming of vlrlr/vstrlr builtins

2023-12-04 Thread Ulrich Weigand via cfe-commits

Author: Ulrich Weigand
Date: 2023-12-04T16:53:18+01:00
New Revision: dca432cb7b1c282f5dc861095813c4f40f109619

URL: 
https://github.com/llvm/llvm-project/commit/dca432cb7b1c282f5dc861095813c4f40f109619
DIFF: 
https://github.com/llvm/llvm-project/commit/dca432cb7b1c282f5dc861095813c4f40f109619.diff

LOG: [SystemZ] Fix naming of vlrlr/vstrlr builtins

The builtins that expand to the vlrl/vlrlr and vstrl/vstrlr
instructions are currently named inconsistently between GCC
and clang.  Rename the clang versions to match GCC.

Added: 


Modified: 
clang/include/clang/Basic/BuiltinsSystemZ.def
clang/lib/Headers/vecintrin.h
clang/test/CodeGen/SystemZ/builtins-systemz-vector2.c
llvm/include/llvm/IR/IntrinsicsSystemZ.td

Removed: 




diff  --git a/clang/include/clang/Basic/BuiltinsSystemZ.def 
b/clang/include/clang/Basic/BuiltinsSystemZ.def
index b84cf5b9cec9f..02171d29ffd91 100644
--- a/clang/include/clang/Basic/BuiltinsSystemZ.def
+++ b/clang/include/clang/Basic/BuiltinsSystemZ.def
@@ -253,8 +253,8 @@ TARGET_BUILTIN(__builtin_s390_vfsqdb, "V2dV2d", "nc", 
"vector")
 TARGET_BUILTIN(__builtin_s390_vftcidb, "V2SLLiV2dIii*", "nc", "vector")
 
 // Vector-enhancements facility 1 intrinsics.
-TARGET_BUILTIN(__builtin_s390_vlrl, "V16ScUivC*", "", "vector-enhancements-1")
-TARGET_BUILTIN(__builtin_s390_vstrl, "vV16ScUiv*", "", "vector-enhancements-1")
+TARGET_BUILTIN(__builtin_s390_vlrlr, "V16ScUivC*", "", "vector-enhancements-1")
+TARGET_BUILTIN(__builtin_s390_vstrlr, "vV16ScUiv*", "", 
"vector-enhancements-1")
 TARGET_BUILTIN(__builtin_s390_vbperm, "V2ULLiV16UcV16Uc", "nc", 
"vector-enhancements-1")
 TARGET_BUILTIN(__builtin_s390_vmslg, "V16UcV2ULLiV2ULLiV16UcIi", "nc", 
"vector-enhancements-1")
 TARGET_BUILTIN(__builtin_s390_vfmaxdb, "V2dV2dV2dIi", "nc", 
"vector-enhancements-1")

diff  --git a/clang/lib/Headers/vecintrin.h b/clang/lib/Headers/vecintrin.h
index 0c535225c78e5..0ea411f40218e 100644
--- a/clang/lib/Headers/vecintrin.h
+++ b/clang/lib/Headers/vecintrin.h
@@ -1543,7 +1543,7 @@ vec_load_len(const double *__ptr, unsigned int __len) {
 #if __ARCH__ >= 12
 static inline __ATTRS_ai __vector unsigned char
 vec_load_len_r(const unsigned char *__ptr, unsigned int __len) {
-  return (__vector unsigned char)__builtin_s390_vlrl(__len, __ptr);
+  return (__vector unsigned char)__builtin_s390_vlrlr(__len, __ptr);
 }
 #endif
 
@@ -1617,7 +1617,7 @@ vec_store_len(__vector double __vec, double *__ptr,
 static inline __ATTRS_ai void
 vec_store_len_r(__vector unsigned char __vec, unsigned char *__ptr,
 unsigned int __len) {
-  __builtin_s390_vstrl((__vector signed char)__vec, __len, __ptr);
+  __builtin_s390_vstrlr((__vector signed char)__vec, __len, __ptr);
 }
 #endif
 

diff  --git a/clang/test/CodeGen/SystemZ/builtins-systemz-vector2.c 
b/clang/test/CodeGen/SystemZ/builtins-systemz-vector2.c
index 0fcfeeafbfaa6..5e287e28ed201 100644
--- a/clang/test/CodeGen/SystemZ/builtins-systemz-vector2.c
+++ b/clang/test/CodeGen/SystemZ/builtins-systemz-vector2.c
@@ -33,10 +33,10 @@ void test_core(void) {
   vul = __builtin_s390_vbperm(vuc, vuc);
   // CHECK: call <2 x i64> @llvm.s390.vbperm(<16 x i8> %{{.*}}, <16 x i8> 
%{{.*}})
 
-  vsc = __builtin_s390_vlrl(len, cptr);
+  vsc = __builtin_s390_vlrlr(len, cptr);
   // CHECK: call <16 x i8> @llvm.s390.vlrl(i32 %{{.*}}, ptr %{{.*}})
 
-  __builtin_s390_vstrl(vsc, len, ptr);
+  __builtin_s390_vstrlr(vsc, len, ptr);
   // CHECK: call void @llvm.s390.vstrl(<16 x i8> %{{.*}}, i32 %{{.*}}, ptr 
%{{.*}})
 }
 

diff  --git a/llvm/include/llvm/IR/IntrinsicsSystemZ.td 
b/llvm/include/llvm/IR/IntrinsicsSystemZ.td
index 9f79bdfa9d2d2..a9d80ee5a5c7a 100644
--- a/llvm/include/llvm/IR/IntrinsicsSystemZ.td
+++ b/llvm/include/llvm/IR/IntrinsicsSystemZ.td
@@ -398,11 +398,11 @@ let TargetPrefix = "s390" in {
  [IntrNoMem, ImmArg>, 
ImmArg>]>;
 
   // Instructions from the Vector Packed Decimal Facility
-  def int_s390_vlrl : ClangBuiltin<"__builtin_s390_vlrl">,
+  def int_s390_vlrl : ClangBuiltin<"__builtin_s390_vlrlr">,
   Intrinsic<[llvm_v16i8_ty], [llvm_i32_ty, llvm_ptr_ty],
 [IntrReadMem, IntrArgMemOnly]>;
 
-  def int_s390_vstrl : ClangBuiltin<"__builtin_s390_vstrl">,
+  def int_s390_vstrl : ClangBuiltin<"__builtin_s390_vstrlr">,
Intrinsic<[], [llvm_v16i8_ty, llvm_i32_ty, llvm_ptr_ty],
  [IntrArgMemOnly, IntrWriteMem]>;
 



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


[clang] c61eb44 - [SystemZ] Implement vector rotate in terms of funnel shift

2023-12-04 Thread Ulrich Weigand via cfe-commits

Author: Ulrich Weigand
Date: 2023-12-04T16:52:00+01:00
New Revision: c61eb440059d6e9c18e6f8404e06bf125aa942c9

URL: 
https://github.com/llvm/llvm-project/commit/c61eb440059d6e9c18e6f8404e06bf125aa942c9
DIFF: 
https://github.com/llvm/llvm-project/commit/c61eb440059d6e9c18e6f8404e06bf125aa942c9.diff

LOG: [SystemZ] Implement vector rotate in terms of funnel shift

Clang currently implements a set of vector rotate builtins
(__builtin_s390_verll*) in terms of platform-specific LLVM
intrinsics.  To simplify the IR (and allow for common code
optimizations if applicable), this patch removes those LLVM
intrinsics and implements the builtins in terms of the
platform-independent funnel shift intrinsics instead.

Also, fix the prototype of the __builtin_s390_verll*
builtins for full compatibility with GCC.

Added: 
llvm/test/CodeGen/SystemZ/vec-rot-01.ll
llvm/test/CodeGen/SystemZ/vec-rot-02.ll

Modified: 
clang/include/clang/Basic/BuiltinsSystemZ.def
clang/lib/CodeGen/CGBuiltin.cpp
clang/lib/Headers/vecintrin.h
clang/test/CodeGen/SystemZ/builtins-systemz-vector.c
clang/test/CodeGen/SystemZ/builtins-systemz-zvector.c
llvm/include/llvm/IR/IntrinsicsSystemZ.td
llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
llvm/lib/Target/SystemZ/SystemZISelLowering.h
llvm/lib/Target/SystemZ/SystemZInstrVector.td
llvm/lib/Target/SystemZ/SystemZOperators.td
llvm/test/CodeGen/SystemZ/vec-intrinsics-01.ll

Removed: 




diff  --git a/clang/include/clang/Basic/BuiltinsSystemZ.def 
b/clang/include/clang/Basic/BuiltinsSystemZ.def
index 079e411364885..b84cf5b9cec9f 100644
--- a/clang/include/clang/Basic/BuiltinsSystemZ.def
+++ b/clang/include/clang/Basic/BuiltinsSystemZ.def
@@ -105,10 +105,10 @@ TARGET_BUILTIN(__builtin_s390_verimb, 
"V16UcV16UcV16UcV16UcIi", "nc", "vector")
 TARGET_BUILTIN(__builtin_s390_verimh, "V8UsV8UsV8UsV8UsIi", "nc", "vector")
 TARGET_BUILTIN(__builtin_s390_verimf, "V4UiV4UiV4UiV4UiIi", "nc", "vector")
 TARGET_BUILTIN(__builtin_s390_verimg, "V2ULLiV2ULLiV2ULLiV2ULLiIi", "nc", 
"vector")
-TARGET_BUILTIN(__builtin_s390_verllb, "V16UcV16UcUi", "nc", "vector")
-TARGET_BUILTIN(__builtin_s390_verllh, "V8UsV8UsUi", "nc", "vector")
-TARGET_BUILTIN(__builtin_s390_verllf, "V4UiV4UiUi", "nc", "vector")
-TARGET_BUILTIN(__builtin_s390_verllg, "V2ULLiV2ULLiUi", "nc", "vector")
+TARGET_BUILTIN(__builtin_s390_verllb, "V16UcV16UcUc", "nc", "vector")
+TARGET_BUILTIN(__builtin_s390_verllh, "V8UsV8UsUc", "nc", "vector")
+TARGET_BUILTIN(__builtin_s390_verllf, "V4UiV4UiUc", "nc", "vector")
+TARGET_BUILTIN(__builtin_s390_verllg, "V2ULLiV2ULLiUc", "nc", "vector")
 TARGET_BUILTIN(__builtin_s390_verllvb, "V16UcV16UcV16Uc", "nc", "vector")
 TARGET_BUILTIN(__builtin_s390_verllvh, "V8UsV8UsV8Us", "nc", "vector")
 TARGET_BUILTIN(__builtin_s390_verllvf, "V4UiV4UiV4Ui", "nc", "vector")

diff  --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 65d9862621061..a0f4172002613 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -18337,6 +18337,32 @@ Value 
*CodeGenFunction::EmitSystemZBuiltinExpr(unsigned BuiltinID,
 return Builder.CreateCall(F, {X, Undef});
   }
 
+  case SystemZ::BI__builtin_s390_verllb:
+  case SystemZ::BI__builtin_s390_verllh:
+  case SystemZ::BI__builtin_s390_verllf:
+  case SystemZ::BI__builtin_s390_verllg: {
+llvm::Type *ResultType = ConvertType(E->getType());
+llvm::Value *Src = EmitScalarExpr(E->getArg(0));
+llvm::Value *Amt = EmitScalarExpr(E->getArg(1));
+// Splat scalar rotate amount to vector type.
+unsigned NumElts = 
cast(ResultType)->getNumElements();
+Amt = Builder.CreateIntCast(Amt, ResultType->getScalarType(), false);
+Amt = Builder.CreateVectorSplat(NumElts, Amt);
+Function *F = CGM.getIntrinsic(Intrinsic::fshl, ResultType);
+return Builder.CreateCall(F, { Src, Src, Amt });
+  }
+
+  case SystemZ::BI__builtin_s390_verllvb:
+  case SystemZ::BI__builtin_s390_verllvh:
+  case SystemZ::BI__builtin_s390_verllvf:
+  case SystemZ::BI__builtin_s390_verllvg: {
+llvm::Type *ResultType = ConvertType(E->getType());
+llvm::Value *Src = EmitScalarExpr(E->getArg(0));
+llvm::Value *Amt = EmitScalarExpr(E->getArg(1));
+Function *F = CGM.getIntrinsic(Intrinsic::fshl, ResultType);
+return Builder.CreateCall(F, { Src, Src, Amt });
+  }
+
   case SystemZ::BI__builtin_s390_vfsqsb:
   case SystemZ::BI__builtin_s390_vfsqdb: {
 llvm::Type *ResultType = ConvertType(E->getType());

diff  --git a/clang/lib/Headers/vecintrin.h b/clang/lib/Headers/vecintrin.h
index ec1dbfd015f6e..0c535225c78e5 100644
--- a/clang/lib/Headers/vecintrin.h
+++ b/clang/lib/Headers/vecintrin.h
@@ -6565,45 +6565,45 @@ vec_rl(__vector unsigned long long __a, __vector 
unsigned long long __b) {
 static inline __ATTRS_o_ai __vector signed char
 vec_rli(__vector signed char __a, unsigned long __b) {
   return (__vecto

[llvm] [clang] [clang, SystemZ] Pass HasDef flag to getMinGlobalAlign(). (PR #73511)

2023-11-28 Thread Ulrich Weigand via cfe-commits

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


[llvm] [clang] [clang, SystemZ] Pass HasDef flag to getMinGlobalAlign(). (PR #73511)

2023-11-28 Thread Ulrich Weigand via cfe-commits


@@ -1687,7 +1687,8 @@ CharUnits ASTContext::getDeclAlign(const Decl *D, bool 
ForAlignof) const {
   if (VD->hasGlobalStorage() && !ForAlignof) {
 uint64_t TypeSize =
 !BaseT->isIncompleteType() ? getTypeSize(T.getTypePtr()) : 0;
-Align = std::max(Align, getTargetInfo().getMinGlobalAlign(TypeSize));
+Align = std::max(Align, getTargetInfo().getMinGlobalAlign(
+TypeSize, VD->hasDefinition()));

uweigand wrote:

So the intent of the option is to 1) when emitting a symbol definition 
directly, keep using the 2-byte ABI alignment, but 2) when refering to a symbol 
that *might* be defined externally, do not make using any alignment assumption. 
 In GCC this is using the same checks used elsewhere to test where a symbol is 
guaranteed local or might be external (keeping in mind things like weak symbols 
or ELF overrides).

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


[clang] [llvm] [SystemZ][z/OS] This change adds support for the PPA2 section in zOS (PR #68926)

2023-11-27 Thread Ulrich Weigand via cfe-commits

https://github.com/uweigand approved this pull request.

This version LGTM now, thanks!

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


[clang] [llvm] [SystemZ] Properly support 16 byte atomic int/fp types and ops. (PR #73134)

2023-11-24 Thread Ulrich Weigand via cfe-commits

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


[clang] [llvm] [SystemZ] Properly support 16 byte atomic int/fp types and ops. (PR #73134)

2023-11-24 Thread Ulrich Weigand via cfe-commits

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


[clang] [llvm] [SystemZ] Properly support 16 byte atomic int/fp types and ops. (PR #73134)

2023-11-24 Thread Ulrich Weigand via cfe-commits


@@ -0,0 +1,71 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
+// RUN: %clang_cc1 -triple s390x-linux-gnu -O1 -emit-llvm %s -o - | FileCheck 
%s
+//
+// Test __atomic_is_lock_free() for __int128 with default alignment (8
+// bytes), atomic alignment (16 bytes) and with a null pointer. Also test
+// __atomic_always_lock_free() and __c11_atomic_is_lock_free().
+
+#include 
+#include 
+
+__int128 Ptr_Al8   __attribute__((aligned(8)));
+__int128 Ptr_Al16 __attribute__((aligned(16)));
+
+// CHECK-LABEL: @fun_PtrAl8_is_lock_free(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:[[CALL:%.*]] = tail call zeroext i1 
@__atomic_is_lock_free(i64 noundef 16, ptr noundef nonnull @Ptr_Al8) 
#[[ATTR2:[0-9]+]]
+// CHECK-NEXT:ret i1 [[CALL]]
+//
+_Bool fun_PtrAl8_is_lock_free() {
+  return __atomic_is_lock_free(16, &Ptr_Al8);
+}
+
+// CHECK-LABEL: @fun_PtrAl8_always_lock_free(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:ret i1 false
+//
+_Bool fun_PtrAl8_always_lock_free() {
+  return __atomic_always_lock_free(16, &Ptr_Al8);
+}
+
+// CHECK-LABEL: @fun_PtrAl16_is_lock_free(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:[[CALL:%.*]] = tail call zeroext i1 
@__atomic_is_lock_free(i64 noundef 16, ptr noundef nonnull @Ptr_Al16) #[[ATTR2]]
+// CHECK-NEXT:ret i1 [[CALL]]
+//
+_Bool fun_PtrAl16_is_lock_free() {
+  return __atomic_is_lock_free(16, &Ptr_Al16);
+}
+
+// CHECK-LABEL: @fun_PtrAl16_always_lock_free(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:ret i1 false
+//
+_Bool fun_PtrAl16_always_lock_free() {
+  return __atomic_always_lock_free(16, &Ptr_Al16);
+}
+
+// CHECK-LABEL: @fun_noptr_is_lock_free(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:ret i1 true
+//
+_Bool fun_noptr_is_lock_free() {
+  return __atomic_is_lock_free(16, 0);

uweigand wrote:

But this seems actually incorrect - when using *default* assumptions, the 
operation should *not* be lock-free ...

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


[llvm] [clang] [SystemZ] Properly support 16 byte atomic int/fp types and ops. (PR #73134)

2023-11-24 Thread Ulrich Weigand via cfe-commits


@@ -0,0 +1,71 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
+// RUN: %clang_cc1 -triple s390x-linux-gnu -O1 -emit-llvm %s -o - | FileCheck 
%s
+//
+// Test __atomic_is_lock_free() for __int128 with default alignment (8
+// bytes), atomic alignment (16 bytes) and with a null pointer. Also test
+// __atomic_always_lock_free() and __c11_atomic_is_lock_free().
+
+#include 
+#include 
+
+__int128 Ptr_Al8   __attribute__((aligned(8)));
+__int128 Ptr_Al16 __attribute__((aligned(16)));
+
+// CHECK-LABEL: @fun_PtrAl8_is_lock_free(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:[[CALL:%.*]] = tail call zeroext i1 
@__atomic_is_lock_free(i64 noundef 16, ptr noundef nonnull @Ptr_Al8) 
#[[ATTR2:[0-9]+]]
+// CHECK-NEXT:ret i1 [[CALL]]
+//
+_Bool fun_PtrAl8_is_lock_free() {
+  return __atomic_is_lock_free(16, &Ptr_Al8);
+}
+
+// CHECK-LABEL: @fun_PtrAl8_always_lock_free(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:ret i1 false
+//
+_Bool fun_PtrAl8_always_lock_free() {
+  return __atomic_always_lock_free(16, &Ptr_Al8);
+}
+
+// CHECK-LABEL: @fun_PtrAl16_is_lock_free(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:[[CALL:%.*]] = tail call zeroext i1 
@__atomic_is_lock_free(i64 noundef 16, ptr noundef nonnull @Ptr_Al16) #[[ATTR2]]

uweigand wrote:

Here I would have expected `true`, assuming the compiler correctly figures out 
the object is 16-byte aligned.

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


[llvm] [clang] [SystemZ] Properly support 16 byte atomic int/fp types and ops. (PR #73134)

2023-11-24 Thread Ulrich Weigand via cfe-commits

https://github.com/uweigand commented:

Not sure about the is_lock_free results, see inline comments.

What does recent GCC return for those?

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


[clang] [SystemZ] Move new test into existing CodeGen test. (PR #73230)

2023-11-23 Thread Ulrich Weigand via cfe-commits

https://github.com/uweigand approved this pull request.

LGTM, thanks!

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


[clang] [llvm] [SystemZ][z/OS] This change adds support for the PPA2 section in zOS (PR #68926)

2023-11-23 Thread Ulrich Weigand via cfe-commits


@@ -1026,6 +1030,72 @@ void SystemZAsmPrinter::emitADASection() {
   OutStreamer->popSection();
 }
 
+static std::string getProductID(Module &M) {
+  std::string ProductID;
+  if (auto *MD = M.getModuleFlag("zos_product_id"))
+ProductID = cast(MD)->getString().str();
+  if (ProductID.empty())
+ProductID = "LLVM";
+  return ProductID;
+}
+
+static uint32_t getProductVersion(Module &M) {
+  if (auto *VersionVal = mdconst::extract_or_null(
+  M.getModuleFlag("zos_product_major_version")))
+return VersionVal->getZExtValue();
+  return LLVM_VERSION_MAJOR;
+}
+
+static uint32_t getProductRelease(Module &M) {
+  if (auto *ReleaseVal = mdconst::extract_or_null(
+  M.getModuleFlag("zos_product_minor_version")))
+return ReleaseVal->getZExtValue();
+  return LLVM_VERSION_MINOR;
+}
+
+static uint32_t getProductPatch(Module &M) {
+  if (auto *PatchVal = mdconst::extract_or_null(
+  M.getModuleFlag("zos_product_patchlevel")))
+return PatchVal->getZExtValue();
+  return LLVM_VERSION_PATCH;
+}
+
+static time_t getTranslationTime(Module &M) {
+  std::time_t Time = 0;
+  if (auto *Val = mdconst::extract_or_null(
+  M.getModuleFlag("zos_translation_time"))) {
+long SecondsSinceEpoch =  Val->getSExtValue();
+Time = static_cast(SecondsSinceEpoch);
+  }
+  return Time;
+}
+
+void SystemZAsmPrinter::emitIDRLSection(Module &M) {
+  OutStreamer->pushSection();
+  OutStreamer->switchSection(getObjFileLowering().getIDRLSection());
+  constexpr unsigned IDRLDataLength = 30;
+  std::time_t Time = getTranslationTime(M);
+
+  uint32_t ProductVersion = getProductVersion(M);
+  uint32_t ProductRelease = getProductRelease(M);
+
+  std::string ProductID = getProductID(M);
+
+  SmallString TempStr;
+  raw_svector_ostream O(TempStr);
+  O << formatv("{0}{1,0-2:d}{2,0-2:d}{3:%Y-%m-%d %H:%M:%S}",
+   ProductID.substr(0, 10).c_str(), ProductVersion, ProductRelease,
+   llvm::sys::toUtcTime(Time));
+  SmallString Data;
+  ConverterEBCDIC::convertToEBCDIC(TempStr, Data);
+
+  OutStreamer->emitInt8(0);   // Reserved.
+  OutStreamer->emitInt8(3);   // Format.
+  OutStreamer->emitInt16(IDRLDataLength); // Length.
+  OutStreamer->emitBytes(Data.str());

uweigand wrote:

One more question about this string - the Length field is hardcoded to 30.  
Does that mean that there are exactly 30 bytes supposed to always follow here?  
 I'm not sure this is guaranteed by the formatv above ...

Also, there doesn't seem to be any test that verifies the layout of this IDRL 
section, I think we definitely need one.

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


[llvm] [clang] [SystemZ][z/OS] This change adds support for the PPA2 section in zOS (PR #68926)

2023-11-22 Thread Ulrich Weigand via cfe-commits


@@ -976,6 +976,46 @@ void CodeGenModule::Release() {
   Context.getTypeSizeInChars(Context.getWideCharType()).getQuantity();
   getModule().addModuleFlag(llvm::Module::Error, "wchar_size", WCharWidth);
 
+  if (getTriple().isOSzOS()) {
+getModule().addModuleFlag(llvm::Module::Warning,
+  "zos_product_major_version",
+  uint32_t(CLANG_VERSION_MAJOR));
+getModule().addModuleFlag(llvm::Module::Warning,
+  "zos_product_minor_version",
+  uint32_t(CLANG_VERSION_MINOR));
+getModule().addModuleFlag(llvm::Module::Warning, "zos_product_patchlevel",
+  uint32_t(CLANG_VERSION_PATCHLEVEL));
+std::string ProductId;
+#ifdef CLANG_VENDOR
+ProductId = #CLANG_VENDOR;
+#else
+ProductId = "clang";
+#endif
+// Remove - from Product Id, which makes it consistent with legacy.
+std::size_t DashFound = ProductId.find("-");
+if (DashFound != std::string::npos)
+  ProductId.erase(ProductId.begin() + DashFound);

uweigand wrote:

Now that this code is moved here, it could only make a difference when 
compiling clang with a `CLANG_VENDOR` containing a dash.  If that is a problem 
for your use case, then why not simply build with the desired `CLANG_VENDOR` to 
begin with?  It's a bit unclear to me which general problem this code solves at 
this place now.

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


[llvm] [clang] [SystemZ][z/OS] This change adds support for the PPA2 section in zOS (PR #68926)

2023-11-22 Thread Ulrich Weigand via cfe-commits


@@ -1026,6 +1030,78 @@ void SystemZAsmPrinter::emitADASection() {
   OutStreamer->popSection();
 }
 
+static uint32_t getProductVersion(Module &M) {
+  if (auto *VersionVal = cast_or_null(
+  M.getModuleFlag("zos_product_major_version")))
+return cast(VersionVal->getValue())->getZExtValue();
+  return LLVM_VERSION_MAJOR;
+}
+
+static uint32_t getProductRelease(Module &M) {
+  if (auto *ReleaseVal = cast_or_null(
+  M.getModuleFlag("zos_product_minor_version")))
+return cast(ReleaseVal->getValue())->getZExtValue();
+  return LLVM_VERSION_MINOR;
+}
+
+static uint32_t getProductPatch(Module &M) {
+  if (auto *PatchVal = cast_or_null(
+  M.getModuleFlag("zos_product_patchlevel")))
+return cast(PatchVal->getValue())->getZExtValue();
+  return LLVM_VERSION_PATCH;
+}
+
+static time_t getTranslationTime(Module &M) {
+  std::time_t Time = 0;
+  if (auto *Val = cast_or_null(
+  M.getModuleFlag("zos_translation_time"))) {
+long SecondsSinceEpoch = 
cast(Val->getValue())->getSExtValue();
+Time = static_cast(SecondsSinceEpoch);
+  }
+  return Time;
+}
+
+void SystemZAsmPrinter::emitIDRLSection(Module &M) {
+  OutStreamer->pushSection();
+  OutStreamer->switchSection(getObjFileLowering().getIDRLSection());
+  constexpr unsigned IDRLDataLength = 30;
+  std::time_t Time = getTranslationTime(M);
+
+  uint32_t ProductVersion = getProductVersion(M);
+  uint32_t ProductRelease = getProductRelease(M);
+
+  std::string ProductID;
+  if (auto *MD = M.getModuleFlag("zos_product_id"))
+ProductID = cast(MD)->getString().str();
+
+  if (ProductID.empty()) {
+char ProductIDFormatted[11]; // 10 + null.
+snprintf(ProductIDFormatted, sizeof(ProductIDFormatted), "LLVM  %02d%02d",
+ ProductVersion, ProductRelease);
+ProductID = ProductIDFormatted;
+  }
+
+  // Remove - from Product Id, which makes it consistent with legacy.
+  // The binder expects alphanumeric characters only.
+  std::size_t DashFound = ProductID.find("-");
+  if (DashFound != std::string::npos)
+ProductID.erase(ProductID.begin() + DashFound);

uweigand wrote:

In the back-end, the string comes from a module flag in the IR - when providing 
their own IR file, a user could set that flag to anything, including a string 
with multiple dashes.  So if this is a problem for the rest of the toolchain, 
we need to be more careful in handling it.

If this is not actually a problem in the binder, then I guess removing that 
code here is fine.

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


[llvm] [clang] [SystemZ][z/OS] This change adds support for the PPA2 section in zOS (PR #68926)

2023-11-22 Thread Ulrich Weigand via cfe-commits


@@ -1026,6 +1030,71 @@ void SystemZAsmPrinter::emitADASection() {
   OutStreamer->popSection();
 }
 
+static uint32_t getProductVersion(Module &M) {
+  if (auto *VersionVal = mdconst::extract_or_null(
+  M.getModuleFlag("zos_product_major_version")))
+return VersionVal->getValue().getZExtValue();

uweigand wrote:

I don't think you need the separate `getValue()` here any more.

Also, you should be making the change to use `mdconst` not only in this one 
place, but in all places where you use `getModuleFlag` to retrieve an integer 
constant.

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


[clang] [llvm] [SystemZ][z/OS] This change adds support for the PPA2 section in zOS (PR #68926)

2023-11-22 Thread Ulrich Weigand via cfe-commits


@@ -1026,6 +1030,71 @@ void SystemZAsmPrinter::emitADASection() {
   OutStreamer->popSection();
 }
 
+static uint32_t getProductVersion(Module &M) {
+  if (auto *VersionVal = mdconst::extract_or_null(
+  M.getModuleFlag("zos_product_major_version")))
+return VersionVal->getValue().getZExtValue();
+  return LLVM_VERSION_MAJOR;
+}
+
+static uint32_t getProductRelease(Module &M) {
+  if (auto *ReleaseVal = cast_or_null(
+  M.getModuleFlag("zos_product_minor_version")))
+return cast(ReleaseVal->getValue())->getZExtValue();
+  return LLVM_VERSION_MINOR;
+}
+
+static uint32_t getProductPatch(Module &M) {
+  if (auto *PatchVal = cast_or_null(
+  M.getModuleFlag("zos_product_patchlevel")))
+return cast(PatchVal->getValue())->getZExtValue();
+  return LLVM_VERSION_PATCH;
+}
+
+static time_t getTranslationTime(Module &M) {
+  std::time_t Time = 0;
+  if (auto *Val = cast_or_null(
+  M.getModuleFlag("zos_translation_time"))) {
+long SecondsSinceEpoch = 
cast(Val->getValue())->getSExtValue();
+Time = static_cast(SecondsSinceEpoch);
+  }
+  return Time;
+}
+
+void SystemZAsmPrinter::emitIDRLSection(Module &M) {
+  OutStreamer->pushSection();
+  OutStreamer->switchSection(getObjFileLowering().getIDRLSection());
+  constexpr unsigned IDRLDataLength = 30;
+  std::time_t Time = getTranslationTime(M);
+
+  uint32_t ProductVersion = getProductVersion(M);
+  uint32_t ProductRelease = getProductRelease(M);
+
+  std::string ProductID;
+  if (auto *MD = M.getModuleFlag("zos_product_id"))
+ProductID = cast(MD)->getString().str();
+
+  if (ProductID.empty()) {
+char ProductIDFormatted[11]; // 10 + null.
+snprintf(ProductIDFormatted, sizeof(ProductIDFormatted), "LLVM");

uweigand wrote:

This `snprintf` call now looks superfluous - just set ProductID to "LLVM".

Also, I think this should all now go into a `getProductID` helper analogous to 
`getProductVersion` and the like.

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


[clang] [llvm] [SystemZ][z/OS] This change adds support for the PPA2 section in zOS (PR #68926)

2023-11-14 Thread Ulrich Weigand via cfe-commits

https://github.com/uweigand commented:

Please find a couple of additional comments inline, related to module flag 
processing.

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


[llvm] [clang] [SystemZ][z/OS] This change adds support for the PPA2 section in zOS (PR #68926)

2023-11-14 Thread Ulrich Weigand via cfe-commits


@@ -976,6 +976,40 @@ void CodeGenModule::Release() {
   Context.getTypeSizeInChars(Context.getWideCharType()).getQuantity();
   getModule().addModuleFlag(llvm::Module::Error, "wchar_size", WCharWidth);
 
+  if (getTriple().isOSzOS()) {
+getModule().addModuleFlag(llvm::Module::Warning,
+  "zos_product_major_version",
+  uint32_t(CLANG_VERSION_MAJOR));
+getModule().addModuleFlag(llvm::Module::Warning,
+  "zos_product_minor_version",
+  uint32_t(CLANG_VERSION_MINOR));
+getModule().addModuleFlag(llvm::Module::Warning, "zos_product_patchlevel",
+  uint32_t(CLANG_VERSION_PATCHLEVEL));
+std::string ProductId;
+#ifdef CLANG_VENDOR
+ProductId = #CLANG_VENDOR;
+#else
+ProductId = "clang";
+#endif
+getModule().addModuleFlag(llvm::Module::Error, "zos_product_id",
+  llvm::MDString::get(VMContext, ProductId));
+
+// Record the language because we need it for the PPA2.
+StringRef lang_str = languageToString(
+LangStandard::getLangStandardForKind(LangOpts.LangStd).Language);
+getModule().addModuleFlag(llvm::Module::Error, "zos_cu_language",
+  llvm::MDString::get(VMContext, lang_str));
+
+time_t TT = PreprocessorOpts.SourceDateEpoch
+? *PreprocessorOpts.SourceDateEpoch
+: std::time(nullptr);
+getModule().addModuleFlag(llvm::Module::Max, "zos_translation_time",
+  static_cast(TT));
+
+getModule().addModuleFlag(llvm::Module::Error, "zos_le_char_mode",
+  llvm::MDString::get(VMContext, "ascii"));

uweigand wrote:

Is "ascii" the correct default here?   In either case, please add a comment 
stating multiple modes will be supported in the future, so we understand why 
this code is here.

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


[llvm] [clang] [SystemZ][z/OS] This change adds support for the PPA2 section in zOS (PR #68926)

2023-11-14 Thread Ulrich Weigand via cfe-commits


@@ -1026,6 +1030,78 @@ void SystemZAsmPrinter::emitADASection() {
   OutStreamer->popSection();
 }
 
+static uint32_t getProductVersion(Module &M) {
+  if (auto *VersionVal = cast_or_null(
+  M.getModuleFlag("zos_product_major_version")))
+return cast(VersionVal->getValue())->getZExtValue();
+  return LLVM_VERSION_MAJOR;
+}
+
+static uint32_t getProductRelease(Module &M) {
+  if (auto *ReleaseVal = cast_or_null(
+  M.getModuleFlag("zos_product_minor_version")))
+return cast(ReleaseVal->getValue())->getZExtValue();
+  return LLVM_VERSION_MINOR;
+}
+
+static uint32_t getProductPatch(Module &M) {
+  if (auto *PatchVal = cast_or_null(
+  M.getModuleFlag("zos_product_patchlevel")))
+return cast(PatchVal->getValue())->getZExtValue();
+  return LLVM_VERSION_PATCH;
+}
+
+static time_t getTranslationTime(Module &M) {
+  std::time_t Time = 0;
+  if (auto *Val = cast_or_null(
+  M.getModuleFlag("zos_translation_time"))) {
+long SecondsSinceEpoch = 
cast(Val->getValue())->getSExtValue();
+Time = static_cast(SecondsSinceEpoch);
+  }
+  return Time;
+}
+
+void SystemZAsmPrinter::emitIDRLSection(Module &M) {
+  OutStreamer->pushSection();
+  OutStreamer->switchSection(getObjFileLowering().getIDRLSection());
+  constexpr unsigned IDRLDataLength = 30;
+  std::time_t Time = getTranslationTime(M);
+
+  uint32_t ProductVersion = getProductVersion(M);
+  uint32_t ProductRelease = getProductRelease(M);
+
+  std::string ProductID;
+  if (auto *MD = M.getModuleFlag("zos_product_id"))
+ProductID = cast(MD)->getString().str();
+
+  if (ProductID.empty()) {
+char ProductIDFormatted[11]; // 10 + null.
+snprintf(ProductIDFormatted, sizeof(ProductIDFormatted), "LLVM  %02d%02d",
+ ProductVersion, ProductRelease);
+ProductID = ProductIDFormatted;
+  }
+
+  // Remove - from Product Id, which makes it consistent with legacy.
+  // The binder expects alphanumeric characters only.
+  std::size_t DashFound = ProductID.find("-");
+  if (DashFound != std::string::npos)
+ProductID.erase(ProductID.begin() + DashFound);
+
+  SmallString TempStr;
+  raw_svector_ostream O(TempStr);
+  O << formatv("{0}{1,0-2:d}{2,0-2:d}{3:%Y-%m-%d %H:%M:%S}", ProductID.c_str(),
+   ProductVersion, ProductRelease, llvm::sys::toUtcTime(Time));

uweigand wrote:

Can this overflow?  In the default case above, you ensure the ProductID has 10 
bytes.  But in the case where the ID comes from the IR, its length can be 
anything, and is not checked here.

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


[llvm] [clang] [SystemZ][z/OS] This change adds support for the PPA2 section in zOS (PR #68926)

2023-11-14 Thread Ulrich Weigand via cfe-commits


@@ -1026,6 +1030,78 @@ void SystemZAsmPrinter::emitADASection() {
   OutStreamer->popSection();
 }
 
+static uint32_t getProductVersion(Module &M) {
+  if (auto *VersionVal = cast_or_null(
+  M.getModuleFlag("zos_product_major_version")))
+return cast(VersionVal->getValue())->getZExtValue();
+  return LLVM_VERSION_MAJOR;
+}
+
+static uint32_t getProductRelease(Module &M) {
+  if (auto *ReleaseVal = cast_or_null(
+  M.getModuleFlag("zos_product_minor_version")))
+return cast(ReleaseVal->getValue())->getZExtValue();
+  return LLVM_VERSION_MINOR;
+}
+
+static uint32_t getProductPatch(Module &M) {
+  if (auto *PatchVal = cast_or_null(
+  M.getModuleFlag("zos_product_patchlevel")))
+return cast(PatchVal->getValue())->getZExtValue();
+  return LLVM_VERSION_PATCH;
+}
+
+static time_t getTranslationTime(Module &M) {
+  std::time_t Time = 0;
+  if (auto *Val = cast_or_null(
+  M.getModuleFlag("zos_translation_time"))) {
+long SecondsSinceEpoch = 
cast(Val->getValue())->getSExtValue();
+Time = static_cast(SecondsSinceEpoch);
+  }
+  return Time;
+}
+
+void SystemZAsmPrinter::emitIDRLSection(Module &M) {
+  OutStreamer->pushSection();
+  OutStreamer->switchSection(getObjFileLowering().getIDRLSection());
+  constexpr unsigned IDRLDataLength = 30;
+  std::time_t Time = getTranslationTime(M);
+
+  uint32_t ProductVersion = getProductVersion(M);
+  uint32_t ProductRelease = getProductRelease(M);
+
+  std::string ProductID;
+  if (auto *MD = M.getModuleFlag("zos_product_id"))
+ProductID = cast(MD)->getString().str();
+
+  if (ProductID.empty()) {
+char ProductIDFormatted[11]; // 10 + null.
+snprintf(ProductIDFormatted, sizeof(ProductIDFormatted), "LLVM  %02d%02d",
+ ProductVersion, ProductRelease);

uweigand wrote:

In this case, `ProductVersion` and `ProductRelease` seem to be present twice, 
first as part of the ID and then again separately.  (This is different from 
when clang sets the ID as just "clang".)  Is this deliberate?

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


[llvm] [clang] [SystemZ][z/OS] This change adds support for the PPA2 section in zOS (PR #68926)

2023-11-14 Thread Ulrich Weigand via cfe-commits

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


[llvm] [clang] [SystemZ][z/OS] This change adds support for the PPA2 section in zOS (PR #68926)

2023-11-14 Thread Ulrich Weigand via cfe-commits


@@ -1026,6 +1030,78 @@ void SystemZAsmPrinter::emitADASection() {
   OutStreamer->popSection();
 }
 
+static uint32_t getProductVersion(Module &M) {
+  if (auto *VersionVal = cast_or_null(
+  M.getModuleFlag("zos_product_major_version")))
+return cast(VersionVal->getValue())->getZExtValue();
+  return LLVM_VERSION_MAJOR;
+}
+
+static uint32_t getProductRelease(Module &M) {
+  if (auto *ReleaseVal = cast_or_null(
+  M.getModuleFlag("zos_product_minor_version")))
+return cast(ReleaseVal->getValue())->getZExtValue();
+  return LLVM_VERSION_MINOR;
+}
+
+static uint32_t getProductPatch(Module &M) {
+  if (auto *PatchVal = cast_or_null(
+  M.getModuleFlag("zos_product_patchlevel")))
+return cast(PatchVal->getValue())->getZExtValue();
+  return LLVM_VERSION_PATCH;
+}
+
+static time_t getTranslationTime(Module &M) {
+  std::time_t Time = 0;
+  if (auto *Val = cast_or_null(
+  M.getModuleFlag("zos_translation_time"))) {
+long SecondsSinceEpoch = 
cast(Val->getValue())->getSExtValue();
+Time = static_cast(SecondsSinceEpoch);
+  }
+  return Time;
+}
+
+void SystemZAsmPrinter::emitIDRLSection(Module &M) {
+  OutStreamer->pushSection();
+  OutStreamer->switchSection(getObjFileLowering().getIDRLSection());
+  constexpr unsigned IDRLDataLength = 30;
+  std::time_t Time = getTranslationTime(M);
+
+  uint32_t ProductVersion = getProductVersion(M);
+  uint32_t ProductRelease = getProductRelease(M);
+
+  std::string ProductID;
+  if (auto *MD = M.getModuleFlag("zos_product_id"))
+ProductID = cast(MD)->getString().str();
+
+  if (ProductID.empty()) {
+char ProductIDFormatted[11]; // 10 + null.
+snprintf(ProductIDFormatted, sizeof(ProductIDFormatted), "LLVM  %02d%02d",
+ ProductVersion, ProductRelease);
+ProductID = ProductIDFormatted;
+  }
+
+  // Remove - from Product Id, which makes it consistent with legacy.
+  // The binder expects alphanumeric characters only.
+  std::size_t DashFound = ProductID.find("-");
+  if (DashFound != std::string::npos)
+ProductID.erase(ProductID.begin() + DashFound);

uweigand wrote:

Can there be multiple dashes, and if so, should they all be removed?   What 
about other disallowed characters?  At this point the ProductID could be 
user-provided in the IR, so shouldn't be careful here?

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


[llvm] [clang] [SystemZ][z/OS] This change adds support for the PPA2 section in zOS (PR #68926)

2023-11-14 Thread Ulrich Weigand via cfe-commits


@@ -1026,6 +1030,78 @@ void SystemZAsmPrinter::emitADASection() {
   OutStreamer->popSection();
 }
 
+static uint32_t getProductVersion(Module &M) {
+  if (auto *VersionVal = cast_or_null(
+  M.getModuleFlag("zos_product_major_version")))
+return cast(VersionVal->getValue())->getZExtValue();

uweigand wrote:

I think instead of these two casts, these days you're supposed to use the new 
`mdconst` interface, e.g. like
```
if (auto *VersionVal = mdconst::extract_or_null(
M.getModuleFlag("zos_product_major_version"))
```


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


[clang] [SystemZ] Do not run mbackchain-4.c test without SystemZ target (PR #71678)

2023-11-08 Thread Ulrich Weigand via cfe-commits

https://github.com/uweigand approved this pull request.

LGTM - sorry for missing that.

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


[llvm] [clang] [SystemZ] Add backchain target-feature (PR #71668)

2023-11-08 Thread Ulrich Weigand via cfe-commits

https://github.com/uweigand approved this pull request.

LGTM.   Thanks for taking care of this, Ilya!

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


[clang] [llvm] [SystemZ][z/OS] This change adds support for the PPA2 section in zOS (PR #68926)

2023-10-31 Thread Ulrich Weigand via cfe-commits


@@ -976,6 +976,40 @@ void CodeGenModule::Release() {
   Context.getTypeSizeInChars(Context.getWideCharType()).getQuantity();
   getModule().addModuleFlag(llvm::Module::Error, "wchar_size", WCharWidth);
 
+  if (getTriple().isOSzOS()) {
+getModule().addModuleFlag(llvm::Module::Warning, "Product Major Version",
+  uint32_t(CLANG_VERSION_MAJOR));
+getModule().addModuleFlag(llvm::Module::Warning, "Product Minor Version",
+  uint32_t(CLANG_VERSION_MINOR));
+getModule().addModuleFlag(llvm::Module::Warning, "Product Patchlevel",
+  uint32_t(CLANG_VERSION_PATCHLEVEL));

uweigand wrote:

I think I commented on that previously:  these flags are set only on z/OS, but 
have rather generic names.   If they're z/OS specific, I think they should have 
names in the "zos_..." name space like the others.

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


[llvm] [clang] [SystemZ][z/OS] This change adds support for the PPA2 section in zOS (PR #68926)

2023-10-31 Thread Ulrich Weigand via cfe-commits


@@ -1765,7 +1765,7 @@ void Clang::RenderTargetOptions(const llvm::Triple 
&EffectiveTriple,
 break;
 
   case llvm::Triple::systemz:
-AddSystemZTargetArgs(Args, CmdArgs);
+AddSystemZTargetArgs(EffectiveTriple, Args, CmdArgs);

uweigand wrote:

This (and the related) changes are no longer needed now.

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


[clang] [llvm] [SystemZ][z/OS] This change adds support for the PPA2 section in zOS (PR #68926)

2023-10-31 Thread Ulrich Weigand via cfe-commits


@@ -976,6 +976,40 @@ void CodeGenModule::Release() {
   Context.getTypeSizeInChars(Context.getWideCharType()).getQuantity();
   getModule().addModuleFlag(llvm::Module::Error, "wchar_size", WCharWidth);
 
+  if (getTriple().isOSzOS()) {
+getModule().addModuleFlag(llvm::Module::Warning, "Product Major Version",
+  uint32_t(CLANG_VERSION_MAJOR));
+getModule().addModuleFlag(llvm::Module::Warning, "Product Minor Version",
+  uint32_t(CLANG_VERSION_MINOR));
+getModule().addModuleFlag(llvm::Module::Warning, "Product Patchlevel",
+  uint32_t(CLANG_VERSION_PATCHLEVEL));
+
+// Record the language because we need it for the PPA2.
+StringRef lang_str = languageToString(
+LangStandard::getLangStandardForKind(LangOpts.LangStd).Language);
+getModule().addModuleFlag(llvm::Module::Error, "zos_cu_language",
+  llvm::MDString::get(VMContext, lang_str));
+
+std::string ProductId;
+#ifdef CLANG_VENDOR
+ProductId = #CLANG_VENDOR;
+#else
+ProductId = "clang";
+#endif
+
+getModule().addModuleFlag(llvm::Module::Error, "Product Id",
+  llvm::MDString::get(VMContext, ProductId));

uweigand wrote:

Same comment as above about the name space.  Also, please move this up next to 
the other product-related flags.

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


[clang] [llvm] [SystemZ][z/OS] This change adds support for the PPA2 section in zOS (PR #68926)

2023-10-31 Thread Ulrich Weigand via cfe-commits


@@ -90,6 +90,7 @@ LANGOPT(C23   , 1, 0, "C23")
 LANGOPT(MSVCCompat, 1, 0, "Microsoft Visual C++ full compatibility 
mode")
 LANGOPT(Kernel, 1, 0, "Kernel mode")
 LANGOPT(MicrosoftExt  , 1, 0, "Microsoft C++ extensions")
+LANGOPT(ASCIICharMode , 1, 1, "z/OS Language Environment Character mode")

uweigand wrote:

This doesn't appear to do anything except for setting the PPA flag.   Is this 
correct?  If the implementation is simply incomplete / not present yet, I don't 
think we should add this flag now - rather, we should have the PPA flag reflect 
the default and update this once full support for ASCII mode is merged.

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


  1   2   >