diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.cpp | 14 | ||||
-rw-r--r-- | clang/lib/Driver/ToolChains/Clang.cpp | 4 | ||||
-rw-r--r-- | clang/lib/Frontend/CompilerInvocation.cpp | 24 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclAttr.cpp | 23 |
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: |