From 85365cd72a9d57c97a96dc845031068ced5aaf18 Mon Sep 17 00:00:00 2001 From: Akira Hatanaka Date: Thu, 2 Jul 2015 22:15:41 +0000 Subject: [PATCH] Attach attribute "trap-func-name" to call sites of llvm.trap and llvm.debugtrap. 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 llvm-svn: 241306 --- clang/lib/CodeGen/BackendUtil.cpp | 1 - clang/lib/CodeGen/CGBuiltin.cpp | 12 +++------ clang/lib/CodeGen/CGCall.cpp | 2 ++ clang/lib/CodeGen/CGExpr.cpp | 15 +++++++++-- clang/lib/CodeGen/CodeGenFunction.cpp | 5 ++-- clang/lib/CodeGen/CodeGenFunction.h | 4 +++ clang/test/CodeGenCXX/trap-fnattr.cpp | 36 +++++++++++++++++++++++++++ 7 files changed, 62 insertions(+), 13 deletions(-) create mode 100644 clang/test/CodeGenCXX/trap-fnattr.cpp diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp index 801b49f04c812..0bccad0570da4 100644 --- a/clang/lib/CodeGen/BackendUtil.cpp +++ b/clang/lib/CodeGen/BackendUtil.cpp @@ -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; diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 8bd80085e65da..2ec909b9aac58 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -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); diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index 142966e7c011d..0535c05da5d52 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -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) { diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 1a76afaf11589..175763c4e815a 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -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) { diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index f1fc8c45f1ea5..1fca466e9244a 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -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(); } diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index cc427c9c88931..fac71bf8a6c28 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -2875,6 +2875,10 @@ class CodeGenFunction : public CodeGenTypeCache { /// 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/clang/test/CodeGenCXX/trap-fnattr.cpp b/clang/test/CodeGenCXX/trap-fnattr.cpp new file mode 100644 index 0000000000000..d9d6f81599c98 --- /dev/null +++ b/clang/test/CodeGenCXX/trap-fnattr.cpp @@ -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" }