<commit_before>//===- lib/Linker/LinkArchives.cpp - Link LLVM objects and libraries ------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains routines to handle linking together LLVM bytecode files,
// and to handle annoying things like static libraries.
//
//===----------------------------------------------------------------------===//

#include "llvm/Linker.h"
#include "llvm/Module.h"
#include "llvm/ModuleProvider.h"
#include "llvm/PassManager.h"
#include "llvm/Bytecode/Reader.h"
#include "llvm/Bytecode/Archive.h"
#include "llvm/Bytecode/WriteBytecodePass.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Transforms/IPO.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Config/config.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FileUtilities.h"
#include "llvm/System/Signals.h"
#include "llvm/Support/SystemUtils.h"
#include <algorithm>
#include <fstream>
#include <memory>
#include <set>
using namespace llvm;

/// FindLib - Try to convert Filename into the name of a file that we can open,
/// if it does not already name a file we can open, by first trying to open
/// Filename, then libFilename.[suffix] for each of a set of several common
/// library suffixes, in each of the directories in Paths and the directory
/// named by the value of the environment variable LLVM_LIB_SEARCH_PATH. Returns
/// an empty string if no matching file can be found.
///
std::string llvm::FindLib(const std::string &Filename,
                          const std::vector<std::string> &Paths,
                          bool SharedObjectOnly) {
  // Determine if the pathname can be found as it stands.
  if (FileOpenable(Filename))
    return Filename;

  // If that doesn't work, convert the name into a library name.
  std::string LibName = "lib" + Filename;

  // Iterate over the directories in Paths to see if we can find the library
  // there.
  for (unsigned Index = 0; Index != Paths.size(); ++Index) {
    std::string Directory = Paths[Index] + "/";

    if (!SharedObjectOnly && FileOpenable(Directory + LibName + ".bc"))
      return Directory + LibName + ".bc";

    if (FileOpenable(Directory + LibName + SHLIBEXT))
      return Directory + LibName + SHLIBEXT;

    if (!SharedObjectOnly && FileOpenable(Directory + LibName + ".a"))
      return Directory + LibName + ".a";
  }

  // One last hope: Check LLVM_LIB_SEARCH_PATH.
  char *SearchPath = getenv("LLVM_LIB_SEARCH_PATH");
  if (SearchPath == NULL)
    return std::string();

  LibName = std::string(SearchPath) + "/" + LibName;
  if (FileOpenable(LibName))
    return LibName;

  return std::string();
}

/// GetAllDefinedSymbols - Modifies its parameter DefinedSymbols to contain the
/// name of each externally-visible symbol defined in M.
///
void llvm::GetAllDefinedSymbols(Module *M,
                                std::set<std::string> &DefinedSymbols) {
  for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I)
    if (I->hasName() && !I->isExternal() && !I->hasInternalLinkage())
      DefinedSymbols.insert(I->getName());
  for (Module::giterator I = M->gbegin(), E = M->gend(); I != E; ++I)
    if (I->hasName() && !I->isExternal() && !I->hasInternalLinkage())
      DefinedSymbols.insert(I->getName());
}

/// GetAllUndefinedSymbols - calculates the set of undefined symbols that still
/// exist in an LLVM module. This is a bit tricky because there may be two
/// symbols with the same name but different LLVM types that will be resolved to
/// each other but aren't currently (thus we need to treat it as resolved).
///
/// Inputs:
///  M - The module in which to find undefined symbols.
///
/// Outputs:
///  UndefinedSymbols - A set of C++ strings containing the name of all
///                     undefined symbols.
///
void
llvm::GetAllUndefinedSymbols(Module *M,
                             std::set<std::string> &UndefinedSymbols) {
  std::set<std::string> DefinedSymbols;
  UndefinedSymbols.clear();   // Start out empty

  for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I)
    if (I->hasName()) {
      if (I->isExternal())
        UndefinedSymbols.insert(I->getName());
      else if (!I->hasInternalLinkage())
        DefinedSymbols.insert(I->getName());
    }
  for (Module::giterator I = M->gbegin(), E = M->gend(); I != E; ++I)
    if (I->hasName()) {
      if (I->isExternal())
        UndefinedSymbols.insert(I->getName());
      else if (!I->hasInternalLinkage())
        DefinedSymbols.insert(I->getName());
    }

  // Prune out any defined symbols from the undefined symbols set...
  for (std::set<std::string>::iterator I = UndefinedSymbols.begin();
       I != UndefinedSymbols.end(); )
    if (DefinedSymbols.count(*I))
      UndefinedSymbols.erase(I++);  // This symbol really is defined!
    else
      ++I; // Keep this symbol in the undefined symbols list
}

/// LoadObject - Read in and parse the bytecode file named by FN and return the
/// module it contains (wrapped in an auto_ptr), or 0 and set ErrorMessage if an
/// error occurs.
///
static std::auto_ptr<Module> LoadObject(const std::string &FN,
                                       std::string &ErrorMessage) {
  std::string ParserErrorMessage;
  Module *Result = ParseBytecodeFile(FN, &ParserErrorMessage);
  if (Result) return std::auto_ptr<Module>(Result);
  ErrorMessage = "Bytecode file '" + FN + "' could not be loaded";
  if (ParserErrorMessage.size()) ErrorMessage += ": " + ParserErrorMessage;
  return std::auto_ptr<Module>();
}

/// LinkInArchive - opens an archive library and link in all objects which
/// provide symbols that are currently undefined.
///
/// Inputs:
///  M        - The module in which to link the archives.
///  Filename - The pathname of the archive.
///  Verbose  - Flags whether verbose messages should be printed.
///
/// Outputs:
///  ErrorMessage - A C++ string detailing what error occurred, if any.
///
/// Return Value:
///  TRUE  - An error occurred.
///  FALSE - No errors.
///
bool llvm::LinkInArchive(Module *M,
                          const std::string &Filename,
                          std::string* ErrorMessage,
                          bool Verbose)
{
  // Find all of the symbols currently undefined in the bytecode program.
  // If all the symbols are defined, the program is complete, and there is
  // no reason to link in any archive files.
  std::set<std::string> UndefinedSymbols;
  GetAllUndefinedSymbols(M, UndefinedSymbols);
  if (UndefinedSymbols.empty()) {
    if (Verbose) std::cerr << "  No symbols undefined, don't link library!\n";
    return false;  // No need to link anything in!
  }

  // Open the archive file
  if (Verbose) std::cerr << "  Loading archive file '" << Filename << "'\n";
  Archive* arch = Archive::OpenAndLoadSymbols(sys::Path(Filename));

  // While we are linking in object files, loop.
  while (true) {
    std::set<ModuleProvider*> Modules;
    // Find the modules we need to link
    arch->findModulesDefiningSymbols(UndefinedSymbols,Modules);

    // If we didn't find any more modules to link this time, we are done.
    if (Modules.empty())
      break;

    // Loop over all the ModuleProviders that we got back from the archive
    for (std::set<ModuleProvider*>::iterator I=Modules.begin(), E=Modules.end();
         I != E; ++I) {
      // Get the module we must link in.
      Module* aModule = (*I)->releaseModule();
      std::cout << "Linked: " << aModule->getModuleIdentifier() << "\n";

      // Link it in
      if (LinkModules(M, aModule, ErrorMessage)) {
        // don't create a memory leak
        delete aModule;
        delete arch;
        return true;   // Couldn't link in the right object file...
      }

      // Since we have linked in this object, throw it away now.
      delete aModule;
    }

    // We have linked in a set of modules determined by the archive to satisfy
    // our missing symbols. Linking in the new modules will have satisfied some
    // symbols but may introduce additional missing symbols. We need to update
    // the list of undefined symbols and try again until the archive doesn't
    // have any modules that satisfy our symbols.
    GetAllUndefinedSymbols(M, UndefinedSymbols);
  }

  return false;
}

/// LinkInFile - opens a bytecode file and links in all objects which
/// provide symbols that are currently undefined.
///
/// Inputs:
///  HeadModule - The module in which to link the bytecode file.
///  Filename   - The pathname of the bytecode file.
///  Verbose    - Flags whether verbose messages should be printed.
///
/// Outputs:
///  ErrorMessage - A C++ string detailing what error occurred, if any.
///
/// Return Value:
///  TRUE  - An error occurred.
///  FALSE - No errors.
///
static bool LinkInFile(Module *HeadModule,
                       const std::string &Filename,
                       std::string &ErrorMessage,
                       bool Verbose)
{
  std::auto_ptr<Module> M(LoadObject(Filename, ErrorMessage));
  if (M.get() == 0) return true;
  bool Result = LinkModules(HeadModule, M.get(), &ErrorMessage);
  if (Verbose) std::cerr << "Linked in bytecode file '" << Filename << "'\n";
  return Result;
}

/// LinkFiles - takes a module and a list of files and links them all together.
/// It locates the file either in the current directory, as its absolute
/// or relative pathname, or as a file somewhere in LLVM_LIB_SEARCH_PATH.
///
/// Inputs:
///  progname   - The name of the program (infamous argv[0]).
///  HeadModule - The module under which all files will be linked.
///  Files      - A vector of C++ strings indicating the LLVM bytecode filenames
///               to be linked.  The names can refer to a mixture of pure LLVM
///               bytecode files and archive (ar) formatted files.
///  Verbose    - Flags whether verbose output should be printed while linking.
///
/// Outputs:
///  HeadModule - The module will have the specified LLVM bytecode files linked
///               in.
///
/// Return value:
///  FALSE - No errors.
///  TRUE  - Some error occurred.
///
bool llvm::LinkFiles(const char *progname, Module *HeadModule,
                     const std::vector<std::string> &Files, bool Verbose) {
  // String in which to receive error messages.
  std::string ErrorMessage;

  // Full pathname of the file
  std::string Pathname;

  // Get the library search path from the environment
  char *SearchPath = getenv("LLVM_LIB_SEARCH_PATH");

  for (unsigned i = 0; i < Files.size(); ++i) {
    // Determine where this file lives.
    if (FileOpenable(Files[i])) {
      Pathname = Files[i];
    } else {
      if (SearchPath == NULL) {
        std::cerr << progname << ": Cannot find linker input file '"
                  << Files[i] << "'\n";
        std::cerr << progname
                  << ": Warning: Your LLVM_LIB_SEARCH_PATH is unset.\n";
        return true;
      }

      Pathname = std::string(SearchPath)+"/"+Files[i];
      if (!FileOpenable(Pathname)) {
        std::cerr << progname << ": Cannot find linker input file '"
                  << Files[i] << "'\n";
        return true;
      }
    }

    // A user may specify an ar archive without -l, perhaps because it
    // is not installed as a library. Detect that and link the library.
    if (IsArchive(Pathname)) {
      if (Verbose)
        std::cerr << "Trying to link archive '" << Pathname << "'\n";

      if (LinkInArchive(HeadModule, Pathname, &ErrorMessage, Verbose)) {
        std::cerr << progname << ": Error linking in archive '" << Pathname
                  << "': " << ErrorMessage << "\n";
        return true;
      }
    } else if (IsBytecode(Pathname)) {
      if (Verbose)
        std::cerr << "Trying to link bytecode file '" << Pathname << "'\n";

      if (LinkInFile(HeadModule, Pathname, ErrorMessage, Verbose)) {
        std::cerr << progname << ": Error linking in bytecode file '"
                  << Pathname << "': " << ErrorMessage << "\n";
        return true;
      }
    } else {
      std::cerr << progname << ": Warning: invalid file `" << Pathname
                << "' ignored.\n";
    }
  }

  return false;
}

