Skip to content

Commit fe5b7ad

Browse files
committed
[aarch64][x86][win] Add support for MSVC's /funcoverride flag (Windows kernel loader replaceable functions)
1 parent 71478ec commit fe5b7ad

File tree

17 files changed

+270
-63
lines changed

17 files changed

+270
-63
lines changed

clang/include/clang/Basic/CodeGenOptions.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -489,6 +489,9 @@ class CodeGenOptions : public CodeGenOptionsBase {
489489
/// The name of a file to use with \c .secure_log_unique directives.
490490
std::string AsSecureLogFile;
491491

492+
/// A list of functions that are replacable by the loader.
493+
std::vector<std::string> LoaderReplaceableFunctionNames;
494+
492495
public:
493496
// Define accessors/mutators for code generation options of enumeration type.
494497
#define CODEGENOPT(Name, Bits, Default)
@@ -561,6 +564,12 @@ class CodeGenOptions : public CodeGenOptionsBase {
561564
/// Reset all of the options that are not considered when building a
562565
/// module.
563566
void resetNonModularOptions(StringRef ModuleFormat);
567+
568+
// Is the given function name one of the functions that can be replaced by the
569+
// loader?
570+
bool isLoaderReplaceableFunctionName(StringRef FuncName) const {
571+
return llvm::is_contained(LoaderReplaceableFunctionNames, FuncName);
572+
}
564573
};
565574

566575
} // end namespace clang

clang/include/clang/Driver/Options.td

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7613,6 +7613,9 @@ def import_call_optimization : Flag<["-"], "import-call-optimization">,
76137613
"by the Windows kernel to enable import call optimization">,
76147614
MarshallingInfoFlag<CodeGenOpts<"ImportCallOptimization">>;
76157615

7616+
def replaceable_function: Joined<["-"], "loader-replaceable-function=">,
7617+
MarshallingInfoStringVector<CodeGenOpts<"LoaderReplaceableFunctionNames">>;
7618+
76167619
} // let Visibility = [CC1Option]
76177620

76187621
//===----------------------------------------------------------------------===//
@@ -8859,6 +8862,10 @@ def _SLASH_Gregcall : CLFlag<"Gregcall">,
88598862
def _SLASH_Gregcall4 : CLFlag<"Gregcall4">,
88608863
HelpText<"Set __regcall4 as a default calling convention to respect __regcall ABI v.4">;
88618864

8865+
def _SLASH_funcoverride : CLCompileJoined<"funcoverride:">,
8866+
HelpText<"Mark <function> as being replaceable by the Windows kernel loader">,
8867+
MetaVarName<"<function>">;
8868+
88628869
// GNU Driver aliases
88638870

88648871
def : Separate<["-"], "Xmicrosoft-visualc-tools-root">, Alias<_SLASH_vctoolsdir>;

clang/lib/CodeGen/CGCall.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2574,6 +2574,10 @@ void CodeGenModule::ConstructAttributeList(StringRef Name,
25742574
GetCPUAndFeaturesAttributes(CalleeInfo.getCalleeDecl(), FuncAttrs);
25752575
}
25762576

2577+
// Mark functions that are replaceable by the loader.
2578+
if (CodeGenOpts.isLoaderReplaceableFunctionName(Name))
2579+
FuncAttrs.addAttribute("loader-replaceable");
2580+
25772581
// Collect attributes from arguments and return values.
25782582
ClangToLLVMArgMapping IRFunctionArgs(getContext(), FI);
25792583

clang/lib/Driver/ToolChains/Clang.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8553,6 +8553,12 @@ void Clang::AddClangCLArgs(const ArgList &Args, types::ID InputType,
85538553
}
85548554
A->claim();
85558555
}
8556+
8557+
for (const auto &FuncOverride :
8558+
Args.getAllArgValues(options::OPT__SLASH_funcoverride)) {
8559+
CmdArgs.push_back(Args.MakeArgString(
8560+
Twine("-loader-replaceable-function=") + FuncOverride));
8561+
}
85568562
}
85578563

85588564
const char *Clang::getBaseInputName(const ArgList &Args,
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// RUN: %clang_cc1 -loader-replaceable-function=override_me -loader-replaceable-function="?override_me_cpp@@YAXXZ" -emit-llvm -o - %s | FileCheck %s
2+
3+
// CHECK: define dso_local void @override_me() #0
4+
extern "C" void override_me() {}
5+
6+
// CHECK: define dso_local void @"?override_me_cpp@@YAXXZ"() #0
7+
void override_me_cpp() {}
8+
9+
// CHECK: define dso_local void @dont_override_me() #1
10+
extern "C" void dont_override_me() {}
11+
12+
// CHECK: attributes #0 = {
13+
// CHECK-SAME: loader-replaceable
14+
15+
// CHECK: attributes #1 = {
16+
// CHECK-NOT: loader-replaceable
17+
// CHECK-SAME: }

clang/test/Driver/cl-options.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -817,4 +817,8 @@
817817
// RUN: %clang_cl -vctoolsdir "" /arm64EC /c -target x86_64-pc-windows-msvc -### -- %s 2>&1 | FileCheck --check-prefix=ARM64EC_OVERRIDE %s
818818
// ARM64EC_OVERRIDE: warning: /arm64EC has been overridden by specified target: x86_64-pc-windows-msvc; option ignored
819819

820+
// RUN: %clang_cl /funcoverride:override_me1 /funcoverride:override_me2 /c -### -- %s 2>&1 | FileCheck %s --check-prefix=FUNCOVERRIDE
821+
// FUNCOVERRIDE: -loader-replaceable-function=override_me1
822+
// FUNCOVERRIDE-SAME: -loader-replaceable-function=override_me2
823+
820824
void f(void) { }

llvm/include/llvm/CodeGen/AsmPrinter.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -796,6 +796,17 @@ class AsmPrinter : public MachineFunctionPass {
796796
getCodeViewJumpTableInfo(int JTI, const MachineInstr *BranchInstr,
797797
const MCSymbol *BranchLabel) const;
798798

799+
//===------------------------------------------------------------------===//
800+
// COFF Helper Routines
801+
//===------------------------------------------------------------------===//
802+
803+
/// Emits symbols and data to allow functions marked with the
804+
/// loader-replaceable attribute to be replaceable.
805+
void emitCOFFReplaceableFunctionData(Module &M);
806+
807+
/// Emits the @feat.00 symbol indicating the features enabled in this module.
808+
void emitCOFFFeatureSymbol(Module &M);
809+
799810
//===------------------------------------------------------------------===//
800811
// Inline Asm Support
801812
//===------------------------------------------------------------------===//

llvm/include/llvm/IR/Attributes.td

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,7 @@ def NoJumpTables : StrBoolAttr<"no-jump-tables">;
400400
def NoInlineLineTables : StrBoolAttr<"no-inline-line-tables">;
401401
def ProfileSampleAccurate : StrBoolAttr<"profile-sample-accurate">;
402402
def UseSampleProfile : StrBoolAttr<"use-sample-profile">;
403+
def LoaderReplaceable : StrBoolAttr<"loader-replaceable">;
403404

404405
def DenormalFPMath : ComplexStrAttr<"denormal-fp-math", [FnAttr]>;
405406
def DenormalFPMathF32 : ComplexStrAttr<"denormal-fp-math-f32", [FnAttr]>;

llvm/include/llvm/IR/Mangler.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ class Triple;
2525
class Twine;
2626
class raw_ostream;
2727

28+
constexpr std::string_view HybridPatchableTargetSuffix = "$hp_target";
29+
2830
class Mangler {
2931
/// We need to give global values the same name every time they are mangled.
3032
/// This keeps track of the number we give to anonymous ones.

llvm/lib/Analysis/InlineCost.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3078,6 +3078,10 @@ std::optional<InlineResult> llvm::getAttributeBasedInliningDecision(
30783078
if (Call.isNoInline())
30793079
return InlineResult::failure("noinline call site attribute");
30803080

3081+
// Don't inline functions that are loader replaceable.
3082+
if (Callee->hasFnAttribute("loader-replaceable"))
3083+
return InlineResult::failure("loader replaceable function attribute");
3084+
30813085
return std::nullopt;
30823086
}
30833087

0 commit comments

Comments
 (0)