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.sreeskanthara...@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. _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits