Skip to content

Commit 9f045fd

Browse files
committed
[clang][Driver] Pass -machine argument to the linker explicitly for ARM64EC targets.
Currently, Clang doesn't explicitly pass the -machine argument to the linker, relying on the linker to infer it from the input. However, MSVC's link.exe requires -machine to be specified explicitly for ARM64EC/ARM64X targets. Although lld-link allows inferring the target from ARM64EC object files, this detection isn't entirely reliable as AMD64 object files are also valid input for ARM64EC target. Handling of -machine:arm64ec is straightforward. For ARM64X, this PR extends the ARM64EC target triple to accept the "arm64x" subarch string, which serves as an alias to "arm64ec" in most cases. However, during linker invocation, "arm64x" distinguishes between -machine:arm64ec and -machine:arm64x. The only analogue to MSVC's behavior is cl.exe -arm64EC, which is handled by -machine:arm64ec part of this PR. As far as I can tell, linking ARM64X images with MSVC requires a direct link.exe invocation. In cases like lib.exe (#85972) or some aspects of link.exe, -machine:arm64x serves as an alias to -machine:arm64ec too.
1 parent c9d1266 commit 9f045fd

File tree

6 files changed

+47
-7
lines changed

6 files changed

+47
-7
lines changed

clang/lib/Driver/Driver.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1458,8 +1458,7 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
14581458
}
14591459

