Index: include/clang/Driver/ToolChain.h =================================================================== --- include/clang/Driver/ToolChain.h +++ include/clang/Driver/ToolChain.h @@ -363,7 +363,8 @@ /// IsUnwindTablesDefault - Does this tool chain use -funwind-tables /// by default. - virtual bool IsUnwindTablesDefault(const llvm::opt::ArgList &Args) const; + virtual bool IsUnwindTablesDefault(const llvm::opt::ArgList &Args, + types::ID InputType) const; /// \brief Test whether this toolchain defaults to PIC. virtual bool isPICDefault() const = 0; Index: lib/Driver/ToolChain.cpp =================================================================== --- lib/Driver/ToolChain.cpp +++ lib/Driver/ToolChain.cpp @@ -231,7 +231,8 @@ return Input.getFilename(); } -bool ToolChain::IsUnwindTablesDefault(const ArgList &Args) const { +bool ToolChain::IsUnwindTablesDefault(const ArgList &Args, + types::ID InputType) const { return false; } Index: lib/Driver/ToolChains/Arch/ARM.h =================================================================== --- lib/Driver/ToolChains/Arch/ARM.h +++ lib/Driver/ToolChains/Arch/ARM.h @@ -59,6 +59,8 @@ int getARMSubArchVersionNumber(const llvm::Triple &Triple); bool isARMMProfile(const llvm::Triple &Triple); +bool ARMNeedUnwindTable(const llvm::opt::ArgList &Args, bool isCXX); + } // end namespace arm } // end namespace tools } // end namespace driver Index: lib/Driver/ToolChains/Arch/ARM.cpp =================================================================== --- lib/Driver/ToolChains/Arch/ARM.cpp +++ lib/Driver/ToolChains/Arch/ARM.cpp @@ -599,3 +599,9 @@ if (arm::getARMSubArchVersionNumber(Triple) >= 7 || arm::isARMMProfile(Triple)) CmdArgs.push_back("--be8"); } + +bool arm::ARMNeedUnwindTable(const ArgList &Args, bool isCXX) { + // Emit the uwtable attribute to generate an unwind table when exceptions are + // supported, even the functions that do not throw still need a .cantunwind directive. + return Args.hasFlag(options::OPT_fexceptions, options::OPT_fno_exceptions, isCXX); +} Index: lib/Driver/ToolChains/BareMetal.h =================================================================== --- lib/Driver/ToolChains/BareMetal.h +++ lib/Driver/ToolChains/BareMetal.h @@ -32,6 +32,8 @@ public: bool useIntegratedAs() const override { return true; } + bool IsUnwindTablesDefault(const llvm::opt::ArgList &Args, + types::ID InputType) const override; bool isCrossCompiling() const override { return true; } bool isPICDefault() const override { return false; } bool isPIEDefault() const override { return false; } Index: lib/Driver/ToolChains/BareMetal.cpp =================================================================== --- lib/Driver/ToolChains/BareMetal.cpp +++ lib/Driver/ToolChains/BareMetal.cpp @@ -13,6 +13,7 @@ #include "InputInfo.h" #include "Gnu.h" +#include "Arch/ARM.h" #include "clang/Basic/VirtualFileSystem.h" #include "clang/Driver/Compilation.h" #include "clang/Driver/Driver.h" @@ -200,3 +201,15 @@ Args.MakeArgString(TC.GetLinkerPath()), CmdArgs, Inputs)); } + +bool BareMetal::IsUnwindTablesDefault(const ArgList &Args, types::ID InputType) const { + switch (getArch()) { + case llvm::Triple::arm: + case llvm::Triple::armeb: + case llvm::Triple::thumb: + case llvm::Triple::thumbeb: + return tools::arm::ARMNeedUnwindTable(Args, types::isCXX(InputType)); + default: + return false; + } +} Index: lib/Driver/ToolChains/Clang.cpp =================================================================== --- lib/Driver/ToolChains/Clang.cpp +++ lib/Driver/ToolChains/Clang.cpp @@ -3512,7 +3512,7 @@ bool AsynchronousUnwindTables = Args.hasFlag(options::OPT_fasynchronous_unwind_tables, options::OPT_fno_asynchronous_unwind_tables, - (getToolChain().IsUnwindTablesDefault(Args) || + (getToolChain().IsUnwindTablesDefault(Args, Input.getType()) || getToolChain().getSanitizerArgs().needsUnwindTables()) && !Freestanding); if (Args.hasFlag(options::OPT_funwind_tables, options::OPT_fno_unwind_tables, Index: lib/Driver/ToolChains/CrossWindows.h =================================================================== --- lib/Driver/ToolChains/CrossWindows.h +++ lib/Driver/ToolChains/CrossWindows.h @@ -56,7 +56,7 @@ const llvm::opt::ArgList &Args); bool IsIntegratedAssemblerDefault() const override { return true; } - bool IsUnwindTablesDefault(const llvm::opt::ArgList &Args) const override; + bool IsUnwindTablesDefault(const llvm::opt::ArgList &Args, types::ID InputType) const override; bool isPICDefault() const override; bool isPIEDefault() const override; bool isPICDefaultForced() const override; Index: lib/Driver/ToolChains/CrossWindows.cpp =================================================================== --- lib/Driver/ToolChains/CrossWindows.cpp +++ lib/Driver/ToolChains/CrossWindows.cpp @@ -8,6 +8,7 @@ //===----------------------------------------------------------------------===// #include "CrossWindows.h" +#include "Arch/ARM.h" #include "CommonArgs.h" #include "clang/Driver/Compilation.h" #include "clang/Driver/Driver.h" @@ -209,10 +210,20 @@ const llvm::opt::ArgList &Args) : Generic_GCC(D, T, Args) {} -bool CrossWindowsToolChain::IsUnwindTablesDefault(const ArgList &Args) const { +bool CrossWindowsToolChain::IsUnwindTablesDefault(const ArgList &Args, types::ID InputType) const { // FIXME: all non-x86 targets need unwind tables, however, LLVM currently does // not know how to emit them. - return getArch() == llvm::Triple::x86_64; + switch (getArch()) { + case llvm::Triple::arm: + case llvm::Triple::armeb: + case llvm::Triple::thumb: + case llvm::Triple::thumbeb: + return tools::arm::ARMNeedUnwindTable(Args, types::isCXX(InputType)); + case llvm::Triple::x86_64: + return true; + default: + return false; + } } bool CrossWindowsToolChain::isPICDefault() const { Index: lib/Driver/ToolChains/Darwin.h =================================================================== --- lib/Driver/ToolChains/Darwin.h +++ lib/Driver/ToolChains/Darwin.h @@ -233,7 +233,7 @@ bool UseObjCMixedDispatch() const override { return true; } - bool IsUnwindTablesDefault(const llvm::opt::ArgList &Args) const override; + bool IsUnwindTablesDefault(const llvm::opt::ArgList &Args, types::ID InputType) const override; RuntimeLibType GetDefaultRuntimeLibType() const override { return ToolChain::RLT_CompilerRT; Index: lib/Driver/ToolChains/Darwin.cpp =================================================================== --- lib/Driver/ToolChains/Darwin.cpp +++ lib/Driver/ToolChains/Darwin.cpp @@ -2053,7 +2053,7 @@ return DAL; } -bool MachO::IsUnwindTablesDefault(const ArgList &Args) const { +bool MachO::IsUnwindTablesDefault(const ArgList &Args, types::ID InputType) const { // Unwind tables are not emitted if -fno-exceptions is supplied (except when // targeting x86_64). return getArch() == llvm::Triple::x86_64 || Index: lib/Driver/ToolChains/Fuchsia.h =================================================================== --- lib/Driver/ToolChains/Fuchsia.h +++ lib/Driver/ToolChains/Fuchsia.h @@ -50,8 +50,9 @@ CXXStdlibType GetDefaultCXXStdlibType() const override { return ToolChain::CST_Libcxx; } - bool IsUnwindTablesDefault(const llvm::opt::ArgList &Args) const override { - return true; + bool IsUnwindTablesDefault(const llvm::opt::ArgList &Args, + types::ID InputType) const override { + return true; } bool isPICDefault() const override { return false; } bool isPIEDefault() const override { return true; } Index: lib/Driver/ToolChains/Gnu.h =================================================================== --- lib/Driver/ToolChains/Gnu.h +++ lib/Driver/ToolChains/Gnu.h @@ -282,7 +282,8 @@ void printVerboseInfo(raw_ostream &OS) const override; - bool IsUnwindTablesDefault(const llvm::opt::ArgList &Args) const override; + bool IsUnwindTablesDefault(const llvm::opt::ArgList &Args, + types::ID InputType) const override; bool isPICDefault() const override; bool isPIEDefault() const override; bool isPICDefaultForced() const override; Index: lib/Driver/ToolChains/Gnu.cpp =================================================================== --- lib/Driver/ToolChains/Gnu.cpp +++ lib/Driver/ToolChains/Gnu.cpp @@ -2301,8 +2301,18 @@ CudaInstallation.print(OS); } -bool Generic_GCC::IsUnwindTablesDefault(const ArgList &Args) const { - return getArch() == llvm::Triple::x86_64; +bool Generic_GCC::IsUnwindTablesDefault(const ArgList &Args, types::ID InputType) const { + switch (getArch()) { + case llvm::Triple::arm: + case llvm::Triple::armeb: + case llvm::Triple::thumb: + case llvm::Triple::thumbeb: + return tools::arm::ARMNeedUnwindTable(Args, types::isCXX(InputType)); + case llvm::Triple::x86_64: + return true; + default: + return false; + } } bool Generic_GCC::isPICDefault() const { Index: lib/Driver/ToolChains/Linux.h =================================================================== --- lib/Driver/ToolChains/Linux.h +++ lib/Driver/ToolChains/Linux.h @@ -36,6 +36,8 @@ void AddIAMCUIncludeArgs(const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args) const override; bool isPIEDefault() const override; + bool IsUnwindTablesDefault(const llvm::opt::ArgList &Args, + types::ID InputType) const override; SanitizerMask getSupportedSanitizers() const override; void addProfileRTLibs(const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs) const override; Index: lib/Driver/ToolChains/Linux.cpp =================================================================== --- lib/Driver/ToolChains/Linux.cpp +++ lib/Driver/ToolChains/Linux.cpp @@ -895,3 +895,17 @@ Twine("-u", llvm::getInstrProfRuntimeHookVarName()))); ToolChain::addProfileRTLibs(Args, CmdArgs); } + +bool Linux::IsUnwindTablesDefault(const ArgList &Args, types::ID InputType) const { + switch (getArch()) { + case llvm::Triple::arm: + case llvm::Triple::armeb: + case llvm::Triple::thumb: + case llvm::Triple::thumbeb: + return tools::arm::ARMNeedUnwindTable(Args, types::isCXX(InputType)); + case llvm::Triple::x86_64: + return true; + default: + return false; + } +} Index: lib/Driver/ToolChains/MSVC.h =================================================================== --- lib/Driver/ToolChains/MSVC.h +++ lib/Driver/ToolChains/MSVC.h @@ -73,7 +73,8 @@ Action::OffloadKind DeviceOffloadKind) const override; bool IsIntegratedAssemblerDefault() const override; - bool IsUnwindTablesDefault(const llvm::opt::ArgList &Args) const override; + bool IsUnwindTablesDefault(const llvm::opt::ArgList &Args, + types::ID InputType) const override; bool isPICDefault() const override; bool isPIEDefault() const override; bool isPICDefaultForced() const override; Index: lib/Driver/ToolChains/MSVC.cpp =================================================================== --- lib/Driver/ToolChains/MSVC.cpp +++ lib/Driver/ToolChains/MSVC.cpp @@ -10,6 +10,7 @@ #include "MSVC.h" #include "CommonArgs.h" #include "Darwin.h" +#include "Arch/ARM.h" #include "clang/Basic/CharInfo.h" #include "clang/Basic/Version.h" #include "clang/Driver/Compilation.h" @@ -707,7 +708,7 @@ return true; } -bool MSVCToolChain::IsUnwindTablesDefault(const ArgList &Args) const { +bool MSVCToolChain::IsUnwindTablesDefault(const ArgList &Args, types::ID InputType) const { // Emit unwind tables by default on Win64. All non-x86_32 Windows platforms // such as ARM and PPC actually require unwind tables, but LLVM doesn't know // how to generate them yet. @@ -716,7 +717,17 @@ if (getTriple().isOSBinFormatMachO()) return false; - return getArch() == llvm::Triple::x86_64; + switch (getArch()) { + case llvm::Triple::arm: + case llvm::Triple::armeb: + case llvm::Triple::thumb: + case llvm::Triple::thumbeb: + return tools::arm::ARMNeedUnwindTable(Args, types::isCXX(InputType)); + case llvm::Triple::x86_64: + return true; + default: + return false; + } } bool MSVCToolChain::isPICDefault() const { Index: lib/Driver/ToolChains/MinGW.h =================================================================== --- lib/Driver/ToolChains/MinGW.h +++ lib/Driver/ToolChains/MinGW.h @@ -60,7 +60,7 @@ const llvm::opt::ArgList &Args); bool IsIntegratedAssemblerDefault() const override; - bool IsUnwindTablesDefault(const llvm::opt::ArgList &Args) const override; + bool IsUnwindTablesDefault(const llvm::opt::ArgList &Args, types::ID InputType) const override; bool isPICDefault() const override; bool isPIEDefault() const override; bool isPICDefaultForced() const override; Index: lib/Driver/ToolChains/MinGW.cpp =================================================================== --- lib/Driver/ToolChains/MinGW.cpp +++ lib/Driver/ToolChains/MinGW.cpp @@ -8,6 +8,7 @@ //===----------------------------------------------------------------------===// #include "MinGW.h" +#include "Arch/ARM.h" #include "InputInfo.h" #include "CommonArgs.h" #include "clang/Driver/Compilation.h" @@ -353,8 +354,18 @@ return new tools::MinGW::Linker(*this); } -bool toolchains::MinGW::IsUnwindTablesDefault(const ArgList &Args) const { - return getArch() == llvm::Triple::x86_64; +bool toolchains::MinGW::IsUnwindTablesDefault(const ArgList &Args, types::ID InputType) const { + switch (getArch()) { + case llvm::Triple::arm: + case llvm::Triple::armeb: + case llvm::Triple::thumb: + case llvm::Triple::thumbeb: + return tools::arm::ARMNeedUnwindTable(Args, types::isCXX(InputType)); + case llvm::Triple::x86_64: + return true; + default: + return false; + } } bool toolchains::MinGW::isPICDefault() const { Index: lib/Driver/ToolChains/NetBSD.h =================================================================== --- lib/Driver/ToolChains/NetBSD.h +++ lib/Driver/ToolChains/NetBSD.h @@ -65,7 +65,7 @@ const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args) const override; - bool IsUnwindTablesDefault(const llvm::opt::ArgList &Args) const override { + bool IsUnwindTablesDefault(const llvm::opt::ArgList &Args, types::ID InputType) const override { return true; } Index: test/Driver/arm-unwind.c =================================================================== --- /dev/null +++ test/Driver/arm-unwind.c @@ -0,0 +1,9 @@ +// Do not add function attribute "uwtable" for arm ehabi targets for C mode. + +// RUN: %clang -target arm-none-eabi -### -S %s -o %t.s 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-EABI %s +// CHECK-EABI-NOT: -munwind-tables + +// RUN: %clang -target arm-linux-gnueabihf -### -S %s -o %t.s 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-GNU %s +// CHECK-GNU-NOT: -munwind-tables Index: test/Driver/arm-unwind.cpp =================================================================== --- /dev/null +++ test/Driver/arm-unwind.cpp @@ -0,0 +1,9 @@ +// Add function attribute "uwtable" for arm ehabi targets in C++. + +// RUN: %clang -target arm-none-eabi -### -S %s -o %t.s 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-EABI %s +// CHECK-EABI: -munwind-tables + +// RUN: %clang -target arm-linux-gnueabihf -### -S %s -o %t.s 2>&1 \ +// RUN: | FileCheck --check-prefix=CHECK-GNU %s +// CHECK-GNU: -munwind-tables