From: Sterling Augustine Date: Tue, 19 Mar 2019 20:01:59 +0000 (+0000) Subject: Add --unwindlib=[libgcc|compiler-rt] to parallel --rtlib= [take 2] X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=6271606969e276f48c6965f31a46acf54e476e65;p=platform%2Fupstream%2Fllvm.git Add --unwindlib=[libgcc|compiler-rt] to parallel --rtlib= [take 2] "clang++ hello.cc --rtlib=compiler-rt" now can works without specifying additional unwind or exception handling libraries. This reworked version of the feature no longer modifies today's default unwind library for compiler-rt: which is nothing. Rather, a user can specify -DCLANG_DEFAULT_UNWINDLIB=libunwind when configuring the compiler. This should address the issues from the previous version. Update tests for new --unwindlib semantics. Differential Revision: https://reviews.llvm.org/D59109 llvm-svn: 356508 --- diff --git a/clang/CMakeLists.txt b/clang/CMakeLists.txt index e36babd..39d8750 100644 --- a/clang/CMakeLists.txt +++ b/clang/CMakeLists.txt @@ -266,6 +266,24 @@ if (NOT(CLANG_DEFAULT_RTLIB STREQUAL "" OR "Default runtime library to use (\"libgcc\" or \"compiler-rt\", empty for platform default)" FORCE) endif() +set(CLANG_DEFAULT_UNWINDLIB "" CACHE STRING + "Default unwind library to use (\"none\" \"libgcc\" or \"libunwind\", empty to match runtime library.)") +if (CLANG_DEFAULT_UNWINDLIB STREQUAL "") + if (CLANG_DEFAULT_RTLIB STREQUAL "libgcc") + set (CLANG_DEFAULT_UNWINDLIB "libgcc" CACHE STRING "" FORCE) + elseif (CLANG_DEFAULT_RTLIBS STREQUAL "libunwind") + set (CLANG_DEFAULT_UNWINDLIB "none" CACHE STRING "" FORCE) + endif() +endif() + +if (NOT(CLANG_DEFAULT_UNWINDLIB STREQUAL "none" OR + CLANG_DEFAULT_UNWINDLIB STREQUAL "libgcc" OR + CLANG_DEFAULT_UNWINDLIB STREQUAL "libunwind")) + message(WARNING "Resetting default unwindlib to use platform default") + set(CLANG_DEFAULT_UNWINDLIB "" CACHE STRING + "Default unwind library to use (\"none\" \"libgcc\" or \"libunwind\", empty for none)" FORCE) +endif() + set(CLANG_DEFAULT_OBJCOPY "objcopy" CACHE STRING "Default objcopy executable to use.") diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td index c822380..9885802 100644 --- a/clang/include/clang/Basic/DiagnosticDriverKinds.td +++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td @@ -51,6 +51,10 @@ def err_drv_invalid_rtlib_name : Error< "invalid runtime library name in argument '%0'">; def err_drv_unsupported_rtlib_for_platform : Error< "unsupported runtime library '%0' for platform '%1'">; +def err_drv_invalid_unwindlib_name : Error< + "invalid unwind library name in argument '%0'">; +def err_drv_incompatible_unwindlib : Error< + "--rtlib=libgcc requires --unwindlib=libgcc">; def err_drv_invalid_stdlib_name : Error< "invalid library name in argument '%0'">; def err_drv_invalid_output_with_multiple_archs : Error< diff --git a/clang/include/clang/Config/config.h.cmake b/clang/include/clang/Config/config.h.cmake index 1d62445..2d4cb74 100644 --- a/clang/include/clang/Config/config.h.cmake +++ b/clang/include/clang/Config/config.h.cmake @@ -23,6 +23,9 @@ /* Default runtime library to use. */ #define CLANG_DEFAULT_RTLIB "${CLANG_DEFAULT_RTLIB}" +/* Default unwind library to use. */ +#define CLANG_DEFAULT_UNWINDLIB "${CLANG_DEFAULT_UNWINDLIB}" + /* Default objcopy to use */ #define CLANG_DEFAULT_OBJCOPY "${CLANG_DEFAULT_OBJCOPY}" diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 0f05eff..dbcc4c0 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -2591,6 +2591,8 @@ def std_EQ : Joined<["-", "--"], "std=">, Flags<[CC1Option]>, }]>; def stdlib_EQ : Joined<["-", "--"], "stdlib=">, Flags<[CC1Option]>, HelpText<"C++ standard library to use">, Values<"libc++,libstdc++,platform">; +def unwindlib_EQ : Joined<["-", "--"], "unwindlib=">, Flags<[CC1Option]>, + HelpText<"Unwind library to use">, Values<"libgcc,unwindlib,platform">; def sub__library : JoinedOrSeparate<["-"], "sub_library">; def sub__umbrella : JoinedOrSeparate<["-"], "sub_umbrella">; def system_header_prefix : Joined<["--"], "system-header-prefix=">, diff --git a/clang/include/clang/Driver/ToolChain.h b/clang/include/clang/Driver/ToolChain.h index 24ba25a..4adf7cc 100644 --- a/clang/include/clang/Driver/ToolChain.h +++ b/clang/include/clang/Driver/ToolChain.h @@ -99,6 +99,12 @@ public: RLT_Libgcc }; + enum UnwindLibType { + UNW_None, + UNW_CompilerRT, + UNW_Libgcc + }; + enum RTTIMode { RM_Enabled, RM_Disabled, @@ -369,6 +375,10 @@ public: return ToolChain::CST_Libstdcxx; } + virtual UnwindLibType GetDefaultUnwindLibType() const { + return ToolChain::UNW_None; + } + virtual std::string getCompilerRTPath() const; virtual std::string getCompilerRT(const llvm::opt::ArgList &Args, @@ -513,6 +523,10 @@ public: // given compilation arguments. virtual CXXStdlibType GetCXXStdlibType(const llvm::opt::ArgList &Args) const; + // GetUnwindLibType - Determine the unwind library type to use with the + // given compilation arguments. + virtual UnwindLibType GetUnwindLibType(const llvm::opt::ArgList &Args) const; + /// AddClangCXXStdlibIncludeArgs - Add the clang -cc1 level arguments to set /// the include paths to use for the given C++ standard library type. virtual void diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp index 6b56271..5dff2b2 100644 --- a/clang/lib/Driver/ToolChain.cpp +++ b/clang/lib/Driver/ToolChain.cpp @@ -693,6 +693,33 @@ ToolChain::RuntimeLibType ToolChain::GetRuntimeLibType( return GetDefaultRuntimeLibType(); } +ToolChain::UnwindLibType ToolChain::GetUnwindLibType( + const ArgList &Args) const { + const Arg *A = Args.getLastArg(options::OPT_unwindlib_EQ); + StringRef LibName = A ? A->getValue() : CLANG_DEFAULT_UNWINDLIB; + + if (LibName == "none") + return ToolChain::UNW_None; + else if (LibName == "platform" || LibName == "") { + ToolChain::RuntimeLibType RtLibType = GetRuntimeLibType(Args); + if (RtLibType == ToolChain::RLT_CompilerRT) + return ToolChain::UNW_None; + else if (RtLibType == ToolChain::RLT_Libgcc) + return ToolChain::UNW_Libgcc; + } else if (LibName == "libunwind") { + if (GetRuntimeLibType(Args) == RLT_Libgcc) + getDriver().Diag(diag::err_drv_incompatible_unwindlib); + return ToolChain::UNW_CompilerRT; + } else if (LibName == "libgcc") + return ToolChain::UNW_Libgcc; + + if (A) + getDriver().Diag(diag::err_drv_invalid_unwindlib_name) + << A->getAsString(Args); + + return GetDefaultUnwindLibType(); +} + ToolChain::CXXStdlibType ToolChain::GetCXXStdlibType(const ArgList &Args) const{ const Arg *A = Args.getLastArg(options::OPT_stdlib_EQ); StringRef LibName = A ? A->getValue() : CLANG_DEFAULT_CXX_STDLIB; diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp index 2a99ce3..cff04d2 100644 --- a/clang/lib/Driver/ToolChains/CommonArgs.cpp +++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -1159,47 +1159,80 @@ bool tools::isObjCAutoRefCount(const ArgList &Args) { return Args.hasFlag(options::OPT_fobjc_arc, options::OPT_fno_objc_arc, false); } -static void AddLibgcc(const llvm::Triple &Triple, const Driver &D, - ArgStringList &CmdArgs, const ArgList &Args) { - bool isAndroid = Triple.isAndroid(); - bool isCygMing = Triple.isOSCygMing(); - bool IsIAMCU = Triple.isOSIAMCU(); - bool StaticLibgcc = Args.hasArg(options::OPT_static_libgcc) || - Args.hasArg(options::OPT_static) || - Args.hasArg(options::OPT_static_pie); - - bool SharedLibgcc = Args.hasArg(options::OPT_shared_libgcc); - bool UnspecifiedLibgcc = !StaticLibgcc && !SharedLibgcc; - - // Gcc adds libgcc arguments in various ways: - // - // gcc : -lgcc --as-needed -lgcc_s --no-as-needed - // g++ : -lgcc_s -lgcc - // gcc shared: -lgcc_s -lgcc - // g++ shared: -lgcc_s -lgcc - // gcc static: -lgcc -lgcc_eh - // g++ static: -lgcc -lgcc_eh - // gcc static-pie: -lgcc -lgcc_eh - // g++ static-pie: -lgcc -lgcc_eh - // - // Also, certain targets need additional adjustments. +enum class LibGccType { UnspecifiedLibGcc, StaticLibGcc, SharedLibGcc }; + +static LibGccType getLibGccType(const ArgList &Args) { + bool Static = Args.hasArg(options::OPT_static_libgcc) || + Args.hasArg(options::OPT_static) || + Args.hasArg(options::OPT_static_pie); + + bool Shared = Args.hasArg(options::OPT_shared_libgcc); + if (Shared) + return LibGccType::SharedLibGcc; + if (Static) + return LibGccType::StaticLibGcc; + return LibGccType::UnspecifiedLibGcc; +} - bool LibGccFirst = (D.CCCIsCC() && UnspecifiedLibgcc) || StaticLibgcc; - if (LibGccFirst) - CmdArgs.push_back("-lgcc"); +// Gcc adds libgcc arguments in various ways: +// +// gcc : -lgcc --as-needed -lgcc_s --no-as-needed +// g++ : -lgcc_s -lgcc +// gcc shared: -lgcc_s -lgcc +// g++ shared: -lgcc_s -lgcc +// gcc static: -lgcc -lgcc_eh +// g++ static: -lgcc -lgcc_eh +// gcc static-pie: -lgcc -lgcc_eh +// g++ static-pie: -lgcc -lgcc_eh +// +// Also, certain targets need additional adjustments. + +static void AddUnwindLibrary(const ToolChain &TC, const Driver &D, + ArgStringList &CmdArgs, const ArgList &Args) { + ToolChain::UnwindLibType UNW = TC.GetUnwindLibType(Args); + // Targets that don't use unwind libraries. + if (TC.getTriple().isAndroid() || TC.getTriple().isOSIAMCU() || + TC.getTriple().isOSBinFormatWasm() || + UNW == ToolChain::UNW_None) + return; - bool AsNeeded = D.CCCIsCC() && UnspecifiedLibgcc && !isAndroid && !isCygMing; + LibGccType LGT = getLibGccType(Args); + bool AsNeeded = D.CCCIsCC() && LGT == LibGccType::UnspecifiedLibGcc && + !TC.getTriple().isAndroid() && !TC.getTriple().isOSCygMing(); if (AsNeeded) CmdArgs.push_back("--as-needed"); - if ((UnspecifiedLibgcc || SharedLibgcc) && !isAndroid) - CmdArgs.push_back("-lgcc_s"); - - else if (StaticLibgcc && !isAndroid && !IsIAMCU) - CmdArgs.push_back("-lgcc_eh"); + switch (UNW) { + case ToolChain::UNW_None: + return; + case ToolChain::UNW_Libgcc: { + LibGccType LGT = getLibGccType(Args); + if (LGT == LibGccType::UnspecifiedLibGcc || LGT == LibGccType::SharedLibGcc) + CmdArgs.push_back("-lgcc_s"); + else if (LGT == LibGccType::StaticLibGcc) + CmdArgs.push_back("-lgcc_eh"); + break; + } + case ToolChain::UNW_CompilerRT: + CmdArgs.push_back("-lunwind"); + break; + } if (AsNeeded) CmdArgs.push_back("--no-as-needed"); +} + +static void AddLibgcc(const ToolChain &TC, const Driver &D, + ArgStringList &CmdArgs, const ArgList &Args) { + bool isAndroid = TC.getTriple().isAndroid(); + + LibGccType LGT = getLibGccType(Args); + bool LibGccFirst = (D.CCCIsCC() && LGT == LibGccType::UnspecifiedLibGcc) || + LGT == LibGccType::StaticLibGcc; + if (LibGccFirst) + CmdArgs.push_back("-lgcc"); + + AddUnwindLibrary(TC, D, CmdArgs, Args); if (!LibGccFirst) CmdArgs.push_back("-lgcc"); @@ -1209,7 +1242,7 @@ static void AddLibgcc(const llvm::Triple &Triple, const Driver &D, // // NOTE: This fixes a link error on Android MIPS as well. The non-static // libgcc for MIPS relies on _Unwind_Find_FDE and dl_iterate_phdr from libdl. - if (isAndroid && !StaticLibgcc) + if (isAndroid && getLibGccType(Args) != LibGccType::StaticLibGcc) CmdArgs.push_back("-ldl"); } @@ -1221,6 +1254,7 @@ void tools::AddRunTimeLibs(const ToolChain &TC, const Driver &D, switch (RLT) { case ToolChain::RLT_CompilerRT: CmdArgs.push_back(TC.getCompilerRTArgString(Args, "builtins")); + AddUnwindLibrary(TC, D, CmdArgs, Args); break; case ToolChain::RLT_Libgcc: // Make sure libgcc is not used under MSVC environment by default @@ -1232,7 +1266,7 @@ void tools::AddRunTimeLibs(const ToolChain &TC, const Driver &D, << Args.getLastArg(options::OPT_rtlib_EQ)->getValue() << "MSVC"; } } else - AddLibgcc(TC.getTriple(), D, CmdArgs, Args); + AddLibgcc(TC, D, CmdArgs, Args); break; } } diff --git a/clang/test/Driver/compiler-rt-unwind.c b/clang/test/Driver/compiler-rt-unwind.c new file mode 100644 index 0000000..00024df --- /dev/null +++ b/clang/test/Driver/compiler-rt-unwind.c @@ -0,0 +1,49 @@ +// General tests that the driver handles combinations of --rtlib=XXX and +// --unwindlib=XXX properly. +// +// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ +// RUN: --target=x86_64-unknown-linux \ +// RUN: --gcc-toolchain="" \ +// RUN: | FileCheck --check-prefix=RTLIB-EMPTY %s +// RTLIB-EMPTY: "{{.*}}lgcc" +// RTLIB-EMPTY: "{{.*}}-lgcc_s" +// +// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ +// RUN: --target=x86_64-unknown-linux -rtlib=libgcc \ +// RUN: --gcc-toolchain="" \ +// RUN: | FileCheck --check-prefix=RTLIB-GCC %s +// RTLIB-GCC: "{{.*}}lgcc" +// RTLIB-GCC: "{{.*}}lgcc_s" +// +// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ +// RUN: --target=x86_64-unknown-linux -rtlib=libgcc --unwindlib=libunwind \ +// RUN: --gcc-toolchain="" \ +// RUN: | FileCheck --check-prefix=RTLIB-GCC-UNWINDLIB-COMPILER-RT %s +// RTLIB-GCC-UNWINDLIB-COMPILER-RT: "{{.*}}lgcc" +// RTLIB-GCC-UNWINDLIB-COMPILER-RT: "{{.*}}lunwind" +// +// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ +// RUN: --target=x86_64-unknown-linux -rtlib=compiler-rt \ +// RUN: --gcc-toolchain="" \ +// RUN: | FileCheck --check-prefix=RTLIB-COMPILER-RT %s +// RTLIB-COMPILER-RT: "{{.*}}libclang_rt.builtins-x86_64.a" +// +// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ +// RUN: --target=x86_64-unknown-linux -rtlib=compiler-rt --unwindlib=libgcc \ +// RUN: --gcc-toolchain="" \ +// RUN: | FileCheck --check-prefix=RTLIB-COMPILER-RT-UNWINDLIB-GCC %s +// RTLIB-COMPILER-RT-UNWINDLIB-GCC: "{{.*}}libclang_rt.builtins-x86_64.a" +// RTLIB-COMPILER-RT-UNWINDLIB-GCC: "{{.*}}lgcc_s" +// +// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ +// RUN: --target=x86_64-unknown-linux -rtlib=compiler-rt --unwindlib=libgcc \ +// RUN: -static --gcc-toolchain="" \ +// RUN: | FileCheck --check-prefix=RTLIB-COMPILER-RT-UNWINDLIB-GCC-STATIC %s +// RTLIB-COMPILER-RT-UNWINDLIB-GCC-STATIC: "{{.*}}libclang_rt.builtins-x86_64.a" +// RTLIB-COMPILER-RT-UNWINDLIB-GCC-STATIC: "{{.*}}lgcc_eh" +// +// RUN: not %clang -no-canonical-prefixes %s -o %t.o 2> %t.err \ +// RUN: --target=x86_64-unknown-linux -rtlib=libgcc --unwindlib=libunwind \ +// RUN: --gcc-toolchain="" \ +// RUN: FileCheck --input-file=%t.err --check-prefix=RTLIB-GCC-UNWINDLIB-COMPILER_RT %s +// RTLIB-GCC-UNWINDLIB-COMPILER_RT: "{{[.|\\\n]*}}--rtlib=libgcc requires --unwindlib=libgcc"