Skip to content

Commit f429ad4

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

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

502+
/// A list of functions that are replacable by the loader.
503+
std::vector<std::string> LoaderReplaceableFunctionNames;
504+
502505
public:
503506
// Define accessors/mutators for code generation options of enumeration type.
504507
#define CODEGENOPT(Name, Bits, Default)
@@ -571,6 +574,12 @@ class CodeGenOptions : public CodeGenOptionsBase {
571574
/// Reset all of the options that are not considered when building a
572575
/// module.
573576
void resetNonModularOptions(StringRef ModuleFormat);
577+
578+
// Is the given function name one of the functions that can be replaced by the
579+
// loader?
580+
bool isLoaderReplaceableFunctionName(StringRef FuncName) const {
581+
return llvm::is_contained(LoaderReplaceableFunctionNames, FuncName);
582+
}
574583
};
575584

576585
} // end namespace clang

clang/include/clang/Driver/Options.td

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

7829+
def replaceable_function: Joined<["-"], "loader-replaceable-function=">,
7830+
MarshallingInfoStringVector<CodeGenOpts<"LoaderReplaceableFunctionNames">>;
7831+
78297832
} // let Visibility = [CC1Option]
78307833

78317834
//===----------------------------------------------------------------------===//
@@ -9088,6 +9091,10 @@ def _SLASH_Gregcall : CLFlag<"Gregcall">,
90889091
def _SLASH_Gregcall4 : CLFlag<"Gregcall4">,
90899092
HelpText<"Set __regcall4 as a default calling convention to respect __regcall ABI v.4">;
90909093

9094+
def _SLASH_funcoverride : CLCompileJoined<"funcoverride:">,
9095+
HelpText<"Mark <function> as being replaceable by the Windows kernel loader">,
9096+
MetaVarName<"<function>">;
9097+
90919098
// GNU Driver aliases
90929099

90939100
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
@@ -8578,6 +8578,12 @@ void Clang::AddClangCLArgs(const ArgList &Args, types::ID InputType,
85788578
}
85798579
A->claim();
85808580
}
8581+
8582+
for (const auto &FuncOverride :
8583+
Args.getAllArgValues(options::OPT__SLASH_funcoverride)) {
8584+
CmdArgs.push_back(Args.MakeArgString(
8585+
Twine("-loader-replaceable-function=") + FuncOverride));
8586+
}
85818587
}
85828588

85838589
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
@@ -823,4 +823,8 @@
823823
// RUN: %clang_cl /d2epilogunwind /c -### -- %s 2>&1 | FileCheck %s --check-prefix=EPILOGUNWIND
824824
// EPILOGUNWIND: -fwinx64-eh-unwindv2
825825

826+
// RUN: %clang_cl /funcoverride:override_me1 /funcoverride:override_me2 /c -### -- %s 2>&1 | FileCheck %s --check-prefix=FUNCOVERRIDE
827+
// FUNCOVERRIDE: -loader-replaceable-function=override_me1
828+
// FUNCOVERRIDE-SAME: -loader-replaceable-function=override_me2
829+
826830
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)