]> granicus.if.org Git - clang/commitdiff
Attach attribute "trap-func-name" to call sites of llvm.trap and llvm.debugtrap.
authorAkira Hatanaka <ahatanaka@apple.com>
Thu, 2 Jul 2015 22:15:41 +0000 (22:15 +0000)
committerAkira Hatanaka <ahatanaka@apple.com>
Thu, 2 Jul 2015 22:15:41 +0000 (22:15 +0000)
This is needed to use clang's command line option "-ftrap-function" for LTO and
enable changing the trap function name on a per-call-site basis.

rdar://problem/21225723

Differential Revision: http://reviews.llvm.org/D10831

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

lib/CodeGen/BackendUtil.cpp
lib/CodeGen/CGBuiltin.cpp
lib/CodeGen/CGCall.cpp
lib/CodeGen/CGExpr.cpp
lib/CodeGen/CodeGenFunction.cpp
lib/CodeGen/CodeGenFunction.h
test/CodeGenCXX/trap-fnattr.cpp [new file with mode: 0644]

index 801b49f04c812cf8364df7aae1a5c3469f3b93c3..0bccad0570da4373a97997ac2f31af434cf52672 100644 (file)
@@ -536,7 +536,6 @@ TargetMachine *EmitAssemblyHelper::CreateTargetMachine(bool MustCreateTM) {
   Options.NoZerosInBSS = CodeGenOpts.NoZeroInitializedInBSS;
   Options.UnsafeFPMath = CodeGenOpts.UnsafeFPMath;
   Options.StackAlignmentOverride = CodeGenOpts.StackAlignment;
-  Options.TrapFuncName = CodeGenOpts.TrapFuncName;
   Options.PositionIndependentExecutable = LangOpts.PIELevel != 0;
   Options.FunctionSections = CodeGenOpts.FunctionSections;
   Options.DataSections = CodeGenOpts.DataSections;
index 8bd80085e65da2d651b35458851c546132de5ec6..2ec909b9aac58de210d0797f05ed379060fd54e2 100644 (file)
@@ -543,14 +543,10 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
     Value *F = CGM.getIntrinsic(Intrinsic::clear_cache);
     return RValue::get(Builder.CreateCall(F, {Begin, End}));
   }
-  case Builtin::BI__builtin_trap: {
-    Value *F = CGM.getIntrinsic(Intrinsic::trap);
-    return RValue::get(Builder.CreateCall(F, {}));
-  }
-  case Builtin::BI__debugbreak: {
-    Value *F = CGM.getIntrinsic(Intrinsic::debugtrap);
-    return RValue::get(Builder.CreateCall(F, {}));
-  }
+  case Builtin::BI__builtin_trap:
+    return RValue::get(EmitTrapCall(Intrinsic::trap));
+  case Builtin::BI__debugbreak:
+    return RValue::get(EmitTrapCall(Intrinsic::debugtrap));
   case Builtin::BI__builtin_unreachable: {
     if (SanOpts.has(SanitizerKind::Unreachable)) {
       SanitizerScope SanScope(this);
index 142966e7c011d9443e26fe9b8ae56fb85dcd97e8..0535c05da5d52aacde9a1ae17adc09ae94ffd540 100644 (file)
@@ -1452,6 +1452,8 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI,
     // Attributes that should go on the call site only.
     if (!CodeGenOpts.SimplifyLibCalls)
       FuncAttrs.addAttribute(llvm::Attribute::NoBuiltin);
+    if (!CodeGenOpts.TrapFuncName.empty())
+      FuncAttrs.addAttribute("trap-func-name", CodeGenOpts.TrapFuncName);
   } else {
     // Attributes that should go on the function, but not the call site.
     if (!CodeGenOpts.DisableFPElim) {
index 1a76afaf11589a17239ae6725b9f86aa2f002b7e..175763c4e815a730e7587076381e2661b1ed18e0 100644 (file)
@@ -2403,8 +2403,7 @@ void CodeGenFunction::EmitTrapCheck(llvm::Value *Checked) {
     TrapBB = createBasicBlock("trap");
     Builder.CreateCondBr(Checked, Cont, TrapBB);
     EmitBlock(TrapBB);
-    llvm::Value *F = CGM.getIntrinsic(llvm::Intrinsic::trap);
-    llvm::CallInst *TrapCall = Builder.CreateCall(F, {});
+    llvm::CallInst *TrapCall = EmitTrapCall(llvm::Intrinsic::trap);
     TrapCall->setDoesNotReturn();
     TrapCall->setDoesNotThrow();
     Builder.CreateUnreachable();
@@ -2415,6 +2414,18 @@ void CodeGenFunction::EmitTrapCheck(llvm::Value *Checked) {
   EmitBlock(Cont);
 }
 
+llvm::CallInst *CodeGenFunction::EmitTrapCall(llvm::Intrinsic::ID IntrID) {
+  llvm::CallInst *TrapCall =
+      Builder.CreateCall(CGM.getIntrinsic(IntrID), {});
+
+  if (!CGM.getCodeGenOpts().TrapFuncName.empty())
+    TrapCall->addAttribute(llvm::AttributeSet::FunctionIndex,
+                           "trap-func-name",
+                           CGM.getCodeGenOpts().TrapFuncName);
+
+  return TrapCall;
+}
+
 /// isSimpleArrayDecayOperand - If the specified expr is a simple decay from an
 /// array to pointer, return the array subexpression.
 static const Expr *isSimpleArrayDecayOperand(const Expr *E) {
index f1fc8c45f1ea50636b71bff7a4d1ee78019e1f70..1fca466e9244af6b61f42f0d45a7b7116e295fb6 100644 (file)
@@ -930,8 +930,9 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn,
       EmitCheck(std::make_pair(IsFalse, SanitizerKind::Return),
                 "missing_return", EmitCheckSourceLocation(FD->getLocation()),
                 None);
-    } else if (CGM.getCodeGenOpts().OptimizationLevel == 0)
-      Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::trap), {});
+    } else if (CGM.getCodeGenOpts().OptimizationLevel == 0) {
+      EmitTrapCall(llvm::Intrinsic::trap);
+    }
     Builder.CreateUnreachable();
     Builder.ClearInsertionPoint();
   }
