[llvm] r191922 - Optimize linkonce_odr unnamed_addr functions during LTO.

Richard Smith richard at metafoo.co.uk
Thu Oct 3 16:38:11 PDT 2013


On Thu, Oct 3, 2013 at 11:29 AM, Rafael Espindola <
rafael.espindola at gmail.com> wrote:

> Author: rafael
> Date: Thu Oct  3 13:29:09 2013
> New Revision: 191922
>
> URL: http://llvm.org/viewvc/llvm-project?rev=191922&view=rev
> Log:
> Optimize linkonce_odr unnamed_addr functions during LTO.
>
> Generalize the API so we can distinguish symbols that are needed just for
> a DSO
> symbol table from those that are used from some native .o.
>
> The symbols that are only wanted for the dso symbol table can be dropped if
> llvm can prove every other dso has a copy (linkonce_odr) and the address
> is not
> important (unnamed_addr).
>
> Modified:
>     llvm/trunk/include/llvm-c/lto.h
>     llvm/trunk/include/llvm/LTO/LTOCodeGenerator.h
>     llvm/trunk/include/llvm/Transforms/IPO.h
>     llvm/trunk/lib/LTO/LTOCodeGenerator.cpp
>     llvm/trunk/lib/Transforms/IPO/IPO.cpp
>     llvm/trunk/lib/Transforms/IPO/Internalize.cpp
>     llvm/trunk/lib/Transforms/IPO/PassManagerBuilder.cpp
>     llvm/trunk/test/LTO/cfi_endproc.ll
>     llvm/trunk/test/Transforms/Internalize/lists.ll
>     llvm/trunk/tools/gold/gold-plugin.cpp
>     llvm/trunk/tools/llvm-lto/llvm-lto.cpp
>     llvm/trunk/tools/lto/lto.cpp
>
> Modified: llvm/trunk/include/llvm-c/lto.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm-c/lto.h?rev=191922&r1=191921&r2=191922&view=diff
>
> ==============================================================================
> --- llvm/trunk/include/llvm-c/lto.h (original)
> +++ llvm/trunk/include/llvm-c/lto.h Thu Oct  3 13:29:09 2013
> @@ -29,7 +29,7 @@
>   * @{
>   */
>
> -#define LTO_API_VERSION 4
> +#define LTO_API_VERSION 5
>
>  typedef enum {
>      LTO_SYMBOL_ALIGNMENT_MASK              = 0x0000001F, /* log2 of
> alignment */
> @@ -253,13 +253,21 @@ lto_codegen_set_assembler_args(lto_code_
>                                 int nargs);
>
>  /**
> - * Adds to a list of all global symbols that must exist in the final
> - * generated code.  If a function is not listed, it might be
> - * inlined into every usage and optimized away.
> + * Tells LTO optimization passes that this symbol must be preserved
> + * because it is referenced by native code or a command line option.
>   */
>  extern void
>  lto_codegen_add_must_preserve_symbol(lto_code_gen_t cg, const char*
> symbol);
>
> +
> +/**
> + * Tells LTO optimization passes that a dynamic shared library is being
> + * built and this symbol may be exported. Unless IR semantics allow the
> symbol
> + * to be made local to the library, it should remain so it can be
> exported by
> + * the shared library.
> + */
> +extern void lto_codegen_add_dso_symbol(lto_code_gen_t cg, const char
> *symbol);
> +
>  /**
>   * Writes a new object file at the specified path that contains the
>   * merged contents of all modules added so far.
>
> Modified: llvm/trunk/include/llvm/LTO/LTOCodeGenerator.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/LTO/LTOCodeGenerator.h?rev=191922&r1=191921&r2=191922&view=diff
>
> ==============================================================================
> --- llvm/trunk/include/llvm/LTO/LTOCodeGenerator.h (original)
> +++ llvm/trunk/include/llvm/LTO/LTOCodeGenerator.h Thu Oct  3 13:29:09 2013
> @@ -73,6 +73,10 @@ struct LTOCodeGenerator {
>
>    void addMustPreserveSymbol(const char *sym) { MustPreserveSymbols[sym]
> = 1; }
>
> +  void addDSOSymbol(const char* Sym) {
> +    DSOSymbols[Sym] = 1;
> +  }
> +
>    // To pass options to the driver and optimization passes. These options
> are
>    // not necessarily for debugging purpose (The function name is
> misleading).
>    // This function should be called before LTOCodeGenerator::compilexxx(),
> @@ -126,6 +130,7 @@ private:
>    void applyScopeRestrictions();
>    void applyRestriction(llvm::GlobalValue &GV,
>                          std::vector<const char*> &MustPreserveList,
> +                        std::vector<const char*> &SymtabList,
>                          llvm::SmallPtrSet<llvm::GlobalValue*, 8> &AsmUsed,
>                          llvm::Mangler &Mangler);
>    bool determineTarget(std::string &errMsg);
> @@ -138,6 +143,7 @@ private:
>    bool EmitDwarfDebugInfo;
>    bool ScopeRestrictionsDone;
>    lto_codegen_model CodeModel;
> +  StringSet DSOSymbols;
>    StringSet MustPreserveSymbols;
>    StringSet AsmUndefinedRefs;
>    llvm::MemoryBuffer *NativeObjectFile;
>
> Modified: llvm/trunk/include/llvm/Transforms/IPO.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/IPO.h?rev=191922&r1=191921&r2=191922&view=diff
>
> ==============================================================================
> --- llvm/trunk/include/llvm/Transforms/IPO.h (original)
> +++ llvm/trunk/include/llvm/Transforms/IPO.h Thu Oct  3 13:29:09 2013
> @@ -104,12 +104,32 @@ Pass *createPruneEHPass();
>
>
>  //===----------------------------------------------------------------------===//
>  /// createInternalizePass - This pass loops over all of the functions in
> the
> -/// input module, internalizing all globals (functions and variables) not
> in the
> -/// given exportList.
> +/// input module, internalizing all globals (functions and variables) it
> can.
> +////
> +/// The symbols in \p ExportList are never internalized.
> +///
> +/// The symbol in DSOList are internalized if it is safe to drop them from
> +/// the symbol table.
> +///
> +/// For example of the difference, consider a dynamic library being built
> from
> +/// two translation units. The first one compiled to a native object
> +/// (ELF/MachO/COFF) and second one compiled to IL. Translation unit A
> has a
> +/// copy of linkonce_odr unnamed_addr function F. The translation unit B
> has a
> +/// copy of the linkonce_odr unnamed_addr functions F and G.
> +///
> +/// Assume the linker decides to keep the copy of F in B. This means that
> LLVM
> +/// must produce F in the object file it passes to the linker, otherwise
> we
> +/// will have an undefined reference. For G the situation is different.
> The
> +/// linker puts the function in the DSOList, since it is only wanted for
> the
> +/// symbol table. With this information internalize can now reason that
> since
> +/// the function is a linkonce_odr and its address is not important, it
> can be
> +/// omitted. Any other shared library needing this function will have a
> copy of
> +/// it.
>  ///
>  /// Note that commandline options that are used with the above function
> are not
>  /// used now!
> -ModulePass *createInternalizePass(ArrayRef<const char *> ExportList);
> +ModulePass *createInternalizePass(ArrayRef<const char *> ExportList,
> +                                  ArrayRef<const char *> DSOList);
>  /// createInternalizePass - Same as above, but with an empty exportList.
>  ModulePass *createInternalizePass();
>
>
> Modified: llvm/trunk/lib/LTO/LTOCodeGenerator.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/LTO/LTOCodeGenerator.cpp?rev=191922&r1=191921&r2=191922&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/LTO/LTOCodeGenerator.cpp (original)
> +++ llvm/trunk/lib/LTO/LTOCodeGenerator.cpp Thu Oct  3 13:29:09 2013
> @@ -310,6 +310,7 @@ bool LTOCodeGenerator::determineTarget(s
>  void LTOCodeGenerator::
>  applyRestriction(GlobalValue &GV,
>                   std::vector<const char*> &MustPreserveList,
> +                 std::vector<const char*> &DSOList,
>                   SmallPtrSet<GlobalValue*, 8> &AsmUsed,
>                   Mangler &Mangler) {
>    SmallString<64> Buffer;
> @@ -319,6 +320,8 @@ applyRestriction(GlobalValue &GV,
>      return;
>    if (MustPreserveSymbols.count(Buffer))
>      MustPreserveList.push_back(GV.getName().data());
> +  if (DSOSymbols.count(Buffer))
> +    DSOList.push_back(GV.getName().data());
>    if (AsmUndefinedRefs.count(Buffer))
>      AsmUsed.insert(&GV);
>  }
> @@ -348,17 +351,18 @@ void LTOCodeGenerator::applyScopeRestric
>                       NULL);
>    Mangler Mangler(MContext, TargetMach);
>    std::vector<const char*> MustPreserveList;
> +  std::vector<const char*> DSOList;
>    SmallPtrSet<GlobalValue*, 8> AsmUsed;
>
>    for (Module::iterator f = mergedModule->begin(),
>           e = mergedModule->end(); f != e; ++f)
> -    applyRestriction(*f, MustPreserveList, AsmUsed, Mangler);
> +    applyRestriction(*f, MustPreserveList, DSOList, AsmUsed, Mangler);
>    for (Module::global_iterator v = mergedModule->global_begin(),
>           e = mergedModule->global_end(); v !=  e; ++v)
> -    applyRestriction(*v, MustPreserveList, AsmUsed, Mangler);
> +    applyRestriction(*v, MustPreserveList, DSOList, AsmUsed, Mangler);
>    for (Module::alias_iterator a = mergedModule->alias_begin(),
>           e = mergedModule->alias_end(); a != e; ++a)
> -    applyRestriction(*a, MustPreserveList, AsmUsed, Mangler);
> +    applyRestriction(*a, MustPreserveList, DSOList, AsmUsed, Mangler);
>
>    GlobalVariable *LLVMCompilerUsed =
>      mergedModule->getGlobalVariable("llvm.compiler.used");
> @@ -386,7 +390,7 @@ void LTOCodeGenerator::applyScopeRestric
>      LLVMCompilerUsed->setSection("llvm.metadata");
>    }
>
> -  passes.add(createInternalizePass(MustPreserveList));
> +  passes.add(createInternalizePass(MustPreserveList, DSOList));
>
>    // apply scope restrictions
>    passes.run(*mergedModule);
>
> Modified: llvm/trunk/lib/Transforms/IPO/IPO.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/IPO.cpp?rev=191922&r1=191921&r2=191922&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/Transforms/IPO/IPO.cpp (original)
> +++ llvm/trunk/lib/Transforms/IPO/IPO.cpp Thu Oct  3 13:29:09 2013
> @@ -98,7 +98,7 @@ void LLVMAddInternalizePass(LLVMPassMana
>    std::vector<const char *> Export;
>    if (AllButMain)
>      Export.push_back("main");
> -  unwrap(PM)->add(createInternalizePass(Export));
> +  unwrap(PM)->add(createInternalizePass(Export, None));
>  }
>
>  void LLVMAddStripDeadPrototypesPass(LLVMPassManagerRef PM) {
>
> Modified: llvm/trunk/lib/Transforms/IPO/Internalize.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/Internalize.cpp?rev=191922&r1=191921&r2=191922&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/Transforms/IPO/Internalize.cpp (original)
> +++ llvm/trunk/lib/Transforms/IPO/Internalize.cpp Thu Oct  3 13:29:09 2013
> @@ -44,13 +44,20 @@ APIList("internalize-public-api-list", c
>          cl::desc("A list of symbol names to preserve"),
>          cl::CommaSeparated);
>
> +static cl::list<std::string>
> +DSOList("internalize-dso-list", cl::value_desc("list"),
> +        cl::desc("A list of symbol names need for a dso symbol table"),
> +        cl::CommaSeparated);
> +
>  namespace {
>    class InternalizePass : public ModulePass {
>      std::set<std::string> ExternalNames;
> +    std::set<std::string> DSONames;
>    public:
>      static char ID; // Pass identification, replacement for typeid
>      explicit InternalizePass();
> -    explicit InternalizePass(ArrayRef<const char *> ExportList);
> +    explicit InternalizePass(ArrayRef<const char *> ExportList,
> +                             ArrayRef<const char *> DSOList);
>      void LoadFile(const char *Filename);
>      virtual bool runOnModule(Module &M);
>
> @@ -71,15 +78,21 @@ InternalizePass::InternalizePass()
>    if (!APIFile.empty())           // If a filename is specified, use it.
>      LoadFile(APIFile.c_str());
>    ExternalNames.insert(APIList.begin(), APIList.end());
> +  DSONames.insert(DSOList.begin(), DSOList.end());
>  }
>
> -InternalizePass::InternalizePass(ArrayRef<const char *> ExportList)
> +InternalizePass::InternalizePass(ArrayRef<const char *> ExportList,
> +                                 ArrayRef<const char *> DSOList)
>    : ModulePass(ID){
>    initializeInternalizePassPass(*PassRegistry::getPassRegistry());
>    for(ArrayRef<const char *>::const_iterator itr = ExportList.begin();
>          itr != ExportList.end(); itr++) {
>      ExternalNames.insert(*itr);
>    }
> +  for(ArrayRef<const char *>::const_iterator itr = DSOList.begin();
> +        itr != DSOList.end(); itr++) {
> +    DSONames.insert(*itr);
> +  }
>  }
>
>  void InternalizePass::LoadFile(const char *Filename) {
> @@ -99,7 +112,8 @@ void InternalizePass::LoadFile(const cha
>  }
>
>  static bool shouldInternalize(const GlobalValue &GV,
> -                              const std::set<std::string> &ExternalNames)
> {
> +                              const std::set<std::string> &ExternalNames,
> +                              const std::set<std::string> &DSONames) {
>    // Function must be defined here
>    if (GV.isDeclaration())
>      return false;
> @@ -116,7 +130,20 @@ static bool shouldInternalize(const Glob
>    if (ExternalNames.count(GV.getName()))
>      return false;
>
> -  return true;
> +  // Not needed for the symbol table?
> +  if (!DSONames.count(GV.getName()))
> +    return true;
> +
> +  // Not a linkonce. Someone can depend on it being on the symbol table.
> +  if (!GV.hasLinkOnceLinkage())
> +    return false;
> +
> +  // The address is not important, we can hide it.
> +  if (GV.hasUnnamedAddr())
> +    return true;
> +
> +  // FIXME: Check if the address is used.
> +  return false;
>  }
>
>  bool InternalizePass::runOnModule(Module &M) {
> @@ -145,7 +172,7 @@ bool InternalizePass::runOnModule(Module
>    // Mark all functions not in the api as internal.
>    // FIXME: maybe use private linkage?
>    for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) {
> -    if (!shouldInternalize(*I, ExternalNames))
> +    if (!shouldInternalize(*I, ExternalNames, DSONames))
>        continue;
>
>      I->setLinkage(GlobalValue::InternalLinkage);
> @@ -182,7 +209,7 @@ bool InternalizePass::runOnModule(Module
>    // FIXME: maybe use private linkage?
>    for (Module::global_iterator I = M.global_begin(), E = M.global_end();
>         I != E; ++I) {
> -    if (!shouldInternalize(*I, ExternalNames))
> +    if (!shouldInternalize(*I, ExternalNames, DSONames))
>        continue;
>
>      I->setLinkage(GlobalValue::InternalLinkage);
> @@ -194,7 +221,7 @@ bool InternalizePass::runOnModule(Module
>    // Mark all aliases that are not in the api as internal as well.
>    for (Module::alias_iterator I = M.alias_begin(), E = M.alias_end();
>         I != E; ++I) {
> -    if (!shouldInternalize(*I, ExternalNames))
> +    if (!shouldInternalize(*I, ExternalNames, DSONames))
>        continue;
>
>      I->setLinkage(GlobalValue::InternalLinkage);
> @@ -210,6 +237,7 @@ ModulePass *llvm::createInternalizePass(
>    return new InternalizePass();
>  }
>
> -ModulePass *llvm::createInternalizePass(ArrayRef<const char *>
> ExportList) {
> -  return new InternalizePass(ExportList);
> +ModulePass *llvm::createInternalizePass(ArrayRef<const char *> ExportList,
> +                                        ArrayRef<const char *> DSOList) {
> +  return new InternalizePass(ExportList, DSOList);
>  }
>
> Modified: llvm/trunk/lib/Transforms/IPO/PassManagerBuilder.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/PassManagerBuilder.cpp?rev=191922&r1=191921&r2=191922&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/Transforms/IPO/PassManagerBuilder.cpp (original)
> +++ llvm/trunk/lib/Transforms/IPO/PassManagerBuilder.cpp Thu Oct  3
> 13:29:09 2013
> @@ -277,7 +277,7 @@ void PassManagerBuilder::populateLTOPass
>    // for a main function.  If main is defined, mark all other functions
>    // internal.
>    if (Internalize)
> -    PM.add(createInternalizePass("main"));
> +    PM.add(createInternalizePass("main", None));
>
>    // Propagate constants at call sites into the functions they call.  This
>    // opens opportunities for globalopt (and inlining) by substituting
> function
>
> Modified: llvm/trunk/test/LTO/cfi_endproc.ll
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/LTO/cfi_endproc.ll?rev=191922&r1=191921&r2=191922&view=diff
>
> ==============================================================================
> --- llvm/trunk/test/LTO/cfi_endproc.ll (original)
> +++ llvm/trunk/test/LTO/cfi_endproc.ll Thu Oct  3 13:29:09 2013
> @@ -27,3 +27,11 @@ define i32 @main(i32 %argc, i8** %argv)
>    call void @PR14512()
>    ret i32 0
>  }
> +
> +; RUN: llvm-lto -o %t -dso-symbol=zed1 -dso-symbol=zed2 %t1 -disable-opt
> +; RUN: llvm-nm %t | FileCheck %s -check-prefix=ZED1_AND_ZED2
> +; ZED1_AND_ZED2: V zed1
> + at zed1 = linkonce_odr global i32 42
> +
> +; ZED1_AND_ZED2: d zed2
> + at zed2 = linkonce_odr unnamed_addr global i32 42
>
> Modified: llvm/trunk/test/Transforms/Internalize/lists.ll
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Internalize/lists.ll?rev=191922&r1=191921&r2=191922&view=diff
>
> ==============================================================================
> --- llvm/trunk/test/Transforms/Internalize/lists.ll (original)
> +++ llvm/trunk/test/Transforms/Internalize/lists.ll Thu Oct  3 13:29:09
> 2013
> @@ -13,6 +13,10 @@
>  ; -file and -list options should be merged, the apifile contains foo and j
>  ; RUN: opt < %s -internalize -internalize-public-api-list bar
> -internalize-public-api-file %S/apifile -S | FileCheck
> --check-prefix=FOO_J_AND_BAR %s
>
> +; Put zed1 and zed2 in the symbol table. If the address is not relevant,
> we
> +; internalize them.
> +; RUN: opt < %s -internalize -internalize-dso-list zed1,zed2 -S |
> FileCheck --check-prefix=ZED1_AND_ZED2 %s
> +
>  ; ALL: @i = internal global
>  ; FOO_AND_J: @i = internal global
>  ; FOO_AND_BAR: @i = internal global
> @@ -25,6 +29,12 @@
>  ; FOO_J_AND_BAR: @j = global
>  @j = global i32 0
>
> +; ZED1_AND_ZED2: @zed1 = linkonce_odr global i32 42
> + at zed1 = linkonce_odr global i32 42
> +
> +; ZED1_AND_ZED2: @zed2 = internal unnamed_addr global i32 42
> + at zed2 = linkonce_odr unnamed_addr global i32 42
> +
>  ; ALL: define internal void @main() {
>  ; FOO_AND_J: define internal void @main() {
>  ; FOO_AND_BAR: define internal void @main() {
>
> Modified: llvm/trunk/tools/gold/gold-plugin.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/gold/gold-plugin.cpp?rev=191922&r1=191921&r2=191922&view=diff
>
> ==============================================================================
> --- llvm/trunk/tools/gold/gold-plugin.cpp (original)
> +++ llvm/trunk/tools/gold/gold-plugin.cpp Thu Oct  3 13:29:09 2013
> @@ -197,7 +197,7 @@ ld_plugin_status onload(ld_plugin_tv *tv
>        case LDPT_ADD_SYMBOLS:
>          add_symbols = tv->tv_u.tv_add_symbols;
>          break;
> -      case LDPT_GET_SYMBOLS:
> +      case LDPT_GET_SYMBOLS_V2:
>          get_symbols = tv->tv_u.tv_get_symbols;
>          break;
>        case LDPT_ADD_INPUT_FILE:
> @@ -386,6 +386,11 @@ static ld_plugin_status all_symbols_read
>
>          if (options::generate_api_file)
>            api_file << I->syms[i].name << "\n";
> +      } else if (I->syms[i].resolution == LDPR_PREVAILING_DEF_IRONLY_EXP)
> {
>

third_party/llvm/llvm/tools/gold/gold-plugin.cpp:200:12: error: use of
undeclared identifier 'LDPT_GET_SYMBOLS_V2'; did you mean
'LDPT_GET_SYMBOLS'?
third_party/llvm/llvm/tools/gold/gold-plugin.cpp:389:43: error: use of
undeclared identifier 'LDPR_PREVAILING_DEF_IRONLY_EXP'; did you mean
'LDPR_PREVAILING_DEF_IRONLY'?

I think you've increased the minimum required version of something. Can you
make this change conditional on these names existing?


> +        lto_codegen_add_dso_symbol(code_gen, I->syms[i].name);
> +
> +        if (options::generate_api_file)
> +          api_file << I->syms[i].name << " dso only\n";
>        }
>      }
>    }
>
> Modified: llvm/trunk/tools/llvm-lto/llvm-lto.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-lto/llvm-lto.cpp?rev=191922&r1=191921&r2=191922&view=diff
>
> ==============================================================================
> --- llvm/trunk/tools/llvm-lto/llvm-lto.cpp (original)
> +++ llvm/trunk/tools/llvm-lto/llvm-lto.cpp Thu Oct  3 13:29:09 2013
> @@ -50,6 +50,10 @@ ExportedSymbols("exported-symbol",
>    cl::desc("Symbol to export from the resulting object file"),
>    cl::ZeroOrMore);
>
> +static cl::list<std::string>
> +DSOSymbols("dso-symbol",
> +  cl::desc("Symbol to put in the symtab in the resulting dso"),
> +  cl::ZeroOrMore);
>
>  int main(int argc, char **argv) {
>    // Print a stack trace if we signal out.
> @@ -117,6 +121,10 @@ int main(int argc, char **argv) {
>    for (unsigned i = 0; i < ExportedSymbols.size(); ++i)
>      CodeGen.addMustPreserveSymbol(ExportedSymbols[i].c_str());
>
> +  // Add all the dso symbols to the table of symbols to expose.
> +  for (unsigned i = 0; i < DSOSymbols.size(); ++i)
> +    CodeGen.addDSOSymbol(DSOSymbols[i].c_str());
> +
>    if (!OutputFilename.empty()) {
>      size_t len = 0;
>      std::string ErrorInfo;
>
> Modified: llvm/trunk/tools/lto/lto.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/lto/lto.cpp?rev=191922&r1=191921&r2=191922&view=diff
>
> ==============================================================================
> --- llvm/trunk/tools/lto/lto.cpp (original)
> +++ llvm/trunk/tools/lto/lto.cpp Thu Oct  3 13:29:09 2013
> @@ -260,6 +260,10 @@ void lto_codegen_add_must_preserve_symbo
>    cg->addMustPreserveSymbol(symbol);
>  }
>
> +void lto_codegen_add_dso_symbol(lto_code_gen_t cg, const char *symbol) {
> +  cg->addDSOSymbol(symbol);
> +}
> +
>  /// lto_codegen_write_merged_modules - Writes a new file at the specified
> path
>  /// that contains the merged contents of all modules added so far.
> Returns true
>  /// on error (check lto_get_error_message() for details).
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20131003/c9186d29/attachment.html>


More information about the llvm-commits mailing list