diff --git a/lld/COFF/Config.h b/lld/COFF/Config.h index 3d416e6985d02..57cb443798cd8 100644 --- a/lld/COFF/Config.h +++ b/lld/COFF/Config.h @@ -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; diff --git a/lld/COFF/SymbolTable.cpp b/lld/COFF/SymbolTable.cpp index 35d54d4945f7f..53581d2d7ed11 100644 --- a/lld/COFF/SymbolTable.cpp +++ b/lld/COFF/SymbolTable.cpp @@ -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; } @@ -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 && + (ctx.config.machine == ARM64 || 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; + ctx.driver.addWinSysRootLibSearchPaths(); + } ctx.driver.parseDirectives(file); } diff --git a/lld/test/COFF/arm64ec.test b/lld/test/COFF/arm64ec.test index e50b14ce0184c..75288e97e598d 100644 --- a/lld/test/COFF/arm64ec.test +++ b/lld/test/COFF/arm64ec.test @@ -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 @@ -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 arm64-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: lld-link: error: arm64ec-data-sym.obj: machine type arm64ec conflicts with x86 + +arm64x can be inferred and when mixed with ARM64, the first one wins +RUN: lld-link -out:test.dll -dll -noentry arm64x-resource.obj arm64-data-sym.obj x86_64-data-sym.obj arm64ec-data-sym.obj +RUN: not lld-link -out:test.dll -dll -noentry arm64-data-sym.obj arm64x-resource.obj x86_64-data-sym.obj 2>&1 | FileCheck -check-prefix=INCOMPAT3 %s +RUN: not lld-link -out:test.dll -dll -noentry arm64-data-sym.obj arm64x-resource.obj arm64ec-data-sym.obj 2>&1 | FileCheck -check-prefix=INCOMPAT4 %s + #--- arm64ec-data-sym.s .data .globl arm64ec_data_sym