Index: include/clang/Basic/Attr.td =================================================================== --- include/clang/Basic/Attr.td +++ include/clang/Basic/Attr.td @@ -2029,6 +2029,12 @@ // Microsoft-related attributes +def MSHookPrologue : InheritableAttr { + let Spellings = [GCC<"ms_hook_prologue">]; + let Subjects = SubjectList<[Function]>; + let Documentation = [MSHookPrologueDocs]; +} + def MSNoVTable : InheritableAttr, TargetSpecificAttr { let Spellings = [Declspec<"novtable">]; let Subjects = SubjectList<[CXXRecord]>; Index: include/clang/Basic/AttrDocs.td =================================================================== --- include/clang/Basic/AttrDocs.td +++ include/clang/Basic/AttrDocs.td @@ -494,6 +494,19 @@ }]; } +def MSHookPrologueDocs : Documentation { + let Category = DocCatFunction; + let Content = [{ +The ``ms_hook_prologue`` attribute marks a function as "hotpatchable" according +to conventions used on Windows. Specifically, enough space will be ensured +in the prologue for a short jump, and an architecturally dependently sized +patch space will be reserved prior to the entry point. See the documentation +for the `/HOTPATCH`_ switch on MSDN. + +.. _`/HOTPATCH/: https://msdn.microsoft.com/en-us/library/ms173507.aspx + }]; +} + def NoDebugDocs : Documentation { let Category = DocCatVariable; let Content = [{ Index: lib/CodeGen/TargetInfo.cpp =================================================================== --- lib/CodeGen/TargetInfo.cpp +++ lib/CodeGen/TargetInfo.cpp @@ -1749,6 +1749,10 @@ llvm::Function *Fn = cast(GV); Fn->setCallingConv(llvm::CallingConv::X86_INTR); } + if (FD->hasAttr()) { + llvm::Function *Fn = cast(GV); + Fn->addFnAttr("patchable-function", "ms-hotpatch"); + } } } @@ -2079,6 +2083,10 @@ llvm::Function *Fn = cast(GV); Fn->setCallingConv(llvm::CallingConv::X86_INTR); } + if (FD->hasAttr()) { + llvm::Function *Fn = cast(GV); + Fn->addFnAttr("patchable-function", "ms-hotpatch"); + } } } }; Index: lib/Sema/SemaDeclAttr.cpp =================================================================== --- lib/Sema/SemaDeclAttr.cpp +++ lib/Sema/SemaDeclAttr.cpp @@ -5748,6 +5748,9 @@ break; // Microsoft attributes: + case AttributeList::AT_MSHookPrologue: + handleSimpleAttribute(S, D, Attr); + break; case AttributeList::AT_MSNoVTable: handleSimpleAttribute(S, D, Attr); break; Index: test/CodeGen/function-attributes.c =================================================================== --- test/CodeGen/function-attributes.c +++ test/CodeGen/function-attributes.c @@ -108,11 +108,18 @@ _setjmp(0); } +// CHECK-LABEL: define void @f21 +// CHECK: [[HOTPATCH:#[0-9]+]] +// CHECK: { +void __attribute__((ms_hook_prologue)) f21(void) { +} + // CHECK: attributes [[NUW]] = { nounwind optsize{{.*}} } // CHECK: attributes [[AI]] = { alwaysinline nounwind optsize{{.*}} } // CHECK: attributes [[NUW_OS_RN]] = { nounwind optsize readnone{{.*}} } // CHECK: attributes [[ALIGN]] = { nounwind optsize alignstack=16{{.*}} } // CHECK: attributes [[RT]] = { nounwind optsize returns_twice{{.*}} } +// CHECK: attributes [[HOTPATCH]] = { nounwind optsize{{.*}}"patchable-function"="ms-hotpatch"{{.*}} } // CHECK: attributes [[NR]] = { noreturn optsize } // CHECK: attributes [[NUW_RN]] = { nounwind optsize readnone } // CHECK: attributes [[RT_CALL]] = { optsize returns_twice }