Skip to content

Commit 0fafcba

Browse files
Merge branch 'main' into groupprivate
2 parents d4bbb2a + 6bbf734 commit 0fafcba

File tree

12 files changed

+212
-16
lines changed

12 files changed

+212
-16
lines changed

clang/lib/CodeGen/CodeGenModule.cpp

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4610,12 +4610,6 @@ void CodeGenModule::emitMultiVersionFunctions() {
46104610
}
46114611
llvm::Function *ResolverFunc = cast<llvm::Function>(ResolverConstant);
46124612

4613-
ResolverFunc->setLinkage(getMultiversionLinkage(*this, GD));
4614-
4615-
if (!ResolverFunc->hasLocalLinkage() && supportsCOMDAT())
4616-
ResolverFunc->setComdat(
4617-
getModule().getOrInsertComdat(ResolverFunc->getName()));
4618-
46194613
const TargetInfo &TI = getTarget();
46204614
llvm::stable_sort(
46214615
Options, [&TI](const CodeGenFunction::FMVResolverOption &LHS,
@@ -4624,6 +4618,11 @@ void CodeGenModule::emitMultiVersionFunctions() {
46244618
});
46254619
CodeGenFunction CGF(*this);
46264620
CGF.EmitMultiVersionResolver(ResolverFunc, Options);
4621+
4622+
setMultiVersionResolverAttributes(ResolverFunc, GD);
4623+
if (!ResolverFunc->hasLocalLinkage() && supportsCOMDAT())
4624+
ResolverFunc->setComdat(
4625+
getModule().getOrInsertComdat(ResolverFunc->getName()));
46274626
}
46284627

46294628
// Ensure that any additions to the deferred decls list caused by emitting a
@@ -4674,7 +4673,7 @@ void CodeGenModule::emitCPUDispatchDefinition(GlobalDecl GD) {
46744673

46754674
auto *ResolverFunc = cast<llvm::Function>(GetOrCreateLLVMFunction(
46764675
ResolverName, ResolverType, ResolverGD, /*ForVTable=*/false));
4677-
ResolverFunc->setLinkage(getMultiversionLinkage(*this, GD));
4676+
46784677
if (supportsCOMDAT())
46794678
ResolverFunc->setComdat(
46804679
getModule().getOrInsertComdat(ResolverFunc->getName()));
@@ -4740,6 +4739,7 @@ void CodeGenModule::emitCPUDispatchDefinition(GlobalDecl GD) {
47404739

47414740
CodeGenFunction CGF(*this);
47424741
CGF.EmitMultiVersionResolver(ResolverFunc, Options);
4742+
setMultiVersionResolverAttributes(ResolverFunc, GD);
47434743

47444744
if (getTarget().supportsIFunc()) {
47454745
llvm::GlobalValue::LinkageTypes Linkage = getMultiversionLinkage(*this, GD);
@@ -4858,6 +4858,26 @@ llvm::Constant *CodeGenModule::GetOrCreateMultiVersionResolver(GlobalDecl GD) {
48584858
return Resolver;
48594859
}
48604860

4861+
void CodeGenModule::setMultiVersionResolverAttributes(llvm::Function *Resolver,
4862+
GlobalDecl GD) {
4863+
const NamedDecl *D = dyn_cast_or_null<NamedDecl>(GD.getDecl());
4864+
Resolver->setLinkage(getMultiversionLinkage(*this, GD));
4865+
4866+
// Function body has to be emitted before calling setGlobalVisibility
4867+
// for Resolver to be considered as definition.
4868+
setGlobalVisibility(Resolver, D);
4869+
4870+
setDSOLocal(Resolver);
4871+
4872+
// Set the default target-specific attributes, such as PAC and BTI ones on
4873+
// AArch64. Not passing Decl to prevent setting unrelated attributes,
4874+
// as Resolver can be shared by multiple declarations.
4875+
// FIXME Some targets may require a non-null D to set some attributes
4876+
// (such as "stackrealign" on X86, even when it is requested via
4877+
// "-mstackrealign" command line option).
4878+
getTargetCodeGenInfo().setTargetAttributes(/*D=*/nullptr, Resolver, *this);
4879+
}
4880+
48614881
bool CodeGenModule::shouldDropDLLAttribute(const Decl *D,
48624882
const llvm::GlobalValue *GV) const {
48634883
auto SC = GV->getDLLStorageClass();

clang/lib/CodeGen/CodeGenModule.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1851,6 +1851,15 @@ class CodeGenModule : public CodeGenTypeCache {
18511851
// that feature and for a regular function (llvm::GlobalValue) otherwise.
18521852
llvm::Constant *GetOrCreateMultiVersionResolver(GlobalDecl GD);
18531853

1854+
// Set attributes to a resolver function generated by Clang.
1855+
// GD is either the cpu_dispatch declaration or an arbitrarily chosen
1856+
// function declaration that triggered the implicit generation of this
1857+
// resolver function.
1858+
//
1859+
/// NOTE: This should only be called for definitions.
1860+
void setMultiVersionResolverAttributes(llvm::Function *Resolver,
1861+
GlobalDecl GD);
1862+
18541863
// In scenarios where a function is not known to be a multiversion function
18551864
// until a later declaration, it is sometimes necessary to change the
18561865
// previously created mangled name to align with requirements of whatever
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// RUN: %clang_cc1 -triple aarch64-linux-gnu -mbranch-target-enforce -msign-return-address=all -emit-llvm %s -o - | FileCheck --check-prefixes=CHECK,BTI-SIGNRA %s
2+
// RUN: %clang_cc1 -triple arm64-apple-ios -mbranch-target-enforce -msign-return-address=all -emit-llvm %s -o - | FileCheck --check-prefixes=CHECK,BTI-SIGNRA %s
3+
// RUN: %clang_cc1 -triple aarch64-linux-gnu -fptrauth-calls -fptrauth-returns -fptrauth-auth-traps -emit-llvm %s -o - | FileCheck --check-prefixes=CHECK,PAUTHTEST %s
4+
// RUN: %clang_cc1 -triple arm64-apple-ios -fptrauth-calls -fptrauth-returns -fptrauth-auth-traps -emit-llvm %s -o - | FileCheck --check-prefixes=CHECK,PAUTHTEST %s
5+
6+
// Check that both multi-versioned functions themselves and corresponding
7+
// resolvers generated by Clang have the correct PAC/BTI attributes.
8+
9+
int __attribute__((target_clones("crc", "default"))) global_target_clones(void) { return 0; }
10+
11+
int __attribute__((target_version("crc"))) global_target_version(void) { return 0; }
12+
int __attribute__((target_version("default"))) global_target_version(void) { return 0; }
13+
14+
static int __attribute__((target_clones("crc", "default"))) static_target_clones(void) { return 0; }
15+
16+
static int __attribute__((target_version("crc"))) static_target_version(void) { return 0; }
17+
static int __attribute__((target_version("default"))) static_target_version(void) { return 0; }
18+
19+
// Force emission of static_* functions.
20+
void *get_ptr1(void) { return static_target_clones; }
21+
void *get_ptr2(void) { return static_target_version; }
22+
23+
// CHECK-DAG: define{{( dso_local)?}} i32 @global_target_clones._Mcrc() #[[ATTR_CRC:[0-9]+]]
24+
// CHECK-DAG: define{{( dso_local)?}} i32 @global_target_clones.default() #[[ATTR_DEFAULT:[0-9]+]]
25+
// CHECK-DAG: define weak_odr ptr @global_target_clones.resolver() #[[ATTR_RESOLVER:[0-9]+]]
26+
// CHECK-DAG: define{{( dso_local)?}} i32 @global_target_version._Mcrc() #[[ATTR_CRC]]
27+
// CHECK-DAG: define{{( dso_local)?}} i32 @global_target_version.default() #[[ATTR_DEFAULT]]
28+
// CHECK-DAG: define weak_odr ptr @global_target_version.resolver() #[[ATTR_RESOLVER]]
29+
30+
// CHECK-DAG: define internal i32 @static_target_clones._Mcrc() #[[ATTR_CRC:[0-9]+]]
31+
// CHECK-DAG: define internal i32 @static_target_clones.default() #[[ATTR_DEFAULT:[0-9]+]]
32+
// CHECK-DAG: define internal ptr @static_target_clones.resolver() #[[ATTR_RESOLVER:[0-9]+]]
33+
// CHECK-DAG: define internal i32 @static_target_version._Mcrc() #[[ATTR_CRC]]
34+
// CHECK-DAG: define internal i32 @static_target_version.default() #[[ATTR_DEFAULT]]
35+
// CHECK-DAG: define internal ptr @static_target_version.resolver() #[[ATTR_RESOLVER]]
36+
37+
// BTI-SIGNRA-DAG: attributes #[[ATTR_CRC]] = { {{.*}}"branch-target-enforcement" {{.*}}"sign-return-address"="all" "sign-return-address-key"="a_key"{{.*}} }
38+
// BTI-SIGNRA-DAG: attributes #[[ATTR_RESOLVER]] = { {{.*}}"branch-target-enforcement" {{.*}}"sign-return-address"="all" "sign-return-address-key"="a_key"{{.*}} }
39+
// BTI-SIGNRA-DAG: attributes #[[ATTR_DEFAULT]] = { {{.*}}"branch-target-enforcement" {{.*}}"sign-return-address"="all" "sign-return-address-key"="a_key"{{.*}} }
40+
// PAUTHTEST-DAG: attributes #[[ATTR_CRC]] = { {{.*}}"ptrauth-auth-traps" "ptrauth-calls" "ptrauth-returns"{{.*}} }
41+
// PAUTHTEST-DAG: attributes #[[ATTR_RESOLVER]] = { {{.*}}"ptrauth-auth-traps" "ptrauth-calls" "ptrauth-returns"{{.*}} }
42+
// PAUTHTEST-DAG: attributes #[[ATTR_DEFAULT]] = { {{.*}}"ptrauth-auth-traps" "ptrauth-calls" "ptrauth-returns"{{.*}} }
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
// RUN: %clang_cc1 -triple aarch64-linux-gnu -mbranch-target-enforce -emit-llvm %s -o - | FileCheck --check-prefixes=BTI,ELF %s
2+
// RUN: %clang_cc1 -triple arm64-apple-ios -mbranch-target-enforce -emit-llvm %s -o - | FileCheck --check-prefixes=BTI %s
3+
// RUN: %clang_cc1 -triple aarch64-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefixes=NOBTI,ELF %s
4+
// RUN: %clang_cc1 -triple arm64-apple-ios -emit-llvm %s -o - | FileCheck --check-prefixes=NOBTI %s
5+
// RUN: %clang_cc1 -triple aarch64-linux-gnu -fvisibility=hidden -emit-llvm %s -o - | FileCheck --check-prefixes=HIDDEN,ELF %s
6+
// RUN: %clang_cc1 -triple arm64-apple-ios -fvisibility=hidden -emit-llvm %s -o - | FileCheck --check-prefixes=HIDDEN %s
7+
8+
// Check that the resolver functions generated by Clang have the correct attributes.
9+
// In these test cases, branch-target-enforcement is used as an example of
10+
// target-specific attribute that has to be set on every function by default.
11+
12+
// FIXME: `cpu_specific`/`cpu_dispatch` and `target` attributes cannot be
13+
// tested on AArch64.
14+
15+
__attribute__((target_clones("crc", "default")))
16+
int global_target_clones(void) { return 0; }
17+
18+
__attribute__((target_version("crc"))) int global_target_version(void) { return 0; }
19+
__attribute__((target_version("default"))) int global_target_version(void) { return 0; }
20+
21+
__attribute__((target_clones("crc", "default")))
22+
static int static_target_clones(void) { return 0; }
23+
24+
__attribute__((target_version("crc"))) static int static_target_version(void) { return 0; }
25+
__attribute__((target_version("default"))) static int static_target_version(void) { return 0; }
26+
27+
// Force emission of static_* functions.
28+
void *get_ptr1(void) { return static_target_clones; }
29+
void *get_ptr2(void) { return static_target_version; }
30+
31+
#ifdef __ELF__
32+
// Make sure target-specific attributes can be overriden as needed for
33+
// non-autogenerated resolver functions.
34+
// Note that since there is only a single definition of ifunc_resolver, it
35+
// is not itself a multi-versioned function, even though it has target(...)
36+
// attribute.
37+
int ifunc_func(void) { return 0; }
38+
__attribute__((target("branch-protection=bti"))) void *ifunc_resolver(void) { return ifunc_func; }
39+
__attribute__((ifunc("ifunc_resolver"))) int ifunc(void);
40+
#endif
41+
42+
// ELF: define{{.*}} ptr @ifunc_resolver() #[[ATTR_IFUNC_RESOLVER:[0-9]+]]
43+
44+
// BTI: define weak_odr ptr @global_target_clones.resolver() #[[ATTR_RESOLVER:[0-9]+]]
45+
// BTI: define weak_odr ptr @global_target_version.resolver() #[[ATTR_RESOLVER]]
46+
// BTI: define internal ptr @static_target_clones.resolver() #[[ATTR_RESOLVER]]
47+
// BTI: define internal ptr @static_target_version.resolver() #[[ATTR_RESOLVER]]
48+
49+
// In NOBTI case, no attribute groups are assigned to the resolver functions:
50+
// NOBTI: define weak_odr ptr @global_target_clones.resolver(){{( comdat)?}} {
51+
// NOBTI: define weak_odr ptr @global_target_version.resolver(){{( comdat)?}} {
52+
// NOBTI: define internal ptr @static_target_clones.resolver() {
53+
// NOBTI: define internal ptr @static_target_version.resolver() {
54+
55+
// HIDDEN: define weak_odr hidden ptr @global_target_clones.resolver(){{( comdat)?}} {
56+
// HIDDEN: define weak_odr hidden ptr @global_target_version.resolver(){{( comdat)?}} {
57+
// HIDDEN: define internal ptr @static_target_clones.resolver() {
58+
// HIDDEN: define internal ptr @static_target_version.resolver() {
59+
60+
// ELF: attributes #[[ATTR_IFUNC_RESOLVER]] = { {{.*}}"branch-target-enforcement"{{.*}} }
61+
62+
// BTI: attributes #[[ATTR_RESOLVER]] = { {{.*}}"branch-target-enforcement"{{.*}} }

flang/include/flang/Optimizer/Passes/Pipelines.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ void addCompilerGeneratedNamesConversionPass(mlir::PassManager &pm);
102102
void addDebugInfoPass(mlir::PassManager &pm,
103103
llvm::codegenoptions::DebugInfoKind debugLevel,
104104
llvm::OptimizationLevel optLevel,
105-
llvm::StringRef inputFilename);
105+
llvm::StringRef inputFilename, int32_t dwarfVersion);
106106

107107
void addFIRToLLVMPass(mlir::PassManager &pm,
108108
const MLIRToLLVMPassPipelineConfig &config);
@@ -158,7 +158,7 @@ void createOpenMPFIRPassPipeline(mlir::PassManager &pm,
158158
void createDebugPasses(mlir::PassManager &pm,
159159
llvm::codegenoptions::DebugInfoKind debugLevel,
160160
llvm::OptimizationLevel OptLevel,
161-
llvm::StringRef inputFilename);
161+
llvm::StringRef inputFilename, int32_t dwarfVersion);
162162

163163
void createDefaultFIRCodeGenPassPipeline(mlir::PassManager &pm,
164164
MLIRToLLVMPassPipelineConfig config,

flang/include/flang/Optimizer/Transforms/Passes.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,10 @@ def AddDebugInfo : Pass<"add-debug-info", "mlir::ModuleOp"> {
242242
"std::string",
243243
/*default=*/"std::string{}",
244244
"name of the input source file">,
245+
Option<"dwarfVersion", "dwarf-version",
246+
"int32_t",
247+
/*default=*/"0",
248+
"dwarf version">,
245249
];
246250
}
247251

flang/include/flang/Tools/CrossToolHelpers.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ struct MLIRToLLVMPassPipelineConfig : public FlangEPCallBacks {
108108
InstrumentFunctionEntry = "__cyg_profile_func_enter";
109109
InstrumentFunctionExit = "__cyg_profile_func_exit";
110110
}
111+
DwarfVersion = opts.DwarfVersion;
111112
}
112113

113114
llvm::OptimizationLevel OptLevel; ///< optimisation level
@@ -143,6 +144,7 @@ struct MLIRToLLVMPassPipelineConfig : public FlangEPCallBacks {
143144
Fortran::frontend::CodeGenOptions::ComplexRangeKind ComplexRange =
144145
Fortran::frontend::CodeGenOptions::ComplexRangeKind::
145146
CX_Full; ///< Method for calculating complex number division
147+
int32_t DwarfVersion = 0; ///< Version of DWARF debug info to generate
146148
};
147149

148150
struct OffloadModuleOpts {

flang/lib/Frontend/CompilerInvocation.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -157,10 +157,9 @@ static bool parseDebugArgs(Fortran::frontend::CodeGenOptions &opts,
157157
clang::DiagnosticsEngine::Warning, "Unsupported debug option: %0");
158158
diags.Report(debugWarning) << arg->getValue();
159159
}
160-
// The default value of 2 here is to match clang.
161160
opts.DwarfVersion =
162161
getLastArgIntValue(args, clang::driver::options::OPT_dwarf_version_EQ,
163-
/*Default=*/2, diags);
162+
/*Default=*/0, diags);
164163
}
165164
return true;
166165
}

flang/lib/Optimizer/Passes/Pipelines.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -95,11 +95,12 @@ getEmissionKind(llvm::codegenoptions::DebugInfoKind kind) {
9595
void addDebugInfoPass(mlir::PassManager &pm,
9696
llvm::codegenoptions::DebugInfoKind debugLevel,
9797
llvm::OptimizationLevel optLevel,
98-
llvm::StringRef inputFilename) {
98+
llvm::StringRef inputFilename, int32_t dwarfVersion) {
9999
fir::AddDebugInfoOptions options;
100100
options.debugLevel = getEmissionKind(debugLevel);
101101
options.isOptimized = optLevel != llvm::OptimizationLevel::O0;
102102
options.inputFilename = inputFilename;
103+
options.dwarfVersion = dwarfVersion;
103104
addPassConditionally(pm, disableDebugInfo,
104105
[&]() { return fir::createAddDebugInfoPass(options); });
105106
}
@@ -333,9 +334,9 @@ void createOpenMPFIRPassPipeline(mlir::PassManager &pm,
333334
void createDebugPasses(mlir::PassManager &pm,
334335
llvm::codegenoptions::DebugInfoKind debugLevel,
335336
llvm::OptimizationLevel OptLevel,
336-
llvm::StringRef inputFilename) {
337+
llvm::StringRef inputFilename, int32_t dwarfVersion) {
337338
if (debugLevel != llvm::codegenoptions::NoDebugInfo)
338-
addDebugInfoPass(pm, debugLevel, OptLevel, inputFilename);
339+
addDebugInfoPass(pm, debugLevel, OptLevel, inputFilename, dwarfVersion);
339340
}
340341

341342
void createDefaultFIRCodeGenPassPipeline(mlir::PassManager &pm,
@@ -352,7 +353,8 @@ void createDefaultFIRCodeGenPassPipeline(mlir::PassManager &pm,
352353
fir::addCodeGenRewritePass(
353354
pm, (config.DebugInfo != llvm::codegenoptions::NoDebugInfo));
354355
fir::addExternalNameConversionPass(pm, config.Underscoring);
355-
fir::createDebugPasses(pm, config.DebugInfo, config.OptLevel, inputFilename);
356+
fir::createDebugPasses(pm, config.DebugInfo, config.OptLevel, inputFilename,
357+
config.DwarfVersion);
356358
fir::addTargetRewritePass(pm);
357359
fir::addCompilerGeneratedNamesConversionPass(pm);
358360

flang/lib/Optimizer/Transforms/AddDebugInfo.cpp

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -649,6 +649,19 @@ void AddDebugInfoPass::runOnOperation() {
649649
signalPassFailure();
650650
return;
651651
}
652+
mlir::OpBuilder builder(context);
653+
if (dwarfVersion > 0) {
654+
mlir::OpBuilder::InsertionGuard guard(builder);
655+
builder.setInsertionPointToEnd(module.getBody());
656+
llvm::SmallVector<mlir::Attribute> moduleFlags;
657+
mlir::IntegerType int32Ty = mlir::IntegerType::get(context, 32);
658+
moduleFlags.push_back(builder.getAttr<mlir::LLVM::ModuleFlagAttr>(
659+
mlir::LLVM::ModFlagBehavior::Max,
660+
mlir::StringAttr::get(context, "Dwarf Version"),
661+
mlir::IntegerAttr::get(int32Ty, dwarfVersion)));
662+
mlir::LLVM::ModuleFlagsOp::create(builder, module.getLoc(),
663+
builder.getArrayAttr(moduleFlags));
664+
}
652665
fir::DebugTypeGenerator typeGen(module, &symbolTable, *dl);
653666
// We need 2 type of file paths here.
654667
// 1. Name of the file as was presented to compiler. This can be absolute
@@ -686,7 +699,6 @@ void AddDebugInfoPass::runOnOperation() {
686699
module.walk([&](mlir::func::FuncOp funcOp) {
687700
handleFuncOp(funcOp, fileAttr, cuAttr, typeGen, &symbolTable);
688701
});
689-
mlir::OpBuilder builder(context);
690702
// We have processed all function. Attach common block variables to the
691703
// global that represent the storage.
692704
for (auto [global, exprs] : globalToGlobalExprsMap) {

0 commit comments

Comments
 (0)