weimingz updated this revision to Diff 85446.
weimingz edited the summary of this revision.
weimingz added a comment.

As Eli sugguested, it's better to check it in Sema. In order to access 
RelocationModel in Sema, we moved it from CodeGenOpts to LangOpts


https://reviews.llvm.org/D28526

Files:
  include/clang/Basic/LangOptions.def
  include/clang/Basic/LangOptions.h
  include/clang/Frontend/CodeGenOptions.h
  lib/AST/ExprConstant.cpp
  lib/CodeGen/BackendUtil.cpp
  lib/Frontend/CodeGenOptions.cpp
  lib/Frontend/CompilerInvocation.cpp
  test/CodeGen/arm-ropi-rwpi.c
  test/Sema/ropi-rwpi.c

Index: test/Sema/ropi-rwpi.c
===================================================================
--- /dev/null
+++ test/Sema/ropi-rwpi.c
@@ -0,0 +1,65 @@
+// OK with local initialization, rwpi with const gv and ropi with non-const gv.
+// RUN: %clang_cc1 -triple armv7 -DDEFAULT -fsyntax-only -verify %s
+// RUN: %clang_cc1 -triple armv7 -DROPI -mrelocation-model ropi -fsyntax-only -verify %s
+// RUN: %clang_cc1 -triple armv7 -DRWPI -mrelocation-model rwpi -fsyntax-only -verify %s
+// RUN: %clang_cc1 -triple armv7 -DROPI -DRWPI -mrelocation-model ropi-rwpi -fsyntax-only -verify %s
+
+extern int func(const int* const []);
+
+extern int gv;
+extern const int c_gv;
+
+void *p1 = &func;
+const void *p2 = &c_gv;
+const int *p_compound_literal_c = &(const int){1};
+
+void ropi_test() {
+  static void *sp1 = &func;
+  static const void *sp2 = &c_gv;
+  static char(*x)[7] = &"abcdef";
+  static const void *x2 = &__func__;
+  static const int *const arr[2] = {&c_gv, &c_gv};
+  static void *addr = &&label1;
+label1:
+  return;
+}
+
+void *p3 = &gv;
+int *p_compound_literal = &(int){1};
+
+void rwpi_test() {
+  static void *sp1 = &gv;
+  static int *const arr[2] = {&gv, &gv};
+}
+
+unsigned test() {
+  unsigned a = (unsigned)&func;
+  unsigned b = (unsigned)&gv;
+  unsigned c = (unsigned)&c_gv;
+  return a + b + c;
+}
+
+#ifdef DEFAULT
+// expected-no-diagnostics
+#endif
+
+#if defined(ROPI)
+// expected-error@12 {{initializer element is not a compile-time constant}}
+// expected-error@13 {{initializer element is not a compile-time constant}}
+// expected-error@14 {{initializer element is not a compile-time constant}}
+
+// expected-error@17 {{initializer element is not a compile-time constant}}
+// expected-error@18 {{initializer element is not a compile-time constant}}
+// expected-error@19 {{initializer element is not a compile-time constant}}
+// expected-error@20 {{initializer element is not a compile-time constant}}
+// expected-error@21 {{initializer element is not a compile-time constant}}
+// expected-error@22 {{initializer element is not a compile-time constant}}
+#endif
+
+#if defined(RWPI)
+// expected-error@27 {{initializer element is not a compile-time constant}}
+// expected-error@28 {{initializer element is not a compile-time constant}}
+
+// expected-error@31 {{initializer element is not a compile-time constant}}
+// expected-error@32 {{initializer element is not a compile-time constant}}
+#endif
Index: test/CodeGen/arm-ropi-rwpi.c
===================================================================
--- /dev/null
+++ test/CodeGen/arm-ropi-rwpi.c
@@ -0,0 +1,32 @@
+// REQUIRES: arm-registered-target
+
+// Below tests check if memcpy is not generated with ropi/rwpi for local var initialization.
+// RUN: %clang_cc1 -triple armv7 -S -emit-llvm -o - %s | FileCheck %s --check-prefix=DEFAULT
+// RUN: %clang_cc1 -triple armv7 -S -emit-llvm -mrelocation-model ropi  -o - %s | FileCheck %s --check-prefix=ROPI
+// RUN: %clang_cc1 -triple armv7 -S -emit-llvm -mrelocation-model rwpi  -o - %s | FileCheck %s --check-prefix=RWPI
+// RUN: %clang_cc1 -triple armv7 -S -emit-llvm -mrelocation-model ropi-rwpi  -o - %s | FileCheck %s --check-prefix=ROPI_RWPI
+
+extern int gv;
+extern const int c_gv;
+
+void test_local() {
+// DEFAULT-LABEL: @test_local
+// DEFAULT: call void @{{llvm.memcpy.*@test_local.x}}
+// DEFAULT: call void @{{llvm.memcpy.*@test_local.y}}
+
+// ROPI-LABEL: @test_local
+// ROPI: call void @{{llvm.memcpy.*@test_local.x}}
+// ROPI-NOT: call void@llvm.memcpy
+
+// RWPI-LABEL: @test_local
+// RWPI-NOT: call void@{{llvm.memcpy.*@test_local.x}}
+// RWPI: call void @{{llvm.memcpy.*@test_local.y}}
+
+// ROPI_RWPI-LABEL: @test_local
+// ROPI_RWPI-NOT: call void @llvm.memcpy
+
+  const int *x[] = {&gv, &gv, &gv}; // This is OK, no diagnostic.
+  func(x);
+  const int *y[] = {&c_gv, &c_gv, &c_gv}; // This is OK, no diagnostic.
+  func(y);
+}
Index: lib/Frontend/CompilerInvocation.cpp
===================================================================
--- lib/Frontend/CompilerInvocation.cpp
+++ lib/Frontend/CompilerInvocation.cpp
@@ -610,7 +610,6 @@
                       Args.hasArg(OPT_cl_unsafe_math_optimizations) ||
                       Args.hasArg(OPT_cl_fast_relaxed_math);
   Opts.UnwindTables = Args.hasArg(OPT_munwind_tables);
-  Opts.RelocationModel = Args.getLastArgValue(OPT_mrelocation_model, "pic");
   Opts.ThreadModel = Args.getLastArgValue(OPT_mthread_model, "posix");
   if (Opts.ThreadModel != "posix" && Opts.ThreadModel != "single")
     Diags.Report(diag::err_drv_invalid_value)
@@ -2008,6 +2007,19 @@
   Opts.AlignDouble = Args.hasArg(OPT_malign_double);
   Opts.PICLevel = getLastArgIntValue(Args, OPT_pic_level, 0, Diags);
   Opts.PIE = Args.hasArg(OPT_pic_is_pie);
+  // Keep this synced with the equivalent code in tools/driver/cc1as_main.cpp.
+  llvm::Reloc::Model RM;
+  RM = llvm::StringSwitch<llvm::Reloc::Model>(
+           Args.getLastArgValue(OPT_mrelocation_model, "pic"))
+           .Case("static", llvm::Reloc::Static)
+           .Case("pic", llvm::Reloc::PIC_)
+           .Case("ropi", llvm::Reloc::ROPI)
+           .Case("rwpi", llvm::Reloc::RWPI)
+           .Case("ropi-rwpi", llvm::Reloc::ROPI_RWPI)
+           .Case("dynamic-no-pic", llvm::Reloc::DynamicNoPIC)
+           .Default(llvm::Reloc::PIC_);
+  Opts.setRelocationModel(RM);
+
   Opts.Static = Args.hasArg(OPT_static_define);
   Opts.DumpRecordLayoutsSimple = Args.hasArg(OPT_fdump_record_layouts_simple);
   Opts.DumpRecordLayouts = Opts.DumpRecordLayoutsSimple
Index: lib/Frontend/CodeGenOptions.cpp
===================================================================
--- lib/Frontend/CodeGenOptions.cpp
+++ lib/Frontend/CodeGenOptions.cpp
@@ -16,8 +16,6 @@
 #define CODEGENOPT(Name, Bits, Default) Name = Default;
 #define ENUM_CODEGENOPT(Name, Type, Bits, Default) set##Name(Default);
 #include "clang/Frontend/CodeGenOptions.def"
-
-  RelocationModel = "pic";
   memcpy(CoverageVersion, "402*", 4);
 }
 
Index: lib/CodeGen/BackendUtil.cpp
===================================================================
--- lib/CodeGen/BackendUtil.cpp
+++ lib/CodeGen/BackendUtil.cpp
@@ -509,17 +509,6 @@
   std::string FeaturesStr =
       llvm::join(TargetOpts.Features.begin(), TargetOpts.Features.end(), ",");
 
