Index: include/clang/Driver/Options.td =================================================================== --- include/clang/Driver/Options.td +++ include/clang/Driver/Options.td @@ -1885,9 +1885,9 @@ def mno_long_calls : Flag<["-"], "mno-long-calls">, Group, HelpText<"Restore the default behaviour of not generating long calls">; def mexecute_only : Flag<["-"], "mexecute-only">, Group, - HelpText<"Disallow generation of data access to code sections (ARM only)">; + HelpText<"Disallow generation of data access to code sections (ARM/AArch64 only)">; def mno_execute_only : Flag<["-"], "mno-execute-only">, Group, - HelpText<"Allow generation of data access to code sections (ARM only)">; + HelpText<"Allow generation of data access to code sections (ARM/AArch64 only)">; def mtp_mode_EQ : Joined<["-"], "mtp=">, Group, Values<"soft, cp15">, HelpText<"Read thread pointer from coprocessor register (ARM only)">; def mpure_code : Flag<["-"], "mpure-code">, Alias; // Alias for GCC compatibility Index: lib/Driver/ToolChains/Arch/AArch64.h =================================================================== --- lib/Driver/ToolChains/Arch/AArch64.h +++ lib/Driver/ToolChains/Arch/AArch64.h @@ -22,6 +22,7 @@ namespace aarch64 { void getAArch64TargetFeatures(const Driver &D, const llvm::opt::ArgList &Args, + llvm::opt::ArgStringList &CmdArgs, std::vector &Features); std::string getAArch64TargetCPU(const llvm::opt::ArgList &Args, Index: lib/Driver/ToolChains/Arch/AArch64.cpp =================================================================== --- lib/Driver/ToolChains/Arch/AArch64.cpp +++ lib/Driver/ToolChains/Arch/AArch64.cpp @@ -150,6 +150,7 @@ } void aarch64::getAArch64TargetFeatures(const Driver &D, const ArgList &Args, + ArgStringList &CmdArgs, std::vector &Features) { Arg *A; bool success = true; @@ -203,4 +204,11 @@ if (Args.hasArg(options::OPT_mno_neg_immediates)) Features.push_back("+no-neg-immediates"); + + // Generate execute-only output (no data access to code sections). + if (Arg *A = Args.getLastArg(options::OPT_mexecute_only, options::OPT_mno_execute_only)) { + if (A->getOption().matches(options::OPT_mexecute_only)) { + Features.push_back("+execute-only"); + } + } } Index: lib/Driver/ToolChains/Clang.cpp =================================================================== --- lib/Driver/ToolChains/Clang.cpp +++ lib/Driver/ToolChains/Clang.cpp @@ -341,7 +341,7 @@ break; case llvm::Triple::aarch64: case llvm::Triple::aarch64_be: - aarch64::getAArch64TargetFeatures(D, Args, Features); + aarch64::getAArch64TargetFeatures(D, Args, CmdArgs, Features); break; case llvm::Triple::x86: case llvm::Triple::x86_64: Index: test/CodeGen/aarch64-execute-only.c =================================================================== --- /dev/null +++ test/CodeGen/aarch64-execute-only.c @@ -0,0 +1,24 @@ +// RUN: %clang -target aarch64-linux-eabi -### %s 2>&1 \ +// RUN: | FileCheck %s -check-prefix CHECK-NO-EXECUTE-ONLY + +// RUN: %clang -target aarch64-linux-eabi -### -mexecute-only %s 2>&1 \ +// RUN: | FileCheck %s -check-prefix CHECK-EXECUTE-ONLY + +// RUN: %clang -target aarch64-linux-eabi -### -mexecute-only -mno-execute-only %s 2>&1 \ +// RUN: | FileCheck %s -check-prefix CHECK-NO-EXECUTE-ONLY + + +// -mpure-code flag for GCC compatibility +// RUN: %clang -target aarch64-linux-eabi -### %s 2>&1 \ +// RUN: | FileCheck %s -check-prefix CHECK-NO-EXECUTE-ONLY + +// RUN: %clang -target aarch64-linux-eabi -### -mpure-code %s 2>&1 \ +// RUN: | FileCheck %s -check-prefix CHECK-EXECUTE-ONLY + +// RUN: %clang -target aarch64-linux-eabi -### -mpure-code -mno-pure-code %s 2>&1 \ +// RUN: | FileCheck %s -check-prefix CHECK-NO-EXECUTE-ONLY + +// CHECK-NO-EXECUTE-ONLY-NOT: "+execute-only" +// CHECK-EXECUTE-ONLY: "+execute-only" + +void a() {}