[clang] 481bb44 - [SystemZ] Emit a .gnu_attribute for an externally visible vector abi.
Jonas Paulsson via cfe-commits
cfe-commits at lists.llvm.org
Tue Dec 6 10:54:24 PST 2022
Author: Jonas Paulsson
Date: 2022-12-06T12:53:40-06:00
New Revision: 481bb44baab5ce7a005b7d7eee6cafbde672695c
URL: https://github.com/llvm/llvm-project/commit/481bb44baab5ce7a005b7d7eee6cafbde672695c
DIFF: https://github.com/llvm/llvm-project/commit/481bb44baab5ce7a005b7d7eee6cafbde672695c.diff
LOG: [SystemZ] Emit a .gnu_attribute for an externally visible vector abi.
On SystemZ, the vector ABI changes depending on the presence of hardware
vector support. Therefore, each binary compiled with a visible vector ABI
(e.g. one that calls an external function with a vector argument) should be
marked with a .gnu_attribute describing this.
Reviewed By: uweigand
Differential Revision: https://reviews.llvm.org/D105067
Added:
clang/test/CodeGen/SystemZ/vec-abi-gnuattr-00.c
clang/test/CodeGen/SystemZ/vec-abi-gnuattr-01.c
clang/test/CodeGen/SystemZ/vec-abi-gnuattr-02.c
clang/test/CodeGen/SystemZ/vec-abi-gnuattr-03.c
clang/test/CodeGen/SystemZ/vec-abi-gnuattr-04.c
clang/test/CodeGen/SystemZ/vec-abi-gnuattr-05.c
clang/test/CodeGen/SystemZ/vec-abi-gnuattr-06.c
clang/test/CodeGen/SystemZ/vec-abi-gnuattr-07.c
clang/test/CodeGen/SystemZ/vec-abi-gnuattr-08.c
clang/test/CodeGen/SystemZ/vec-abi-gnuattr-09.c
clang/test/CodeGen/SystemZ/vec-abi-gnuattr-10.c
clang/test/CodeGen/SystemZ/vec-abi-gnuattr-11.c
clang/test/CodeGen/SystemZ/vec-abi-gnuattr-12.c
clang/test/CodeGen/SystemZ/vec-abi-gnuattr-13.c
clang/test/CodeGen/SystemZ/vec-abi-gnuattr-14.c
clang/test/CodeGen/SystemZ/vec-abi-gnuattr-15.c
clang/test/CodeGen/SystemZ/vec-abi-gnuattr-16.c
clang/test/CodeGen/SystemZ/vec-abi-gnuattr-17.c
clang/test/CodeGen/SystemZ/vec-abi-gnuattr-18.c
clang/test/CodeGen/SystemZ/vec-abi-gnuattr-19.c
clang/test/CodeGen/SystemZ/vec-abi-gnuattr-20.cpp
clang/test/CodeGen/SystemZ/vec-abi-gnuattr-21.c
clang/test/CodeGen/SystemZ/vec-abi-gnuattr-22.c
clang/test/CodeGen/SystemZ/vec-abi-gnuattr-23.c
clang/test/CodeGen/SystemZ/vec-abi-gnuattr-24.c
llvm/test/MC/SystemZ/gnu-attributes.s
Modified:
clang/lib/CodeGen/CodeGenTypes.h
clang/lib/CodeGen/TargetInfo.cpp
llvm/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp
llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
llvm/lib/Target/SystemZ/SystemZAsmPrinter.h
Removed:
################################################################################
diff --git a/clang/lib/CodeGen/CodeGenTypes.h b/clang/lib/CodeGen/CodeGenTypes.h
index 69acf605dc36b..e76fda95513f6 100644
--- a/clang/lib/CodeGen/CodeGenTypes.h
+++ b/clang/lib/CodeGen/CodeGenTypes.h
@@ -109,6 +109,7 @@ class CodeGenTypes {
const llvm::DataLayout &getDataLayout() const {
return TheModule.getDataLayout();
}
+ CodeGenModule &getCGM() const { return CGM; }
ASTContext &getContext() const { return Context; }
const ABIInfo &getABIInfo() const { return TheABIInfo; }
const TargetInfo &getTarget() const { return Target; }
diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp
index 8be0625120ec8..bcb0e7b085743 100644
--- a/clang/lib/CodeGen/TargetInfo.cpp
+++ b/clang/lib/CodeGen/TargetInfo.cpp
@@ -7402,18 +7402,20 @@ class SystemZABIInfo : public ABIInfo {
ABIArgInfo classifyReturnType(QualType RetTy) const;
ABIArgInfo classifyArgumentType(QualType ArgTy) const;
- void computeInfo(CGFunctionInfo &FI) const override {
- if (!getCXXABI().classifyReturnType(FI))
- FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
- for (auto &I : FI.arguments())
- I.info = classifyArgumentType(I.type);
- }
-
+ void computeInfo(CGFunctionInfo &FI) const override;
Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
QualType Ty) const override;
};
class SystemZTargetCodeGenInfo : public TargetCodeGenInfo {
+ // These are used for speeding up the search for a visible vector ABI.
+ mutable bool HasVisibleVecABIFlag = false;
+ mutable std::set<const Type *> SeenTypes;
+
+ // Returns true (the first time) if Ty is or found to make use of a vector
+ // type (e.g. as a function argument).
+ bool isVectorTypeBased(const Type *Ty) const;
+
public:
SystemZTargetCodeGenInfo(CodeGenTypes &CGT, bool HasVector, bool SoftFloatABI)
: TargetCodeGenInfo(
@@ -7422,6 +7424,37 @@ class SystemZTargetCodeGenInfo : public TargetCodeGenInfo {
std::make_unique<SwiftABIInfo>(CGT, /*SwiftErrorInRegister=*/false);
}
+ // The vector ABI is
diff erent when the vector facility is present and when
+ // a module e.g. defines an externally visible vector variable, a flag
+ // indicating a visible vector ABI is added. Eventually this will result in
+ // a GNU attribute indicating the vector ABI of the module. Ty is the type
+ // of a variable or function parameter that is globally visible.
+ void handleExternallyVisibleObjABI(const Type *Ty,
+ CodeGen::CodeGenModule &M) const {
+ if (!HasVisibleVecABIFlag && isVectorTypeBased(Ty)) {
+ M.getModule().addModuleFlag(llvm::Module::Warning,
+ "s390x-visible-vector-ABI", 1);
+ HasVisibleVecABIFlag = true;
+ }
+ }
+
+ void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
+ CodeGen::CodeGenModule &M) const override {
+ if (!D)
+ return;
+
+ // Check if the vector ABI becomes visible by an externally visible
+ // variable or function.
+ if (const auto *VD = dyn_cast<VarDecl>(D)) {
+ if (VD->isExternallyVisible())
+ handleExternallyVisibleObjABI(VD->getType().getTypePtr(), M);
+ }
+ else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ if (FD->isExternallyVisible())
+ handleExternallyVisibleObjABI(FD->getType().getTypePtr(), M);
+ }
+ }
+
llvm::Value *testFPKind(llvm::Value *V, unsigned BuiltinID,
CGBuilderTy &Builder,
CodeGenModule &CGM) const override {
@@ -7579,6 +7612,9 @@ Address SystemZABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
// Every non-vector argument occupies 8 bytes and is passed by preference
// in either GPRs or FPRs. Vector arguments occupy 8 or 16 bytes and are
// always passed on the stack.
+ const SystemZTargetCodeGenInfo &SZCGI =
+ static_cast<const SystemZTargetCodeGenInfo &>(
+ CGT.getCGM().getTargetCodeGenInfo());
Ty = getContext().getCanonicalType(Ty);
auto TyInfo = getContext().getTypeInfoInChars(Ty);
llvm::Type *ArgTy = CGF.ConvertTypeForMem(Ty);
@@ -7589,6 +7625,7 @@ Address SystemZABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr,
bool IsVector = false;
CharUnits UnpaddedSize;
CharUnits DirectAlign;
+ SZCGI.handleExternallyVisibleObjABI(Ty.getTypePtr(), CGT.getCGM());
if (IsIndirect) {
DirectTy = llvm::PointerType::getUnqual(DirectTy);
UnpaddedSize = DirectAlign = CharUnits::fromQuantity(8);
@@ -7783,6 +7820,51 @@ ABIArgInfo SystemZABIInfo::classifyArgumentType(QualType Ty) const {
return ABIArgInfo::getDirect(nullptr);
}
+void SystemZABIInfo::computeInfo(CGFunctionInfo &FI) const {
+ const SystemZTargetCodeGenInfo &SZCGI =
+ static_cast<const SystemZTargetCodeGenInfo &>(
+ CGT.getCGM().getTargetCodeGenInfo());
+ if (!getCXXABI().classifyReturnType(FI))
+ FI.getReturnInfo() = classifyReturnType(FI.getReturnType());
+ unsigned Idx = 0;
+ for (auto &I : FI.arguments()) {
+ I.info = classifyArgumentType(I.type);
+ if (FI.isVariadic() && Idx++ >= FI.getNumRequiredArgs())
+ // Check if a vararg vector argument is passed, in which case the
+ // vector ABI becomes visible as the va_list could be passed on to
+ // other functions.
+ SZCGI.handleExternallyVisibleObjABI(I.type.getTypePtr(), CGT.getCGM());
+ }
+}
+
+bool SystemZTargetCodeGenInfo::isVectorTypeBased(const Type *Ty) const {
+ while (Ty->isPointerType() || Ty->isArrayType())
+ Ty = Ty->getPointeeOrArrayElementType();
+ if (!SeenTypes.insert(Ty).second)
+ return false;
+ if (Ty->isVectorType())
+ return true;
+ if (const auto *RecordTy = Ty->getAs<RecordType>()) {
+ const RecordDecl *RD = RecordTy->getDecl();
+ if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD))
+ if (CXXRD->hasDefinition())
+ for (const auto &I : CXXRD->bases())
+ if (isVectorTypeBased(I.getType().getTypePtr()))
+ return true;
+ for (const auto *FD : RD->fields())
+ if (isVectorTypeBased(FD->getType().getTypePtr()))
+ return true;
+ }
+ if (const auto *FT = Ty->getAs<FunctionType>())
+ if (isVectorTypeBased(FT->getReturnType().getTypePtr()))
+ return true;
+ if (const FunctionProtoType *Proto = Ty->getAs<FunctionProtoType>())
+ for (auto ParamType : Proto->getParamTypes())
+ if (isVectorTypeBased(ParamType.getTypePtr()))
+ return true;
+ return false;
+}
+
//===----------------------------------------------------------------------===//
// MSP430 ABI Implementation
//===----------------------------------------------------------------------===//
diff --git a/clang/test/CodeGen/SystemZ/vec-abi-gnuattr-00.c b/clang/test/CodeGen/SystemZ/vec-abi-gnuattr-00.c
new file mode 100644
index 0000000000000..8f2569e1248cb
--- /dev/null
+++ b/clang/test/CodeGen/SystemZ/vec-abi-gnuattr-00.c
@@ -0,0 +1,28 @@
+// RUN: %clang_cc1 -triple s390x-ibm-linux -target-cpu arch10 -emit-llvm \
+// RUN: -fzvector -o - %s 2>&1 | FileCheck %s --check-prefix=MODFLAG
+//
+// Test the emission of the "s390x-visible-vector-ABI" module flag.
+
+// RUN: %clang_cc1 -triple s390x-ibm-linux -target-cpu arch10 -S \
+// RUN: -fzvector -o - %s 2>&1 | FileCheck %s --check-prefix=ARCH10-ASM
+// RUN: %clang_cc1 -triple s390x-ibm-linux -target-cpu arch13 -S \
+// RUN: -fzvector -o - %s 2>&1 | FileCheck %s --check-prefix=ARCH13-ASM
+//
+// Test the emission of a gnu attribute describing the vector ABI.
+
+// Call to external function with vector argument.
+
+typedef __attribute__((vector_size(16))) int v4i32;
+
+void bar(v4i32 Arg);
+
+void foo() {
+ v4i32 Var = {0, 0, 0, 0};
+ bar(Var);
+}
+
+//MODFLAG: !llvm.module.flags = !{!0, !1}
+//MODFLAG: !0 = !{i32 2, !"s390x-visible-vector-ABI", i32 1}
+
+//ARCH10-ASM: .gnu_attribute 8, 1
+//ARCH13-ASM: .gnu_attribute 8, 2
diff --git a/clang/test/CodeGen/SystemZ/vec-abi-gnuattr-01.c b/clang/test/CodeGen/SystemZ/vec-abi-gnuattr-01.c
new file mode 100644
index 0000000000000..5a33acd857e44
--- /dev/null
+++ b/clang/test/CodeGen/SystemZ/vec-abi-gnuattr-01.c
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -triple s390x-ibm-linux -target-cpu arch13 -emit-llvm \
+// RUN: -fzvector -o - %s 2>&1 | FileCheck %s
+//
+// Test the emission of the "s390x-visible-vector-ABI" module flag.
+
+// Call to external function with vector return value.
+
+typedef __attribute__((vector_size(16))) int v4i32;
+
+v4i32 bar(void);
+
+void foo(v4i32 *Dst) {
+ v4i32 Var = bar();
+ *Dst = Var;
+}
+
+//CHECK: !llvm.module.flags = !{!0, !1}
+//CHECK: !0 = !{i32 2, !"s390x-visible-vector-ABI", i32 1}
diff --git a/clang/test/CodeGen/SystemZ/vec-abi-gnuattr-02.c b/clang/test/CodeGen/SystemZ/vec-abi-gnuattr-02.c
new file mode 100644
index 0000000000000..8c44c14cc2459
--- /dev/null
+++ b/clang/test/CodeGen/SystemZ/vec-abi-gnuattr-02.c
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -triple s390x-ibm-linux -emit-llvm -fzvector -o - %s 2>&1 \
+// RUN: | FileCheck %s
+//
+// Test that the "s390x-visible-vector-ABI" module flag is not emitted.
+
+// Call to external function *without* vector argument.
+
+void bar(int arg);
+
+void foo() {
+ int Var = 0;
+ bar(Var);
+}
+
+//CHECK-NOT: !{i32 2, !"s390x-visible-vector-ABI", i32 1}
diff --git a/clang/test/CodeGen/SystemZ/vec-abi-gnuattr-03.c b/clang/test/CodeGen/SystemZ/vec-abi-gnuattr-03.c
new file mode 100644
index 0000000000000..caba77d206576
--- /dev/null
+++ b/clang/test/CodeGen/SystemZ/vec-abi-gnuattr-03.c
@@ -0,0 +1,17 @@
+// RUN: %clang_cc1 -triple s390x-ibm-linux -emit-llvm -fzvector -o - %s \
+// RUN: -Wno-undefined-internal 2>&1 | FileCheck %s
+//
+// Test that the "s390x-visible-vector-ABI" module flag is not emitted.
+
+// Calling *local* function with vector argument.
+
+typedef __attribute__((vector_size(16))) int v4i32;
+
+static void bar(v4i32 arg);
+
+void foo() {
+ v4i32 Var = {0, 0, 0, 0};
+ bar(Var);
+}
+
+//CHECK-NOT: !{i32 2, !"s390x-visible-vector-ABI", i32 1}
diff --git a/clang/test/CodeGen/SystemZ/vec-abi-gnuattr-04.c b/clang/test/CodeGen/SystemZ/vec-abi-gnuattr-04.c
new file mode 100644
index 0000000000000..70d31f36b22ab
--- /dev/null
+++ b/clang/test/CodeGen/SystemZ/vec-abi-gnuattr-04.c
@@ -0,0 +1,20 @@
+// RUN: %clang_cc1 -triple s390x-ibm-linux -emit-llvm -fzvector -o - %s 2>&1 \
+// RUN: | FileCheck %s
+//
+// Test the emission of the "s390x-visible-vector-ABI" module flag.
+
+// Call via global function pointer in internal function, with vector argument.
+
+typedef __attribute__((vector_size(16))) int v4i32;
+
+void (*bar)(v4i32 Arg);
+
+static void foo() {
+ v4i32 Var = {0, 0, 0, 0};
+ (*bar)(Var);
+}
+
+void fun() { foo(); }
+
+//CHECK: !llvm.module.flags = !{!0, !1}
+//CHECK: !0 = !{i32 2, !"s390x-visible-vector-ABI", i32 1}
diff --git a/clang/test/CodeGen/SystemZ/vec-abi-gnuattr-05.c b/clang/test/CodeGen/SystemZ/vec-abi-gnuattr-05.c
new file mode 100644
index 0000000000000..c19fd17a9684d
--- /dev/null
+++ b/clang/test/CodeGen/SystemZ/vec-abi-gnuattr-05.c
@@ -0,0 +1,20 @@
+// RUN: %clang_cc1 -triple s390x-ibm-linux -emit-llvm -fzvector -o - %s 2>&1 \
+// RUN: | FileCheck %s
+//
+// Test the emission of the "s390x-visible-vector-ABI" module flag.
+
+// Call via global function pointer in internal function, with vector return
+// value.
+
+typedef __attribute__((vector_size(16))) int v4i32;
+
+v4i32 (*bar)(int);
+
+static int foo() {
+ (*bar)(0)[0];
+}
+
+int fun() { return foo(); }
+
+//CHECK: !llvm.module.flags = !{!0, !1}
+//CHECK: !0 = !{i32 2, !"s390x-visible-vector-ABI", i32 1}
diff --git a/clang/test/CodeGen/SystemZ/vec-abi-gnuattr-06.c b/clang/test/CodeGen/SystemZ/vec-abi-gnuattr-06.c
new file mode 100644
index 0000000000000..b8cee2aeefb96
--- /dev/null
+++ b/clang/test/CodeGen/SystemZ/vec-abi-gnuattr-06.c
@@ -0,0 +1,21 @@
+// RUN: %clang_cc1 -triple s390x-ibm-linux -emit-llvm -fzvector -o - %s 2>&1 \
+// RUN: | FileCheck %s
+//
+// Test the emission of the "s390x-visible-vector-ABI" module flag.
+
+// Passing address of local function with vector arg to global function.
+
+typedef __attribute__((vector_size(16))) int v4i32;
+
+void GlobFun(v4i32 (*f)(v4i32));
+
+static v4i32 foo(v4i32 Arg) {
+ return Arg;
+}
+
+void fun() {
+ GlobFun(foo);
+}
+
+//CHECK: !llvm.module.flags = !{!0, !1}
+//CHECK: !0 = !{i32 2, !"s390x-visible-vector-ABI", i32 1}
diff --git a/clang/test/CodeGen/SystemZ/vec-abi-gnuattr-07.c b/clang/test/CodeGen/SystemZ/vec-abi-gnuattr-07.c
new file mode 100644
index 0000000000000..7c99e5f71e1ff
--- /dev/null
+++ b/clang/test/CodeGen/SystemZ/vec-abi-gnuattr-07.c
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -triple s390x-ibm-linux -emit-llvm -fzvector -o - %s 2>&1 \
+// RUN: | FileCheck %s
+//
+// Test the emission of the "s390x-visible-vector-ABI" module flag.
+
+// Passing an array of vectors.
+
+typedef __attribute__((vector_size(16))) int v4i32;
+
+void bar(v4i32 Arg[2]);
+
+void foo() {
+ v4i32 Var[2] = {{0, 0, 0, 0}, {0, 0, 0, 0}};
+ bar(Var);
+}
+
+//CHECK: !llvm.module.flags = !{!0, !1}
+//CHECK: !0 = !{i32 2, !"s390x-visible-vector-ABI", i32 1}
diff --git a/clang/test/CodeGen/SystemZ/vec-abi-gnuattr-08.c b/clang/test/CodeGen/SystemZ/vec-abi-gnuattr-08.c
new file mode 100644
index 0000000000000..38c7e86b0e24e
--- /dev/null
+++ b/clang/test/CodeGen/SystemZ/vec-abi-gnuattr-08.c
@@ -0,0 +1,23 @@
+// RUN: %clang_cc1 -triple s390x-ibm-linux -emit-llvm -fzvector -o - %s 2>&1 \
+// RUN: | FileCheck %s
+//
+// Test the emission of the "s390x-visible-vector-ABI" module flag.
+
+// Passing a struct containing a vector element.
+
+typedef __attribute__((vector_size(16))) int v4i32;
+
+struct S {
+ int A;
+ v4i32 B;
+};
+
+void bar(struct S Arg);
+
+void foo() {
+ struct S Var = {0, {0, 0, 0, 0}};
+ bar(Var);
+}
+
+//CHECK: !llvm.module.flags = !{!0, !1}
+//CHECK: !0 = !{i32 2, !"s390x-visible-vector-ABI", i32 1}
diff --git a/clang/test/CodeGen/SystemZ/vec-abi-gnuattr-09.c b/clang/test/CodeGen/SystemZ/vec-abi-gnuattr-09.c
new file mode 100644
index 0000000000000..e30e560a1f6cf
--- /dev/null
+++ b/clang/test/CodeGen/SystemZ/vec-abi-gnuattr-09.c
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -triple s390x-ibm-linux -emit-llvm -fzvector -o - %s 2>&1 \
+// RUN: | FileCheck %s
+//
+// Test the emission of the "s390x-visible-vector-ABI" module flag.
+
+// Call to vararg function with a vector argument.
+
+typedef __attribute__((vector_size(16))) int v4i32;
+
+void bar(int N, ...);
+
+void foo() {
+ v4i32 Var = {0, 0, 0, 0};
+ bar(0, Var);
+}
+
+//CHECK: !llvm.module.flags = !{!0, !1}
+//CHECK: !0 = !{i32 2, !"s390x-visible-vector-ABI", i32 1}
diff --git a/clang/test/CodeGen/SystemZ/vec-abi-gnuattr-10.c b/clang/test/CodeGen/SystemZ/vec-abi-gnuattr-10.c
new file mode 100644
index 0000000000000..f9729e0581db5
--- /dev/null
+++ b/clang/test/CodeGen/SystemZ/vec-abi-gnuattr-10.c
@@ -0,0 +1,17 @@
+// RUN: %clang_cc1 -triple s390x-ibm-linux -emit-llvm -fzvector -o - %s 2>&1 \
+// RUN: | FileCheck %s
+//
+// Test the emission of the "s390x-visible-vector-ABI" module flag.
+
+// Call to vararg function *without* any vector argument.
+
+typedef __attribute__((vector_size(16))) int v4i32;
+
+void bar(int N, ...);
+
+void foo() {
+ int Var = 0;
+ bar(0, Var);
+}
+
+//CHECK-NOT: !{i32 2, !"s390x-visible-vector-ABI", i32 1}
diff --git a/clang/test/CodeGen/SystemZ/vec-abi-gnuattr-11.c b/clang/test/CodeGen/SystemZ/vec-abi-gnuattr-11.c
new file mode 100644
index 0000000000000..fc6cf0f7e643e
--- /dev/null
+++ b/clang/test/CodeGen/SystemZ/vec-abi-gnuattr-11.c
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -triple s390x-ibm-linux -emit-llvm -fzvector -o - %s 2>&1 \
+// RUN: | FileCheck %s
+//
+// Test the emission of the "s390x-visible-vector-ABI" module flag.
+
+// Call to varargs function via global pointer to pointer to function.
+
+typedef __attribute__((vector_size(16))) int v4i32;
+
+void (**bar)(int N, ...);
+
+void foo() {
+ v4i32 Var = {0, 0, 0, 0};
+ (**bar)(0, Var);
+}
+
+//CHECK: !llvm.module.flags = !{!0, !1}
+//CHECK: !0 = !{i32 2, !"s390x-visible-vector-ABI", i32 1}
diff --git a/clang/test/CodeGen/SystemZ/vec-abi-gnuattr-12.c b/clang/test/CodeGen/SystemZ/vec-abi-gnuattr-12.c
new file mode 100644
index 0000000000000..cd7c89b72ea2d
--- /dev/null
+++ b/clang/test/CodeGen/SystemZ/vec-abi-gnuattr-12.c
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -triple s390x-ibm-linux -emit-llvm -fzvector -o - %s 2>&1 \
+// RUN: | FileCheck %s
+//
+// Test the emission of the "s390x-visible-vector-ABI" module flag.
+
+// Passing vector argument to varargs function via local function pointer.
+
+typedef __attribute__((vector_size(16))) int v4i32;
+
+void foo(void (*bar)(int, ...)) {
+ v4i32 Var = {0, 0, 0, 0};
+ (*bar)(0, Var);
+}
+
+//CHECK: !llvm.module.flags = !{!0, !1}
+//CHECK: !0 = !{i32 2, !"s390x-visible-vector-ABI", i32 1}
diff --git a/clang/test/CodeGen/SystemZ/vec-abi-gnuattr-13.c b/clang/test/CodeGen/SystemZ/vec-abi-gnuattr-13.c
new file mode 100644
index 0000000000000..8fbd2e918db3c
--- /dev/null
+++ b/clang/test/CodeGen/SystemZ/vec-abi-gnuattr-13.c
@@ -0,0 +1,22 @@
+// RUN: %clang_cc1 -triple s390x-ibm-linux -emit-llvm -fzvector -o - %s \
+// RUN: -Wno-undefined-internal 2>&1 | FileCheck %s
+//
+// Test the emission of the "s390x-visible-vector-ABI" module flag.
+
+// Passing vector argument to varargs function between static functions. This
+// also potentially exposes the vector ABI as the va_list may be passed on to
+// another (global) function.
+
+typedef __attribute__((vector_size(16))) int v4i32;
+
+static int bar(int N, ...);
+
+static void foo() {
+ v4i32 Var = {0, 0, 0, 0};
+ bar(0, Var);
+}
+
+void fun() { foo(); }
+
+//CHECK: !llvm.module.flags = !{!0, !1}
+//CHECK: !0 = !{i32 2, !"s390x-visible-vector-ABI", i32 1}
diff --git a/clang/test/CodeGen/SystemZ/vec-abi-gnuattr-14.c b/clang/test/CodeGen/SystemZ/vec-abi-gnuattr-14.c
new file mode 100644
index 0000000000000..795807f5b92a0
--- /dev/null
+++ b/clang/test/CodeGen/SystemZ/vec-abi-gnuattr-14.c
@@ -0,0 +1,20 @@
+// RUN: %clang_cc1 -triple s390x-ibm-linux -emit-llvm -fzvector -o - %s 2>&1 \
+// RUN: | FileCheck %s
+//
+// Test the emission of the "s390x-visible-vector-ABI" module flag.
+
+// Use of va_arg with a vector type exposes the vector ABI.
+
+#include <stdarg.h>
+
+static int bar(va_list vl) {
+ return va_arg(vl, vector int)[0];
+}
+
+int foo(va_list vl) {
+ return bar(vl);
+}
+
+//CHECK: !llvm.module.flags = !{!0, !1}
+//CHECK: !0 = !{i32 2, !"s390x-visible-vector-ABI", i32 1}
+
diff --git a/clang/test/CodeGen/SystemZ/vec-abi-gnuattr-15.c b/clang/test/CodeGen/SystemZ/vec-abi-gnuattr-15.c
new file mode 100644
index 0000000000000..2c1c40d119ee6
--- /dev/null
+++ b/clang/test/CodeGen/SystemZ/vec-abi-gnuattr-15.c
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -triple s390x-ibm-linux -emit-llvm -fzvector -o - %s 2>&1 \
+// RUN: | FileCheck %s
+//
+// Test the emission of the "s390x-visible-vector-ABI" module flag.
+
+// Defining globally visible function with vector argument.
+
+typedef __attribute__((vector_size(16))) int v4i32;
+
+void fun(v4i32 Arg, v4i32 *Dst) {
+ *Dst = Arg;
+}
+
+//CHECK: !llvm.module.flags = !{!0, !1}
+//CHECK: !0 = !{i32 2, !"s390x-visible-vector-ABI", i32 1}
diff --git a/clang/test/CodeGen/SystemZ/vec-abi-gnuattr-16.c b/clang/test/CodeGen/SystemZ/vec-abi-gnuattr-16.c
new file mode 100644
index 0000000000000..66e21e44d2d7e
--- /dev/null
+++ b/clang/test/CodeGen/SystemZ/vec-abi-gnuattr-16.c
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -triple s390x-ibm-linux -emit-llvm -fzvector -o - %s 2>&1 \
+// RUN: | FileCheck %s
+//
+// Test the emission of the "s390x-visible-vector-ABI" module flag.
+
+// Defining globally visible function with vector return value.
+
+typedef __attribute__((vector_size(16))) int v4i32;
+
+v4i32 fun(int v) {
+ v4i32 Val = {v, v, v, v};
+ return Val;
+}
+
+//CHECK: !llvm.module.flags = !{!0, !1}
+//CHECK: !0 = !{i32 2, !"s390x-visible-vector-ABI", i32 1}
diff --git a/clang/test/CodeGen/SystemZ/vec-abi-gnuattr-17.c b/clang/test/CodeGen/SystemZ/vec-abi-gnuattr-17.c
new file mode 100644
index 0000000000000..192fe89590aee
--- /dev/null
+++ b/clang/test/CodeGen/SystemZ/vec-abi-gnuattr-17.c
@@ -0,0 +1,13 @@
+// RUN: %clang_cc1 -triple s390x-ibm-linux -emit-llvm -fzvector -o - %s 2>&1 \
+// RUN: | FileCheck %s
+//
+// Test the emission of the "s390x-visible-vector-ABI" module flag.
+
+// Globally visible vector variable.
+
+typedef __attribute__((vector_size(16))) int v4i32;
+
+v4i32 Var;
+
+//CHECK: !llvm.module.flags = !{!0, !1}
+//CHECK: !0 = !{i32 2, !"s390x-visible-vector-ABI", i32 1}
diff --git a/clang/test/CodeGen/SystemZ/vec-abi-gnuattr-18.c b/clang/test/CodeGen/SystemZ/vec-abi-gnuattr-18.c
new file mode 100644
index 0000000000000..ced54b02d1576
--- /dev/null
+++ b/clang/test/CodeGen/SystemZ/vec-abi-gnuattr-18.c
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -triple s390x-ibm-linux -emit-llvm -fzvector -o - %s 2>&1 \
+// RUN: | FileCheck %s
+//
+// Test the emission of the "s390x-visible-vector-ABI" module flag.
+
+// Globally visible struct array with vector element.
+
+typedef __attribute__((vector_size(16))) int v4i32;
+
+struct S {
+ int i;
+ v4i32 Var;
+};
+
+struct S Arr[16];
+
+//CHECK: !llvm.module.flags = !{!0, !1}
+//CHECK: !0 = !{i32 2, !"s390x-visible-vector-ABI", i32 1}
diff --git a/clang/test/CodeGen/SystemZ/vec-abi-gnuattr-19.c b/clang/test/CodeGen/SystemZ/vec-abi-gnuattr-19.c
new file mode 100644
index 0000000000000..8065121434c87
--- /dev/null
+++ b/clang/test/CodeGen/SystemZ/vec-abi-gnuattr-19.c
@@ -0,0 +1,19 @@
+// RUN: %clang_cc1 -triple s390x-ibm-linux -emit-llvm -fzvector -o - %s 2>&1 \
+// RUN: | FileCheck %s
+//
+// Test the emission of the "s390x-visible-vector-ABI" module flag.
+
+// Globally visible struct with function pointer array member with vector
+// return values.
+
+typedef __attribute__((vector_size(16))) int v4i32;
+
+struct S {
+ int i;
+ v4i32 (*funcptr[4])(int);
+};
+
+struct S Arr[16];
+
+//CHECK: !llvm.module.flags = !{!0, !1}
+//CHECK: !0 = !{i32 2, !"s390x-visible-vector-ABI", i32 1}
diff --git a/clang/test/CodeGen/SystemZ/vec-abi-gnuattr-20.cpp b/clang/test/CodeGen/SystemZ/vec-abi-gnuattr-20.cpp
new file mode 100644
index 0000000000000..66c2ba23fede9
--- /dev/null
+++ b/clang/test/CodeGen/SystemZ/vec-abi-gnuattr-20.cpp
@@ -0,0 +1,28 @@
+// RUN: %clang_cc1 -triple s390x-ibm-linux -emit-llvm -fzvector -o - %s 2>&1 \
+// RUN: | FileCheck %s
+//
+// Test the emission of the "s390x-visible-vector-ABI" module flag.
+
+// Globally visible C++ object with vector member.
+
+typedef __attribute__((vector_size(16))) int v4i32;
+
+class Base {
+protected:
+ v4i32 v;
+};
+
+class C : public Base {
+ int i;
+
+public:
+ C() {
+ i = 1;
+ v = {1, 2, 3, 4};
+ }
+};
+
+C Obj;
+
+//CHECK: !llvm.module.flags = !{!0, !1}
+//CHECK: !0 = !{i32 2, !"s390x-visible-vector-ABI", i32 1}
diff --git a/clang/test/CodeGen/SystemZ/vec-abi-gnuattr-21.c b/clang/test/CodeGen/SystemZ/vec-abi-gnuattr-21.c
new file mode 100644
index 0000000000000..5589d6cddfe48
--- /dev/null
+++ b/clang/test/CodeGen/SystemZ/vec-abi-gnuattr-21.c
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -triple s390x-ibm-linux -emit-llvm -fzvector -o - %s 2>&1 \
+// RUN: | FileCheck %s
+//
+// Test the emission of the "s390x-visible-vector-ABI" module flag.
+
+// Globally visible struct with a zero (variable) length array of vector values.
+
+typedef __attribute__((vector_size(16))) int v4i32;
+
+struct S {
+ int A;
+ v4i32 B[0];
+} s;
+
+//CHECK: !llvm.module.flags = !{!0, !1}
+//CHECK: !0 = !{i32 2, !"s390x-visible-vector-ABI", i32 1}
diff --git a/clang/test/CodeGen/SystemZ/vec-abi-gnuattr-22.c b/clang/test/CodeGen/SystemZ/vec-abi-gnuattr-22.c
new file mode 100644
index 0000000000000..8a0ff9c5f8263
--- /dev/null
+++ b/clang/test/CodeGen/SystemZ/vec-abi-gnuattr-22.c
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -triple s390x-ibm-linux -emit-llvm -fzvector -o - %s 2>&1 \
+// RUN: | FileCheck %s
+//
+// Test the emission of the "s390x-visible-vector-ABI" module flag.
+
+// Globally visible pointer to a vector variable. An unused pointer doesn't
+// really expose the vector ABI, but as there seems to be no easy way to
+// check if a pointer is dereferenced or not (when compiling C++ at least),
+// this is treated conservatively.
+
+typedef __attribute__((vector_size(16))) int v4i32;
+
+v4i32 *VecPtr;
+
+//CHECK: !llvm.module.flags = !{!0, !1}
+//CHECK: !0 = !{i32 2, !"s390x-visible-vector-ABI", i32 1}
diff --git a/clang/test/CodeGen/SystemZ/vec-abi-gnuattr-23.c b/clang/test/CodeGen/SystemZ/vec-abi-gnuattr-23.c
new file mode 100644
index 0000000000000..3e9ffbb563522
--- /dev/null
+++ b/clang/test/CodeGen/SystemZ/vec-abi-gnuattr-23.c
@@ -0,0 +1,27 @@
+// RUN: %clang_cc1 -triple s390x-ibm-linux -emit-llvm -fzvector -o - %s 2>&1 \
+// RUN: | FileCheck %s
+//
+// Test the emission of the "s390x-visible-vector-ABI" module flag.
+
+// Using external vector variable (twice to test that the module flag is only
+// added once, which would be an error).
+
+typedef __attribute__((vector_size(16))) int v4i32;
+
+extern v4i32 Var;
+
+static void foo() {
+ v4i32 Loc = {1, 1, 1, 1};
+ Var = Var + Loc;
+}
+
+static void bar() {
+ v4i32 Loc = {1, 2, 3, 4};
+ Var = Var + Loc;
+}
+
+void fun1() { foo(); }
+void fun2() { bar(); }
+
+//CHECK: !llvm.module.flags = !{!0, !1}
+//CHECK: !0 = !{i32 2, !"s390x-visible-vector-ABI", i32 1}
diff --git a/clang/test/CodeGen/SystemZ/vec-abi-gnuattr-24.c b/clang/test/CodeGen/SystemZ/vec-abi-gnuattr-24.c
new file mode 100644
index 0000000000000..a18fe924dc2d9
--- /dev/null
+++ b/clang/test/CodeGen/SystemZ/vec-abi-gnuattr-24.c
@@ -0,0 +1,37 @@
+// RUN: %clang_cc1 -triple s390x-ibm-linux -emit-llvm -fzvector -o - %s 2>&1 \
+// RUN: | FileCheck %s
+//
+// Test that the "s390x-visible-vector-ABI" module flag is not emitted.
+
+// Use of va_arg with a scalar type.
+#include <stdarg.h>
+int fun0(va_list vl) {
+ return va_arg(vl, int);
+}
+
+typedef __attribute__((vector_size(16))) int v4i32;
+
+// Declaring unused global function with vector argument and return values;
+v4i32 globfun(v4i32 Arg);
+
+// Declaring global scalar variable used below.
+int GlobVal;
+
+// Declaring extern global scalar variable used below.
+extern int GlobExtVar;
+
+// Local vector variable used below.
+static v4i32 Var;
+
+// Local function with vector argument and return values;
+static v4i32 foo(v4i32 Arg) {
+ Var = Var + Arg;
+ return Var;
+}
+
+int fun1() {
+ v4i32 V = {1, 2, 3, 4};
+ return foo(V)[0] + GlobVal + GlobExtVar;
+}
+
+//CHECK-NOT: !{i32 2, !"s390x-visible-vector-ABI", i32 1}
diff --git a/llvm/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp b/llvm/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp
index 60e1b05a6d1ab..92186b7538286 100644
--- a/llvm/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp
+++ b/llvm/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp
@@ -432,6 +432,7 @@ class SystemZAsmParser : public MCTargetAsmParser {
bool ParseDirectiveInsn(SMLoc L);
bool ParseDirectiveMachine(SMLoc L);
+ bool ParseGNUAttribute(SMLoc L);
OperandMatchResultTy parseAddress(OperandVector &Operands,
MemoryKind MemKind,
@@ -1224,6 +1225,8 @@ bool SystemZAsmParser::ParseDirective(AsmToken DirectiveID) {
return ParseDirectiveInsn(DirectiveID.getLoc());
if (IDVal == ".machine")
return ParseDirectiveMachine(DirectiveID.getLoc());
+ if (IDVal.startswith(".gnu_attribute"))
+ return ParseGNUAttribute(DirectiveID.getLoc());
return true;
}
@@ -1358,6 +1361,24 @@ bool SystemZAsmParser::ParseDirectiveMachine(SMLoc L) {
return false;
}
+bool SystemZAsmParser::ParseGNUAttribute(SMLoc L) {
+ int64_t Tag;
+ int64_t IntegerValue;
+ if (!Parser.parseGNUAttribute(L, Tag, IntegerValue))
+ return false;
+
+ // Tag_GNU_S390_ABI_Vector tag is '8' and can be 0, 1, or 2.
+ if (Tag != 8 || (IntegerValue < 0 || IntegerValue > 2)) {
+ Error(Parser.getTok().getLoc(),
+ "Unrecognized .gnu_attribute tag/value pair.");
+ return false;
+ }
+
+ Parser.getStreamer().emitGNUAttribute(Tag, IntegerValue);
+
+ return true;
+}
+
bool SystemZAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
SMLoc &EndLoc, bool RestoreOnFailure) {
Register Reg;
diff --git a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
index d72a58057b941..20c666a643407 100644
--- a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
@@ -759,6 +759,17 @@ void SystemZAsmPrinter::LowerPATCHPOINT(const MachineInstr &MI,
getSubtargetInfo());
}
+// The *alignment* of 128-bit vector types is
diff erent between the software
+// and hardware vector ABIs. If the there is an externally visible use of a
+// vector type in the module it should be annotated with an attribute.
+void SystemZAsmPrinter::emitAttributes(Module &M) {
+ if (M.getModuleFlag("s390x-visible-vector-ABI")) {
+ bool HasVectorFeature =
+ TM.getMCSubtargetInfo()->getFeatureBits()[SystemZ::FeatureVector];
+ OutStreamer->emitGNUAttribute(8, HasVectorFeature ? 2 : 1);
+ }
+}
+
// Convert a SystemZ-specific constant pool modifier into the associated
// MCSymbolRefExpr variant kind.
static MCSymbolRefExpr::VariantKind
@@ -859,6 +870,10 @@ bool SystemZAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
return false;
}
+void SystemZAsmPrinter::emitEndOfAsmFile(Module &M) {
+ emitAttributes(M);
+}
+
void SystemZAsmPrinter::emitFunctionBodyEnd() {
if (TM.getTargetTriple().isOSzOS()) {
// Emit symbol for the end of function if the z/OS target streamer
diff --git a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.h b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.h
index 044dfbcd3316a..c99fcda6dcc52 100644
--- a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.h
+++ b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.h
@@ -57,6 +57,7 @@ class LLVM_LIBRARY_VISIBILITY SystemZAsmPrinter : public AsmPrinter {
StringRef getPassName() const override { return "SystemZ Assembly Printer"; }
void emitInstruction(const MachineInstr *MI) override;
void emitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) override;
+ void emitEndOfAsmFile(Module &M) override;
bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
const char *ExtraCode, raw_ostream &OS) override;
bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
@@ -74,6 +75,7 @@ class LLVM_LIBRARY_VISIBILITY SystemZAsmPrinter : public AsmPrinter {
void LowerFENTRY_CALL(const MachineInstr &MI, SystemZMCInstLower &MCIL);
void LowerSTACKMAP(const MachineInstr &MI);
void LowerPATCHPOINT(const MachineInstr &MI, SystemZMCInstLower &Lower);
+ void emitAttributes(Module &M);
};
} // end namespace llvm
diff --git a/llvm/test/MC/SystemZ/gnu-attributes.s b/llvm/test/MC/SystemZ/gnu-attributes.s
new file mode 100644
index 0000000000000..fc62062b7c50c
--- /dev/null
+++ b/llvm/test/MC/SystemZ/gnu-attributes.s
@@ -0,0 +1,17 @@
+# RUN: llvm-mc -triple s390x-linux-gnu -filetype=asm %s | \
+# RUN: FileCheck %s --check-prefix=ASM
+# RUN: llvm-mc -triple s390x-linux-gnu -filetype=obj %s | \
+# RUN: llvm-objdump --mcpu=z14 -D - | FileCheck %s --check-prefix=OBJ
+
+#ASM: .text
+#ASM: .gnu_attribute 8, 2
+
+#OBJ: 0000000000000000 <.gnu.attributes>:
+#OBJ: 0: 41 00 00 00
+#OBJ: 4: 0f 67
+#OBJ: 6: 6e 75 00 01
+#OBJ: a: 00 00
+#OBJ: c: 00 07
+#OBJ: e: 08 02
+
+ .gnu_attribute 8, 2
More information about the cfe-commits
mailing list