Skip to content

Commit 90db419

Browse files
[clang][AArch64] Add --print-supported-extensions support (#65466)
This follows the RISC-V work done in 4b40ced. This uses AArch64's target parser instead. We just list the names, without the "+" on them, which matches RISC-V's format. ``` $ ./bin/clang -target aarch64-linux-gnu --print-supported-extensions clang version 18.0.0 (https://github.com/llvm/llvm-project.git 154da8aec20719c82235a6957aa6e461f5a5e030) Target: aarch64-unknown-linux-gnu Thread model: posix InstalledDir: <...> All available -march extensions for AArch64 aes b16b16 bf16 brbe crc crypto cssc <...> ``` Since our extensions don't have versions in the same way there's just one column with the name in. Any extension without a feature name (including the special "none") is not listed as those cannot be passed to -march, they're just for the backend. For example the MTE extension can be added with "+memtag" but MTE2 and MTE3 do not have feature names so they cannot be added to -march. This does not attempt to tackle the fact that clang allows invalid combinations of AArch64 extensions, it simply lists the possible options. It's still up to the user to ask for something sensible. Equally, this has no context of what CPU is being selected. Neither does the RISC-V option, the user has to be aware of that. I've added a target parser test, and a high level clang test that checks RISC-V and AArch64 work and that Intel, that doesn't support this, shows the correct error.
1 parent 00add6e commit 90db419

File tree

7 files changed

+81
-3
lines changed

7 files changed

+81
-3
lines changed

clang/include/clang/Driver/Options.td

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5271,7 +5271,7 @@ def print_supported_cpus : Flag<["-", "--"], "print-supported-cpus">,
52715271
MarshallingInfoFlag<FrontendOpts<"PrintSupportedCPUs">>;
52725272
def print_supported_extensions : Flag<["-", "--"], "print-supported-extensions">,
52735273
Visibility<[ClangOption, CC1Option, CLOption]>,
5274-
HelpText<"Print supported extensions for RISC-V">,
5274+
HelpText<"Print supported -march extensions (RISC-V and AArch64 only)">,
52755275
MarshallingInfoFlag<FrontendOpts<"PrintSupportedExtensions">>;
52765276
def : Flag<["-"], "mcpu=help">, Alias<print_supported_cpus>;
52775277
def : Flag<["-"], "mtune=help">, Alias<print_supported_cpus>;

clang/lib/Driver/Driver.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4284,7 +4284,8 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args,
42844284
// and quits.
42854285
if (Arg *A = Args.getLastArg(Opt)) {
42864286
if (Opt == options::OPT_print_supported_extensions &&
4287-
!C.getDefaultToolChain().getTriple().isRISCV()) {
4287+
!C.getDefaultToolChain().getTriple().isRISCV() &&
4288+
!C.getDefaultToolChain().getTriple().isAArch64()) {
42884289
C.getDriver().Diag(diag::err_opt_not_valid_on_target)
42894290
<< "--print-supported-extensions";
42904291
return;
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// Test that --print-supported-extensions lists supported -march extensions
2+
// on supported architectures, and errors on unsupported architectures.
3+
4+
// RUN: %if aarch64-registered-target %{ %clang --target=aarch64-linux-gnu \
5+
// RUN: --print-supported-extensions 2>&1 | FileCheck %s --check-prefix AARCH64 %}
6+
// AARCH64: All available -march extensions for AArch64
7+
8+
// RUN: %if aarch64-registered-target %{ %clang --target=riscv64-linux-gnu \
9+
// RUN: --print-supported-extensions 2>&1 | FileCheck %s --check-prefix RISCV %}
10+
// RISCV: All available -march extensions for RISC-V
11+
12+
// RUN: %if x86-registered-target %{ not %clang --target=x86_64-linux-gnu \
13+
// RUN: --print-supported-extensions 2>&1 | FileCheck %s --check-prefix X86 %}
14+
// X86: error: option '--print-supported-extensions' cannot be specified on this target

clang/tools/driver/cc1_main.cpp

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
#include "llvm/Support/Timer.h"
4646
#include "llvm/Support/raw_ostream.h"
4747
#include "llvm/Target/TargetMachine.h"
48+
#include "llvm/TargetParser/AArch64TargetParser.h"
4849
#include <cstdio>
4950

5051
#ifdef CLANG_HAVE_RLIMITS
@@ -183,6 +184,34 @@ static int PrintSupportedCPUs(std::string TargetStr) {
183184
return 0;
184185
}
185186

187+
static int PrintSupportedExtensions(std::string TargetStr) {
188+
std::string Error;
189+
const llvm::Target *TheTarget =
190+
llvm::TargetRegistry::lookupTarget(TargetStr, Error);
191+
if (!TheTarget) {
192+
llvm::errs() << Error;
193+
return 1;
194+
}
195+
196+
llvm::TargetOptions Options;
197+
std::unique_ptr<llvm::TargetMachine> TheTargetMachine(
198+
TheTarget->createTargetMachine(TargetStr, "", "", Options, std::nullopt));
199+
const llvm::Triple &MachineTriple = TheTargetMachine->getTargetTriple();
200+
201+
if (MachineTriple.isRISCV())
202+
llvm::riscvExtensionsHelp();
203+
else if (MachineTriple.isAArch64())
204+
llvm::AArch64::PrintSupportedExtensions();
205+
else {
206+
// The option was already checked in Driver::HandleImmediateArgs,
207+
// so we do not expect to get here if we are not a supported architecture.
208+
assert(0 && "Unhandled triple for --print-supported-extensions option.");
209+
return 1;
210+
}
211+
212+
return 0;
213+
}
214+
186215
int cc1_main(ArrayRef<const char *> Argv, const char *Argv0, void *MainAddr) {
187216
ensureSufficientStack();
188217

@@ -224,7 +253,7 @@ int cc1_main(ArrayRef<const char *> Argv, const char *Argv0, void *MainAddr) {
224253

225254
// --print-supported-extensions takes priority over the actual compilation.
226255
if (Clang->getFrontendOpts().PrintSupportedExtensions)
227-
return llvm::riscvExtensionsHelp(), 0;
256+
return PrintSupportedExtensions(Clang->getTargetOpts().Triple);
228257

229258
// Infer the builtin include path if unspecified.
230259
if (Clang->getHeaderSearchOpts().UseBuiltinIncludes &&

llvm/include/llvm/TargetParser/AArch64TargetParser.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -576,6 +576,8 @@ bool isX18ReservedByDefault(const Triple &TT);
576576
// themselves, they are sequential (0, 1, 2, 3, ...).
577577
uint64_t getCpuSupportsMask(ArrayRef<StringRef> FeatureStrs);
578578

579+
void PrintSupportedExtensions();
580+
579581
} // namespace AArch64
580582
} // namespace llvm
581583

llvm/lib/TargetParser/AArch64TargetParser.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
//===----------------------------------------------------------------------===//
1313

1414
#include "llvm/TargetParser/AArch64TargetParser.h"
15+
#include "llvm/Support/raw_ostream.h"
1516
#include "llvm/TargetParser/ARMTargetParserCommon.h"
1617
#include "llvm/TargetParser/Triple.h"
1718
#include <cctype>
@@ -132,3 +133,12 @@ std::optional<AArch64::CpuInfo> AArch64::parseCpu(StringRef Name) {
132133

133134
return {};
134135
}
136+
137+
void AArch64::PrintSupportedExtensions() {
138+
outs() << "All available -march extensions for AArch64\n\n";
139+
for (const auto &Ext : Extensions) {
140+
// Extensions without a feature cannot be used with -march.
141+
if (!Ext.Feature.empty())
142+
outs() << '\t' << Ext.Name << "\n";
143+
}
144+
}

llvm/unittests/TargetParser/TargetParserTest.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1805,4 +1805,26 @@ TEST(TargetParserTest, AArch64ArchExtFeature) {
18051805
}
18061806
}
18071807

1808+
TEST(TargetParserTest, AArch64PrintSupportedExtensions) {
1809+
std::string expected = "All available -march extensions for AArch64\n\n"
1810+
"\taes\n\tb16b16\n\tbf16";
1811+
1812+
outs().flush();
1813+
testing::internal::CaptureStdout();
1814+
AArch64::PrintSupportedExtensions();
1815+
outs().flush();
1816+
std::string captured = testing::internal::GetCapturedStdout();
1817+
1818+
// Check that the start of the output is as expected.
1819+
EXPECT_EQ(0ULL, captured.find(expected));
1820+
1821+
// Should not include "none".
1822+
EXPECT_EQ(std::string::npos, captured.find("none"));
1823+
// Should not include anything that lacks a feature name. Checking a few here
1824+
// but not all as if one is hidden correctly the rest should be.
1825+
EXPECT_EQ(std::string::npos, captured.find("memtag3"));
1826+
EXPECT_EQ(std::string::npos, captured.find("sha1"));
1827+
EXPECT_EQ(std::string::npos, captured.find("ssbs2"));
1828+
}
1829+
18081830
} // namespace

0 commit comments

Comments
 (0)