/// LinkLibraries - takes the specified library files and links them into the
/// main bytecode object file.
///
/// Inputs:
///  progname   - The name of the program (infamous argv[0]).
///  HeadModule - The module into which all necessary libraries will be linked.
///  Libraries  - The list of libraries to link into the module.
///  LibPaths   - The list of library paths in which to find libraries.
///  Verbose    - Flags whether verbose messages should be printed.
///  Native     - Flags whether native code is being generated.
///
/// Outputs:
///  HeadModule - The module will have all necessary libraries linked in.
///
/// Return value:
///  FALSE - No error.
///  TRUE  - Error.
///
void llvm::LinkLibraries(const char *progname, Module *HeadModule,
                         const std::vector<std::string> &Libraries,
                         const std::vector<std::string> &LibPaths,
                         bool Verbose, bool Native) {
  // String in which to receive error messages.
  std::string ErrorMessage;

  for (unsigned i = 0; i < Libraries.size(); ++i) {
    // Determine where this library lives.
    std::string Pathname = FindLib(Libraries[i], LibPaths);
    if (Pathname.empty()) {
      // If the pathname does not exist, then continue to the next one if
      // we're doing a native link and give an error if we're doing a bytecode
      // link.
      if (!Native) {
        std::cerr << progname << ": WARNING: Cannot find library -l"
                  << Libraries[i] << "\n";
        continue;
      }
    }

    // A user may specify an ar archive without -l, perhaps because it
    // is not installed as a library. Detect that and link the library.
    if (IsArchive(Pathname)) {
      if (Verbose)
        std::cerr << "Trying to link archive '" << Pathname << "' (-l"
                  << Libraries[i] << ")\n";

      if (LinkInArchive(HeadModule, Pathname, &ErrorMessage, Verbose)) {
        std::cerr << progname << ": " << ErrorMessage
                  << ": Error linking in archive '" << Pathname << "' (-l"
                  << Libraries[i] << ")\n";
        exit(1);
      }
    } else if (IsBytecode(Pathname)) {
      if (Verbose)
        std::cerr << "Trying to link bytecode file '" << Pathname
                  << "' (-l" << Libraries[i] << ")\n";

      if (LinkInFile(HeadModule, Pathname, ErrorMessage, Verbose)) {
        std::cerr << progname << ": " << ErrorMessage
                  << ": error linking in bytecode file '" << Pathname << "' (-l"
                  << Libraries[i] << ")\n";
        exit(1);
      }
    }
  }
}
<commit_msg>Remove a forgotten debug output line.<commit_after>//===- lib/Linker/LinkArchives.cpp - Link LLVM objects and libraries ------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains routines to handle linking together LLVM bytecode files,
// and to handle annoying things like static libraries.
//
//===----------------------------------------------------------------------===//

#include "llvm/Linker.h"
#include "llvm/Module.h"
#include "llvm/ModuleProvider.h"
#include "llvm/PassManager.h"
#include "llvm/Bytecode/Reader.h"
#include "llvm/Bytecode/Archive.h"
#include "llvm/Bytecode/WriteBytecodePass.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Transforms/IPO.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Config/config.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FileUtilities.h"
#include "llvm/System/Signals.h"
#include "llvm/Support/SystemUtils.h"
#include <algorithm>
#include <fstream>
#include <memory>
#include <set>
using namespace llvm;

/// FindLib - Try to convert Filename into the name of a file that we can open,
/// if it does not already name a file we can open, by first trying to open
/// Filename, then libFilename.[suffix] for each of a set of several common
/// library suffixes, in each of the directories in Paths and the directory
/// named by the value of the environment variable LLVM_LIB_SEARCH_PATH. Returns
/// an empty string if no matching file can be found.
///
std::string llvm::FindLib(const std::string &Filename,
                          const std::vector<std::string> &Paths,
                          bool SharedObjectOnly) {
  // Determine if the pathname can be found as it stands.
  if (FileOpenable(Filename))
    return Filename;

  // If that doesn't work, convert the name into a library name.
  std::string LibName = "lib" + Filename;

  // Iterate over the directories in Paths to see if we can find the library
  // there.
  for (unsigned Index = 0; Index != Paths.size(); ++Index) {
    std::string Directory = Paths[Index] + "/";

    if (!SharedObjectOnly && FileOpenable(Directory + LibName + ".bc"))
      return Directory + LibName + ".bc";

    if (FileOpenable(Directory + LibName + SHLIBEXT))
      return Directory + LibName + SHLIBEXT;

    if (!SharedObjectOnly && FileOpenable(Directory + LibName + ".a"))
      return Directory + LibName + ".a";
  }

  // One last hope: Check LLVM_LIB_SEARCH_PATH.
  char *SearchPath = getenv("LLVM_LIB_SEARCH_PATH");
  if (SearchPath == NULL)
    return std::string();

  LibName = std::string(SearchPath) + "/" + LibName;
  if (FileOpenable(LibName))
    return LibName;

  return std::string();
}

/// GetAllDefinedSymbols - Modifies its parameter DefinedSymbols to contain the
/// name of each externally-visible symbol defined in M.
///
void llvm::GetAllDefinedSymbols(Module *M,
                                std::set<std::string> &DefinedSymbols) {
  for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I)
    if (I->hasName() && !I->isExternal() && !I->hasInternalLinkage())
      DefinedSymbols.insert(I->getName());
  for (Module::giterator I = M->gbegin(), E = M->gend(); I != E; ++I)
    if (I->hasName() && !I->isExternal() && !I->hasInternalLinkage())
      DefinedSymbols.insert(I->getName());
}

/// GetAllUndefinedSymbols - calculates the set of undefined symbols that still
/// exist in an LLVM module. This is a bit tricky because there may be two
/// symbols with the same name but different LLVM types that will be resolved to
/// each other but aren't currently (thus we need to treat it as resolved).
///
/// Inputs:
///  M - The module in which to find undefined symbols.
///
/// Outputs:
///  UndefinedSymbols - A set of C++ strings containing the name of all
///                     undefined symbols.
///
void
llvm::GetAllUndefinedSymbols(Module *M,
                             std::set<std::string> &UndefinedSymbols) {
  std::set<std::string> DefinedSymbols;
  UndefinedSymbols.clear();   // Start out empty

  for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I)
    if (I->hasName()) {
      if (I->isExternal())
        UndefinedSymbols.insert(I->getName());
      else if (!I->hasInternalLinkage())
        DefinedSymbols.insert(I->getName());
    }
  for (Module::giterator I = M->gbegin(), E = M->gend(); I != E; ++I)
    if (I->hasName()) {
      if (I->isExternal())
        UndefinedSymbols.insert(I->getName());
      else if (!I->hasInternalLinkage())
        DefinedSymbols.insert(I->getName());
    }

  // Prune out any defined symbols from the undefined symbols set...
  for (std::set<std::string>::iterator I = UndefinedSymbols.begin();
       I != UndefinedSymbols.end(); )
    if (DefinedSymbols.count(*I))
      UndefinedSymbols.erase(I++);  // This symbol really is defined!
    else
      ++I; // Keep this symbol in the undefined symbols list
}

/// LoadObject - Read in and parse the bytecode file named by FN and return the
/// module it contains (wrapped in an auto_ptr), or 0 and set ErrorMessage if an
/// error occurs.
///
static std::auto_ptr<Module> LoadObject(const std::string &FN,
                                       std::string &ErrorMessage) {
  std::string ParserErrorMessage;
  Module *Result = ParseBytecodeFile(FN, &ParserErrorMessage);
  if (Result) return std::auto_ptr<Module>(Result);
  ErrorMessage = "Bytecode file '" + FN + "' could not be loaded";
  if (ParserErrorMessage.size()) ErrorMessage += ": " + ParserErrorMessage;
  return std::auto_ptr<Module>();
}

/// LinkInArchive - opens an archive library and link in all objects which
/// provide symbols that are currently undefined.
///
/// Inputs:
///  M        - The module in which to link the archives.
///  Filename - The pathname of the archive.
///  Verbose  - Flags whether verbose messages should be printed.
///
/// Outputs:
///  ErrorMessage - A C++ string detailing what error occurred, if any.
///
/// Return Value:
///  TRUE  - An error occurred.
///  FALSE - No errors.
///
bool llvm::LinkInArchive(Module *M,
                          const std::string &Filename,
                          std::string* ErrorMessage,
                          bool Verbose)
{
  // Find all of the symbols currently undefined in the bytecode program.
  // If all the symbols are defined, the program is complete, and there is
  // no reason to link in any archive files.
  std::set<std::string> UndefinedSymbols;
  GetAllUndefinedSymbols(M, UndefinedSymbols);
  if (UndefinedSymbols.empty()) {
    if (Verbose) std::cerr << "  No symbols undefined, don't link library!\n";
    return false;  // No need to link anything in!
  }

  // Open the archive file
  if (Verbose) std::cerr << "  Loading archive file '" << Filename << "'\n";
  Archive* arch = Archive::OpenAndLoadSymbols(sys::Path(Filename));

  // While we are linking in object files, loop.
  while (true) {
    std::set<ModuleProvider*> Modules;
    // Find the modules we need to link
    arch->findModulesDefiningSymbols(UndefinedSymbols,Modules);

    // If we didn't find any more modules to link this time, we are done.
    if (Modules.empty())
      break;

    // Loop over all the ModuleProviders that we got back from the archive
    for (std::set<ModuleProvider*>::iterator I=Modules.begin(), E=Modules.end();
         I != E; ++I) {
      // Get the module we must link in.
      Module* aModule = (*I)->releaseModule();

      // Link it in
      if (LinkModules(M, aModule, ErrorMessage)) {
        // don't create a memory leak
        delete aModule;
        delete arch;
        return true;   // Couldn't link in the right object file...
      }

      // Since we have linked in this object, throw it away now.
      delete aModule;
    }

    // We have linked in a set of modules determined by the archive to satisfy
    // our missing symbols. Linking in the new modules will have satisfied some
    // symbols but may introduce additional missing symbols. We need to update
    // the list of undefined symbols and try again until the archive doesn't
    // have any modules that satisfy our symbols.
    GetAllUndefinedSymbols(M, UndefinedSymbols);
  }

  return false;
}