14601460
// Report warning when arm64EC option is overridden by specified target
1461-
if ((TC.getTriple().getArch() != llvm::Triple::aarch64 ||
1462-
TC.getTriple().getSubArch() != llvm::Triple::AArch64SubArch_arm64ec) &&
1461+
if (!TC.getTriple().isWindowsArm64EC() &&
14631462
UArgs->hasArg(options::OPT__SLASH_arm64EC)) {
14641463
getDiags().Report(clang::diag::warn_target_override_arm64ec)
14651464
<< TC.getTriple().str();

clang/lib/Driver/ToolChains/MSVC.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,13 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA,
7979
CmdArgs.push_back(
8080
Args.MakeArgString(std::string("-out:") + Output.getFilename()));
8181

82+
if (TC.getTriple().isWindowsArm64EC()) {
83+
if (TC.getTriple().getSubArch() == llvm::Triple::AArch64SubArch_arm64x)
84+
CmdArgs.push_back("-machine:arm64x");
85+
else
86+
CmdArgs.push_back("-machine:arm64ec");
87+
}
88+
8289
if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles) &&
8390
!C.getDriver().IsCLMode() && !C.getDriver().IsFlangMode()) {
8491
CmdArgs.push_back("-defaultlib:libcmt");

clang/test/Driver/msvc-link.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,9 @@
3636
// VFSOVERLAY: "--vfsoverlay"
3737
// VFSOVERLAY: lld-link
3838
// VFSOVERLAY: "/vfsoverlay:{{.*}}" "{{.*}}.obj"
39+
40+
// RUN: %clang -target arm64ec-pc-windows-msvc -fuse-ld=link -### %s 2>&1 | FileCheck --check-prefix=ARM64EC %s
41+
// ARM64EC: "-machine:arm64ec"
42+
43+
// RUN: %clang -target arm64x-pc-windows-msvc -fuse-ld=link -### %s 2>&1 | FileCheck --check-prefix=ARM64X %s
44+
// ARM64X: "-machine:arm64x"

llvm/include/llvm/TargetParser/Triple.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ class Triple {
148148

149149
AArch64SubArch_arm64e,
150150
AArch64SubArch_arm64ec,
151+
AArch64SubArch_arm64x,
151152

152153
KalimbaSubArch_v3,
153154
KalimbaSubArch_v4,
@@ -623,7 +624,8 @@ class Triple {
623624
// Checks if we're using the Windows Arm64EC ABI.
624625
bool isWindowsArm64EC() const {
625626
return getArch() == Triple::aarch64 &&
626-
getSubArch() == Triple::AArch64SubArch_arm64ec;
627+
(getSubArch() == Triple::AArch64SubArch_arm64ec ||
628+
getSubArch() == Triple::AArch64SubArch_arm64x);
627629
}
628630

629631
bool isWindowsCoreCLREnvironment() const {

llvm/lib/TargetParser/Triple.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ StringRef Triple::getArchName(ArchType Kind, SubArchType SubArch) {
110110
return "mipsisa64r6el";
111111
break;
112112
case Triple::aarch64:
113-
if (SubArch == AArch64SubArch_arm64ec)
113+
if (SubArch == AArch64SubArch_arm64ec || SubArch == AArch64SubArch_arm64x)
114114
return "arm64ec";
115115
if (SubArch == AArch64SubArch_arm64e)
116116
return "arm64e";
@@ -515,10 +515,8 @@ static Triple::ArchType parseArch(StringRef ArchName) {
515515
.Case("aarch64_be", Triple::aarch64_be)
516516
.Case("aarch64_32", Triple::aarch64_32)
517517
.Case("arc", Triple::arc)
518-
.Case("arm64", Triple::aarch64)
518+
.Cases("arm64", "arm64e", "arm64ec", "arm64x", Triple::aarch64)
519519
.Case("arm64_32", Triple::aarch64_32)
520-
.Case("arm64e", Triple::aarch64)
521-
.Case("arm64ec", Triple::aarch64)
522520
.Case("arm", Triple::arm)
523521
.Case("armeb", Triple::armeb)
524522
.Case("thumb", Triple::thumb)
@@ -729,6 +727,9 @@ static Triple::SubArchType parseSubArch(StringRef SubArchName) {
729727
if (SubArchName == "arm64ec")
730728
return Triple::AArch64SubArch_arm64ec;
731729

730+
if (SubArchName == "arm64x")
731+
return Triple::AArch64SubArch_arm64x;
732+
732733
if (SubArchName.starts_with("spirv"))
733734
return StringSwitch<Triple::SubArchType>(SubArchName)
734735
.EndsWith("v1.0", Triple::SPIRVSubArch_v10)

llvm/unittests/TargetParser/TripleTest.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2226,6 +2226,16 @@ TEST(TripleTest, ParseARMArch) {
22262226
T.setArch(Triple::aarch64, Triple::AArch64SubArch_arm64ec);
22272227
EXPECT_EQ("arm64ec", T.getArchName());
22282228
}
2229+
{
2230+
Triple T = Triple("arm64x");
2231+
EXPECT_EQ(Triple::aarch64, T.getArch());
2232+
EXPECT_EQ(Triple::AArch64SubArch_arm64x, T.getSubArch());
2233+
}
2234+
{
2235+
Triple T;
2236+
T.setArch(Triple::aarch64, Triple::AArch64SubArch_arm64x);
2237+
EXPECT_EQ("arm64ec", T.getArchName());
2238+
}
22292239
}
22302240

22312241
TEST(TripleTest, isArmT32) {
@@ -2371,4 +2381,19 @@ TEST(TripleTest, isArmMClass) {
23712381
EXPECT_TRUE(T.isArmMClass());
23722382
}
23732383
}
2384+
2385+
TEST(TripleTest, isWindowsArm64EC) {
2386+
{
2387+
Triple T = Triple("arm64ec");
2388+
EXPECT_TRUE(T.isWindowsArm64EC());
2389+
}
2390+
{
2391+
Triple T = Triple("arm64x");
2392+
EXPECT_TRUE(T.isWindowsArm64EC());
2393+
}
2394+
{
2395+
Triple T = Triple("aarch64");
2396+
EXPECT_FALSE(T.isWindowsArm64EC());
2397+
}
2398+
}
23742399
} // end anonymous namespace

0 commit comments

Comments
 (0)