aboutsummaryrefslogtreecommitdiff
path: root/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/CodeGen/CodeGenFunction.cpp14
-rw-r--r--clang/lib/Driver/ToolChains/Clang.cpp4
-rw-r--r--clang/lib/Frontend/CompilerInvocation.cpp24
-rw-r--r--clang/lib/Sema/SemaDeclAttr.cpp23
4 files changed, 65 insertions, 0 deletions
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp
index 05942f4..17c1c91 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -898,6 +898,20 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
if (D && D->hasAttr<NoProfileFunctionAttr>())
Fn->addFnAttr(llvm::Attribute::NoProfile);
+ if (D) {
+ // Function attributes take precedence over command line flags.
+ if (auto *A = D->getAttr<FunctionReturnThunksAttr>()) {
+ switch (A->getThunkType()) {
+ case FunctionReturnThunksAttr::Kind::Keep:
+ break;
+ case FunctionReturnThunksAttr::Kind::Extern:
+ Fn->addFnAttr(llvm::Attribute::FnRetThunkExtern);
+ break;
+ }
+ } else if (CGM.getCodeGenOpts().FunctionReturnThunks)
+ Fn->addFnAttr(llvm::Attribute::FnRetThunkExtern);
+ }
+
if (FD && (getLangOpts().OpenCL ||
(getLangOpts().HIP && getLangOpts().CUDAIsDevice))) {
// Add metadata for a kernel function.
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index ec1a31f..b5bfea1 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -6344,6 +6344,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (IsUsingLTO)
Args.AddLastArg(CmdArgs, options::OPT_mibt_seal);
+ if (Arg *A = Args.getLastArg(options::OPT_mfunction_return_EQ))
+ CmdArgs.push_back(
+ Args.MakeArgString(Twine("-mfunction-return=") + A->getValue()));
+
// Forward -f options with positive and negative forms; we translate these by
// hand. Do not propagate PGO options to the GPU-side compilations as the
// profile info is for the host-side compilation only.
diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp
index abef4cf..50aaab6 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -1485,6 +1485,9 @@ void CompilerInvocation::GenerateCodeGenArgs(
if (Opts.IBTSeal)
GenerateArg(Args, OPT_mibt_seal, SA);
+ if (Opts.FunctionReturnThunks)
+ GenerateArg(Args, OPT_mfunction_return_EQ, "thunk-extern", SA);
+
for (const auto &F : Opts.LinkBitcodeFiles) {
bool Builtint = F.LinkFlags == llvm::Linker::Flags::LinkOnlyNeeded &&
F.PropagateAttrs && F.Internalize;
@@ -1825,6 +1828,27 @@ bool CompilerInvocation::ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args,
Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Name;
}
+ if (const Arg *A = Args.getLastArg(OPT_mfunction_return_EQ)) {
+ auto Val = llvm::StringSwitch<llvm::FunctionReturnThunksKind>(A->getValue())
+ .Case("keep", llvm::FunctionReturnThunksKind::Keep)
+ .Case("thunk-extern", llvm::FunctionReturnThunksKind::Extern)
+ .Default(llvm::FunctionReturnThunksKind::Invalid);
+ // SystemZ might want to add support for "expolines."
+ if (!T.isX86())
+ Diags.Report(diag::err_drv_argument_not_allowed_with)
+ << A->getSpelling() << T.getTriple();
+ else if (Val == llvm::FunctionReturnThunksKind::Invalid)
+ Diags.Report(diag::err_drv_invalid_value)
+ << A->getAsString(Args) << A->getValue();
+ else if (Val == llvm::FunctionReturnThunksKind::Extern &&
+ Args.getLastArgValue(OPT_mcmodel_EQ).equals("large"))
+ Diags.Report(diag::err_drv_argument_not_allowed_with)
+ << A->getAsString(Args)
+ << Args.getLastArg(OPT_mcmodel_EQ)->getAsString(Args);
+ else
+ Opts.FunctionReturnThunks = static_cast<unsigned>(Val);
+ }
+
if (Opts.PrepareForLTO && Args.hasArg(OPT_mibt_seal))
Opts.IBTSeal = 1;
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index 5138971..de8d795 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -8000,6 +8000,26 @@ static void handleZeroCallUsedRegsAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
D->addAttr(ZeroCallUsedRegsAttr::Create(S.Context, Kind, AL));
}
+static void handleFunctionReturnThunksAttr(Sema &S, Decl *D,
+ const ParsedAttr &AL) {
+ StringRef KindStr;
+ SourceLocation LiteralLoc;
+ if (!S.checkStringLiteralArgumentAttr(AL, 0, KindStr, &LiteralLoc))
+ return;
+
+ FunctionReturnThunksAttr::Kind Kind;
+ if (!FunctionReturnThunksAttr::ConvertStrToKind(KindStr, Kind)) {
+ S.Diag(LiteralLoc, diag::warn_attribute_type_not_supported)
+ << AL << KindStr;
+ return;
+ }
+ // FIXME: it would be good to better handle attribute merging rather than
+ // silently replacing the existing attribute, so long as it does not break
+ // the expected codegen tests.
+ D->dropAttr<FunctionReturnThunksAttr>();
+ D->addAttr(FunctionReturnThunksAttr::Create(S.Context, Kind, AL));
+}
+
static void handleSYCLKernelAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
// The 'sycl_kernel' attribute applies only to function templates.
const auto *FD = cast<FunctionDecl>(D);
@@ -8866,6 +8886,9 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL,
case ParsedAttr::AT_ZeroCallUsedRegs:
handleZeroCallUsedRegsAttr(S, D, AL);
break;
+ case ParsedAttr::AT_FunctionReturnThunks:
+ handleFunctionReturnThunksAttr(S, D, AL);
+ break;
// Microsoft attributes:
case ParsedAttr::AT_LayoutVersion: