[clang] [llvm] [SystemZ][z/OS] __ptr32 support for z/OS (PR #101696)
Abhina Sree via cfe-commits
cfe-commits at lists.llvm.org
Fri Aug 2 08:46:27 PDT 2024
https://github.com/abhina-sree updated https://github.com/llvm/llvm-project/pull/101696
>From 0246fe8e7f8d93ad3e37ff770a18bd1928552b5f Mon Sep 17 00:00:00 2001
From: Abhina Sreeskantharajan <Abhina.Sreeskantharajan at ibm.com>
Date: Fri, 2 Aug 2024 11:44:44 -0400
Subject: [PATCH] __ptr32 support for z/OS
---
clang/include/clang/Basic/LangOptions.def | 1 +
clang/include/clang/Basic/TokenKinds.def | 3 +-
clang/include/clang/Driver/Options.td | 4 +
clang/lib/AST/ItaniumMangle.cpp | 8 +-
clang/lib/Basic/IdentifierTable.cpp | 18 +-
clang/lib/Basic/Targets/SystemZ.h | 40 ++-
clang/lib/Frontend/CompilerInvocation.cpp | 11 +
clang/lib/Sema/SemaType.cpp | 3 +-
.../SystemZ/zos-mixed-ptr-sizes-definitions.c | 54 ++++
.../SystemZ/zos-mixed-ptr-sizes-malloc.c | 84 +++++
.../SystemZ/zos-mixed-ptr-sizes-sizeof.c | 94 ++++++
.../CodeGen/SystemZ/zos-mixed-ptr-sizes.c | 298 ++++++++++++++++++
clang/test/CodeGen/target-data.c | 2 +-
.../zos-mangle-ptr-size-address-space.cpp | 17 +
clang/test/Sema/ZOSExtensions.cpp | 119 +++++++
clang/test/Sema/attr-print-zos.c | 31 ++
.../Target/SystemZ/SystemZTargetMachine.cpp | 8 +
17 files changed, 785 insertions(+), 10 deletions(-)
create mode 100644 clang/test/CodeGen/SystemZ/zos-mixed-ptr-sizes-definitions.c
create mode 100644 clang/test/CodeGen/SystemZ/zos-mixed-ptr-sizes-malloc.c
create mode 100644 clang/test/CodeGen/SystemZ/zos-mixed-ptr-sizes-sizeof.c
create mode 100644 clang/test/CodeGen/SystemZ/zos-mixed-ptr-sizes.c
create mode 100644 clang/test/CodeGenCXX/zos-mangle-ptr-size-address-space.cpp
create mode 100644 clang/test/Sema/ZOSExtensions.cpp
create mode 100644 clang/test/Sema/attr-print-zos.c
diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def
index 0035092ce0d863..c276c98d57db7b 100644
--- a/clang/include/clang/Basic/LangOptions.def
+++ b/clang/include/clang/Basic/LangOptions.def
@@ -91,6 +91,7 @@ LANGOPT(C2y , 1, 0, "C2y")
LANGOPT(MSVCCompat , 1, 0, "Microsoft Visual C++ full compatibility mode")
LANGOPT(Kernel , 1, 0, "Kernel mode")
LANGOPT(MicrosoftExt , 1, 0, "Microsoft C++ extensions")
+LANGOPT(ZOSExt , 1, 0, "z/OS extensions")
LANGOPT(AsmBlocks , 1, 0, "Microsoft inline asm blocks")
LANGOPT(Borland , 1, 0, "Borland extensions")
LANGOPT(CPlusPlus , 1, 0, "C++")
diff --git a/clang/include/clang/Basic/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def
index 7e638dc1ddcdba..9cb8a34ac15575 100644
--- a/clang/include/clang/Basic/TokenKinds.def
+++ b/clang/include/clang/Basic/TokenKinds.def
@@ -292,6 +292,7 @@ PUNCTUATOR(caretcaret, "^^")
// CHAR8SUPPORT - This is a keyword if 'char8_t' is a built-in type
// KEYFIXEDPOINT - This is a keyword according to the N1169 fixed point
// extension.
+// KEYZOS - This is a keyword in C/C++ on z/OS
//
KEYWORD(auto , KEYALL)
KEYWORD(break , KEYALL)
@@ -722,7 +723,7 @@ KEYWORD(__funcref , KEYALL)
// Microsoft extensions which should be disabled in strict conformance mode
KEYWORD(__ptr64 , KEYMS)
-KEYWORD(__ptr32 , KEYMS)
+KEYWORD(__ptr32 , KEYMS | KEYZOS)
KEYWORD(__sptr , KEYMS)
KEYWORD(__uptr , KEYMS)
KEYWORD(__w64 , KEYMS)
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index f690467bb82cd3..00b8f7c5635e2c 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -3065,6 +3065,10 @@ dll version.}]>;
def fms_omit_default_lib : Joined<["-"], "fms-omit-default-lib">,
Group<f_Group>, Flags<[]>,
Visibility<[ClangOption, CLOption]>;
+def fzos_extensions : Flag<["-"], "fzos-extensions">, Group<f_Group>, Visibility<[ClangOption, CC1Option]>,
+ HelpText<"Accept some non-standard constructs supported by the z/OS compiler">;
+def fno_zos_extensions : Flag<["-"], "fno-zos-extensions">, Group<f_Group>, Visibility<[ClangOption, CC1Option]>,
+ HelpText<"Do not accept non-standard constructs supported by the z/OS compiler">;
defm delayed_template_parsing : BoolFOption<"delayed-template-parsing",
LangOpts<"DelayedTemplateParsing">, DefaultFalse,
PosFlag<SetTrue, [], [ClangOption, CC1Option],
diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp
index ead5da4e90f2f0..65f30cd2b012b7 100644
--- a/clang/lib/AST/ItaniumMangle.cpp
+++ b/clang/lib/AST/ItaniumMangle.cpp
@@ -2727,6 +2727,8 @@ void CXXNameMangler::mangleQualifiers(Qualifiers Quals, const DependentAddressSp
// <type> ::= U <OpenCL-addrspace>
// <type> ::= U <CUDA-addrspace>
+ llvm::Triple Triple = getASTContext().getTargetInfo().getTriple();
+
SmallString<64> ASString;
LangAS AS = Quals.getAddressSpace();
@@ -2795,7 +2797,11 @@ void CXXNameMangler::mangleQualifiers(Qualifiers Quals, const DependentAddressSp
ASString = "ptr32_sptr";
break;
case LangAS::ptr32_uptr:
- ASString = "ptr32_uptr";
+ // For z/OS, there are no special mangling rules applied to the ptr32
+ // qualifier. Ex: void foo(int * __ptr32 p) -> _Z3f2Pi. The mangling for
+ // "p" is treated the same as a regular integer pointer.
+ if (!Triple.isOSzOS())
+ ASString = "ptr32_uptr";
break;
case LangAS::ptr64:
ASString = "ptr64";
diff --git a/clang/lib/Basic/IdentifierTable.cpp b/clang/lib/Basic/IdentifierTable.cpp
index 4f7ccaf4021d63..1ef07d41839c7a 100644
--- a/clang/lib/Basic/IdentifierTable.cpp
+++ b/clang/lib/Basic/IdentifierTable.cpp
@@ -107,12 +107,14 @@ namespace {
KEYMSCOMPAT = 0x400000,
KEYSYCL = 0x800000,
KEYCUDA = 0x1000000,
- KEYHLSL = 0x2000000,
- KEYFIXEDPOINT = 0x4000000,
+ KEYZOS = 0x2000000,
+ KEYNOZOS = 0x4000000,
+ KEYHLSL = 0x8000000,
+ KEYFIXEDPOINT = 0x10000000,
KEYMAX = KEYFIXEDPOINT, // The maximum key
KEYALLCXX = KEYCXX | KEYCXX11 | KEYCXX20,
- KEYALL = (KEYMAX | (KEYMAX-1)) & ~KEYNOMS18 &
- ~KEYNOOPENCL // KEYNOMS18 and KEYNOOPENCL are used to exclude.
+ KEYALL = (KEYMAX | (KEYMAX-1)) & ~KEYNOMS18 & ~KEYNOOPENCL &
+ ~KEYNOZOS // KEYNOMS18, KEYNOOPENCL, KEYNOZOS are excluded.
};
/// How a keyword is treated in the selected standard. This enum is ordered
@@ -199,6 +201,8 @@ static KeywordStatus getKeywordStatusHelper(const LangOptions &LangOpts,
return LangOpts.isSYCL() ? KS_Enabled : KS_Unknown;
case KEYCUDA:
return LangOpts.CUDA ? KS_Enabled : KS_Unknown;
+ case KEYZOS:
+ return LangOpts.ZOSExt ? KS_Enabled : KS_Unknown;
case KEYHLSL:
return LangOpts.HLSL ? KS_Enabled : KS_Unknown;
case KEYNOCXX:
@@ -211,6 +215,9 @@ static KeywordStatus getKeywordStatusHelper(const LangOptions &LangOpts,
case KEYNOMS18:
// The disable behavior for this is handled in getKeywordStatus.
return KS_Unknown;
+ case KEYNOZOS:
+ // The disable behavior for this is handled in getKeywordStatus.
+ return KS_Unknown;
case KEYFIXEDPOINT:
return LangOpts.FixedPoint ? KS_Enabled : KS_Disabled;
default:
@@ -230,7 +237,8 @@ static KeywordStatus getKeywordStatus(const LangOptions &LangOpts,
if (LangOpts.MSVCCompat && (Flags & KEYNOMS18) &&
!LangOpts.isCompatibleWithMSVC(LangOptions::MSVC2015))
return KS_Disabled;
-
+ if (LangOpts.ZOSExt && (Flags & KEYNOZOS))
+ return KS_Disabled;
KeywordStatus CurStatus = KS_Unknown;
while (Flags != 0) {
diff --git a/clang/lib/Basic/Targets/SystemZ.h b/clang/lib/Basic/Targets/SystemZ.h
index 3bc6f2c1d30832..7390f25d6efb1d 100644
--- a/clang/lib/Basic/Targets/SystemZ.h
+++ b/clang/lib/Basic/Targets/SystemZ.h
@@ -21,6 +21,30 @@
namespace clang {
namespace targets {
+static const unsigned ZOSAddressMap[] = {
+ 0, // Default
+ 0, // opencl_global
+ 0, // opencl_local
+ 0, // opencl_constant
+ 0, // opencl_private
+ 0, // opencl_generic
+ 0, // opencl_global_device
+ 0, // opencl_global_host
+ 0, // cuda_device
+ 0, // cuda_constant
+ 0, // cuda_shared
+ 0, // sycl_global
+ 0, // sycl_global_device
+ 0, // sycl_global_host
+ 0, // sycl_local
+ 0, // sycl_private
+ 0, // ptr32_sptr
+ 1, // ptr32_uptr
+ 0, // ptr64
+ 0, // hlsl_groupshared
+ 0 // wasm_funcref
+};
+
class LLVM_LIBRARY_VISIBILITY SystemZTargetInfo : public TargetInfo {
static const char *const GCCRegNames[];
@@ -30,6 +54,7 @@ class LLVM_LIBRARY_VISIBILITY SystemZTargetInfo : public TargetInfo {
bool HasVector;
bool SoftFloat;
bool UnalignedSymbols;
+ enum AddrSpace { ptr32 = 1 };
public:
SystemZTargetInfo(const llvm::Triple &Triple, const TargetOptions &)
@@ -49,6 +74,9 @@ class LLVM_LIBRARY_VISIBILITY SystemZTargetInfo : public TargetInfo {
MinGlobalAlign = 16;
HasUnalignedAccess = true;
if (Triple.isOSzOS()) {
+ if (Triple.isArch64Bit()) {
+ AddrSpaceMap = &ZOSAddressMap;
+ }
TLSSupported = false;
// All vector types are default aligned on an 8-byte boundary, even if the
// vector facility is not available. That is different from Linux.
@@ -56,7 +84,7 @@ class LLVM_LIBRARY_VISIBILITY SystemZTargetInfo : public TargetInfo {
// Compared to Linux/ELF, the data layout differs only in some details:
// - name mangling is GOFF.
// - 32 bit pointers, either as default or special address space
- resetDataLayout("E-m:l-i1:8:16-i8:8:16-i64:64-f128:64-v128:64-"
+ resetDataLayout("E-m:l-p1:32:32-i1:8:16-i8:8:16-i64:64-f128:64-v128:64-"
"a:8:16-n32:64");
} else {
TLSSupported = true;
@@ -224,6 +252,16 @@ class LLVM_LIBRARY_VISIBILITY SystemZTargetInfo : public TargetInfo {
std::pair<unsigned, unsigned> hardwareInterferenceSizes() const override {
return std::make_pair(256, 256);
}
+ uint64_t getPointerWidthV(LangAS AddrSpace) const override {
+ return (getTriple().isOSzOS() && getTriple().isArch64Bit() &&
+ getTargetAddressSpace(AddrSpace) == ptr32)
+ ? 32
+ : PointerWidth;
+ }
+
+ uint64_t getPointerAlignV(LangAS AddrSpace) const override {
+ return getPointerWidthV(AddrSpace);
+ }
};
} // namespace targets
} // namespace clang
diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp
index f6b6c44a4cab6a..790a65942d6761 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -3642,6 +3642,14 @@ void CompilerInvocationBase::GenerateLangArgs(const LangOptions &Opts,
GenerateArg(Consumer, OPT_ftrigraphs);
}
+ if (T.isOSzOS()) {
+ if (!Opts.ZOSExt)
+ GenerateArg(Consumer, OPT_fno_zos_extensions);
+ } else {
+ if (Opts.ZOSExt)
+ GenerateArg(Consumer, OPT_fzos_extensions);
+ }
+
if (Opts.Blocks && !(Opts.OpenCL && Opts.OpenCLVersion == 200))
GenerateArg(Consumer, OPT_fblocks);
@@ -4043,6 +4051,9 @@ bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args,
Opts.Trigraphs =
Args.hasFlag(OPT_ftrigraphs, OPT_fno_trigraphs, Opts.Trigraphs);
+ Opts.ZOSExt =
+ Args.hasFlag(OPT_fzos_extensions, OPT_fno_zos_extensions, T.isOSzOS());
+
Opts.Blocks = Args.hasArg(OPT_fblocks) || (Opts.OpenCL
&& Opts.OpenCLVersion == 200);
diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index 6fa39cdccef2b9..6ea87cc3425dc7 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -7051,6 +7051,7 @@ static bool handleMSPointerTypeQualifierAttr(TypeProcessingState &State,
// Add address space to type based on its attributes.
LangAS ASIdx = LangAS::Default;
+ llvm::Triple Triple = S.Context.getTargetInfo().getTriple();
uint64_t PtrWidth =
S.Context.getTargetInfo().getPointerWidth(LangAS::Default);
if (PtrWidth == 32) {
@@ -7059,7 +7060,7 @@ static bool handleMSPointerTypeQualifierAttr(TypeProcessingState &State,
else if (Attrs[attr::UPtr])
ASIdx = LangAS::ptr32_uptr;
} else if (PtrWidth == 64 && Attrs[attr::Ptr32]) {
- if (Attrs[attr::UPtr])
+ if (Triple.isOSzOS() || Attrs[attr::UPtr])
ASIdx = LangAS::ptr32_uptr;
else
ASIdx = LangAS::ptr32_sptr;
diff --git a/clang/test/CodeGen/SystemZ/zos-mixed-ptr-sizes-definitions.c b/clang/test/CodeGen/SystemZ/zos-mixed-ptr-sizes-definitions.c
new file mode 100644
index 00000000000000..8fac3ccc78e5a5
--- /dev/null
+++ b/clang/test/CodeGen/SystemZ/zos-mixed-ptr-sizes-definitions.c
@@ -0,0 +1,54 @@
+
+// RUN: %clang_cc1 -triple s390x-ibm-zos -fzos-extensions -emit-llvm < %s | FileCheck %s --check-prefix=PTR32-ZOS
+// RUN: %clang_cc1 -triple s390x-ibm-linux -fzos-extensions -emit-llvm < %s | FileCheck %s --check-prefix=PTR32-LINUX
+// RUN: %clang_cc1 -triple s390x-linux-gnu -fzos-extensions -emit-llvm < %s | FileCheck %s --check-prefix=PTR32-LINUX
+
+void ptr32_declarations() {
+ // PTR32-ZOS-LABEL: @ptr32_declarations()
+ // PTR32-LINUX-LABEL: @ptr32_declarations()
+
+ // PTR32-ZOS: %p1 = alloca ptr addrspace(1), align 4
+ // PTR32-LINUX-NOT: %p1 = alloca i8 addrspace(1)*, align 4
+ // PTR32-LINUX: %p1 = alloca ptr, align 8
+ char * __ptr32 p1;
+
+ // PTR32-ZOS: %p2 = alloca ptr, align 8
+ // PTR32-LINUX-NOT: %p2 = alloca ptr addrspace(1), align 8
+ // PTR32-LINUX: %p2 = alloca ptr, align 8
+ char * __ptr32 *p2;
+
+ // PTR32-ZOS: %p3 = alloca ptr addrspace(1), align 4
+ // PTR32-LINUX-NOT: %p3 = alloca i8* addrspace(1)*, align 4
+ // PTR32-LINUX: %p3 = alloca ptr, align 8
+ char ** __ptr32 p3;
+
+ // PTR32-ZOS: %p4 = alloca ptr, align 8
+ // PTR32-LINUX-NOT: %p4 = alloca ptr addrspace(1), align 8
+ // PTR32-LINUX: %p4 = alloca ptr, align 8
+ char ** __ptr32 *p4;
+
+ // PTR32-ZOS: %p5 = alloca ptr, align 8
+ // PTR32-LINUX-NOT: %p5 = alloca ptr addrspace(1), align 8
+ // PTR32-LINUX: %p5 = alloca ptr, align 8
+ char *** __ptr32 *p5;
+
+ // PTR32-ZOS: %p6 = alloca ptr, align 8
+ // PTR32-LINUX: %p6 = alloca ptr, align 8
+ char **p6;
+
+ // PTR32-ZOS: %p7 = alloca ptr addrspace(1), align 4
+ // PTR32-LINUX-NOT: %p7 = alloca i8 addrspace(1)* addrspace(1)*, align 4
+ // PTR32-LINUX: %p7 = alloca ptr, align 8
+ char * __ptr32 * __ptr32 p7;
+
+ // PTR32-ZOS: %p8 = alloca ptr addrspace(1), align 4
+ // PTR32-LINUX-NOT: %p8 = alloca i8* addrspace(1)* addrspace(1)*, align 4
+ // PTR32-LINUX: %p8 = alloca ptr, align 8
+ char ** __ptr32 * __ptr32 p8;
+
+ // PTR32-ZOS: %p9 = alloca ptr, align 8
+ // PTR32-LINUX-NOT: %p9 = alloca i8* addrspace(1)* addrspace(1)**, align 8
+ // PTR32-LINUX: %p9 = alloca ptr, align 8
+ char ** __ptr32 * __ptr32 *p9;
+
+}
diff --git a/clang/test/CodeGen/SystemZ/zos-mixed-ptr-sizes-malloc.c b/clang/test/CodeGen/SystemZ/zos-mixed-ptr-sizes-malloc.c
new file mode 100644
index 00000000000000..1018c113ceea01
--- /dev/null
+++ b/clang/test/CodeGen/SystemZ/zos-mixed-ptr-sizes-malloc.c
@@ -0,0 +1,84 @@
+// RUN: %clang_cc1 -triple s390x-ibm-zos -fzos-extensions -emit-llvm -O2 < %s | FileCheck %s --check-prefix=X64
+#include <stddef.h>
+void *__malloc31(size_t);
+
+int test_1() {
+ // X64-LABEL: define {{.*}} i32 @test_1()
+ // X64: ret i32 135
+ int *__ptr32 a;
+ int *b;
+ int i;
+ int sum1, sum2, sum3;
+
+ a = (int *__ptr32)__malloc31(sizeof(int) * 10);
+
+ b = a;
+ sum1 = 0;
+ for (i = 0; i < 10; ++i) {
+ a[i] = i;
+ sum1 += i;
+ }
+
+ sum2 = 0;
+ for (i = 0; i < 10; ++i) {
+ sum2 += a[i];
+ }
+ sum3 = 0;
+ for (i = 0; i < 10; ++i) {
+ sum3 += b[i];
+ }
+
+ return (sum1 + sum2 + sum3);
+}
+
+int test_2() {
+ // X64-LABEL: define {{.*}} i32 @test_2()
+ // X64: ret i32 4
+ int *a = (int *)__malloc31(sizeof(int));
+ int *__ptr32 b;
+
+ *a = 99;
+ b = a;
+ *b = 44;
+
+ // Test should return 4
+ return (*b - 40);
+}
+
+int test_3() {
+ // X64-LABEL: define {{.*}} i32 @test_3()
+ // X64: ret i32 4
+ int *a = (int *)__malloc31(sizeof(int));
+ int *__ptr32 b;
+
+ *a = 99;
+ b = a;
+
+ // Test should return 4
+ return (*b - 95);
+}
+
+int test_4() {
+ // X64-LABEL: define {{.*}} i32 @test_4()
+ // X64: ret i32 1
+ int *a = (int *)__malloc31(sizeof(int));
+ float *d = (float *)__malloc31(sizeof(float));
+
+ int *__ptr32 b;
+ int *c;
+
+ float *__ptr32 e;
+ float *f;
+
+ *a = 0;
+ *d = 0.0;
+
+ b = a;
+ c = a;
+ e = d;
+ f = d;
+
+ // Test should return 1
+ return (b == c && e == f);
+}
+
diff --git a/clang/test/CodeGen/SystemZ/zos-mixed-ptr-sizes-sizeof.c b/clang/test/CodeGen/SystemZ/zos-mixed-ptr-sizes-sizeof.c
new file mode 100644
index 00000000000000..6b434a926f706b
--- /dev/null
+++ b/clang/test/CodeGen/SystemZ/zos-mixed-ptr-sizes-sizeof.c
@@ -0,0 +1,94 @@
+// RUN: %clang_cc1 -emit-llvm -triple s390x-ibm-zos -fzos-extensions -fdump-record-layouts < %s | FileCheck %s --check-prefix=PTR32-ZOS
+// RUN: %clang_cc1 -emit-llvm -triple s390x-ibm-linux -fzos-extensions -fdump-record-layouts < %s | FileCheck %s --check-prefix=PTR32-LINUX
+// RUN: %clang_cc1 -emit-llvm -triple s390x-linux-gnu -fzos-extensions -fdump-record-layouts < %s | FileCheck %s --check-prefix=PTR32-LINUX
+
+// PTR32-ZOS: 0 | struct s1
+// PTR32-ZOS-NEXT: 0 | long a
+// PTR32-ZOS-NEXT: 8 | int b
+// PTR32-ZOS-NEXT: 12 | int * __ptr32 c
+// PTR32-ZOS-NEXT: 16 | int d
+// PTR32-ZOS-NEXT: | [sizeof=24, align=8]
+
+// PTR32-LINUX: 0 | struct s1
+// PTR32-LINUX-NEXT: 0 | long a
+// PTR32-LINUX-NEXT: 8 | int b
+// PTR32-LINUX-NEXT: 16 | int * __ptr32 c
+// PTR32-LINUX-NEXT: 24 | int d
+// PTR32-LINUX-NEXT: | [sizeof=32, align=8]
+struct s1 {
+ long a;
+ int b;
+ int * __ptr32 c;
+ int d;
+} S1;
+
+// PTR32-ZOS: 0 | struct s2
+// PTR32-ZOS-NEXT: 0 | long a
+// PTR32-ZOS-NEXT: 8 | int b
+// PTR32-ZOS-NEXT: 16 | int * c
+// PTR32-ZOS-NEXT: 24 | int d
+// PTR32-ZOS-NEXT: | [sizeof=32, align=8]
+
+// PTR32-LINUX: 0 | struct s2
+// PTR32-LINUX-NEXT: 0 | long a
+// PTR32-LINUX-NEXT: 8 | int b
+// PTR32-LINUX-NEXT: 16 | int * c
+// PTR32-LINUX-NEXT: 24 | int d
+// PTR32-LINUX-NEXT: | [sizeof=32, align=8]
+struct s2 {
+ long a;
+ int b;
+ int *c;
+ int d;
+} S2;
+
+// PTR32-ZOS: 0 | struct s3
+// PTR32-ZOS-NEXT: 0 | int a
+// PTR32-ZOS-NEXT: 4 | int * __ptr32 b
+// PTR32-ZOS-NEXT: 8 | int * __ptr32 c
+// PTR32-ZOS-NEXT: 12 | int * d
+// PTR32-ZOS-NEXT: | [sizeof=20, align=1]
+
+struct __attribute__((packed)) s3 {
+ int a;
+ int *__ptr32 b;
+ int *__ptr32 c;
+ int *d;
+};
+struct s3 S3;
+
+// PTR32-ZOS: 0 | union u1
+// PTR32-ZOS-NEXT: 0 | int * __ptr32 a
+// PTR32-ZOS-NEXT: 0 | int * b
+// PTR32-ZOS-NEXT: | [sizeof=8, align=8]
+
+// PTR32-LINUX: 0 | union u1
+// PTR32-LINUX-NEXT: 0 | int * __ptr32 a
+// PTR32-LINUX-NEXT: 0 | int * b
+// PTR32-LINUX-NEXT: | [sizeof=8, align=8]
+union u1 {
+ int *__ptr32 a;
+ int *b;
+} U1;
+
+// PTR32-ZOS: 0 | union u2
+// PTR32-ZOS-NEXT: 0 | int * __ptr32 a
+// PTR32-ZOS-NEXT: 0 | int * b
+// PTR32-ZOS-NEXT: | [sizeof=8, align=1]
+
+union __attribute__((packed)) u2 {
+ int *__ptr32 a;
+ int *b;
+};
+union u2 U2;
+
+// PTR32-ZOS: 0 | union u3
+// PTR32-ZOS-NEXT: 0 | int * __ptr32 a
+// PTR32-ZOS-NEXT: 0 | short b
+// PTR32-ZOS-NEXT: | [sizeof=4, align=1]
+
+union __attribute__((packed)) u3 {
+ int *__ptr32 a;
+ short b;
+};
+union u3 U3;
diff --git a/clang/test/CodeGen/SystemZ/zos-mixed-ptr-sizes.c b/clang/test/CodeGen/SystemZ/zos-mixed-ptr-sizes.c
new file mode 100644
index 00000000000000..24bd75284ebc4c
--- /dev/null
+++ b/clang/test/CodeGen/SystemZ/zos-mixed-ptr-sizes.c
@@ -0,0 +1,298 @@
+// RUN: %clang_cc1 -triple s390x-ibm-zos -fzos-extensions -emit-llvm -O2 < %s | FileCheck %s --check-prefix=X64
+
+#define PSA_PTR 0x00
+#define PSAAOLD 0x224
+
+struct Foo {
+ int * __ptr32 p32;
+ int *p64;
+ char *cp64;
+};
+
+void use_foo(struct Foo *f);
+
+void ptr32_to_ptr(struct Foo *f, int * __ptr32 i) {
+ // X64-LABEL: define void @ptr32_to_ptr(ptr noundef %f, ptr addrspace(1) noundef %i)
+ // X64: %{{.+}} = addrspacecast ptr addrspace(1) %i to ptr
+ f->p64= i;
+ use_foo(f);
+}
+
+void ptr_to_ptr32(struct Foo *f, int *i) {
+ // X64-LABEL: define void @ptr_to_ptr32(ptr noundef %f, ptr noundef %i)
+ // X64: %{{.+}} = addrspacecast ptr %i to ptr addrspace(1)
+ f->p32 = i;
+ use_foo(f);
+}
+
+void ptr32_to_ptr32(struct Foo *f, int * __ptr32 i) {
+ // X64-LABEL: define void @ptr32_to_ptr32(ptr noundef %f, ptr addrspace(1) noundef %i)
+ // X64-NOT: addrspacecast
+ f->p32 = i;
+ use_foo(f);
+}
+
+void ptr_to_ptr32_explicit_cast(struct Foo *f, int *i) {
+ // X64-LABEL: define void @ptr_to_ptr32_explicit_cast(ptr noundef %f, ptr noundef %i)
+ // X64: %{{.+}} = addrspacecast ptr %i to ptr addrspace(1)
+ f->p32 = (int * __ptr32)i;
+ use_foo(f);
+}
+
+void test_indexing(struct Foo *f) {
+ // X64-LABEL: define void @test_indexing(ptr noundef %f)
+ // X64: addrspacecast ptr addrspace(1) {{%[0-9]}} to ptr
+ f->cp64 = ((char * __ptr32 *)1028)[1];
+ use_foo(f);
+}
+
+void test_indexing_2(struct Foo *f) {
+ // X64-LABEL: define void @test_indexing_2(ptr noundef %f)
+ // X64: getelementptr inbounds i8, ptr addrspace(1) {{%[0-9]}}, i32 16
+ // X64: getelementptr inbounds i8, ptr {{%[0-9]}}, i64 24
+ f->cp64 = ((char *** __ptr32 *)1028)[1][2][3];
+ use_foo(f);
+}
+
+unsigned long* test_misc() {
+ // X64-LABEL: define ptr @test_misc()
+ // X64: %arrayidx = getelementptr inbounds i8, ptr addrspace(1) %0, i32 88
+ // X64-NEXT: %1 = load ptr, ptr addrspace(1) %arrayidx
+ // X64-NEXT: %arrayidx1 = getelementptr inbounds i8, ptr %1, i64 8
+ // X64-NEXT: %2 = load ptr, ptr %arrayidx1
+ // X64-NEXT: %arrayidx2 = getelementptr inbounds i8, ptr %2, i64 904
+ // X64-NEXT: %3 = load ptr, ptr %arrayidx2
+ // X64-NEXT: %arrayidx3 = getelementptr inbounds i8, ptr %3, i64 1192
+ unsigned long* x = (unsigned long*)((char***** __ptr32*)1208)[0][11][1][113][149];
+ return x;
+}
+
+char* __ptr32* __ptr32 test_misc_2() {
+ // X64-LABEL: define ptr addrspace(1) @test_misc_2()
+ // X64: br i1 %cmp, label %if.then, label %if.end
+ // X64: %1 = load ptr addrspace(1), ptr inttoptr (i64 16 to ptr)
+ // X64-NEXT: %arrayidx = getelementptr inbounds i8, ptr addrspace(1) %1, i32 544
+ // X64-NEXT: %2 = load ptr addrspace(1), ptr addrspace(1) %arrayidx
+ // X64-NEXT: %arrayidx1 = getelementptr inbounds i8, ptr addrspace(1) %2, i32 24
+ // X64-NEXT: %3 = load ptr addrspace(1), ptr addrspace(1) %arrayidx1
+ // X64-NEXT: store ptr addrspace(1) %3, ptr @test_misc_2.res
+ // X64: ret ptr addrspace(1)
+ static char* __ptr32* __ptr32 res = 0;
+ if (res == 0) {
+ res = ((char* __ptr32* __ptr32* __ptr32* __ptr32*)0)[4][136][6];
+ }
+ return res;
+}
+
+unsigned short test_misc_3() {
+ // X64-LABEL: define zeroext i16 @test_misc_3()
+ // X64: %0 = load ptr addrspace(1), ptr inttoptr (i64 548 to ptr)
+ // X64-NEXT: %1 = addrspacecast ptr addrspace(1) %0 to ptr
+ // X64-NEXT: %arrayidx = getelementptr inbounds i8, ptr %1, i64 36
+ // X64-NEXT: %2 = load i16, ptr %arrayidx, align 2
+ // X64-NEXT: ret i16 %2
+ unsigned short this_asid = ((unsigned short*)(*(char* __ptr32*)(0x224)))[18];
+ return this_asid;
+}
+
+int test_misc_4() {
+ // X64-LABEL: define signext range(i32 0, 2) i32 @test_misc_4()
+ // X64: getelementptr inbounds i8, ptr addrspace(1) {{%[0-9]}}, i32 88
+ // X64: getelementptr inbounds i8, ptr {{%[0-9]}}, i64 8
+ // X64: getelementptr inbounds i8, ptr {{%[0-9]}}, i64 984
+ // X64: getelementptr inbounds i8, ptr %3, i64 80
+ // X64: icmp sgt i32 {{.*[0-9]}}, 67240703
+ // X64: ret i32
+ int a = (*(int*)(80 + ((char**** __ptr32*)1208)[0][11][1][123]) > 0x040202FF);
+ return a;
+}
+
+void test_misc_5(struct Foo *f) {
+ // X64-LABEL: define void @test_misc_5(ptr noundef %f)
+ // X64: addrspacecast ptr addrspace(1) %0 to ptr
+ f->cp64 = *(char* __ptr32 *)(PSA_PTR + PSAAOLD);
+ use_foo(f);
+}
+
+int test_misc_6() {
+ // X64-LABEL: define {{.*}} i32 @test_misc_6()
+ // X64: ret i32 8
+ int * __ptr32 ip32;
+ int *ip64;
+ ip64 = ip32;
+ return sizeof(ip64);
+}
+
+int test_misc_7() {
+ // X64-LABEL: define {{.*}} i32 @test_misc_7()
+ // X64: ret i32 12
+ int foo = 12;
+
+ int *ip64;
+ int * __ptr32 ip32;
+
+ ip64 = &foo;
+ ip32 = (int * __ptr32) ip64;
+
+ return *ip32;
+}
+
+int test_misc_8() {
+ // X64-LABEL: define {{.*}} i32 @test_misc_8()
+ // X64: ret i32 97
+ char foo = 'a';
+
+ char *cp64;
+ char * __ptr32 cp32;
+
+ cp64 = &foo;
+ cp32 = (char * __ptr32) cp64;
+
+ return *cp32;
+}
+
+int test_misc_9() {
+ // X64-LABEL: define {{.*}} i32 @test_misc_9()
+ // X64: ret i32 15
+ int foo = 15;
+
+ int *ip64;
+ int * __ptr32 ip32;
+
+ ip32 = &foo;
+ ip64 = (int *)ip32;
+
+ return *ip64;
+}
+
+int test_misc_10() {
+ // X64-LABEL: define {{.*}} i32 @test_misc_10()
+ // X64: ret i32 97
+ char foo = 'a';
+
+ char *cp64;
+ char * __ptr32 cp32;
+
+ cp32 = &foo;
+ cp64= (char *)cp32;
+
+ return *cp64;
+}
+
+int test_function_ptr32_is_32bit() {
+ // X64-LABEL: define {{.*}} i32 @test_function_ptr32_is_32bit()
+ // X64: ret i32 4
+ int (* __ptr32 a)(int a);
+ return sizeof(a);
+}
+
+int get_processor_count() {
+ // X64-LABEL: define signext range(i32 -128, 128) i32 @get_processor_count()
+ // X64: load ptr addrspace(1), ptr inttoptr (i64 16 to ptr)
+ // X64-NEXT: [[ARR_IDX1:%[a-z].*]] = getelementptr inbounds i8, ptr addrspace(1) %0, i32 660
+ // X64: load ptr addrspace(1), ptr addrspace(1) [[ARR_IDX1]]
+ // X64: load i8, ptr addrspace(1) {{%[a-z].*}}
+ // X64: sext i8 {{%[0-9]}} to i32
+ // X64-NEXT: ret i32
+ return ((char * __ptr32 * __ptr32 *)0)[4][165][53];
+}
+
+int get_sizes_ptr32() {
+ // X64-LABEL: define {{.*}} i32 @get_sizes_ptr32()
+ // X64: ret i32 72
+ char * __ptr32 a;
+ signed char * __ptr32 b;
+ unsigned char *__ptr32 c;
+ int * __ptr32 d;
+ signed int * __ptr32 e;
+ unsigned int *__ptr32 f;
+ short * __ptr32 g;
+ signed short * __ptr32 h;
+ unsigned short * __ptr32 i;
+ long * __ptr32 j;
+ signed * __ptr32 k;
+ unsigned * __ptr32 l;
+ long long * __ptr32 m;
+ signed long long * __ptr32 n;
+ unsigned long long * __ptr32 o;
+ float * __ptr32 p;
+ double * __ptr32 q;
+ long double * __ptr32 r;
+
+ int sum = 0;
+ sum += sizeof(a);
+ sum += sizeof(b);
+ sum += sizeof(c);
+ sum += sizeof(d);
+ sum += sizeof(e);
+ sum += sizeof(f);
+ sum += sizeof(g);
+ sum += sizeof(h);
+ sum += sizeof(i);
+ sum += sizeof(j);
+ sum += sizeof(k);
+ sum += sizeof(l);
+ sum += sizeof(m);
+ sum += sizeof(n);
+ sum += sizeof(o);
+ sum += sizeof(p);
+ sum += sizeof(q);
+ sum += sizeof(r);
+
+ return sum;
+}
+
+int get_sizes_p64() {
+ // X64-LABEL: define {{.*}} i32 @get_sizes_p64()
+ // X64: ret i32 144
+ char *a;
+ signed char *b;
+ unsigned char *c;
+ int *d;
+ signed int *e;
+ unsigned int *f;
+ short *g;
+ signed short *h;
+ unsigned short *i;
+ long *j;
+ signed *k;
+ unsigned *l;
+ long long *m;
+ signed long long *n;
+ unsigned long long *o;
+ float *p;
+ double *q;
+ long double *r;
+
+ int sum = 0;
+ sum += sizeof(a);
+ sum += sizeof(b);
+ sum += sizeof(c);
+ sum += sizeof(d);
+ sum += sizeof(e);
+ sum += sizeof(f);
+ sum += sizeof(g);
+ sum += sizeof(h);
+ sum += sizeof(i);
+ sum += sizeof(j);
+ sum += sizeof(k);
+ sum += sizeof(l);
+ sum += sizeof(m);
+ sum += sizeof(n);
+ sum += sizeof(o);
+ sum += sizeof(p);
+ sum += sizeof(q);
+ sum += sizeof(r);
+
+ return sum;
+
+}
+
+int host_cpu() {
+ char *__ptr32 CVT = *(char * __ptr32 *__ptr32) 16;
+ unsigned short Id = *(unsigned short *)&CVT[-6];
+ Id = ((((Id >> 12) & 0x0f) * 10 + ((Id >> 8) & 0x0f)) * 10 + ((Id >> 4) & 0x0f)) * 10 + (Id & 0x0f);
+ int HaveVectorSupport = CVT[244] & 0x80;
+ int z13 = (Id >= 2964 && HaveVectorSupport);
+ return z13;
+}
diff --git a/clang/test/CodeGen/target-data.c b/clang/test/CodeGen/target-data.c
index 9a9fda70226fc2..41cbd5a0219d5e 100644
--- a/clang/test/CodeGen/target-data.c
+++ b/clang/test/CodeGen/target-data.c
@@ -235,7 +235,7 @@
// RUN: FileCheck %s -check-prefix=ZOS
// RUN: %clang_cc1 -triple s390x-none-zos -target-cpu z13 -o - -emit-llvm %s | \
// RUN: FileCheck %s -check-prefix=ZOS
-// ZOS: target datalayout = "E-m:l-i1:8:16-i8:8:16-i64:64-f128:64-v128:64-a:8:16-n32:64"
+// ZOS: target datalayout = "E-m:l-p1:32:32-i1:8:16-i8:8:16-i64:64-f128:64-v128:64-a:8:16-n32:64"
// RUN: %clang_cc1 -triple msp430-unknown -o - -emit-llvm %s | \
// RUN: FileCheck %s -check-prefix=MSP430
diff --git a/clang/test/CodeGenCXX/zos-mangle-ptr-size-address-space.cpp b/clang/test/CodeGenCXX/zos-mangle-ptr-size-address-space.cpp
new file mode 100644
index 00000000000000..d14ce117b2be4a
--- /dev/null
+++ b/clang/test/CodeGenCXX/zos-mangle-ptr-size-address-space.cpp
@@ -0,0 +1,17 @@
+// RUN: %clang_cc1 -fzos-extensions -emit-llvm -triple s390x-ibm-zos -x c++ -o - %s | FileCheck %s --check-prefixes=CHECK
+
+// CHECK-LABEL: define void @_Z2f1v()
+void f1() {}
+
+// CHECK-LABEL: define void @_Z2f2Pi(ptr addrspace(1) noundef %p32)
+void f2(int * __ptr32 p32) {}
+
+// CHECK-LABEL: define noundef ptr addrspace(1) @_Z2f3Pi(ptr addrspace(1) noundef %p32)
+int * __ptr32 f3(int * __ptr32 p32) {
+ return p32;
+}
+
+// CHECK-LABEL: define noundef ptr @_Z2f4PPi(ptr noundef %p32)
+int * __ptr32 *f4(int * __ptr32 *p32) {
+ return p32;
+}
diff --git a/clang/test/Sema/ZOSExtensions.cpp b/clang/test/Sema/ZOSExtensions.cpp
new file mode 100644
index 00000000000000..65caa12afdcf09
--- /dev/null
+++ b/clang/test/Sema/ZOSExtensions.cpp
@@ -0,0 +1,119 @@
+// RUN: %clang_cc1 -triple s390x-ibm-zos %s -fsyntax-only -fzos-extensions -verify
+
+struct A {
+ int a;
+ short b;
+ float q;
+ double z;
+};
+
+union B {
+ int a;
+ short b;
+ float q;
+ double z;
+};
+
+class C {
+ int a;
+ short b;
+ float q;
+ double z;
+};
+
+// ************************
+// INCORRECT DECLARATION
+// ************************
+int * __ptr64 p64; // expected-error {{expected ';' after top level declarator}}
+int *wrong_var3 __ptr32; // expected-error {{expected ';' after top level declarator}} expected-warning {{declaration does not declare anything}}
+
+// **************************
+// INCORRECT USAGES OF PTR32
+// **************************
+struct D {
+ int __ptr32 *a; // expected-error {{'__ptr32' attribute only applies to pointer arguments}}
+};
+
+union E {
+ int __ptr32 *b; // expected-error {{'__ptr32' attribute only applies to pointer arguments}}
+};
+
+char __ptr32 *a; // expected-error {{'__ptr32' attribute only applies to pointer arguments}}
+signed char __ptr32 *b; // expected-error {{'__ptr32' attribute only applies to pointer arguments}}
+unsigned char __ptr32 *c; // expected-error {{'__ptr32' attribute only applies to pointer arguments}}
+int __ptr32 *d; // expected-error {{'__ptr32' attribute only applies to pointer arguments}}
+signed int __ptr32 *e; // expected-error {{'__ptr32' attribute only applies to pointer arguments}}
+unsigned int __ptr32 *f; // expected-error {{'__ptr32' attribute only applies to pointer arguments}}
+short int __ptr32 *g; // expected-error {{'__ptr32' attribute only applies to pointer arguments}}
+signed short int __ptr32 *h; // expected-error {{'__ptr32' attribute only applies to pointer arguments}}
+unsigned short int __ptr32 *i; // expected-error {{'__ptr32' attribute only applies to pointer arguments}}
+long int __ptr32 *j; // expected-error {{'__ptr32' attribute only applies to pointer arguments}}
+signed long int __ptr32 *k; // expected-error {{'__ptr32' attribute only applies to pointer arguments}}
+unsigned long int __ptr32 *l; // expected-error {{'__ptr32' attribute only applies to pointer arguments}}
+long long int __ptr32 *m; // expected-error {{'__ptr32' attribute only applies to pointer arguments}}
+signed long long int __ptr32 *n; // expected-error {{'__ptr32' attribute only applies to pointer arguments}}
+unsigned long long int __ptr32 *o; // expected-error {{'__ptr32' attribute only applies to pointer arguments}}
+float __ptr32 *p; // expected-error {{'__ptr32' attribute only applies to pointer arguments}}
+double __ptr32 *q; // expected-error {{'__ptr32' attribute only applies to pointer arguments}}
+int __ptr32 **r; // expected-error {{'__ptr32' attribute only applies to pointer arguments}}
+int __ptr32 *__ptr32 *s; // expected-error {{'__ptr32' attribute only applies to pointer arguments}}
+int __ptr32 *__ptr32 *__ptr32 t; // expected-error {{'__ptr32' attribute only applies to pointer arguments}}
+int __ptr32 *__ptr32 *__ptr32 *__ptr32 u; // expected-error {{'__ptr32' attribute only applies to pointer arguments}}
+int __ptr32 __ptr32 **v_i; // expected-error {{'__ptr32' attribute only applies to pointer arguments}} expected-error {{'__ptr32' attribute only applies to pointer arguments}}
+int __ptr32 __ptr32 __ptr32 w_i; // expected-error {{'__ptr32' attribute only applies to pointer arguments}} expected-error {{'__ptr32' attribute only applies to pointer arguments}} expected-error {{'__ptr32' attribute only applies to pointer arguments}}
+
+__ptr32 int wrong_var; // expected-error {{'__ptr32' attribute only applies to pointer arguments}}
+
+struct A __ptr32 *c1; // expected-error {{'__ptr32' attribute only applies to pointer arguments}}
+struct A __ptr32 **e1; // expected-error {{'__ptr32' attribute only applies to pointer arguments}}
+struct A __ptr32 *__ptr32 *f1; // expected-error {{'__ptr32' attribute only applies to pointer arguments}}
+struct A __ptr32 *__ptr32 *__ptr32 g1; // expected-error {{'__ptr32' attribute only applies to pointer arguments}}
+union B __ptr32 *d1; // expected-error {{'__ptr32' attribute only applies to pointer arguments}}
+union B __ptr32 **h1; // expected-error {{'__ptr32' attribute only applies to pointer arguments}}
+union B __ptr32 * __ptr32 *i1; // expected-error {{'__ptr32' attribute only applies to pointer arguments}}
+union B __ptr32 * __ptr32 * __ptr32 j1; // expected-error {{'__ptr32' attribute only applies to pointer arguments}}
+
+C __ptr32 **k1; // expected-error {{'__ptr32' attribute only applies to pointer arguments}}
+C __ptr32 * __ptr32 *l1; // expected-error {{'__ptr32' attribute only applies to pointer arguments}}
+C __ptr32 * __ptr32 * __ptr32 m1; // expected-error {{'__ptr32' attribute only applies to pointer arguments}}
+
+struct D n1;
+union E o1;
+
+int incorrect_func() {
+ int __ptr32 = 1; // expected-error {{expected unqualified-id}}
+ return __ptr32; // expected-error {{expected expression}}
+}
+
+typedef int __ptr32; // expected-warning {{typedef requires a name}}
+int incorrect_func2() {
+ return 1;
+}
+
+typedef int __ptr32 *v; // expected-error {{'__ptr32' attribute only applies to pointer arguments}}
+int incorrect_func3() {
+ v v1;
+ return 0;
+}
+
+int *__ptr32 a_ptr; //expected-note {{previous definition is here}}
+int *a_ptr; // expected-error {{redefinition of 'a_ptr' with a different type: 'int *' vs 'int * __ptr32'}}
+
+// *******************************************************
+// FUNCTION OVERLOADING BETWEEN PTR32 AND REGULAR POINTERS
+// *******************************************************
+void func(int * __ptr32 p32) {} // expected-note {{previous definition is here}}
+void func(int *p64) {} // expected-error {{redefinition of 'func'}}
+
+// Overloads between ptr32 and other non-pointer types are permissible
+void func1(int *__ptr32 p32) {}
+void func1(int p64) {}
+
+// ******
+// MISC
+// ******
+void func2() {
+ char * __ptr32 v = ((char * __ptr32 *)1028)[0];
+ char *v1 = ((char ** __ptr32 *)1028)[0][1];
+}
+
diff --git a/clang/test/Sema/attr-print-zos.c b/clang/test/Sema/attr-print-zos.c
new file mode 100644
index 00000000000000..f19926c131a4f3
--- /dev/null
+++ b/clang/test/Sema/attr-print-zos.c
@@ -0,0 +1,31 @@
+// RUN: %clang_cc1 %s -triple s390x-ibm-zos -ast-print -fzos-extensions | FileCheck %s
+
+// CHECK: int * __ptr32 p32;
+int * __ptr32 p32;
+
+// CHECK: char * __ptr32 c32;
+char * __ptr32 c32;
+
+// CHECK: void * __ptr32 v32;
+void * __ptr32 v32;
+
+// CHECK: int * __ptr32 *q;
+int * __ptr32 *q;
+
+// CHECK: void *func(int * __ptr32 p);
+void *func(int * __ptr32 p);
+
+// CHECK: int * __ptr32 func1(int * __ptr32 p);
+int * __ptr32 func1(int * __ptr32 p);
+
+// CHECK: int *func2(void * __ptr32 p);
+int *func2(void * __ptr32 p);
+
+// CHECK: int *const __ptr32 r;
+int * __ptr32 const r;
+
+// CHECK: int ** __ptr32 *v;
+int * *__ptr32* v;
+
+// CHECK: int *** __ptr32 *z;
+int ** * __ptr32 * z;
diff --git a/llvm/lib/Target/SystemZ/SystemZTargetMachine.cpp b/llvm/lib/Target/SystemZ/SystemZTargetMachine.cpp
index 6f76839724ee9f..53ed46f14f14dc 100644
--- a/llvm/lib/Target/SystemZ/SystemZTargetMachine.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZTargetMachine.cpp
@@ -59,6 +59,14 @@ static std::string computeDataLayout(const Triple &TT) {
// Data mangling.
Ret += DataLayout::getManglingComponent(TT);
+ // Special features for z/OS.
+ if (TT.isOSzOS()) {
+ if (TT.isArch64Bit()) {
+ // Custom address space for ptr32.
+ Ret += "-p1:32:32";
+ }
+ }
+
// Make sure that global data has at least 16 bits of alignment by
// default, so that we can refer to it using LARL. We don't have any
// special requirements for stack variables though.
More information about the cfe-commits
mailing list