diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def --- a/clang/include/clang/Basic/CodeGenOptions.def +++ b/clang/include/clang/Basic/CodeGenOptions.def @@ -139,6 +139,9 @@ VALUE_CODEGENOPT(PatchableFunctionEntryCount , 32, 0) ///< Number of NOPs at function entry VALUE_CODEGENOPT(PatchableFunctionEntryOffset , 32, 0) +CODEGENOPT(HotPatch, 1, 0) ///< Supports the Microsoft /HOTPATCH flag and would + ///< generate a 'patchable-function' attribute. + CODEGENOPT(InstrumentForProfiling , 1, 0) ///< Set when -pg is enabled. CODEGENOPT(CallFEntry , 1, 0) ///< Set when -mfentry is enabled. CODEGENOPT(MNopMCount , 1, 0) ///< Set when -mnop-mcount is enabled. diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -2490,6 +2490,9 @@ def fpatchable_function_entry_EQ : Joined<["-"], "fpatchable-function-entry=">, Group, Flags<[CC1Option]>, MetaVarName<"">, HelpText<"Generate M NOPs before function entry and N-M NOPs after function entry">, MarshallingInfoInt>; +def fhotpatch : Flag<["-"], "fhotpatch">, Group, Flags<[CC1Option]>, + HelpText<"Ensure that all functions can be hotpatched at runtime">, + MarshallingInfoFlag>; def fpcc_struct_return : Flag<["-"], "fpcc-struct-return">, Group, Flags<[CC1Option]>, HelpText<"Override the default ABI to return all structs on the stack">; def fpch_preprocess : Flag<["-"], "fpch-preprocess">, Group; @@ -6114,6 +6117,8 @@ def _SLASH_help : CLFlag<"help">, Alias, HelpText<"Display available options">; def _SLASH_HELP : CLFlag<"HELP">, Alias; +def _SLASH_hotpatch : CLFlag<"hotpatch">, Alias, + HelpText<"Create hotpatchable image">; def _SLASH_I : CLJoinedOrSeparate<"I">, HelpText<"Add directory to include search path">, MetaVarName<"">, Alias; @@ -6470,7 +6475,6 @@ def _SLASH_headerUnitAngle : CLJoinedOrSeparate<"headerUnit:angle">; def _SLASH_headerUnitQuote : CLJoinedOrSeparate<"headerUnit:quote">; def _SLASH_homeparams : CLFlag<"homeparams">; -def _SLASH_hotpatch : CLFlag<"hotpatch">; def _SLASH_kernel : CLFlag<"kernel">; def _SLASH_LN : CLFlag<"LN">; def _SLASH_MP : CLJoined<"MP">; diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp --- a/clang/lib/CodeGen/BackendUtil.cpp +++ b/clang/lib/CodeGen/BackendUtil.cpp @@ -645,6 +645,7 @@ Options.MCOptions.CommandLineArgs = CodeGenOpts.CommandLineArgs; Options.DebugStrictDwarf = CodeGenOpts.DebugStrictDwarf; Options.ObjectFilenameForDebug = CodeGenOpts.ObjectFilenameForDebug; + Options.Hotpatch = CodeGenOpts.HotPatch; return true; } diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -882,6 +882,8 @@ if (Offset) Fn->addFnAttr("patchable-function-prefix", std::to_string(Offset)); } + if (CGM.getCodeGenOpts().HotPatch) + Fn->addFnAttr("patchable-function", "prologue-short-redirect"); // Add no-jump-tables value. if (CGM.getCodeGenOpts().NoUseJumpTables) diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -5994,6 +5994,7 @@ "-fpatchable-function-entry-offset=" + Twine(Offset))); } } + Args.AddLastArg(CmdArgs, options::OPT_fhotpatch); if (TC.SupportsProfiling()) { Args.AddLastArg(CmdArgs, options::OPT_pg); diff --git a/clang/test/CodeGen/patchable-function-entry.c b/clang/test/CodeGen/patchable-function-entry.c --- a/clang/test/CodeGen/patchable-function-entry.c +++ b/clang/test/CodeGen/patchable-function-entry.c @@ -1,5 +1,6 @@ // RUN: %clang_cc1 -triple aarch64 -emit-llvm %s -o - | FileCheck %s // RUN: %clang_cc1 -triple x86_64 -emit-llvm %s -fpatchable-function-entry=1 -o - | FileCheck --check-prefixes=CHECK,OPT %s +// RUN: %clang_cc1 -triple x86_64 -emit-llvm %s -fhotpatch -o - | FileCheck --check-prefixes=HOTPATCH %s // CHECK: define{{.*}} void @f0() #0 __attribute__((patchable_function_entry(0))) void f0() {} @@ -34,3 +35,7 @@ // CHECK: attributes #2 = { {{.*}} "patchable-function-entry"="0" "patchable-function-prefix"="4" // CHECK: attributes #3 = { {{.*}} "patchable-function-entry"="3" "patchable-function-prefix"="2" // OPT: attributes #4 = { {{.*}} "patchable-function-entry"="1" +// HOTPATCH: attributes #0 = { {{.*}} "patchable-function"="prologue-short-redirect" +// HOTPATCH: attributes #1 = { {{.*}} "patchable-function"="prologue-short-redirect" +// HOTPATCH: attributes #2 = { {{.*}} "patchable-function"="prologue-short-redirect" +// HOTPATCH: attributes #3 = { {{.*}} "patchable-function"="prologue-short-redirect" diff --git a/clang/test/CodeGenCXX/debug-info-hotpatch.cpp b/clang/test/CodeGenCXX/debug-info-hotpatch.cpp new file mode 100644 --- /dev/null +++ b/clang/test/CodeGenCXX/debug-info-hotpatch.cpp @@ -0,0 +1,13 @@ +// REQUIRES: x86-registered-target +// RUN: %clang_cl --target=x86_64-windows-msvc /c /hotpatch /Z7 %s -o %t.obj +// RUN: llvm-pdbutil dump -symbols %t.obj | FileCheck %s +// RUN: %clang_cl --target=x86_64-windows-msvc /c /Z7 %s -o %t.obj +// RUN: llvm-pdbutil dump -symbols %t.obj | FileCheck %s --check-prefix=NOHOTPATCH + +int main() { + return 0; +} + +// CHECK: S_COMPILE3 [size = [[#]]] +// CHECK: flags = hot patchable +// NOHOTPATCH-NOT: flags = hot patchable diff --git a/clang/test/Driver/cl-options.c b/clang/test/Driver/cl-options.c --- a/clang/test/Driver/cl-options.c +++ b/clang/test/Driver/cl-options.c @@ -118,6 +118,9 @@ // RUN: %clang_cl /Gw /Gw- -### -- %s 2>&1 | FileCheck -check-prefix=Gw_ %s // Gw_-NOT: -fdata-sections +// RUN: %clang_cl /hotpatch -### -- %s 2>&1 | FileCheck -check-prefix=hotpatch %s +// hotpatch: -fhotpatch + // RUN: %clang_cl /Imyincludedir -### -- %s 2>&1 | FileCheck -check-prefix=SLASH_I %s // RUN: %clang_cl /I myincludedir -### -- %s 2>&1 | FileCheck -check-prefix=SLASH_I %s // SLASH_I: "-I" "myincludedir" diff --git a/llvm/include/llvm/Target/TargetOptions.h b/llvm/include/llvm/Target/TargetOptions.h --- a/llvm/include/llvm/Target/TargetOptions.h +++ b/llvm/include/llvm/Target/TargetOptions.h @@ -140,9 +140,9 @@ EnableMachineFunctionSplitter(false), SupportsDefaultOutlining(false), EmitAddrsig(false), EmitCallSiteInfo(false), SupportsDebugEntryValues(false), EnableDebugEntryValues(false), - ValueTrackingVariableLocations(false), - ForceDwarfFrameSection(false), XRayOmitFunctionIndex(false), - DebugStrictDwarf(false), + ValueTrackingVariableLocations(false), ForceDwarfFrameSection(false), + XRayOmitFunctionIndex(false), DebugStrictDwarf(false), + Hotpatch(false), FPDenormalMode(DenormalMode::IEEE, DenormalMode::IEEE) {} /// DisableFramePointerElim - This returns true if frame pointer elimination @@ -342,6 +342,9 @@ /// By default, it is set to false. unsigned DebugStrictDwarf : 1; + /// Emit the hotpatch flag in CodeView debug. + unsigned Hotpatch : 1; + /// Name of the stack usage file (i.e., .su file) if user passes /// -fstack-usage. If empty, it can be implied that -fstack-usage is not /// passed on the command line. diff --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp --- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp @@ -843,6 +843,8 @@ if (MMI->getModule()->getProfileSummary(/*IsCS*/ false) != nullptr) { Flags |= static_cast(CompileSym3Flags::PGO); } + if (Asm->TM.Options.Hotpatch) + Flags |= static_cast(CompileSym3Flags::HotPatch); OS.AddComment("Flags and language"); OS.emitInt32(Flags);