Index: include/clang/Driver/Options.td =================================================================== --- include/clang/Driver/Options.td +++ include/clang/Driver/Options.td @@ -2054,9 +2054,9 @@ def ffixed_x#i : Flag<["-"], "ffixed-x"#i>, Group, HelpText<"Reserve the "#i#" 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 @@ -341,6 +341,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/CGDeclCXX.cpp =================================================================== --- lib/CodeGen/CGDeclCXX.cpp +++ lib/CodeGen/CGDeclCXX.cpp @@ -361,10 +361,18 @@ auto RASignKind = getCodeGenOpts().getSignReturnAddress(); if (RASignKind != CodeGenOptions::SignReturnAddressScope::None) + { Fn->addFnAttr("sign-return-address", RASignKind == CodeGenOptions::SignReturnAddressScope::All ? "all" : "non-leaf"); + auto RASignKey = getCodeGenOpts().getSignReturnAddressKey(); + Fn->addFnAttr("sign-return-address-key", + RASignKey == CodeGenOptions::SignReturnAddressKeyValue::AKey + ? "a_key" + : "b_key"); + } + return Fn; } 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 @@ -1470,7 +1470,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 @@ -1129,8 +1129,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")) @@ -1140,7 +1143,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,14 +1,22 @@ // 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"={{.*}} }} // CHECK-PARTIAL: @foo() #[[ATTR:[0-9]*]] -// CHECK-PARTIAL: attributes #[[ATTR]] = { {{.*}} "sign-return-address"="non-leaf" {{.*}}} +// CHECK-PARTIAL: attributes #[[ATTR]] = { {{.*}} "sign-return-address"="non-leaf" "sign-return-address-key"="a_key" {{.*}}} // CHECK-ALL: @foo() #[[ATTR:[0-9]*]] -// CHECK-ALL: attributes #[[ATTR]] = { {{.*}} "sign-return-address"="all" {{.*}} } +// CHECK-ALL: attributes #[[ATTR]] = { {{.*}} "sign-return-address"="all" "sign-return-address-key"="a_key" {{.*}} } + +// 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() {} Index: test/CodeGenCXX/aarch64-sign-return-address-static-ctor.cpp =================================================================== --- test/CodeGenCXX/aarch64-sign-return-address-static-ctor.cpp +++ test/CodeGenCXX/aarch64-sign-return-address-static-ctor.cpp @@ -4,6 +4,10 @@ // RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-PARTIAL // RUN: %clang -target aarch64-arm-none-eabi -S -emit-llvm -o - -msign-return-address=all %s | \ // RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-ALL +// RUN: %clang -target aarch64-arm-none-eabi -S -emit-llvm -o - -msign-return-address=all+a_key %s | \ +// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-A-KEY +// RUN: %clang -target aarch64-arm-none-eabi -S -emit-llvm -o - -msign-return-address=all+b_key %s | \ +// RUN: FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-B-KEY struct Foo { Foo() {} @@ -17,5 +21,7 @@ // CHECK: @[[CTOR_FN]]() #[[ATTR:[0-9]*]] // CHECK-NONE-NOT: attributes #[[ATTR]] = { {{.*}} "sign-return-address"={{.*}} }} -// CHECK-PARTIAL: attributes #[[ATTR]] = { {{.*}} "sign-return-address"="non-leaf" {{.*}}} -// CHECK-ALL: attributes #[[ATTR]] = { {{.*}} "sign-return-address"="all" {{.*}} } +// CHECK-PARTIAL: attributes #[[ATTR]] = { {{.*}} "sign-return-address"="non-leaf" "sign-return-address-key"="a_key" {{.*}}} +// CHECK-ALL: attributes #[[ATTR]] = { {{.*}} "sign-return-address"="all" "sign-return-address-key"="a_key" {{.*}} } +// CHECK-A-KEY: attributes #[[ATTR]] = { {{.*}} "sign-return-address"="all" "sign-return-address-key"="a_key" {{.*}} } +// CHECK-B-KEY: attributes #[[ATTR]] = { {{.*}} "sign-return-address"="all" "sign-return-address-key"="b_key" {{.*}} }