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 @@ -274,6 +274,8 @@ if (Used.count(GV) || IsPreservedSymbol) Sym.Flags |= 1 << storage::Symbol::FB_used; + if (IsPreservedSymbol) + Sym.Flags |= 1 << storage::Symbol::FB_libcall; if (GV->isThreadLocal()) Sym.Flags |= 1 << storage::Symbol::FB_tls; if (GV->hasGlobalUnnamedAddr())