ahatanak updated this revision to Diff 34872. ahatanak added a comment. Sorry for the delay in my response.
I had discussions with the users who requested this feature and it turns out they were asking for two different kinds of attributes. They are both needed to disable tail call optimization to preserve the stack frame but they differ in which stack frame they are trying to preserve. The attribute in this patch disables optimization on the call sites inside a function to preserve the stack frame of the function. The other attribute disables tail call *to* the function and therefore preserves the stack frame of the calling function. I'll send a patch for the other attribute shortly. http://reviews.llvm.org/D12547 Files: include/clang/Basic/Attr.td include/clang/Basic/AttrDocs.td lib/CodeGen/CGCall.cpp lib/Sema/SemaDeclAttr.cpp test/CodeGen/attr-disable-tail-calls.c test/Sema/disable-tail-calls-attr.c
Index: test/Sema/disable-tail-calls-attr.c =================================================================== --- /dev/null +++ test/Sema/disable-tail-calls-attr.c @@ -0,0 +1,5 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +void __attribute__((disable_tail_calls,naked)) foo1(int a) { // expected-error {{'disable_tail_calls' and 'naked' attributes are not compatible}} + __asm__(""); +} Index: test/CodeGen/attr-disable-tail-calls.c =================================================================== --- test/CodeGen/attr-disable-tail-calls.c +++ test/CodeGen/attr-disable-tail-calls.c @@ -1,11 +1,19 @@ -// RUN: %clang_cc1 -triple x86_64-apple-macosx10.7.0 %s -emit-llvm -mdisable-tail-calls -o - | FileCheck %s -check-prefix=CHECK -check-prefix=DISABLE -// RUN: %clang_cc1 -triple x86_64-apple-macosx10.7.0 %s -emit-llvm -o - | FileCheck %s -check-prefix=CHECK -check-prefix=ENABLE +// RUN: %clang_cc1 -triple x86_64-apple-macosx10.7.0 %s -emit-llvm -mdisable-tail-calls -o - | FileCheck %s -check-prefix=DISABLE +// RUN: %clang_cc1 -triple x86_64-apple-macosx10.7.0 %s -emit-llvm -o - | FileCheck %s -check-prefix=ENABLE -// CHECK: define i32 @f1() [[ATTR:#[0-9]+]] { +// DISABLE: define i32 @f1() [[ATTRTRUE:#[0-9]+]] { +// DISABLE: define i32 @f2() [[ATTRTRUE]] { +// ENABLE: define i32 @f1() [[ATTRFALSE:#[0-9]+]] { +// ENABLE: define i32 @f2() [[ATTRTRUE:#[0-9]+]] { int f1() { return 0; } -// DISABLE: attributes [[ATTR]] = { {{.*}} "disable-tail-calls"="true" {{.*}} } -// ENABLE: attributes [[ATTR]] = { {{.*}} "disable-tail-calls"="false" {{.*}} } +int f2() __attribute__((disable_tail_calls)) { + return 0; +} + +// DISABLE: attributes [[ATTRTRUE]] = { {{.*}} "disable-tail-calls"="true" {{.*}} } +// ENABLE: attributes [[ATTRFALSE]] = { {{.*}} "disable-tail-calls"="false" {{.*}} } +// ENABLE: attributes [[ATTRTRUE]] = { {{.*}} "disable-tail-calls"="true" {{.*}} } Index: lib/Sema/SemaDeclAttr.cpp =================================================================== --- lib/Sema/SemaDeclAttr.cpp +++ lib/Sema/SemaDeclAttr.cpp @@ -1696,6 +1696,18 @@ Attr.getAttributeSpellingListIndex())); } +static void handleDisableTailCallsAttr(Sema &S, Decl *D, + const AttributeList &Attr) { + if (auto *A = D->getAttr<NakedAttr>()) { + S.Diag(Attr.getLoc(), diag::err_attributes_are_not_compatible) + << Attr.getName() << A; + return; + } + + D->addAttr(::new (S.Context) DisableTailCallsAttr( + Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex())); +} + static void handleUsedAttr(Sema &S, Decl *D, const AttributeList &Attr) { if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { if (VD->hasLocalStorage()) { @@ -4886,6 +4898,9 @@ case AttributeList::AT_ReturnsTwice: handleSimpleAttribute<ReturnsTwiceAttr>(S, D, Attr); break; + case AttributeList::AT_DisableTailCalls: + handleDisableTailCallsAttr(S, D, Attr); + break; case AttributeList::AT_Used: handleUsedAttr(S, D, Attr); break; Index: lib/CodeGen/CGCall.cpp =================================================================== --- lib/CodeGen/CGCall.cpp +++ lib/CodeGen/CGCall.cpp @@ -1480,8 +1480,12 @@ FuncAttrs.addAttribute("no-frame-pointer-elim-non-leaf"); } + bool DisableTailCalls = + (TargetDecl && TargetDecl->hasAttr<DisableTailCallsAttr>()) || + CodeGenOpts.DisableTailCalls; FuncAttrs.addAttribute("disable-tail-calls", - llvm::toStringRef(CodeGenOpts.DisableTailCalls)); + llvm::toStringRef(DisableTailCalls)); + FuncAttrs.addAttribute("less-precise-fpmad", llvm::toStringRef(CodeGenOpts.LessPreciseFPMAD)); FuncAttrs.addAttribute("no-infs-fp-math", Index: include/clang/Basic/AttrDocs.td =================================================================== --- include/clang/Basic/AttrDocs.td +++ include/clang/Basic/AttrDocs.td @@ -1612,3 +1612,10 @@ arguments, with arbitrary offsets. }]; } + +def DisableTailCallsDocs : Documentation { + let Category = DocCatFunction; + let Content = [{ +The ``disable_tail_calls`` attribute instructs the backend to not perform tail call optimization. + }]; +} Index: include/clang/Basic/Attr.td =================================================================== --- include/clang/Basic/Attr.td +++ include/clang/Basic/Attr.td @@ -881,6 +881,13 @@ let Documentation = [Undocumented]; } +def DisableTailCalls : InheritableAttr { + let Spellings = [GNU<"disable_tail_calls">, + CXX11<"clang", "disable_tail_calls">]; + let Subjects = SubjectList<[Function, ObjCMethod]>; + let Documentation = [DisableTailCallsDocs]; +} + def NoAlias : InheritableAttr { let Spellings = [Declspec<"noalias">]; let Subjects = SubjectList<[Function]>;
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits