[clang] [Serialization] Read the initializer for interesting static variables before consuming it (PR #92353)
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)
@@ -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)
@@ -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 , 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 ) const override { +if (!getCXXABI().classifyReturnType(FI)) + FI.getReturnInfo() = + classifyReturnType(FI.getReturnType(), FI.getCallingConvention()); + +unsigned NumRequiredArgs = FI.getNumRequiredArgs(); +unsigned ArgNo = 0; + +for (auto : FI.arguments()) { + bool IsNamedArg = ArgNo < NumRequiredArgs; + I.info = + classifyArgumentType(I.type, IsNamedArg, FI.getCallingConvention()); + ++ArgNo; +} + } + + Address EmitVAArg(CodeGenFunction , Address VAListAddr, +QualType Ty) const override; +}; + +class ZOSXPLinkTargetCodeGenInfo : public TargetCodeGenInfo { +public: + ZOSXPLinkTargetCodeGenInfo(CodeGenTypes , 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 : 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
[clang] [SystemZ][z/OS] Implement z/OS XPLINK ABI (PR #91384)
@@ -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 , 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 ) const override { +if (!getCXXABI().classifyReturnType(FI)) + FI.getReturnInfo() = + classifyReturnType(FI.getReturnType(), FI.getCallingConvention()); + +unsigned NumRequiredArgs = FI.getNumRequiredArgs(); +unsigned ArgNo = 0; + +for (auto : FI.arguments()) { + bool IsNamedArg = ArgNo < NumRequiredArgs; + I.info = + classifyArgumentType(I.type, IsNamedArg, FI.getCallingConvention()); + ++ArgNo; +} + } + + Address EmitVAArg(CodeGenFunction , Address VAListAddr, +QualType Ty) const override; +}; + +class ZOSXPLinkTargetCodeGenInfo : public TargetCodeGenInfo { +public: + ZOSXPLinkTargetCodeGenInfo(CodeGenTypes , 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 : 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
[clang] [SystemZ][z/OS] Implement z/OS XPLINK ABI (PR #91384)
@@ -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 , 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 ) const override { +if (!getCXXABI().classifyReturnType(FI)) + FI.getReturnInfo() = + classifyReturnType(FI.getReturnType(), FI.getCallingConvention()); + +unsigned NumRequiredArgs = FI.getNumRequiredArgs(); +unsigned ArgNo = 0; + +for (auto : FI.arguments()) { + bool IsNamedArg = ArgNo < NumRequiredArgs; + I.info = + classifyArgumentType(I.type, IsNamedArg, FI.getCallingConvention()); + ++ArgNo; +} + } + + Address EmitVAArg(CodeGenFunction , Address VAListAddr, +QualType Ty) const override; +}; + +class ZOSXPLinkTargetCodeGenInfo : public TargetCodeGenInfo { +public: + ZOSXPLinkTargetCodeGenInfo(CodeGenTypes , 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 : 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
[clang] [SystemZ][z/OS] Implement z/OS XPLINK ABI (PR #91384)
@@ -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 , 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 ) const override { +if (!getCXXABI().classifyReturnType(FI)) + FI.getReturnInfo() = + classifyReturnType(FI.getReturnType(), FI.getCallingConvention()); + +unsigned NumRequiredArgs = FI.getNumRequiredArgs(); +unsigned ArgNo = 0; + +for (auto : FI.arguments()) { + bool IsNamedArg = ArgNo < NumRequiredArgs; + I.info = + classifyArgumentType(I.type, IsNamedArg, FI.getCallingConvention()); + ++ArgNo; +} + } + + Address EmitVAArg(CodeGenFunction , Address VAListAddr, +QualType Ty) const override; +}; + +class ZOSXPLinkTargetCodeGenInfo : public TargetCodeGenInfo { +public: + ZOSXPLinkTargetCodeGenInfo(CodeGenTypes , 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 : 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
[clang] [SystemZ][z/OS] Implement z/OS XPLINK ABI (PR #91384)
@@ -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 , 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 ) const override { +if (!getCXXABI().classifyReturnType(FI)) + FI.getReturnInfo() = + classifyReturnType(FI.getReturnType(), FI.getCallingConvention()); + +unsigned NumRequiredArgs = FI.getNumRequiredArgs(); +unsigned ArgNo = 0; + +for (auto : FI.arguments()) { + bool IsNamedArg = ArgNo < NumRequiredArgs; + I.info = + classifyArgumentType(I.type, IsNamedArg, FI.getCallingConvention()); + ++ArgNo; +} + } + + Address EmitVAArg(CodeGenFunction , Address VAListAddr, +QualType Ty) const override; +}; + +class ZOSXPLinkTargetCodeGenInfo : public TargetCodeGenInfo { +public: + ZOSXPLinkTargetCodeGenInfo(CodeGenTypes , 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 : 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
[clang] [SystemZ][z/OS] Implement z/OS XPLINK ABI (PR #91384)
@@ -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 , 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 ) const override { +if (!getCXXABI().classifyReturnType(FI)) + FI.getReturnInfo() = + classifyReturnType(FI.getReturnType(), FI.getCallingConvention()); + +unsigned NumRequiredArgs = FI.getNumRequiredArgs(); +unsigned ArgNo = 0; + +for (auto : FI.arguments()) { + bool IsNamedArg = ArgNo < NumRequiredArgs; + I.info = + classifyArgumentType(I.type, IsNamedArg, FI.getCallingConvention()); + ++ArgNo; +} + } + + Address EmitVAArg(CodeGenFunction , Address VAListAddr, +QualType Ty) const override; +}; + +class ZOSXPLinkTargetCodeGenInfo : public TargetCodeGenInfo { +public: + ZOSXPLinkTargetCodeGenInfo(CodeGenTypes , 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 : 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
[clang] [SystemZ][z/OS] Implement z/OS XPLINK ABI (PR #91384)
@@ -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)
@@ -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 , 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 ) const override { +if (!getCXXABI().classifyReturnType(FI)) + FI.getReturnInfo() = + classifyReturnType(FI.getReturnType(), FI.getCallingConvention()); + +unsigned NumRequiredArgs = FI.getNumRequiredArgs(); +unsigned ArgNo = 0; + +for (auto : FI.arguments()) { + bool IsNamedArg = ArgNo < NumRequiredArgs; + I.info = + classifyArgumentType(I.type, IsNamedArg, FI.getCallingConvention()); + ++ArgNo; +} + } + + Address EmitVAArg(CodeGenFunction , Address VAListAddr, +QualType Ty) const override; +}; + +class ZOSXPLinkTargetCodeGenInfo : public TargetCodeGenInfo { +public: + ZOSXPLinkTargetCodeGenInfo(CodeGenTypes , 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 : 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
[clang] [SystemZ][z/OS] Implement z/OS XPLINK ABI (PR #91384)
@@ -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 , 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 ) const override { +if (!getCXXABI().classifyReturnType(FI)) + FI.getReturnInfo() = classifyReturnType(FI.getReturnType()); + +unsigned NumRequiredArgs = FI.getNumRequiredArgs(); +unsigned ArgNo = 0; + +for (auto : FI.arguments()) { + bool IsNamedArg = ArgNo < NumRequiredArgs; + I.info = classifyArgumentType(I.type, IsNamedArg); + ++ArgNo; +} + } + + Address EmitVAArg(CodeGenFunction , Address VAListAddr, +QualType Ty) const override; +}; + +class ZOSXPLinkTargetCodeGenInfo : public TargetCodeGenInfo { +public: + ZOSXPLinkTargetCodeGenInfo(CodeGenTypes , 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 : 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
[clang] [SystemZ][z/OS] Implement z/OS XPLINK ABI (PR #91384)
@@ -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 , 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 ) const override { +if (!getCXXABI().classifyReturnType(FI)) + FI.getReturnInfo() = classifyReturnType(FI.getReturnType()); + +unsigned NumRequiredArgs = FI.getNumRequiredArgs(); +unsigned ArgNo = 0; + +for (auto : FI.arguments()) { + bool IsNamedArg = ArgNo < NumRequiredArgs; + I.info = classifyArgumentType(I.type, IsNamedArg); + ++ArgNo; +} + } + + Address EmitVAArg(CodeGenFunction , Address VAListAddr, +QualType Ty) const override; +}; + +class ZOSXPLinkTargetCodeGenInfo : public TargetCodeGenInfo { +public: + ZOSXPLinkTargetCodeGenInfo(CodeGenTypes , 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 : 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 elements with
[clang] [SystemZ][z/OS] Implement z/OS XPLINK ABI (PR #91384)
@@ -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 , 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 ) const override { +if (!getCXXABI().classifyReturnType(FI)) + FI.getReturnInfo() = classifyReturnType(FI.getReturnType()); + +unsigned NumRequiredArgs = FI.getNumRequiredArgs(); +unsigned ArgNo = 0; + +for (auto : FI.arguments()) { + bool IsNamedArg = ArgNo < NumRequiredArgs; + I.info = classifyArgumentType(I.type, IsNamedArg); + ++ArgNo; +} + } + + Address EmitVAArg(CodeGenFunction , Address VAListAddr, +QualType Ty) const override; +}; + +class ZOSXPLinkTargetCodeGenInfo : public TargetCodeGenInfo { +public: + ZOSXPLinkTargetCodeGenInfo(CodeGenTypes , 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 : 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 elements with
[clang] [SystemZ][z/OS] Implement z/OS XPLINK ABI (PR #91384)
@@ -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 , 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 ) const override { +if (!getCXXABI().classifyReturnType(FI)) + FI.getReturnInfo() = classifyReturnType(FI.getReturnType()); + +unsigned NumRequiredArgs = FI.getNumRequiredArgs(); +unsigned ArgNo = 0; + +for (auto : FI.arguments()) { + bool IsNamedArg = ArgNo < NumRequiredArgs; + I.info = classifyArgumentType(I.type, IsNamedArg); + ++ArgNo; +} + } + + Address EmitVAArg(CodeGenFunction , Address VAListAddr, +QualType Ty) const override; +}; + +class ZOSXPLinkTargetCodeGenInfo : public TargetCodeGenInfo { +public: + ZOSXPLinkTargetCodeGenInfo(CodeGenTypes , 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 : 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 elements with
[clang] [SystemZ][z/OS] Implement z/OS XPLINK ABI (PR #91384)
@@ -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)
@@ -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 , 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 ) const override { +if (!getCXXABI().classifyReturnType(FI)) + FI.getReturnInfo() = classifyReturnType(FI.getReturnType()); + +unsigned NumRequiredArgs = FI.getNumRequiredArgs(); +unsigned ArgNo = 0; + +for (auto : FI.arguments()) { + bool IsNamedArg = ArgNo < NumRequiredArgs; + I.info = classifyArgumentType(I.type, IsNamedArg); + ++ArgNo; +} + } + + Address EmitVAArg(CodeGenFunction , Address VAListAddr, +QualType Ty) const override; +}; + +class ZOSXPLinkTargetCodeGenInfo : public TargetCodeGenInfo { +public: + ZOSXPLinkTargetCodeGenInfo(CodeGenTypes , 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 : 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 elements with
[clang] [SystemZ][z/OS] Implement z/OS XPLINK ABI (PR #91384)
@@ -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 , 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 ) const override { +if (!getCXXABI().classifyReturnType(FI)) + FI.getReturnInfo() = classifyReturnType(FI.getReturnType()); + +unsigned NumRequiredArgs = FI.getNumRequiredArgs(); +unsigned ArgNo = 0; + +for (auto : FI.arguments()) { + bool IsNamedArg = ArgNo < NumRequiredArgs; + I.info = classifyArgumentType(I.type, IsNamedArg); + ++ArgNo; +} + } + + Address EmitVAArg(CodeGenFunction , Address VAListAddr, +QualType Ty) const override; +}; + +class ZOSXPLinkTargetCodeGenInfo : public TargetCodeGenInfo { +public: + ZOSXPLinkTargetCodeGenInfo(CodeGenTypes , 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 : 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
[clang] [SystemZ][z/OS] Implement z/OS XPLINK ABI (PR #91384)
@@ -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 , 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 ) const override { +if (!getCXXABI().classifyReturnType(FI)) + FI.getReturnInfo() = classifyReturnType(FI.getReturnType()); + +unsigned NumRequiredArgs = FI.getNumRequiredArgs(); +unsigned ArgNo = 0; + +for (auto : FI.arguments()) { + bool IsNamedArg = ArgNo < NumRequiredArgs; + I.info = classifyArgumentType(I.type, IsNamedArg); + ++ArgNo; +} + } + + Address EmitVAArg(CodeGenFunction , Address VAListAddr, +QualType Ty) const override; +}; + +class ZOSXPLinkTargetCodeGenInfo : public TargetCodeGenInfo { +public: + ZOSXPLinkTargetCodeGenInfo(CodeGenTypes , 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)
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)
@@ -1191,6 +1191,10 @@ void DeclSpec::Finish(Sema , const PrintingPolicy ) { // 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)
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 , const PrintingPolicy ) { !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)
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 , const PrintingPolicy ) { // 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 __vector
[clang] [C++17] Support __GCC_[CON|DE]STRUCTIVE_SIZE (PR #89446)
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)
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)
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)
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 , ArgList , 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 ---
[clang] 70677c8 - Revert "[libomptarget] Build plugins-nextgen for SystemZ (#83978)"
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 , ArgList , 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_TARGETS
[clang] [llvm] [openmp] [libomptarget] Build plugins-nextgen for SystemZ (PR #83978)
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)
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 , ArgList , 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
[clang] [llvm] [openmp] [libomptarget] Build plugins-nextgen for SystemZ (PR #83978)
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 ---
[libcxx] [mlir] [llvm] [compiler-rt] [clang] [asan] Enable StackSafetyAnalysis by default (PR #77210)
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)
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)
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)
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)
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)
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)
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)
@@ -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
[clang] [llvm] [SystemZ] Support i128 as legal type in VRs (PR #74625)
@@ -6481,6 +6737,71 @@ SDValue SystemZTargetLowering::combineLOAD( SDNode *N, DAGCombinerInfo ) const { SelectionDAG = 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)
@@ -2918,16 +3049,17 @@ static Comparison getCmp(SelectionDAG , 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)
@@ -2772,6 +2837,27 @@ static unsigned getTestUnderMaskCond(unsigned BitSize, unsigned CCMask, // Update the arguments with the TM version if so. static void adjustForTestUnderMask(SelectionDAG , const SDLoc , Comparison ) { + // 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)
@@ -1466,7 +1509,15 @@ static SDValue convertValVTToLocVT(SelectionDAG , const SDLoc , static SDValue lowerI128ToGR128(SelectionDAG , 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)
@@ -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)
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)
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
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,
[clang] dca432c - [SystemZ] Fix naming of vlrlr/vstrlr builtins
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
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
[llvm] [clang] [clang, SystemZ] Pass HasDef flag to getMinGlobalAlign(). (PR #73511)
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)
@@ -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)
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)
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)
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)
@@ -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, _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, _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, _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, _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)
@@ -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, _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, _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)
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)
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)
@@ -1026,6 +1030,72 @@ void SystemZAsmPrinter::emitADASection() { OutStreamer->popSection(); } +static std::string getProductID(Module ) { + 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 ) { + 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 ) { + 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 ) { + if (auto *PatchVal = mdconst::extract_or_null( + M.getModuleFlag("zos_product_patchlevel"))) +return PatchVal->getZExtValue(); + return LLVM_VERSION_PATCH; +} + +static time_t getTranslationTime(Module ) { + 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 ) { + 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)
@@ -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)
@@ -1026,6 +1030,78 @@ void SystemZAsmPrinter::emitADASection() { OutStreamer->popSection(); } +static uint32_t getProductVersion(Module ) { + 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 ) { + 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 ) { + 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 ) { + 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 ) { + 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)
@@ -1026,6 +1030,71 @@ void SystemZAsmPrinter::emitADASection() { OutStreamer->popSection(); } +static uint32_t getProductVersion(Module ) { + 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)
@@ -1026,6 +1030,71 @@ void SystemZAsmPrinter::emitADASection() { OutStreamer->popSection(); } +static uint32_t getProductVersion(Module ) { + 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 ) { + 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 ) { + 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 ) { + 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 ) { + 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)
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)
@@ -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)
@@ -1026,6 +1030,78 @@ void SystemZAsmPrinter::emitADASection() { OutStreamer->popSection(); } +static uint32_t getProductVersion(Module ) { + 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 ) { + 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 ) { + 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 ) { + 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 ) { + 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)
@@ -1026,6 +1030,78 @@ void SystemZAsmPrinter::emitADASection() { OutStreamer->popSection(); } +static uint32_t getProductVersion(Module ) { + 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 ) { + 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 ) { + 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 ) { + 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 ) { + 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)
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)
@@ -1026,6 +1030,78 @@ void SystemZAsmPrinter::emitADASection() { OutStreamer->popSection(); } +static uint32_t getProductVersion(Module ) { + 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 ) { + 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 ) { + 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 ) { + 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 ) { + 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)
@@ -1026,6 +1030,78 @@ void SystemZAsmPrinter::emitADASection() { OutStreamer->popSection(); } +static uint32_t getProductVersion(Module ) { + 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)
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)
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)
@@ -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)
@@ -1765,7 +1765,7 @@ void Clang::RenderTargetOptions(const llvm::Triple , 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)
@@ -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)
@@ -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
[llvm] [clang] [SystemZ][z/OS] This change adds support for the PPA2 section in zOS (PR #68926)
@@ -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)); + +getModule().addModuleFlag(llvm::Module::Error, "TranslationTime", uweigand wrote: I don't think `Error` is the correct setting for this. That would prevent LTO unless modules were built at the exact same time. Rather, I think this should be `Max` 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
[clang] [llvm] [SystemZ][z/OS] This change adds support for the PPA2 section in zOS (PR #68926)
https://github.com/uweigand requested changes to this pull request. 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)
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
[clang] [clang] Language to String function (PR #69487)
uweigand wrote: This is intended to be used by the z/OS target, see the patch here: https://github.com/llvm/llvm-project/pull/68926 I asked Yusra to pull this part out into a separate PR. https://github.com/llvm/llvm-project/pull/69487 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [SystemZ][z/OS] This change adds support for the PPA2 section in zOS (PR #68926)
@@ -1296,6 +1372,124 @@ void SystemZAsmPrinter::emitPPA1(MCSymbol *FnEndSym) { 4); } +void SystemZAsmPrinter::emitStartOfAsmFile(Module ) { + if (TM.getTargetTriple().isOSzOS()) +emitPPA2(M); + AsmPrinter::emitStartOfAsmFile(M); +} + +void SystemZAsmPrinter::emitPPA2(Module ) { + OutStreamer->pushSection(); + OutStreamer->switchSection(getObjFileLowering().getPPA2Section()); + MCContext = OutStreamer->getContext(); + // Make CELQSTRT symbol. + const char *StartSymbolName = "CELQSTRT"; + MCSymbol *CELQSTRT = OutContext.getOrCreateSymbol(StartSymbolName); + + // Create symbol and assign to class field for use in PPA1. + PPA2Sym = OutContext.createTempSymbol("PPA2", false); + MCSymbol *DateVersionSym = OutContext.createTempSymbol("DVS", false); + + std::time_t Time = TranslationTime; + SmallString<15> CompilationTime; // 14 + null + raw_svector_ostream O(CompilationTime); + O << formatv("{0:%Y%m%d%H%M%S}", llvm::sys::toUtcTime(Time)); + + uint32_t ProductVersion = getProductVersion(M), + ProductRelease = getProductRelease(M), + ProductPatch = getProductPatch(M); + + SmallString<7> Version; // 6 + null + raw_svector_ostream ostr(Version); + ostr << formatv("{0,0-2:d}{1,0-2:d}{2,0-2:d}", ProductVersion, ProductRelease, + ProductPatch); + + // Drop 0 during conversion. + SmallString CompilationTimeStr; + SmallString VersionStr; + + ConverterEBCDIC::convertToEBCDIC(CompilationTime, CompilationTimeStr); + ConverterEBCDIC::convertToEBCDIC(Version, VersionStr); + + enum class PPA2MemberId : uint8_t { +// See z/OS Language Environment Vendor Interfaces v2r5, p.23, for +// complete list. Only the C runtime is supported by this backend. +LE_C_Runtime = 3, + }; + enum class PPA2MemberSubId : uint8_t { +// List of languages using the LE C runtime implementation. +C = 0x00, +CXX = 0x01, +Swift = 0x03, +Go = 0x60, +LLVMBasedLang = 0xe7, + }; + // PPA2 Flags + enum class PPA2Flags : uint8_t { +CompileForBinaryFloatingPoint = 0x80, +CompiledWithXPLink = 0x01, +CompiledUnitASCII = 0x04, +HasServiceInfo = 0x20, + }; + + PPA2MemberSubId MemberSubId = PPA2MemberSubId::LLVMBasedLang; + if (auto *MD = M.getModuleFlag("zos_cu_language")) { +StringRef Language = cast(MD)->getString(); +MemberSubId = StringSwitch(Language) + .Case("C", PPA2MemberSubId::C) + .Case("CXX", PPA2MemberSubId::CXX) + .Case("Swift", PPA2MemberSubId::Swift) + .Case("Go", PPA2MemberSubId::Go) + .Default(PPA2MemberSubId::LLVMBasedLang); + } + + // Emit PPA2 section. + OutStreamer->emitLabel(PPA2Sym); + OutStreamer->emitInt8(static_cast(PPA2MemberId::LE_C_Runtime)); + OutStreamer->emitInt8(static_cast(MemberSubId)); + OutStreamer->emitInt8(0x22); // Member defined, c370_plist+c370_env + OutStreamer->emitInt8(0x04); // Control level 4 (XPLink) + OutStreamer->emitAbsoluteSymbolDiff(CELQSTRT, PPA2Sym, 4); + OutStreamer->emitInt32(0x); + OutStreamer->emitAbsoluteSymbolDiff(DateVersionSym, PPA2Sym, 4); + OutStreamer->emitInt32( + 0x); // Offset to main entry point, always 0 (so says TR). + uint8_t Flgs = static_cast(PPA2Flags::CompileForBinaryFloatingPoint); + Flgs |= static_cast(PPA2Flags::CompiledWithXPLink); + + if (auto *MD = M.getModuleFlag("zos_le_char_mode")) { uweigand wrote: This is also nowhere set in clang right now. Should it be? If it isn't set, is EBCDIC the right default? 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][z/OS] This change adds support for the PPA2 section in zOS (PR #68926)
@@ -976,6 +976,24 @@ void CodeGenModule::Release() { Context.getTypeSizeInChars(Context.getWideCharType()).getQuantity(); getModule().addModuleFlag(llvm::Module::Error, "wchar_size", WCharWidth); + if (getTriple().isOSzOS()) { +int32_t ProductVersion, ProductRelease, ProductPatch; +ProductVersion = LLVM_VERSION_MAJOR, ProductRelease = LLVM_VERSION_MINOR, +ProductPatch = LLVM_VERSION_PATCH; uweigand wrote: Do we need extra variables for this? 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][z/OS] This change adds support for the PPA2 section in zOS (PR #68926)
@@ -1026,6 +1036,68 @@ void SystemZAsmPrinter::emitADASection() { OutStreamer->popSection(); } +static uint32_t getProductVersion(Module ) { + if (auto *VersionVal = cast_or_null( + M.getModuleFlag("Product Major Version"))) +return cast(VersionVal->getValue())->getZExtValue(); + return LLVM_VERSION_MAJOR; +} + +static uint32_t getProductRelease(Module ) { + if (auto *ReleaseVal = cast_or_null( + M.getModuleFlag("Product Minor Version"))) +return cast(ReleaseVal->getValue())->getZExtValue(); + return LLVM_VERSION_MINOR; +} + +static uint32_t getProductPatch(Module ) { + if (auto *PatchVal = cast_or_null( + M.getModuleFlag("Product Patchlevel"))) +return cast(PatchVal->getValue())->getZExtValue(); + return LLVM_VERSION_PATCH; +} + +void SystemZAsmPrinter::emitIDRLSection(Module ) { + OutStreamer->pushSection(); + OutStreamer->switchSection(getObjFileLowering().getIDRLSection()); + constexpr unsigned IDRLDataLength = 30; + std::time_t Time = TranslationTime; + + uint32_t ProductVersion = getProductVersion(M); + uint32_t ProductRelease = getProductRelease(M); + + std::string ProductID; + if (auto *MD = M.getModuleFlag("Product Id")) uweigand wrote: This is never set in clang by your patch. Should it be? 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][z/OS] This change adds support for the PPA2 section in zOS (PR #68926)
@@ -10,9 +10,49 @@ #include "clang/Config/config.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/FormatVariadic.h" #include "llvm/TargetParser/Triple.h" using namespace clang; +const char *clang::languageToString(Language L) { + // I would like to make this function and the definition of Language + // in the .h file simply expand the contents of a .def file. + // However, in the .h the members of the enum have doxygen annotations + // and/or comments which would be lost. uweigand wrote: I'm not sure I have a good solution for this, but I'd like to see comments on this from the wider clang community. Maybe it would make sense to submit just this function as a separate PR. 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][z/OS] This change adds support for the PPA2 section in zOS (PR #68926)
@@ -2267,6 +2268,14 @@ void Clang::AddSystemZTargetArgs(const ArgList , CmdArgs.push_back("-mfloat-abi"); CmdArgs.push_back("soft"); } + + if (Triple.isOSzOS()) { +CmdArgs.push_back("-mllvm"); +CmdArgs.push_back( +Args.MakeArgString(llvm::Twine("-translation-time=") + .concat(llvm::Twine(std::time(nullptr))) + .str())); + } uweigand wrote: Is there a good reason for this to be a command-line option, or could this also be a module flag just like the others added above? Seems odd to use two different mechanisms 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
[clang] [SystemZ][z/OS] This change adds support for the PPA2 section in zOS (PR #68926)
@@ -976,6 +976,24 @@ void CodeGenModule::Release() { Context.getTypeSizeInChars(Context.getWideCharType()).getQuantity(); getModule().addModuleFlag(llvm::Module::Error, "wchar_size", WCharWidth); + if (getTriple().isOSzOS()) { +int32_t ProductVersion, ProductRelease, ProductPatch; +ProductVersion = LLVM_VERSION_MAJOR, ProductRelease = LLVM_VERSION_MINOR, +ProductPatch = LLVM_VERSION_PATCH; +getModule().addModuleFlag(llvm::Module::Warning, "Product Major Version", + ProductVersion); +getModule().addModuleFlag(llvm::Module::Warning, "Product Minor Version", + ProductRelease); +getModule().addModuleFlag(llvm::Module::Warning, "Product Patchlevel", + ProductPatch); uweigand wrote: These are set only on z/OS, but the flag names appear generic. If they're (set and) used only on z/OS, shouldn't they carry a z/OS specific name like below? 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][z/OS] This change adds support for the PPA2 section in zOS (PR #68926)
@@ -10,7 +10,7 @@ // .byte (i.e., the one for the 3) would, it seems, also match // the .byte line below for the 34. -// RUN: %clang_cc1 --target=s390x-ibm-zos -xc -S -o - %s | FileCheck %s --check-prefix CHECK-C +// RUN: %clang --target=s390x-ibm-zos -xc -S -o - %s | FileCheck %s --check-prefix CHECK-C uweigand wrote: No, you should be using `%clang_cc1` here. You'll just need to fix the arguments as appropriate for `%clang_cc1` - look at what the other tests in this directory are doing. 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] [clang][CodeGen] Use byval for SystemZ indirect arguments (PR #66404)
uweigand wrote: This looks correct to me. I'm just wondering if there's any unexpected change of generated code due to this - did you do a comparison before/after of some larger code bases? https://github.com/llvm/llvm-project/pull/66404 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [SystemZ][z/OS] This change adds support for the PPA2 section in zOS (PR #65407)
uweigand wrote: SystemZ back-end changes LGTM.Additional reviews as to the Clang and time support changes would be appreciated. https://github.com/llvm/llvm-project/pull/65407 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [SystemZ][z/OS] This change adds support for the PPA2 section in zOS (PR #65407)
https://github.com/uweigand approved this pull request. LGTM https://github.com/llvm/llvm-project/pull/65407 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[libunwind] 24ec521 - [libunwind][SystemZ] Use process_vm_readv to avoid potential segfaults
Author: Ulrich Weigand Date: 2022-07-18T16:54:48+02:00 New Revision: 24ec521cd7bb51447f4ab03460d91c57378d49f7 URL: https://github.com/llvm/llvm-project/commit/24ec521cd7bb51447f4ab03460d91c57378d49f7 DIFF: https://github.com/llvm/llvm-project/commit/24ec521cd7bb51447f4ab03460d91c57378d49f7.diff LOG: [libunwind][SystemZ] Use process_vm_readv to avoid potential segfaults Fix potential crashes during unwind when checking for signal frames and the current PC is invalid. The same bug was fixed for aarch64 in https://reviews.llvm.org/D126343. Reviewed by: MaskRay Differential Revision: https://reviews.llvm.org/D129856 Added: Modified: libunwind/src/UnwindCursor.hpp libunwind/test/bad_unwind_info.pass.cpp Removed: diff --git a/libunwind/src/UnwindCursor.hpp b/libunwind/src/UnwindCursor.hpp index e363f9e59c9a..b8bd9bc59010 100644 --- a/libunwind/src/UnwindCursor.hpp +++ b/libunwind/src/UnwindCursor.hpp @@ -2695,8 +2695,14 @@ bool UnwindCursor::setInfoForSigReturn(Registers_s390x &) { // own restorer function, though, or user-mode QEMU might write a trampoline // onto the stack. const pint_t pc = static_cast(this->getReg(UNW_REG_IP)); - const uint16_t inst = _addressSpace.get16(pc); - if (inst == 0x0a77 || inst == 0x0aad) { + // The PC might contain an invalid address if the unwind info is bad, so + // directly accessing it could cause a segfault. Use process_vm_readv to + // read the memory safely instead. + uint16_t inst; + struct iovec local_iov = {, sizeof inst}; + struct iovec remote_iov = {reinterpret_cast(pc), sizeof inst}; + long bytesRead = process_vm_readv(getpid(), _iov, 1, _iov, 1, 0); + if (bytesRead == sizeof inst && (inst == 0x0a77 || inst == 0x0aad)) { _info = {}; _info.start_ip = pc; _info.end_ip = pc + 2; diff --git a/libunwind/test/bad_unwind_info.pass.cpp b/libunwind/test/bad_unwind_info.pass.cpp index 97427ea92273..06017d17ab57 100644 --- a/libunwind/test/bad_unwind_info.pass.cpp +++ b/libunwind/test/bad_unwind_info.pass.cpp @@ -10,7 +10,7 @@ // Ensure that libunwind doesn't crash on invalid info; the Linux aarch64 // sigreturn frame check would previously attempt to access invalid memory in // this scenario. -// REQUIRES: linux && (target={{aarch64-.+}} || target={{x86_64-.+}}) +// REQUIRES: linux && (target={{aarch64-.+}} || target={{s390x-.+}} || target={{x86_64-.+}}) // GCC doesn't support __attribute__((naked)) on AArch64. // UNSUPPORTED: gcc @@ -36,6 +36,20 @@ __attribute__((naked)) void bad_unwind_info() { ".cfi_def_cfa_offset 0\n" ".cfi_restore x30\n" "ret\n"); +#elif defined(__s390x__) + __asm__("stmg%r14,%r15,112(%r15)\n" + "mvghi 104(%r15),4\n" + "# purposely use incorrect offset for %r14\n" + ".cfi_offset 14, -56\n" + ".cfi_offset 15, -40\n" + "lay %r15,-160(%r15)\n" + ".cfi_def_cfa_offset 320\n" + "brasl %r14,stepper\n" + "lmg %r14,%r15,272(%r15)\n" + ".cfi_restore 15\n" + ".cfi_restore 14\n" + ".cfi_def_cfa_offset 160\n" + "br %r14\n"); #elif defined(__x86_64__) __asm__("pushq %rbx\n" ".cfi_def_cfa_offset 16\n" @@ -48,7 +62,7 @@ __attribute__((naked)) void bad_unwind_info() { ".cfi_def_cfa_offset 8\n" "ret\n"); #else -#error This test is only supported on aarch64 or x86-64 +#error This test is only supported on aarch64, s390x, or x86-64 #endif } ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[libunwind] 7167237 - [libunwind][SystemZ] Unwind out of signal handlers
Author: Ulrich Weigand Date: 2022-05-04T10:43:11+02:00 New Revision: 71672375fe91d602699ae2a6d6a88e910ff91b5c URL: https://github.com/llvm/llvm-project/commit/71672375fe91d602699ae2a6d6a88e910ff91b5c DIFF: https://github.com/llvm/llvm-project/commit/71672375fe91d602699ae2a6d6a88e910ff91b5c.diff LOG: [libunwind][SystemZ] Unwind out of signal handlers Unwinding out of signal handlers currently does not work since the sigreturn trampoline is not annotated with CFI data. Fix this by detecting the sigreturn trampoline during unwinding and providing appropriate unwind data manually. This follows closely the approach used by existing code for the AArch64 target. Reviewed by: MaskRay Differential Revision: https://reviews.llvm.org/D124765 Added: Modified: libunwind/src/UnwindCursor.hpp libunwind/test/signal_unwind.pass.cpp libunwind/test/unwind_leaffunction.pass.cpp Removed: diff --git a/libunwind/src/UnwindCursor.hpp b/libunwind/src/UnwindCursor.hpp index 655e41d81d5eb..7e56eff471596 100644 --- a/libunwind/src/UnwindCursor.hpp +++ b/libunwind/src/UnwindCursor.hpp @@ -953,7 +953,7 @@ class UnwindCursor : public AbstractUnwindCursor{ } #endif -#if defined(_LIBUNWIND_TARGET_LINUX) && defined(_LIBUNWIND_TARGET_AARCH64) +#if defined(_LIBUNWIND_TARGET_LINUX) && (defined(_LIBUNWIND_TARGET_AARCH64) || defined(_LIBUNWIND_TARGET_S390X)) bool setInfoForSigReturn() { R dummy; return setInfoForSigReturn(dummy); @@ -962,8 +962,14 @@ class UnwindCursor : public AbstractUnwindCursor{ R dummy; return stepThroughSigReturn(dummy); } + #if defined(_LIBUNWIND_TARGET_AARCH64) bool setInfoForSigReturn(Registers_arm64 &); int stepThroughSigReturn(Registers_arm64 &); + #endif + #if defined(_LIBUNWIND_TARGET_S390X) + bool setInfoForSigReturn(Registers_s390x &); + int stepThroughSigReturn(Registers_s390x &); + #endif template bool setInfoForSigReturn(Registers &) { return false; } @@ -1258,7 +1264,7 @@ class UnwindCursor : public AbstractUnwindCursor{ unw_proc_info_t _info; bool _unwindInfoMissing; bool _isSignalFrame; -#if defined(_LIBUNWIND_TARGET_LINUX) && defined(_LIBUNWIND_TARGET_AARCH64) +#if defined(_LIBUNWIND_TARGET_LINUX) && (defined(_LIBUNWIND_TARGET_AARCH64) || defined(_LIBUNWIND_TARGET_S390X)) bool _isSigReturn = false; #endif }; @@ -2465,7 +2471,7 @@ int UnwindCursor::stepWithTBTable(pint_t pc, tbtable *TBTable, template void UnwindCursor::setInfoBasedOnIPRegister(bool isReturnAddress) { -#if defined(_LIBUNWIND_TARGET_LINUX) && defined(_LIBUNWIND_TARGET_AARCH64) +#if defined(_LIBUNWIND_TARGET_LINUX) && (defined(_LIBUNWIND_TARGET_AARCH64) || defined(_LIBUNWIND_TARGET_S390X)) _isSigReturn = false; #endif @@ -2580,7 +2586,7 @@ void UnwindCursor::setInfoBasedOnIPRegister(bool isReturnAddress) { } #endif // #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) -#if defined(_LIBUNWIND_TARGET_LINUX) && defined(_LIBUNWIND_TARGET_AARCH64) +#if defined(_LIBUNWIND_TARGET_LINUX) && (defined(_LIBUNWIND_TARGET_AARCH64) || defined(_LIBUNWIND_TARGET_S390X)) if (setInfoForSigReturn()) return; #endif @@ -2653,6 +2659,104 @@ int UnwindCursor::stepThroughSigReturn(Registers_arm64 &) { } #endif // defined(_LIBUNWIND_TARGET_LINUX) && defined(_LIBUNWIND_TARGET_AARCH64) +#if defined(_LIBUNWIND_TARGET_LINUX) && defined(_LIBUNWIND_TARGET_S390X) +template +bool UnwindCursor::setInfoForSigReturn(Registers_s390x &) { + // Look for the sigreturn trampoline. The trampoline's body is a + // specific instruction (see below). Typically the trampoline comes from the + // vDSO (i.e. the __kernel_[rt_]sigreturn function). A libc might provide its + // own restorer function, though, or user-mode QEMU might write a trampoline + // onto the stack. + const pint_t pc = static_cast(this->getReg(UNW_REG_IP)); + const uint16_t inst = _addressSpace.get16(pc); + if (inst == 0x0a77 || inst == 0x0aad) { +_info = {}; +_info.start_ip = pc; +_info.end_ip = pc + 2; +_isSigReturn = true; +return true; + } + return false; +} + +template +int UnwindCursor::stepThroughSigReturn(Registers_s390x &) { + // Determine current SP. + const pint_t sp = static_cast(this->getReg(UNW_REG_SP)); + // According to the s390x ABI, the CFA is at (incoming) SP + 160. + const pint_t cfa = sp + 160; + + // Determine current PC and instruction there (this must be either + // a "svc __NR_sigreturn" or "svc __NR_rt_sigreturn"). + const pint_t pc = static_cast(this->getReg(UNW_REG_IP)); + const uint16_t inst = _addressSpace.get16(pc); + + // Find the addresses of the signo and sigcontext in the frame. + pint_t pSigctx = 0; + pint_t pSigno = 0; + + // "svc __NR_sigreturn" uses a non-RT signal trampoline frame. + if (inst == 0x0a77) { +// Layout of a non-RT signal trampoline frame, starting at the CFA: +
[libunwind] 364c502 - [libunwind] Add SystemZ support
Author: Ulrich Weigand Date: 2022-05-02T14:35:29+02:00 New Revision: 364c5023d2ce1617c706b185892ddfaa2fd4d166 URL: https://github.com/llvm/llvm-project/commit/364c5023d2ce1617c706b185892ddfaa2fd4d166 DIFF: https://github.com/llvm/llvm-project/commit/364c5023d2ce1617c706b185892ddfaa2fd4d166.diff LOG: [libunwind] Add SystemZ support Add support for the SystemZ (s390x) architecture to libunwind. Support should be feature-complete with the exception of unwinding from signal handlers (to be added later). Reviewed by: MaskRay Differential Revision: https://reviews.llvm.org/D124248 Added: Modified: libunwind/include/__libunwind_config.h libunwind/include/libunwind.h libunwind/src/Registers.hpp libunwind/src/UnwindCursor.hpp libunwind/src/UnwindRegistersRestore.S libunwind/src/UnwindRegistersSave.S libunwind/src/config.h libunwind/src/libunwind.cpp Removed: diff --git a/libunwind/include/__libunwind_config.h b/libunwind/include/__libunwind_config.h index 30f5e0a23d08e..e626567d4e594 100644 --- a/libunwind/include/__libunwind_config.h +++ b/libunwind/include/__libunwind_config.h @@ -29,6 +29,7 @@ #define _LIBUNWIND_HIGHEST_DWARF_REGISTER_HEXAGON 34 #define _LIBUNWIND_HIGHEST_DWARF_REGISTER_RISCV 64 #define _LIBUNWIND_HIGHEST_DWARF_REGISTER_VE143 +#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_S390X 83 #if defined(_LIBUNWIND_IS_NATIVE_ONLY) # if defined(__linux__) @@ -160,6 +161,11 @@ # define _LIBUNWIND_CONTEXT_SIZE 67 # define _LIBUNWIND_CURSOR_SIZE 79 # define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_VE +# elif defined(__s390x__) +# define _LIBUNWIND_TARGET_S390X 1 +# define _LIBUNWIND_CONTEXT_SIZE 34 +# define _LIBUNWIND_CURSOR_SIZE 46 +# define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_S390X # else # error "Unsupported architecture." # endif @@ -178,6 +184,7 @@ # define _LIBUNWIND_TARGET_HEXAGON 1 # define _LIBUNWIND_TARGET_RISCV 1 # define _LIBUNWIND_TARGET_VE 1 +# define _LIBUNWIND_TARGET_S390X 1 # define _LIBUNWIND_CONTEXT_SIZE 167 # define _LIBUNWIND_CURSOR_SIZE 179 # define _LIBUNWIND_HIGHEST_DWARF_REGISTER 287 diff --git a/libunwind/include/libunwind.h b/libunwind/include/libunwind.h index a69e72fc132df..3d8fd2146ebbd 100644 --- a/libunwind/include/libunwind.h +++ b/libunwind/include/libunwind.h @@ -1177,4 +1177,46 @@ enum { UNW_VE_VL = 145, }; +// s390x register numbers +enum { + UNW_S390X_R0 = 0, + UNW_S390X_R1 = 1, + UNW_S390X_R2 = 2, + UNW_S390X_R3 = 3, + UNW_S390X_R4 = 4, + UNW_S390X_R5 = 5, + UNW_S390X_R6 = 6, + UNW_S390X_R7 = 7, + UNW_S390X_R8 = 8, + UNW_S390X_R9 = 9, + UNW_S390X_R10 = 10, + UNW_S390X_R11 = 11, + UNW_S390X_R12 = 12, + UNW_S390X_R13 = 13, + UNW_S390X_R14 = 14, + UNW_S390X_R15 = 15, + UNW_S390X_F0 = 16, + UNW_S390X_F2 = 17, + UNW_S390X_F4 = 18, + UNW_S390X_F6 = 19, + UNW_S390X_F1 = 20, + UNW_S390X_F3 = 21, + UNW_S390X_F5 = 22, + UNW_S390X_F7 = 23, + UNW_S390X_F8 = 24, + UNW_S390X_F10 = 25, + UNW_S390X_F12 = 26, + UNW_S390X_F14 = 27, + UNW_S390X_F9 = 28, + UNW_S390X_F11 = 29, + UNW_S390X_F13 = 30, + UNW_S390X_F15 = 31, + // 32-47 Control Registers + // 48-63 Access Registers + UNW_S390X_PSWM= 64, + UNW_S390X_PSWA= 65, + // 66-67 Reserved + // 68-83 Vector Registers %v16-%v31 +}; + #endif diff --git a/libunwind/src/Registers.hpp b/libunwind/src/Registers.hpp index 32c13e6c9a248..28c617f34999b 100644 --- a/libunwind/src/Registers.hpp +++ b/libunwind/src/Registers.hpp @@ -39,6 +39,7 @@ enum { REGISTERS_HEXAGON, REGISTERS_RISCV, REGISTERS_VE, + REGISTERS_S390X, }; #if defined(_LIBUNWIND_TARGET_I386) @@ -4716,6 +4717,293 @@ inline const char *Registers_ve::getRegisterName(int regNum) { } #endif // _LIBUNWIND_TARGET_VE +#if defined(_LIBUNWIND_TARGET_S390X) +/// Registers_s390x holds the register state of a thread in a +/// 64-bit Linux on IBM zSystems process. +class _LIBUNWIND_HIDDEN Registers_s390x { +public: + Registers_s390x(); + Registers_s390x(const void *registers); + + boolvalidRegister(int num) const; + uint64_tgetRegister(int num) const; + voidsetRegister(int num, uint64_t value); + boolvalidFloatRegister(int num) const; + double getFloatRegister(int num) const; + voidsetFloatRegister(int num, double value); + boolvalidVectorRegister(int num) const; + v128getVectorRegister(int num) const; + voidsetVectorRegister(int num, v128 value); + static const char *getRegisterName(int num); + voidjumpto(); + static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_S390X; } + static int getArch() { return REGISTERS_S390X; } + +
[clang] 1283ccb - Support z16 processor name
Author: Ulrich Weigand Date: 2022-04-21T19:58:22+02:00 New Revision: 1283ccb610feef4f2e0edf22f66a705155a0e0c7 URL: https://github.com/llvm/llvm-project/commit/1283ccb610feef4f2e0edf22f66a705155a0e0c7 DIFF: https://github.com/llvm/llvm-project/commit/1283ccb610feef4f2e0edf22f66a705155a0e0c7.diff LOG: Support z16 processor name The recently announced IBM z16 processor implements the architecture already supported as "arch14" in LLVM. This patch adds support for "z16" as an alternate architecture name for arch14. Added: llvm/test/MC/Disassembler/SystemZ/insns-z16.txt llvm/test/MC/SystemZ/insn-bad-z16.s llvm/test/MC/SystemZ/insn-good-z16.s Modified: clang/lib/Basic/Targets/SystemZ.cpp clang/test/CodeGen/SystemZ/builtins-systemz-vector4.c clang/test/CodeGen/SystemZ/builtins-systemz-zvector4-error.c clang/test/CodeGen/SystemZ/builtins-systemz-zvector4.c clang/test/CodeGen/SystemZ/systemz-abi-vector.c clang/test/CodeGen/SystemZ/systemz-abi.c clang/test/Driver/systemz-march.c clang/test/Misc/target-invalid-cpu-note.c clang/test/Preprocessor/predefined-arch-macros.c llvm/lib/Support/Host.cpp llvm/lib/Target/SystemZ/SystemZProcessors.td llvm/test/CodeGen/SystemZ/vec-intrinsics-04.ll llvm/unittests/Support/Host.cpp Removed: llvm/test/MC/Disassembler/SystemZ/insns-arch14.txt llvm/test/MC/SystemZ/insn-bad-arch14.s llvm/test/MC/SystemZ/insn-good-arch14.s diff --git a/clang/lib/Basic/Targets/SystemZ.cpp b/clang/lib/Basic/Targets/SystemZ.cpp index 3af9216315132..84874b58ba68c 100644 --- a/clang/lib/Basic/Targets/SystemZ.cpp +++ b/clang/lib/Basic/Targets/SystemZ.cpp @@ -104,7 +104,7 @@ static constexpr ISANameRevision ISARevisions[] = { {{"arch11"}, 11}, {{"z13"}, 11}, {{"arch12"}, 12}, {{"z14"}, 12}, {{"arch13"}, 13}, {{"z15"}, 13}, - {{"arch14"}, 14} + {{"arch14"}, 14}, {{"z16"}, 14}, }; int SystemZTargetInfo::getISARevision(StringRef Name) const { diff --git a/clang/test/CodeGen/SystemZ/builtins-systemz-vector4.c b/clang/test/CodeGen/SystemZ/builtins-systemz-vector4.c index b0cd994904134..c5ce47cea2ea8 100644 --- a/clang/test/CodeGen/SystemZ/builtins-systemz-vector4.c +++ b/clang/test/CodeGen/SystemZ/builtins-systemz-vector4.c @@ -1,5 +1,5 @@ // REQUIRES: systemz-registered-target -// RUN: %clang_cc1 -target-cpu arch14 -triple s390x-ibm-linux -flax-vector-conversions=none \ +// RUN: %clang_cc1 -target-cpu z16 -triple s390x-ibm-linux -flax-vector-conversions=none \ // RUN: -Wall -Wno-unused -Werror -emit-llvm %s -o - | FileCheck %s typedef __attribute__((vector_size(16))) signed char vec_schar; diff --git a/clang/test/CodeGen/SystemZ/builtins-systemz-zvector4-error.c b/clang/test/CodeGen/SystemZ/builtins-systemz-zvector4-error.c index a893e77acbf60..df547cb99f24b 100644 --- a/clang/test/CodeGen/SystemZ/builtins-systemz-zvector4-error.c +++ b/clang/test/CodeGen/SystemZ/builtins-systemz-zvector4-error.c @@ -1,5 +1,5 @@ // REQUIRES: systemz-registered-target -// RUN: %clang_cc1 -target-cpu arch14 -triple s390x-linux-gnu \ +// RUN: %clang_cc1 -target-cpu z16 -triple s390x-linux-gnu \ // RUN: -fzvector -flax-vector-conversions=none \ // RUN: -Wall -Wno-unused -Werror -fsyntax-only -verify %s diff --git a/clang/test/CodeGen/SystemZ/builtins-systemz-zvector4.c b/clang/test/CodeGen/SystemZ/builtins-systemz-zvector4.c index 602886c17d198..adc55927ce366 100644 --- a/clang/test/CodeGen/SystemZ/builtins-systemz-zvector4.c +++ b/clang/test/CodeGen/SystemZ/builtins-systemz-zvector4.c @@ -1,8 +1,8 @@ // REQUIRES: systemz-registered-target -// RUN: %clang_cc1 -target-cpu arch14 -triple s390x-linux-gnu \ +// RUN: %clang_cc1 -target-cpu z16 -triple s390x-linux-gnu \ // RUN: -O2 -fzvector -flax-vector-conversions=none \ // RUN: -Wall -Wno-unused -Werror -emit-llvm %s -o - | FileCheck %s -// RUN: %clang_cc1 -target-cpu arch14 -triple s390x-linux-gnu \ +// RUN: %clang_cc1 -target-cpu z16 -triple s390x-linux-gnu \ // RUN: -O2 -fzvector -flax-vector-conversions=none \ // RUN: -Wall -Wno-unused -Werror -S %s -o - | FileCheck %s --check-prefix=CHECK-ASM diff --git a/clang/test/CodeGen/SystemZ/systemz-abi-vector.c b/clang/test/CodeGen/SystemZ/systemz-abi-vector.c index 4a4f03c813463..7817249da757b 100644 --- a/clang/test/CodeGen/SystemZ/systemz-abi-vector.c +++ b/clang/test/CodeGen/SystemZ/systemz-abi-vector.c @@ -14,6 +14,8 @@ // RUN: -emit-llvm -o - %s | FileCheck --check-prefix=CHECK-VECTOR %s // RUN: %clang_cc1 -no-opaque-pointers -no-enable-noundef-analysis -triple s390x-linux-gnu -target-cpu arch13 \ // RUN: -emit-llvm -o - %s | FileCheck --check-prefix=CHECK-VECTOR %s +// RUN: %clang_cc1 -no-opaque-pointers -no-enable-noundef-analysis -triple s390x-linux-gnu -target-cpu z16 \ +// RUN: -emit-llvm -o - %s | FileCheck --check-prefix=CHECK-VECTOR %s // RUN: %clang_cc1 -no-opaque-pointers
[clang] 7f00395 - [SystemZ] Implement __builtin_eh_return_data_regno
Author: Ulrich Weigand Date: 2020-07-24T10:28:06+02:00 New Revision: 7f003957bfcd1ed29ded176f04e3cdb55a0c0112 URL: https://github.com/llvm/llvm-project/commit/7f003957bfcd1ed29ded176f04e3cdb55a0c0112 DIFF: https://github.com/llvm/llvm-project/commit/7f003957bfcd1ed29ded176f04e3cdb55a0c0112.diff LOG: [SystemZ] Implement __builtin_eh_return_data_regno Implement __builtin_eh_return_data_regno for SystemZ. Match behavior of GCC. Author: slavek-kucera Differential Revision: https://reviews.llvm.org/D84341 Added: Modified: clang/lib/Basic/Targets/SystemZ.h clang/test/CodeGen/builtins-systemz.c Removed: diff --git a/clang/lib/Basic/Targets/SystemZ.h b/clang/lib/Basic/Targets/SystemZ.h index d7869e3754a8..39fdcf90d0c8 100644 --- a/clang/lib/Basic/Targets/SystemZ.h +++ b/clang/lib/Basic/Targets/SystemZ.h @@ -157,6 +157,10 @@ class LLVM_LIBRARY_VISIBILITY SystemZTargetInfo : public TargetInfo { const char *getLongDoubleMangling() const override { return "g"; } bool hasExtIntType() const override { return true; } + + int getEHDataRegisterNumber(unsigned RegNo) const override { +return RegNo < 4 ? 6 + RegNo : -1; + } }; } // namespace targets } // namespace clang diff --git a/clang/test/CodeGen/builtins-systemz.c b/clang/test/CodeGen/builtins-systemz.c index f5de7009acba..bf8a995383a2 100644 --- a/clang/test/CodeGen/builtins-systemz.c +++ b/clang/test/CodeGen/builtins-systemz.c @@ -142,3 +142,10 @@ void test_htmxl1(void) { result = __TM_failure_code (tdb); } +void test_eh_return_data_regno() { + volatile int res; + res = __builtin_eh_return_data_regno(0); // CHECK: store volatile i32 6 + res = __builtin_eh_return_data_regno(1); // CHECK: store volatile i32 7 + res = __builtin_eh_return_data_regno(2); // CHECK: store volatile i32 8 + res = __builtin_eh_return_data_regno(3); // CHECK: store volatile i32 9 +} ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] 4c5a93b - [ABI] Handle C++20 [[no_unique_address]] attribute
Author: Ulrich Weigand Date: 2020-07-10T14:01:05+02:00 New Revision: 4c5a93bd58bad70e91ac525b0e020bd5119a321a URL: https://github.com/llvm/llvm-project/commit/4c5a93bd58bad70e91ac525b0e020bd5119a321a DIFF: https://github.com/llvm/llvm-project/commit/4c5a93bd58bad70e91ac525b0e020bd5119a321a.diff LOG: [ABI] Handle C++20 [[no_unique_address]] attribute Many platform ABIs have special support for passing aggregates that either just contain a single member of floatint-point type, or else a homogeneous set of members of the same floating-point type. When making this determination, any extra "empty" members of the aggregate type will typically be ignored. However, in C++ (at least in all prior versions), no data member would actually count as empty, even if it's type is an empty record -- it would still be considered to take up at least one byte of space, and therefore make those ABI special cases not apply. This is now changing in C++20, which introduced the [[no_unique_address]] attribute. Members of empty record type, if they also carry this attribute, now do *not* take up any space in the type, and therefore the ABI special cases for single-element or homogeneous aggregates should apply. The C++ Itanium ABI has been updated accordingly, and GCC 10 has added support for this new case. This patch now adds support to LLVM. This is cross-platform; it affects all platforms that use the single-element or homogeneous aggregate ABI special case and implement this using any of the following common subroutines in lib/CodeGen/TargetInfo.cpp: isEmptyField isEmptyRecord isSingleElementStruct isHomogeneousAggregate Added: Modified: clang/lib/CodeGen/TargetInfo.cpp clang/test/CodeGen/systemz-abi.cpp Removed: diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp index b83267dec6f0..9cd63ebe29ee 100644 --- a/clang/lib/CodeGen/TargetInfo.cpp +++ b/clang/lib/CodeGen/TargetInfo.cpp @@ -499,11 +499,15 @@ static bool isEmptyField(ASTContext , const FieldDecl *FD, // Constant arrays of empty records count as empty, strip them off. // Constant arrays of zero length always count as empty. + bool WasArray = false; if (AllowArrays) while (const ConstantArrayType *AT = Context.getAsConstantArrayType(FT)) { if (AT->getSize() == 0) return true; FT = AT->getElementType(); + // The [[no_unique_address]] special case below does not apply to + // arrays of C++ empty records, so we need to remember this fact. + WasArray = true; } const RecordType *RT = FT->getAs(); @@ -514,7 +518,14 @@ static bool isEmptyField(ASTContext , const FieldDecl *FD, // // FIXME: We should use a predicate for whether this behavior is true in the // current ABI. - if (isa(RT->getDecl())) + // + // The exception to the above rule are fields marked with the + // [[no_unique_address]] attribute (since C++20). Those do count as empty + // according to the Itanium ABI. The exception applies only to records, + // not arrays of records, so we must also check whether we stripped off an + // array type above. + if (isa(RT->getDecl()) && + (WasArray || !FD->hasAttr())) return false; return isEmptyRecord(Context, FT, AllowArrays); @@ -7236,6 +7247,10 @@ QualType SystemZABIInfo::GetSingleElementType(QualType Ty) const { if (getContext().getLangOpts().CPlusPlus && FD->isZeroLengthBitField(getContext())) continue; + // Like isSingleElementStruct(), ignore C++20 empty data members. + if (FD->hasAttr() && + isEmptyRecord(getContext(), FD->getType(), true)) +continue; // Unlike isSingleElementStruct(), arrays do not count. // Nested structures still do though. diff --git a/clang/test/CodeGen/systemz-abi.cpp b/clang/test/CodeGen/systemz-abi.cpp index 7604dea41dde..a91cb72ae33e 100644 --- a/clang/test/CodeGen/systemz-abi.cpp +++ b/clang/test/CodeGen/systemz-abi.cpp @@ -23,3 +23,37 @@ struct agg_float_cpp pass_agg_float_cpp(struct agg_float_cpp arg) { return arg; // CHECK-LABEL: define void @_Z18pass_agg_float_cpp13agg_float_cpp(%struct.agg_float_cpp* noalias sret align 4 %{{.*}}, float %{{.*}}) // SOFT-FLOAT-LABEL: define void @_Z18pass_agg_float_cpp13agg_float_cpp(%struct.agg_float_cpp* noalias sret align 4 %{{.*}}, i32 %{{.*}}) + +// A field member of empty class type in C++ makes the record nonhomogeneous, +// unless it is marked as [[no_unique_address]]. This does not apply to arrays. +struct empty { }; +struct agg_nofloat_empty { float a; empty dummy; }; +struct agg_nofloat_empty pass_agg_nofloat_empty(struct agg_nofloat_empty arg) { return arg; } +// CHECK-LABEL: define void @_Z22pass_agg_nofloat_empty17agg_nofloat_empty(%struct.agg_nofloat_empty* noalias sret align 4 %{{.*}}, i64 %{{.*}}) +// SOFT-FLOAT-LABEL: define void
[clang] 80a1b95 - [SystemZ ABI] Allow class types in GetSingleElementType
Author: Ulrich Weigand Date: 2020-07-07T19:56:19+02:00 New Revision: 80a1b95b8e72674cef7efb39636dc73c248ae6f3 URL: https://github.com/llvm/llvm-project/commit/80a1b95b8e72674cef7efb39636dc73c248ae6f3 DIFF: https://github.com/llvm/llvm-project/commit/80a1b95b8e72674cef7efb39636dc73c248ae6f3.diff LOG: [SystemZ ABI] Allow class types in GetSingleElementType The SystemZ ABI specifies that aggregate types with just a single member of floating-point type shall be passed as if they were just a scalar of that type. This applies to both struct and class types (but not unions). However, the current ABI support code in clang only checks this case for struct types, which means that for class types, generated code does not adhere to the platform ABI. Fixed by accepting both struct and class types in the SystemZABIInfo::GetSingleElementType routine. Added: Modified: clang/lib/CodeGen/TargetInfo.cpp clang/test/CodeGen/systemz-abi.c clang/test/CodeGen/systemz-abi.cpp Removed: diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp index 7947aff6cc2f..801adc29acd1 100644 --- a/clang/lib/CodeGen/TargetInfo.cpp +++ b/clang/lib/CodeGen/TargetInfo.cpp @@ -7208,7 +7208,9 @@ bool SystemZABIInfo::isFPArgumentType(QualType Ty) const { } QualType SystemZABIInfo::GetSingleElementType(QualType Ty) const { - if (const RecordType *RT = Ty->getAsStructureType()) { + const RecordType *RT = Ty->getAs(); + + if (RT && RT->isStructureOrClassType()) { const RecordDecl *RD = RT->getDecl(); QualType Found; diff --git a/clang/test/CodeGen/systemz-abi.c b/clang/test/CodeGen/systemz-abi.c index 35adbbe301c4..9f9cb2275bfa 100644 --- a/clang/test/CodeGen/systemz-abi.c +++ b/clang/test/CodeGen/systemz-abi.c @@ -155,6 +155,17 @@ struct agg_nofloat3 pass_agg_nofloat3(struct agg_nofloat3 arg) { return arg; } // CHECK-LABEL: define void @pass_agg_nofloat3(%struct.agg_nofloat3* noalias sret align 4 %{{.*}}, i32 %{{.*}}) +// Union types likewise are *not* float-like aggregate types + +union union_float { float a; }; +union union_float pass_union_float(union union_float arg) { return arg; } +// CHECK-LABEL: define void @pass_union_float(%union.union_float* noalias sret align 4 %{{.*}}, i32 %{{.*}}) + +union union_double { double a; }; +union union_double pass_union_double(union union_double arg) { return arg; } +// CHECK-LABEL: define void @pass_union_double(%union.union_double* noalias sret align 8 %{{.*}}, i64 %{{.*}}) + + // Accessing variable argument lists int va_int(__builtin_va_list l) { return __builtin_va_arg(l, int); } diff --git a/clang/test/CodeGen/systemz-abi.cpp b/clang/test/CodeGen/systemz-abi.cpp index cb381e88dd8f..7604dea41dde 100644 --- a/clang/test/CodeGen/systemz-abi.cpp +++ b/clang/test/CodeGen/systemz-abi.cpp @@ -2,10 +2,24 @@ // RUN: %clang_cc1 -triple s390x-linux-gnu -emit-llvm -x c++ -o - %s -mfloat-abi soft \ // RUN: | FileCheck %s --check-prefix=SOFT-FLOAT +// Verify that class types are also recognized as float-like aggregate types + +class agg_float_class { float a; }; +class agg_float_class pass_agg_float_class(class agg_float_class arg) { return arg; } +// CHECK-LABEL: define void @_Z20pass_agg_float_class15agg_float_class(%class.agg_float_class* noalias sret align 4 %{{.*}}, float %{{.*}}) +// SOFT-FLOAT-LABEL: define void @_Z20pass_agg_float_class15agg_float_class(%class.agg_float_class* noalias sret align 4 %{{.*}}, i32 %{{.*}}) + +class agg_double_class { double a; }; +class agg_double_class pass_agg_double_class(class agg_double_class arg) { return arg; } +// CHECK-LABEL: define void @_Z21pass_agg_double_class16agg_double_class(%class.agg_double_class* noalias sret align 8 %{{.*}}, double %{{.*}}) +// SOFT-FLOAT-LABEL: define void @_Z21pass_agg_double_class16agg_double_class(%class.agg_double_class* noalias sret align 8 %{{.*}}, i64 %{{.*}}) + + // For compatibility with GCC, this structure is passed in an FPR in C++, // but passed in a GPR in C (checked in systemz-abi.c). struct agg_float_cpp { float a; int : 0; }; struct agg_float_cpp pass_agg_float_cpp(struct agg_float_cpp arg) { return arg; } // CHECK-LABEL: define void @_Z18pass_agg_float_cpp13agg_float_cpp(%struct.agg_float_cpp* noalias sret align 4 %{{.*}}, float %{{.*}}) -// SOFT-FLOAT: define void @_Z18pass_agg_float_cpp13agg_float_cpp(%struct.agg_float_cpp* noalias sret align 4 %{{.*}}, i32 %{{.*}}) +// SOFT-FLOAT-LABEL: define void @_Z18pass_agg_float_cpp13agg_float_cpp(%struct.agg_float_cpp* noalias sret align 4 %{{.*}}, i32 %{{.*}}) + ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] 095ccf4 - [SystemZ] Avoid __INTPTR_TYPE__ conversions in vecintrin.h
Author: Ulrich Weigand Date: 2020-04-28T18:49:49+02:00 New Revision: 095ccf4455654750cd4c0296ff91565c2b613319 URL: https://github.com/llvm/llvm-project/commit/095ccf4455654750cd4c0296ff91565c2b613319 DIFF: https://github.com/llvm/llvm-project/commit/095ccf4455654750cd4c0296ff91565c2b613319.diff LOG: [SystemZ] Avoid __INTPTR_TYPE__ conversions in vecintrin.h Some intrinsics in vecintrin.h are currently implemented by performing address arithmetic in __INTPTR_TYPE__ and converting the result to some pointer type. While this works correctly, it leads to suboptimal code generation since many optimizers cannot trace the provenance of the resulting pointers. Fixed by using "char *" pointer arithmetic instead. Added: Modified: clang/lib/Headers/vecintrin.h Removed: diff --git a/clang/lib/Headers/vecintrin.h b/clang/lib/Headers/vecintrin.h index aa2a0c300120..e58c9769e8cb 100644 --- a/clang/lib/Headers/vecintrin.h +++ b/clang/lib/Headers/vecintrin.h @@ -860,7 +860,7 @@ vec_gather_element(__vector signed int __vec, const signed int *__ptr, int __index) __constant_range(__index, 0, 3) { __vec[__index] = *(const signed int *)( -(__INTPTR_TYPE__)__ptr + (__INTPTR_TYPE__)__offset[__index]); +(const char *)__ptr + __offset[__index]); return __vec; } @@ -870,7 +870,7 @@ vec_gather_element(__vector __bool int __vec, const unsigned int *__ptr, int __index) __constant_range(__index, 0, 3) { __vec[__index] = *(const unsigned int *)( -(__INTPTR_TYPE__)__ptr + (__INTPTR_TYPE__)__offset[__index]); +(const char *)__ptr + __offset[__index]); return __vec; } @@ -880,7 +880,7 @@ vec_gather_element(__vector unsigned int __vec, const unsigned int *__ptr, int __index) __constant_range(__index, 0, 3) { __vec[__index] = *(const unsigned int *)( -(__INTPTR_TYPE__)__ptr + (__INTPTR_TYPE__)__offset[__index]); +(const char *)__ptr + __offset[__index]); return __vec; } @@ -890,7 +890,7 @@ vec_gather_element(__vector signed long long __vec, const signed long long *__ptr, int __index) __constant_range(__index, 0, 1) { __vec[__index] = *(const signed long long *)( -(__INTPTR_TYPE__)__ptr + (__INTPTR_TYPE__)__offset[__index]); +(const char *)__ptr + __offset[__index]); return __vec; } @@ -900,7 +900,7 @@ vec_gather_element(__vector __bool long long __vec, const unsigned long long *__ptr, int __index) __constant_range(__index, 0, 1) { __vec[__index] = *(const unsigned long long *)( -(__INTPTR_TYPE__)__ptr + (__INTPTR_TYPE__)__offset[__index]); +(const char *)__ptr + __offset[__index]); return __vec; } @@ -910,7 +910,7 @@ vec_gather_element(__vector unsigned long long __vec, const unsigned long long *__ptr, int __index) __constant_range(__index, 0, 1) { __vec[__index] = *(const unsigned long long *)( -(__INTPTR_TYPE__)__ptr + (__INTPTR_TYPE__)__offset[__index]); +(const char *)__ptr + __offset[__index]); return __vec; } @@ -921,7 +921,7 @@ vec_gather_element(__vector float __vec, const float *__ptr, int __index) __constant_range(__index, 0, 3) { __vec[__index] = *(const float *)( -(__INTPTR_TYPE__)__ptr + (__INTPTR_TYPE__)__offset[__index]); +(const char *)__ptr + __offset[__index]); return __vec; } #endif @@ -932,7 +932,7 @@ vec_gather_element(__vector double __vec, const double *__ptr, int __index) __constant_range(__index, 0, 1) { __vec[__index] = *(const double *)( -(__INTPTR_TYPE__)__ptr + (__INTPTR_TYPE__)__offset[__index]); +(const char *)__ptr + __offset[__index]); return __vec; } @@ -943,7 +943,7 @@ vec_scatter_element(__vector signed int __vec, __vector unsigned int __offset, signed int *__ptr, int __index) __constant_range(__index, 0, 3) { - *(signed int *)((__INTPTR_TYPE__)__ptr + __offset[__index]) = + *(signed int *)((char *)__ptr + __offset[__index]) = __vec[__index]; } @@ -952,7 +952,7 @@ vec_scatter_element(__vector __bool int __vec, __vector unsigned int __offset, unsigned int *__ptr, int __index) __constant_range(__index, 0, 3) { - *(unsigned int *)((__INTPTR_TYPE__)__ptr + __offset[__index]) = + *(unsigned int *)((char *)__ptr + __offset[__index]) = __vec[__index]; } @@ -961,7 +961,7 @@ vec_scatter_element(__vector unsigned int __vec, __vector unsigned int __offset, unsigned int *__ptr, int __index) __constant_range(__index, 0, 3) { - *(unsigned int *)((__INTPTR_TYPE__)__ptr + __offset[__index]) = + *(unsigned int *)((char *)__ptr + __offset[__index]) = __vec[__index]; } @@ -970,7 +970,7 @@ vec_scatter_element(__vector signed long long __vec,
[clang] 9c9d88d - [SystemZ] Allow configuring default CLANG_SYSTEMZ_ARCH
Author: Ulrich Weigand Date: 2020-03-30T14:20:48+02:00 New Revision: 9c9d88d8b1bb6468f6c4258fe41bbcd01f742801 URL: https://github.com/llvm/llvm-project/commit/9c9d88d8b1bb6468f6c4258fe41bbcd01f742801 DIFF: https://github.com/llvm/llvm-project/commit/9c9d88d8b1bb6468f6c4258fe41bbcd01f742801.diff LOG: [SystemZ] Allow configuring default CLANG_SYSTEMZ_ARCH On Ubuntu, we want to raise default CLANG_SYSTEMZ_ARCH to z13, thus allow configuring this via CMake. On Debian, we want to raise it to z196. Author: Dimitri John Ledkov Differential Revision: https://reviews.llvm.org/D75914 Added: Modified: clang/CMakeLists.txt clang/lib/Driver/ToolChains/Arch/SystemZ.cpp Removed: diff --git a/clang/CMakeLists.txt b/clang/CMakeLists.txt index 7809d6529195..c9e76c5e4518 100644 --- a/clang/CMakeLists.txt +++ b/clang/CMakeLists.txt @@ -306,6 +306,10 @@ if (NOT DEFINED MATCHED_ARCH OR "${CMAKE_MATCH_1}" LESS 35) "Default architecture for OpenMP offloading to Nvidia GPUs." FORCE) endif() +set(CLANG_SYSTEMZ_DEFAULT_ARCH "z10" CACHE STRING + "SystemZ Default Arch") +add_definitions( -DCLANG_SYSTEMZ_DEFAULT_ARCH="${CLANG_SYSTEMZ_DEFAULT_ARCH}") + set(CLANG_VENDOR ${PACKAGE_VENDOR} CACHE STRING "Vendor-specific text for showing with version information.") diff --git a/clang/lib/Driver/ToolChains/Arch/SystemZ.cpp b/clang/lib/Driver/ToolChains/Arch/SystemZ.cpp index 4d871104c95a..b263fb7df09e 100644 --- a/clang/lib/Driver/ToolChains/Arch/SystemZ.cpp +++ b/clang/lib/Driver/ToolChains/Arch/SystemZ.cpp @@ -47,7 +47,7 @@ std::string systemz::getSystemZTargetCPU(const ArgList ) { return std::string(CPUName); } - return "z10"; + return CLANG_SYSTEMZ_DEFAULT_ARCH; } void systemz::getSystemZTargetFeatures(const Driver , const ArgList , ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] cebba7c - [SystemZ] Avoid unnecessary conversions in vecintrin.h
Author: Ulrich Weigand Date: 2020-01-16T18:58:14+01:00 New Revision: cebba7ce3952c8f37a923fa3a10360fd4c463775 URL: https://github.com/llvm/llvm-project/commit/cebba7ce3952c8f37a923fa3a10360fd4c463775 DIFF: https://github.com/llvm/llvm-project/commit/cebba7ce3952c8f37a923fa3a10360fd4c463775.diff LOG: [SystemZ] Avoid unnecessary conversions in vecintrin.h Use floating-point instead of integer zero constants to avoid creating implicit conversions, which currently cause suboptimal code to be generated with -ffp-exception-behavior=strict. NFC otherwise. Added: Modified: clang/lib/Headers/vecintrin.h Removed: diff --git a/clang/lib/Headers/vecintrin.h b/clang/lib/Headers/vecintrin.h index c71b76a3ee39..6f9b609f2dfe 100644 --- a/clang/lib/Headers/vecintrin.h +++ b/clang/lib/Headers/vecintrin.h @@ -290,7 +290,7 @@ vec_promote(unsigned long long __scalar, int __index) { #if __ARCH__ >= 12 static inline __ATTRS_o_ai vector float vec_promote(float __scalar, int __index) { - const vector float __zero = (vector float)0; + const vector float __zero = (vector float)0.0f; vector float __vec = __builtin_shufflevector(__zero, __zero, -1, -1, -1, -1); __vec[__index & 3] = __scalar; return __vec; @@ -299,7 +299,7 @@ vec_promote(float __scalar, int __index) { static inline __ATTRS_o_ai vector double vec_promote(double __scalar, int __index) { - const vector double __zero = (vector double)0; + const vector double __zero = (vector double)0.0; vector double __vec = __builtin_shufflevector(__zero, __zero, -1, -1); __vec[__index & 1] = __scalar; return __vec; @@ -366,7 +366,7 @@ vec_insert_and_zero(const unsigned long long *__ptr) { #if __ARCH__ >= 12 static inline __ATTRS_o_ai vector float vec_insert_and_zero(const float *__ptr) { - vector float __vec = (vector float)0; + vector float __vec = (vector float)0.0f; __vec[1] = *__ptr; return __vec; } @@ -374,7 +374,7 @@ vec_insert_and_zero(const float *__ptr) { static inline __ATTRS_o_ai vector double vec_insert_and_zero(const double *__ptr) { - vector double __vec = (vector double)0; + vector double __vec = (vector double)0.0; __vec[0] = *__ptr; return __vec; } ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] 76e9c2a - [FPEnv] Generate constrained FP comparisons from clang
Author: Ulrich Weigand Date: 2020-01-10T14:33:10+01:00 New Revision: 76e9c2a9870e36415eb343d28942a42296f85597 URL: https://github.com/llvm/llvm-project/commit/76e9c2a9870e36415eb343d28942a42296f85597 DIFF: https://github.com/llvm/llvm-project/commit/76e9c2a9870e36415eb343d28942a42296f85597.diff LOG: [FPEnv] Generate constrained FP comparisons from clang Update the IRBuilder to generate constrained FP comparisons in CreateFCmp when IsFPConstrained is true, similar to the other places in the IRBuilder. Also, add a new CreateFCmpS to emit signaling FP comparisons, and use it in clang where comparisons are supposed to be signaling (currently, only when emitting code for the <, <=, >, >= operators). Note that there is currently no way to add fast-math flags to a constrained FP comparison, since this is implemented as an intrinsic call that returns a boolean type, and FMF are only allowed for calls returning a floating-point type. However, given the discussion around https://bugs.llvm.org/show_bug.cgi?id=42179, it seems that FCmp itself really shouldn't have any FMF either, so this is probably OK. Reviewed by: craig.topper Differential Revision: https://reviews.llvm.org/D71467 Added: clang/test/CodeGen/fpconstrained-cmp-double.c clang/test/CodeGen/fpconstrained-cmp-float.c Modified: clang/lib/CodeGen/CGExprScalar.cpp llvm/include/llvm/IR/IRBuilder.h Removed: diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index 4adaca8ae571..4338d1c3dcdf 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -798,17 +798,17 @@ class ScalarExprEmitter // Comparisons. Value *EmitCompare(const BinaryOperator *E, llvm::CmpInst::Predicate UICmpOpc, llvm::CmpInst::Predicate SICmpOpc, - llvm::CmpInst::Predicate FCmpOpc); -#define VISITCOMP(CODE, UI, SI, FP) \ + llvm::CmpInst::Predicate FCmpOpc, bool IsSignaling); +#define VISITCOMP(CODE, UI, SI, FP, SIG) \ Value *VisitBin##CODE(const BinaryOperator *E) { \ return EmitCompare(E, llvm::ICmpInst::UI, llvm::ICmpInst::SI, \ - llvm::FCmpInst::FP); } - VISITCOMP(LT, ICMP_ULT, ICMP_SLT, FCMP_OLT) - VISITCOMP(GT, ICMP_UGT, ICMP_SGT, FCMP_OGT) - VISITCOMP(LE, ICMP_ULE, ICMP_SLE, FCMP_OLE) - VISITCOMP(GE, ICMP_UGE, ICMP_SGE, FCMP_OGE) - VISITCOMP(EQ, ICMP_EQ , ICMP_EQ , FCMP_OEQ) - VISITCOMP(NE, ICMP_NE , ICMP_NE , FCMP_UNE) + llvm::FCmpInst::FP, SIG); } + VISITCOMP(LT, ICMP_ULT, ICMP_SLT, FCMP_OLT, true) + VISITCOMP(GT, ICMP_UGT, ICMP_SGT, FCMP_OGT, true) + VISITCOMP(LE, ICMP_ULE, ICMP_SLE, FCMP_OLE, true) + VISITCOMP(GE, ICMP_UGE, ICMP_SGE, FCMP_OGE, true) + VISITCOMP(EQ, ICMP_EQ , ICMP_EQ , FCMP_OEQ, false) + VISITCOMP(NE, ICMP_NE , ICMP_NE , FCMP_UNE, false) #undef VISITCOMP Value *VisitBinAssign (const BinaryOperator *E); @@ -3804,7 +3804,8 @@ static llvm::Intrinsic::ID GetIntrinsic(IntrinsicType IT, Value *ScalarExprEmitter::EmitCompare(const BinaryOperator *E, llvm::CmpInst::Predicate UICmpOpc, llvm::CmpInst::Predicate SICmpOpc, - llvm::CmpInst::Predicate FCmpOpc) { + llvm::CmpInst::Predicate FCmpOpc, + bool IsSignaling) { TestAndClearIgnoreResultAssign(); Value *Result; QualType LHSTy = E->getLHS()->getType(); @@ -3900,7 +3901,10 @@ Value *ScalarExprEmitter::EmitCompare(const BinaryOperator *E, if (BOInfo.isFixedPointBinOp()) { Result = EmitFixedPointBinOp(BOInfo); } else if (LHS->getType()->isFPOrFPVectorTy()) { - Result = Builder.CreateFCmp(FCmpOpc, LHS, RHS, "cmp"); + if (!IsSignaling) +Result = Builder.CreateFCmp(FCmpOpc, LHS, RHS, "cmp"); + else +Result = Builder.CreateFCmpS(FCmpOpc, LHS, RHS, "cmp"); } else if (LHSTy->hasSignedIntegerRepresentation()) { Result = Builder.CreateICmp(SICmpOpc, LHS, RHS, "cmp"); } else { @@ -3957,6 +3961,8 @@ Value *ScalarExprEmitter::EmitCompare(const BinaryOperator *E, Value *ResultR, *ResultI; if (CETy->isRealFloatingType()) { + // As complex comparisons can only be equality comparisons, they + // are never signaling comparisons. ResultR = Builder.CreateFCmp(FCmpOpc, LHS.first, RHS.first, "cmp.r"); ResultI = Builder.CreateFCmp(FCmpOpc, LHS.second, RHS.second, "cmp.i"); } else { diff --git a/clang/test/CodeGen/fpconstrained-cmp-double.c b/clang/test/CodeGen/fpconstrained-cmp-double.c new file mode 100644 index ..2819970a3fcf --- /dev/null +++ b/clang/test/CodeGen/fpconstrained-cmp-double.c @@ -0,0 +1,151 @@ +// RUN: %clang_cc1 -ffp-exception-behavior=ignore -emit-llvm -o - %s | FileCheck %s