aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--llvm/docs/LangRef.rst26
-rw-r--r--llvm/lib/Analysis/InlineCost.cpp9
-rw-r--r--llvm/lib/IR/Attributes.cpp6
-rw-r--r--llvm/test/ThinLTO/X86/nossp.ll23
-rw-r--r--llvm/test/Transforms/Inline/inline_nossp.ll50
-rw-r--r--llvm/test/Transforms/Inline/inline_ssp.ll19
6 files changed, 48 insertions, 85 deletions
diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index 3a47cb5..33ff3a8 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -1995,11 +1995,9 @@ example:
Variables that are identified as requiring a protector will be arranged
on the stack such that they are adjacent to the stack protector guard.
- A function with the ``ssp`` attribute but without the ``alwaysinline``
- attribute cannot be inlined into a function without a
- ``ssp/sspreq/sspstrong`` attribute. If inlined, the caller will get the
- ``ssp`` attribute. ``call``, ``invoke``, and ``callbr`` instructions with
- the ``alwaysinline`` attribute force inlining.
+ If a function with an ``ssp`` attribute is inlined into a calling function,
+ the attribute is not carried over to the calling function.
+
``sspstrong``
This attribute indicates that the function should emit a stack smashing
protector. This attribute causes a strong heuristic to be used when
@@ -2024,12 +2022,10 @@ example:
This overrides the ``ssp`` function attribute.
- A function with the ``sspstrong`` attribute but without the
- ``alwaysinline`` attribute cannot be inlined into a function without a
- ``ssp/sspstrong/sspreq`` attribute. If inlined, the caller will get the
- ``sspstrong`` attribute unless the ``sspreq`` attribute exists. ``call``,
- ``invoke``, and ``callbr`` instructions with the ``alwaysinline`` attribute
- force inlining.
+ If a function with an ``sspstrong`` attribute is inlined into a calling
+ function which has an ``ssp`` attribute, the calling function's attribute
+ will be upgraded to ``sspstrong``.
+
``sspreq``
This attribute indicates that the function should *always* emit a stack
smashing protector. This overrides the ``ssp`` and ``sspstrong`` function
@@ -2046,11 +2042,9 @@ example:
#. Variables that have had their address taken are 3rd closest to the
protector.
- A function with the ``sspreq`` attribute but without the ``alwaysinline``
- attribute cannot be inlined into a function without a
- ``ssp/sspstrong/sspreq`` attribute. If inlined, the caller will get the
- ``sspreq`` attribute. ``call``, ``invoke``, and ``callbr`` instructions
- with the ``alwaysinline`` attribute force inlining.
+ If a function with an ``sspreq`` attribute is inlined into a calling
+ function which has an ``ssp`` or ``sspstrong`` attribute, the calling
+ function's attribute will be upgraded to ``sspreq``.
``strictfp``
This attribute indicates that the function was called from a scope that
diff --git a/llvm/lib/Analysis/InlineCost.cpp b/llvm/lib/Analysis/InlineCost.cpp
index ff31e81..5dce896 100644
--- a/llvm/lib/Analysis/InlineCost.cpp
+++ b/llvm/lib/Analysis/InlineCost.cpp
@@ -2898,15 +2898,6 @@ Optional<InlineResult> llvm::getAttributeBasedInliningDecision(
if (Call.isNoInline())
return InlineResult::failure("noinline call site attribute");
- // Don't inline functions if one does not have any stack protector attribute
- // but the other does.
- if (Caller->hasStackProtectorFnAttr() && !Callee->hasStackProtectorFnAttr())
- return InlineResult::failure(
- "stack protected caller but callee requested no stack protector");
- if (Callee->hasStackProtectorFnAttr() && !Caller->hasStackProtectorFnAttr())
- return InlineResult::failure(
- "stack protected callee but caller requested no stack protector");
-
return None;
}
diff --git a/llvm/lib/IR/Attributes.cpp b/llvm/lib/IR/Attributes.cpp
index 9726397..542b470 100644
--- a/llvm/lib/IR/Attributes.cpp
+++ b/llvm/lib/IR/Attributes.cpp
@@ -1921,6 +1921,12 @@ static void setOR(Function &Caller, const Function &Callee) {
/// 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) {
+ // If the calling function has *no* stack protection level (e.g. it was built
+ // with Clang's -fno-stack-protector or no_stack_protector attribute), don't
+ // change it as that could change the program's semantics.
+ if (!Caller.hasStackProtectorFnAttr())
+ 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.
diff --git a/llvm/test/ThinLTO/X86/nossp.ll b/llvm/test/ThinLTO/X86/nossp.ll
index c542a85..cfc54d5 100644
--- a/llvm/test/ThinLTO/X86/nossp.ll
+++ b/llvm/test/ThinLTO/X86/nossp.ll
@@ -23,7 +23,8 @@ declare void @ssp_callee() ssp
; nossp caller should be able to inline nossp callee.
define void @nossp_caller() {
-; CHECK-LABEL: @nossp_caller
+; CHECK-LABEL: define void @nossp_caller()
+; CHECK-NOT: #0
; CHECK-NEXT: tail call void @foo
tail call void @nossp_callee()
ret void
@@ -31,28 +32,34 @@ define void @nossp_caller() {
; ssp caller should be able to inline ssp callee.
define void @ssp_caller() ssp {
-; CHECK-LABEL: @ssp_caller
+; CHECK-LABEL: define void @ssp_caller()
+; CHECK-SAME: #0
; CHECK-NEXT: tail call void @foo
tail call void @ssp_callee()
ret void
}
-; nossp caller should *NOT* be able to inline ssp callee.
+; nossp caller should be able to inline ssp callee.
+; the ssp attribute is not propagated.
define void @nossp_caller2() {
-; CHECK-LABEL: @nossp_caller2
-; CHECK-NEXT: tail call void @ssp_callee
+; CHECK-LABEL: define void @nossp_caller2()
+; CHECK-NOT: #0
+; CHECK-NEXT: tail call void @foo
tail call void @ssp_callee()
ret void
}
-; ssp caller should *NOT* be able to inline nossp callee.
+; ssp caller should be able to inline nossp callee.
define void @ssp_caller2() ssp {
-; CHECK-LABEL: @ssp_caller2
-; CHECK-NEXT: tail call void @nossp_callee
+; CHECK-LABEL: define void @ssp_caller2()
+; CHECK-SAME: #0
+; CHECK-NEXT: tail call void @foo
tail call void @nossp_callee()
ret void
}
+; CHECK: attributes #0 = { ssp }
+
;--- b.ll
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-pc-linux-gnu"
diff --git a/llvm/test/Transforms/Inline/inline_nossp.ll b/llvm/test/Transforms/Inline/inline_nossp.ll
deleted file mode 100644
index c7145c8..0000000
--- a/llvm/test/Transforms/Inline/inline_nossp.ll
+++ /dev/null
@@ -1,50 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt -passes='cgscc(inline)' %s -S -pass-remarks-missed=inline 2>&1 | FileCheck --check-prefixes=CHECK,CHECK-INLINE %s
-; RUN: opt -passes=always-inline -o - -S %s | FileCheck %s
-
-; CHECK-INLINE: 'ssp' not inlined into 'nossp_caller' because it should never be inlined (cost=never): stack protected callee but caller requested no stack protector
-; CHECK-INLINE: 'nossp' not inlined into 'ssp_caller' because it should never be inlined (cost=never): stack protected caller but callee requested no stack protector
-
-; Not interesting to test.
-define i32 @nossp() { ret i32 41 }
-define i32 @ssp() sspstrong { ret i32 42 }
-define i32 @nossp_alwaysinline() alwaysinline { ret i32 43 }
-define i32 @ssp_alwaysinline() sspstrong alwaysinline { ret i32 44 }
-
-; @ssp should not be inlined due to mismatch stack protector.
-; @ssp_alwaysinline should be inlined due to alwaysinline.
-define i32 @nossp_caller() {
-; CHECK-LABEL: @nossp_caller(
-; CHECK-NEXT: [[TMP1:%.*]] = call i32 @ssp()
-; CHECK-NEXT: ret i32 44
-;
- call i32 @ssp()
- %2 = call i32 @ssp_alwaysinline()
- ret i32 %2
-}
-; @nossp should not be inlined due to mismatch stack protector.
-; @nossp_alwaysinline should be inlined due to alwaysinline.
-define i32 @ssp_caller() sspstrong {
-; CHECK-LABEL: @ssp_caller(
-; CHECK-NEXT: [[TMP1:%.*]] = call i32 @nossp()
-; CHECK-NEXT: ret i32 43
-;
- call i32 @nossp()
- %2 = call i32 @nossp_alwaysinline()
- ret i32 %2
-}
-
-; The alwaysinline attribute can also appear on the CallBase (ie. the call
-; site), ie. when __attribute__((flatten)) is used on the caller. Treat this
-; the same as if the caller had the fn attr alwaysinline and permit inline
-; substitution, despite the mismatch between caller and callee on ssp attrs.
-;
-; Curiously, the always_inline attribute on a CallInst is only expanded by the
-; inline pass, but not always_inline pass!
-define i32 @nossp_alwaysinline_caller() {
-; CHECK-INLINE-LABEL: @nossp_alwaysinline_caller(
-; CHECK-INLINE-NEXT: ret i32 42
-;
- %1 = call i32 @ssp() alwaysinline
- ret i32 %1
-}
diff --git a/llvm/test/Transforms/Inline/inline_ssp.ll b/llvm/test/Transforms/Inline/inline_ssp.ll
index ccfe934..a4f73f4 100644
--- a/llvm/test/Transforms/Inline/inline_ssp.ll
+++ b/llvm/test/Transforms/Inline/inline_ssp.ll
@@ -9,15 +9,23 @@
; These first four functions (@fun_sspreq, @fun_sspstrong, @fun_ssp, @fun_nossp)
; are used by the remaining functions to ensure that the SSP attributes are
-; propagated correctly. The caller should have its SSP attribute set as:
+; propagated correctly. If the caller had an SSP attribute before inlining, it
+; should have its new SSP attribute set as:
; strictest(caller-ssp-attr, callee-ssp-attr), where strictness is ordered as:
-; sspreq > sspstrong > ssp > [no ssp]
+; sspreq > sspstrong > ssp
+
define internal void @fun_sspreq() sspreq {
entry:
%call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str3, i32 0, i32 0))
ret void
}
+define internal void @fun_sspreq_alwaysinline() sspreq alwaysinline {
+entry:
+ %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str3, i32 0, i32 0))
+ ret void
+}
+
define internal void @fun_sspstrong() sspstrong {
entry:
%call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([15 x i8], [15 x i8]* @.str2, i32 0, i32 0))
@@ -66,6 +74,13 @@ entry:
ret void
}
+define void @alwaysinline_req_nossp() {
+entry:
+; CHECK: @alwaysinline_req_nossp() {
+ call void @fun_sspreq_alwaysinline()
+ ret void
+}
+
define void @inline_strong_req() sspreq {
entry:
; CHECK: @inline_strong_req() #[[SSPREQ]]