]> granicus.if.org Git - clang/commitdiff
Implement support for -fwrapv, rdar://7221421
authorChris Lattner <sabre@nondot.org>
Sat, 26 Jun 2010 21:25:03 +0000 (21:25 +0000)
committerChris Lattner <sabre@nondot.org>
Sat, 26 Jun 2010 21:25:03 +0000 (21:25 +0000)
As part of this, pull together trapv handling into the same enum.

This also add support for NSW multiplies.

This also makes PCH disagreement on overflow behavior silent, since it
really doesn't matter except for warnings and codegen (no macros get
defined etc).

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@106956 91177308-0d34-0410-b5e6-96231b3b80d8

13 files changed:
include/clang/Basic/DiagnosticFrontendKinds.td
include/clang/Basic/LangOptions.h
include/clang/Driver/CC1Options.td
include/clang/Driver/Options.td
lib/CodeGen/CGExprScalar.cpp
lib/Driver/Tools.cpp
lib/Frontend/CompilerInvocation.cpp
lib/Frontend/PCHReader.cpp
lib/Frontend/PCHWriter.cpp
test/CodeGen/builtins-ppc-altivec.c
test/CodeGen/exprs.c
test/CodeGen/extern-inline.c
test/CodeGen/integer-overflow.c [new file with mode: 0644]

index 50937790d89a004cf1c39899c13a1d499850c548..989ec38d29500d05623137577bcaeb974044a9ab 100644 (file)
@@ -189,9 +189,6 @@ def warn_pch_math_errno : Error<
     "math functions %select{do not respect|respect}0 'errno' in PCH "
     "file but they are currently set to %select{not respect|respect}1 "
     "'errno'">;
-def warn_pch_overflow_checking : Error<
-    "signed integer overflow checking was %select{disabled|enabled}0 in PCH "
-    "file but is currently %select{disabled|enabled}1">;
 def warn_pch_optimize : Error<
     "the macro '__OPTIMIZE__' was %select{not defined|defined}0 in "
     "the PCH file but is currently %select{undefined|defined}1">;
index cd9849d5dbf0673443f13f49a405069db0afc837..c09d8aab44af8c4718451ab58507067c5c61ca28 100644 (file)
@@ -66,9 +66,6 @@ public:
   unsigned MathErrno         : 1; // Math functions must respect errno
                                   // (modulo the platform support).
 
-  unsigned OverflowChecking  : 1; // Extension to call a handler function when
-                                  // signed integer arithmetic overflows.
-
   unsigned HeinousExtensions : 1; // Extensions that we really don't like and
                                   // may be ripped out at any time.
 
@@ -109,15 +106,12 @@ public:
   unsigned NoBitFieldTypeAlign : 1;
 
 private:
-  unsigned GC : 2;                // Objective-C Garbage Collection modes.  We
-                                  // declare this enum as unsigned because MSVC
-                                  // insists on making enums signed.  Set/Query
-                                  // this value using accessors.
+  // We declare multibit enums as unsigned because MSVC insists on making enums
+  // signed.  Set/Query these values using accessors.
+  unsigned GC : 2;                // Objective-C Garbage Collection modes.
   unsigned SymbolVisibility  : 3; // Symbol's visibility.
-  unsigned StackProtector    : 2; // Whether stack protectors are on. We declare
-                                  // this enum as unsigned because MSVC insists
-                                  // on making enums signed.  Set/Query this
-                                  // value using accessors.
+  unsigned StackProtector    : 2; // Whether stack protectors are on.
+  unsigned SignedOverflowBehavior : 2; // How to handle signed integer overflow.
 
 public:
   unsigned InstantiationDepth;    // Maximum template instantiation depth.
@@ -131,6 +125,12 @@ public:
     Protected,
     Hidden
   };
+  
+  enum SignedOverflowBehaviorTy {
+    SOB_Undefined,  // Default C standard behavior.
+    SOB_Defined,    // -fwrapv
+    SOB_Trapping    // -ftrapv
+  };
 
   LangOptions() {
     Trigraphs = BCPLComment = Bool = DollarIdents = AsmPreprocessor = 0;
@@ -154,14 +154,15 @@ public:
     Blocks = 0;
     EmitAllDecls = 0;
     MathErrno = 1;
-
+    SignedOverflowBehavior = SOB_Undefined;
+    
     AssumeSaneOperatorNew = 1;
 
     // FIXME: The default should be 1.
     AccessControl = 0;
     ElideConstructors = 1;
 
-    OverflowChecking = 0;
+    SignedOverflowBehavior = 0;
     ObjCGCBitmapPrint = 0;
 
     InstantiationDepth = 1024;
@@ -197,6 +198,13 @@ public:
     return (VisibilityMode) SymbolVisibility;
   }
   void setVisibilityMode(VisibilityMode v) { SymbolVisibility = (unsigned) v; }
