summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
Diffstat (limited to 'clang')
-rw-r--r--clang/include/clang/Basic/Attr.td6
-rw-r--r--clang/include/clang/Basic/AttrDocs.td9
-rw-r--r--clang/lib/CodeGen/CGCall.cpp3
-rw-r--r--clang/lib/Sema/SemaDeclAttr.cpp3
-rw-r--r--clang/test/CodeGen/split-stacks.c14
-rw-r--r--clang/test/CodeGenCXX/split-stacks.cpp33
-rw-r--r--clang/test/SemaCXX/attr-no-split-stack.cpp34
7 files changed, 98 insertions, 4 deletions
diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td
index 5c5e597993a..a243994e202 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -823,6 +823,12 @@ def NoMips16 : InheritableAttr, TargetSpecificAttr<TargetMips> {
let Documentation = [Undocumented];
}
+def NoSplitStack : InheritableAttr {
+ let Spellings = [GCC<"no_split_stack">];
+ let Subjects = SubjectList<[Function], ErrorDiag>;
+ let Documentation = [NoSplitStackDocs];
+}
+
def NonNull : InheritableAttr {
let Spellings = [GCC<"nonnull">];
let Subjects = SubjectList<[ObjCMethod, HasFunctionProto, ParmVar], WarnDiag,
diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td
index a5eb25c1d9f..a0c2028512a 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -371,6 +371,15 @@ of the condition.
}];
}
+def NoSplitStackDocs : Documentation {
+ let Category = DocCatFunction;
+ let Content = [{
+The ``no_split_stack`` attribute disables the emission of the split stack
+preamble for a particular function. It has no effect if ``-fsplit-stack``
+is not specified.
+ }];
+}
+
def ObjCRequiresSuperDocs : Documentation {
let Category = DocCatFunction;
let Content = [{
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index 61bf985278e..e477a54c67e 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -1117,7 +1117,8 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI,
FuncAttrs.addAttribute(llvm::Attribute::NoRedZone);
if (CodeGenOpts.NoImplicitFloat)
FuncAttrs.addAttribute(llvm::Attribute::NoImplicitFloat);
- if (CodeGenOpts.EnableSegmentedStacks)
+ if (CodeGenOpts.EnableSegmentedStacks &&
+ !(TargetDecl && TargetDecl->hasAttr<NoSplitStackAttr>()))
FuncAttrs.addAttribute("split-stack");
if (AttrOnCallSite) {
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index 2e97a8aa9d4..b7c1d5d15b7 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -4180,6 +4180,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
case AttributeList::AT_NoCommon:
handleSimpleAttribute<NoCommonAttr>(S, D, Attr);
break;
+ case AttributeList::AT_NoSplitStack:
+ handleSimpleAttribute<NoSplitStackAttr>(S, D, Attr);
+ break;
case AttributeList::AT_NonNull:
if (ParmVarDecl *PVD = dyn_cast<ParmVarDecl>(D))
handleNonNullAttrParameter(S, PVD, Attr);
diff --git a/clang/test/CodeGen/split-stacks.c b/clang/test/CodeGen/split-stacks.c
index 98112467a56..bf4cf0f026a 100644
--- a/clang/test/CodeGen/split-stacks.c
+++ b/clang/test/CodeGen/split-stacks.c
@@ -5,13 +5,21 @@ int foo() {
return 0;
}
+__attribute__((no_split_stack))
+int nosplit() {
+ return 0;
+}
+
int main() {
return foo();
}
-// CHECK-SEGSTK: define i32 @foo() #0 {
-// CHECK-SEGSTK: define i32 @main() #0 {
-// CHECK-SEGSTK: #0 = { {{.*}} "split-stack" {{.*}} }
+// CHECK-SEGSTK: define i32 @foo() [[SS:#[0-9]+]] {
+// CHECK-SEGSTK: define i32 @nosplit() [[NSS:#[0-9]+]] {
+// CHECK-SEGSTK: define i32 @main() [[SS]] {
+// CHECK-SEGSTK-NOT: [[NSS]] = { {{.*}} "split-stack" {{.*}} }
+// CHECK-SEGSTK: [[SS]] = { {{.*}} "split-stack" {{.*}} }
+// CHECK-SEGSTK-NOT: [[NSS]] = { {{.*}} "split-stack" {{.*}} }
// CHECK-NOSEGSTK: define i32 @foo() #0 {
// CHECK-NOSEGSTK: define i32 @main() #0 {
diff --git a/clang/test/CodeGenCXX/split-stacks.cpp b/clang/test/CodeGenCXX/split-stacks.cpp
new file mode 100644
index 00000000000..3e120344d6b
--- /dev/null
+++ b/clang/test/CodeGenCXX/split-stacks.cpp
@@ -0,0 +1,33 @@
+// RUN: %clang -target x86_64-linux-gnu -fsplit-stack -S -std=c++11 %s -emit-llvm -o - | FileCheck -check-prefix=CHECK-SEGSTK %s
+// RUN: %clang -target x86_64-linux-gnu -S -std=c++11 %s -emit-llvm -o - | FileCheck -check-prefix=CHECK-NOSEGSTK %s
+
+int foo() {
+ return 0;
+}
+
+template <typename T>
+[[gnu::no_split_stack]]
+int tnosplit() {
+ return 0;
+}
+
+[[gnu::no_split_stack]]
+int nosplit() {
+ return tnosplit<int>();
+}
+
+// CHECK-SEGSTK: define i32 @_Z3foov() [[SS:#[0-9]+]] {
+// CHECK-SEGSTK: define i32 @_Z7nosplitv() [[NSS1:#[0-9]+]] {
+// CHECK-SEGSTK: define linkonce_odr i32 @_Z8tnosplitIiEiv() [[NSS2:#[0-9]+]] {
+// CHECK-SEGSTK-NOT: [[NSS1]] = { {{.*}} "split-stack" {{.*}} }
+// CHECK-SEGSTK-NOT: [[NSS2]] = { {{.*}} "split-stack" {{.*}} }
+// CHECK-SEGSTK: [[SS]] = { {{.*}} "split-stack" {{.*}} }
+// CHECK-SEGSTK-NOT: [[NSS1]] = { {{.*}} "split-stack" {{.*}} }
+// CHECK-SEGSTK-NOT: [[NSS2]] = { {{.*}} "split-stack" {{.*}} }
+
+// CHECK-NOSEGSTK: define i32 @_Z3foov() [[NSS0:#[0-9]+]] {
+// CHECK-NOSEGSTK: define i32 @_Z7nosplitv() [[NSS1:#[0-9]+]] {
+// CHECK-NOSEGSTK: define linkonce_odr i32 @_Z8tnosplitIiEiv() [[NSS2:#[0-9]+]] {
+// CHECK-NOSEGSTK-NOT: [[NSS1]] = { {{.*}} "split-stack" {{.*}} }
+// CHECK-NOSEGSTK-NOT: [[NSS2]] = { {{.*}} "split-stack" {{.*}} }
+// CHECK-NOSEGSTK-NOT: [[NSS3]] = { {{.*}} "split-stack" {{.*}} }
diff --git a/clang/test/SemaCXX/attr-no-split-stack.cpp b/clang/test/SemaCXX/attr-no-split-stack.cpp
new file mode 100644
index 00000000000..3575e9983f4
--- /dev/null
+++ b/clang/test/SemaCXX/attr-no-split-stack.cpp
@@ -0,0 +1,34 @@
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
+
+int i __attribute__((no_split_stack)); // expected-error {{'no_split_stack' attribute only applies to functions}}
+
+void f1() __attribute__((no_split_stack));
+void f2() __attribute__((no_split_stack(1))); // expected-error {{'no_split_stack' attribute takes no arguments}}
+
+template <typename T>
+void tf1() __attribute__((no_split_stack));
+
+int f3(int __attribute__((no_split_stack)), int); // expected-error{{'no_split_stack' attribute only applies to functions}}
+
+struct A {
+ int f __attribute__((no_split_stack)); // expected-error{{'no_split_stack' attribute only applies to functions}}
+ void mf1() __attribute__((no_split_stack));
+ static void mf2() __attribute__((no_split_stack));
+};
+
+int ci [[gnu::no_split_stack]]; // expected-error {{'no_split_stack' attribute only applies to functions}}
+
+[[gnu::no_split_stack]] void cf1();
+[[gnu::no_split_stack(1)]] void cf2(); // expected-error {{'no_split_stack' attribute takes no arguments}}
+
+template <typename T>
+[[gnu::no_split_stack]]
+void ctf1();
+
+int cf3(int c[[gnu::no_split_stack]], int); // expected-error{{'no_split_stack' attribute only applies to functions}}
+
+struct CA {
+ int f [[gnu::no_split_stack]]; // expected-error{{'no_split_stack' attribute only applies to functions}}
+ [[gnu::no_split_stack]] void mf1();
+ [[gnu::no_split_stack]] static void mf2();
+};
OpenPOWER on IntegriCloud