From 9856826368a0b5bf71fd7508683484cdc5081eea Mon Sep 17 00:00:00 2001 From: Stefan Schmidt Date: Thu, 18 Dec 2025 05:19:53 +0100 Subject: [PATCH] [clang] Enable fat-lto-object support for COFF targets --- clang/lib/Driver/ToolChains/Clang.cpp | 2 +- clang/test/CodeGen/fat-lto-objects.c | 14 ++++++++++++++ clang/test/Driver/fat-lto-objects.c | 8 ++++++++ 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 310f3b58a211e..ab47d4f7e4e03 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -7837,7 +7837,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, options::OPT_fno_fat_lto_objects)) { if (IsUsingLTO && A->getOption().matches(options::OPT_ffat_lto_objects)) { assert(LTOMode == LTOK_Full || LTOMode == LTOK_Thin); - if (!Triple.isOSBinFormatELF()) { + if (!Triple.isOSBinFormatELF() && !Triple.isOSBinFormatCOFF()) { D.Diag(diag::err_drv_unsupported_opt_for_target) << A->getAsString(Args) << TC.getTripleString(); } diff --git a/clang/test/CodeGen/fat-lto-objects.c b/clang/test/CodeGen/fat-lto-objects.c index 36a73684e7bfe..bcbcb31e1579a 100644 --- a/clang/test/CodeGen/fat-lto-objects.c +++ b/clang/test/CodeGen/fat-lto-objects.c @@ -35,6 +35,9 @@ // RUN: %clang -cc1 -triple x86_64-unknown-linux-gnu -flto=full -ffat-lto-objects -fsplit-lto-unit -S < %s -o - \ // RUN: | FileCheck %s --check-prefixes=ASM +// RUN: %clang -cc1 -triple i386-pc-win32 -flto=full -ffat-lto-objects -fsplit-lto-unit -S < %s -o - \ +// RUN: | FileCheck %s --check-prefixes=ASM-COFF + /// Make sure that FatLTO generates .llvm.lto sections that are the same as the output from normal LTO compilations // RUN: %clang -O2 --target=x86_64-unknown-linux-gnu -fPIE -flto=full -ffat-lto-objects -c %s -o %t.fatlto.full.o // RUN: llvm-objcopy --dump-section=.llvm.lto=%t.fatlto.full.bc %t.fatlto.full.o @@ -43,6 +46,13 @@ // RUN: llvm-dis < %t.nofat.full.bc -o %t.nofat.full.ll // RUN: diff %t.fatlto.full.ll %t.nofat.full.ll +// RUN: %clang -O2 --target=i386-pc-win32 -flto=full -ffat-lto-objects -c %s -o %t.fatlto.full.coff.o +// RUN: llvm-objcopy --dump-section=.llvm.lto=%t.fatlto.full.coff.bc %t.fatlto.full.coff.o +// RUN: llvm-dis < %t.fatlto.full.coff.bc -o %t.fatlto.full.coff.ll +// RUN: %clang -O2 --target=i386-pc-win32 -flto=full -c %s -o %t.nofat.full.coff.bc +// RUN: llvm-dis < %t.nofat.full.coff.bc -o %t.nofat.full.coff.ll +// RUN: diff %t.fatlto.full.coff.ll %t.nofat.full.coff.ll + // RUN: %clang -O2 --target=x86_64-unknown-linux-gnu -fPIE -flto=thin -ffat-lto-objects -c %s -o %t.fatlto.thin.o // RUN: llvm-objcopy --dump-section=.llvm.lto=%t.fatlto.thin.bc %t.fatlto.thin.o // RUN: llvm-dis < %t.fatlto.thin.bc -o %t.fatlto.thin.ll @@ -67,6 +77,10 @@ // ASM-NEXT: .asciz "BC // ASM-NEXT: .size .Lllvm.embedded.object +// ASM-COFF: .section .llvm.lto,"ynD" +// ASM-COFF-NEXT: L_llvm.embedded.object: +// ASM-COFF-NEXT: .asciz "BC + const char* foo = "foo"; int test(void) { diff --git a/clang/test/Driver/fat-lto-objects.c b/clang/test/Driver/fat-lto-objects.c index 7b87e2b468886..84dd945e208b9 100644 --- a/clang/test/Driver/fat-lto-objects.c +++ b/clang/test/Driver/fat-lto-objects.c @@ -1,10 +1,12 @@ // RUN: %clang --target=x86_64-unknown-linux-gnu -flto -ffat-lto-objects -### %s -c 2>&1 | FileCheck %s -check-prefix=CHECK-CC +// RUN: %clang --target=i386-pc-win32 -flto -ffat-lto-objects -### %s -c 2>&1 | FileCheck %s -check-prefix=CHECK-CC // CHECK-CC: -cc1 // CHECK-CC-SAME: -emit-obj // CHECK-CC-SAME: -ffat-lto-objects /// Without -flto -S will just emit normal ASM, so we don't expect -emit-{llvm,obj} or -ffat-lto-objects to be passed to cc1. // RUN: %clang --target=x86_64-unknown-linux-gnu -ffat-lto-objects -### %s -S 2>&1 | FileCheck %s -check-prefix=CHECK-CC-S +// RUN: %clang --target=i386-pc-win32 -ffat-lto-objects -### %s -S 2>&1 | FileCheck %s -check-prefix=CHECK-CC-S // CHECK-CC-S: -cc1 // CHECK-CC-S: -S // CHECK-CC-S-NOT: -emit-obj @@ -13,35 +15,41 @@ /// When fat LTO is enabled with -S, we expect asm output and -ffat-lto-objects to be passed to cc1. // RUN: %clang --target=x86_64-unknown-linux-gnu -flto -ffat-lto-objects -### %s -S 2>&1 | FileCheck %s -check-prefix=CHECK-CC-S-LTO +// RUN: %clang --target=i386-pc-win32 -flto -ffat-lto-objects -### %s -S 2>&1 | FileCheck %s -check-prefix=CHECK-CC-S-LTO // CHECK-CC-S-LTO: -cc1 // CHECK-CC-S-NOT: -emit-llvm // CHECK-CC-S-LTO-SAME: -ffat-lto-objects /// When fat LTO is enabled with -S and -emit-llvm, we expect IR output and -ffat-lto-objects to be passed to cc1. // RUN: %clang --target=x86_64-unknown-linux-gnu -flto -ffat-lto-objects -### %s -S -emit-llvm 2>&1 | FileCheck %s -check-prefix=CHECK-CC-S-EL-LTO +// RUN: %clang --target=i386-pc-win32 -flto -ffat-lto-objects -### %s -S -emit-llvm 2>&1 | FileCheck %s -check-prefix=CHECK-CC-S-EL-LTO // CHECK-CC-S-EL-LTO: -cc1 // CHECK-CC-S-EL-LTO-SAME: -emit-llvm // CHECK-CC-S-EL-LTO-SAME: -ffat-lto-objects /// When fat LTO is enabled without -S we expect native object output and -ffat-lto-object to be passed to cc1. // RUN: %clang --target=x86_64-unknown-linux-gnu -flto -ffat-lto-objects -### %s -c 2>&1 | FileCheck %s -check-prefix=CHECK-CC-C-LTO +// RUN: %clang --target=i386-pc-win32 -flto -ffat-lto-objects -### %s -c 2>&1 | FileCheck %s -check-prefix=CHECK-CC-C-LTO // CHECK-CC-C-LTO: -cc1 // CHECK-CC-C-LTO-SAME: -emit-obj // CHECK-CC-C-LTO-SAME: -ffat-lto-objects /// When fat LTO is enabled with -c and -emit-llvm we expect bitcode output and -ffat-lto-object to be passed to cc1. // RUN: %clang --target=x86_64-unknown-linux-gnu -flto -ffat-lto-objects -### %s -c -emit-llvm 2>&1 | FileCheck %s -check-prefix=CHECK-CC-C-EL-LTO +// RUN: %clang --target=i386-pc-win32 -flto -ffat-lto-objects -### %s -c -emit-llvm 2>&1 | FileCheck %s -check-prefix=CHECK-CC-C-EL-LTO // CHECK-CC-C-EL-LTO: -cc1 // CHECK-CC-C-EL-LTO-SAME: -emit-llvm-bc // CHECK-CC-C-EL-LTO-SAME: -ffat-lto-objects /// Make sure we don't have a warning for -ffat-lto-objects being unused // RUN: %clang --target=x86_64-unknown-linux-gnu -ffat-lto-objects -fdriver-only -Werror -v %s -c 2>&1 | FileCheck %s -check-prefix=CHECK-CC-NOLTO +// RUN: %clang --target=i386-pc-win32 -ffat-lto-objects -fdriver-only -Werror -v %s -c 2>&1 | FileCheck %s -check-prefix=CHECK-CC-NOLTO // CHECK-CC-NOLTO: -cc1 // CHECK-CC-NOLTO-SAME: -emit-obj // CHECK-CC-NOLTO-NOT: -ffat-lto-objects // RUN: %clang --target=x86_64-unknown-linux-gnu -flto -ffat-lto-objects -fno-fat-lto-objects -### %s -c 2>&1 | FileCheck %s -check-prefix=CHECK-CC-NOLTO +// RUN: %clang --target=i386-pc-win32 -flto -ffat-lto-objects -fno-fat-lto-objects -### %s -c 2>&1 | FileCheck %s -check-prefix=CHECK-CC-NOLTO /// We need to pass an additional flag (--fat-lto-objects) to lld when linking w/ -flto -ffat-lto-objects /// But it should not be there when LTO is disabled w/ -fno-lto