/// LinkInFile - opens a bytecode file and links in all objects which
/// provide symbols that are currently undefined.
///
/// Inputs:
///  HeadModule - The module in which to link the bytecode file.
///  Filename   - The pathname of the bytecode file.
///  Verbose    - Flags whether verbose messages should be printed.
///
/// Outputs:
///  ErrorMessage - A C++ string detailing what error occurred, if any.
///
/// Return Value:
///  TRUE  - An error occurred.
///  FALSE - No errors.
///
static bool LinkInFile(Module *HeadModule,
                       const std::string &Filename,
                       std::string &ErrorMessage,
                       bool Verbose)
{
  std::auto_ptr<Module> M(LoadObject(Filename, ErrorMessage));
  if (M.get() == 0) return true;
  bool Result = LinkModules(HeadModule, M.get(), &ErrorMessage);
  if (Verbose) std::cerr << "Linked in bytecode file '" << Filename << "'\n";
  return Result;
}

/// LinkFiles - takes a module and a list of files and links them all together.
/// It locates the file either in the current directory, as its absolute
/// or relative pathname, or as a file somewhere in LLVM_LIB_SEARCH_PATH.
///
/// Inputs:
///  progname   - The name of the program (infamous argv[0]).
///  HeadModule - The module under which all files will be linked.
///  Files      - A vector of C++ strings indicating the LLVM bytecode filenames
///               to be linked.  The names can refer to a mixture of pure LLVM
///               bytecode files and archive (ar) formatted files.
///  Verbose    - Flags whether verbose output should be printed while linking.
///
/// Outputs:
///  HeadModule - The module will have the specified LLVM bytecode files linked
///               in.
///
/// Return value:
///  FALSE - No errors.
///  TRUE  - Some error occurred.
///
bool llvm::LinkFiles(const char *progname, Module *HeadModule,
                     const std::vector<std::string> &Files, bool Verbose) {
  // String in which to receive error messages.
  std::string ErrorMessage;

  // Full pathname of the file
  std::string Pathname;

  // Get the library search path from the environment
  char *SearchPath = getenv("LLVM_LIB_SEARCH_PATH");

  for (unsigned i = 0; i < Files.size(); ++i) {
    // Determine where this file lives.
    if (FileOpenable(Files[i])) {
      Pathname = Files[i];
    } else {
      if (SearchPath == NULL) {
        std::cerr << progname << ": Cannot find linker input file '"
                  << Files[i] << "'\n";
        std::cerr << progname
                  << ": Warning: Your LLVM_LIB_SEARCH_PATH is unset.\n";
        return true;
      }

      Pathname = std::string(SearchPath)+"/"+Files[i];
      if (!FileOpenable(Pathname)) {
        std::cerr << progname << ": Cannot find linker input file '"
                  << Files[i] << "'\n";
        return true;
      }
    }

    // A user may specify an ar archive without -l, perhaps because it
    // is not installed as a library. Detect that and link the library.
    if (IsArchive(Pathname)) {
      if (Verbose)
        std::cerr << "Trying to link archive '" << Pathname << "'\n";

      if (LinkInArchive(HeadModule, Pathname, &ErrorMessage, Verbose)) {
        std::cerr << progname << ": Error linking in archive '" << Pathname
                  << "': " << ErrorMessage << "\n";
        return true;
      }
    } else if (IsBytecode(Pathname)) {
      if (Verbose)
        std::cerr << "Trying to link bytecode file '" << Pathname << "'\n";

      if (LinkInFile(HeadModule, Pathname, ErrorMessage, Verbose)) {
        std::cerr << progname << ": Error linking in bytecode file '"
                  << Pathname << "': " << ErrorMessage << "\n";
        return true;
      }
    } else {
      std::cerr << progname << ": Warning: invalid file `" << Pathname
                << "' ignored.\n";
    }
  }

  return false;
}

/// LinkLibraries - takes the specified library files and links them into the
/// main bytecode object file.
///
/// Inputs:
///  progname   - The name of the program (infamous argv[0]).
///  HeadModule - The module into which all necessary libraries will be linked.
///  Libraries  - The list of libraries to link into the module.
///  LibPaths   - The list of library paths in which to find libraries.
///  Verbose    - Flags whether verbose messages should be printed.
///  Native     - Flags whether native code is being generated.
///
/// Outputs:
///  HeadModule - The module will have all necessary libraries linked in.
///
/// Return value:
///  FALSE - No error.
///  TRUE  - Error.
///
void llvm::LinkLibraries(const char *progname, Module *HeadModule,
                         const std::vector<std::string> &Libraries,
                         const std::vector<std::string> &LibPaths,
                         bool Verbose, bool Native) {
  // String in which to receive error messages.
  std::string ErrorMessage;

  for (unsigned i = 0; i < Libraries.size(); ++i) {
    // Determine where this library lives.
    std::string Pathname = FindLib(Libraries[i], LibPaths);
    if (Pathname.empty()) {
      // If the pathname does not exist, then continue to the next one if
      // we're doing a native link and give an error if we're doing a bytecode
      // link.
      if (!Native) {
        std::cerr << progname << ": WARNING: Cannot find library -l"
                  << Libraries[i] << "\n";
        continue;
      }
    }

    // A user may specify an ar archive without -l, perhaps because it
    // is not installed as a library. Detect that and link the library.
    if (IsArchive(Pathname)) {
      if (Verbose)
        std::cerr << "Trying to link archive '" << Pathname << "' (-l"
                  << Libraries[i] << ")\n";

      if (LinkInArchive(HeadModule, Pathname, &ErrorMessage, Verbose)) {
        std::cerr << progname << ": " << ErrorMessage
                  << ": Error linking in archive '" << Pathname << "' (-l"
                  << Libraries[i] << ")\n";
        exit(1);
      }
    } else if (IsBytecode(Pathname)) {
      if (Verbose)
        std::cerr << "Trying to link bytecode file '" << Pathname
                  << "' (-l" << Libraries[i] << ")\n";

      if (LinkInFile(HeadModule, Pathname, ErrorMessage, Verbose)) {
        std::cerr << progname << ": " << ErrorMessage
                  << ": error linking in bytecode file '" << Pathname << "' (-l"
                  << Libraries[i] << ")\n";
        exit(1);
      }
    }
  }
}
<|endoftext|>


<commit_before>//===- lib/Linker/LinkArchives.cpp - Link LLVM objects and libraries ------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains routines to handle linking together LLVM bytecode files,
// and to handle annoying things like static libraries.
//
//===----------------------------------------------------------------------===//

#include "llvm/Linker.h"
#include "llvm/Module.h"
#include "llvm/ModuleProvider.h"
#include "llvm/ADT/SetOperations.h"
#include "llvm/Bytecode/Reader.h"
#include "llvm/Bytecode/Archive.h"
#include "llvm/Config/config.h"
#include <memory>
#include <set>
using namespace llvm;

/// GetAllUndefinedSymbols - calculates the set of undefined symbols that still
/// exist in an LLVM module. This is a bit tricky because there may be two
/// symbols with the same name but different LLVM types that will be resolved to
/// each other but aren't currently (thus we need to treat it as resolved).
///
/// Inputs:
///  M - The module in which to find undefined symbols.
///
/// Outputs:
///  UndefinedSymbols - A set of C++ strings containing the name of all
///                     undefined symbols.
///
static void
GetAllUndefinedSymbols(Module *M, std::set<std::string> &UndefinedSymbols) {
  std::set<std::string> DefinedSymbols;
  UndefinedSymbols.clear();

  // If the program doesn't define a main, try pulling one in from a .a file.
  // This is needed for programs where the main function is defined in an
  // archive, such f2c'd programs.
  Function *Main = M->getMainFunction();
  if (Main == 0 || Main->isExternal())
    UndefinedSymbols.insert("main");

  for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I)
    if (I->hasName()) {
      if (I->isExternal())
        UndefinedSymbols.insert(I->getName());
      else if (!I->hasInternalLinkage()) {
        assert(!I->hasDLLImportLinkage()
               && "Found dllimported non-external symbol!");
        DefinedSymbols.insert(I->getName());
      }
    }
  for (Module::global_iterator I = M->global_begin(), E = M->global_end();
       I != E; ++I)
    if (I->hasName()) {
      if (I->isExternal())
        UndefinedSymbols.insert(I->getName());
      else if (!I->hasInternalLinkage()) {
        assert(!I->hasDLLImportLinkage()
               && "Found dllimported non-external symbol!");
        DefinedSymbols.insert(I->getName());
      }
    }

  // Prune out any defined symbols from the undefined symbols set...
  for (std::set<std::string>::iterator I = UndefinedSymbols.begin();
       I != UndefinedSymbols.end(); )
    if (DefinedSymbols.count(*I))
      UndefinedSymbols.erase(I++);  // This symbol really is defined!
    else
      ++I; // Keep this symbol in the undefined symbols list
}

/// LinkInArchive - opens an archive library and link in all objects which
/// provide symbols that are currently undefined.
///
/// Inputs:
///  Filename - The pathname of the archive.
///
/// Return Value:
///  TRUE  - An error occurred.
///  FALSE - No errors.
bool
Linker::LinkInArchive(const sys::Path &Filename) {

  // Make sure this is an archive file we're dealing with
  if (!Filename.isArchive())
    return error("File '" + Filename.toString() + "' is not an archive.");

  // Open the archive file
  verbose("Linking archive file '" + Filename.toString() + "'");

  // Find all of the symbols currently undefined in the bytecode program.
  // If all the symbols are defined, the program is complete, and there is
  // no reason to link in any archive files.
  std::set<std::string> UndefinedSymbols;
  GetAllUndefinedSymbols(Composite, UndefinedSymbols);

  if (UndefinedSymbols.empty()) {
    verbose("No symbols undefined, skipping library '" +
            Filename.toString() + "'");
    return false;  // No need to link anything in!
  }

  std::string ErrMsg;
  std::auto_ptr<Archive> AutoArch (
    Archive::OpenAndLoadSymbols(Filename,&ErrMsg));

  Archive* arch = AutoArch.get();

  if (!arch)
    return error("Cannot read archive '" + Filename.toString() +
                 "': " + ErrMsg);

  // Save a set of symbols that are not defined by the archive. Since we're
  // entering a loop, there's no point searching for these multiple times. This
  // variable is used to "set_subtract" from the set of undefined symbols.
  std::set<std::string> NotDefinedByArchive;

  // Save the current set of undefined symbols, because we may have to make
  // multiple passes over the archive:
  std::set<std::string> CurrentlyUndefinedSymbols;

  do {
    CurrentlyUndefinedSymbols = UndefinedSymbols;

    // Find the modules we need to link into the target module
    std::set<ModuleProvider*> Modules;
    if (!arch->findModulesDefiningSymbols(UndefinedSymbols, Modules, &ErrMsg))
      return error("Cannot find symbols in '" + Filename.toString() +
                   "': " + ErrMsg);

    // If we didn't find any more modules to link this time, we are done
    // searching this archive.
    if (Modules.empty())
      break;

    // Any symbols remaining in UndefinedSymbols after
    // findModulesDefiningSymbols are ones that the archive does not define. So
    // we add them to the NotDefinedByArchive variable now.
    NotDefinedByArchive.insert(UndefinedSymbols.begin(),
        UndefinedSymbols.end());

    // Loop over all the ModuleProviders that we got back from the archive
    for (std::set<ModuleProvider*>::iterator I=Modules.begin(), E=Modules.end();
         I != E; ++I) {

      // Get the module we must link in.
      std::string moduleErrorMsg;
      std::auto_ptr<Module> AutoModule((*I)->releaseModule( &moduleErrorMsg ));
      Module* aModule = AutoModule.get();

      if (aModule != NULL) {
        verbose("  Linking in module: " + aModule->getModuleIdentifier());

        // Link it in
        if (LinkInModule(aModule, &moduleErrorMsg)) {
          return error("Cannot link in module '" +
                       aModule->getModuleIdentifier() + "': " + moduleErrorMsg);
        }
      } else {
	// (scottm) NOTE: For some reason, Modules.empty() isn't entirely
        // accurrate, least with gcc 4.1.2 on Debian and doesn't return true
        // when it ought.  Consequently, aModule can be NULL -- ignore it for
        // the time being, since it seems relatively benign.
      }
    }

    // Get the undefined symbols from the aggregate module. This recomputes the
    // symbols we still need after the new modules have been linked in.
    GetAllUndefinedSymbols(Composite, UndefinedSymbols);

    // At this point we have two sets of undefined symbols: UndefinedSymbols
    // which holds the undefined symbols from all the modules, and
    // NotDefinedByArchive which holds symbols we know the archive doesn't
    // define. There's no point searching for symbols that we won't find in the
    // archive so we subtract these sets.
    set_subtract(UndefinedSymbols, NotDefinedByArchive);

    // If there's no symbols left, no point in continuing to search the
    // archive.
    if (UndefinedSymbols.empty())
      break;
  } while (CurrentlyUndefinedSymbols != UndefinedSymbols);

  return false;
}
<commit_msg>Remvoe a do-nothing else block.<commit_after>//===- lib/Linker/LinkArchives.cpp - Link LLVM objects and libraries ------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains routines to handle linking together LLVM bytecode files,
// and to handle annoying things like static libraries.
//
//===----------------------------------------------------------------------===//

#include "llvm/Linker.h"
#include "llvm/Module.h"
#include "llvm/ModuleProvider.h"
#include "llvm/ADT/SetOperations.h"
#include "llvm/Bytecode/Reader.h"
#include "llvm/Bytecode/Archive.h"
#include "llvm/Config/config.h"
#include <memory>
#include <set>
using namespace llvm;

/// GetAllUndefinedSymbols - calculates the set of undefined symbols that still
/// exist in an LLVM module. This is a bit tricky because there may be two
/// symbols with the same name but different LLVM types that will be resolved to
/// each other but aren't currently (thus we need to treat it as resolved).
///
/// Inputs:
///  M - The module in which to find undefined symbols.
///
/// Outputs:
///  UndefinedSymbols - A set of C++ strings containing the name of all
///                     undefined symbols.
///
static void
GetAllUndefinedSymbols(Module *M, std::set<std::string> &UndefinedSymbols) {
  std::set<std::string> DefinedSymbols;
  UndefinedSymbols.clear();

  // If the program doesn't define a main, try pulling one in from a .a file.
  // This is needed for programs where the main function is defined in an
  // archive, such f2c'd programs.
  Function *Main = M->getMainFunction();
  if (Main == 0 || Main->isExternal())
    UndefinedSymbols.insert("main");

  for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I)
    if (I->hasName()) {
      if (I->isExternal())
        UndefinedSymbols.insert(I->getName());
      else if (!I->hasInternalLinkage()) {
        assert(!I->hasDLLImportLinkage()
               && "Found dllimported non-external symbol!");
        DefinedSymbols.insert(I->getName());
      }
    }
  for (Module::global_iterator I = M->global_begin(), E = M->global_end();
       I != E; ++I)
    if (I->hasName()) {
      if (I->isExternal())
        UndefinedSymbols.insert(I->getName());
      else if (!I->hasInternalLinkage()) {
        assert(!I->hasDLLImportLinkage()
               && "Found dllimported non-external symbol!");
        DefinedSymbols.insert(I->getName());
      }
    }

  // Prune out any defined symbols from the undefined symbols set...
  for (std::set<std::string>::iterator I = UndefinedSymbols.begin();
       I != UndefinedSymbols.end(); )
    if (DefinedSymbols.count(*I))
      UndefinedSymbols.erase(I++);  // This symbol really is defined!
    else
      ++I; // Keep this symbol in the undefined symbols list
}

/// LinkInArchive - opens an archive library and link in all objects which
/// provide symbols that are currently undefined.
///
/// Inputs:
///  Filename - The pathname of the archive.
///
/// Return Value:
///  TRUE  - An error occurred.
///  FALSE - No errors.
bool
Linker::LinkInArchive(const sys::Path &Filename) {

  // Make sure this is an archive file we're dealing with
  if (!Filename.isArchive())
    return error("File '" + Filename.toString() + "' is not an archive.");

  // Open the archive file
  verbose("Linking archive file '" + Filename.toString() + "'");

  // Find all of the symbols currently undefined in the bytecode program.
  // If all the symbols are defined, the program is complete, and there is
  // no reason to link in any archive files.
  std::set<std::string> UndefinedSymbols;
  GetAllUndefinedSymbols(Composite, UndefinedSymbols);

  if (UndefinedSymbols.empty()) {
    verbose("No symbols undefined, skipping library '" +
            Filename.toString() + "'");
    return false;  // No need to link anything in!
  }

  std::string ErrMsg;
  std::auto_ptr<Archive> AutoArch (
    Archive::OpenAndLoadSymbols(Filename,&ErrMsg));

  Archive* arch = AutoArch.get();

  if (!arch)
    return error("Cannot read archive '" + Filename.toString() +
                 "': " + ErrMsg);

  // Save a set of symbols that are not defined by the archive. Since we're
  // entering a loop, there's no point searching for these multiple times. This
  // variable is used to "set_subtract" from the set of undefined symbols.
  std::set<std::string> NotDefinedByArchive;

  // Save the current set of undefined symbols, because we may have to make
  // multiple passes over the archive:
  std::set<std::string> CurrentlyUndefinedSymbols;

  do {
    CurrentlyUndefinedSymbols = UndefinedSymbols;

    // Find the modules we need to link into the target module
    std::set<ModuleProvider*> Modules;
    if (!arch->findModulesDefiningSymbols(UndefinedSymbols, Modules, &ErrMsg))
      return error("Cannot find symbols in '" + Filename.toString() +
                   "': " + ErrMsg);

    // If we didn't find any more modules to link this time, we are done
    // searching this archive.
    if (Modules.empty())
      break;

    // Any symbols remaining in UndefinedSymbols after
    // findModulesDefiningSymbols are ones that the archive does not define. So
    // we add them to the NotDefinedByArchive variable now.
    NotDefinedByArchive.insert(UndefinedSymbols.begin(),
        UndefinedSymbols.end());

    // Loop over all the ModuleProviders that we got back from the archive
    for (std::set<ModuleProvider*>::iterator I=Modules.begin(), E=Modules.end();
         I != E; ++I) {

      // Get the module we must link in.
      std::string moduleErrorMsg;
      std::auto_ptr<Module> AutoModule((*I)->releaseModule( &moduleErrorMsg ));
      Module* aModule = AutoModule.get();

      if (aModule != NULL) {
        verbose("  Linking in module: " + aModule->getModuleIdentifier());

        // Link it in
        if (LinkInModule(aModule, &moduleErrorMsg)) {
          return error("Cannot link in module '" +
                       aModule->getModuleIdentifier() + "': " + moduleErrorMsg);
        }
      }
    }

    // Get the undefined symbols from the aggregate module. This recomputes the
    // symbols we still need after the new modules have been linked in.
    GetAllUndefinedSymbols(Composite, UndefinedSymbols);

    // At this point we have two sets of undefined symbols: UndefinedSymbols
    // which holds the undefined symbols from all the modules, and
    // NotDefinedByArchive which holds symbols we know the archive doesn't
    // define. There's no point searching for symbols that we won't find in the
    // archive so we subtract these sets.
    set_subtract(UndefinedSymbols, NotDefinedByArchive);

    // If there's no symbols left, no point in continuing to search the
    // archive.
    if (UndefinedSymbols.empty())
      break;
  } while (CurrentlyUndefinedSymbols != UndefinedSymbols);

  return false;
}
<|endoftext|>


<commit_before>//===- SubtargetFeature.cpp - CPU characteristics Implementation ----------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the SubtargetFeature interface.
//
//===----------------------------------------------------------------------===//

#include "llvm/MC/SubtargetFeature.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/ADT/StringExtras.h"
#include <algorithm>
#include <cassert>
#include <cctype>
#include <cstdlib>
using namespace llvm;

//===----------------------------------------------------------------------===//
//                          Static Helper Functions
//===----------------------------------------------------------------------===//

/// hasFlag - Determine if a feature has a flag; '+' or '-'
///
static inline bool hasFlag(const StringRef Feature) {
  assert(!Feature.empty() && "Empty string");
  // Get first character
  char Ch = Feature[0];
  // Check if first character is '+' or '-' flag
  return Ch == '+' || Ch =='-';
}

/// StripFlag - Return string stripped of flag.
///
static inline std::string StripFlag(const StringRef Feature) {
  return hasFlag(Feature) ? Feature.substr(1) : Feature;
}

/// isEnabled - Return true if enable flag; '+'.
///
static inline bool isEnabled(const StringRef Feature) {
  assert(!Feature.empty() && "Empty string");
  // Get first character
  char Ch = Feature[0];
  // Check if first character is '+' for enabled
  return Ch == '+';
}

/// PrependFlag - Return a string with a prepended flag; '+' or '-'.
///
static inline std::string PrependFlag(const StringRef Feature,
                                    bool IsEnabled) {
  assert(!Feature.empty() && "Empty string");
  if (hasFlag(Feature))
    return Feature;
  std::string Prefix = IsEnabled ? "+" : "-";
  Prefix += Feature;
  return Prefix;
}

/// Split - Splits a string of comma separated items in to a vector of strings.
///
static void Split(std::vector<std::string> &V, const StringRef S) {
  if (S.empty())
    return;

  // Start at beginning of string.
  size_t Pos = 0;
  while (true) {
    // Find the next comma
    size_t Comma = S.find(',', Pos);
    // If no comma found then the rest of the string is used
    if (Comma == std::string::npos) {
      // Add string to vector
      V.push_back(S.substr(Pos));
      break;
    }
    // Otherwise add substring to vector
    V.push_back(S.substr(Pos, Comma - Pos));
    // Advance to next item
    Pos = Comma + 1;
  }
}

/// Join a vector of strings to a string with a comma separating each element.
///
static std::string Join(const std::vector<std::string> &V) {
  // Start with empty string.
  std::string Result;
  // If the vector is not empty
  if (!V.empty()) {
    // Start with the first feature
    Result = V[0];
    // For each successive feature
    for (size_t i = 1; i < V.size(); i++) {
      // Add a comma
      Result += ",";
      // Add the feature
      Result += V[i];
    }
  }
  // Return the features string
  return Result;
}

/// Adding features.
void SubtargetFeatures::AddFeature(const StringRef String,
                                   bool IsEnabled) {
  // Don't add empty features
  if (!String.empty()) {
    // Convert to lowercase, prepend flag and add to vector
    Features.push_back(PrependFlag(LowercaseString(String), IsEnabled));
  }
}

/// Find KV in array using binary search.
template<typename T> const T *Find(const StringRef S, const T *A, size_t L) {
  // Make the lower bound element we're looking for
  T KV;
  KV.Key = S.data();
  // Determine the end of the array
  const T *Hi = A + L;
  // Binary search the array
  const T *F = std::lower_bound(A, Hi, KV);
  // If not found then return NULL
  if (F == Hi || std::string(F->Key) != S) return NULL;
  // Return the found array item
  return F;
}

/// getLongestEntryLength - Return the length of the longest entry in the table.
///
static size_t getLongestEntryLength(const SubtargetFeatureKV *Table,
                                    size_t Size) {
  size_t MaxLen = 0;
  for (size_t i = 0; i < Size; i++)
    MaxLen = std::max(MaxLen, std::strlen(Table[i].Key));
  return MaxLen;
}

/// Display help for feature choices.
///
static void Help(const SubtargetFeatureKV *CPUTable, size_t CPUTableSize,
                 const SubtargetFeatureKV *FeatTable, size_t FeatTableSize) {
  // Determine the length of the longest CPU and Feature entries.
  unsigned MaxCPULen  = getLongestEntryLength(CPUTable, CPUTableSize);
  unsigned MaxFeatLen = getLongestEntryLength(FeatTable, FeatTableSize);

  // Print the CPU table.
  errs() << "Available CPUs for this target:\n\n";
  for (size_t i = 0; i != CPUTableSize; i++)
    errs() << "  " << CPUTable[i].Key
         << std::string(MaxCPULen - std::strlen(CPUTable[i].Key), ' ')
         << " - " << CPUTable[i].Desc << ".\n";
  errs() << "\n";

  // Print the Feature table.
  errs() << "Available features for this target:\n\n";
  for (size_t i = 0; i != FeatTableSize; i++)
    errs() << "  " << FeatTable[i].Key
         << std::string(MaxFeatLen - std::strlen(FeatTable[i].Key), ' ')
         << " - " << FeatTable[i].Desc << ".\n";
  errs() << "\n";

  errs() << "Use +feature to enable a feature, or -feature to disable it.\n"
       << "For example, llc -mcpu=mycpu -mattr=+feature1,-feature2\n";
  std::exit(1);
}

//===----------------------------------------------------------------------===//
//                    SubtargetFeatures Implementation
//===----------------------------------------------------------------------===//

SubtargetFeatures::SubtargetFeatures(const StringRef Initial) {
  // Break up string into separate features
  Split(Features, Initial);
}

std::string SubtargetFeatures::getString() const {
  return Join(Features);
}

/// SetImpliedBits - For each feature that is (transitively) implied by this
/// feature, set it.
///
static
void SetImpliedBits(uint64_t &Bits, const SubtargetFeatureKV *FeatureEntry,
                    const SubtargetFeatureKV *FeatureTable,
                    size_t FeatureTableSize) {
  for (size_t i = 0; i < FeatureTableSize; ++i) {
    const SubtargetFeatureKV &FE = FeatureTable[i];

    if (FeatureEntry->Value == FE.Value) continue;

    if (FeatureEntry->Implies & FE.Value) {
      Bits |= FE.Value;
      SetImpliedBits(Bits, &FE, FeatureTable, FeatureTableSize);
    }
  }
}

/// ClearImpliedBits - For each feature that (transitively) implies this
/// feature, clear it.
///
static
void ClearImpliedBits(uint64_t &Bits, const SubtargetFeatureKV *FeatureEntry,
                      const SubtargetFeatureKV *FeatureTable,
                      size_t FeatureTableSize) {
  for (size_t i = 0; i < FeatureTableSize; ++i) {
    const SubtargetFeatureKV &FE = FeatureTable[i];

    if (FeatureEntry->Value == FE.Value) continue;

    if (FE.Implies & FeatureEntry->Value) {
      Bits &= ~FE.Value;
      ClearImpliedBits(Bits, &FE, FeatureTable, FeatureTableSize);
    }
  }
}

/// getFeatureBits - Get feature bits a CPU.
///
uint64_t SubtargetFeatures::getFeatureBits(const StringRef CPU,
                                         const SubtargetFeatureKV *CPUTable,
                                         size_t CPUTableSize,
                                         const SubtargetFeatureKV *FeatureTable,
                                         size_t FeatureTableSize) {
  assert(CPUTable && "missing CPU table");
  assert(FeatureTable && "missing features table");
#ifndef NDEBUG
  for (size_t i = 1; i < CPUTableSize; i++) {
    assert(strcmp(CPUTable[i - 1].Key, CPUTable[i].Key) < 0 &&
           "CPU table is not sorted");
  }
  for (size_t i = 1; i < FeatureTableSize; i++) {
    assert(strcmp(FeatureTable[i - 1].Key, FeatureTable[i].Key) < 0 &&
          "CPU features table is not sorted");
  }
#endif
  uint64_t Bits = 0;                    // Resulting bits

  // Check if help is needed
  if (CPU == "help")
    Help(CPUTable, CPUTableSize, FeatureTable, FeatureTableSize);

  // Find CPU entry
  const SubtargetFeatureKV *CPUEntry = Find(CPU, CPUTable, CPUTableSize);
  // If there is a match
  if (CPUEntry) {
    // Set base feature bits
    Bits = CPUEntry->Value;

    // Set the feature implied by this CPU feature, if any.
    for (size_t i = 0; i < FeatureTableSize; ++i) {
      const SubtargetFeatureKV &FE = FeatureTable[i];
      if (CPUEntry->Value & FE.Value)
        SetImpliedBits(Bits, &FE, FeatureTable, FeatureTableSize);
    }
  } else {
    errs() << "'" << CPU
           << "' is not a recognized processor for this target"
           << " (ignoring processor)\n";
  }
  // Iterate through each feature
  for (size_t i = 0, E = Features.size(); i < E; i++) {
    const StringRef Feature = Features[i];

    // Check for help
    if (Feature == "+help")
      Help(CPUTable, CPUTableSize, FeatureTable, FeatureTableSize);

    // Find feature in table.
    const SubtargetFeatureKV *FeatureEntry =
                       Find(StripFlag(Feature), FeatureTable, FeatureTableSize);
    // If there is a match
    if (FeatureEntry) {
      // Enable/disable feature in bits
      if (isEnabled(Feature)) {
        Bits |=  FeatureEntry->Value;

        // For each feature that this implies, set it.
        SetImpliedBits(Bits, FeatureEntry, FeatureTable, FeatureTableSize);
      } else {
        Bits &= ~FeatureEntry->Value;

        // For each feature that implies this, clear it.
        ClearImpliedBits(Bits, FeatureEntry, FeatureTable, FeatureTableSize);
      }
    } else {
      errs() << "'" << Feature
             << "' is not a recognized feature for this target"
             << " (ignoring feature)\n";
    }
  }

  return Bits;
}

/// Get scheduling itinerary of a CPU.
void *SubtargetFeatures::getItinerary(const StringRef CPU,
                                      const SubtargetInfoKV *Table,
                                      size_t TableSize) {
  assert(Table && "missing table");
#ifndef NDEBUG
  for (size_t i = 1; i < TableSize; i++) {
    assert(strcmp(Table[i - 1].Key, Table[i].Key) < 0 && "Table is not sorted");
  }
#endif

  // Find entry
  const SubtargetInfoKV *Entry = Find(CPU, Table, TableSize);

  if (Entry) {
    return Entry->Value;
  } else {
    errs() << "'" << CPU
           << "' is not a recognized processor for this target"
           << " (ignoring processor)\n";
    return NULL;
  }
}

/// print - Print feature string.
///
void SubtargetFeatures::print(raw_ostream &OS) const {
  for (size_t i = 0, e = Features.size(); i != e; ++i)
    OS << Features[i] << "  ";
  OS << "\n";
}

/// dump - Dump feature info.
///
void SubtargetFeatures::dump() const {
  print(dbgs());
}

/// getDefaultSubtargetFeatures - Return a string listing the features
/// associated with the target triple.
///
/// FIXME: This is an inelegant way of specifying the features of a
/// subtarget. It would be better if we could encode this information
/// into the IR. See <rdar://5972456>.
///
void SubtargetFeatures::getDefaultSubtargetFeatures(const Triple& Triple) {
  if (Triple.getVendor() == Triple::Apple) {
    if (Triple.getArch() == Triple::ppc) {
      // powerpc-apple-*
      AddFeature("altivec");
    } else if (Triple.getArch() == Triple::ppc64) {
      // powerpc64-apple-*
      AddFeature("64bit");
      AddFeature("altivec");
    }
  }
}
<commit_msg>Eliminate one extra conversion.<commit_after>//===- SubtargetFeature.cpp - CPU characteristics Implementation ----------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the SubtargetFeature interface.
//
//===----------------------------------------------------------------------===//

#include "llvm/MC/SubtargetFeature.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/ADT/StringExtras.h"
#include <algorithm>
#include <cassert>
#include <cctype>
#include <cstdlib>
using namespace llvm;

//===----------------------------------------------------------------------===//
//                          Static Helper Functions
//===----------------------------------------------------------------------===//

/// hasFlag - Determine if a feature has a flag; '+' or '-'
///
static inline bool hasFlag(const StringRef Feature) {
  assert(!Feature.empty() && "Empty string");
  // Get first character
  char Ch = Feature[0];
  // Check if first character is '+' or '-' flag
  return Ch == '+' || Ch =='-';
}

/// StripFlag - Return string stripped of flag.
///
static inline std::string StripFlag(const StringRef Feature) {
  return hasFlag(Feature) ? Feature.substr(1) : Feature;
}

/// isEnabled - Return true if enable flag; '+'.
///
static inline bool isEnabled(const StringRef Feature) {
  assert(!Feature.empty() && "Empty string");
  // Get first character
  char Ch = Feature[0];
  // Check if first character is '+' for enabled
  return Ch == '+';
}

/// PrependFlag - Return a string with a prepended flag; '+' or '-'.
///
static inline std::string PrependFlag(const StringRef Feature,
                                    bool IsEnabled) {
  assert(!Feature.empty() && "Empty string");
  if (hasFlag(Feature))
    return Feature;
  std::string Prefix = IsEnabled ? "+" : "-";
  Prefix += Feature;
  return Prefix;
}

/// Split - Splits a string of comma separated items in to a vector of strings.
///
static void Split(std::vector<std::string> &V, const StringRef S) {
  if (S.empty())
    return;

  // Start at beginning of string.
  size_t Pos = 0;
  while (true) {
    // Find the next comma
    size_t Comma = S.find(',', Pos);
    // If no comma found then the rest of the string is used
    if (Comma == std::string::npos) {
      // Add string to vector
      V.push_back(S.substr(Pos));
      break;
    }
    // Otherwise add substring to vector
    V.push_back(S.substr(Pos, Comma - Pos));
    // Advance to next item
    Pos = Comma + 1;
  }
}

/// Join a vector of strings to a string with a comma separating each element.
///
static std::string Join(const std::vector<std::string> &V) {
  // Start with empty string.
  std::string Result;
  // If the vector is not empty
  if (!V.empty()) {
    // Start with the first feature
    Result = V[0];
    // For each successive feature
    for (size_t i = 1; i < V.size(); i++) {
      // Add a comma
      Result += ",";
      // Add the feature
      Result += V[i];
    }
  }
  // Return the features string
  return Result;
}

/// Adding features.
void SubtargetFeatures::AddFeature(const StringRef String,
                                   bool IsEnabled) {
  // Don't add empty features
  if (!String.empty()) {
    // Convert to lowercase, prepend flag and add to vector
    Features.push_back(PrependFlag(LowercaseString(String), IsEnabled));
  }
}

/// Find KV in array using binary search.
template<typename T> const T *Find(const StringRef S, const T *A, size_t L) {
  // Make the lower bound element we're looking for
  T KV;
  KV.Key = S.data();
  // Determine the end of the array
  const T *Hi = A + L;
  // Binary search the array
  const T *F = std::lower_bound(A, Hi, KV);
  // If not found then return NULL
  if (F == Hi || StringRef(F->Key) != S) return NULL;
  // Return the found array item
  return F;
}

/// getLongestEntryLength - Return the length of the longest entry in the table.
///
static size_t getLongestEntryLength(const SubtargetFeatureKV *Table,
                                    size_t Size) {
  size_t MaxLen = 0;
  for (size_t i = 0; i < Size; i++)
    MaxLen = std::max(MaxLen, std::strlen(Table[i].Key));
  return MaxLen;
}

/// Display help for feature choices.
///
static void Help(const SubtargetFeatureKV *CPUTable, size_t CPUTableSize,
                 const SubtargetFeatureKV *FeatTable, size_t FeatTableSize) {
  // Determine the length of the longest CPU and Feature entries.
  unsigned MaxCPULen  = getLongestEntryLength(CPUTable, CPUTableSize);
  unsigned MaxFeatLen = getLongestEntryLength(FeatTable, FeatTableSize);

  // Print the CPU table.
  errs() << "Available CPUs for this target:\n\n";
  for (size_t i = 0; i != CPUTableSize; i++)
    errs() << "  " << CPUTable[i].Key
         << std::string(MaxCPULen - std::strlen(CPUTable[i].Key), ' ')
         << " - " << CPUTable[i].Desc << ".\n";
  errs() << "\n";

  // Print the Feature table.
  errs() << "Available features for this target:\n\n";
  for (size_t i = 0; i != FeatTableSize; i++)
    errs() << "  " << FeatTable[i].Key
         << std::string(MaxFeatLen - std::strlen(FeatTable[i].Key), ' ')
         << " - " << FeatTable[i].Desc << ".\n";
  errs() << "\n";

  errs() << "Use +feature to enable a feature, or -feature to disable it.\n"
       << "For example, llc -mcpu=mycpu -mattr=+feature1,-feature2\n";
  std::exit(1);
}

//===----------------------------------------------------------------------===//
//                    SubtargetFeatures Implementation
//===----------------------------------------------------------------------===//

SubtargetFeatures::SubtargetFeatures(const StringRef Initial) {
  // Break up string into separate features
  Split(Features, Initial);
}

std::string SubtargetFeatures::getString() const {
  return Join(Features);
}

/// SetImpliedBits - For each feature that is (transitively) implied by this
/// feature, set it.
///
static
void SetImpliedBits(uint64_t &Bits, const SubtargetFeatureKV *FeatureEntry,
                    const SubtargetFeatureKV *FeatureTable,
                    size_t FeatureTableSize) {
  for (size_t i = 0; i < FeatureTableSize; ++i) {
    const SubtargetFeatureKV &FE = FeatureTable[i];

    if (FeatureEntry->Value == FE.Value) continue;

    if (FeatureEntry->Implies & FE.Value) {
      Bits |= FE.Value;
      SetImpliedBits(Bits, &FE, FeatureTable, FeatureTableSize);
    }
  }
}

/// ClearImpliedBits - For each feature that (transitively) implies this
/// feature, clear it.
///
static
void ClearImpliedBits(uint64_t &Bits, const SubtargetFeatureKV *FeatureEntry,
                      const SubtargetFeatureKV *FeatureTable,
                      size_t FeatureTableSize) {
  for (size_t i = 0; i < FeatureTableSize; ++i) {
    const SubtargetFeatureKV &FE = FeatureTable[i];

    if (FeatureEntry->Value == FE.Value) continue;

    if (FE.Implies & FeatureEntry->Value) {
      Bits &= ~FE.Value;
      ClearImpliedBits(Bits, &FE, FeatureTable, FeatureTableSize);
    }
  }
}

/// getFeatureBits - Get feature bits a CPU.
///
uint64_t SubtargetFeatures::getFeatureBits(const StringRef CPU,
                                         const SubtargetFeatureKV *CPUTable,
                                         size_t CPUTableSize,
                                         const SubtargetFeatureKV *FeatureTable,
                                         size_t FeatureTableSize) {
  assert(CPUTable && "missing CPU table");
  assert(FeatureTable && "missing features table");
#ifndef NDEBUG
  for (size_t i = 1; i < CPUTableSize; i++) {
    assert(strcmp(CPUTable[i - 1].Key, CPUTable[i].Key) < 0 &&
           "CPU table is not sorted");
  }
  for (size_t i = 1; i < FeatureTableSize; i++) {
    assert(strcmp(FeatureTable[i - 1].Key, FeatureTable[i].Key) < 0 &&
          "CPU features table is not sorted");
  }
#endif
  uint64_t Bits = 0;                    // Resulting bits

  // Check if help is needed
  if (CPU == "help")
    Help(CPUTable, CPUTableSize, FeatureTable, FeatureTableSize);

  // Find CPU entry
  const SubtargetFeatureKV *CPUEntry = Find(CPU, CPUTable, CPUTableSize);
  // If there is a match
  if (CPUEntry) {
    // Set base feature bits
    Bits = CPUEntry->Value;

    // Set the feature implied by this CPU feature, if any.
    for (size_t i = 0; i < FeatureTableSize; ++i) {
      const SubtargetFeatureKV &FE = FeatureTable[i];
      if (CPUEntry->Value & FE.Value)
        SetImpliedBits(Bits, &FE, FeatureTable, FeatureTableSize);
    }
  } else {
    errs() << "'" << CPU
           << "' is not a recognized processor for this target"
           << " (ignoring processor)\n";
  }
  // Iterate through each feature
  for (size_t i = 0, E = Features.size(); i < E; i++) {
    const StringRef Feature = Features[i];

    // Check for help
    if (Feature == "+help")
      Help(CPUTable, CPUTableSize, FeatureTable, FeatureTableSize);

    // Find feature in table.
    const SubtargetFeatureKV *FeatureEntry =
                       Find(StripFlag(Feature), FeatureTable, FeatureTableSize);
    // If there is a match
    if (FeatureEntry) {
      // Enable/disable feature in bits
      if (isEnabled(Feature)) {
        Bits |=  FeatureEntry->Value;

        // For each feature that this implies, set it.
        SetImpliedBits(Bits, FeatureEntry, FeatureTable, FeatureTableSize);
      } else {
        Bits &= ~FeatureEntry->Value;

        // For each feature that implies this, clear it.
        ClearImpliedBits(Bits, FeatureEntry, FeatureTable, FeatureTableSize);
      }
    } else {
      errs() << "'" << Feature
             << "' is not a recognized feature for this target"
             << " (ignoring feature)\n";
    }
  }

  return Bits;
}

/// Get scheduling itinerary of a CPU.
void *SubtargetFeatures::getItinerary(const StringRef CPU,
                                      const SubtargetInfoKV *Table,
                                      size_t TableSize) {
  assert(Table && "missing table");
#ifndef NDEBUG
  for (size_t i = 1; i < TableSize; i++) {
    assert(strcmp(Table[i - 1].Key, Table[i].Key) < 0 && "Table is not sorted");
  }
#endif

  // Find entry
  const SubtargetInfoKV *Entry = Find(CPU, Table, TableSize);

  if (Entry) {
    return Entry->Value;
  } else {
    errs() << "'" << CPU
           << "' is not a recognized processor for this target"
           << " (ignoring processor)\n";
    return NULL;
  }
}

/// print - Print feature string.
///
void SubtargetFeatures::print(raw_ostream &OS) const {
  for (size_t i = 0, e = Features.size(); i != e; ++i)
    OS << Features[i] << "  ";
  OS << "\n";
}

/// dump - Dump feature info.
///
void SubtargetFeatures::dump() const {
  print(dbgs());
}

/// getDefaultSubtargetFeatures - Return a string listing the features
/// associated with the target triple.
///
/// FIXME: This is an inelegant way of specifying the features of a
/// subtarget. It would be better if we could encode this information
/// into the IR. See <rdar://5972456>.
///
void SubtargetFeatures::getDefaultSubtargetFeatures(const Triple& Triple) {
  if (Triple.getVendor() == Triple::Apple) {
    if (Triple.getArch() == Triple::ppc) {
      // powerpc-apple-*
      AddFeature("altivec");
    } else if (Triple.getArch() == Triple::ppc64) {
      // powerpc64-apple-*
      AddFeature("64bit");
      AddFeature("altivec");
    }
  }
}
<|endoftext|>


<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/nest/p9_htm_start.C $      */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2015,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
/// ----------------------------------------------------------------------------
/// @file  p9_htm_start.C
///
/// @brief Start the HTM collection from a processor chip
///
/// The purpose of this procedure is to start the HTM collection from a
/// processor chip.
///
///
///----------------------------------------------------------------------------
/// *HWP HWP Owner   : Joe McGill <jmcgill@us.ibm.com>
/// *HWP FW Owner    : Thi Tran <thi@us.ibm.com>
/// *HWP Team        : Nest
/// *HWP Level       : 1
/// *HWP Consumed by : HB
///----------------------------------------------------------------------------

//------------------------------------------------------------------------------
// Includes
//------------------------------------------------------------------------------
#include <p9_htm_start.H>
#include <p9_htm_setup.H>
#include <p9_misc_scom_addresses.H>
#include <p9_quad_scom_addresses.H>

extern "C" {

///
/// @brief Start HTM collection
///
/// @param[in] i_target         Reference to Processor Chip target
/// @param[in] i_htmModeRegAddr The associated HTM Mode Register
///
/// @return FAPI2_RC_SUCCESS if success, else error code.
///
    fapi2::ReturnCode startHTM(
        const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target,
        const uint64_t i_htmModeRegAddr)
    {
        FAPI_INF("startHTM");
        fapi2::ReturnCode l_rc;
        fapi2::buffer<uint64_t> l_scomData(0);
        uint32_t l_htmPendingActionCount = 0;
        bool l_htmReady = false;

        // Verify HTM is in "Complete" state
        FAPI_TRY(fapi2::getScom(i_target, i_htmModeRegAddr + HTM_STAT, l_scomData),
                 "startHTM: getScom returns error (1): Addr "
                 "0x%016llX, l_rc 0x%.8X",
                 i_htmModeRegAddr + HTM_STAT,
                 (uint64_t)fapi2::current_err);

        FAPI_ASSERT( (l_scomData & HTM_STAT_COMPLETE),
                     fapi2::PROC_HTM_CTRL_BAD_STATE()
                     .set_HTM_STATUS_REG(l_scomData)
                     .set_TARGET(i_target),
                     "startHTM: HTM is not in Complete state, can't reset "
                     "HTM_STAT 0x%016llX", l_scomData);

        // Trigger START
        l_scomData = 0;
        l_scomData.setBit<HTM_TRIG_RESET>();
        FAPI_TRY(fapi2::putScom(i_target, i_htmModeRegAddr + HTM_TRIG, l_scomData),
                 "startHTM: putScom returns error: "
                 "Addr 0x%016llX, l_rc 0x%.8X",
                 i_htmModeRegAddr + HTM_TRIG,
                 (uint64_t)fapi2::current_err);

        // Waiting for Ready state
        FAPI_INF("startHTM: Waiting for action to complete...");
        l_htmReady = false;

        while (l_htmPendingActionCount < PROC_HTM_CTRL_TIMEOUT_COUNT)
        {
            FAPI_TRY(fapi2::delay(PROC_HTM_CTRL_HW_NS_DELAY,
                                  PROC_HTM_CTRL_SIM_CYCLE_DELAY),
                     "startHTM: fapi delay returns an error, l_rc 0x%.8X",
                     (uint64_t)fapi2::current_err);

            // Check ready bit
            FAPI_TRY(fapi2::getScom(i_target, i_htmModeRegAddr + HTM_STAT, l_scomData),
                     "startHTM: getScom returns error (2): "
                     "Addr 0x%016llX, l_rc 0x%.8X",
                     i_htmModeRegAddr + HTM_STAT,
                     (uint64_t)fapi2::current_err);

            if (l_scomData & HTM_STAT_READY)
            {
                l_htmReady = true;
                FAPI_INF("startHTM: HTM is ready.");
                break;
            }

            // "Complete" is not asserted yet; increment timeout and check again
            l_htmPendingActionCount++;
        }

        // Error out if Ready state is not set
        FAPI_ASSERT( (l_htmReady == true), fapi2::PROC_HTM_CTRL_TIMEOUT()
                     .set_DELAY_COUNT(l_htmPendingActionCount)
                     .set_HTM_STATUS_REG(l_scomData),
                     "startHTM: Timeout waiting for Ready state, Count 0x%.8X, "
                     "HTM_STAT 0x%016llX", l_htmPendingActionCount, l_scomData );

    fapi_try_exit:
        return fapi2::current_err;
    }

///
/// @brief p9_htm_start procedure entry point
/// See doxygen in p9_htm_start.H
///
    fapi2::ReturnCode p9_htm_start(
        const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target)
    {
        FAPI_DBG("Entering p9_htm_start");

        fapi2::ReturnCode l_rc;
        uint8_t l_nhtm_trace_type = 0;
        uint8_t l_chtm_trace_type = 0;
        auto l_modeRegList = std::vector<uint64_t>();

        // Get NTHM trace option
        FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_NHTM_TRACE_TYPE, i_target,
                               l_nhtm_trace_type),
                 "p9_htm_start: Error getting ATTR_NHTM_TRACE_TYPE, l_rc 0x%.8X",
                 (uint64_t)fapi2::current_err);

        // Get CTHM trace option
        FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CHTM_TRACE_TYPE, i_target,
                               l_chtm_trace_type),
                 "p9_htm_start: Error getting ATTR_CHTM_TRACE_TYPE, l_rc 0x%.8X",
                 (uint64_t)fapi2::current_err);

        // Display enabled HTM trace types
        FAPI_INF("p9_htm_start: NHTM type: 0x%.8X, CHTM type: 0x%.8X",
                 l_nhtm_trace_type, l_chtm_trace_type);

        // If no HTM trace collection is enabled, exit.
        if ( (l_nhtm_trace_type == fapi2::ENUM_ATTR_NHTM_TRACE_TYPE_DISABLE) &&
             (l_chtm_trace_type == fapi2::ENUM_ATTR_CHTM_TRACE_TYPE_DISABLE) )
        {
            FAPI_INF("p9_htm_start: HTM traces are disabled.");
            return l_rc;
        }

        // --------- Get the registers for Nest HTM ----------------------
        if (l_nhtm_trace_type != fapi2::ENUM_ATTR_NHTM_TRACE_TYPE_DISABLE)
        {
            l_modeRegList.push_back(PU_HTM0_HTM_MODE);
            l_modeRegList.push_back(PU_HTM1_HTM_MODE);
        }

        // --------- Get the register for Core HTM ----------------------
        if (l_chtm_trace_type != fapi2::ENUM_ATTR_CHTM_TRACE_TYPE_DISABLE)
        {
            l_modeRegList.push_back(EQ_HTM_MODE);
        }

        // --------- Start HTM ----------------------
        for (auto itr = l_modeRegList.begin(); itr != l_modeRegList.end();
             ++itr)
        {
            FAPI_TRY( startHTM(i_target, (*itr)),
                      "p9_htm_start: startHTM() returns error: Addr 0x%016llX, "
                      "l_rc 0x%.8X",
                      (*itr), (uint64_t)fapi2::current_err );
        }

    fapi_try_exit:
        FAPI_DBG("Exiting p9_htm_start");
        return fapi2::current_err;
    }

} // extern "C"
<commit_msg>p9_htm_setup (L2) - Part 1: New files to be mirrored to HB<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/nest/p9_htm_start.C $      */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2015,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
/// ----------------------------------------------------------------------------
/// @file  p9_htm_start.C
///
/// @brief Start the HTM collection from a processor chip
///
/// The purpose of this procedure is to start the HTM collection from a
/// processor chip.
///
///
///----------------------------------------------------------------------------
/// *HWP HWP Owner   : Joe McGill <jmcgill@us.ibm.com>
/// *HWP FW Owner    : Thi Tran <thi@us.ibm.com>
/// *HWP Team        : Nest
/// *HWP Level       : 1
/// *HWP Consumed by : HB
///----------------------------------------------------------------------------

//------------------------------------------------------------------------------
// Includes
//------------------------------------------------------------------------------
#include <p9_htm_start.H>

extern "C" {

///
/// @brief p9_htm_start procedure entry point
/// See doxygen in p9_htm_start.H
///
    fapi2::ReturnCode p9_htm_start(
        const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target)
    {
        FAPI_DBG("Entering p9_htm_start");
        fapi2::ReturnCode l_rc;

        FAPI_DBG("Exiting p9_htm_start");
        return fapi2::current_err;
    }

} // extern "C"
<|endoftext|>


<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/perv/p9_start_cbs.C $      */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2015,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
//------------------------------------------------------------------------------
/// @file  p9_start_cbs.C
///
/// @brief Start CBS : Trigger CBS
//------------------------------------------------------------------------------
// *HWP HW Owner        : Abhishek Agarwal <abagarw8@in.ibm.com>
// *HWP HW Backup Owner : Srinivas V Naga <srinivan@in.ibm.com>
// *HWP FW Owner        : sunil kumar <skumar8j@in.ibm.com>
// *HWP Team            : Perv
// *HWP Level           : 2
// *HWP Consumed by     : SE:HB
//------------------------------------------------------------------------------

//## auto_generated
#include "p9_start_cbs.H"
//## auto_generated
#include "p9_const_common.H"

#include <p9_perv_scom_addresses.H>
#include <p9_perv_scom_addresses_fld.H>
#include <p9_perv_scom_addresses_fixes.H>
#include <p9_perv_scom_addresses_fld_fixes.H>

enum P9_START_CBS_Private_Constants
{
    P9_CFAM_CBS_POLL_COUNT = 20, // Observed Number of times CBS read for CBS_INTERNAL_STATE_VECTOR
    CBS_IDLE_VALUE = 0x002, // Read the value of CBS_CS_INTERNAL_STATE_VECTOR
    P9_CBS_IDLE_HW_NS_DELAY = 640000, // unit is nano seconds [min : 64k x (1/100MHz) = 64k x 10(-8) = 640 us
    //                       max : 64k x (1/50MHz) = 128k x 10(-8) = 1280 us]
    P9_CBS_IDLE_SIM_CYCLE_DELAY = 7500000 // unit is sim cycles,to match the poll count change( 250000 * 30 )
};