-  // Keep this synced with the equivalent code in tools/driver/cc1as_main.cpp.
-  llvm::Optional<llvm::Reloc::Model> RM;
-  RM = llvm::StringSwitch<llvm::Reloc::Model>(CodeGenOpts.RelocationModel)
-           .Case("static", llvm::Reloc::Static)
-           .Case("pic", llvm::Reloc::PIC_)
-           .Case("ropi", llvm::Reloc::ROPI)
-           .Case("rwpi", llvm::Reloc::RWPI)
-           .Case("ropi-rwpi", llvm::Reloc::ROPI_RWPI)
-           .Case("dynamic-no-pic", llvm::Reloc::DynamicNoPIC);
-  assert(RM.hasValue() && "invalid PIC model!");
-
   CodeGenOpt::Level OptLevel;
   switch (CodeGenOpts.OptimizationLevel) {
   default:
@@ -616,8 +605,9 @@
       Options.MCOptions.IASSearchPaths.push_back(
           Entry.IgnoreSysRoot ? Entry.Path : HSOpts.Sysroot + Entry.Path);
 
-  TM.reset(TheTarget->createTargetMachine(Triple, TargetOpts.CPU, FeaturesStr,
-                                          Options, RM, CM, OptLevel));
+  TM.reset(TheTarget->createTargetMachine(
+      Triple, TargetOpts.CPU, FeaturesStr, Options,
+      LangOpts.getRelocationModel(), CM, OptLevel));
 }
 
 bool EmitAssemblyHelper::AddEmitPasses(legacy::PassManager &CodeGenPasses,
Index: lib/AST/ExprConstant.cpp
===================================================================
--- lib/AST/ExprConstant.cpp
+++ lib/AST/ExprConstant.cpp
@@ -1544,7 +1544,6 @@
 static bool CheckLValueConstantExpression(EvalInfo &Info, SourceLocation Loc,
                                           QualType Type, const LValue &LVal) {
   bool IsReferenceType = Type->isReferenceType();
-
   APValue::LValueBase Base = LVal.getLValueBase();
   const SubobjectDesignator &Designator = LVal.getLValueDesignator();
 
@@ -1564,6 +1563,42 @@
     // Don't allow references to temporaries to escape.
     return false;
   }
+
+  auto RM = Info.getLangOpts().getRelocationModel();
+  bool IsROPI = RM == llvm::Reloc::ROPI_RWPI || RM == llvm::Reloc::ROPI;
+  bool IsRWPI = RM == llvm::Reloc::ROPI_RWPI || RM == llvm::Reloc::RWPI;
+  if (Base && (IsROPI || IsRWPI)) {
+    if (const ValueDecl *D = Base.dyn_cast<const ValueDecl *>()) {
+      assert((isa<VarDecl>(D) || isa<FunctionDecl>(D)) &&
+             "unexpected ValueDecl type");
+      bool IsConstTyped = D->getType().isConstant(Info.Ctx);
+      if (isa<VarDecl>(D)) {
+        if ((IsRWPI && !IsConstTyped) || (IsROPI && IsConstTyped))
+          return false;
+      } else if (IsROPI) // Check ROPI with FunctionDecl.
+        return false;
+    }
+    // Check if Base is a read-only expr (e.g. StringLiteral) or compound
+    // literals that can be mutable or constant. Here only C related exprs are
+    // checked since C++ is disabled for ropi/rwpi.
+    if (const Expr *E = Base.dyn_cast<const Expr *>()) {
+      bool IsConstTyped = E->getType().isConstant(Info.Ctx);
+      switch (E->getStmtClass()) {
+      case Expr::CompoundLiteralExprClass:
+        if ((IsROPI && IsConstTyped) || (IsRWPI && !IsConstTyped))
+          return false;
+        break;
+      case Expr::StringLiteralClass:
+      case Expr::PredefinedExprClass:
+      case Expr::AddrLabelExprClass:
+        if (IsROPI)
+          return false;
+      default:
+        break;
+      }
+    }
+  }
+
   assert((Info.checkingPotentialConstantExpression() ||
           LVal.getLValueCallIndex() == 0) &&
          "have call index for global lvalue");
Index: include/clang/Frontend/CodeGenOptions.h
===================================================================
--- include/clang/Frontend/CodeGenOptions.h
+++ include/clang/Frontend/CodeGenOptions.h
@@ -142,9 +142,6 @@
   /// in the backend for setting the name in the skeleton cu.
   std::string SplitDwarfFile;
 
-  /// The name of the relocation model to use.
-  std::string RelocationModel;
-
   /// The thread model to use
   std::string ThreadModel;
 
Index: include/clang/Basic/LangOptions.h
===================================================================
--- include/clang/Basic/LangOptions.h
+++ include/clang/Basic/LangOptions.h
@@ -20,6 +20,7 @@
 #include "clang/Basic/ObjCRuntime.h"
 #include "clang/Basic/Sanitizers.h"
 #include "clang/Basic/Visibility.h"
+#include "llvm/Support/CodeGen.h"
 #include <string>
 #include <vector>
 
@@ -48,7 +49,8 @@
 class LangOptions : public LangOptionsBase {
 public:
   typedef clang::Visibility Visibility;
-  
+  typedef llvm::Reloc::Model RelocModel;
+
   enum GCMode { NonGC, GCOnly, HybridGC };
   enum StackProtectorMode { SSPOff, SSPOn, SSPStrong, SSPReq };
   
Index: include/clang/Basic/LangOptions.def
===================================================================
--- include/clang/Basic/LangOptions.def
+++ include/clang/Basic/LangOptions.def
@@ -223,6 +223,7 @@
 LANGOPT(ObjCWeak            , 1, 0, "Objective-C __weak in ARC and MRC files")
 LANGOPT(ObjCSubscriptingLegacyRuntime         , 1, 0, "Subscripting support in legacy ObjectiveC runtime")
 LANGOPT(FakeAddressSpaceMap , 1, 0, "OpenCL fake address space map")
+ENUM_LANGOPT(RelocationModel , RelocModel, 3, llvm::Reloc::PIC_, "Relocation model")
 ENUM_LANGOPT(AddressSpaceMapMangling , AddrSpaceMapMangling, 2, ASMM_Target, "OpenCL address space map mangling mode")
 LANGOPT(IncludeDefaultHeader, 1, 0, "Include default header file for OpenCL")
 BENIGN_LANGOPT(DelayedTemplateParsing , 1, 0, "delayed template parsing")
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to