diff --git a/llvm/include/llvm/Object/IRSymtab.h b/llvm/include/llvm/Object/IRSymtab.h --- a/llvm/include/llvm/Object/IRSymtab.h +++ b/llvm/include/llvm/Object/IRSymtab.h @@ -114,6 +114,7 @@ FB_format_specific, FB_unnamed_addr, FB_executable, + FB_libcall, }; }; @@ -200,6 +201,7 @@ bool isCommon() const { return (Flags >> S::FB_common) & 1; } bool isIndirect() const { return (Flags >> S::FB_indirect) & 1; } bool isUsed() const { return (Flags >> S::FB_used) & 1; } + bool isLibCall() const { return (Flags >> S::FB_libcall) & 1; } bool isTLS() const { return (Flags >> S::FB_tls) & 1; } bool canBeOmittedFromSymbolTable() const { diff --git a/llvm/lib/LTO/LTO.cpp b/llvm/lib/LTO/LTO.cpp --- a/llvm/lib/LTO/LTO.cpp +++ b/llvm/lib/LTO/LTO.cpp @@ -667,7 +667,8 @@ // with -defsym or -wrap options, used elsewhere, e.g. it is visible to a // regular object, is referenced from llvm.compiler.used/llvm.used, or was // already recorded as being referenced from a different partition. - if (Res.LinkerRedefined || Res.VisibleToRegularObj || Sym.isUsed() || + if (Res.LinkerRedefined || Res.VisibleToRegularObj || + (Sym.isUsed() && !(Conf.Freestanding && Sym.isLibCall())) || (GlobalRes.Partition != GlobalResolution::Unknown && GlobalRes.Partition != Partition)) { GlobalRes.Partition = GlobalResolution::External; diff --git a/llvm/lib/Object/IRSymtab.cpp b/llvm/lib/Object/IRSymtab.cpp --- a/llvm/lib/Object/IRSymtab.cpp +++ b/llvm/lib/Object/IRSymtab.cpp @@ -45,10 +45,13 @@ "disable-bitcode-version-upgrade", cl::Hidden, cl::desc("Disable automatic bitcode upgrade for version mismatch")); -static const char *PreservedSymbols[] = { +static const char *LibcallSymbols[] = { #define HANDLE_LIBCALL(code, name) name, #include "llvm/IR/RuntimeLibcalls.def" #undef HANDLE_LIBCALL +}; + +static const char *PreservedSymbols[] = { // There are global variables, so put it here instead of in // RuntimeLibcalls.def. // TODO: Are there similar such variables? @@ -270,9 +273,12 @@ setStr(Sym.IRName, GV->getName()); + bool IsLibcallSymbol = llvm::is_contained(LibcallSymbols, GV->getName()); bool IsPreservedSymbol = llvm::is_contained(PreservedSymbols, GV->getName()); - if (Used.count(GV) || IsPreservedSymbol) + if (IsLibcallSymbol) + Sym.Flags |= 1 << storage::Symbol::FB_libcall; + if (Used.count(GV) || IsPreservedSymbol || IsLibcallSymbol) Sym.Flags |= 1 << storage::Symbol::FB_used; if (GV->isThreadLocal()) Sym.Flags |= 1 << storage::Symbol::FB_tls;