Index: include/clang/Driver/Options.td =================================================================== --- include/clang/Driver/Options.td +++ include/clang/Driver/Options.td @@ -2045,9 +2045,9 @@ def ffixed_x20 : Flag<["-"], "ffixed-x20">, Group, HelpText<"Reserve the x20 register (AArch64 only)">; -def msign_return_address : Joined<["-"], "msign-return-address=">, - Flags<[CC1Option]>, Group, - HelpText<"Select return address signing scope">, Values<"none,all,non-leaf">; +def msign_return_address_EQ : Joined<["-"], "msign-return-address=">, + Flags<[CC1Option]>, Group, Values<"none,all,non-leaf[+a_key,b_key]">, + HelpText<"Select return address signing scope">; def msimd128 : Flag<["-"], "msimd128">, Group; def mno_simd128 : Flag<["-"], "mno-simd128">, Group; Index: include/clang/Frontend/CodeGenOptions.h =================================================================== --- include/clang/Frontend/CodeGenOptions.h +++ include/clang/Frontend/CodeGenOptions.h @@ -114,6 +114,8 @@ All // Sign the return address of all functions }; + enum SignReturnAddressKeyValue { AKey, BKey }; + /// The code model to use (-mcmodel). std::string CodeModel; Index: include/clang/Frontend/CodeGenOptions.def =================================================================== --- include/clang/Frontend/CodeGenOptions.def +++ include/clang/Frontend/CodeGenOptions.def @@ -340,6 +340,7 @@ CODEGENOPT(Addrsig, 1, 0) ENUM_CODEGENOPT(SignReturnAddress, SignReturnAddressScope, 2, None) +ENUM_CODEGENOPT(SignReturnAddressKey, SignReturnAddressKeyValue, 1, AKey) /// Whether to emit unused static constants. CODEGENOPT(KeepStaticConsts, 1, 0) Index: lib/CodeGen/TargetInfo.cpp =================================================================== --- lib/CodeGen/TargetInfo.cpp +++ lib/CodeGen/TargetInfo.cpp @@ -4985,6 +4985,12 @@ Kind == CodeGenOptions::SignReturnAddressScope::All ? "all" : "non-leaf"); + + auto Key = CGM.getCodeGenOpts().getSignReturnAddressKey(); + Fn->addFnAttr("sign-return-address-key", + Key == CodeGenOptions::SignReturnAddressKeyValue::AKey + ? "a_key" + : "b_key"); } }; Index: lib/Driver/ToolChains/Clang.cpp =================================================================== --- lib/Driver/ToolChains/Clang.cpp +++ lib/Driver/ToolChains/Clang.cpp @@ -1456,7 +1456,7 @@ CmdArgs.push_back("-aarch64-enable-global-merge=true"); } - if (Arg *A = Args.getLastArg(options::OPT_msign_return_address)) { + if (Arg *A = Args.getLastArg(options::OPT_msign_return_address_EQ)) { CmdArgs.push_back( Args.MakeArgString(Twine("-msign-return-address=") + A->getValue())); } Index: lib/Frontend/CompilerInvocation.cpp =================================================================== --- lib/Frontend/CompilerInvocation.cpp +++ lib/Frontend/CompilerInvocation.cpp @@ -1131,8 +1131,11 @@ Opts.Addrsig = Args.hasArg(OPT_faddrsig); - if (Arg *A = Args.getLastArg(OPT_msign_return_address)) { - StringRef SignScope = A->getValue(); + if (Arg *A = Args.getLastArg(OPT_msign_return_address_EQ)) { + const auto SignScopeKey = StringRef(A->getValue()).split('+'); + StringRef SignScope = SignScopeKey.first; + StringRef SignKey = SignScopeKey.second; + if (SignScope.equals_lower("none")) Opts.setSignReturnAddress(CodeGenOptions::SignReturnAddressScope::None); else if (SignScope.equals_lower("all")) @@ -1142,7 +1145,17 @@ CodeGenOptions::SignReturnAddressScope::NonLeaf); else Diags.Report(diag::err_drv_invalid_value) - << A->getAsString(Args) << A->getValue(); + << A->getAsString(Args) << SignScope; + + if (!SignScope.empty() && !SignKey.empty()) { + if (SignKey.equals_lower("a_key")) + Opts.setSignReturnAddressKey(CodeGenOptions::SignReturnAddressKeyValue::AKey); + else if (SignKey.equals_lower("b_key")) + Opts.setSignReturnAddressKey(CodeGenOptions::SignReturnAddressKeyValue::BKey); + else + Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) + << SignKey; + } } Opts.KeepStaticConsts = Args.hasArg(OPT_fkeep_static_consts); Index: test/CodeGen/aarch64-sign-return-address.c =================================================================== --- test/CodeGen/aarch64-sign-return-address.c +++ test/CodeGen/aarch64-sign-return-address.c @@ -1,6 +1,8 @@ // RUN: %clang -target aarch64-arm-none-eabi -S -emit-llvm -o - -msign-return-address=none %s | FileCheck %s --check-prefix=CHECK-NONE // RUN: %clang -target aarch64-arm-none-eabi -S -emit-llvm -o - -msign-return-address=non-leaf %s | FileCheck %s --check-prefix=CHECK-PARTIAL // RUN: %clang -target aarch64-arm-none-eabi -S -emit-llvm -o - -msign-return-address=all %s | FileCheck %s --check-prefix=CHECK-ALL +// RUN: %clang -target aarch64-arm-none-eabi -S -emit-llvm -o - -msign-return-address=all+a_key %s | FileCheck %s --check-prefix=CHECK-A-KEY +// RUN: %clang -target aarch64-arm-none-eabi -S -emit-llvm -o - -msign-return-address=all+b_key %s | FileCheck %s --check-prefix=CHECK-B-KEY // CHECK-NONE: @foo() #[[ATTR:[0-9]*]] // CHECK-NONE-NOT: attributes #[[ATTR]] = { {{.*}} "sign-return-address"={{.*}} }} @@ -11,4 +13,10 @@ // CHECK-ALL: @foo() #[[ATTR:[0-9]*]] // CHECK-ALL: attributes #[[ATTR]] = { {{.*}} "sign-return-address"="all" {{.*}} } +// CHECK-A-KEY: @foo() #[[ATTR:[0-9]*]] +// CHECK-A-KEY: attributes #[[ATTR]] = { {{.*}} "sign-return-address"="all" "sign-return-address-key"="a_key" {{.*}} } + +// CHECK-B-KEY: @foo() #[[ATTR:[0-9]*]] +// CHECK-B-KEY: attributes #[[ATTR]] = { {{.*}} "sign-return-address"="all" "sign-return-address-key"="b_key" {{.*}} } + void foo() {}