Skip to content

Commit 0fc8343

Browse files
committed
[aarch64][x86][win] Add support for MSVC's /funcoverride flag (Windows kernel loader replaceable functions)
1 parent 3bc3b1c commit 0fc8343

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
@@ -497,6 +497,9 @@ class CodeGenOptions : public CodeGenOptionsBase {
497497
/// The name of a file to use with \c .secure_log_unique directives.
498498
std::string AsSecureLogFile;
499499

500+
/// A list of functions that are replacable by the loader.
501+
std::vector<std::string> LoaderReplaceableFunctionNames;
502+
500503
public:
501504
// Define accessors/mutators for code generation options of enumeration type.
502505
#define CODEGENOPT(Name, Bits, Default)
@@ -569,6 +572,12 @@ class CodeGenOptions : public CodeGenOptionsBase {
569572
/// Reset all of the options that are not considered when building a
570573
/// module.
571574
void resetNonModularOptions(StringRef ModuleFormat);
575+
576+
// Is the given function name one of the functions that can be replaced by the
577+
// loader?
578+
bool isLoaderReplaceableFunctionName(StringRef FuncName) const {
579+
return llvm::is_contained(LoaderReplaceableFunctionNames, FuncName);
580+
}
572581
};
573582

574583
} // end namespace clang

clang/include/clang/Driver/Options.td

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

7817+
def replaceable_function: Joined<["-"], "loader-replaceable-function=">,
7818+
MarshallingInfoStringVector<CodeGenOpts<"LoaderReplaceableFunctionNames">>;
7819+
78177820
} // let Visibility = [CC1Option]
78187821

78197822
//===----------------------------------------------------------------------===//
@@ -9069,6 +9072,10 @@ def _SLASH_Gregcall : CLFlag<"Gregcall">,
90699072
def _SLASH_Gregcall4 : CLFlag<"Gregcall4">,
90709073
HelpText<"Set __regcall4 as a default calling convention to respect __regcall ABI v.4">;
90719074

9075+
def _SLASH_funcoverride : CLCompileJoined<"funcoverride:">,
9076+
HelpText<"Mark <function> as being replaceable by the Windows kernel loader">,
9077+
MetaVarName<"<function>">;
9078+
90729079
// GNU Driver aliases
90739080

90749081
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
@@ -2641,6 +2641,10 @@ void CodeGenModule::ConstructAttributeList(StringRef Name,
26412641
GetCPUAndFeaturesAttributes(CalleeInfo.getCalleeDecl(), FuncAttrs);
26422642
}
26432643

2644+
// Mark functions that are replaceable by the loader.
2645+
if (CodeGenOpts.isLoaderReplaceableFunctionName(Name))
2646+
FuncAttrs.addAttribute("loader-replaceable");
2647+
26442648
// Collect attributes from arguments and return values.
26452649
ClangToLLVMArgMapping IRFunctionArgs(getContext(), FI);
26462650

clang/lib/Driver/ToolChains/Clang.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8569,6 +8569,12 @@ void Clang::AddClangCLArgs(const ArgList &Args, types::ID InputType,
85698569
}
85708570
A->claim();
85718571
}
8572+
8573+
for (const auto &FuncOverride :
8574+
Args.getAllArgValues(options::OPT__SLASH_funcoverride)) {
8575+
CmdArgs.push_back(Args.MakeArgString(
8576+
Twine("-loader-replaceable-function=") + FuncOverride));
8577+
}
85728578
}
85738579

85748580
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 -triple=x86_64-pc-windows-msvc -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
@@ -820,4 +820,8 @@
820820
// RUN: %clang_cl -vctoolsdir "" /arm64EC /c -target x86_64-pc-windows-msvc -### -- %s 2>&1 | FileCheck --check-prefix=ARM64EC_OVERRIDE %s
821821
// ARM64EC_OVERRIDE: warning: /arm64EC has been overridden by specified target: x86_64-pc-windows-msvc; option ignored
822822

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

llvm/include/llvm/CodeGen/AsmPrinter.h

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

815+
//===------------------------------------------------------------------===//
816+
// COFF Helper Routines
817+
//===------------------------------------------------------------------===//
818+
819+
/// Emits symbols and data to allow functions marked with the
820+
/// loader-replaceable attribute to be replaceable.
821+
void emitCOFFReplaceableFunctionData(Module &M);
822+
823+
/// Emits the @feat.00 symbol indicating the features enabled in this module.
824+
void emitCOFFFeatureSymbol(Module &M);
825+
815826
//===------------------------------------------------------------------===//
816827
// Inline Asm Support
817828
//===------------------------------------------------------------------===//

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
@@ -3174,6 +3174,10 @@ std::optional<InlineResult> llvm::getAttributeBasedInliningDecision(
31743174
if (Call.isNoInline())
31753175
return InlineResult::failure("noinline call site attribute");
31763176

3177+
// Don't inline functions that are loader replaceable.
3178+
if (Callee->hasFnAttribute("loader-replaceable"))
3179+
return InlineResult::failure("loader replaceable function attribute");
3180+
31773181
return std::nullopt;
31783182
}
31793183

0 commit comments

Comments
 (0)