Skip to content

Commit 1156c06

Browse files
authored
[CIR][CIRGen] Match skeleton for setCIRFunctionAttributesForDefinition (#1232)
Match `CodeGenModule::SetLLVMFunctionAttributesForDefinition` so that we can see what's missing and have a good base to build upon.
1 parent 8b74dc0 commit 1156c06

File tree

2 files changed

+135
-44
lines changed

2 files changed

+135
-44
lines changed

clang/include/clang/CIR/MissingFeatures.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -371,6 +371,13 @@ struct MissingFeatures {
371371
static bool setVisibilityFromDLLStorageClass() { return false; }
372372
static bool mustTailCallUndefinedGlobals() { return false; }
373373

374+
//-- Missing parts of the setCIRFunctionAttributesForDefinition skeleton.
375+
static bool stackProtector() { return false; }
376+
static bool optimizeForSize() { return false; }
377+
static bool minSize() { return false; }
378+
static bool setFunctionAlignment() { return false; }
379+
static bool memberFunctionPointerTypeMetadata() { return false; }
380+
374381
//-- Other missing features
375382

376383
// We need to track the parent record types that represent a field

clang/lib/CIR/CodeGen/CIRGenModule.cpp

Lines changed: 128 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -2506,84 +2506,168 @@ void CIRGenModule::setCIRFunctionAttributesForDefinition(const Decl *decl,
25062506
attrs.set(attr.getMnemonic(), attr);
25072507
}
25082508

2509+
if (codeGenOpts.StackClashProtector)
2510+
llvm_unreachable("NYI");
2511+
2512+
if (codeGenOpts.StackProbeSize && codeGenOpts.StackProbeSize != 4096)
2513+
llvm_unreachable("NYI");
2514+
25092515
if (!hasUnwindExceptions(getLangOpts())) {
25102516
auto attr = cir::NoThrowAttr::get(&getMLIRContext());
25112517
attrs.set(attr.getMnemonic(), attr);
25122518
}
25132519

2520+
assert(!MissingFeatures::stackProtector());
2521+
2522+
auto existingInlineAttr = dyn_cast_if_present<cir::InlineAttr>(
2523+
attrs.get(cir::InlineAttr::getMnemonic()));
2524+
bool isNoInline = existingInlineAttr && existingInlineAttr.isNoInline();
2525+
bool isAlwaysInline =
2526+
existingInlineAttr && existingInlineAttr.isAlwaysInline();
2527+
25142528
if (!decl) {
2515-
// If we don't have a declaration to control inlining, the function isn't
2516-
// explicitly marked as alwaysinline for semantic reasons, and inlining is
2517-
// disabled, mark the function as noinline.
2518-
if (codeGenOpts.getInlining() == CodeGenOptions::OnlyAlwaysInlining) {
2529+
// Non-entry HLSL functions must always be inlined.
2530+
if (getLangOpts().HLSL && !isNoInline) {
25192531
auto attr = cir::InlineAttr::get(&getMLIRContext(),
25202532
cir::InlineKind::AlwaysInline);
25212533
attrs.set(attr.getMnemonic(), attr);
2534+
} else if (!isAlwaysInline && codeGenOpts.getInlining() ==
2535+
CodeGenOptions::OnlyAlwaysInlining) {
2536+
// If we don't have a declaration to control inlining, the function isn't
2537+
// explicitly marked as alwaysinline for semantic reasons, and inlining is
2538+
// disabled, mark the function as noinline.
2539+
auto attr =
2540+
cir::InlineAttr::get(&getMLIRContext(), cir::InlineKind::NoInline);
2541+
attrs.set(attr.getMnemonic(), attr);
25222542
}
2523-
} else if (decl->hasAttr<NoInlineAttr>()) {
2543+
2544+
f.setExtraAttrsAttr(cir::ExtraFuncAttributesAttr::get(
2545+
&getMLIRContext(), attrs.getDictionary(&getMLIRContext())));
2546+
return;
2547+
}
2548+
2549+
// Handle SME attributes that apply to function definitions,
2550+
// rather than to function prototypes.
2551+
if (decl->hasAttr<ArmLocallyStreamingAttr>())
2552+
llvm_unreachable("NYI");
2553+
2554+
if (auto *attr = decl->getAttr<ArmNewAttr>()) {
2555+
if (attr->isNewZA())
2556+
llvm_unreachable("NYI");
2557+
if (attr->isNewZT0())
2558+
llvm_unreachable("NYI");
2559+
}
2560+
2561+
// Track whether we need to add the optnone attribute,
2562+
// starting with the default for this optimization level.
2563+
bool shouldAddOptNone =
2564+
!codeGenOpts.DisableO0ImplyOptNone && codeGenOpts.OptimizationLevel == 0;
2565+
// We can't add optnone in the following cases, it won't pass the verifier.
2566+
shouldAddOptNone &= !decl->hasAttr<MinSizeAttr>();
2567+
shouldAddOptNone &= !decl->hasAttr<AlwaysInlineAttr>();
2568+
2569+
// Non-entry HLSL functions must always be inlined.
2570+
if (getLangOpts().HLSL && !isNoInline && !decl->hasAttr<NoInlineAttr>()) {
2571+
auto attr =
2572+
cir::InlineAttr::get(&getMLIRContext(), cir::InlineKind::AlwaysInline);
2573+
attrs.set(attr.getMnemonic(), attr);
2574+
} else if ((shouldAddOptNone || decl->hasAttr<OptimizeNoneAttr>()) &&
2575+
!isAlwaysInline) {
2576+
// Add optnone, but do so only if the function isn't always_inline.
2577+
auto optNoneAttr = cir::OptNoneAttr::get(&getMLIRContext());
2578+
attrs.set(optNoneAttr.getMnemonic(), optNoneAttr);
2579+
2580+
// OptimizeNone implies noinline; we should not be inlining such functions.
2581+
auto noInlineAttr =
2582+
cir::InlineAttr::get(&getMLIRContext(), cir::InlineKind::NoInline);
2583+
attrs.set(noInlineAttr.getMnemonic(), noInlineAttr);
2584+
2585+
// We still need to handle naked functions even though optnone subsumes
2586+
// much of their semantics.
2587+
if (decl->hasAttr<NakedAttr>())
2588+
llvm_unreachable("NYI");
2589+
2590+
// OptimizeNone wins over OptimizeForSize and MinSize.
2591+
assert(!MissingFeatures::optimizeForSize());
2592+
assert(!MissingFeatures::minSize());
2593+
} else if (decl->hasAttr<NakedAttr>()) {
2594+
// Naked implies noinline: we should not be inlining such functions.
2595+
llvm_unreachable("NYI");
2596+
} else if (decl->hasAttr<NoDuplicateAttr>()) {
2597+
llvm_unreachable("NYI");
2598+
} else if (decl->hasAttr<NoInlineAttr>() && !isAlwaysInline) {
25242599
// Add noinline if the function isn't always_inline.
25252600
auto attr =
25262601
cir::InlineAttr::get(&getMLIRContext(), cir::InlineKind::NoInline);
25272602
attrs.set(attr.getMnemonic(), attr);
2528-
} else if (decl->hasAttr<AlwaysInlineAttr>()) {
2603+
} else if (decl->hasAttr<AlwaysInlineAttr>() && !isNoInline) {
25292604
// (noinline wins over always_inline, and we can't specify both in IR)
25302605
auto attr =
25312606
cir::InlineAttr::get(&getMLIRContext(), cir::InlineKind::AlwaysInline);
25322607
attrs.set(attr.getMnemonic(), attr);
25332608
} else if (codeGenOpts.getInlining() == CodeGenOptions::OnlyAlwaysInlining) {
25342609
// If we're not inlining, then force everything that isn't always_inline
25352610
// to carry an explicit noinline attribute.
2536-
auto attr =
2537-
cir::InlineAttr::get(&getMLIRContext(), cir::InlineKind::NoInline);
2538-
attrs.set(attr.getMnemonic(), attr);
2611+
if (!isAlwaysInline) {
2612+
auto attr =
2613+
cir::InlineAttr::get(&getMLIRContext(), cir::InlineKind::NoInline);
2614+
attrs.set(attr.getMnemonic(), attr);
2615+
}
25392616
} else {
25402617
// Otherwise, propagate the inline hint attribute and potentially use its
25412618
// absence to mark things as noinline.
25422619
// Search function and template pattern redeclarations for inline.
2543-
auto CheckForInline = [](const FunctionDecl *decl) {
2544-
auto CheckRedeclForInline = [](const FunctionDecl *Redecl) {
2545-
return Redecl->isInlineSpecified();
2620+
if (auto *fd = dyn_cast<FunctionDecl>(decl)) {
2621+
auto checkForInline = [](const FunctionDecl *decl) {
2622+
auto checkRedeclForInline = [](const FunctionDecl *redecl) {
2623+
return redecl->isInlineSpecified();
2624+
};
2625+
if (any_of(decl->redecls(), checkRedeclForInline))
2626+
return true;
2627+
const FunctionDecl *pattern = decl->getTemplateInstantiationPattern();
2628+
if (!pattern)
2629+
return false;
2630+
return any_of(pattern->redecls(), checkRedeclForInline);
25462631
};
2547-
if (any_of(decl->redecls(), CheckRedeclForInline))
2548-
return true;
2549-
const FunctionDecl *Pattern = decl->getTemplateInstantiationPattern();
2550-
if (!Pattern)
2551-
return false;
2552-
return any_of(Pattern->redecls(), CheckRedeclForInline);
2553-
};
2554-
if (CheckForInline(cast<FunctionDecl>(decl))) {
2555-
auto attr =
2556-
cir::InlineAttr::get(&getMLIRContext(), cir::InlineKind::InlineHint);
2557-
attrs.set(attr.getMnemonic(), attr);
2558-
} else if (codeGenOpts.getInlining() == CodeGenOptions::OnlyHintInlining) {
2559-
auto attr =
2560-
cir::InlineAttr::get(&getMLIRContext(), cir::InlineKind::NoInline);
2561-
attrs.set(attr.getMnemonic(), attr);
2632+
if (checkForInline(fd)) {
2633+
auto attr = cir::InlineAttr::get(&getMLIRContext(),
2634+
cir::InlineKind::InlineHint);
2635+
attrs.set(attr.getMnemonic(), attr);
2636+
} else if (codeGenOpts.getInlining() ==
2637+
CodeGenOptions::OnlyHintInlining &&
2638+
!fd->isInlined() && !isAlwaysInline) {
2639+
auto attr =
2640+
cir::InlineAttr::get(&getMLIRContext(), cir::InlineKind::NoInline);
2641+
attrs.set(attr.getMnemonic(), attr);
2642+
}
25622643
}
25632644
}
25642645

2565-
// Track whether we need to add the optnone attribute,
2566-
// starting with the default for this optimization level.
2567-
bool ShouldAddOptNone =
2568-
!codeGenOpts.DisableO0ImplyOptNone && codeGenOpts.OptimizationLevel == 0;
2569-
if (decl) {
2570-
ShouldAddOptNone &= !decl->hasAttr<MinSizeAttr>();
2571-
ShouldAddOptNone &= !decl->hasAttr<AlwaysInlineAttr>();
2572-
ShouldAddOptNone |= decl->hasAttr<OptimizeNoneAttr>();
2646+
// Add other optimization related attributes if we are optimizing this
2647+
// function.
2648+
if (!decl->hasAttr<OptimizeNoneAttr>()) {
2649+
if (decl->hasAttr<ColdAttr>()) {
2650+
llvm_unreachable("NYI");
2651+
}
2652+
if (decl->hasAttr<HotAttr>())
2653+
llvm_unreachable("NYI");
2654+
if (decl->hasAttr<MinSizeAttr>())
2655+
assert(!MissingFeatures::minSize());
25732656
}
25742657

2575-
if (ShouldAddOptNone) {
2576-
auto optNoneAttr = cir::OptNoneAttr::get(&getMLIRContext());
2577-
attrs.set(optNoneAttr.getMnemonic(), optNoneAttr);
2658+
f.setExtraAttrsAttr(cir::ExtraFuncAttributesAttr::get(
2659+
&getMLIRContext(), attrs.getDictionary(&getMLIRContext())));
25782660

2579-
// OptimizeNone implies noinline; we should not be inlining such functions.
2580-
auto noInlineAttr =
2581-
cir::InlineAttr::get(&getMLIRContext(), cir::InlineKind::NoInline);
2582-
attrs.set(noInlineAttr.getMnemonic(), noInlineAttr);
2661+
assert(!MissingFeatures::setFunctionAlignment());
2662+
2663+
// In the cross-dso CFI mode with canonical jump tables, we want !type
2664+
// attributes on definitions only.
2665+
if (codeGenOpts.SanitizeCfiCrossDso &&
2666+
codeGenOpts.SanitizeCfiCanonicalJumpTables) {
2667+
llvm_unreachable("NYI");
25832668
}
25842669

2585-
f.setExtraAttrsAttr(cir::ExtraFuncAttributesAttr::get(
2586-
&getMLIRContext(), attrs.getDictionary(&getMLIRContext())));
2670+
assert(!MissingFeatures::memberFunctionPointerTypeMetadata());
25872671
}
25882672

25892673
void CIRGenModule::setCIRFunctionAttributes(GlobalDecl GD,

0 commit comments

Comments
 (0)