+  
+  SignedOverflowBehaviorTy getSignedOverflowBehavior() const {
+    return (SignedOverflowBehaviorTy)SignedOverflowBehavior;
+  }
+  void setSignedOverflowBehavior(SignedOverflowBehaviorTy V) {
+    SignedOverflowBehavior = (unsigned)V;
+  }
 };
 
 }  // end namespace clang
index c1de8b1d3a908a585b3e9d9e5cce7d2d12e5fc02..65284fbc9dccc06357831858f9dbf51c9b6ffd14 100644 (file)
@@ -426,6 +426,8 @@ def fobjc_nonfragile_abi2 : Flag<"-fobjc-nonfragile-abi2">,
   HelpText<"enable objective-c's enhanced nonfragile abi">;
 def ftrapv : Flag<"-ftrapv">,
   HelpText<"Trap on integer overflow">;
+def fwrapv : Flag<"-fwrapv">,
+  HelpText<"Treat signed integer overflow as two's complement">;
 def pic_level : Separate<"-pic-level">,
   HelpText<"Value for __PIC__">;
 def pthread : Flag<"-pthread">,
index 129ce5e1397886cdf832e46312081076f13e6fb7..1e3669597f0bd68321cd7774eb7afaed0a1aeaf3 100644 (file)
@@ -388,6 +388,7 @@ def fuse_cxa_atexit : Flag<"-fuse-cxa-atexit">, Group<f_Group>;
 def fverbose_asm : Flag<"-fverbose-asm">, Group<f_Group>;
 def fvisibility_EQ : Joined<"-fvisibility=">, Group<f_Group>;
 def fvisibility_inlines_hidden : Flag<"-fvisibility-inlines-hidden">, Group<f_Group>;
+def fwrapv : Flag<"-fwrapv">, Group<f_Group>;
 def fwritable_strings : Flag<"-fwritable-strings">, Group<f_Group>;
 def fzero_initialized_in_bss : Flag<"-fzero-initialized-in-bss">, Group<f_Group>;
 def ffunction_sections: Flag <"-ffunction-sections">, Group<f_Group>;
