Index: clang/include/clang/Basic/LangOptions.def =================================================================== --- clang/include/clang/Basic/LangOptions.def +++ clang/include/clang/Basic/LangOptions.def @@ -201,6 +201,7 @@ LANGOPT(EnableAIXQuadwordAtomicsABI , 1, 0, "Use 16-byte atomic lock free semantics") COMPATIBLE_VALUE_LANGOPT(PICLevel , 2, 0, "__PIC__ level") COMPATIBLE_VALUE_LANGOPT(PIE , 1, 0, "is pie") +LANGOPT(NoPicDataIsTextRelative , 1, 0, "Local data is not text relative with PIC.") LANGOPT(ROPI , 1, 0, "Read-only position independence") LANGOPT(RWPI , 1, 0, "Read-write position independence") COMPATIBLE_LANGOPT(GNUInline , 1, 0, "GNU inline semantics") Index: clang/include/clang/Driver/Options.td =================================================================== --- clang/include/clang/Driver/Options.td +++ clang/include/clang/Driver/Options.td @@ -2690,6 +2690,8 @@ def fno_pic : Flag<["-"], "fno-pic">, Group; def fpie : Flag<["-"], "fpie">, Group; def fno_pie : Flag<["-"], "fno-pie">, Group; +defm pic_data_is_text_relative : SimpleMFlag<"pic-data-is-text-relative", + "Assume", "Don't assume", " data segments are relative to text segment">; def fdirect_access_external_data : Flag<["-"], "fdirect-access-external-data">, Group, Flags<[CC1Option]>, HelpText<"Don't use GOT indirection to reference external data symbols">; def fno_direct_access_external_data : Flag<["-"], "fno-direct-access-external-data">, Group, Flags<[CC1Option]>, @@ -6067,6 +6069,9 @@ def pic_is_pie : Flag<["-"], "pic-is-pie">, HelpText<"File is for a position independent executable">, MarshallingInfoFlag>; +def no_pic_data_is_text_relative : Flag<["-"], "no-pic-data-is-text-relative">, + HelpText<"Don't assume data segments are relative to text segment">, + MarshallingInfoFlag>; } // let Flags = [CC1Option, FC1Option, NoDriverOption] Index: clang/lib/CodeGen/CodeGenModule.cpp =================================================================== --- clang/lib/CodeGen/CodeGenModule.cpp +++ clang/lib/CodeGen/CodeGenModule.cpp @@ -865,6 +865,9 @@ getModule().setPICLevel(static_cast(PLevel)); if (Context.getLangOpts().PIE) getModule().setPIELevel(static_cast(PLevel)); + if (Context.getLangOpts().NoPicDataIsTextRelative) + getModule().addModuleFlag(llvm::Module::Error, + "no_pic_data_is_text_relative", 1); } if (getCodeGenOpts().CodeModel.size() > 0) { Index: clang/lib/Driver/ToolChains/Clang.cpp =================================================================== --- clang/lib/Driver/ToolChains/Clang.cpp +++ clang/lib/Driver/ToolChains/Clang.cpp @@ -5091,6 +5091,12 @@ unsigned PICLevel; bool IsPIE; std::tie(RelocationModel, PICLevel, IsPIE) = ParsePICArgs(TC, Args); + Arg *LastPICDataRelArg = + Args.getLastArg(options::OPT_mno_pic_data_is_text_relative, + options::OPT_mpic_data_is_text_relative); + bool NoPICDataIsTextRelative = LastPICDataRelArg && + LastPICDataRelArg->getOption() + .matches(options::OPT_mno_pic_data_is_text_relative); bool IsROPI = RelocationModel == llvm::Reloc::ROPI || RelocationModel == llvm::Reloc::ROPI_RWPI; @@ -5119,6 +5125,18 @@ CmdArgs.push_back(PICLevel == 1 ? "1" : "2"); if (IsPIE) CmdArgs.push_back("-pic-is-pie"); + if (NoPICDataIsTextRelative) + CmdArgs.push_back("-no-pic-data-is-text-relative"); + } + if (NoPICDataIsTextRelative) { + if (!Triple.isSystemZ()) + D.Diag(diag::err_drv_unsupported_opt_for_target) + << "-mno-pic-data-is-text-relative" + << RawTriple.str(); + else if (!PICLevel) + D.Diag(diag::err_drv_argument_only_allowed_with) + << "-mno-pic-data-is-text-relative" + << "-fpic/-fpie"; } if (RelocationModel == llvm::Reloc::ROPI || Index: clang/test/CodeGen/piclevels.c =================================================================== --- clang/test/CodeGen/piclevels.c +++ clang/test/CodeGen/piclevels.c @@ -2,6 +2,8 @@ // RUN: %clang_cc1 -emit-llvm -pic-level 1 %s -o - | FileCheck %s -check-prefix=CHECK-SMALLPIC -check-prefix=CHECK-NOPIE // RUN: %clang_cc1 -emit-llvm -pic-level 2 -pic-is-pie %s -o - | FileCheck %s -check-prefix=CHECK-BIGPIC -check-prefix=CHECK-BIGPIE // RUN: %clang_cc1 -emit-llvm -pic-level 1 -pic-is-pie %s -o - | FileCheck %s -check-prefix=CHECK-SMALLPIC -check-prefix=CHECK-SMALLPIE +// RUN: %clang_cc1 -triple s390x-ibm-linux -emit-llvm -pic-level 2 -pic-is-pie -no-pic-data-is-text-relative %s -o - | FileCheck %s -check-prefix=CHECK-NO-PIC-DATA-TEXT-REL +// RUN: %clang_cc1 -triple s390x-ibm-linux -emit-llvm -pic-level 2 -pic-is-pie %s -o - | FileCheck %s -check-prefix=CHECK-PIC-DATA-TEXT-REL // CHECK-BIGPIC: !llvm.module.flags = !{{{.*}}} // CHECK-BIGPIC: ![[#]] = !{i32 8, !"PIC Level", i32 2} @@ -10,3 +12,5 @@ // CHECK-NOPIE-NOT: PIE Level // CHECK-BIGPIE: ![[#]] = !{i32 7, !"PIE Level", i32 2} // CHECK-SMALLPIE: ![[#]] = !{i32 7, !"PIE Level", i32 1} +// CHECK-NO-PIC-DATA-TEXT-REL: ![[#]] = !{i32 1, !"no_pic_data_is_text_relative", i32 1} +// CHECK-PIC-DATA-TEXT-REL-NOT: "no_pic_data_is_text_relative" Index: clang/test/Driver/pic.c =================================================================== --- clang/test/Driver/pic.c +++ clang/test/Driver/pic.c @@ -1,5 +1,5 @@ -// Test the driver's control over the PIC behavior. These consist of tests of -// the relocation model flags and the pic level flags passed to CC1. +// Test the driver's control over the PIC behavior. These mainly consist of +// tests of the relocation model flags and the pic level flags passed to CC1. // // CHECK-NO-PIC: "-mrelocation-model" "static" // CHECK-NO-PIC-NOT: "-pic-level" @@ -45,6 +45,10 @@ // // CHECK-NO-UNUSED-ARG-NOT: argument unused during compilation // +// CHECK-NO-PIC-DATA-TEXT-REL: "-no-pic-data-is-text-relative" +// CHECK-PIC-DATA-TEXT-REL-NOT: "-no-pic-data-is-text-relative" +// CHECK-NO-PIC-DATA-TEXT-REL-NON-SYSTEMZ: error: unsupported option '-mno-pic-data-is-text-relative' for target 'arm-arm-none-eabi' +// // RUN: %clang -c %s -target i386-unknown-unknown -### 2>&1 \ // RUN: | FileCheck %s --check-prefix=CHECK-NO-PIC // RUN: %clang -c %s -target i386-unknown-unknown -fpic -### 2>&1 \ @@ -313,3 +317,10 @@ // RUN: | FileCheck %s --check-prefix=CHECK-PIC2 // RUN: %clang -fPIC -c %s -target armv7-pc-windows-gnu -### 2>&1 \ // RUN: | FileCheck %s --check-prefix=CHECK-NO-PIC + +// RUN: %clang -c -target s390x-linux-gnu -mno-pic-data-is-text-relative %s \ +// RUN: -### 2>&1 | FileCheck %s --check-prefix=CHECK-NO-PIC-DATA-TEXT-REL +// RUN: %clang -c -target s390x-linux-gnu -mpic-data-is-text-relative %s -### \ +// RUN: 2>&1 | FileCheck %s --check-prefix=CHECK-PIC-DATA-TEXT-REL +// RUN: %clang -c -target arm-arm-none-eabi -mno-pic-data-is-text-relative %s \ +// RUN: -### 2>&1 | FileCheck %s --check-prefix=CHECK-NO-PIC-DATA-TEXT-REL-NON-SYSTEMZ Index: llvm/lib/Target/SystemZ/SystemZISelLowering.cpp =================================================================== --- llvm/lib/Target/SystemZ/SystemZISelLowering.cpp +++ llvm/lib/Target/SystemZ/SystemZISelLowering.cpp @@ -3209,9 +3209,12 @@ int64_t Offset = Node->getOffset(); EVT PtrVT = getPointerTy(DAG.getDataLayout()); CodeModel::Model CM = DAG.getTarget().getCodeModel(); + const Module *M = DAG.getMachineFunction().getFunction().getParent(); + bool NoPicDataIsTextRelative = + M->getModuleFlag("no_pic_data_is_text_relative"); SDValue Result; - if (Subtarget.isPC32DBLSymbol(GV, CM)) { + if (!NoPicDataIsTextRelative && Subtarget.isPC32DBLSymbol(GV, CM)) { if (isInt<32>(Offset)) { // Assign anchors at 1<<12 byte boundaries. uint64_t Anchor = Offset & ~uint64_t(0xfff); Index: llvm/test/CodeGen/SystemZ/no-pic-data-is-text-rel.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/SystemZ/no-pic-data-is-text-rel.ll @@ -0,0 +1,33 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=s390x-linux-gnu < %s | FileCheck %s +; +; Test that an internal global value is accessed via GOT if the +; "no_pic_data_is_text_relative" module flag is present. + +@A_glob = global i32 0 +@B_loc = internal global i32 0 + +define signext i32 @LocFun() { +; CHECK-LABEL: LocFun: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: lgrl %r1, B_loc@GOT +; CHECK-NEXT: lgrl %r2, A_glob@GOT +; CHECK-NEXT: l %r0, 0(%r1) +; CHECK-NEXT: a %r0, 0(%r2) +; CHECK-NEXT: lgfr %r2, %r0 +; CHECK-NEXT: st %r0, 0(%r1) +; CHECK-NEXT: br %r14 +entry: + %0 = load i32, ptr @A_glob, align 4 + %1 = load i32, ptr @B_loc, align 4 + %add = add nsw i32 %1, %0 + store i32 %add, ptr @B_loc, align 4 + ret i32 %add +} + +!llvm.module.flags = !{!0, !1, !2, !3} + +!0 = !{i32 1, !"wchar_size", i32 4} +!1 = !{i32 8, !"PIC Level", i32 2} +!2 = !{i32 7, !"PIE Level", i32 2} +!3 = !{i32 1, !"no_pic_data_is_text_relative", i32 1} Index: llvm/test/CodeGen/SystemZ/pic-data-is-text-rel.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/SystemZ/pic-data-is-text-rel.ll @@ -0,0 +1,32 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=s390x-linux-gnu < %s | FileCheck %s +; +; Test that an internal global value is not accessed via GOT if the +; "no_pic_data_is_text_relative" module flag is absent. + +@A_glob = global i32 0 +@B_loc = internal global i32 0 + +define signext i32 @LocFun() { +; CHECK-LABEL: LocFun: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: lgrl %r1, A_glob@GOT +; CHECK-NEXT: lrl %r0, B_loc +; CHECK-NEXT: a %r0, 0(%r1) +; CHECK-NEXT: lgfr %r2, %r0 +; CHECK-NEXT: strl %r0, B_loc +; CHECK-NEXT: br %r14 +entry: + %0 = load i32, ptr @A_glob, align 4 + %1 = load i32, ptr @B_loc, align 4 + %add = add nsw i32 %1, %0 + store i32 %add, ptr @B_loc, align 4 + ret i32 %add +} + +!llvm.module.flags = !{!0, !1, !2} + +!0 = !{i32 1, !"wchar_size", i32 4} +!1 = !{i32 8, !"PIC Level", i32 2} +!2 = !{i32 7, !"PIE Level", i32 2} +