Index: lib/Target/X86/X86AsmPrinter.h =================================================================== --- lib/Target/X86/X86AsmPrinter.h +++ lib/Target/X86/X86AsmPrinter.h @@ -107,6 +107,8 @@ SMShadowTracker.emitShadowPadding(*OutStreamer, getSubtargetInfo()); } + void EmitFunctionEntryLabel() override; + bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, unsigned AsmVariant, const char *ExtraCode, raw_ostream &OS) override; Index: lib/Target/X86/X86AsmPrinter.cpp =================================================================== --- lib/Target/X86/X86AsmPrinter.cpp +++ lib/Target/X86/X86AsmPrinter.cpp @@ -73,6 +73,23 @@ return false; } +void X86AsmPrinter::EmitFunctionEntryLabel() { + // If a hotpatch function, we need to ensure 64 (32-bit) or 128 (64-bit) + // bytes of padding precede the label. This is the scratch space used + // by the hotpatching mechanism to insert a jump to the patch code. The + // movl %edi, %edi instruction emitted as the very first instruction of + // a hotpatch function is usually overwritten with a short jump + // instruction when the patch is installed, so it will jump directly into + // this space. + if (MF->getFunction()->hasFnAttribute("ms-hotpatch")) { + // FIXME: Figure out some way to use the X86AsmBackend::writeNopData() + // method for this. + OutStreamer->EmitFill(Subtarget->is64Bit() ? 128 : 64, 0xcc); + } + + AsmPrinter::EmitFunctionEntryLabel(); +} + /// printSymbolOperand - Print a raw symbol reference operand. This handles /// jump tables, constant pools, global address and external symbols, all of /// which print to a label with various suffixes for relocation types etc. Index: lib/Target/X86/X86FrameLowering.cpp =================================================================== --- lib/Target/X86/X86FrameLowering.cpp +++ lib/Target/X86/X86FrameLowering.cpp @@ -927,6 +927,7 @@ bool NeedsWinCFI = IsWin64Prologue && Fn->needsUnwindTableEntry(); bool NeedsDwarfCFI = !IsWin64Prologue && (MMI.hasDebugInfo() || Fn->needsUnwindTableEntry()); + bool IsMSHotpatch = Fn->hasFnAttribute("ms-hotpatch"); unsigned FramePtr = TRI->getFrameRegister(MF); const unsigned MachineFramePtr = STI.isTarget64BitILP32() @@ -975,6 +976,16 @@ MFI->setStackSize(StackSize); } + if (IsMSHotpatch && !Is64Bit) + // Add a no-op movl %edi, %edi instruction. A short jump instruction + // will be written over it if a patch is installed. This particular + // instruction is often used as a sort of magic number indicating that + // this function can be patched. + // N.B. This MI *must* be the first instruction, or the hook won't work. + BuildMI(MBB, MBBI, DL, TII.get(X86::MOV32rr_REV), X86::EDI) + .addReg(X86::EDI) + .setMIFlag(MachineInstr::FrameSetup); + // Insert stack pointer adjustment for later moving of return addr. Only // applies to tail call optimized functions where the callee argument stack // size is bigger than the callers. @@ -1068,7 +1079,9 @@ if (!IsWin64Prologue && !IsFunclet) { // Update EBP with the new base value. BuildMI(MBB, MBBI, DL, - TII.get(Uses64BitFramePtr ? X86::MOV64rr : X86::MOV32rr), + TII.get(IsMSHotpatch ? + (Uses64BitFramePtr ? X86::MOV64rr_REV : X86::MOV32rr_REV): + (Uses64BitFramePtr ? X86::MOV64rr : X86::MOV32rr)), FramePtr) .addReg(StackPtr) .setMIFlag(MachineInstr::FrameSetup); Index: lib/Target/X86/X86ISelLowering.cpp =================================================================== --- lib/Target/X86/X86ISelLowering.cpp +++ lib/Target/X86/X86ISelLowering.cpp @@ -2495,9 +2495,10 @@ const TargetFrameLowering &TFI = *Subtarget.getFrameLowering(); const Function* Fn = MF.getFunction(); - if (Fn->hasExternalLinkage() && - Subtarget.isTargetCygMing() && - Fn->getName() == "main") + if ((Fn->hasExternalLinkage() && + Subtarget.isTargetCygMing() && + Fn->getName() == "main") || + Fn->hasFnAttribute("ms-hotpatch")) FuncInfo->setForceFramePointer(true); MachineFrameInfo *MFI = MF.getFrameInfo(); Index: test/CodeGen/X86/ms-hotpatch-attr.ll =================================================================== --- /dev/null +++ test/CodeGen/X86/ms-hotpatch-attr.ll @@ -0,0 +1,16 @@ +; RUN: llc < %s -march=x86 -filetype=asm | FileCheck -check-prefix=CHECK-32 %s +; RUN: llc < %s -march=x86-64 -filetype=asm | FileCheck -check-prefix=CHECK-64 %s + +; CHECK-32: .space 64,204 +; CHECK-32-LABEL: foo: +; CHECK-32: movl %edi, %edi +; CHECK-32-NEXT: pushl %ebp +; CHECK-32-NEXT: movl %esp, %ebp +; CHECK-64: .space 128,204 +; CHECK-64-LABEL: foo: +; CHECK-64: pushq %rbp +; CHECK-64-NEXT: movq %rsp, %rbp +define void @foo() nounwind "ms-hotpatch" { +entry: + ret void +}