index 4372279175e6705cadd3163eaf315947b8a33681..72da22695f88c556553117dc4d47efd52720d919 100644 (file)
@@ -291,9 +291,17 @@ public:
 
   // Binary Operators.
   Value *EmitMul(const BinOpInfo &Ops) {
-    if (CGF.getContext().getLangOptions().OverflowChecking
-        && Ops.Ty->isSignedIntegerType())
-      return EmitOverflowCheckedBinOp(Ops);
+    if (Ops.Ty->isSignedIntegerType()) {
+      switch (CGF.getContext().getLangOptions().getSignedOverflowBehavior()) {
+      case LangOptions::SOB_Undefined:
+        return Builder.CreateNSWMul(Ops.LHS, Ops.RHS, "mul");
+      case LangOptions::SOB_Defined:
+        return Builder.CreateMul(Ops.LHS, Ops.RHS, "mul");
+      case LangOptions::SOB_Trapping:
+        return EmitOverflowCheckedBinOp(Ops);
+      }
+    }
+    
     if (Ops.LHS->getType()->isFPOrFPVectorTy())
       return Builder.CreateFMul(Ops.LHS, Ops.RHS, "mul");
     return Builder.CreateMul(Ops.LHS, Ops.RHS, "mul");
@@ -1119,9 +1127,17 @@ Value *ScalarExprEmitter::VisitUnaryMinus(const UnaryOperator *E) {
     return Builder.CreateFNeg(Op, "neg");
   
   // Signed integer overflow is undefined behavior.
-  if (E->getType()->isSignedIntegerType())
-    return Builder.CreateNSWNeg(Op, "neg");
-    
+  if (E->getType()->isSignedIntegerType()) {
+    switch (CGF.getContext().getLangOptions().getSignedOverflowBehavior()) {
+    case LangOptions::SOB_Trapping:
+      // FIXME: Implement -ftrapv for negate.
+    case LangOptions::SOB_Undefined:
+      return Builder.CreateNSWNeg(Op, "neg");
+    case LangOptions::SOB_Defined:
+      return Builder.CreateNeg(Op, "neg");
+    }
+  }
+  
   return Builder.CreateNeg(Op, "neg");
 }
 
@@ -1397,17 +1413,20 @@ Value *ScalarExprEmitter::EmitOverflowCheckedBinOp(const BinOpInfo &Ops) {
 
 Value *ScalarExprEmitter::EmitAdd(const BinOpInfo &Ops) {
   if (!Ops.Ty->isAnyPointerType()) {
-    if (CGF.getContext().getLangOptions().OverflowChecking &&
-        Ops.Ty->isSignedIntegerType())
-      return EmitOverflowCheckedBinOp(Ops);
-
+    if (Ops.Ty->isSignedIntegerType()) {
+      switch (CGF.getContext().getLangOptions().getSignedOverflowBehavior()) {
+      case LangOptions::SOB_Undefined:
+        return Builder.CreateNSWAdd(Ops.LHS, Ops.RHS, "add");
+      case LangOptions::SOB_Defined:
+        return Builder.CreateAdd(Ops.LHS, Ops.RHS, "add");
+      case LangOptions::SOB_Trapping:
+        return EmitOverflowCheckedBinOp(Ops);
+      }
+    }
+    
     if (Ops.LHS->getType()->isFPOrFPVectorTy())
       return Builder.CreateFAdd(Ops.LHS, Ops.RHS, "add");
 
-    // Signed integer overflow is undefined behavior.
-    if (Ops.Ty->isSignedIntegerType())
-      return Builder.CreateNSWAdd(Ops.LHS, Ops.RHS, "add");
-
     return Builder.CreateAdd(Ops.LHS, Ops.RHS, "add");
   }
 
@@ -1473,17 +1492,20 @@ Value *ScalarExprEmitter::EmitAdd(const BinOpInfo &Ops) {
 
 Value *ScalarExprEmitter::EmitSub(const BinOpInfo &Ops) {
   if (!isa<llvm::PointerType>(Ops.LHS->getType())) {
-    if (CGF.getContext().getLangOptions().OverflowChecking
-        && Ops.Ty->isSignedIntegerType())
-      return EmitOverflowCheckedBinOp(Ops);
-
+    if (Ops.Ty->isSignedIntegerType()) {
+      switch (CGF.getContext().getLangOptions().getSignedOverflowBehavior()) {
+      case LangOptions::SOB_Undefined:
+        return Builder.CreateNSWSub(Ops.LHS, Ops.RHS, "sub");
+      case LangOptions::SOB_Defined:
+        return Builder.CreateSub(Ops.LHS, Ops.RHS, "sub");
+      case LangOptions::SOB_Trapping:
+        return EmitOverflowCheckedBinOp(Ops);
+      }
+    }
+    
     if (Ops.LHS->getType()->isFPOrFPVectorTy())
       return Builder.CreateFSub(Ops.LHS, Ops.RHS, "sub");
 
-    // Signed integer overflow is undefined behavior.
-    if (Ops.Ty->isSignedIntegerType())
-      return Builder.CreateNSWSub(Ops.LHS, Ops.RHS, "sub");
-
     return Builder.CreateSub(Ops.LHS, Ops.RHS, "sub");
   }
 
index e7cff8ea8973b403add78adb0231843fca5274fc..22b14825ef3307da2f7fdc498c58a439979a4408 100644 (file)
@@ -1182,6 +1182,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
   Args.AddLastArg(CmdArgs, options::OPT_fdiagnostics_print_source_range_info);
   Args.AddLastArg(CmdArgs, options::OPT_ftime_report);
   Args.AddLastArg(CmdArgs, options::OPT_ftrapv);
+  Args.AddLastArg(CmdArgs, options::OPT_fwrapv);
   Args.AddLastArg(CmdArgs, options::OPT_fwritable_strings);
 
   Args.AddLastArg(CmdArgs, options::OPT_pthread);
index e7a75a619dca7e9b010a7d899279604e252542a7..76770ae36c0cb7b674f93743a70096bfcff50e87 100644 (file)
@@ -549,8 +549,11 @@ static void LangOptsToArgs(const LangOptions &Opts,
     Res.push_back("-femit-all-decls");
   if (Opts.MathErrno)
     Res.push_back("-fmath-errno");
-  if (Opts.OverflowChecking)
-    Res.push_back("-ftrapv");
+  switch (Opts.getSignedOverflowBehavior()) {
+  case LangOptions::SOB_Undefined: break;
+  case LangOptions::SOB_Defined:   Res.push_back("-fwrapv"); break;
+  case LangOptions::SOB_Trapping:  Res.push_back("-ftrapv"); break;
+  }
   if (Opts.HeinousExtensions)
     Res.push_back("-fheinous-gnu-extensions");
   // Optimize is implicit.
@@ -1257,8 +1260,11 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
 
   if (Args.hasArg(OPT_fvisibility_inlines_hidden))
     Opts.InlineVisibilityHidden = 1;
-    
-  Opts.OverflowChecking = Args.hasArg(OPT_ftrapv);
+  
+  if (Args.hasArg(OPT_ftrapv))
+    Opts.setSignedOverflowBehavior(LangOptions::SOB_Trapping); 
+  else if (Args.hasArg(OPT_fwrapv))
+    Opts.setSignedOverflowBehavior(LangOptions::SOB_Defined); 
 
   // Mimicing gcc's behavior, trigraphs are only enabled if -trigraphs
   // is specified, or -std is set to a conforming mode.
index 5bd3c0481a0e8d23e328e211ed9e480dd9a20e55..c220e269c23513783c6131e009ac8c02d175dbb2 100644 (file)
@@ -93,7 +93,7 @@ PCHValidator::ReadLanguageOptions(const LangOptions &LangOpts) {
   PARSE_LANGOPT_IMPORTANT(Blocks, diag::warn_pch_blocks);
   PARSE_LANGOPT_BENIGN(EmitAllDecls);
   PARSE_LANGOPT_IMPORTANT(MathErrno, diag::warn_pch_math_errno);
-  PARSE_LANGOPT_IMPORTANT(OverflowChecking, diag::warn_pch_overflow_checking);
+  PARSE_LANGOPT_BENIGN(getSignedOverflowBehavior());
   PARSE_LANGOPT_IMPORTANT(HeinousExtensions,
                           diag::warn_pch_heinous_extensions);
   // FIXME: Most of the options below are benign if the macro wasn't
@@ -1915,7 +1915,8 @@ bool PCHReader::ParseLanguageOptions(
     PARSE_LANGOPT(Blocks);
     PARSE_LANGOPT(EmitAllDecls);
     PARSE_LANGOPT(MathErrno);
-    PARSE_LANGOPT(OverflowChecking);
+    LangOpts.setSignedOverflowBehavior((LangOptions::SignedOverflowBehaviorTy)
+                                       Record[Idx++]);
     PARSE_LANGOPT(HeinousExtensions);
     PARSE_LANGOPT(Optimize);
     PARSE_LANGOPT(OptimizeSize);
@@ -1926,13 +1927,10 @@ bool PCHReader::ParseLanguageOptions(
     PARSE_LANGOPT(AccessControl);
     PARSE_LANGOPT(CharIsSigned);
     PARSE_LANGOPT(ShortWChar);
-    LangOpts.setGCMode((LangOptions::GCMode)Record[Idx]);
-    ++Idx;
-    LangOpts.setVisibilityMode((LangOptions::VisibilityMode)Record[Idx]);
-    ++Idx;
+    LangOpts.setGCMode((LangOptions::GCMode)Record[Idx++]);
+    LangOpts.setVisibilityMode((LangOptions::VisibilityMode)Record[Idx++]);
     LangOpts.setStackProtectorMode((LangOptions::StackProtectorMode)
-                                   Record[Idx]);
-    ++Idx;
+                                   Record[Idx++]);
     PARSE_LANGOPT(InstantiationDepth);
     PARSE_LANGOPT(OpenCL);
     PARSE_LANGOPT(CatchUndefined);
index 3c42d474dc0851d5e28592942139132bdbbe0627..efed0f0a6c439a537c355b58ad6fb5a78d489f91 100644 (file)
@@ -833,11 +833,8 @@ void PCHWriter::WriteLanguageOptions(const LangOptions &LangOpts) {
   Record.push_back(LangOpts.MathErrno); // Math functions must respect errno
                                   // (modulo the platform support).
 
-  Record.push_back(LangOpts.OverflowChecking); // Extension to call a handler function when
-                                  // signed integer arithmetic overflows.
-
-  Record.push_back(LangOpts.HeinousExtensions); // Extensions that we really don't like and
-                                  // may be ripped out at any time.
+  Record.push_back(LangOpts.getSignedOverflowBehavior());
+  Record.push_back(LangOpts.HeinousExtensions);
 
   Record.push_back(LangOpts.Optimize); // Whether __OPTIMIZE__ should be defined.
   Record.push_back(LangOpts.OptimizeSize); // Whether __OPTIMIZE_SIZE__ should be
index 1ffb05905afcfb4d042cfcedf2b8ac5c5f83e484..4b9c3d5c422f1346e2d3183543b13aac38fdc5c8 100644 (file)
@@ -428,13 +428,13 @@ int main ()
   res_vus = vec_mladd(vus, vus, vus);           // CHECK: mul <8 x i16>
                                                 // CHECK: add <8 x i16>
 
-  res_vs = vec_mladd(vus, vs, vs);              // CHECK: mul <8 x i16>
+  res_vs = vec_mladd(vus, vs, vs);              // CHECK: mul nsw <8 x i16>
                                                 // CHECK: add nsw <8 x i16>
 
-  res_vs = vec_mladd(vs, vus, vus);             // CHECK: mul <8 x i16>
+  res_vs = vec_mladd(vs, vus, vus);             // CHECK: mul nsw <8 x i16>
                                                 // CHECK: add nsw <8 x i16>
 
-  res_vs = vec_mladd(vs, vs, vs);               // CHECK: mul <8 x i16>
+  res_vs = vec_mladd(vs, vs, vs);               // CHECK: mul nsw <8 x i16>
                                                 // CHECK: add nsw <8 x i16>
 
   /* vec_mradds */
index a90ae58dc3f7faf8e0eafacc5b202a1ea05f81b4..d182ce81cab7eed6040081388f25e52e0f3c4c15 100644 (file)
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 %s -emit-llvm -o - 
 
 // PR1895
 // sizeof function
@@ -119,16 +119,3 @@ void f9(struct S *x) {
 void f10() {
   __builtin_sin(0);
 }
-
-// Tests for signed integer overflow stuff.
-// rdar://7432000
-void f11() {
-  // CHECK: define void @f11
-  extern volatile int f11G, a, b;
-  // CHECK: add nsw i32
-  f11G = a + b;
-  // CHECK: sub nsw i32
-  f11G = a - b;
-  // CHECK: sub nsw i32 0, 
-  f11G = -a;
-}
index 5dd9bfda574c98294e072510aaabeaad3949d77c..60f6d034bf1fda0cb22f5c92aced2ea28222fe2e 100644 (file)
@@ -19,7 +19,7 @@ int g2(void) {return f2(0,1);}
 static int f2(int a, int b) {return a*b;}
 // CHECK: load i32* %{{.*}}
 // CHECK: load i32* %{{.*}}
-// CHECK: mul i32 %{{.*}}, %{{.*}}
+// CHECK: mul nsw i32 %{{.*}}, %{{.*}}
 int h2(void) {return f2(1,2);}
 // CHECK: call i32 @f2
 
diff --git a/test/CodeGen/integer-overflow.c b/test/CodeGen/integer-overflow.c
new file mode 100644 (file)
index 0000000..7969216
--- /dev/null
@@ -0,0 +1,33 @@
+// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s --check-prefix=DEFAULT
+// RUN: %clang_cc1 %s -emit-llvm -o - -fwrapv | FileCheck %s --check-prefix=WRAPV
+// RUN: %clang_cc1 %s -emit-llvm -o - -ftrapv | FileCheck %s --check-prefix=TRAPV
+
+
+// Tests for signed integer overflow stuff.
+// rdar://7432000 rdar://7221421
+void test1() {
+  // DEFAULT: define void @test1
+  // WRAPV: define void @test1
+  // TRAPV: define void @test1
+  extern volatile int f11G, a, b;
+  
+  // DEFAULT: add nsw i32
+  // WRAPV: add i32
+  // TRAPV: llvm.sadd.with.overflow.i32
+  f11G = a + b;
+  
+  // DEFAULT: sub nsw i32
+  // WRAPV: sub i32
+  // TRAPV: llvm.ssub.with.overflow.i32
+  f11G = a - b;
+  
+  // DEFAULT: sub nsw i32 0, 
+  // WRAPV: sub i32 0, 
+  // TRAPV: sub nsw i32 0, 
+  f11G = -a;
+  
+  // DEFAULT: mul nsw i32
+  // WRAPV: mul i32
+  // TRAPV: llvm.smul.with.overflow.i32
+  f11G = a * b;
+}