From 70cf01c27697f56d955fb7ee2b05b1c29ddf5cb7 Mon Sep 17 00:00:00 2001 From: Etienne Bergeron Date: Tue, 7 Jun 2016 20:15:35 +0000 Subject: [PATCH] [stack-protection] Add support for MSVC buffer security check Summary: This patch is adding support for the MSVC buffer security check implementation The buffer security check is turned on with the '/GS' compiler switch. * https://msdn.microsoft.com/en-us/library/8dbf701c.aspx * To be added to clang here: http://reviews.llvm.org/D20347 Some overview of buffer security check feature and implementation: * https://msdn.microsoft.com/en-us/library/aa290051(VS.71).aspx * http://www.ksyash.com/2011/01/buffer-overflow-protection-3/ * http://blog.osom.info/2012/02/understanding-vs-c-compilers-buffer.html For the following example: ``` int example(int offset, int index) { char buffer[10]; memset(buffer, 0xCC, index); return buffer[index]; } ``` The MSVC compiler is adding these instructions to perform stack integrity check: ``` push ebp mov ebp,esp sub esp,50h [1] mov eax,dword ptr [__security_cookie (01068024h)] [2] xor eax,ebp [3] mov dword ptr [ebp-4],eax push ebx push esi push edi mov eax,dword ptr [index] push eax push 0CCh lea ecx,[buffer] push ecx call _memset (010610B9h) add esp,0Ch mov eax,dword ptr [index] movsx eax,byte ptr buffer[eax] pop edi pop esi pop ebx [4] mov ecx,dword ptr [ebp-4] [5] xor ecx,ebp [6] call @__security_check_cookie@4 (01061276h) mov esp,ebp pop ebp ret ``` The instrumentation above is: * [1] is loading the global security canary, * [3] is storing the local computed ([2]) canary to the guard slot, * [4] is loading the guard slot and ([5]) re-compute the global canary, * [6] is validating the resulting canary with the '__security_check_cookie' and performs error handling. Overview of the current stack-protection implementation: * lib/CodeGen/StackProtector.cpp * There is a default stack-protection implementation applied on intermediate representation. * The target can overload 'getIRStackGuard' method if it has a standard location for the stack protector cookie. * An intrinsic 'Intrinsic::stackprotector' is added to the prologue. It will be expanded by the instruction selection pass (DAG or Fast). * Basic Blocks are added to every instrumented function to receive the code for handling stack guard validation and errors handling. * Guard manipulation and comparison are added directly to the intermediate representation. * lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp * lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp * There is an implementation that adds instrumentation during instruction selection (for better handling of sibbling calls). * see long comment above 'class StackProtectorDescriptor' declaration. * The target needs to override 'getSDagStackGuard' to activate SDAG stack protection generation. (note: getIRStackGuard MUST be nullptr). * 'getSDagStackGuard' returns the appropriate stack guard (security cookie) * The code is generated by 'SelectionDAGBuilder.cpp' and 'SelectionDAGISel.cpp'. * include/llvm/Target/TargetLowering.h * Contains function to retrieve the default Guard 'Value'; should be overriden by each target to select which implementation is used and provide Guard 'Value'. * lib/Target/X86/X86ISelLowering.cpp * Contains the x86 specialisation; Guard 'Value' used by the SelectionDAG algorithm. Function-based Instrumentation: * The MSVC doesn't inline the stack guard comparison in every function. Instead, a call to '__security_check_cookie' is added to the epilogue before every return instructions. * To support function-based instrumentation, this patch is * adding a function to get the function-based check (llvm 'Value', see include/llvm/Target/TargetLowering.h), * If provided, the stack protection instrumentation won't be inlined and a call to that function will be added to the prologue. * modifying (SelectionDAGISel.cpp) do avoid producing basic blocks used for inline instrumentation, * generating the function-based instrumentation during the ISEL pass (SelectionDAGBuilder.cpp), * if FastISEL (not SelectionDAG), using the fallback which rely on the same function-based implemented over intermediate representation (StackProtector.cpp). Modifications * adding support for MSVC (lib/Target/X86/X86ISelLowering.cpp) * adding support function-based instrumentation (lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp, .h) Results * IR generated instrumentation: ``` clang-cl /GS test.cc /Od /c -mllvm -print-isel-input ``` ``` *** Final LLVM Code input to ISel *** ; Function Attrs: nounwind sspstrong define i32 @"\01?example@@YAHHH@Z"(i32 %offset, i32 %index) #0 { entry: %StackGuardSlot = alloca i8* <<<-- Allocated guard slot %0 = call i8* @llvm.stackguard() <<<-- Loading Stack Guard value call void @llvm.stackprotector(i8* %0, i8** %StackGuardSlot) <<<-- Prologue intrinsic call (store to Guard slot) %index.addr = alloca i32, align 4 %offset.addr = alloca i32, align 4 %buffer = alloca [10 x i8], align 1 store i32 %index, i32* %index.addr, align 4 store i32 %offset, i32* %offset.addr, align 4 %arraydecay = getelementptr inbounds [10 x i8], [10 x i8]* %buffer, i32 0, i32 0 %1 = load i32, i32* %index.addr, align 4 call void @llvm.memset.p0i8.i32(i8* %arraydecay, i8 -52, i32 %1, i32 1, i1 false) %2 = load i32, i32* %index.addr, align 4 %arrayidx = getelementptr inbounds [10 x i8], [10 x i8]* %buffer, i32 0, i32 %2 %3 = load i8, i8* %arrayidx, align 1 %conv = sext i8 %3 to i32 %4 = load volatile i8*, i8** %StackGuardSlot <<<-- Loading Guard slot call void @__security_check_cookie(i8* %4) <<<-- Epilogue function-based check ret i32 %conv } ``` * SelectionDAG generated instrumentation: ``` clang-cl /GS test.cc /O1 /c /FA ``` ``` "?example@@YAHHH@Z": # @"\01?example@@YAHHH@Z" # BB#0: # %entry pushl %esi subl $16, %esp movl ___security_cookie, %eax <<<-- Loading Stack Guard value movl 28(%esp), %esi movl %eax, 12(%esp) <<<-- Store to Guard slot leal 2(%esp), %eax pushl %esi pushl $204 pushl %eax calll _memset addl $12, %esp movsbl 2(%esp,%esi), %esi movl 12(%esp), %ecx <<<-- Loading Guard slot calll @__security_check_cookie@4 <<<-- Epilogue function-based check movl %esi, %eax addl $16, %esp popl %esi retl ``` Reviewers: kcc, pcc, eugenis, rnk Subscribers: majnemer, llvm-commits, hans, thakis, rnk Differential Revision: http://reviews.llvm.org/D20346 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@272053 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Target/TargetLowering.h | 10 +- lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp | 39 +- lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h | 22 +- lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp | 30 +- lib/CodeGen/StackProtector.cpp | 45 ++- lib/CodeGen/TargetLoweringBase.cpp | 6 +- lib/Target/X86/X86ISelLowering.cpp | 35 +- lib/Target/X86/X86ISelLowering.h | 4 +- test/CodeGen/X86/stack-protector-msvc.ll | 40 +++ test/CodeGen/X86/stack-protector-weight.ll | 40 ++- test/CodeGen/X86/stack-protector.ll | 438 +++++++++++++++++++++++ 11 files changed, 668 insertions(+), 41 deletions(-) create mode 100644 test/CodeGen/X86/stack-protector-msvc.ll diff --git a/include/llvm/Target/TargetLowering.h b/include/llvm/Target/TargetLowering.h index 5113ae7292c..d8b89a64e62 100644 --- a/include/llvm/Target/TargetLowering.h +++ b/include/llvm/Target/TargetLowering.h @@ -1078,8 +1078,8 @@ public: /// LOAD_STACK_GUARD, or customize @llvm.stackguard(). virtual Value *getIRStackGuard(IRBuilder<> &IRB) const; - /// Inserts necessary declarations for SSP purpose. Should be used only when - /// getIRStackGuard returns nullptr. + /// Inserts necessary declarations for SSP (stack protection) purpose. + /// Should be used only when getIRStackGuard returns nullptr. virtual void insertSSPDeclarations(Module &M) const; /// Return the variable that's previously inserted by insertSSPDeclarations, @@ -1087,6 +1087,12 @@ public: /// getIRStackGuard returns nullptr. virtual Value *getSDagStackGuard(const Module &M) const; + /// If the target has a standard stack protection check function that + /// performs validation and error handling, returns the function. Otherwise, + /// returns nullptr. Must be previously inserted by insertSSPDeclarations. + /// Should be used only when getIRStackGuard returns nullptr. + virtual Value *getSSPStackGuardCheck(const Module &M) const; + /// If the target has a standard location for the unsafe stack pointer, /// returns the address of that location. Otherwise, returns nullptr. virtual Value *getSafeStackPointerLocation(IRBuilder<> &IRB) const; diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp index 2c4f37a84cb..6a727a1ad04 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -2040,6 +2040,40 @@ void SelectionDAGBuilder::visitSPDescriptorParent(StackProtectorDescriptor &SPD, const Module &M = *ParentBB->getParent()->getFunction()->getParent(); unsigned Align = DL->getPrefTypeAlignment(Type::getInt8PtrTy(M.getContext())); + // Generate code to load the content of the guard slot. + SDValue StackSlot = DAG.getLoad( + PtrTy, dl, DAG.getEntryNode(), StackSlotPtr, + MachinePointerInfo::getFixedStack(DAG.getMachineFunction(), FI), true, + false, false, Align); + + // Retrieve guard check function, nullptr if instrumentation is inlined. + if (const Value *GuardCheck = TLI.getSSPStackGuardCheck(M)) { + // The target provides a guard check function to validate the guard value. + // Generate a call to that function with the content of the guard slot as + // argument. + auto *Fn = cast(GuardCheck); + FunctionType *FnTy = Fn->getFunctionType(); + assert(FnTy->getNumParams() == 1 && "Invalid function signature"); + + TargetLowering::ArgListTy Args; + TargetLowering::ArgListEntry Entry; + Entry.Node = StackSlot; + Entry.Ty = FnTy->getParamType(0); + if (Fn->hasAttribute(1, Attribute::AttrKind::InReg)) + Entry.isInReg = true; + Args.push_back(Entry); + + TargetLowering::CallLoweringInfo CLI(DAG); + CLI.setDebugLoc(getCurSDLoc()) + .setChain(DAG.getEntryNode()) + .setCallee(Fn->getCallingConv(), FnTy->getReturnType(), + getValue(GuardCheck), std::move(Args)); + + std::pair Result = TLI.LowerCallTo(CLI); + DAG.setRoot(Result.second); + return; + } + // If useLoadStackGuardNode returns true, generate LOAD_STACK_GUARD. // Otherwise, emit a volatile load to retrieve the stack guard value. SDValue Chain = DAG.getEntryNode(); @@ -2054,11 +2088,6 @@ void SelectionDAGBuilder::visitSPDescriptorParent(StackProtectorDescriptor &SPD, true, false, false, Align); } - SDValue StackSlot = DAG.getLoad( - PtrTy, dl, DAG.getEntryNode(), StackSlotPtr, - MachinePointerInfo::getFixedStack(DAG.getMachineFunction(), FI), true, - false, false, Align); - // Perform the comparison via a subtract/getsetcc. EVT VT = Guard.getValueType(); SDValue Sub = DAG.getNode(ISD::SUB, dl, VT, Guard, StackSlot); diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h index a7d296929a3..68af2d90bce 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h +++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h @@ -456,7 +456,14 @@ private: /// /// c. After we finish selecting the basic block, in FinishBasicBlock if /// the StackProtectorDescriptor attached to the SelectionDAGBuilder is - /// initialized, we first find a splice point in the parent basic block + /// initialized, we produce the validation code with one of these + /// techniques: + /// 1) with a call to a guard check function + /// 2) with inlined instrumentation + /// + /// 1) We insert a call to the check function before the terminator. + /// + /// 2) We first find a splice point in the parent basic block /// before the terminator and then splice the terminator of said basic /// block into the success basic block. Then we code-gen a new tail for /// the parent basic block consisting of the two loads, the comparison, @@ -475,15 +482,22 @@ private: return ParentMBB && SuccessMBB && FailureMBB; } + bool shouldEmitFunctionBasedCheckStackProtector() const { + return ParentMBB && !SuccessMBB && !FailureMBB; + } + /// Initialize the stack protector descriptor structure for a new basic /// block. - void initialize(const BasicBlock *BB, MachineBasicBlock *MBB) { + void initialize(const BasicBlock *BB, MachineBasicBlock *MBB, + bool FunctionBasedInstrumentation) { // Make sure we are not initialized yet. assert(!shouldEmitStackProtector() && "Stack Protector Descriptor is " "already initialized!"); ParentMBB = MBB; - SuccessMBB = AddSuccessorMBB(BB, MBB, /* IsLikely */ true); - FailureMBB = AddSuccessorMBB(BB, MBB, /* IsLikely */ false, FailureMBB); + if (!FunctionBasedInstrumentation) { + SuccessMBB = AddSuccessorMBB(BB, MBB, /* IsLikely */ true); + FailureMBB = AddSuccessorMBB(BB, MBB, /* IsLikely */ false, FailureMBB); + } } /// Reset state that changes when we handle different basic blocks. diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp index 0ae1a95b875..918c013c798 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -1463,8 +1463,12 @@ void SelectionDAGISel::SelectAllBasicBlocks(const Function &Fn) { LowerArguments(Fn); } } - if (getAnalysis().shouldEmitSDCheck(*LLVMBB)) - SDB->SPDescriptor.initialize(LLVMBB, FuncInfo->MBBMap[LLVMBB]); + if (getAnalysis().shouldEmitSDCheck(*LLVMBB)) { + bool FunctionBasedInstrumentation = + TLI->getSSPStackGuardCheck(*Fn.getParent()); + SDB->SPDescriptor.initialize(LLVMBB, FuncInfo->MBBMap[LLVMBB], + FunctionBasedInstrumentation); + } if (Begin != BI) ++NumDAGBlocks; @@ -1552,7 +1556,7 @@ static bool MIIsInTerminatorSequence(const MachineInstr *MI) { /// terminator, but additionally the copies that move the vregs into the /// physical registers. static MachineBasicBlock::iterator -FindSplitPointForStackProtector(MachineBasicBlock *BB, DebugLoc DL) { +FindSplitPointForStackProtector(MachineBasicBlock *BB) { MachineBasicBlock::iterator SplitPoint = BB->getFirstTerminator(); // if (SplitPoint == BB->begin()) @@ -1593,7 +1597,23 @@ SelectionDAGISel::FinishBasicBlock() { } // Handle stack protector. - if (SDB->SPDescriptor.shouldEmitStackProtector()) { + if (SDB->SPDescriptor.shouldEmitFunctionBasedCheckStackProtector()) { + // The target provides a guard check function. There is no need to + // generate error handling code or to split current basic block. + MachineBasicBlock *ParentMBB = SDB->SPDescriptor.getParentMBB(); + + // Add load and check to the basicblock. + FuncInfo->MBB = ParentMBB; + FuncInfo->InsertPt = + FindSplitPointForStackProtector(ParentMBB); + SDB->visitSPDescriptorParent(SDB->SPDescriptor, ParentMBB); + CurDAG->setRoot(SDB->getRoot()); + SDB->clear(); + CodeGenAndEmitDAG(); + + // Clear the Per-BB State. + SDB->SPDescriptor.resetPerBBState(); + } else if (SDB->SPDescriptor.shouldEmitStackProtector()) { MachineBasicBlock *ParentMBB = SDB->SPDescriptor.getParentMBB(); MachineBasicBlock *SuccessMBB = SDB->SPDescriptor.getSuccessMBB(); @@ -1604,7 +1624,7 @@ SelectionDAGISel::FinishBasicBlock() { // register allocation issues caused by us splitting the parent mbb. The // register allocator will clean up said virtual copies later on. MachineBasicBlock::iterator SplitPoint = - FindSplitPointForStackProtector(ParentMBB, SDB->getCurDebugLoc()); + FindSplitPointForStackProtector(ParentMBB); // Splice the terminator of ParentMBB into SuccessMBB. SuccessMBB->splice(SuccessMBB->end(), ParentMBB, diff --git a/lib/CodeGen/StackProtector.cpp b/lib/CodeGen/StackProtector.cpp index 8a56c6a14d9..5f58c04d971 100644 --- a/lib/CodeGen/StackProtector.cpp +++ b/lib/CodeGen/StackProtector.cpp @@ -18,6 +18,7 @@ #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/Statistic.h" #include "llvm/Analysis/BranchProbabilityInfo.h" +#include "llvm/Analysis/EHPersonalities.h" #include "llvm/Analysis/ValueTracking.h" #include "llvm/CodeGen/Analysis.h" #include "llvm/CodeGen/Passes.h" @@ -95,11 +96,19 @@ bool StackProtector::runOnFunction(Function &Fn) { Attribute Attr = Fn.getFnAttribute("stack-protector-buffer-size"); if (Attr.isStringAttribute() && Attr.getValueAsString().getAsInteger(10, SSPBufferSize)) - return false; // Invalid integer string + return false; // Invalid integer string if (!RequiresStackProtector()) return false; + // TODO(etienneb): Functions with funclets are not correctly supported now. + // Do nothing if this is funclet-based personality. + if (Fn.hasPersonalityFn()) { + EHPersonality Personality = classifyEHPersonality(Fn.getPersonalityFn()); + if (isFuncletEHPersonality(Personality)) + return false; + } + ++NumFunProtected; return InsertStackProtectors(); } @@ -313,9 +322,9 @@ static bool CreatePrologue(Function *F, Module *M, ReturnInst *RI, PointerType *PtrTy = Type::getInt8PtrTy(RI->getContext()); AI = B.CreateAlloca(PtrTy, nullptr, "StackGuardSlot"); - Value *Guard = getStackGuard(TLI, M, B, &SupportsSelectionDAGSP); + Value *GuardSlot = getStackGuard(TLI, M, B, &SupportsSelectionDAGSP); B.CreateCall(Intrinsic::getDeclaration(M, Intrinsic::stackprotector), - {Guard, AI}); + {GuardSlot, AI}); return SupportsSelectionDAGSP; } @@ -336,12 +345,36 @@ bool StackProtector::InsertStackProtectors() { if (!RI) continue; + // Generate prologue instrumentation if not already generated. if (!HasPrologue) { HasPrologue = true; SupportsSelectionDAGSP &= CreatePrologue(F, M, RI, TLI, AI); } - if (!SupportsSelectionDAGSP) { + // SelectionDAG based code generation. Nothing else needs to be done here. + // The epilogue instrumentation is postponed to SelectionDAG. + if (SupportsSelectionDAGSP) + break; + + // Set HasIRCheck to true, so that SelectionDAG will not generate its own + // version. SelectionDAG called 'shouldEmitSDCheck' to check whether + // instrumentation has already been generated. + HasIRCheck = true; + + // Generate epilogue instrumentation. The epilogue intrumentation can be + // function-based or inlined depending on which mechanism the target is + // providing. + if (Value* GuardCheck = TLI->getSSPStackGuardCheck(*M)) { + // Generate the function-based epilogue instrumentation. + // The target provides a guard check function, generate a call to it. + IRBuilder<> B(RI); + LoadInst *Guard = B.CreateLoad(AI, true, "Guard"); + CallInst *Call = B.CreateCall(GuardCheck, {Guard}); + llvm::Function *Function = cast(GuardCheck); + Call->setAttributes(Function->getAttributes()); + Call->setCallingConv(Function->getCallingConv()); + } else { + // Generate the epilogue with inline instrumentation. // If we do not support SelectionDAG based tail calls, generate IR level // tail calls. // @@ -372,10 +405,6 @@ bool StackProtector::InsertStackProtectors() { // fail BB generated by the stack protector pseudo instruction. BasicBlock *FailBB = CreateFailBB(); - // Set HasIRCheck to true, so that SelectionDAG will not generate its own - // version. - HasIRCheck = true; - // Split the basic block before the return instruction. BasicBlock *NewBB = BB->splitBasicBlock(RI->getIterator(), "SP_return"); diff --git a/lib/CodeGen/TargetLoweringBase.cpp b/lib/CodeGen/TargetLoweringBase.cpp index 97f85f53946..67b2ee96283 100644 --- a/lib/CodeGen/TargetLoweringBase.cpp +++ b/lib/CodeGen/TargetLoweringBase.cpp @@ -898,7 +898,7 @@ void TargetLoweringBase::initActions() { setOperationAction(ISD::ZERO_EXTEND_VECTOR_INREG, VT, Expand); } - // For most targets @llvm.get.dynamic.area.offest just returns 0. + // For most targets @llvm.get.dynamic.area.offset just returns 0. setOperationAction(ISD::GET_DYNAMIC_AREA_OFFSET, VT, Expand); } @@ -1833,3 +1833,7 @@ void TargetLoweringBase::insertSSPDeclarations(Module &M) const { Value *TargetLoweringBase::getSDagStackGuard(const Module &M) const { return M.getGlobalVariable("__stack_chk_guard"); } + +Value *TargetLoweringBase::getSSPStackGuardCheck(const Module &M) const { + return nullptr; +} diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index 8856532ceed..ddb85db34b6 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -1974,8 +1974,39 @@ Value *X86TargetLowering::getIRStackGuard(IRBuilder<> &IRB) const { } void X86TargetLowering::insertSSPDeclarations(Module &M) const { - if (!Subtarget.isTargetGlibc()) - TargetLowering::insertSSPDeclarations(M); + // MSVC CRT provides functionalities for stack protection. + if (Subtarget.getTargetTriple().isOSMSVCRT()) { + // MSVC CRT has a global variable holding security cookie. + M.getOrInsertGlobal("__security_cookie", + Type::getInt8PtrTy(M.getContext())); + + // MSVC CRT has a function to validate security cookie. + auto *SecurityCheckCookie = cast( + M.getOrInsertFunction("__security_check_cookie", + Type::getVoidTy(M.getContext()), + Type::getInt8PtrTy(M.getContext()), nullptr)); + SecurityCheckCookie->setCallingConv(CallingConv::X86_FastCall); + SecurityCheckCookie->addAttribute(1, Attribute::AttrKind::InReg); + return; + } + // glibc has a special slot for the stack guard. + if (Subtarget.isTargetGlibc()) + return; + TargetLowering::insertSSPDeclarations(M); +} + +Value *X86TargetLowering::getSDagStackGuard(const Module &M) const { + // MSVC CRT has a global variable holding security cookie. + if (Subtarget.getTargetTriple().isOSMSVCRT()) + return M.getGlobalVariable("__security_cookie"); + return TargetLowering::getSDagStackGuard(M); +} + +Value *X86TargetLowering::getSSPStackGuardCheck(const Module &M) const { + // MSVC CRT has a function to validate security cookie. + if (Subtarget.getTargetTriple().isOSMSVCRT()) + return M.getFunction("__security_check_cookie"); + return TargetLowering::getSSPStackGuardCheck(M); } Value *X86TargetLowering::getSafeStackPointerLocation(IRBuilder<> &IRB) const { diff --git a/lib/Target/X86/X86ISelLowering.h b/lib/Target/X86/X86ISelLowering.h index f532cddeaa3..c6733467a4a 100644 --- a/lib/Target/X86/X86ISelLowering.h +++ b/lib/Target/X86/X86ISelLowering.h @@ -969,7 +969,10 @@ namespace llvm { /// returns the address of that location. Otherwise, returns nullptr. Value *getIRStackGuard(IRBuilder<> &IRB) const override; + bool useLoadStackGuardNode() const override; void insertSSPDeclarations(Module &M) const override; + Value *getSDagStackGuard(const Module &M) const override; + Value *getSSPStackGuardCheck(const Module &M) const override; /// Return true if the target stores SafeStack pointer at a fixed offset in /// some non-standard address space, and populates the address space and @@ -981,7 +984,6 @@ namespace llvm { bool isNoopAddrSpaceCast(unsigned SrcAS, unsigned DestAS) const override; - bool useLoadStackGuardNode() const override; /// \brief Customize the preferred legalization strategy for certain types. LegalizeTypeAction getPreferredVectorAction(EVT VT) const override; diff --git a/test/CodeGen/X86/stack-protector-msvc.ll b/test/CodeGen/X86/stack-protector-msvc.ll new file mode 100644 index 00000000000..5eccc65f2de --- /dev/null +++ b/test/CodeGen/X86/stack-protector-msvc.ll @@ -0,0 +1,40 @@ + +; RUN: llc -mtriple=i386-pc-windows-msvc < %s -o - | FileCheck -check-prefix=MSVC-I386 %s +; RUN: llc -mtriple=x86_64-pc-windows-msvc < %s -o - | FileCheck -check-prefix=MSVC-64 %s + +; MSVC-I386: movl ___security_cookie, %[[REG1:[a-z]*]] +; MSVC-I386: movl %[[REG1]], [[SLOT:[0-9]*]](%esp) +; MSVC-I386: calll _strcpy +; MSVC-I386: movl [[SLOT]](%esp), %ecx +; MSVC-I386: calll @__security_check_cookie@4 +; MSVC-I386: retl + +; MSVC-64: movq __security_cookie(%rip), %[[REG1:[a-z]*]] +; MSVC-64: movq %[[REG1]], [[SLOT:[0-9]*]](%rsp) +; MSVC-64: callq strcpy +; MSVC-64: movq [[SLOT]](%rsp), %rcx +; MSVC-64: callq __security_check_cookie + +@"\01LC" = internal constant [11 x i8] c"buf == %s\0A\00" ; <[11 x i8]*> [#uses=1] + +define void @test(i8* %a) nounwind ssp { +entry: + %a_addr = alloca i8* ; [#uses=2] + %buf = alloca [8 x i8] ; <[8 x i8]*> [#uses=2] + %"alloca point" = bitcast i32 0 to i32 ; [#uses=0] + store i8* %a, i8** %a_addr + %buf1 = bitcast [8 x i8]* %buf to i8* ; [#uses=1] + %0 = load i8*, i8** %a_addr, align 4 ; [#uses=1] + %1 = call i8* @strcpy(i8* %buf1, i8* %0) nounwind ; [#uses=0] + %buf2 = bitcast [8 x i8]* %buf to i8* ; [#uses=1] + %2 = call i32 (i8*, ...) @printf(i8* getelementptr ([11 x i8], [11 x i8]* @"\01LC", i32 0, i32 0), i8* %buf2) nounwind ; [#uses=0] + br label %return + +return: ; preds = %entry + ret void +} + +declare i8* @strcpy(i8*, i8*) nounwind + +declare i32 @printf(i8*, ...) nounwind + diff --git a/test/CodeGen/X86/stack-protector-weight.ll b/test/CodeGen/X86/stack-protector-weight.ll index dea66d28e3d..58c6c713941 100644 --- a/test/CodeGen/X86/stack-protector-weight.ll +++ b/test/CodeGen/X86/stack-protector-weight.ll @@ -1,17 +1,31 @@ -; RUN: llc -mtriple=x86_64-apple-darwin -print-machineinstrs=expand-isel-pseudos -enable-selectiondag-sp=true %s -o /dev/null 2>&1 | FileCheck %s --check-prefix=SELDAG -; RUN: llc -mtriple=x86_64-apple-darwin -print-machineinstrs=expand-isel-pseudos -enable-selectiondag-sp=false %s -o /dev/null 2>&1 | FileCheck %s --check-prefix=IR +; RUN: llc -mtriple=x86_64-apple-darwin -print-machineinstrs=expand-isel-pseudos -enable-selectiondag-sp=true %s -o /dev/null 2>&1 | FileCheck %s --check-prefix=DARWIN-SELDAG +; RUN: llc -mtriple=x86_64-apple-darwin -print-machineinstrs=expand-isel-pseudos -enable-selectiondag-sp=false %s -o /dev/null 2>&1 | FileCheck %s --check-prefix=DARWIN-IR +; RUN: llc -mtriple=i386-pc-windows-msvc -print-machineinstrs=expand-isel-pseudos -enable-selectiondag-sp=true %s -o /dev/null 2>&1 | FileCheck %s -check-prefix=MSVC-SELDAG +; RUN: llc -mtriple=i386-pc-windows-msvc -print-machineinstrs=expand-isel-pseudos -enable-selectiondag-sp=false %s -o /dev/null 2>&1 | FileCheck %s -check-prefix=MSVC-IR -; SELDAG: # Machine code for function test_branch_weights: -; SELDAG: Successors according to CFG: BB#[[SUCCESS:[0-9]+]]({{[0-9a-fx/= ]+}}100.00%) BB#[[FAILURE:[0-9]+]] -; SELDAG: BB#[[FAILURE]]: -; SELDAG: CALL64pcrel32 -; SELDAG: BB#[[SUCCESS]]: +; DARWIN-SELDAG: # Machine code for function test_branch_weights: +; DARWIN-SELDAG: Successors according to CFG: BB#[[SUCCESS:[0-9]+]]({{[0-9a-fx/= ]+}}100.00%) BB#[[FAILURE:[0-9]+]] +; DARWIN-SELDAG: BB#[[FAILURE]]: +; DARWIN-SELDAG: CALL64pcrel32 +; DARWIN-SELDAG: BB#[[SUCCESS]]: -; IR: # Machine code for function test_branch_weights: -; IR: Successors according to CFG: BB#[[SUCCESS:[0-9]+]]({{[0-9a-fx/= ]+}}100.00%) BB#[[FAILURE:[0-9]+]] -; IR: BB#[[SUCCESS]]: -; IR: BB#[[FAILURE]]: -; IR: CALL64pcrel32 +; DARWIN-IR: # Machine code for function test_branch_weights: +; DARWIN-IR: Successors according to CFG: BB#[[SUCCESS:[0-9]+]]({{[0-9a-fx/= ]+}}100.00%) BB#[[FAILURE:[0-9]+]] +; DARWIN-IR: BB#[[SUCCESS]]: +; DARWIN-IR: BB#[[FAILURE]]: +; DARWIN-IR: CALL64pcrel32 + +; MSVC-SELDAG: # Machine code for function test_branch_weights: +; MSVC-SELDAG: mem:Volatile LD4[@__security_cookie] +; MSVC-SELDAG: ST4[FixedStack0] +; MSVC-SELDAG: LD4[FixedStack0] +; MSVC-SELDAG: CALLpcrel32 + +; MSVC-IR: # Machine code for function test_branch_weights: +; MSVC-IR: mem:Volatile LD4[@__security_cookie] +; MSVC-IR: ST4[FixedStack0] +; MSVC-IR: LD4[%StackGuardSlot] +; MSVC-IR: CALLpcrel32 define i32 @test_branch_weights(i32 %n) #0 { entry: @@ -33,4 +47,4 @@ declare void @foo2(i32*) declare void @llvm.lifetime.end(i64, i8* nocapture) -attributes #0 = { ssp "stack-protector-buffer-size"="8" } +attributes #0 = { sspstrong "stack-protector-buffer-size"="8" } diff --git a/test/CodeGen/X86/stack-protector.ll b/test/CodeGen/X86/stack-protector.ll index 398b8548747..63dc412078f 100644 --- a/test/CodeGen/X86/stack-protector.ll +++ b/test/CodeGen/X86/stack-protector.ll @@ -3,6 +3,7 @@ ; RUN: llc -code-model=kernel -mtriple=x86_64-pc-linux-gnu < %s -o - | FileCheck --check-prefix=LINUX-KERNEL-X64 %s ; RUN: llc -mtriple=x86_64-apple-darwin < %s -o - | FileCheck --check-prefix=DARWIN-X64 %s ; 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 %struct.foo = type { [16 x i8] } %struct.foo.0 = type { [4 x i8] } @@ -40,6 +41,10 @@ entry: ; DARWIN-X64-LABEL: test1a: ; DARWIN-X64-NOT: callq ___stack_chk_fail ; DARWIN-X64: .cfi_endproc + +; MSVC-I386-LABEL: test1a: +; MSVC-I386-NOT: calll @__security_check_cookie@4 +; MSVC-I386: retl %a.addr = alloca i8*, align 8 %buf = alloca [16 x i8], align 16 store i8* %a, i8** %a.addr, align 8 @@ -76,6 +81,10 @@ entry: ; OPENBSD-AMD64-LABEL: test1b: ; OPENBSD-AMD64: movq __guard_local(%rip) ; OPENBSD-AMD64: callq __stack_smash_handler + +; MSVC-I386-LABEL: test1b: +; MSVC-I386: movl ___security_cookie, +; MSVC-I386: calll @__security_check_cookie@4 %a.addr = alloca i8*, align 8 %buf = alloca [16 x i8], align 16 store i8* %a, i8** %a.addr, align 8 @@ -108,6 +117,10 @@ entry: ; DARWIN-X64-LABEL: test1c: ; DARWIN-X64: mov{{l|q}} ___stack_chk_guard ; DARWIN-X64: callq ___stack_chk_fail + +; MSVC-I386-LABEL: test1c: +; MSVC-I386: movl ___security_cookie, +; MSVC-I386: calll @__security_check_cookie@4 %a.addr = alloca i8*, align 8 %buf = alloca [16 x i8], align 16 store i8* %a, i8** %a.addr, align 8 @@ -140,6 +153,10 @@ entry: ; DARWIN-X64-LABEL: test1d: ; DARWIN-X64: mov{{l|q}} ___stack_chk_guard ; DARWIN-X64: callq ___stack_chk_fail + +; MSVC-I386-LABEL: test1d: +; MSVC-I386: movl ___security_cookie, +; MSVC-I386: calll @__security_check_cookie@4 %a.addr = alloca i8*, align 8 %buf = alloca [16 x i8], align 16 store i8* %a, i8** %a.addr, align 8 @@ -171,6 +188,10 @@ entry: ; DARWIN-X64-LABEL: test2a: ; DARWIN-X64-NOT: callq ___stack_chk_fail ; DARWIN-X64: .cfi_endproc + +; MSVC-I386-LABEL: test2a: +; MSVC-I386-NOT: calll @__security_check_cookie@4 +; MSVC-I386: retl %a.addr = alloca i8*, align 8 %b = alloca %struct.foo, align 1 store i8* %a, i8** %a.addr, align 8 @@ -239,6 +260,10 @@ entry: ; DARWIN-X64-LABEL: test2c: ; DARWIN-X64: mov{{l|q}} ___stack_chk_guard ; DARWIN-X64: callq ___stack_chk_fail + +; MSVC-I386-LABEL: test2c: +; MSVC-I386: movl ___security_cookie, +; MSVC-I386: calll @__security_check_cookie@4 %a.addr = alloca i8*, align 8 %b = alloca %struct.foo, align 1 store i8* %a, i8** %a.addr, align 8 @@ -273,6 +298,10 @@ entry: ; DARWIN-X64-LABEL: test2d: ; DARWIN-X64: mov{{l|q}} ___stack_chk_guard ; DARWIN-X64: callq ___stack_chk_fail + +; MSVC-I386-LABEL: test2d: +; MSVC-I386: movl ___security_cookie, +; MSVC-I386: calll @__security_check_cookie@4 %a.addr = alloca i8*, align 8 %b = alloca %struct.foo, align 1 store i8* %a, i8** %a.addr, align 8 @@ -306,6 +335,10 @@ entry: ; DARWIN-X64-LABEL: test3a: ; DARWIN-X64-NOT: callq ___stack_chk_fail ; DARWIN-X64: .cfi_endproc + +; MSVC-I386-LABEL: test3a: +; MSVC-I386-NOT: calll @__security_check_cookie@4 +; MSVC-I386: retl %a.addr = alloca i8*, align 8 %buf = alloca [4 x i8], align 1 store i8* %a, i8** %a.addr, align 8 @@ -338,6 +371,10 @@ entry: ; DARWIN-X64-LABEL: test3b: ; DARWIN-X64-NOT: callq ___stack_chk_fail ; DARWIN-X64: .cfi_endproc + +; MSVC-I386-LABEL: test3b: +; MSVC-I386-NOT: calll @__security_check_cookie@4 +; MSVC-I386: retl %a.addr = alloca i8*, align 8 %buf = alloca [4 x i8], align 1 store i8* %a, i8** %a.addr, align 8 @@ -370,6 +407,10 @@ entry: ; DARWIN-X64-LABEL: test3c: ; DARWIN-X64: mov{{l|q}} ___stack_chk_guard ; DARWIN-X64: callq ___stack_chk_fail + +; MSVC-I386-LABEL: test3c: +; MSVC-I386: movl ___security_cookie, +; MSVC-I386: calll @__security_check_cookie@4 %a.addr = alloca i8*, align 8 %buf = alloca [4 x i8], align 1 store i8* %a, i8** %a.addr, align 8 @@ -402,6 +443,10 @@ entry: ; DARWIN-X64-LABEL: test3d: ; DARWIN-X64: mov{{l|q}} ___stack_chk_guard ; DARWIN-X64: callq ___stack_chk_fail + +; MSVC-I386-LABEL: test3d: +; MSVC-I386: movl ___security_cookie, +; MSVC-I386: calll @__security_check_cookie@4 %a.addr = alloca i8*, align 8 %buf = alloca [4 x i8], align 1 store i8* %a, i8** %a.addr, align 8 @@ -433,6 +478,10 @@ entry: ; DARWIN-X64-LABEL: test4a: ; DARWIN-X64-NOT: callq ___stack_chk_fail ; DARWIN-X64: .cfi_endproc + +; MSVC-I386-LABEL: test4a: +; MSVC-I386-NOT: calll @__security_check_cookie@4 +; MSVC-I386: retl %a.addr = alloca i8*, align 8 %b = alloca %struct.foo.0, align 1 store i8* %a, i8** %a.addr, align 8 @@ -467,6 +516,10 @@ entry: ; DARWIN-X64-LABEL: test4b: ; DARWIN-X64-NOT: callq ___stack_chk_fail ; DARWIN-X64: .cfi_endproc + +; MSVC-I386-LABEL: test4b: +; MSVC-I386-NOT: calll @__security_check_cookie@4 +; MSVC-I386: retl %a.addr = alloca i8*, align 8 %b = alloca %struct.foo.0, align 1 store i8* %a, i8** %a.addr, align 8 @@ -501,6 +554,10 @@ entry: ; DARWIN-X64-LABEL: test4c: ; DARWIN-X64: mov{{l|q}} ___stack_chk_guard ; DARWIN-X64: callq ___stack_chk_fail + +; MSVC-I386-LABEL: test4c: +; MSVC-I386: movl ___security_cookie, +; MSVC-I386: calll @__security_check_cookie@4 %a.addr = alloca i8*, align 8 %b = alloca %struct.foo.0, align 1 store i8* %a, i8** %a.addr, align 8 @@ -535,6 +592,10 @@ entry: ; DARWIN-X64-LABEL: test4d: ; DARWIN-X64: mov{{l|q}} ___stack_chk_guard ; DARWIN-X64: callq ___stack_chk_fail + +; MSVC-I386-LABEL: test4d: +; MSVC-I386: movl ___security_cookie, +; MSVC-I386: calll @__security_check_cookie@4 %a.addr = alloca i8*, align 8 %b = alloca %struct.foo.0, align 1 store i8* %a, i8** %a.addr, align 8 @@ -568,6 +629,10 @@ entry: ; DARWIN-X64-LABEL: test5a: ; DARWIN-X64-NOT: callq ___stack_chk_fail ; DARWIN-X64: .cfi_endproc + +; MSVC-I386-LABEL: test5a: +; MSVC-I386-NOT: calll @__security_check_cookie@4 +; MSVC-I386: retl %a.addr = alloca i8*, align 8 store i8* %a, i8** %a.addr, align 8 %0 = load i8*, i8** %a.addr, align 8 @@ -596,6 +661,10 @@ entry: ; DARWIN-X64-LABEL: test5b: ; DARWIN-X64-NOT: callq ___stack_chk_fail ; DARWIN-X64: .cfi_endproc + +; MSVC-I386-LABEL: test5b: +; MSVC-I386-NOT: calll @__security_check_cookie@4 +; MSVC-I386: retl %a.addr = alloca i8*, align 8 store i8* %a, i8** %a.addr, align 8 %0 = load i8*, i8** %a.addr, align 8 @@ -624,6 +693,10 @@ entry: ; DARWIN-X64-LABEL: test5c: ; DARWIN-X64-NOT: callq ___stack_chk_fail ; DARWIN-X64: .cfi_endproc + +; MSVC-I386-LABEL: test5c: +; MSVC-I386-NOT: calll @__security_check_cookie@4 +; MSVC-I386: retl %a.addr = alloca i8*, align 8 store i8* %a, i8** %a.addr, align 8 %0 = load i8*, i8** %a.addr, align 8 @@ -652,6 +725,10 @@ entry: ; DARWIN-X64-LABEL: test5d: ; DARWIN-X64: mov{{l|q}} ___stack_chk_guard ; DARWIN-X64: callq ___stack_chk_fail + +; MSVC-I386-LABEL: test5d: +; MSVC-I386: movl ___security_cookie, +; MSVC-I386: calll @__security_check_cookie@4 %a.addr = alloca i8*, align 8 store i8* %a, i8** %a.addr, align 8 %0 = load i8*, i8** %a.addr, align 8 @@ -679,6 +756,10 @@ entry: ; DARWIN-X64-LABEL: test6a: ; DARWIN-X64-NOT: callq ___stack_chk_fail ; DARWIN-X64: .cfi_endproc + +; MSVC-I386-LABEL: test6a: +; MSVC-I386-NOT: calll @__security_check_cookie@4 +; MSVC-I386: retl %retval = alloca i32, align 4 %a = alloca i32, align 4 %j = alloca i32*, align 8 @@ -711,6 +792,11 @@ entry: ; DARWIN-X64-LABEL: test6b: ; DARWIN-X64-NOT: callq ___stack_chk_fail ; DARWIN-X64: .cfi_endproc + + +; MSVC-I386-LABEL: test6b: +; MSVC-I386-NOT: calll @__security_check_cookie@4 +; MSVC-I386: retl %retval = alloca i32, align 4 %a = alloca i32, align 4 %j = alloca i32*, align 8 @@ -743,6 +829,10 @@ entry: ; DARWIN-X64-LABEL: test6c: ; DARWIN-X64: mov{{l|q}} ___stack_chk_guard ; DARWIN-X64: callq ___stack_chk_fail + +; MSVC-I386-LABEL: test6c: +; MSVC-I386: movl ___security_cookie, +; MSVC-I386: calll @__security_check_cookie@4 %retval = alloca i32, align 4 %a = alloca i32, align 4 %j = alloca i32*, align 8 @@ -775,6 +865,10 @@ entry: ; DARWIN-X64-LABEL: test6d: ; DARWIN-X64: mov{{l|q}} ___stack_chk_guard ; DARWIN-X64: callq ___stack_chk_fail + +; MSVC-I386-LABEL: test6d: +; MSVC-I386: movl ___security_cookie, +; MSVC-I386: calll @__security_check_cookie@4 %retval = alloca i32, align 4 %a = alloca i32, align 4 %j = alloca i32*, align 8 @@ -806,6 +900,10 @@ entry: ; DARWIN-X64-LABEL: test7a: ; DARWIN-X64-NOT: callq ___stack_chk_fail ; DARWIN-X64: .cfi_endproc + +; MSVC-I386-LABEL: test7a: +; MSVC-I386-NOT: calll @__security_check_cookie@4 +; MSVC-I386: retl %a = alloca i32, align 4 %0 = ptrtoint i32* %a to i64 %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0), i64 %0) @@ -833,6 +931,10 @@ entry: ; DARWIN-X64-LABEL: test7b: ; DARWIN-X64-NOT: callq ___stack_chk_fail ; DARWIN-X64: .cfi_endproc + +; MSVC-I386-LABEL: test7b: +; MSVC-I386-NOT: calll @__security_check_cookie@4 +; MSVC-I386: retl %a = alloca i32, align 4 %0 = ptrtoint i32* %a to i64 %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0), i64 %0) @@ -860,6 +962,10 @@ entry: ; DARWIN-X64-LABEL: test7c: ; DARWIN-X64: mov{{l|q}} ___stack_chk_guard ; DARWIN-X64: callq ___stack_chk_fail + +; MSVC-I386-LABEL: test7c: +; MSVC-I386: movl ___security_cookie, +; MSVC-I386: calll @__security_check_cookie@4 %a = alloca i32, align 4 %0 = ptrtoint i32* %a to i64 %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0), i64 %0) @@ -887,6 +993,10 @@ entry: ; DARWIN-X64-LABEL: test7d: ; DARWIN-X64: mov{{l|q}} ___stack_chk_guard ; DARWIN-X64: callq ___stack_chk_fail + +; MSVC-I386-LABEL: test7d: +; MSVC-I386: movl ___security_cookie, +; MSVC-I386: calll @__security_check_cookie@4 %a = alloca i32, align 4 %0 = ptrtoint i32* %a to i64 %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0), i64 %0) @@ -913,6 +1023,10 @@ entry: ; DARWIN-X64-LABEL: test8a: ; DARWIN-X64-NOT: callq ___stack_chk_fail ; DARWIN-X64: .cfi_endproc + +; MSVC-I386-LABEL: test8a: +; MSVC-I386-NOT: calll @__security_check_cookie@4 +; MSVC-I386: retl %b = alloca i32, align 4 call void @funcall(i32* %b) ret void @@ -939,6 +1053,10 @@ entry: ; DARWIN-X64-LABEL: test8b: ; DARWIN-X64-NOT: callq ___stack_chk_fail ; DARWIN-X64: .cfi_endproc + +; MSVC-I386-LABEL: test8b: +; MSVC-I386-NOT: calll @__security_check_cookie@4 +; MSVC-I386: retl %b = alloca i32, align 4 call void @funcall(i32* %b) ret void @@ -965,6 +1083,10 @@ entry: ; DARWIN-X64-LABEL: test8c: ; DARWIN-X64: mov{{l|q}} ___stack_chk_guard ; DARWIN-X64: callq ___stack_chk_fail + +; MSVC-I386-LABEL: test8c: +; MSVC-I386: movl ___security_cookie, +; MSVC-I386: calll @__security_check_cookie@4 %b = alloca i32, align 4 call void @funcall(i32* %b) ret void @@ -991,6 +1113,10 @@ entry: ; DARWIN-X64-LABEL: test8d: ; DARWIN-X64: mov{{l|q}} ___stack_chk_guard ; DARWIN-X64: callq ___stack_chk_fail + +; MSVC-I386-LABEL: test8d: +; MSVC-I386: movl ___security_cookie, +; MSVC-I386: calll @__security_check_cookie@4 %b = alloca i32, align 4 call void @funcall(i32* %b) ret void @@ -1016,6 +1142,10 @@ entry: ; DARWIN-X64-LABEL: test9a: ; DARWIN-X64-NOT: callq ___stack_chk_fail ; DARWIN-X64: .cfi_endproc + +; MSVC-I386-LABEL: test9a: +; MSVC-I386-NOT: calll @__security_check_cookie@4 +; MSVC-I386: retl %x = alloca double, align 8 %call = call double @testi_aux() store double %call, double* %x, align 8 @@ -1046,6 +1176,10 @@ entry: ; DARWIN-X64-LABEL: test9b: ; DARWIN-X64-NOT: callq ___stack_chk_fail ; DARWIN-X64: .cfi_endproc + +; MSVC-I386-LABEL: test9b: +; MSVC-I386-NOT: calll @__security_check_cookie@4 +; MSVC-I386: retl %x = alloca double, align 8 %call = call double @testi_aux() store double %call, double* %x, align 8 @@ -1076,6 +1210,10 @@ entry: ; DARWIN-X64-LABEL: test9c: ; DARWIN-X64: mov{{l|q}} ___stack_chk_guard ; DARWIN-X64: callq ___stack_chk_fail + +; MSVC-I386-LABEL: test9c: +; MSVC-I386: movl ___security_cookie, +; MSVC-I386: calll @__security_check_cookie@4 %x = alloca double, align 8 %call = call double @testi_aux() store double %call, double* %x, align 8 @@ -1106,6 +1244,10 @@ entry: ; DARWIN-X64-LABEL: test9d: ; DARWIN-X64: mov{{l|q}} ___stack_chk_guard ; DARWIN-X64: callq ___stack_chk_fail + +; MSVC-I386-LABEL: test9d: +; MSVC-I386: movl ___security_cookie, +; MSVC-I386: calll @__security_check_cookie@4 %x = alloca double, align 8 %call = call double @testi_aux() store double %call, double* %x, align 8 @@ -1135,6 +1277,10 @@ entry: ; DARWIN-X64-LABEL: test10a: ; DARWIN-X64-NOT: callq ___stack_chk_fail ; DARWIN-X64: .cfi_endproc + +; MSVC-I386-LABEL: test10a: +; MSVC-I386-NOT: calll @__security_check_cookie@4 +; MSVC-I386: retl %x = alloca double, align 8 %call = call double @testi_aux() store double %call, double* %x, align 8 @@ -1180,6 +1326,10 @@ entry: ; DARWIN-X64-LABEL: test10b: ; DARWIN-X64-NOT: callq ___stack_chk_fail ; DARWIN-X64: .cfi_endproc + +; MSVC-I386-LABEL: test10b: +; MSVC-I386-NOT: calll @__security_check_cookie@4 +; MSVC-I386: retl %x = alloca double, align 8 %call = call double @testi_aux() store double %call, double* %x, align 8 @@ -1225,6 +1375,10 @@ entry: ; DARWIN-X64-LABEL: test10c: ; DARWIN-X64: mov{{l|q}} ___stack_chk_guard ; DARWIN-X64: callq ___stack_chk_fail + +; MSVC-I386-LABEL: test10c: +; MSVC-I386: movl ___security_cookie, +; MSVC-I386: calll @__security_check_cookie@4 %x = alloca double, align 8 %call = call double @testi_aux() store double %call, double* %x, align 8 @@ -1270,6 +1424,10 @@ entry: ; DARWIN-X64-LABEL: test10d: ; DARWIN-X64: mov{{l|q}} ___stack_chk_guard ; DARWIN-X64: callq ___stack_chk_fail + +; MSVC-I386-LABEL: test10d: +; MSVC-I386: movl ___security_cookie, +; MSVC-I386: calll @__security_check_cookie@4 %x = alloca double, align 8 %call = call double @testi_aux() store double %call, double* %x, align 8 @@ -1314,6 +1472,10 @@ entry: ; DARWIN-X64-LABEL: test11a: ; DARWIN-X64-NOT: callq ___stack_chk_fail ; DARWIN-X64: .cfi_endproc + +; MSVC-I386-LABEL: test11a: +; MSVC-I386-NOT: calll @__security_check_cookie@4 +; MSVC-I386: retl %c = alloca %struct.pair, align 4 %b = alloca i32*, align 8 %y = getelementptr inbounds %struct.pair, %struct.pair* %c, i32 0, i32 1 @@ -1344,6 +1506,10 @@ entry: ; DARWIN-X64-LABEL: test11b: ; DARWIN-X64-NOT: callq ___stack_chk_fail ; DARWIN-X64: .cfi_endproc + +; MSVC-I386-LABEL: test11b: +; MSVC-I386-NOT: calll @__security_check_cookie@4 +; MSVC-I386: retl %c = alloca %struct.pair, align 4 %b = alloca i32*, align 8 %y = getelementptr inbounds %struct.pair, %struct.pair* %c, i32 0, i32 1 @@ -1374,6 +1540,10 @@ entry: ; DARWIN-X64-LABEL: test11c: ; DARWIN-X64: mov{{l|q}} ___stack_chk_guard ; DARWIN-X64: callq ___stack_chk_fail + +; MSVC-I386-LABEL: test11c: +; MSVC-I386: movl ___security_cookie, +; MSVC-I386: calll @__security_check_cookie@4 %c = alloca %struct.pair, align 4 %b = alloca i32*, align 8 %y = getelementptr inbounds %struct.pair, %struct.pair* %c, i32 0, i32 1 @@ -1404,6 +1574,10 @@ entry: ; DARWIN-X64-LABEL: test11d: ; DARWIN-X64: mov{{l|q}} ___stack_chk_guard ; DARWIN-X64: callq ___stack_chk_fail + +; MSVC-I386-LABEL: test11d: +; MSVC-I386: movl ___security_cookie, +; MSVC-I386: calll @__security_check_cookie@4 %c = alloca %struct.pair, align 4 %b = alloca i32*, align 8 %y = getelementptr inbounds %struct.pair, %struct.pair* %c, i32 0, i32 1 @@ -1433,6 +1607,10 @@ entry: ; DARWIN-X64-LABEL: test12a: ; DARWIN-X64-NOT: callq ___stack_chk_fail ; DARWIN-X64: .cfi_endproc + +; MSVC-I386-LABEL: test12a: +; MSVC-I386-NOT: calll @__security_check_cookie@4 +; MSVC-I386: retl %c = alloca %struct.pair, align 4 %b = alloca i32*, align 8 %y = getelementptr inbounds %struct.pair, %struct.pair* %c, i32 0, i32 1 @@ -1462,6 +1640,10 @@ entry: ; DARWIN-X64-LABEL: test12b: ; DARWIN-X64-NOT: callq ___stack_chk_fail ; DARWIN-X64: .cfi_endproc + +; MSVC-I386-LABEL: test12b: +; MSVC-I386-NOT: calll @__security_check_cookie@4 +; MSVC-I386: retl %c = alloca %struct.pair, align 4 %b = alloca i32*, align 8 %y = getelementptr inbounds %struct.pair, %struct.pair* %c, i32 0, i32 1 @@ -1490,6 +1672,10 @@ entry: ; DARWIN-X64-LABEL: test12c: ; DARWIN-X64: mov{{l|q}} ___stack_chk_guard ; DARWIN-X64: callq ___stack_chk_fail + +; MSVC-I386-LABEL: test12c: +; MSVC-I386: movl ___security_cookie, +; MSVC-I386: calll @__security_check_cookie@4 %c = alloca %struct.pair, align 4 %b = alloca i32*, align 8 %y = getelementptr inbounds %struct.pair, %struct.pair* %c, i32 0, i32 1 @@ -1519,6 +1705,10 @@ entry: ; DARWIN-X64-LABEL: test12d: ; DARWIN-X64: mov{{l|q}} ___stack_chk_guard ; DARWIN-X64: callq ___stack_chk_fail + +; MSVC-I386-LABEL: test12d: +; MSVC-I386: movl ___security_cookie, +; MSVC-I386: calll @__security_check_cookie@4 %c = alloca %struct.pair, align 4 %b = alloca i32*, align 8 %y = getelementptr inbounds %struct.pair, %struct.pair* %c, i32 0, i32 1 @@ -1547,6 +1737,10 @@ entry: ; DARWIN-X64-LABEL: test13a: ; DARWIN-X64-NOT: callq ___stack_chk_fail ; DARWIN-X64: .cfi_endproc + +; MSVC-I386-LABEL: test13a: +; MSVC-I386-NOT: calll @__security_check_cookie@4 +; MSVC-I386: retl %c = alloca %struct.pair, align 4 %y = getelementptr inbounds %struct.pair, %struct.pair* %c, i64 0, i32 1 %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i64 0, i64 0), i32* %y) @@ -1574,6 +1768,10 @@ entry: ; DARWIN-X64-LABEL: test13b: ; DARWIN-X64-NOT: callq ___stack_chk_fail ; DARWIN-X64: .cfi_endproc + +; MSVC-I386-LABEL: test13b: +; MSVC-I386-NOT: calll @__security_check_cookie@4 +; MSVC-I386: retl %c = alloca %struct.pair, align 4 %y = getelementptr inbounds %struct.pair, %struct.pair* %c, i64 0, i32 1 %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i64 0, i64 0), i32* %y) @@ -1601,6 +1799,10 @@ entry: ; DARWIN-X64-LABEL: test13c: ; DARWIN-X64: mov{{l|q}} ___stack_chk_guard ; DARWIN-X64: callq ___stack_chk_fail + +; MSVC-I386-LABEL: test13c: +; MSVC-I386: movl ___security_cookie, +; MSVC-I386: calll @__security_check_cookie@4 %c = alloca %struct.pair, align 4 %y = getelementptr inbounds %struct.pair, %struct.pair* %c, i64 0, i32 1 %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i64 0, i64 0), i32* %y) @@ -1628,6 +1830,10 @@ entry: ; DARWIN-X64-LABEL: test13d: ; DARWIN-X64: mov{{l|q}} ___stack_chk_guard ; DARWIN-X64: callq ___stack_chk_fail + +; MSVC-I386-LABEL: test13d: +; MSVC-I386: movl ___security_cookie, +; MSVC-I386: calll @__security_check_cookie@4 %c = alloca %struct.pair, align 4 %y = getelementptr inbounds %struct.pair, %struct.pair* %c, i64 0, i32 1 %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i64 0, i64 0), i32* %y) @@ -1654,6 +1860,10 @@ entry: ; DARWIN-X64-LABEL: test14a: ; DARWIN-X64-NOT: callq ___stack_chk_fail ; DARWIN-X64: .cfi_endproc + +; MSVC-I386-LABEL: test14a: +; MSVC-I386-NOT: calll @__security_check_cookie@4 +; MSVC-I386: retl %a = alloca i32, align 4 %add.ptr5 = getelementptr inbounds i32, i32* %a, i64 -12 %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i64 0, i64 0), i32* %add.ptr5) @@ -1681,6 +1891,10 @@ entry: ; DARWIN-X64-LABEL: test14b: ; DARWIN-X64-NOT: callq ___stack_chk_fail ; DARWIN-X64: .cfi_endproc + +; MSVC-I386-LABEL: test14b: +; MSVC-I386-NOT: calll @__security_check_cookie@4 +; MSVC-I386: retl %a = alloca i32, align 4 %add.ptr5 = getelementptr inbounds i32, i32* %a, i64 -12 %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i64 0, i64 0), i32* %add.ptr5) @@ -1708,6 +1922,10 @@ entry: ; DARWIN-X64-LABEL: test14c: ; DARWIN-X64: mov{{l|q}} ___stack_chk_guard ; DARWIN-X64: callq ___stack_chk_fail + +; MSVC-I386-LABEL: test14c: +; MSVC-I386: movl ___security_cookie, +; MSVC-I386: calll @__security_check_cookie@4 %a = alloca i32, align 4 %add.ptr5 = getelementptr inbounds i32, i32* %a, i64 -12 %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i64 0, i64 0), i32* %add.ptr5) @@ -1735,6 +1953,10 @@ entry: ; DARWIN-X64-LABEL: test14d: ; DARWIN-X64: mov{{l|q}} ___stack_chk_guard ; DARWIN-X64: callq ___stack_chk_fail + +; MSVC-I386-LABEL: test14d: +; MSVC-I386: movl ___security_cookie, +; MSVC-I386: calll @__security_check_cookie@4 %a = alloca i32, align 4 %add.ptr5 = getelementptr inbounds i32, i32* %a, i64 -12 %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i64 0, i64 0), i32* %add.ptr5) @@ -1762,6 +1984,10 @@ entry: ; DARWIN-X64-LABEL: test15a: ; DARWIN-X64-NOT: callq ___stack_chk_fail ; DARWIN-X64: .cfi_endproc + +; MSVC-I386-LABEL: test15a: +; MSVC-I386-NOT: calll @__security_check_cookie@4 +; MSVC-I386: retl %a = alloca i32, align 4 %b = alloca float*, align 8 store i32 0, i32* %a, align 4 @@ -1794,6 +2020,10 @@ entry: ; DARWIN-X64-LABEL: test15b: ; DARWIN-X64-NOT: callq ___stack_chk_fail ; DARWIN-X64: .cfi_endproc + +; MSVC-I386-LABEL: test15b: +; MSVC-I386-NOT: calll @__security_check_cookie@4 +; MSVC-I386: retl %a = alloca i32, align 4 %b = alloca float*, align 8 store i32 0, i32* %a, align 4 @@ -1826,6 +2056,10 @@ entry: ; DARWIN-X64-LABEL: test15c: ; DARWIN-X64: mov{{l|q}} ___stack_chk_guard ; DARWIN-X64: callq ___stack_chk_fail + +; MSVC-I386-LABEL: test15c: +; MSVC-I386: movl ___security_cookie, +; MSVC-I386: calll @__security_check_cookie@4 %a = alloca i32, align 4 %b = alloca float*, align 8 store i32 0, i32* %a, align 4 @@ -1858,6 +2092,10 @@ entry: ; DARWIN-X64-LABEL: test15d: ; DARWIN-X64: mov{{l|q}} ___stack_chk_guard ; DARWIN-X64: callq ___stack_chk_fail + +; MSVC-I386-LABEL: test15d: +; MSVC-I386: movl ___security_cookie, +; MSVC-I386: calll @__security_check_cookie@4 %a = alloca i32, align 4 %b = alloca float*, align 8 store i32 0, i32* %a, align 4 @@ -1889,6 +2127,10 @@ entry: ; DARWIN-X64-LABEL: test16a: ; DARWIN-X64-NOT: callq ___stack_chk_fail ; DARWIN-X64: .cfi_endproc + +; MSVC-I386-LABEL: test16a: +; MSVC-I386-NOT: calll @__security_check_cookie@4 +; MSVC-I386: retl %a = alloca i32, align 4 store i32 0, i32* %a, align 4 %0 = bitcast i32* %a to float* @@ -1918,6 +2160,10 @@ entry: ; DARWIN-X64-LABEL: test16b: ; DARWIN-X64-NOT: callq ___stack_chk_fail ; DARWIN-X64: .cfi_endproc + +; MSVC-I386-LABEL: test16b: +; MSVC-I386-NOT: calll @__security_check_cookie@4 +; MSVC-I386: retl %a = alloca i32, align 4 store i32 0, i32* %a, align 4 %0 = bitcast i32* %a to float* @@ -1947,6 +2193,10 @@ entry: ; DARWIN-X64-LABEL: test16c: ; DARWIN-X64: mov{{l|q}} ___stack_chk_guard ; DARWIN-X64: callq ___stack_chk_fail + +; MSVC-I386-LABEL: test16c: +; MSVC-I386: movl ___security_cookie, +; MSVC-I386: calll @__security_check_cookie@4 %a = alloca i32, align 4 store i32 0, i32* %a, align 4 %0 = bitcast i32* %a to float* @@ -1976,6 +2226,10 @@ entry: ; DARWIN-X64-LABEL: test16d: ; DARWIN-X64: mov{{l|q}} ___stack_chk_guard ; DARWIN-X64: callq ___stack_chk_fail + +; MSVC-I386-LABEL: test16d: +; MSVC-I386: movl ___security_cookie, +; MSVC-I386: calll @__security_check_cookie@4 %a = alloca i32, align 4 store i32 0, i32* %a, align 4 %0 = bitcast i32* %a to float* @@ -2003,6 +2257,10 @@ entry: ; DARWIN-X64-LABEL: test17a: ; DARWIN-X64-NOT: callq ___stack_chk_fail ; DARWIN-X64: .cfi_endproc + +; MSVC-I386-LABEL: test17a: +; MSVC-I386-NOT: calll @__security_check_cookie@4 +; MSVC-I386: retl %c = alloca %struct.vec, align 16 %y = getelementptr inbounds %struct.vec, %struct.vec* %c, i64 0, i32 0 %add.ptr = getelementptr inbounds <4 x i32>, <4 x i32>* %y, i64 -12 @@ -2031,6 +2289,10 @@ entry: ; DARWIN-X64-LABEL: test17b: ; DARWIN-X64-NOT: callq ___stack_chk_fail ; DARWIN-X64: .cfi_endproc + +; MSVC-I386-LABEL: test17b: +; MSVC-I386-NOT: calll @__security_check_cookie@4 +; MSVC-I386: retl %c = alloca %struct.vec, align 16 %y = getelementptr inbounds %struct.vec, %struct.vec* %c, i64 0, i32 0 %add.ptr = getelementptr inbounds <4 x i32>, <4 x i32>* %y, i64 -12 @@ -2059,6 +2321,10 @@ entry: ; DARWIN-X64-LABEL: test17c: ; DARWIN-X64: mov{{l|q}} ___stack_chk_guard ; DARWIN-X64: callq ___stack_chk_fail + +; MSVC-I386-LABEL: test17c: +; MSVC-I386: movl ___security_cookie, +; MSVC-I386: calll @__security_check_cookie@4 %c = alloca %struct.vec, align 16 %y = getelementptr inbounds %struct.vec, %struct.vec* %c, i64 0, i32 0 %add.ptr = getelementptr inbounds <4 x i32>, <4 x i32>* %y, i64 -12 @@ -2087,6 +2353,10 @@ entry: ; DARWIN-X64-LABEL: test17d: ; DARWIN-X64: mov{{l|q}} ___stack_chk_guard ; DARWIN-X64: callq ___stack_chk_fail + +; MSVC-I386-LABEL: test17d: +; MSVC-I386: movl ___security_cookie, +; MSVC-I386: calll @__security_check_cookie@4 %c = alloca %struct.vec, align 16 %y = getelementptr inbounds %struct.vec, %struct.vec* %c, i64 0, i32 0 %add.ptr = getelementptr inbounds <4 x i32>, <4 x i32>* %y, i64 -12 @@ -2114,6 +2384,10 @@ entry: ; DARWIN-X64-LABEL: test18a: ; DARWIN-X64-NOT: callq ___stack_chk_fail ; DARWIN-X64: .cfi_endproc + +; MSVC-I386-LABEL: test18a: +; MSVC-I386-NOT: calll @__security_check_cookie@4 +; MSVC-I386: retl %a = alloca i32, align 4 %exn.slot = alloca i8* %ehselector.slot = alloca i32 @@ -2151,6 +2425,10 @@ entry: ; DARWIN-X64-LABEL: test18b: ; DARWIN-X64-NOT: callq ___stack_chk_fail ; DARWIN-X64: .cfi_endproc + +; MSVC-I386-LABEL: test18b: +; MSVC-I386-NOT: calll @__security_check_cookie@4 +; MSVC-I386: retl %a = alloca i32, align 4 %exn.slot = alloca i8* %ehselector.slot = alloca i32 @@ -2188,6 +2466,10 @@ entry: ; DARWIN-X64-LABEL: test18c: ; DARWIN-X64: mov{{l|q}} ___stack_chk_guard ; DARWIN-X64: callq ___stack_chk_fail + +; MSVC-I386-LABEL: test18c: +; MSVC-I386: movl ___security_cookie, +; MSVC-I386: calll @__security_check_cookie@4 %a = alloca i32, align 4 %exn.slot = alloca i8* %ehselector.slot = alloca i32 @@ -2225,6 +2507,10 @@ entry: ; DARWIN-X64-LABEL: test18d: ; DARWIN-X64: mov{{l|q}} ___stack_chk_guard ; DARWIN-X64: callq ___stack_chk_fail + +; MSVC-I386-LABEL: test18d: +; MSVC-I386: movl ___security_cookie, +; MSVC-I386: calll @__security_check_cookie@4 %a = alloca i32, align 4 %exn.slot = alloca i8* %ehselector.slot = alloca i32 @@ -2261,6 +2547,10 @@ entry: ; DARWIN-X64-LABEL: test19a: ; DARWIN-X64-NOT: callq ___stack_chk_fail ; DARWIN-X64: .cfi_endproc + +; MSVC-I386-LABEL: test19a: +; MSVC-I386-NOT: calll @__security_check_cookie@4 +; MSVC-I386: retl %c = alloca %struct.pair, align 4 %exn.slot = alloca i8* %ehselector.slot = alloca i32 @@ -2301,6 +2591,10 @@ entry: ; DARWIN-X64-LABEL: test19b: ; DARWIN-X64-NOT: callq ___stack_chk_fail ; DARWIN-X64: .cfi_endproc + +; MSVC-I386-LABEL: test19b: +; MSVC-I386-NOT: calll @__security_check_cookie@4 +; MSVC-I386: retl %c = alloca %struct.pair, align 4 %exn.slot = alloca i8* %ehselector.slot = alloca i32 @@ -2341,6 +2635,10 @@ entry: ; DARWIN-X64-LABEL: test19c: ; DARWIN-X64: mov{{l|q}} ___stack_chk_guard ; DARWIN-X64: callq ___stack_chk_fail + +; MSVC-I386-LABEL: test19c: +; MSVC-I386: movl ___security_cookie, +; MSVC-I386: calll @__security_check_cookie@4 %c = alloca %struct.pair, align 4 %exn.slot = alloca i8* %ehselector.slot = alloca i32 @@ -2385,6 +2683,10 @@ entry: ; DARWIN-X64: mov{{l|q}} ___stack_chk_guard ; DARWIN-X64: callq ___stack_chk_fail ; DARWIN-X64-NOT: callq ___stack_chk_fail + +; MSVC-I386-LABEL: test19d: +; MSVC-I386: movl ___security_cookie, +; MSVC-I386: calll @__security_check_cookie@4 %c = alloca %struct.pair, align 4 %exn.slot = alloca i8* %ehselector.slot = alloca i32 @@ -2423,6 +2725,10 @@ entry: ; DARWIN-X64-LABEL: test20a: ; DARWIN-X64-NOT: callq ___stack_chk_fail ; DARWIN-X64: .cfi_endproc + +; MSVC-I386-LABEL: test20a: +; MSVC-I386-NOT: calll @__security_check_cookie@4 +; MSVC-I386: retl %a = alloca i32*, align 8 %b = alloca i32**, align 8 %call = call i32* @getp() @@ -2454,6 +2760,10 @@ entry: ; DARWIN-X64-LABEL: test20b: ; DARWIN-X64-NOT: callq ___stack_chk_fail ; DARWIN-X64: .cfi_endproc + +; MSVC-I386-LABEL: test20b: +; MSVC-I386-NOT: calll @__security_check_cookie@4 +; MSVC-I386: retl %a = alloca i32*, align 8 %b = alloca i32**, align 8 %call = call i32* @getp() @@ -2485,6 +2795,10 @@ entry: ; DARWIN-X64-LABEL: test20c: ; DARWIN-X64: mov{{l|q}} ___stack_chk_guard ; DARWIN-X64: callq ___stack_chk_fail + +; MSVC-I386-LABEL: test20c: +; MSVC-I386: movl ___security_cookie, +; MSVC-I386: calll @__security_check_cookie@4 %a = alloca i32*, align 8 %b = alloca i32**, align 8 %call = call i32* @getp() @@ -2516,6 +2830,10 @@ entry: ; DARWIN-X64-LABEL: test20d: ; DARWIN-X64: mov{{l|q}} ___stack_chk_guard ; DARWIN-X64: callq ___stack_chk_fail + +; MSVC-I386-LABEL: test20d: +; MSVC-I386: movl ___security_cookie, +; MSVC-I386: calll @__security_check_cookie@4 %a = alloca i32*, align 8 %b = alloca i32**, align 8 %call = call i32* @getp() @@ -2546,6 +2864,10 @@ entry: ; DARWIN-X64-LABEL: test21a: ; DARWIN-X64-NOT: callq ___stack_chk_fail ; DARWIN-X64: .cfi_endproc + +; MSVC-I386-LABEL: test21a: +; MSVC-I386-NOT: calll @__security_check_cookie@4 +; MSVC-I386: retl %a = alloca i32*, align 8 %b = alloca float**, align 8 %call = call i32* @getp() @@ -2578,6 +2900,10 @@ entry: ; DARWIN-X64-LABEL: test21b: ; DARWIN-X64-NOT: callq ___stack_chk_fail ; DARWIN-X64: .cfi_endproc + +; MSVC-I386-LABEL: test21b: +; MSVC-I386-NOT: calll @__security_check_cookie@4 +; MSVC-I386: retl %a = alloca i32*, align 8 %b = alloca float**, align 8 %call = call i32* @getp() @@ -2610,6 +2936,10 @@ entry: ; DARWIN-X64-LABEL: test21c: ; DARWIN-X64: mov{{l|q}} ___stack_chk_guard ; DARWIN-X64: callq ___stack_chk_fail + +; MSVC-I386-LABEL: test21c: +; MSVC-I386: movl ___security_cookie, +; MSVC-I386: calll @__security_check_cookie@4 %a = alloca i32*, align 8 %b = alloca float**, align 8 %call = call i32* @getp() @@ -2642,6 +2972,10 @@ entry: ; DARWIN-X64-LABEL: test21d: ; DARWIN-X64: mov{{l|q}} ___stack_chk_guard ; DARWIN-X64: callq ___stack_chk_fail + +; MSVC-I386-LABEL: test21d: +; MSVC-I386: movl ___security_cookie, +; MSVC-I386: calll @__security_check_cookie@4 %a = alloca i32*, align 8 %b = alloca float**, align 8 %call = call i32* @getp() @@ -2673,6 +3007,10 @@ entry: ; DARWIN-X64-LABEL: test22a: ; DARWIN-X64-NOT: callq ___stack_chk_fail ; DARWIN-X64: .cfi_endproc + +; MSVC-I386-LABEL: test22a: +; MSVC-I386-NOT: calll @__security_check_cookie@4 +; MSVC-I386: retl %a = alloca %class.A, align 1 %array = getelementptr inbounds %class.A, %class.A* %a, i32 0, i32 0 %arrayidx = getelementptr inbounds [2 x i8], [2 x i8]* %array, i32 0, i64 0 @@ -2701,6 +3039,10 @@ entry: ; DARWIN-X64-LABEL: test22b: ; DARWIN-X64-NOT: callq ___stack_chk_fail ; DARWIN-X64: .cfi_endproc + +; MSVC-I386-LABEL: test22b: +; MSVC-I386-NOT: calll @__security_check_cookie@4 +; MSVC-I386: retl %a = alloca %class.A, align 1 %array = getelementptr inbounds %class.A, %class.A* %a, i32 0, i32 0 %arrayidx = getelementptr inbounds [2 x i8], [2 x i8]* %array, i32 0, i64 0 @@ -2729,6 +3071,10 @@ entry: ; DARWIN-X64-LABEL: test22c: ; DARWIN-X64: mov{{l|q}} ___stack_chk_guard ; DARWIN-X64: callq ___stack_chk_fail + +; MSVC-I386-LABEL: test22c: +; MSVC-I386: movl ___security_cookie, +; MSVC-I386: calll @__security_check_cookie@4 %a = alloca %class.A, align 1 %array = getelementptr inbounds %class.A, %class.A* %a, i32 0, i32 0 %arrayidx = getelementptr inbounds [2 x i8], [2 x i8]* %array, i32 0, i64 0 @@ -2757,6 +3103,10 @@ entry: ; DARWIN-X64-LABEL: test22d: ; DARWIN-X64: mov{{l|q}} ___stack_chk_guard ; DARWIN-X64: callq ___stack_chk_fail + +; MSVC-I386-LABEL: test22d: +; MSVC-I386: movl ___security_cookie, +; MSVC-I386: calll @__security_check_cookie@4 %a = alloca %class.A, align 1 %array = getelementptr inbounds %class.A, %class.A* %a, i32 0, i32 0 %arrayidx = getelementptr inbounds [2 x i8], [2 x i8]* %array, i32 0, i64 0 @@ -2784,6 +3134,10 @@ entry: ; DARWIN-X64-LABEL: test23a: ; DARWIN-X64-NOT: callq ___stack_chk_fail ; DARWIN-X64: .cfi_endproc + +; MSVC-I386-LABEL: test23a: +; MSVC-I386-NOT: calll @__security_check_cookie@4 +; MSVC-I386: retl %x = alloca %struct.deep, align 1 %b = getelementptr inbounds %struct.deep, %struct.deep* %x, i32 0, i32 0 %c = bitcast %union.anon* %b to %struct.anon* @@ -2816,6 +3170,10 @@ entry: ; DARWIN-X64-LABEL: test23b: ; DARWIN-X64-NOT: callq ___stack_chk_fail ; DARWIN-X64: .cfi_endproc + +; MSVC-I386-LABEL: test23b: +; MSVC-I386-NOT: calll @__security_check_cookie@4 +; MSVC-I386: retl %x = alloca %struct.deep, align 1 %b = getelementptr inbounds %struct.deep, %struct.deep* %x, i32 0, i32 0 %c = bitcast %union.anon* %b to %struct.anon* @@ -2848,6 +3206,10 @@ entry: ; DARWIN-X64-LABEL: test23c: ; DARWIN-X64: mov{{l|q}} ___stack_chk_guard ; DARWIN-X64: callq ___stack_chk_fail + +; MSVC-I386-LABEL: test23c: +; MSVC-I386: movl ___security_cookie, +; MSVC-I386: calll @__security_check_cookie@4 %x = alloca %struct.deep, align 1 %b = getelementptr inbounds %struct.deep, %struct.deep* %x, i32 0, i32 0 %c = bitcast %union.anon* %b to %struct.anon* @@ -2880,6 +3242,10 @@ entry: ; DARWIN-X64-LABEL: test23d: ; DARWIN-X64: mov{{l|q}} ___stack_chk_guard ; DARWIN-X64: callq ___stack_chk_fail + +; MSVC-I386-LABEL: test23d: +; MSVC-I386: movl ___security_cookie, +; MSVC-I386: calll @__security_check_cookie@4 %x = alloca %struct.deep, align 1 %b = getelementptr inbounds %struct.deep, %struct.deep* %x, i32 0, i32 0 %c = bitcast %union.anon* %b to %struct.anon* @@ -2911,6 +3277,10 @@ entry: ; DARWIN-X64-LABEL: test24a: ; DARWIN-X64-NOT: callq ___stack_chk_fail ; DARWIN-X64: .cfi_endproc + +; MSVC-I386-LABEL: test24a: +; MSVC-I386-NOT: calll @__security_check_cookie@4 +; MSVC-I386: retl %n.addr = alloca i32, align 4 %a = alloca i32*, align 8 store i32 %n, i32* %n.addr, align 4 @@ -2943,6 +3313,10 @@ entry: ; DARWIN-X64-LABEL: test24b: ; DARWIN-X64: mov{{l|q}} ___stack_chk_guard ; DARWIN-X64: callq ___stack_chk_fail + +; MSVC-I386-LABEL: test24b: +; MSVC-I386: movl ___security_cookie, +; MSVC-I386: calll @__security_check_cookie@4 %n.addr = alloca i32, align 4 %a = alloca i32*, align 8 store i32 %n, i32* %n.addr, align 4 @@ -2975,6 +3349,10 @@ entry: ; DARWIN-X64-LABEL: test24c: ; DARWIN-X64: mov{{l|q}} ___stack_chk_guard ; DARWIN-X64: callq ___stack_chk_fail + +; MSVC-I386-LABEL: test24c: +; MSVC-I386: movl ___security_cookie, +; MSVC-I386: calll @__security_check_cookie@4 %n.addr = alloca i32, align 4 %a = alloca i32*, align 8 store i32 %n, i32* %n.addr, align 4 @@ -3007,6 +3385,10 @@ entry: ; DARWIN-X64-LABEL: test24d: ; DARWIN-X64: mov{{l|q}} ___stack_chk_guard ; DARWIN-X64: callq ___stack_chk_fail + +; MSVC-I386-LABEL: test24d: +; MSVC-I386: movl ___security_cookie, +; MSVC-I386: calll @__security_check_cookie@4 %n.addr = alloca i32, align 4 %a = alloca i32*, align 8 store i32 %n, i32* %n.addr, align 4 @@ -3038,6 +3420,10 @@ entry: ; DARWIN-X64-LABEL: test25a: ; DARWIN-X64-NOT: callq ___stack_chk_fail ; DARWIN-X64: .cfi_endproc + +; MSVC-I386-LABEL: test25a: +; MSVC-I386-NOT: calll @__security_check_cookie@4 +; MSVC-I386: retl %a = alloca [4 x i32], align 16 %arrayidx = getelementptr inbounds [4 x i32], [4 x i32]* %a, i32 0, i64 0 %0 = load i32, i32* %arrayidx, align 4 @@ -3065,6 +3451,10 @@ entry: ; DARWIN-X64-LABEL: test25b: ; DARWIN-X64: mov{{l|q}} ___stack_chk_guard ; DARWIN-X64: callq ___stack_chk_fail + +; MSVC-I386-LABEL: test25b: +; MSVC-I386-NOT: calll @__security_check_cookie@4 +; MSVC-I386: retl %a = alloca [4 x i32], align 16 %arrayidx = getelementptr inbounds [4 x i32], [4 x i32]* %a, i32 0, i64 0 %0 = load i32, i32* %arrayidx, align 4 @@ -3092,6 +3482,10 @@ entry: ; DARWIN-X64-LABEL: test25c: ; DARWIN-X64: mov{{l|q}} ___stack_chk_guard ; DARWIN-X64: callq ___stack_chk_fail + +; MSVC-I386-LABEL: test25c: +; MSVC-I386: movl ___security_cookie, +; MSVC-I386: calll @__security_check_cookie@4 %a = alloca [4 x i32], align 16 %arrayidx = getelementptr inbounds [4 x i32], [4 x i32]* %a, i32 0, i64 0 %0 = load i32, i32* %arrayidx, align 4 @@ -3119,6 +3513,10 @@ entry: ; DARWIN-X64-LABEL: test25d: ; DARWIN-X64: mov{{l|q}} ___stack_chk_guard ; DARWIN-X64: callq ___stack_chk_fail + +; MSVC-I386-LABEL: test25d: +; MSVC-I386: movl ___security_cookie, +; MSVC-I386: calll @__security_check_cookie@4 %a = alloca [4 x i32], align 16 %arrayidx = getelementptr inbounds [4 x i32], [4 x i32]* %a, i32 0, i64 0 %0 = load i32, i32* %arrayidx, align 4 @@ -3148,6 +3546,10 @@ entry: ; DARWIN-X64-LABEL: test26: ; DARWIN-X64-NOT: callq ___stack_chk_fail ; DARWIN-X64: .cfi_endproc + +; MSVC-I386-LABEL: test26: +; MSVC-I386-NOT: calll @__security_check_cookie@4 +; MSVC-I386: retl %c = alloca %struct.nest, align 4 %b = getelementptr inbounds %struct.nest, %struct.nest* %c, i32 0, i32 1 %_a = getelementptr inbounds %struct.pair, %struct.pair* %b, i32 0, i32 0 @@ -3180,6 +3582,10 @@ bb: ; DARWIN-X64-LABEL: test27: ; DARWIN-X64: mov{{l|q}} ___stack_chk_guard ; DARWIN-X64: callq ___stack_chk_fail + +; MSVC-I386-LABEL: test27: +; MSVC-I386: movl ___security_cookie, +; MSVC-I386: calll @__security_check_cookie@4 %tmp = alloca %struct.small*, align 8 %tmp1 = call i32 (...) @dummy(%struct.small** %tmp) %tmp2 = load %struct.small*, %struct.small** %tmp, align 8 @@ -3233,6 +3639,10 @@ entry: ; DARWIN-X64-LABEL: test28a: ; DARWIN-X64-NOT: callq ___stack_chk_fail ; DARWIN-X64: .cfi_endproc + +; MSVC-I386-LABEL: test28a: +; MSVC-I386-NOT: calll @__security_check_cookie@4 +; MSVC-I386: retl %test = alloca [32 x i8], align 16 %arraydecay = getelementptr inbounds [32 x i8], [32 x i8]* %test, i32 0, i32 0 %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0), i8* %arraydecay) @@ -3259,6 +3669,10 @@ entry: ; DARWIN-X64-LABEL: test28b: ; DARWIN-X64: mov{{l|q}} ___stack_chk_guard ; DARWIN-X64: callq ___stack_chk_fail + +; MSVC-I386-LABEL: test28b: +; MSVC-I386: movl ___security_cookie, +; MSVC-I386: calll @__security_check_cookie@4 %test = alloca [33 x i8], align 16 %arraydecay = getelementptr inbounds [33 x i8], [33 x i8]* %test, i32 0, i32 0 %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0), i8* %arraydecay) @@ -3285,6 +3699,10 @@ entry: ; DARWIN-X64-LABEL: test29a: ; DARWIN-X64-NOT: callq ___stack_chk_fail ; DARWIN-X64: .cfi_endproc + +; MSVC-I386-LABEL: test29a: +; MSVC-I386-NOT: calll @__security_check_cookie@4 +; MSVC-I386: retl %test = alloca [4 x i8], align 1 %arraydecay = getelementptr inbounds [4 x i8], [4 x i8]* %test, i32 0, i32 0 %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0), i8* %arraydecay) @@ -3311,6 +3729,10 @@ entry: ; DARWIN-X64-LABEL: test29b: ; DARWIN-X64: mov{{l|q}} ___stack_chk_guard ; DARWIN-X64: callq ___stack_chk_fail + +; MSVC-I386-LABEL: test29b: +; MSVC-I386: movl ___security_cookie, +; MSVC-I386: calll @__security_check_cookie@4 %test = alloca [5 x i8], align 1 %arraydecay = getelementptr inbounds [5 x i8], [5 x i8]* %test, i32 0, i32 0 %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0), i8* %arraydecay) @@ -3338,6 +3760,10 @@ entry: ; DARWIN-X64-LABEL: test30a: ; DARWIN-X64-NOT: callq ___stack_chk_fail ; DARWIN-X64: .cfi_endproc + +; MSVC-I386-LABEL: test30a: +; MSVC-I386-NOT: calll @__security_check_cookie@4 +; MSVC-I386: retl %test = alloca %struct.small_char, align 4 %test.coerce = alloca { i64, i8 } %0 = bitcast { i64, i8 }* %test.coerce to i8* @@ -3372,6 +3798,10 @@ entry: ; DARWIN-X64-LABEL: test30b: ; DARWIN-X64: mov{{l|q}} ___stack_chk_guard ; DARWIN-X64: callq ___stack_chk_fail + +; MSVC-I386-LABEL: test30b: +; MSVC-I386: movl ___security_cookie, +; MSVC-I386: calll @__security_check_cookie@4 %test = alloca %struct.small_char, align 4 %test.coerce = alloca { i64, i8 } %0 = bitcast { i64, i8 }* %test.coerce to i8* @@ -3406,6 +3836,10 @@ entry: ; DARWIN-X64-LABEL: test31a: ; DARWIN-X64-NOT: callq ___stack_chk_fail ; DARWIN-X64: .cfi_endproc + +; MSVC-I386-LABEL: test31a: +; MSVC-I386-NOT: calll @__security_check_cookie@4 +; MSVC-I386: retl %test = alloca i8*, align 8 %0 = alloca i8, i64 4 store i8* %0, i8** %test, align 8 @@ -3434,6 +3868,10 @@ entry: ; DARWIN-X64-LABEL: test31b: ; DARWIN-X64: mov{{l|q}} ___stack_chk_guard ; DARWIN-X64: callq ___stack_chk_fail + +; MSVC-I386-LABEL: test31b: +; MSVC-I386: movl ___security_cookie, +; MSVC-I386: calll @__security_check_cookie@4 %test = alloca i8*, align 8 %0 = alloca i8, i64 5 store i8* %0, i8** %test, align 8 -- 2.11.0