#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Instructions.h"
+#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/MDBuilder.h"
#include "llvm/IR/Module.h"
return NeedsProtector;
}
+static bool isLifetimeInst(const Instruction *I) {
+ if (const auto Intrinsic = dyn_cast<IntrinsicInst>(I)) {
+ const auto Id = Intrinsic->getIntrinsicID();
+ return Id == Intrinsic::lifetime_start || Id == Intrinsic::lifetime_end;
+ }
+ return false;
+}
+
bool StackProtector::HasAddressTaken(const Instruction *AI) {
for (const User *U : AI->users()) {
if (const StoreInst *SI = dyn_cast<StoreInst>(U)) {
} else if (const PtrToIntInst *SI = dyn_cast<PtrToIntInst>(U)) {
if (AI == SI->getOperand(0))
return true;
- } else if (isa<CallInst>(U)) {
- return true;
+ } else if (const CallInst *CI = dyn_cast<CallInst>(U)) {
+ // Ignore intrinsics that are not calls. TODO: Use isLoweredToCall().
+ if (!isa<DbgInfoIntrinsic>(CI) && !isLifetimeInst(CI))
+ return true;
} else if (isa<InvokeInst>(U)) {
return true;
} else if (const SelectInst *SI = dyn_cast<SelectInst>(U)) {
; RUN: llc -mtriple=x86_64-apple-darwin < %s -o -
+; RUN: llc -mtriple=x86_64-pc-linux-gnu < %s -o - | FileCheck --check-prefix=IGNORE_INTRIN %s
; PR16954
;
ret i32 %1
}
+define i32 @IgnoreIntrinsicTest() #1 {
+; IGNORE_INTRIN: IgnoreIntrinsicTest:
+ %1 = alloca i32, align 4
+ %2 = bitcast i32* %1 to i8*
+ call void @llvm.dbg.declare(metadata i32* %1, metadata !73, metadata !DIExpression()), !dbg !74
+ store volatile i32 1, i32* %1, align 4
+ %3 = load volatile i32, i32* %1, align 4
+ %4 = mul nsw i32 %3, 42
+ ret i32 %4
+; IGNORE_INTRIN-NOT: callq __stack_chk_fail
+; IGNORE_INTRIN: .cfi_endproc
+}
+
; Function Attrs: nounwind readnone
declare void @llvm.dbg.value(metadata, i64, metadata, metadata)
+declare void @llvm.dbg.declare(metadata, metadata, metadata)
attributes #0 = { sspreq }
!70 = !DILocalVariable(name: "", line: 2, arg: 3, scope: !65, file: !10, type: !50)
!71 = !DILocation(line: 1, scope: !65, inlinedAt: !40)
!72 = !{i32 1, !"Debug Info Version", i32 3}
+!73 = !DILocalVariable(name: "x", scope: !74, file: !1, line: 2, type: !13)
+!74 = distinct !DISubprogram(name: "IgnoreIntrinsicTest", linkageName: "IgnoreIntrinsicTest", scope: !1, file: !1, line: 1, type: !13, isLocal: false, isDefinition: true, scopeLine: 1, flags: DIFlagPrototyped, isOptimized: true, unit: !0, variables: !5)
+!75 = !DILocation(line: 2, column: 16, scope: !7)
; RUN: llc -mtriple=amd64-pc-openbsd < %s -o - | FileCheck --check-prefix=OPENBSD-AMD64 %s
; RUN: llc -mtriple=i386-pc-windows-msvc < %s -o - | FileCheck -check-prefix=MSVC-I386 %s
; RUN: llc -mtriple=x86_64-w64-mingw32 < %s -o - | FileCheck --check-prefix=MINGW-X64 %s
+; RUN: llc -mtriple=x86_64-pc-linux-gnu < %s -o - | FileCheck --check-prefix=IGNORE_INTRIN %s
%struct.foo = type { [16 x i8] }
%struct.foo.0 = type { [4 x i8] }
ret void, !dbg !9
}
+define i32 @IgnoreIntrinsicTest() #1 {
+; IGNORE_INTRIN: IgnoreIntrinsicTest:
+ %1 = alloca i32, align 4
+ %2 = bitcast i32* %1 to i8*
+ call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %2)
+ store volatile i32 1, i32* %1, align 4
+ %3 = load volatile i32, i32* %1, align 4
+ %4 = mul nsw i32 %3, 42
+ call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %2)
+ ret i32 %4
+; IGNORE_INTRIN-NOT: callq __stack_chk_fail
+; IGNORE_INTRIN: .cfi_endproc
+}
+
declare double @testi_aux()
declare i8* @strcpy(i8*, i8*)
declare i32 @printf(i8*, ...)
declare i32* @getp()
declare i32 @dummy(...)
declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture readonly, i64, i1)
+declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture)
+declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture)
attributes #0 = { ssp }
attributes #1 = { sspstrong }