patch-r263312-llvm-r169939-inline-asm-with-realign.diff revision 269012
1Pull in r196939 from upstream llvm trunk (by Reid Kleckner): 2 3 Reland "Fix miscompile of MS inline assembly with stack realignment" 4 5 This re-lands commit r196876, which was reverted in r196879. 6 7 The tests have been fixed to pass on platforms with a stack alignment 8 larger than 4. 9 10 Update to clang side tests will land shortly. 11 12Introduced here: http://svnweb.freebsd.org/changeset/base/263312 13 14Index: test/CodeGen/X86/inline-asm-stack-realign2.ll 15=================================================================== 16--- test/CodeGen/X86/inline-asm-stack-realign2.ll 17+++ test/CodeGen/X86/inline-asm-stack-realign2.ll 18@@ -0,0 +1,15 @@ 19+; RUN: not llc -mtriple=i686-pc-win32 < %s 2>&1 | FileCheck %s 20+ 21+; We don't currently support realigning the stack and adjusting the stack 22+; pointer in inline asm. This can even happen in GNU asm. 23+ 24+; CHECK: Stack realignment in presence of dynamic stack adjustments is not supported with inline assembly 25+ 26+define i32 @foo() { 27+entry: 28+ %r = alloca i32, align 16 29+ store i32 -1, i32* %r, align 16 30+ call void asm sideeffect "push %esi\0A\09xor %esi, %esi\0A\09mov %esi, $0\0A\09pop %esi", "=*m,~{flags},~{esi},~{esp},~{dirflag},~{fpsr},~{flags}"(i32* %r) 31+ %0 = load i32* %r, align 16 32+ ret i32 %0 33+} 34Index: test/CodeGen/X86/inline-asm-stack-realign.ll 35=================================================================== 36--- test/CodeGen/X86/inline-asm-stack-realign.ll 37+++ test/CodeGen/X86/inline-asm-stack-realign.ll 38@@ -0,0 +1,16 @@ 39+; RUN: not llc -mtriple=i686-pc-win32 < %s 2>&1 | FileCheck %s 40+ 41+; We don't currently support realigning the stack and adjusting the stack 42+; pointer in inline asm. This commonly happens in MS inline assembly using 43+; push and pop. 44+ 45+; CHECK: Stack realignment in presence of dynamic stack adjustments is not supported with inline assembly 46+ 47+define i32 @foo() { 48+entry: 49+ %r = alloca i32, align 16 50+ store i32 -1, i32* %r, align 16 51+ call void asm sideeffect inteldialect "push esi\0A\09xor esi, esi\0A\09mov dword ptr $0, esi\0A\09pop esi", "=*m,~{flags},~{esi},~{esp},~{dirflag},~{fpsr},~{flags}"(i32* %r) 52+ %0 = load i32* %r, align 16 53+ ret i32 %0 54+} 55Index: test/CodeGen/X86/ms-inline-asm.ll 56=================================================================== 57--- test/CodeGen/X86/ms-inline-asm.ll 58+++ test/CodeGen/X86/ms-inline-asm.ll 59@@ -5,7 +5,6 @@ entry: 60 %0 = tail call i32 asm sideeffect inteldialect "mov eax, $1\0A\09mov $0, eax", "=r,r,~{eax},~{dirflag},~{fpsr},~{flags}"(i32 1) nounwind 61 ret i32 %0 62 ; CHECK: t1 63-; CHECK: movl %esp, %ebp 64 ; CHECK: {{## InlineAsm Start|#APP}} 65 ; CHECK: .intel_syntax 66 ; CHECK: mov eax, ecx 67@@ -19,7 +18,6 @@ entry: 68 call void asm sideeffect inteldialect "mov eax, $$1", "~{eax},~{dirflag},~{fpsr},~{flags}"() nounwind 69 ret void 70 ; CHECK: t2 71-; CHECK: movl %esp, %ebp 72 ; CHECK: {{## InlineAsm Start|#APP}} 73 ; CHECK: .intel_syntax 74 ; CHECK: mov eax, 1 75@@ -34,7 +32,6 @@ entry: 76 call void asm sideeffect inteldialect "mov eax, DWORD PTR [$0]", "*m,~{eax},~{dirflag},~{fpsr},~{flags}"(i32* %V.addr) nounwind 77 ret void 78 ; CHECK: t3 79-; CHECK: movl %esp, %ebp 80 ; CHECK: {{## InlineAsm Start|#APP}} 81 ; CHECK: .intel_syntax 82 ; CHECK: mov eax, DWORD PTR {{[[esp]}} 83@@ -56,7 +53,6 @@ entry: 84 %0 = load i32* %b1, align 4 85 ret i32 %0 86 ; CHECK: t18 87-; CHECK: movl %esp, %ebp 88 ; CHECK: {{## InlineAsm Start|#APP}} 89 ; CHECK: .intel_syntax 90 ; CHECK: lea ebx, foo 91@@ -76,7 +72,6 @@ entry: 92 call void asm sideeffect inteldialect "call $0", "r,~{dirflag},~{fpsr},~{flags}"(void ()* @t19_helper) nounwind 93 ret void 94 ; CHECK-LABEL: t19: 95-; CHECK: movl %esp, %ebp 96 ; CHECK: movl ${{_?}}t19_helper, %eax 97 ; CHECK: {{## InlineAsm Start|#APP}} 98 ; CHECK: .intel_syntax 99@@ -95,7 +90,6 @@ entry: 100 %0 = load i32** %res, align 4 101 ret i32* %0 102 ; CHECK-LABEL: t30: 103-; CHECK: movl %esp, %ebp 104 ; CHECK: {{## InlineAsm Start|#APP}} 105 ; CHECK: .intel_syntax 106 ; CHECK: lea edi, dword ptr [{{_?}}results] 107@@ -103,8 +97,31 @@ entry: 108 ; CHECK: {{## InlineAsm End|#NO_APP}} 109 ; CHECK: {{## InlineAsm Start|#APP}} 110 ; CHECK: .intel_syntax 111-; CHECK: mov dword ptr [esi], edi 112+; CHECK: mov dword ptr [esp], edi 113 ; CHECK: .att_syntax 114 ; CHECK: {{## InlineAsm End|#NO_APP}} 115-; CHECK: movl (%esi), %eax 116+; CHECK: movl (%esp), %eax 117 } 118+ 119+; Stack realignment plus MS inline asm that does *not* adjust the stack is no 120+; longer an error. 121+ 122+define i32 @t31() { 123+entry: 124+ %val = alloca i32, align 64 125+ store i32 -1, i32* %val, align 64 126+ call void asm sideeffect inteldialect "mov dword ptr $0, esp", "=*m,~{dirflag},~{fpsr},~{flags}"(i32* %val) #1 127+ %sp = load i32* %val, align 64 128+ ret i32 %sp 129+; CHECK-LABEL: t31: 130+; CHECK: pushl %ebp 131+; CHECK: movl %esp, %ebp 132+; CHECK: andl $-64, %esp 133+; CHECK: {{## InlineAsm Start|#APP}} 134+; CHECK: .intel_syntax 135+; CHECK: mov dword ptr [esp], esp 136+; CHECK: .att_syntax 137+; CHECK: {{## InlineAsm End|#NO_APP}} 138+; CHECK: movl (%esp), %eax 139+; CHECK: ret 140+} 141Index: include/llvm/CodeGen/MachineFrameInfo.h 142=================================================================== 143--- include/llvm/CodeGen/MachineFrameInfo.h 144+++ include/llvm/CodeGen/MachineFrameInfo.h 145@@ -223,6 +223,10 @@ class MachineFrameInfo { 146 /// Whether the "realign-stack" option is on. 147 bool RealignOption; 148 149+ /// True if the function includes inline assembly that adjusts the stack 150+ /// pointer. 151+ bool HasInlineAsmWithSPAdjust; 152+ 153 const TargetFrameLowering *getFrameLowering() const; 154 public: 155 explicit MachineFrameInfo(const TargetMachine &TM, bool RealignOpt) 156@@ -451,6 +455,10 @@ class MachineFrameInfo { 157 bool hasCalls() const { return HasCalls; } 158 void setHasCalls(bool V) { HasCalls = V; } 159 160+ /// Returns true if the function contains any stack-adjusting inline assembly. 161+ bool hasInlineAsmWithSPAdjust() const { return HasInlineAsmWithSPAdjust; } 162+ void setHasInlineAsmWithSPAdjust(bool B) { HasInlineAsmWithSPAdjust = B; } 163+ 164 /// getMaxCallFrameSize - Return the maximum size of a call frame that must be 165 /// allocated for an outgoing function call. This is only available if 166 /// CallFrameSetup/Destroy pseudo instructions are used by the target, and 167Index: include/llvm/CodeGen/MachineFunction.h 168=================================================================== 169--- include/llvm/CodeGen/MachineFunction.h 170+++ include/llvm/CodeGen/MachineFunction.h 171@@ -131,8 +131,8 @@ class MachineFunction { 172 /// about the control flow of such functions. 173 bool ExposesReturnsTwice; 174 175- /// True if the function includes MS-style inline assembly. 176- bool HasMSInlineAsm; 177+ /// True if the function includes any inline assembly. 178+ bool HasInlineAsm; 179 180 MachineFunction(const MachineFunction &) LLVM_DELETED_FUNCTION; 181 void operator=(const MachineFunction&) LLVM_DELETED_FUNCTION; 182@@ -218,15 +218,14 @@ class MachineFunction { 183 ExposesReturnsTwice = B; 184 } 185 186- /// Returns true if the function contains any MS-style inline assembly. 187- bool hasMSInlineAsm() const { 188- return HasMSInlineAsm; 189+ /// Returns true if the function contains any inline assembly. 190+ bool hasInlineAsm() const { 191+ return HasInlineAsm; 192 } 193 194- /// Set a flag that indicates that the function contains MS-style inline 195- /// assembly. 196- void setHasMSInlineAsm(bool B) { 197- HasMSInlineAsm = B; 198+ /// Set a flag that indicates that the function contains inline assembly. 199+ void setHasInlineAsm(bool B) { 200+ HasInlineAsm = B; 201 } 202 203 /// getInfo - Keep track of various per-function pieces of information for 204Index: lib/Target/X86/X86FrameLowering.cpp 205=================================================================== 206--- lib/Target/X86/X86FrameLowering.cpp 207+++ lib/Target/X86/X86FrameLowering.cpp 208@@ -50,7 +50,7 @@ bool X86FrameLowering::hasFP(const MachineFunction 209 return (MF.getTarget().Options.DisableFramePointerElim(MF) || 210 RegInfo->needsStackRealignment(MF) || 211 MFI->hasVarSizedObjects() || 212- MFI->isFrameAddressTaken() || MF.hasMSInlineAsm() || 213+ MFI->isFrameAddressTaken() || MFI->hasInlineAsmWithSPAdjust() || 214 MF.getInfo<X86MachineFunctionInfo>()->getForceFramePointer() || 215 MMI.callsUnwindInit() || MMI.callsEHReturn()); 216 } 217Index: lib/Target/X86/X86RegisterInfo.cpp 218=================================================================== 219--- lib/Target/X86/X86RegisterInfo.cpp 220+++ lib/Target/X86/X86RegisterInfo.cpp 221@@ -347,6 +347,12 @@ BitVector X86RegisterInfo::getReservedRegs(const M 222 "Stack realignment in presence of dynamic allocas is not supported with" 223 "this calling convention."); 224 225+ // FIXME: Do a proper analysis of the inline asm to see if it actually 226+ // conflicts with the base register we chose. 227+ if (MF.hasInlineAsm()) 228+ report_fatal_error("Stack realignment in presence of dynamic stack " 229+ "adjustments is not supported with inline assembly."); 230+ 231 for (MCSubRegIterator I(getBaseRegister(), this, /*IncludeSelf=*/true); 232 I.isValid(); ++I) 233 Reserved.set(*I); 234@@ -403,18 +409,15 @@ bool X86RegisterInfo::hasBasePointer(const Machine 235 if (!EnableBasePointer) 236 return false; 237 238- // When we need stack realignment and there are dynamic allocas, we can't 239- // reference off of the stack pointer, so we reserve a base pointer. 240- // 241- // This is also true if the function contain MS-style inline assembly. We 242- // do this because if any stack changes occur in the inline assembly, e.g., 243- // "pusha", then any C local variable or C argument references in the 244- // inline assembly will be wrong because the SP is not properly tracked. 245- if ((needsStackRealignment(MF) && MFI->hasVarSizedObjects()) || 246- MF.hasMSInlineAsm()) 247- return true; 248- 249- return false; 250+ // When we need stack realignment, we can't address the stack from the frame 251+ // pointer. When we have dynamic allocas or stack-adjusting inline asm, we 252+ // can't address variables from the stack pointer. MS inline asm can 253+ // reference locals while also adjusting the stack pointer. When we can't 254+ // use both the SP and the FP, we need a separate base pointer register. 255+ bool CantUseFP = needsStackRealignment(MF); 256+ bool CantUseSP = 257+ MFI->hasVarSizedObjects() || MFI->hasInlineAsmWithSPAdjust(); 258+ return CantUseFP && CantUseSP; 259 } 260 261 bool X86RegisterInfo::canRealignStack(const MachineFunction &MF) const { 262Index: lib/MC/MCParser/AsmParser.cpp 263=================================================================== 264--- lib/MC/MCParser/AsmParser.cpp 265+++ lib/MC/MCParser/AsmParser.cpp 266@@ -4192,6 +4192,11 @@ bool AsmParser::parseMSInlineAsm( 267 AsmStrRewrites.push_back(AsmRewrite(AOK_Input, Start, SymName.size())); 268 } 269 } 270+ 271+ // Consider implicit defs to be clobbers. Think of cpuid and push. 272+ const uint16_t *ImpDefs = Desc.getImplicitDefs(); 273+ for (unsigned I = 0, E = Desc.getNumImplicitDefs(); I != E; ++I) 274+ ClobberRegs.push_back(ImpDefs[I]); 275 } 276 277 // Set the number of Outputs and Inputs. 278Index: lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp 279=================================================================== 280--- lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp 281+++ lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp 282@@ -851,12 +851,20 @@ void RegsForValue::AddInlineAsmOperands(unsigned C 283 SDValue Res = DAG.getTargetConstant(Flag, MVT::i32); 284 Ops.push_back(Res); 285 286+ unsigned SP = TLI.getStackPointerRegisterToSaveRestore(); 287 for (unsigned Value = 0, Reg = 0, e = ValueVTs.size(); Value != e; ++Value) { 288 unsigned NumRegs = TLI.getNumRegisters(*DAG.getContext(), ValueVTs[Value]); 289 MVT RegisterVT = RegVTs[Value]; 290 for (unsigned i = 0; i != NumRegs; ++i) { 291 assert(Reg < Regs.size() && "Mismatch in # registers expected"); 292- Ops.push_back(DAG.getRegister(Regs[Reg++], RegisterVT)); 293+ unsigned TheReg = Regs[Reg++]; 294+ Ops.push_back(DAG.getRegister(TheReg, RegisterVT)); 295+ 296+ // Notice if we clobbered the stack pointer. Yes, inline asm can do this. 297+ if (TheReg == SP && Code == InlineAsm::Kind_Clobber) { 298+ MachineFrameInfo *MFI = DAG.getMachineFunction().getFrameInfo(); 299+ MFI->setHasInlineAsmWithSPAdjust(true); 300+ } 301 } 302 } 303 } 304Index: lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp 305=================================================================== 306--- lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp 307+++ lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp 308@@ -428,7 +428,9 @@ bool SelectionDAGISel::runOnMachineFunction(Machin 309 310 SDB->init(GFI, *AA, LibInfo); 311 312- MF->setHasMSInlineAsm(false); 313+ MF->setHasInlineAsm(false); 314+ MF->getFrameInfo()->setHasInlineAsmWithSPAdjust(false); 315+ 316 SelectAllBasicBlocks(Fn); 317 318 // If the first basic block in the function has live ins that need to be 319@@ -511,7 +513,7 @@ bool SelectionDAGISel::runOnMachineFunction(Machin 320 for (MachineFunction::const_iterator I = MF->begin(), E = MF->end(); I != E; 321 ++I) { 322 323- if (MFI->hasCalls() && MF->hasMSInlineAsm()) 324+ if (MFI->hasCalls() && MF->hasInlineAsm()) 325 break; 326 327 const MachineBasicBlock *MBB = I; 328@@ -522,8 +524,8 @@ bool SelectionDAGISel::runOnMachineFunction(Machin 329 II->isStackAligningInlineAsm()) { 330 MFI->setHasCalls(true); 331 } 332- if (II->isMSInlineAsm()) { 333- MF->setHasMSInlineAsm(true); 334+ if (II->isInlineAsm()) { 335+ MF->setHasInlineAsm(true); 336 } 337 } 338 } 339