fapi2::ReturnCode p9_start_cbs(const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>
                               & i_target_chip,
                               const bool i_sbe_start)
{
    fapi2::buffer<uint32_t> l_read_reg ;
    bool l_read_vdn_pgood_status = false;
    bool l_sbe_start_value = false;
    bool l_fsi2pib_status = false;
    fapi2::buffer<uint32_t> l_data32;
    fapi2::buffer<uint32_t> l_data32_cbs_cs;
    int l_timeout = 0;
    FAPI_INF("p9_start_cbs: Entering ...");

    FAPI_DBG("Clearing  Selfboot message register before every boot ");
    // buffer is init value is 0
    FAPI_TRY(fapi2::putCfamRegister(i_target_chip, PERV_SB_MSG_FSI, l_data32));

    l_sbe_start_value = !i_sbe_start;

    FAPI_DBG("Configuring Prevent SBE start option");
    FAPI_IMP("SBE start value : %d", l_sbe_start_value);
    //Setting CBS_CS register value
    FAPI_TRY(fapi2::getCfamRegister(i_target_chip, PERV_CBS_CS_FSI,
                                    l_data32_cbs_cs));
    //CFAM.CBS_CS.CBS_CS_PREVENT_SBE_START = l_sbe_start_value
    l_data32_cbs_cs.writeBit<3>(l_sbe_start_value);
    FAPI_TRY(fapi2::putCfamRegister(i_target_chip, PERV_CBS_CS_FSI,
                                    l_data32_cbs_cs));

    FAPI_DBG("check for VDN_PGOOD");
    //Getting PERV_CBS_ENVSTAT register value
    FAPI_TRY(fapi2::getCfamRegister(i_target_chip, PERV_CBS_ENVSTAT_FSI,
                                    l_data32));
    l_read_vdn_pgood_status =
        l_data32.getBit<PERV_CBS_ENVSTAT_C4_VDN_GPOOD>();  //l_read_vdn_pgood_status = PERV_CBS_ENVSTAT.PERV_CBS_ENVSTAT_C4_VDN_GPOOD

    FAPI_ASSERT(l_read_vdn_pgood_status,
                fapi2::VDN_PGOOD_NOT_SET()
                .set_MASTER_CHIP(i_target_chip)
                .set_CBS_ENVSTAT_READ(l_data32),
                "ERROR:VDN_PGOOD OFF, CBS_ENVSTAT BIT 2 NOT SET");

    FAPI_DBG("Resetting CFAM Boot Sequencer (CBS) to flush value");
    //Setting CBS_CS register value
    FAPI_TRY(fapi2::getCfamRegister(i_target_chip, PERV_CBS_CS_FSI,
                                    l_data32_cbs_cs));
    l_data32_cbs_cs.clearBit<0>();  //CFAM.CBS_CS.CBS_CS_START_BOOT_SEQUENCER = 0
    FAPI_TRY(fapi2::putCfamRegister(i_target_chip, PERV_CBS_CS_FSI,
                                    l_data32_cbs_cs));

    FAPI_DBG("Triggering CFAM Boot Sequencer (CBS) to start");
    //Setting CBS_CS register value
    l_data32_cbs_cs.setBit<0>();  //CFAM.CBS_CS.CBS_CS_START_BOOT_SEQUENCER = 1
    FAPI_TRY(fapi2::putCfamRegister(i_target_chip, PERV_CBS_CS_FSI,
                                    l_data32_cbs_cs));

    FAPI_DBG("Check cbs_cs_internal_state_vector");
    l_timeout = P9_CFAM_CBS_POLL_COUNT;

    //UNTIL CBS_CS.CBS_CS_INTERNAL_STATE_VECTOR == CBS_IDLE_VALUE
    while (l_timeout != 0)
    {
        //Getting CBS_CS register value
        FAPI_TRY(fapi2::getCfamRegister(i_target_chip, PERV_CBS_CS_FSI,
                                        l_data32_cbs_cs));
        uint32_t l_poll_data = 0;    //uint32_t l_poll_data = CFAM.CBS_CS.CBS_CS_INTERNAL_STATE_VECTOR
        l_data32_cbs_cs.extractToRight<16, 16>(l_poll_data);

        if (l_poll_data == CBS_IDLE_VALUE)
        {
            break;
        }

        fapi2::delay(P9_CBS_IDLE_HW_NS_DELAY, P9_CBS_IDLE_SIM_CYCLE_DELAY);
        --l_timeout;
    }

    FAPI_DBG("Loop Count :%d", l_timeout);

    FAPI_ASSERT(l_timeout > 0,
                fapi2::CBS_NOT_IN_IDLE_STATE()
                .set_MASTER_CHIP_TARGET(i_target_chip)
                .set_MASTER_CHIP(i_target_chip)
                .set_CBS_CS_READ(l_data32_cbs_cs)
                .set_CBS_CS_IDLE_VALUE(CBS_IDLE_VALUE)
                .set_LOOP_COUNT(l_timeout)
                .set_HW_DELAY(P9_CBS_IDLE_HW_NS_DELAY),
                "ERROR: CBS HAS NOT REACHED IDLE STATE VALUE 0x002 ");

    FAPI_DBG("check for VDD status");
    //Getting FSI2PIB_STATUS register value
    FAPI_TRY(fapi2::getCfamRegister(i_target_chip, PERV_FSI2PIB_STATUS_FSI,
                                    l_data32));
    //l_fsi2pib_status = CFAM.FSI2PIB_STATUS.VDD_NEST_OBSERVE
    l_fsi2pib_status = l_data32.getBit<PERV_FSI2PIB_STATUS_VDD_NEST_OBSERVE>();

    FAPI_ASSERT(l_fsi2pib_status,
                fapi2::VDD_NEST_OBSERVE_NOT_SET()
                .set_MASTER_CHIP(i_target_chip)
                .set_FSI2PIB_STATUS_READ(l_data32),
                "ERROR:VDD OFF, FSI2PIB  BIT 16 NOT SET");

    FAPI_INF("p9_start_cbs: Exiting ...");

fapi_try_exit:
    return fapi2::current_err;

}
<commit_msg>p9_start_cbs: Make sure SKIP_SCAN0_CLOCKSTART is off<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/perv/p9_start_cbs.C $      */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2015,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
//------------------------------------------------------------------------------
/// @file  p9_start_cbs.C
///
/// @brief Start CBS : Trigger CBS
//------------------------------------------------------------------------------
// *HWP HW Owner        : Abhishek Agarwal <abagarw8@in.ibm.com>
// *HWP HW Backup Owner : Srinivas V Naga <srinivan@in.ibm.com>
// *HWP FW Owner        : sunil kumar <skumar8j@in.ibm.com>
// *HWP Team            : Perv
// *HWP Level           : 2
// *HWP Consumed by     : SE:HB
//------------------------------------------------------------------------------

//## auto_generated
#include "p9_start_cbs.H"
//## auto_generated
#include "p9_const_common.H"

#include <p9_perv_scom_addresses.H>
#include <p9_perv_scom_addresses_fld.H>
#include <p9_perv_scom_addresses_fixes.H>
#include <p9_perv_scom_addresses_fld_fixes.H>

enum P9_START_CBS_Private_Constants
{
    P9_CFAM_CBS_POLL_COUNT = 20, // Observed Number of times CBS read for CBS_INTERNAL_STATE_VECTOR
    CBS_IDLE_VALUE = 0x002, // Read the value of CBS_CS_INTERNAL_STATE_VECTOR
    P9_CBS_IDLE_HW_NS_DELAY = 640000, // unit is nano seconds [min : 64k x (1/100MHz) = 64k x 10(-8) = 640 us
    //                       max : 64k x (1/50MHz) = 128k x 10(-8) = 1280 us]
    P9_CBS_IDLE_SIM_CYCLE_DELAY = 7500000 // unit is sim cycles,to match the poll count change( 250000 * 30 )
};

fapi2::ReturnCode p9_start_cbs(const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>
                               & i_target_chip,
                               const bool i_sbe_start)
{
    fapi2::buffer<uint32_t> l_read_reg ;
    bool l_read_vdn_pgood_status = false;
    bool l_sbe_start_value = false;
    bool l_fsi2pib_status = false;
    fapi2::buffer<uint32_t> l_data32;
    fapi2::buffer<uint32_t> l_data32_cbs_cs;
    int l_timeout = 0;
    FAPI_INF("p9_start_cbs: Entering ...");

    FAPI_DBG("Clearing  Selfboot message register before every boot ");
    // buffer is init value is 0
    FAPI_TRY(fapi2::putCfamRegister(i_target_chip, PERV_SB_MSG_FSI, l_data32));

    l_sbe_start_value = !i_sbe_start;

    FAPI_DBG("Configuring Prevent SBE start option");
    FAPI_IMP("SBE start value : %d", l_sbe_start_value);
    //Setting CBS_CS register value
    FAPI_TRY(fapi2::getCfamRegister(i_target_chip, PERV_CBS_CS_FSI,
                                    l_data32_cbs_cs));
    l_data32_cbs_cs.writeBit<PERV_CBS_CS_OPTION_PREVENT_SBE_START>(l_sbe_start_value);
    FAPI_TRY(fapi2::putCfamRegister(i_target_chip, PERV_CBS_CS_FSI,
                                    l_data32_cbs_cs));

    FAPI_DBG("check for VDN_PGOOD");
    //Getting PERV_CBS_ENVSTAT register value
    FAPI_TRY(fapi2::getCfamRegister(i_target_chip, PERV_CBS_ENVSTAT_FSI,
                                    l_data32));
    l_read_vdn_pgood_status = l_data32.getBit<PERV_CBS_ENVSTAT_C4_VDN_GPOOD>();

    FAPI_ASSERT(l_read_vdn_pgood_status,
                fapi2::VDN_PGOOD_NOT_SET()
                .set_MASTER_CHIP(i_target_chip)
                .set_CBS_ENVSTAT_READ(l_data32),
                "ERROR:VDN_PGOOD OFF, CBS_ENVSTAT BIT 2 NOT SET");

    FAPI_DBG("Resetting CFAM Boot Sequencer (CBS) to flush value");
    //Setting CBS_CS register value
    FAPI_TRY(fapi2::getCfamRegister(i_target_chip, PERV_CBS_CS_FSI,
                                    l_data32_cbs_cs));
    l_data32_cbs_cs.clearBit<PERV_CBS_CS_START_BOOT_SEQUENCER>();
    l_data32_cbs_cs.clearBit<PERV_CBS_CS_OPTION_SKIP_SCAN0_CLOCKSTART>();
    FAPI_TRY(fapi2::putCfamRegister(i_target_chip, PERV_CBS_CS_FSI,
                                    l_data32_cbs_cs));

    FAPI_DBG("Triggering CFAM Boot Sequencer (CBS) to start");
    //Setting CBS_CS register value
    l_data32_cbs_cs.setBit<PERV_CBS_CS_START_BOOT_SEQUENCER>();
    FAPI_TRY(fapi2::putCfamRegister(i_target_chip, PERV_CBS_CS_FSI,
                                    l_data32_cbs_cs));

    FAPI_DBG("Check cbs_cs_internal_state_vector");
    l_timeout = P9_CFAM_CBS_POLL_COUNT;

    //UNTIL CBS_CS.CBS_CS_INTERNAL_STATE_VECTOR == CBS_IDLE_VALUE
    while (l_timeout != 0)
    {
        //Getting CBS_CS register value
        FAPI_TRY(fapi2::getCfamRegister(i_target_chip, PERV_CBS_CS_FSI,
                                        l_data32_cbs_cs));
        uint32_t l_poll_data = 0;
        l_data32_cbs_cs.extractToRight<PERV_CBS_CS_INTERNAL_STATE_VECTOR, PERV_CBS_CS_INTERNAL_STATE_VECTOR_LEN>(l_poll_data);

        if (l_poll_data == CBS_IDLE_VALUE)
        {
            break;
        }

        fapi2::delay(P9_CBS_IDLE_HW_NS_DELAY, P9_CBS_IDLE_SIM_CYCLE_DELAY);
        --l_timeout;
    }

    FAPI_DBG("Loop Count :%d", l_timeout);

    FAPI_ASSERT(l_timeout > 0,
                fapi2::CBS_NOT_IN_IDLE_STATE()
                .set_MASTER_CHIP_TARGET(i_target_chip)
                .set_MASTER_CHIP(i_target_chip)
                .set_CBS_CS_READ(l_data32_cbs_cs)
                .set_CBS_CS_IDLE_VALUE(CBS_IDLE_VALUE)
                .set_LOOP_COUNT(l_timeout)
                .set_HW_DELAY(P9_CBS_IDLE_HW_NS_DELAY),
                "ERROR: CBS HAS NOT REACHED IDLE STATE VALUE 0x002 ");

    FAPI_DBG("check for VDD status");
    //Getting FSI2PIB_STATUS register value
    FAPI_TRY(fapi2::getCfamRegister(i_target_chip, PERV_FSI2PIB_STATUS_FSI,
                                    l_data32));
    l_fsi2pib_status = l_data32.getBit<PERV_FSI2PIB_STATUS_VDD_NEST_OBSERVE>();

    FAPI_ASSERT(l_fsi2pib_status,
                fapi2::VDD_NEST_OBSERVE_NOT_SET()
                .set_MASTER_CHIP(i_target_chip)
                .set_FSI2PIB_STATUS_READ(l_data32),
                "ERROR:VDD OFF, FSI2PIB  BIT 16 NOT SET");

    FAPI_INF("p9_start_cbs: Exiting ...");

fapi_try_exit:
    return fapi2::current_err;

}
<|endoftext|>