index cc427c9c88931ac432779d4aa59622f4e7718154..fac71bf8a6c285f5053949cf6e2c04d24c8531ab 100644 (file)
@@ -2875,6 +2875,10 @@ public:
   /// conditional branch to it, for the -ftrapv checks.
   void EmitTrapCheck(llvm::Value *Checked);
 
+  /// \brief Emit a call to trap or debugtrap and attach function attribute
+  /// "trap-func-name" if specified.
+  llvm::CallInst *EmitTrapCall(llvm::Intrinsic::ID IntrID);
+
   /// \brief Create a check for a function parameter that may potentially be
   /// declared as non-null.
   void EmitNonNullArgCheck(RValue RV, QualType ArgType, SourceLocation ArgLoc,
diff --git a/test/CodeGenCXX/trap-fnattr.cpp b/test/CodeGenCXX/trap-fnattr.cpp
new file mode 100644 (file)
index 0000000..d9d6f81
--- /dev/null
@@ -0,0 +1,36 @@
+// RUN: %clang_cc1 -O0 -emit-llvm -ftrapv -ftrap-function=mytrap %s -o - | FileCheck %s -check-prefix=TRAPFUNC
+// RUN: %clang_cc1 -O0 -emit-llvm -ftrapv %s -o - | FileCheck %s -check-prefix=NOOPTION
+
+// TRAPFUNC-LABEL: define void @_Z12test_builtinv
+// TRAPFUNC: call void @llvm.trap() [[ATTR0:#[0-9]+]]
+
+// NOOPTION-LABEL: define void @_Z12test_builtinv
+// NOOPTION: call void @llvm.trap(){{$}}
+
+void test_builtin(void) {
+  __builtin_trap();
+}
+
+// TRAPFUNC-LABEL: define i32 @_Z13test_noreturnv
+// TRAPFUNC: call void @llvm.trap() [[ATTR0]]
+
+// NOOPTION-LABEL: define i32 @_Z13test_noreturnv
+// NOOPTION: call void @llvm.trap(){{$}}
+
+int test_noreturn(void) {
+}
+
+// TRAPFUNC-LABEL: define i32 @_Z17test_add_overflowii
+// TRAPFUNC: call void @llvm.trap() [[ATTR1:#[0-9]+]]
+
+// NOOPTION-LABEL: define i32 @_Z17test_add_overflowii
+// NOOPTION: call void @llvm.trap() [[ATTR2:#[0-9]+]]
+
+int test_add_overflow(int a, int b) {
+  return a + b;
+}
+
+// TRAPFUNC: attributes [[ATTR0]] = { {{.*}}"trap-func-name"="mytrap" }
+// TRAPFUNC: attributes [[ATTR1]] = { {{.*}}"trap-func-name"="mytrap" }
+
+// NOOPTION-NOT: attributes [[ATTR2]] = { {{.*}}"trap-func-name"="mytrap" }