nickdesaulniers updated this revision to Diff 297969.
nickdesaulniers added a comment.
- add -passes='cgscc(inline)' to inline_nossp.ll
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D87956/new/
https://reviews.llvm.org/D87956
Files:
clang/include/clang/Basic/AttrDocs.td
clang/lib/CodeGen/CodeGenModule.cpp
clang/test/CodeGen/stack-protector.c
llvm/bindings/go/llvm/ir_test.go
llvm/bindings/ocaml/llvm/llvm.ml
llvm/docs/BitCodeFormat.rst
llvm/docs/LangRef.rst
llvm/include/llvm/Bitcode/LLVMBitCodes.h
llvm/include/llvm/IR/Attributes.td
llvm/lib/AsmParser/LLLexer.cpp
llvm/lib/AsmParser/LLParser.cpp
llvm/lib/AsmParser/LLToken.h
llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
llvm/lib/CodeGen/StackProtector.cpp
llvm/lib/IR/Attributes.cpp
llvm/lib/IR/Verifier.cpp
llvm/lib/Transforms/IPO/ForceFunctionAttrs.cpp
llvm/lib/Transforms/Utils/CodeExtractor.cpp
llvm/lib/Transforms/Utils/InlineFunction.cpp
llvm/test/CodeGen/X86/stack-protector-2.ll
llvm/test/Transforms/CodeExtractor/PartialInlineAttributes.ll
llvm/test/Transforms/Inline/inline_nossp.ll
llvm/test/Transforms/Inline/inline_ssp.ll
llvm/test/Verifier/function-attribute-nossp-ssp-sspreq-sspstrong.ll
llvm/utils/emacs/llvm-mode.el
llvm/utils/kate/llvm.xml
llvm/utils/llvm.grm
llvm/utils/vim/syntax/llvm.vim
llvm/utils/vscode/llvm/syntaxes/ll.tmLanguage.yaml
Index: llvm/utils/vscode/llvm/syntaxes/ll.tmLanguage.yaml
===================================================================
--- llvm/utils/vscode/llvm/syntaxes/ll.tmLanguage.yaml
+++ llvm/utils/vscode/llvm/syntaxes/ll.tmLanguage.yaml
@@ -244,6 +244,7 @@
\\bspir_func\\b|\
\\bspir_kernel\\b|\
\\bsret\\b|\
+ \\bnossp\\b|\
\\bssp\\b|\
\\bsspreq\\b|\
\\bsspstrong\\b|\
Index: llvm/utils/vim/syntax/llvm.vim
===================================================================
--- llvm/utils/vim/syntax/llvm.vim
+++ llvm/utils/vim/syntax/llvm.vim
@@ -147,6 +147,7 @@
\ spir_func
\ spir_kernel
\ sret
+ \ nossp
\ ssp
\ sspreq
\ sspstrong
Index: llvm/utils/llvm.grm
===================================================================
--- llvm/utils/llvm.grm
+++ llvm/utils/llvm.grm
@@ -168,6 +168,7 @@
| noinline
| alwaysinline
| optsize
+ | nossp
| ssp
| sspreq
| returns_twice
Index: llvm/utils/kate/llvm.xml
===================================================================
--- llvm/utils/kate/llvm.xml
+++ llvm/utils/kate/llvm.xml
@@ -92,6 +92,7 @@
<item> optsize </item>
<item> readnone </item>
<item> readonly </item>
+ <item> nossp </item>
<item> ssp </item>
<item> sspreq </item>
<item> sspstrong </item>
Index: llvm/utils/emacs/llvm-mode.el
===================================================================
--- llvm/utils/emacs/llvm-mode.el
+++ llvm/utils/emacs/llvm-mode.el
@@ -26,7 +26,7 @@
"inaccessiblemem_or_argmemonly" "inlinehint" "jumptable" "minsize" "naked" "nobuiltin"
"noduplicate" "nofree" "noimplicitfloat" "noinline" "nonlazybind" "noredzone" "noreturn"
"norecurse" "noundef" "nounwind" "optnone" "optsize" "readnone" "readonly" "returns_twice"
- "speculatable" "ssp" "sspreq" "sspstrong" "safestack" "sanitize_address" "sanitize_hwaddress" "sanitize_memtag"
+ "speculatable" "nossp" "ssp" "sspreq" "sspstrong" "safestack" "sanitize_address" "sanitize_hwaddress" "sanitize_memtag"
"sanitize_thread" "sanitize_memory" "strictfp" "uwtable" "willreturn" "writeonly" "immarg") 'symbols) . font-lock-constant-face)
;; Variables
'("%[-a-zA-Z$._][-a-zA-Z$._0-9]*" . font-lock-variable-name-face)
Index: llvm/test/Verifier/function-attribute-nossp-ssp-sspreq-sspstrong.ll
===================================================================
--- /dev/null
+++ llvm/test/Verifier/function-attribute-nossp-ssp-sspreq-sspstrong.ll
@@ -0,0 +1,58 @@
+; RUN: not opt -verify -o - %s 2>&1 | FileCheck %s
+define void @test_1 () #1 { ret void }
+define void @test_2 () #2 { ret void }
+define void @test_3 () #3 { ret void }
+define void @test_4 () #4 { ret void }
+define void @test_5 () #5 { ret void }
+define void @test_6 () #6 { ret void }
+define void @test_7 () #7 { ret void }
+define void @test_8 () #8 { ret void }
+define void @test_9 () #9 { ret void }
+define void @test_10 () #10 { ret void }
+define void @test_11 () #10 { ret void }
+define void @test_12 () #10 { ret void }
+define void @test_13 () #10 { ret void }
+define void @test_14 () #10 { ret void }
+
+attributes #0 = { nossp }
+attributes #1 = { ssp }
+attributes #2 = { sspreq }
+attributes #3 = { sspstrong }
+
+attributes #4 = { nossp ssp }
+attributes #5 = { nossp sspreq }
+attributes #6 = { nossp sspstrong }
+
+attributes #7 = { ssp sspreq }
+attributes #8 = { ssp sspstrong }
+
+attributes #9 = { sspreq sspstrong }
+
+attributes #10 = { nossp ssp sspreq }
+attributes #11 = { nossp ssp sspstrong }
+attributes #12 = { nossp sspreq sspstrong }
+attributes #13 = { ssp sspreq sspstrong }
+attributes #14 = { nossp ssp sspreq sspstrong }
+
+; CHECK: fn attrs should be mutually exclusive
+; CHECK-NEXT: void ()* @test_4
+; CHECK: fn attrs should be mutually exclusive
+; CHECK-NEXT: void ()* @test_5
+; CHECK: fn attrs should be mutually exclusive
+; CHECK-NEXT: void ()* @test_6
+; CHECK: fn attrs should be mutually exclusive
+; CHECK-NEXT: void ()* @test_7
+; CHECK: fn attrs should be mutually exclusive
+; CHECK-NEXT: void ()* @test_8
+; CHECK: fn attrs should be mutually exclusive
+; CHECK-NEXT: void ()* @test_9
+; CHECK: fn attrs should be mutually exclusive
+; CHECK-NEXT: void ()* @test_10
+; CHECK: fn attrs should be mutually exclusive
+; CHECK-NEXT: void ()* @test_11
+; CHECK: fn attrs should be mutually exclusive
+; CHECK-NEXT: void ()* @test_12
+; CHECK: fn attrs should be mutually exclusive
+; CHECK-NEXT: void ()* @test_13
+; CHECK: fn attrs should be mutually exclusive
+; CHECK-NEXT: void ()* @test_14
Index: llvm/test/Transforms/Inline/inline_ssp.ll
===================================================================
--- llvm/test/Transforms/Inline/inline_ssp.ll
+++ llvm/test/Transforms/Inline/inline_ssp.ll
@@ -1,6 +1,10 @@
; RUN: opt -inline %s -S | FileCheck %s
; RUN: opt -passes='cgscc(inline)' %s -S | FileCheck %s
; Ensure SSP attributes are propagated correctly when inlining.
+; This test case covers callers that are unspecified in their level of stack
+; protection. See also llvm/test/Transforms/Inline/inline_nossp.ll
+; which tests callers with ``nossp`` function attribute which is stack
+; protection explicitly disabled.
@.str = private unnamed_addr constant [11 x i8] c"fun_nossp\0A\00", align 1
@.str1 = private unnamed_addr constant [9 x i8] c"fun_ssp\0A\00", align 1
Index: llvm/test/Transforms/Inline/inline_nossp.ll
===================================================================
--- /dev/null
+++ llvm/test/Transforms/Inline/inline_nossp.ll
@@ -0,0 +1,38 @@
+; RUN: opt -inline -o - -S %s | FileCheck %s
+; RUN: opt -passes='cgscc(inline)' %s -S | FileCheck %s
+; RUN: opt -always-inline -o - -S %s | FileCheck %s
+
+declare dso_local void @foo(i8*)
+
+define dso_local void @bar(i64 %0) #0 {
+ %2 = alloca i64, align 8
+ store i64 %0, i64* %2, align 8
+ %3 = load i64, i64* %2, align 8
+ %4 = alloca i8, i64 %3, align 16
+ call void @foo(i8* %4)
+ ret void
+}
+
+define dso_local void @baz(i64 %0) #1 {
+ %2 = alloca i64, align 8
+ store i64 %0, i64* %2, align 8
+ %3 = load i64, i64* %2, align 8
+ %4 = alloca i8, i64 %3, align 16
+ call void @foo(i8* %4)
+ ret void
+}
+
+define dso_local void @quux() #2 {
+; Check that the calls to @bar and @baz are not inlined into @quux, since @quux
+; does not want a stack protector.
+; CHECK-LABEL: @quux
+; CHECK-NEXT: call void @bar
+; CHECK-NEXT: call void @baz
+ call void @bar(i64 1024)
+ call void @baz(i64 1024)
+ ret void
+}
+
+attributes #0 = { sspstrong }
+attributes #1 = { sspstrong alwaysinline }
+attributes #2 = { nossp }
Index: llvm/test/Transforms/CodeExtractor/PartialInlineAttributes.ll
===================================================================
--- llvm/test/Transforms/CodeExtractor/PartialInlineAttributes.ll
+++ llvm/test/Transforms/CodeExtractor/PartialInlineAttributes.ll
@@ -73,10 +73,10 @@
attributes #0 = {
inlinehint minsize noduplicate noimplicitfloat norecurse noredzone nounwind
nonlazybind optsize safestack sanitize_address sanitize_hwaddress sanitize_memory
- sanitize_thread ssp sspreq sspstrong strictfp uwtable "foo"="bar"
+ sanitize_thread sspstrong strictfp uwtable "foo"="bar"
"patchable-function"="prologue-short-redirect" "probe-stack"="_foo_guard" "stack-probe-size"="4096" }
-; CHECK: attributes [[FN_ATTRS]] = { inlinehint minsize noduplicate noimplicitfloat norecurse noredzone nounwind nonlazybind optsize safestack sanitize_address sanitize_hwaddress sanitize_memory sanitize_thread ssp sspreq sspstrong strictfp uwtable "foo"="bar" "patchable-function"="prologue-short-redirect" "probe-stack"="_foo_guard" "stack-probe-size"="4096" }
+; CHECK: attributes [[FN_ATTRS]] = { inlinehint minsize noduplicate noimplicitfloat norecurse noredzone nounwind nonlazybind optsize safestack sanitize_address sanitize_hwaddress sanitize_memory sanitize_thread sspstrong strictfp uwtable "foo"="bar" "patchable-function"="prologue-short-redirect" "probe-stack"="_foo_guard" "stack-probe-size"="4096" }
; attributes to drop
attributes #1 = {
Index: llvm/test/CodeGen/X86/stack-protector-2.ll
===================================================================
--- llvm/test/CodeGen/X86/stack-protector-2.ll
+++ llvm/test/CodeGen/X86/stack-protector-2.ll
@@ -1,5 +1,5 @@
; RUN: llc -mtriple=x86_64-pc-linux-gnu -start-before=stack-protector -stop-after=stack-protector -o - < %s | FileCheck %s
-; Bugs 42238/43308: Test some additional situations not caught previously.
+; Bugs 42238/43308/47479: Test some additional situations not caught previously.
define void @store_captures() #0 {
; CHECK-LABEL: @store_captures(
@@ -162,4 +162,31 @@
declare void @llvm.memset.p0i8.i64(i8* nocapture writeonly, i8, i64, i1 immarg)
+
+; Test that the same function does not get a canary if nossp fn attr is set.
+declare dso_local void @foo(i8*)
+
+define dso_local void @bar_sspstrong(i64 %0) #0 {
+; CHECK-LABEL: @bar_sspstrong
+; CHECK-NEXT: %StackGuardSlot = alloca i8*
+ %2 = alloca i64, align 8
+ store i64 %0, i64* %2, align 8
+ %3 = load i64, i64* %2, align 8
+ %4 = alloca i8, i64 %3, align 16
+ call void @foo(i8* %4)
+ ret void
+}
+
+define dso_local void @bar_nossp(i64 %0) #1 {
+; CHECK-LABEL: @bar_nossp
+; CHECK-NEXT: %2 = alloca i64
+ %2 = alloca i64, align 8
+ store i64 %0, i64* %2, align 8
+ %3 = load i64, i64* %2, align 8
+ %4 = alloca i8, i64 %3, align 16
+ call void @foo(i8* %4)
+ ret void
+}
+
attributes #0 = { sspstrong }
+attributes #1 = { nossp }
Index: llvm/lib/Transforms/Utils/InlineFunction.cpp
===================================================================
--- llvm/lib/Transforms/Utils/InlineFunction.cpp
+++ llvm/lib/Transforms/Utils/InlineFunction.cpp
@@ -1676,6 +1676,16 @@
return InlineResult::failure("incompatible GC");
}
+ // Inlining a function that explicitly should not have a stack protector may
+ // break the code if inlined into a function that does have a stack
+ // protector.
+ if (Caller->hasFnAttribute(Attribute::NoStackProtect))
+ if (CalledFunc->hasFnAttribute(Attribute::StackProtect) ||
+ CalledFunc->hasFnAttribute(Attribute::StackProtectStrong) ||
+ CalledFunc->hasFnAttribute(Attribute::StackProtectReq))
+ return InlineResult::failure(
+ "non-stack-protected caller would inline stack-protected callee");
+
// Get the personality function from the callee if it contains a landing pad.
Constant *CalledPersonality =
CalledFunc->hasPersonalityFn()
Index: llvm/lib/Transforms/Utils/CodeExtractor.cpp
===================================================================
--- llvm/lib/Transforms/Utils/CodeExtractor.cpp
+++ llvm/lib/Transforms/Utils/CodeExtractor.cpp
@@ -925,6 +925,7 @@
case Attribute::SanitizeHWAddress:
case Attribute::SanitizeMemTag:
case Attribute::SpeculativeLoadHardening:
+ case Attribute::NoStackProtect:
case Attribute::StackProtect:
case Attribute::StackProtectReq:
case Attribute::StackProtectStrong:
Index: llvm/lib/Transforms/IPO/ForceFunctionAttrs.cpp
===================================================================
--- llvm/lib/Transforms/IPO/ForceFunctionAttrs.cpp
+++ llvm/lib/Transforms/IPO/ForceFunctionAttrs.cpp
@@ -68,6 +68,7 @@
.Case("sanitize_thread", Attribute::SanitizeThread)
.Case("sanitize_memtag", Attribute::SanitizeMemTag)
.Case("speculative_load_hardening", Attribute::SpeculativeLoadHardening)
+ .Case("nossp", Attribute::NoStackProtect)
.Case("ssp", Attribute::StackProtect)
.Case("sspreq", Attribute::StackProtectReq)
.Case("sspstrong", Attribute::StackProtectStrong)
Index: llvm/lib/IR/Verifier.cpp
===================================================================
--- llvm/lib/IR/Verifier.cpp
+++ llvm/lib/IR/Verifier.cpp
@@ -1577,6 +1577,7 @@
case Attribute::NoInline:
case Attribute::AlwaysInline:
case Attribute::OptimizeForSize:
+ case Attribute::NoStackProtect:
case Attribute::StackProtect:
case Attribute::StackProtectReq:
case Attribute::StackProtectStrong:
@@ -1971,6 +1972,21 @@
CheckFailed(
"\"patchable-function-entry\" takes an unsigned integer: " + S, V);
}
+ {
+ unsigned N = 0;
+ if (Attrs.hasFnAttribute(Attribute::NoStackProtect))
+ ++N;
+ if (Attrs.hasFnAttribute(Attribute::StackProtect))
+ ++N;
+ if (Attrs.hasFnAttribute(Attribute::StackProtectReq))
+ ++N;
+ if (Attrs.hasFnAttribute(Attribute::StackProtectStrong))
+ ++N;
+ Assert(N < 2,
+ "nossp, ssp, sspreq, sspstrong fn attrs should be mutually "
+ "exclusive",
+ V);
+ }
}
void Verifier::verifyFunctionMetadata(
Index: llvm/lib/IR/Attributes.cpp
===================================================================
--- llvm/lib/IR/Attributes.cpp
+++ llvm/lib/IR/Attributes.cpp
@@ -421,6 +421,8 @@
return "speculative_load_hardening";
if (hasAttribute(Attribute::Speculatable))
return "speculatable";
+ if (hasAttribute(Attribute::NoStackProtect))
+ return "nossp";
if (hasAttribute(Attribute::StackProtect))
return "ssp";
if (hasAttribute(Attribute::StackProtectReq))
@@ -1899,9 +1901,11 @@
/// If the inlined function had a higher stack protection level than the
/// calling function, then bump up the caller's stack protection level.
static void adjustCallerSSPLevel(Function &Caller, const Function &Callee) {
+ // Caller should never inherit a stack protector function attribute if the
+ // caller was explicitly annotated as nossp.
+ if (Caller.hasFnAttribute(Attribute::NoStackProtect))
+ return;
// If upgrading the SSP attribute, clear out the old SSP Attributes first.
- // Having multiple SSP attributes doesn't actually hurt, but it adds useless
- // clutter to the IR.
AttrBuilder OldSSPAttr;
OldSSPAttr.addAttribute(Attribute::StackProtect)
.addAttribute(Attribute::StackProtectStrong)
Index: llvm/lib/CodeGen/StackProtector.cpp
===================================================================
--- llvm/lib/CodeGen/StackProtector.cpp
+++ llvm/lib/CodeGen/StackProtector.cpp
@@ -270,13 +270,15 @@
/// regardless of size, functions with any buffer regardless of type and size,
/// functions with aggregates that contain any buffer regardless of type and
/// size, and functions that contain stack-based variables that have had their
-/// address taken.
+/// address taken. The heuristic will be disregarded for functions explicitly
+/// marked nossp.
bool StackProtector::RequiresStackProtector() {
bool Strong = false;
bool NeedsProtector = false;
HasPrologue = findStackProtectorIntrinsic(*F);
- if (F->hasFnAttribute(Attribute::SafeStack))
+ if (F->hasFnAttribute(Attribute::SafeStack) ||
+ F->hasFnAttribute(Attribute::NoStackProtect))
return false;
// We are constructing the OptimizationRemarkEmitter on the fly rather than
Index: llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
===================================================================
--- llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
+++ llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
@@ -697,6 +697,8 @@
return bitc::ATTR_KIND_SPECULATABLE;
case Attribute::StackAlignment:
return bitc::ATTR_KIND_STACK_ALIGNMENT;
+ case Attribute::NoStackProtect:
+ return bitc::ATTR_KIND_NO_STACK_PROTECT;
case Attribute::StackProtect:
return bitc::ATTR_KIND_STACK_PROTECT;
case Attribute::StackProtectReq:
Index: llvm/lib/AsmParser/LLToken.h
===================================================================
--- llvm/lib/AsmParser/LLToken.h
+++ llvm/lib/AsmParser/LLToken.h
@@ -223,6 +223,7 @@
kw_returns_twice,
kw_signext,
kw_speculatable,
+ kw_nossp,
kw_ssp,
kw_sspreq,
kw_sspstrong,
Index: llvm/lib/AsmParser/LLParser.cpp
===================================================================
--- llvm/lib/AsmParser/LLParser.cpp
+++ llvm/lib/AsmParser/LLParser.cpp
@@ -1335,6 +1335,9 @@
case lltok::kw_returns_twice:
B.addAttribute(Attribute::ReturnsTwice); break;
case lltok::kw_speculatable: B.addAttribute(Attribute::Speculatable); break;
+ case lltok::kw_nossp:
+ B.addAttribute(Attribute::NoStackProtect);
+ break;
case lltok::kw_ssp: B.addAttribute(Attribute::StackProtect); break;
case lltok::kw_sspreq: B.addAttribute(Attribute::StackProtectReq); break;
case lltok::kw_sspstrong:
@@ -1739,6 +1742,7 @@
case lltok::kw_sanitize_memory:
case lltok::kw_sanitize_thread:
case lltok::kw_speculative_load_hardening:
+ case lltok::kw_nossp:
case lltok::kw_ssp:
case lltok::kw_sspreq:
case lltok::kw_sspstrong:
@@ -1843,6 +1847,7 @@
case lltok::kw_sanitize_memory:
case lltok::kw_sanitize_thread:
case lltok::kw_speculative_load_hardening:
+ case lltok::kw_nossp:
case lltok::kw_ssp:
case lltok::kw_sspreq:
case lltok::kw_sspstrong:
Index: llvm/lib/AsmParser/LLLexer.cpp
===================================================================
--- llvm/lib/AsmParser/LLLexer.cpp
+++ llvm/lib/AsmParser/LLLexer.cpp
@@ -678,6 +678,7 @@
KEYWORD(signext);
KEYWORD(speculatable);
KEYWORD(sret);
+ KEYWORD(nossp);
KEYWORD(ssp);
KEYWORD(sspreq);
KEYWORD(sspstrong);
Index: llvm/include/llvm/IR/Attributes.td
===================================================================
--- llvm/include/llvm/IR/Attributes.td
+++ llvm/include/llvm/IR/Attributes.td
@@ -179,6 +179,9 @@
/// Function can be speculated.
def Speculatable : EnumAttr<"speculatable">;
+/// Stack protection explicitly disabled.
+def NoStackProtect : EnumAttr<"nossp">;
+
/// Stack protection.
def StackProtect : EnumAttr<"ssp">;
Index: llvm/include/llvm/Bitcode/LLVMBitCodes.h
===================================================================
--- llvm/include/llvm/Bitcode/LLVMBitCodes.h
+++ llvm/include/llvm/Bitcode/LLVMBitCodes.h
@@ -650,6 +650,7 @@
ATTR_KIND_NULL_POINTER_IS_VALID = 67,
ATTR_KIND_NOUNDEF = 68,
ATTR_KIND_BYREF = 69,
+ ATTR_KIND_NO_STACK_PROTECT = 70,
};
enum ComdatSelectionKindCodes {
Index: llvm/docs/LangRef.rst
===================================================================
--- llvm/docs/LangRef.rst
+++ llvm/docs/LangRef.rst
@@ -1820,6 +1820,21 @@
undefined behavior, the undefined behavior may be observed even
if the call site is dead code.
+``nossp``
+ This attribute indicates the function should not emit a stack smashing
+ protector. This is useful for code that intentionally manipulates the stack
+ canary, such as operating system kernel code that must save/restore such
+ canary values on context switch.
+
+ If a function with the ``nossp`` attribute calls a callee function that has
+ a stack protector function attribute, such as ``ssp``, ``sspreq``, or
+ ``sspstrong``, then the callee will not be inline substituted into the
+ caller. Even when the callee is ``alwaysinline``, the above holds.
+
+ Such inlining might break assumptions in the caller that it was
+ built without stack protection. This permits the callee to retain its stack
+ protector.
+
``ssp``
This attribute indicates that the function should emit a stack
smashing protector. It is in the form of a "canary" --- a random value
Index: llvm/docs/BitCodeFormat.rst
===================================================================
--- llvm/docs/BitCodeFormat.rst
+++ llvm/docs/BitCodeFormat.rst
@@ -950,6 +950,7 @@
* bit 36: ``inlinehint``
* bits 37-39: ``alignstack n``, represented as the logarithm
base 2 of the requested alignment, plus 1
+* bit 40: ``nossp``
.. _PARAMATTR_GROUP_BLOCK:
@@ -1068,6 +1069,8 @@
* code 66: ``no_merge``
* code 67: ``null_pointer_is_valid``
* code 68: ``noundef``
+* code 69: ``byref``
+* code 70: ``nossp``
.. note::
The ``allocsize`` attribute has a special encoding for its arguments. Its two
Index: llvm/bindings/ocaml/llvm/llvm.ml
===================================================================
--- llvm/bindings/ocaml/llvm/llvm.ml
+++ llvm/bindings/ocaml/llvm/llvm.ml
@@ -122,6 +122,7 @@
| Noinline
| Alwaysinline
| Optsize
+ | Nossp
| Ssp
| Sspreq
| Alignment of int
Index: llvm/bindings/go/llvm/ir_test.go
===================================================================
--- llvm/bindings/go/llvm/ir_test.go
+++ llvm/bindings/go/llvm/ir_test.go
@@ -78,6 +78,7 @@
"returns_twice",
"signext",
"safestack",
+ "nossp",
"ssp",
"sspreq",
"sspstrong",
Index: clang/test/CodeGen/stack-protector.c
===================================================================
--- clang/test/CodeGen/stack-protector.c
+++ clang/test/CodeGen/stack-protector.c
@@ -36,7 +36,7 @@
// SSPREQ: attributes #[[A]] = {{.*}} sspreq
// SAFESTACK-NOSSP: attributes #[[A]] = {{.*}} safestack
-// SAFESTACK-NOSSP-NOT: ssp
+// SAFESTACK-NOSSP-NOT: attributes #[[A]] = {{.*}} ssp
// SAFESTACK-SSP: attributes #[[A]] = {{.*}} safestack ssp{{ }}
// SAFESTACK-SSPSTRONG: attributes #[[A]] = {{.*}} safestack sspstrong
@@ -47,6 +47,11 @@
// SSPSTRONG-NOT: attributes #[[B]] = {{.*}} sspstrong
// SSPREQ-NOT: attributes #[[B]] = {{.*}} sspreq
+// NOSSP: attributes #[[B]] = {{.*}} nossp
+// SSP: attributes #[[B]] = {{.*}} nossp
+// SSPSTRONG: attributes #[[B]] = {{.*}} nossp
+// SSPREQ: attributes #[[B]] = {{.*}} nossp
+
// SAFESTACK-SSP: attributes #[[B]] = {{.*}} safestack
// SAFESTACK-SSP-NOT: attributes #[[B]] = {{.*}} safestack ssp{{ }}
// SAFESTACK-SSPSTRONG: attributes #[[B]] = {{.*}} safestack
Index: clang/lib/CodeGen/CodeGenModule.cpp
===================================================================
--- clang/lib/CodeGen/CodeGenModule.cpp
+++ clang/lib/CodeGen/CodeGenModule.cpp
@@ -1594,14 +1594,14 @@
if (!hasUnwindExceptions(LangOpts))
B.addAttribute(llvm::Attribute::NoUnwind);
- if (!D || !D->hasAttr<NoStackProtectorAttr>()) {
- if (LangOpts.getStackProtector() == LangOptions::SSPOn)
- B.addAttribute(llvm::Attribute::StackProtect);
- else if (LangOpts.getStackProtector() == LangOptions::SSPStrong)
- B.addAttribute(llvm::Attribute::StackProtectStrong);
- else if (LangOpts.getStackProtector() == LangOptions::SSPReq)
- B.addAttribute(llvm::Attribute::StackProtectReq);
- }
+ if (D && D->hasAttr<NoStackProtectorAttr>())
+ B.addAttribute(llvm::Attribute::NoStackProtect);
+ else if (LangOpts.getStackProtector() == LangOptions::SSPOn)
+ B.addAttribute(llvm::Attribute::StackProtect);
+ else if (LangOpts.getStackProtector() == LangOptions::SSPStrong)
+ B.addAttribute(llvm::Attribute::StackProtectStrong);
+ else if (LangOpts.getStackProtector() == LangOptions::SSPReq)
+ B.addAttribute(llvm::Attribute::StackProtectReq);
if (!D) {
// If we don't have a declaration to control inlining, the function isn't
Index: clang/include/clang/Basic/AttrDocs.td
===================================================================
--- clang/include/clang/Basic/AttrDocs.td
+++ clang/include/clang/Basic/AttrDocs.td
@@ -3872,6 +3872,10 @@
int bar(int y); // bar can be built with the stack protector.
+A callee that has a stack protector will not be inlined into a
+``__attribute__((no_stack_protector))`` caller, even if the callee is marked
+``__attribute__((always_inline))``.
+
}];
}
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits