[clang] [llvm] [SystemZ][z/OS] __ptr32 support for z/OS in Clang (PR #96063)

via cfe-commits cfe-commits at lists.llvm.org
Wed Jun 19 04:46:40 PDT 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-systemz

@llvm/pr-subscribers-clang

Author: Fanbo Meng (fanbo-meng)

<details>
<summary>Changes</summary>

Enabling __ptr32 keyword to support in Clang for z/OS. It is represented by addrspace(1) in LLVM IR. Unlike existing implementation, __ptr32 is not mangled into symbol names for z/OS.

---

Patch is 35.27 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/96063.diff


17 Files Affected:

- (modified) clang/include/clang/Basic/LangOptions.def (+1) 
- (modified) clang/include/clang/Basic/TokenKinds.def (+2-1) 
- (modified) clang/include/clang/Driver/Options.td (+4) 
- (modified) clang/lib/AST/ItaniumMangle.cpp (+7-1) 
- (modified) clang/lib/Basic/IdentifierTable.cpp (+12-4) 
- (modified) clang/lib/Basic/Targets/SystemZ.h (+42-1) 
- (modified) clang/lib/Frontend/CompilerInvocation.cpp (+11) 
- (modified) clang/lib/Sema/SemaType.cpp (+8-3) 
- (modified) clang/test/CodeGen/target-data.c (+1-1) 
- (added) clang/test/CodeGen/zos-mixed-ptr-sizes-definitions.c (+53) 
- (added) clang/test/CodeGen/zos-mixed-ptr-sizes-malloc.c (+84) 
- (added) clang/test/CodeGen/zos-mixed-ptr-sizes-sizeof.c (+94) 
- (added) clang/test/CodeGen/zos-mixed-ptr-sizes.c (+298) 
- (added) clang/test/CodeGenCXX/zos-mangle-ptr-size-address-space.cpp (+17) 
- (added) clang/test/Sema/ZOSExtensions.cpp (+119) 
- (added) clang/test/Sema/attr-print-zos.c (+31) 
- (modified) llvm/lib/Target/SystemZ/SystemZTargetMachine.cpp (+8) 


``````````diff
diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def
index 2dea3cd4d795b..9f303b2f549bf 100644
--- a/clang/include/clang/Basic/LangOptions.def
+++ b/clang/include/clang/Basic/LangOptions.def
@@ -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(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 9c4b17465e18a..9717ecd6d7d66 100644
--- a/clang/include/clang/Basic/TokenKinds.def
+++ b/clang/include/clang/Basic/TokenKinds.def
@@ -286,6 +286,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)
@@ -708,7 +709,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 d44faa55c456f..e0ae29f881d9e 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -3038,6 +3038,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 ed9e6eeb36c75..8c0bc9474dbc0 100644
--- a/clang/lib/AST/ItaniumMangle.cpp
+++ b/clang/lib/AST/ItaniumMangle.cpp
@@ -2728,6 +2728,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();
 
@@ -2796,7 +2798,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 feea84544d62f..ac7409c9b587b 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 used to exclude.
   };
 
   /// 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,6 +237,7 @@ 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;
 
diff --git a/clang/lib/Basic/Targets/SystemZ.h b/clang/lib/Basic/Targets/SystemZ.h
index 3bc6f2c1d3083..5f4f93cbfa48e 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,19 @@ 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 {
+    unsigned TargetAddrSpace = getTargetAddressSpace(AddrSpace);
+    return (TargetAddrSpace == ptr32 && getTriple().isOSzOS() &&
+            getTriple().isArch64Bit())
+               ? 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 58694e5399d58..ef982214eba61 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -3567,6 +3567,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);
 
@@ -3968,6 +3976,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 441fdcca0758f..346139042d114 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -7089,6 +7089,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) {
@@ -7097,10 +7098,14 @@ 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()) {
       ASIdx = LangAS::ptr32_uptr;
-    else
-      ASIdx = LangAS::ptr32_sptr;
+    } else {
+      if (Attrs[attr::UPtr])
+        ASIdx = LangAS::ptr32_uptr;
+      else
+        ASIdx = LangAS::ptr32_sptr;
+    }
   }
 
   QualType Pointee = Type->getPointeeType();
diff --git a/clang/test/CodeGen/target-data.c b/clang/test/CodeGen/target-data.c
index 7f7005d21b99a..d487584521e78 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/CodeGen/zos-mixed-ptr-sizes-definitions.c b/clang/test/CodeGen/zos-mixed-ptr-sizes-definitions.c
new file mode 100644
index 0000000000000..887ce1ddfe931
--- /dev/null
+++ b/clang/test/CodeGen/zos-mixed-ptr-sizes-definitions.c
@@ -0,0 +1,53 @@
+// 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/zos-mixed-ptr-sizes-malloc.c b/clang/test/CodeGen/zos-mixed-ptr-sizes-malloc.c
new file mode 100644
index 0000000000000..1018c113ceea0
--- /dev/null
+++ b/clang/test/CodeGen/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/zos-mixed-ptr-sizes-sizeof.c b/clang/test/CodeGen/zos-mixed-ptr-sizes-sizeof.c
new file mode 100644
index 0000000000000..6b434a926f706
--- /dev/null
+++ b/clang/test/CodeGen/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/zos-mixed-ptr-sizes.c b/clang/test/CodeGen/zos-mixed-ptr-sizes.c
new file mode 100644
index 0000000000000..24bd75284ebc4
--- /dev/null
+++ b/clang/test/CodeGen/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...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/96063


More information about the cfe-commits mailing list