Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions lld/COFF/Config.h
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ struct Configuration {
bool is64() const { return llvm::COFF::is64Bit(machine); }

llvm::COFF::MachineTypes machine = IMAGE_FILE_MACHINE_UNKNOWN;
bool machineInferred = false;
size_t wordsize;
bool verbose = false;
WindowsSubsystem subsystem = llvm::COFF::IMAGE_SUBSYSTEM_UNKNOWN;
Expand Down
22 changes: 18 additions & 4 deletions lld/COFF/SymbolTable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ static bool compatibleMachineType(COFFLinkerContext &ctx, MachineTypes mt) {
return COFF::isArm64EC(mt) || mt == AMD64;
case ARM64X:
return COFF::isAnyArm64(mt) || mt == AMD64;
case IMAGE_FILE_MACHINE_UNKNOWN:
return true;
default:
return ctx.config.machine == mt;
}
Expand Down Expand Up @@ -74,14 +76,26 @@ void SymbolTable::addFile(InputFile *file) {
}

MachineTypes mt = file->getMachineType();
if (ctx.config.machine == IMAGE_FILE_MACHINE_UNKNOWN) {
ctx.config.machine = mt;
ctx.driver.addWinSysRootLibSearchPaths();
} else if (!compatibleMachineType(ctx, mt)) {
// The ARM64EC target must be explicitly specified and cannot be inferred.
if (mt == ARM64EC &&
(ctx.config.machine == IMAGE_FILE_MACHINE_UNKNOWN ||
(ctx.config.machineInferred && (COFF::isAnyArm64(ctx.config.machine) ||
ctx.config.machine == AMD64)))) {
error(toString(file) + ": machine type arm64ec is ambiguous and cannot be "
"inferred, use /machine:arm64ec or /machine:arm64x");
return;
}
if (!compatibleMachineType(ctx, mt)) {
error(toString(file) + ": machine type " + machineToStr(mt) +
" conflicts with " + machineToStr(ctx.config.machine));
return;
}
if (ctx.config.machine == IMAGE_FILE_MACHINE_UNKNOWN &&
mt != IMAGE_FILE_MACHINE_UNKNOWN) {
ctx.config.machineInferred = true;
ctx.config.machine = mt == ARM64X ? ARM64 : mt;
ctx.driver.addWinSysRootLibSearchPaths();
}

ctx.driver.parseDirectives(file);
}
Expand Down
23 changes: 22 additions & 1 deletion lld/test/COFF/arm64ec.test
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ RUN: split-file %s %t.dir && cd %t.dir
RUN: llvm-mc -filetype=obj -triple=aarch64-windows arm64-data-sym.s -o arm64-data-sym.obj
RUN: llvm-mc -filetype=obj -triple=arm64ec-windows arm64ec-data-sym.s -o arm64ec-data-sym.obj
RUN: llvm-mc -filetype=obj -triple=x86_64-windows x86_64-data-sym.s -o x86_64-data-sym.obj
RUN: llvm-mc -filetype=obj -triple=i686-windows x86_64-data-sym.s -o i686-data-sym.obj
RUN: llvm-cvtres -machine:arm64x -out:arm64x-resource.obj %S/Inputs/resource.res

RUN: lld-link -out:test.dll -machine:arm64ec arm64ec-data-sym.obj -dll -noentry
Expand Down Expand Up @@ -36,7 +37,7 @@ ARM64X-DATA: 03030303 01010101 02020202

RUN: not lld-link -out:test.dll -machine:arm64 arm64-data-sym.obj arm64ec-data-sym.obj \
RUN: -dll -noentry 2>&1 | FileCheck -check-prefix=INCOMPAT1 %s
INCOMPAT1: lld-link: error: arm64ec-data-sym.obj: machine type arm64ec conflicts with arm64
INCOMPAT1: arm64ec-data-sym.obj: machine type arm64ec conflicts with arm64
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happened with the lld-link: error: prefix here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An oversight, fixed, sorry.


RUN: not lld-link -out:test.dll -machine:arm64ec arm64ec-data-sym.obj arm64-data-sym.obj \
RUN: -dll -noentry 2>&1 | FileCheck -check-prefix=INCOMPAT2 %s
Expand All @@ -46,6 +47,26 @@ RUN: not lld-link -out:test.dll -machine:arm64 arm64-data-sym.obj x86_64-data-sy
RUN: -dll -noentry 2>&1 | FileCheck -check-prefix=INCOMPAT3 %s
INCOMPAT3: lld-link: error: x86_64-data-sym.obj: machine type x64 conflicts with arm64

arm64ec machine type can't be inferred, it must be specified explicitly.
RUN: not lld-link -out:test.dll arm64ec-data-sym.obj \
RUN: -dll -noentry 2>&1 | FileCheck -check-prefix=INCOMPAT4 %s
INCOMPAT4: lld-link: error: arm64ec-data-sym.obj: machine type arm64ec is ambiguous and cannot be inferred, use /machine:arm64ec or /machine:arm64x

RUN: not lld-link -out:test.dll x86_64-data-sym.obj arm64ec-data-sym.obj \
RUN: -dll -noentry 2>&1 | FileCheck -check-prefix=INCOMPAT4 %s

RUN: not lld-link -out:test.dll aarch64-data-sym.obj arm64ec-data-sym.obj \
RUN: -dll -noentry 2>&1 | FileCheck -check-prefix=INCOMPAT4 %s

RUN: not lld-link -out:test.dll i686-data-sym.obj arm64ec-data-sym.obj \
RUN: -dll -noentry 2>&1 | FileCheck -check-prefix=INCOMPAT5 %s
INCOMPAT5: arm64ec-data-sym.obj: machine type arm64ec conflicts with x86

arm64x input implies arm64 target
RUN: lld-link -out:test.dll -machine:arm64 arm64x-resource.obj -dll -noentry
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As we're explicitly specifying -machine:arm64 here, I don't see how this triggers the implicit arm64x -> arm64 machine type handling?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I messed up that test. After revisiting the MSVC behavior, I found that passing a single input file triggers an exception. However, when multiple files are passed, it behaves similarly to LLD without this change. I’ve now limited the impact of this change to ARM64EC, which aligns more closely with MSVC’s handling in these scenarios.

RUN: llvm-readobj --file-headers test.dll | FileCheck -check-prefix=ARM64-HEADER %s
ARM64-HEADER: Machine: IMAGE_FILE_MACHINE_ARM64 (0xAA64)

#--- arm64ec-data-sym.s
.data
.globl arm64ec_data_sym
Expand Down
Loading