diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -247,6 +247,9 @@ directory (``/tmp`` on \*NIX systems, if none of the environment variables TMPDIR, TMP, and TEMP are specified). +- `-ffat-lto-objects` can now be used to emit object files with both object + code and bitcode. Previously this flag was ignored for GCC compatibility. + Removed Compiler Flags ------------------------- - The deprecated flag `-fmodules-ts` is removed. Please use ``-std=c++20`` diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def --- a/clang/include/clang/Basic/CodeGenOptions.def +++ b/clang/include/clang/Basic/CodeGenOptions.def @@ -164,6 +164,7 @@ ///< compile step. CODEGENOPT(LTOUnit, 1, 0) ///< Emit IR to support LTO unit features (CFI, whole ///< program vtable opt). +CODEGENOPT(FatLTO, 1, 0) ///< Set when -ffat-lto-objects is enabled. CODEGENOPT(EnableSplitLTOUnit, 1, 0) ///< Enable LTO unit splitting to support /// CFI and traditional whole program /// devirtualization that require whole diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -2308,6 +2308,11 @@ Flags<[CoreOption, CC1Option]>, Group, HelpText<"Write minimized bitcode to for the ThinLTO thin link only">, MarshallingInfoString>; +defm fat_lto_objects : BoolFOption<"fat-lto-objects", + CodeGenOpts<"FatLTO">, DefaultFalse, + PosFlag, + NegFlag, + BothFlags<[CC1Option], "">>; def fmacro_backtrace_limit_EQ : Joined<["-"], "fmacro-backtrace-limit=">, Group, Flags<[NoXarchOption, CC1Option, CoreOption]>, HelpText<"Set the maximum number of entries to print in a macro expansion backtrace (0 = no limit)">, @@ -5045,7 +5050,6 @@ defm reorder_blocks : BooleanFFlag<"reorder-blocks">, Group; defm branch_count_reg : BooleanFFlag<"branch-count-reg">, Group; defm default_inline : BooleanFFlag<"default-inline">, Group; -defm fat_lto_objects : BooleanFFlag<"fat-lto-objects">, Group; defm float_store : BooleanFFlag<"float-store">, Group; defm friend_injection : BooleanFFlag<"friend-injection">, Group; defm function_attribute_list : BooleanFFlag<"function-attribute-list">, Group; diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp --- a/clang/lib/CodeGen/BackendUtil.cpp +++ b/clang/lib/CodeGen/BackendUtil.cpp @@ -24,6 +24,7 @@ #include "llvm/Bitcode/BitcodeReader.h" #include "llvm/Bitcode/BitcodeWriter.h" #include "llvm/Bitcode/BitcodeWriterPass.h" +#include "llvm/Bitcode/EmbedBitcodePass.h" #include "llvm/CodeGen/RegAllocRegistry.h" #include "llvm/CodeGen/SchedulerRegistry.h" #include "llvm/CodeGen/TargetSubtargetInfo.h" @@ -1004,7 +1005,10 @@ }); } - if (IsThinLTO) { + if (CodeGenOpts.FatLTO) { + MPM = PB.buildFatLTODefaultPipeline( + Level, IsThinLTO, IsThinLTO || shouldEmitRegularLTOSummary()); + } else if (IsThinLTO) { MPM = PB.buildThinLTOPreLinkDefaultPipeline(Level); } else if (IsLTO) { MPM = PB.buildLTOPreLinkDefaultPipeline(Level); @@ -1055,6 +1059,12 @@ MPM.addPass(PrintModulePass(*OS, "", CodeGenOpts.EmitLLVMUseLists, EmitLTOSummary)); } + } else if (CodeGenOpts.FatLTO) { + // Set EnableSplitLTOUnit, since FatLTO uses a different action than + // Backend_EmitBC or Backend_EmitLL, and thus it won't be set correctly + if (!TheModule->getModuleFlag("EnableSplitLTOUnit")) + TheModule->addModuleFlag(Module::Error, "EnableSplitLTOUnit", + uint32_t(CodeGenOpts.EnableSplitLTOUnit)); } // Now that we have all of the passes ready, run them. diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -4654,8 +4654,13 @@ } case phases::Backend: { if (isUsingLTO() && TargetDeviceOffloadKind == Action::OFK_None) { - types::ID Output = - Args.hasArg(options::OPT_S) ? types::TY_LTO_IR : types::TY_LTO_BC; + types::ID Output; + if (Args.hasArg(options::OPT_S)) + Output = types::TY_LTO_IR; + else if (Args.hasArg(options::OPT_ffat_lto_objects)) + Output = types::TY_PP_Asm; + else + Output = types::TY_LTO_BC; return C.MakeAction(Input, Output); } if (isUsingLTO(/* IsOffload */ true) && diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -7294,6 +7294,14 @@ } } + if (IsUsingLTO && Args.getLastArg(options::OPT_ffat_lto_objects)) { + assert(LTOMode == LTOK_Full || LTOMode == LTOK_Thin); + CmdArgs.push_back(Args.MakeArgString( + Twine("-flto=") + (LTOMode == LTOK_Thin ? "thin" : "full"))); + CmdArgs.push_back("-flto-unit"); + CmdArgs.push_back("-ffat-lto-objects"); + } + if (Args.hasArg(options::OPT_forder_file_instrumentation)) { CmdArgs.push_back("-forder-file-instrumentation"); // Enable order file instrumentation when ThinLTO is not on. When ThinLTO is diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp --- a/clang/lib/Driver/ToolChains/CommonArgs.cpp +++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -619,6 +619,10 @@ PluginName + Suffix, Plugin); CmdArgs.push_back(Args.MakeArgString(Twine(PluginPrefix) + Plugin)); + } else { + // For LLD we need to enable fat object support + if (Args.hasArg(options::OPT_ffat_lto_objects)) + CmdArgs.push_back("-fat-lto-objects"); } const char *PluginOptPrefix = IsOSAIX ? "-bplugin_opt:" : "-plugin-opt="; diff --git a/clang/test/CodeGen/embed-lto-fatlto.c b/clang/test/CodeGen/embed-lto-fatlto.c new file mode 100644 --- /dev/null +++ b/clang/test/CodeGen/embed-lto-fatlto.c @@ -0,0 +1,17 @@ +// RUN: %clang -cc1 -triple x86_64-unknown-linux-gnu -S -flto=full -ffat-lto-objects -fsplit-lto-unit -emit-llvm < %s | FileCheck %s --check-prefixes=FULL,SPLIT +// RUN: %clang -cc1 -triple x86_64-unknown-linux-gnu -S -flto=full -ffat-lto-objects -emit-llvm < %s | FileCheck %s --check-prefixes=FULL,SPLIT + +// RUN: %clang -cc1 -triple x86_64-unknown-linux-gnu -S -flto=thin -fsplit-lto-unit -ffat-lto-objects -emit-llvm < %s | FileCheck %s --check-prefixes=THIN,SPLIT +// RUN: %clang -cc1 -triple x86_64-unknown-linux-gnu -S -flto=thin -ffat-lto-objects -emit-llvm < %s | FileCheck %s --check-prefixes=THIN,NOSPLIT + +/// Check that the ThinLTO metadata is only set false for full LTO +// FULL: !{{[0-9]+}} = !{i32 1, !"ThinLTO", i32 0} +// THIN-NOT: !{{[0-9]+}} = !{i32 1, !"ThinLTO", i32 0} + +/// Be sure we enable split LTO unints correctly under -ffat-lto-objects +// SPLIT: !{{[0-9]+}} = !{i32 1, !"EnableSplitLTOUnit", i32 1} +// NOSPLIT: !{{[0-9]+}} = !{i32 1, !"EnableSplitLTOUnit", i32 0} + +int test(void) { + return 0xabcd; +} diff --git a/clang/test/Driver/clang_f_opts.c b/clang/test/Driver/clang_f_opts.c --- a/clang/test/Driver/clang_f_opts.c +++ b/clang/test/Driver/clang_f_opts.c @@ -425,7 +425,6 @@ // CHECK-WARNING-DAG: optimization flag '-fwhole-program' is not supported // CHECK-WARNING-DAG: optimization flag '-fcaller-saves' is not supported // CHECK-WARNING-DAG: optimization flag '-freorder-blocks' is not supported -// CHECK-WARNING-DAG: optimization flag '-ffat-lto-objects' is not supported // CHECK-WARNING-DAG: optimization flag '-fmerge-constants' is not supported // CHECK-WARNING-DAG: optimization flag '-finline-small-functions' is not supported // CHECK-WARNING-DAG: optimization flag '-ftree-dce' is not supported diff --git a/clang/test/Driver/fatlto-objects.c b/clang/test/Driver/fatlto-objects.c new file mode 100644 --- /dev/null +++ b/clang/test/Driver/fatlto-objects.c @@ -0,0 +1,19 @@ +// REQUIRES: x86_64-linux +// RUN: %clang -target=x86_64-unknown-linux-gnu -flto -ffat-lto-objects -fintegrated-as -### %s -c 2>&1 | FileCheck %s -check-prefix=CHECK-CC +// CHECK-CC: -cc1 +// CHECK-CC: -emit-obj +// CHECK-CC: -ffat-lto-objects + +// RUN: %clang -target=x86_64-unknown-linux-gnu -ffat-lto-objects -fintegrated-as -### %s -c 2>&1 | FileCheck %s -check-prefix=CHECK-CC-NOLTO +// CHECK-CC-NOLTO: -cc1 +// CHECK-CC-NOLTO: -emit-obj +// CHECK-CC-NOLTO-NOT: -ffat-lto-objects + +/// We need to pass an additional flag to lld when linking w/ -flto -ffat-lto-objects +/// But it should not be there when LTO is disabled w/ -fno-lto +// RUN: %clang --target=x86_64-unknown-linux-gnu --sysroot=%S/Inputs/basic_cross_linux_tree %s \ +// RUN: -fuse-ld=lld -flto -ffat-lto-objects -### 2>&1 | FileCheck --check-prefix=LTO %s +// RUN: %clang --target=x86_64-unknown-linux-gnu --sysroot=%S/Inputs/basic_cross_linux_tree %s \ +// RUN: -fuse-ld=lld -fno-lto -ffat-lto-objects -### 2>&1 | FileCheck --check-prefix=NOLTO %s +// LTO: -fat-lto-objects +// NOLTO-NOT: -fat-lto-objects diff --git a/clang/test/Driver/fatlto.c b/clang/test/Driver/fatlto.c new file mode 100644 --- /dev/null +++ b/clang/test/Driver/fatlto.c @@ -0,0 +1 @@ +