<commit_before>/*
 * Copyright (C) 2012 by Glenn Hickey (hickey@soe.ucsc.edu)
 *
 * Released under the MIT license, see LICENSE.txt
 */

#include <cstdlib>
#include <iostream>
#include <cassert>
#include <fstream>
#include <deque>

#include "sgbuilder.h"
#include "sgsql.h"

using namespace std;
using namespace hal;

static bool isCamelHal(AlignmentConstPtr aligment);
static void breadthFirstGenomeSearch(const Genome* reference,
                                     const vector<const Genome*>& targets,
                                     vector<const Genome*>& outTraversal);

static CLParserPtr initParser()
{
  CLParserPtr optionsParser = hdf5CLParserInstance();
  optionsParser->addArgument("halFile", "input hal file");
  optionsParser->addArgument("fastaFile", "Output FASTA sequences");
  optionsParser->addArgument("sqlFile", "SQL inserts written here");
  optionsParser->addOption("refGenome",
                           "name of reference genome (HAL root if empty)",
                           "\"\"");
  optionsParser->addOption("rootGenome",
                           "process only genomes in clade with specified root"
                           " (HAL root if empty)",
                           "\"\"");
  optionsParser->addOption("targetGenomes",
                           "comma-separated (no spaces) list of target genomes "
                           "(others are excluded) (vist all if empty)",
                           "\"\"");
  optionsParser->addOptionFlag("noAncestors",
                               "don't write ancestral paths. Note that "
                               "ancestral *sequences* may still get written"
                               " as they can be necessary for expressing"
                               " some alignments. IMPORTANT: "
                               "Must be used in conjunction with --refGenome"
                               " to set a non-ancestral genome as the reference"
                               " because the default reference is the root.",
                               false);
  optionsParser->addOptionFlag("onlySequenceNames",
                               "use only sequence names for output names.  By "
                               "default, the UCSC convention of "
                               "Genome.Sequence is used",
                               false);

  optionsParser->setDescription("Convert HAL alignment to GA4GH Side "
                                "Graph SQL format");
  return optionsParser;
}

int main(int argc, char** argv)
{
  CLParserPtr optionsParser = initParser();
  string halPath;
  string fastaPath;
  string sqlPath;
  string refGenomeName;
  string rootGenomeName;
  string targetGenomes;
  bool noAncestors;
  bool onlySequenceNames;
  try
  {
    optionsParser->parseOptions(argc, argv);
    halPath = optionsParser->getArgument<string>("halFile");
    fastaPath = optionsParser->getArgument<string>("fastaFile");
    sqlPath = optionsParser->getArgument<string>("sqlFile");
    refGenomeName = optionsParser->getOption<string>("refGenome");
    rootGenomeName = optionsParser->getOption<string>("rootGenome");
    targetGenomes = optionsParser->getOption<string>("targetGenomes");
    noAncestors = optionsParser->getFlag("noAncestors");
    onlySequenceNames = optionsParser->getFlag("onlySequenceNames");
    if (rootGenomeName != "\"\"" && targetGenomes != "\"\"")
    {
      throw hal_exception("--rootGenome and --targetGenomes options are "
                          "mutually exclusive");
    }
  }
  catch(exception& e)
  {
    cerr << e.what() << endl;
    optionsParser->printUsage(cerr);
    exit(1);
  }
  try
  {
    ofstream fastaStream(fastaPath.c_str());
    if (!fastaStream)
    {
      throw hal_exception("error opening output fasta file " + fastaPath);
    }
    fastaStream.close();

    ofstream sqlStream(sqlPath.c_str());
    if (!sqlStream)
    {
      throw hal_exception("error opening output sql file " + sqlPath);
    }
    sqlStream.close();

    AlignmentConstPtr alignment = openHalAlignmentReadOnly(halPath,
                                                           optionsParser);
    if (alignment->getNumGenomes() == 0)
    {
      throw hal_exception("hal alignmenet is empty");
    }

    // root is specified either by the parameter or as the alignment root
    // by default
    const Genome* rootGenome = NULL;
    if (rootGenomeName != "\"\"")
    {
      rootGenome = alignment->openGenome(rootGenomeName);
    }
    else
    {
      rootGenome = alignment->openGenome(alignment->getRootName());
    }
    if (rootGenome == NULL)
    {
      throw hal_exception(string("Root genome, ") + rootGenomeName +
                          ", not found in alignment");
    }

    // if target set not specified we default to all leaves under the
    // given root.
    vector<const Genome*> targetVec;
    if (targetGenomes == "\"\"")
    {
      set<const Genome*> allGenomes;
      getGenomesInSubTree(rootGenome, allGenomes);
      for (set<const Genome*>::iterator i = allGenomes.begin();
           i != allGenomes.end(); ++i)
      {
        if ((*i)->getNumChildren() == 0)
        {
          targetVec.push_back(*i);
        }
      }
    }
    // target genomes pulled from list.
    else
    {
      vector<string> targetNames = chopString(targetGenomes, ",");
      for (size_t i = 0; i < targetNames.size(); ++i)
      {
        const Genome* tgtGenome = alignment->openGenome(targetNames[i]);
        if (tgtGenome == NULL)
        {
          throw hal_exception(string("Target genome, ") + targetNames[i] +
                              ", not found in alignment");
        }
        targetVec.push_back(tgtGenome);
      }
    }

    // open the reference genome (root genome if unspecified)
    const Genome* refGenome = NULL;
    if (refGenomeName != "\"\"")
    {
      refGenome = alignment->openGenome(refGenomeName);
      if (refGenome == NULL)
      {
        throw hal_exception(string("Reference genome, ") + refGenomeName +
                            ", not found in alignment");
      }
      set<const Genome*> genomeSet;
      genomeSet.insert(refGenome);
      genomeSet.insert(rootGenome);
      if (getLowestCommonAncestor(genomeSet) != rootGenome)
      {
        throw hal_exception(string("reference genome must be under root"));
      }
    }
    else
    {
      refGenome = rootGenome;
    }

    // make sure refGenome not in target genomes
    for (vector<const Genome*>::iterator i = targetVec.begin();
         i != targetVec.end(); ++i)
    {
      if (*i == refGenome)
      {
        targetVec.erase(i);
        break;
      }
    }

    // get a breadth-first ordering of all target genomes
    // starting at the reference and including any ancestors
    // that need to get walked across
    vector<const Genome*> breadthFirstOrdering;
    breadthFirstGenomeSearch(refGenome, targetVec, breadthFirstOrdering);

    bool camelMode = isCamelHal(alignment);
    if (camelMode)
    {
      cout << "CAMEL output detected.  Will infer root sequence "
           << "from children" << endl;
    }
    SGBuilder sgbuild;
    sgbuild.init(alignment, rootGenome, false, isCamelHal(alignment),
                 onlySequenceNames);

    // add the genomes in the breadth first order
    for (size_t i = 0; i < breadthFirstOrdering.size(); ++i)
    {
      sgbuild.addGenome(breadthFirstOrdering[i]);
    }

    // compute all the joins in second pass (and do sanity check
    // on every path in graph)
    sgbuild.computeJoins(!noAncestors);

    //cout << *sgbuild.getSideGraph() << endl;

    SGSQL sqlWriter;
    sqlWriter.writeDb(&sgbuild, sqlPath, fastaPath, halPath,
                      !noAncestors);

  }
/*  catch(hal_exception& e)
  {
    cerr << "hal exception caught: " << e.what() << endl;
    return 1;
  }
  catch(exception& e)
  {
    cerr << "Exception caught: " << e.what() << endl;
    return 1;
  }
*/
  catch(int e) {}
  return 0;
}

/** CAMEL writes the root's DNA sequence as N's.  This screws up SNP detection
 * in the conversion when the root is used as the first anchor.  So we run a
 * check here to see if the root's all N's, if it is we set the camel flag
 * in sgbuilder to tell it to infer the root from its children (possible as
 * there are no substitutions in CAMEL HAL files */
bool isCamelHal(AlignmentConstPtr alignment)
{
  const Genome* rootGenome = alignment->openGenome(alignment->getRootName());
  if (rootGenome->getSequenceLength() == 0)
  {
    return false;
  }
  DNAIteratorConstPtr dnaIt = rootGenome->getDNAIterator();
  DNAIteratorConstPtr end = rootGenome->getDNAEndIterator();
  for (; !dnaIt->equals(end); dnaIt->toRight())
  {
    if (toupper(dnaIt->getChar()) != 'N')
    {
      return false;
    }
  }
  return true;
}

void breadthFirstGenomeSearch(const Genome* reference,
                              const vector<const Genome*>& targets,
                              vector<const Genome*>& outTraversal)
{
  // find all genomes we need to visit
  set<const Genome*> inputSet;
  inputSet.insert(reference);
  for (size_t i = 0; i < targets.size(); ++i)
  {
    inputSet.insert(targets[i]);
  }
  set<const Genome*> visitSet;
  getGenomesInSpanningTree(inputSet, visitSet);

  // find our breadth first order through the visit set, starting at
  // reference.
  set<const Genome*> flagged;
  deque<const Genome*> bfsQueue;
  bfsQueue.push_back(reference);
  while (!bfsQueue.empty())
  {
    const Genome* genome = bfsQueue.front();
    bfsQueue.pop_front();
    outTraversal.push_back(genome);
    vector<const Genome*> neighbours;
    for (hal_size_t i = 0; i < genome->getNumChildren(); ++i)
    {
      neighbours.push_back(genome->getChild(i));
    }
    if (genome->getParent() != NULL)
    {
      neighbours.push_back(genome->getParent());
    }
    for (hal_size_t i = 0; i < neighbours.size(); ++i)
    {
      const Genome* neighbour = neighbours[i];
      if (visitSet.find(neighbour) != visitSet.end() &&
          flagged.find(neighbour) == flagged.end())
      {
        bfsQueue.push_back(neighbour);
      }
    }
    flagged.insert(genome);
  }
}
<commit_msg>disable refgenome option for now<commit_after>/*
 * Copyright (C) 2012 by Glenn Hickey (hickey@soe.ucsc.edu)
 *
 * Released under the MIT license, see LICENSE.txt
 */

#include <cstdlib>
#include <iostream>
#include <cassert>
#include <fstream>
#include <deque>

#include "sgbuilder.h"
#include "sgsql.h"

using namespace std;
using namespace hal;

static bool isCamelHal(AlignmentConstPtr aligment);
static void breadthFirstGenomeSearch(const Genome* reference,
                                     const vector<const Genome*>& targets,
                                     vector<const Genome*>& outTraversal);

static CLParserPtr initParser()
{
  CLParserPtr optionsParser = hdf5CLParserInstance();
  optionsParser->addArgument("halFile", "input hal file");
  optionsParser->addArgument("fastaFile", "Output FASTA sequences");
  optionsParser->addArgument("sqlFile", "SQL inserts written here");
  optionsParser->addOption("refGenome",
                           "name of reference genome (HAL root if empty)",
                           "\"\"");
  optionsParser->addOption("rootGenome",
                           "process only genomes in clade with specified root"
                           " (HAL root if empty)",
                           "\"\"");
  optionsParser->addOption("targetGenomes",
                           "comma-separated (no spaces) list of target genomes "
                           "(others are excluded) (vist all if empty)",
                           "\"\"");
  optionsParser->addOptionFlag("noAncestors",
                               "don't write ancestral paths. Note that "
                               "ancestral *sequences* may still get written"
                               " as they can be necessary for expressing"
                               " some alignments. IMPORTANT: "
                               "Must be used in conjunction with --refGenome"
                               " to set a non-ancestral genome as the reference"
                               " because the default reference is the root.",
                               false);
  optionsParser->addOptionFlag("onlySequenceNames",
                               "use only sequence names for output names.  By "
                               "default, the UCSC convention of "
                               "Genome.Sequence is used",
                               false);

  optionsParser->setDescription("Convert HAL alignment to GA4GH Side "
                                "Graph SQL format");
  return optionsParser;
}

int main(int argc, char** argv)
{
  CLParserPtr optionsParser = initParser();
  string halPath;
  string fastaPath;
  string sqlPath;
  string refGenomeName;
  string rootGenomeName;
  string targetGenomes;
  bool noAncestors;
  bool onlySequenceNames;
  try
  {
    optionsParser->parseOptions(argc, argv);
    halPath = optionsParser->getArgument<string>("halFile");
    fastaPath = optionsParser->getArgument<string>("fastaFile");
    sqlPath = optionsParser->getArgument<string>("sqlFile");
    refGenomeName = optionsParser->getOption<string>("refGenome");
    rootGenomeName = optionsParser->getOption<string>("rootGenome");
    targetGenomes = optionsParser->getOption<string>("targetGenomes");
    noAncestors = optionsParser->getFlag("noAncestors");
    onlySequenceNames = optionsParser->getFlag("onlySequenceNames");
    if (rootGenomeName != "\"\"" && targetGenomes != "\"\"")
    {
      throw hal_exception("--rootGenome and --targetGenomes options are "
                          "mutually exclusive");
    }
    // temp
    if (refGenomeName != "\"\"")
    {
      throw hal_exception("--refGenome option temporarily out of service");
    }
  }
  catch(exception& e)
  {
    cerr << e.what() << endl;
    optionsParser->printUsage(cerr);
    exit(1);
  }
  try
  {
    ofstream fastaStream(fastaPath.c_str());
    if (!fastaStream)
    {
      throw hal_exception("error opening output fasta file " + fastaPath);
    }
    fastaStream.close();

    ofstream sqlStream(sqlPath.c_str());
    if (!sqlStream)
    {
      throw hal_exception("error opening output sql file " + sqlPath);
    }
    sqlStream.close();

    AlignmentConstPtr alignment = openHalAlignmentReadOnly(halPath,
                                                           optionsParser);
    if (alignment->getNumGenomes() == 0)
    {
      throw hal_exception("hal alignmenet is empty");
    }

    // root is specified either by the parameter or as the alignment root
    // by default
    const Genome* rootGenome = NULL;
    if (rootGenomeName != "\"\"")
    {
      rootGenome = alignment->openGenome(rootGenomeName);
    }
    else
    {
      rootGenome = alignment->openGenome(alignment->getRootName());
    }
    if (rootGenome == NULL)
    {
      throw hal_exception(string("Root genome, ") + rootGenomeName +
                          ", not found in alignment");
    }

    // if target set not specified we default to all leaves under the
    // given root.
    vector<const Genome*> targetVec;
    if (targetGenomes == "\"\"")
    {
      set<const Genome*> allGenomes;
      getGenomesInSubTree(rootGenome, allGenomes);
      for (set<const Genome*>::iterator i = allGenomes.begin();
           i != allGenomes.end(); ++i)
      {
        if ((*i)->getNumChildren() == 0)
        {
          targetVec.push_back(*i);
        }
      }
    }
    // target genomes pulled from list.
    else
    {
      vector<string> targetNames = chopString(targetGenomes, ",");
      for (size_t i = 0; i < targetNames.size(); ++i)
      {
        const Genome* tgtGenome = alignment->openGenome(targetNames[i]);
        if (tgtGenome == NULL)
        {
          throw hal_exception(string("Target genome, ") + targetNames[i] +
                              ", not found in alignment");
        }
        targetVec.push_back(tgtGenome);
      }
    }

    // open the reference genome (root genome if unspecified)
    const Genome* refGenome = NULL;
    if (refGenomeName != "\"\"")
    {
      refGenome = alignment->openGenome(refGenomeName);
      if (refGenome == NULL)
      {
        throw hal_exception(string("Reference genome, ") + refGenomeName +
                            ", not found in alignment");
      }
      set<const Genome*> genomeSet;
      genomeSet.insert(refGenome);
      genomeSet.insert(rootGenome);
      if (getLowestCommonAncestor(genomeSet) != rootGenome)
      {
        throw hal_exception(string("reference genome must be under root"));
      }
    }
    else
    {
      refGenome = rootGenome;
    }

    // make sure refGenome not in target genomes
    for (vector<const Genome*>::iterator i = targetVec.begin();
         i != targetVec.end(); ++i)
    {
      if (*i == refGenome)
      {
        targetVec.erase(i);
        break;
      }
    }

    // get a breadth-first ordering of all target genomes
    // starting at the reference and including any ancestors
    // that need to get walked across
    vector<const Genome*> breadthFirstOrdering;
    breadthFirstGenomeSearch(refGenome, targetVec, breadthFirstOrdering);

    bool camelMode = isCamelHal(alignment);
    if (camelMode)
    {
      cout << "CAMEL output detected.  Will infer root sequence "
           << "from children" << endl;
    }
    SGBuilder sgbuild;
    sgbuild.init(alignment, rootGenome, false, isCamelHal(alignment),
                 onlySequenceNames);

    // add the genomes in the breadth first order
    for (size_t i = 0; i < breadthFirstOrdering.size(); ++i)
    {
      sgbuild.addGenome(breadthFirstOrdering[i]);
    }

    // compute all the joins in second pass (and do sanity check
    // on every path in graph)
    sgbuild.computeJoins(!noAncestors);

    //cout << *sgbuild.getSideGraph() << endl;

    SGSQL sqlWriter;
    sqlWriter.writeDb(&sgbuild, sqlPath, fastaPath, halPath,
                      !noAncestors);

  }
/*  catch(hal_exception& e)
  {
    cerr << "hal exception caught: " << e.what() << endl;
    return 1;
  }
  catch(exception& e)
  {
    cerr << "Exception caught: " << e.what() << endl;
    return 1;
  }
*/
  catch(int e) {}
  return 0;
}

/** CAMEL writes the root's DNA sequence as N's.  This screws up SNP detection
 * in the conversion when the root is used as the first anchor.  So we run a
 * check here to see if the root's all N's, if it is we set the camel flag
 * in sgbuilder to tell it to infer the root from its children (possible as
 * there are no substitutions in CAMEL HAL files */
bool isCamelHal(AlignmentConstPtr alignment)
{
  const Genome* rootGenome = alignment->openGenome(alignment->getRootName());
  if (rootGenome->getSequenceLength() == 0)
  {
    return false;
  }
  DNAIteratorConstPtr dnaIt = rootGenome->getDNAIterator();
  DNAIteratorConstPtr end = rootGenome->getDNAEndIterator();
  for (; !dnaIt->equals(end); dnaIt->toRight())
  {
    if (toupper(dnaIt->getChar()) != 'N')
    {
      return false;
    }
  }
  return true;
}

void breadthFirstGenomeSearch(const Genome* reference,
                              const vector<const Genome*>& targets,
                              vector<const Genome*>& outTraversal)
{
  // find all genomes we need to visit
  set<const Genome*> inputSet;
  inputSet.insert(reference);
  for (size_t i = 0; i < targets.size(); ++i)
  {
    inputSet.insert(targets[i]);
  }
  set<const Genome*> visitSet;
  getGenomesInSpanningTree(inputSet, visitSet);

  // find our breadth first order through the visit set, starting at
  // reference.
  set<const Genome*> flagged;
  deque<const Genome*> bfsQueue;
  bfsQueue.push_back(reference);
  while (!bfsQueue.empty())
  {
    const Genome* genome = bfsQueue.front();
    bfsQueue.pop_front();
    outTraversal.push_back(genome);
    vector<const Genome*> neighbours;
    for (hal_size_t i = 0; i < genome->getNumChildren(); ++i)
    {
      neighbours.push_back(genome->getChild(i));
    }
    if (genome->getParent() != NULL)
    {
      neighbours.push_back(genome->getParent());
    }
    for (hal_size_t i = 0; i < neighbours.size(); ++i)
    {
      const Genome* neighbour = neighbours[i];
      if (visitSet.find(neighbour) != visitSet.end() &&
          flagged.find(neighbour) == flagged.end())
      {
        bfsQueue.push_back(neighbour);
      }
    }
    flagged.insert(genome);
  }
}
<|endoftext|>


<commit_before>//--------------------------------------------------------------------*- C++ -*-
// CLING - the C++ LLVM-based InterpreterG :)
// author:  Axel Naumann <axel@cern.ch>
//
// This file is dual-licensed: you can choose to license it under the University
// of Illinois Open Source License or the GNU Lesser General Public License. See
// LICENSE.TXT for details.
//------------------------------------------------------------------------------

#include "IncrementalExecutor.h"
#include "IncrementalJIT.h"
#include "Threading.h"

#include "cling/Interpreter/Value.h"
#include "cling/Interpreter/Transaction.h"
#include "cling/Utils/AST.h"
#include "cling/Utils/Output.h"
#include "cling/Utils/Platform.h"

#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/TargetOptions.h"
#include "clang/Frontend/CodeGenOptions.h"
#include "clang/Frontend/CompilerInstance.h"

#include "llvm/IR/Constants.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Support/Host.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Target/TargetMachine.h"

using namespace llvm;

namespace cling {

namespace {

static std::unique_ptr<TargetMachine>
CreateHostTargetMachine(const clang::CompilerInstance& CI) {
  const clang::TargetOptions& TargetOpts = CI.getTargetOpts();
  const clang::CodeGenOptions& CGOpt = CI.getCodeGenOpts();
  const std::string& Triple = TargetOpts.Triple;

  std::string Error;
  const Target *TheTarget = TargetRegistry::lookupTarget(Triple, Error);
  if (!TheTarget) {
    cling::errs() << "cling::IncrementalExecutor: unable to find target:\n"
                  << Error;
    return std::unique_ptr<TargetMachine>();
  }

// We have to use large code model for PowerPC64 because TOC and text sections
// can be more than 2GB apart.
#if defined(__powerpc64__) || defined(__PPC64__)
  CodeModel::Model CMModel = CodeModel::Large;
#else
  CodeModel::Model CMModel = CodeModel::JITDefault;
#endif
  CodeGenOpt::Level OptLevel = CodeGenOpt::Default;
  switch (CGOpt.OptimizationLevel) {
    case 0: OptLevel = CodeGenOpt::None; break;
    case 1: OptLevel = CodeGenOpt::Less; break;
    case 2: OptLevel = CodeGenOpt::Default; break;
    case 3: OptLevel = CodeGenOpt::Aggressive; break;
    default: OptLevel = CodeGenOpt::Default;
  }

  std::string MCPU;
  std::string FeaturesStr;

  auto TM = std::unique_ptr<TargetMachine>(TheTarget->createTargetMachine(
      Triple, MCPU, FeaturesStr, llvm::TargetOptions(),
      Optional<Reloc::Model>(), CMModel, OptLevel));
  TM->Options.EmulatedTLS = true;
  return TM;
}

} // anonymous namespace

IncrementalExecutor::IncrementalExecutor(clang::DiagnosticsEngine& diags,
                                         const clang::CompilerInstance& CI):
  m_Callbacks(nullptr), m_externalIncrementalExecutor(nullptr)
#if 0
  : m_Diags(diags)
#endif
{

  // MSVC doesn't support m_AtExitFuncsSpinLock=ATOMIC_FLAG_INIT; in the class definition
  std::atomic_flag_clear( &m_AtExitFuncsSpinLock );

  std::unique_ptr<TargetMachine> TM(CreateHostTargetMachine(CI));
  m_BackendPasses.reset(new BackendPasses(CI.getCodeGenOpts(),
                                          CI.getTargetOpts(),
                                          CI.getLangOpts(),
                                          *TM));
  m_JIT.reset(new IncrementalJIT(*this, std::move(TM)));
}

// Keep in source: ~unique_ptr<ClingJIT> needs ClingJIT
IncrementalExecutor::~IncrementalExecutor() {}

void IncrementalExecutor::shuttingDown() {
  // It is legal to register an atexit handler from within another atexit
  // handler and furthor-more the standard says they need to run in reverse
  // order, so this function must be recursion safe.
  AtExitFunctions Local;
  {
    cling::internal::SpinLockGuard slg(m_AtExitFuncsSpinLock);
    // Check this case first, to avoid the swap all-together.
    if (m_AtExitFuncs.empty())
      return;
    Local.swap(m_AtExitFuncs);
  }
  for (auto&& Ordered : llvm::reverse(Local.ordered())) {
    for (auto&& AtExit : llvm::reverse(Ordered->second))
      AtExit();
    // The standard says that they need to run in reverse order, which means
    // anything added from 'AtExit()' must now be run!
    shuttingDown();
  }
}

void IncrementalExecutor::AddAtExitFunc(void (*func)(void*), void* arg,
                                       const std::shared_ptr<llvm::Module>& M) {
  // Register a CXAAtExit function
  cling::internal::SpinLockGuard slg(m_AtExitFuncsSpinLock);
  m_AtExitFuncs[M].emplace_back(func, arg);
}

void unresolvedSymbol()
{
  // This might get called recursively, or a billion of times. Do not generate
  // useless output; unresolvedSymbol() is always handed out with an error
  // message - that's enough.
  //cling::errs() << "IncrementalExecutor: calling unresolved symbol, "
  //  "see previous error message!\n";

  // throw exception instead?
}

void* IncrementalExecutor::HandleMissingFunction(const std::string& mangled_name)
{
  // Not found in the map, add the symbol in the list of unresolved symbols
  if (m_unresolvedSymbols.insert(mangled_name).second) {
    //cling::errs() << "IncrementalExecutor: use of undefined symbol '"
    //             << mangled_name << "'!\n";
  }

  return utils::FunctionToVoidPtr(&unresolvedSymbol);
}

void* IncrementalExecutor::NotifyLazyFunctionCreators(const std::string& mangled_name)
{
  for (std::vector<LazyFunctionCreatorFunc_t>::iterator it
         = m_lazyFuncCreator.begin(), et = m_lazyFuncCreator.end();
       it != et; ++it) {
    void* ret = (void*)((LazyFunctionCreatorFunc_t)*it)(mangled_name);
    if (ret)
      return ret;
  }
  void *address = nullptr;
  if (m_externalIncrementalExecutor)
   address = m_externalIncrementalExecutor->getAddressOfGlobal(mangled_name);

  return (address ? address : HandleMissingFunction(mangled_name));
}

#if 0
// FIXME: employ to empty module dependencies *within* the *current* module.
static void
freeCallersOfUnresolvedSymbols(llvm::SmallVectorImpl<llvm::Function*>&
                               funcsToFree, llvm::ExecutionEngine* engine) {
  llvm::SmallPtrSet<llvm::Function*, 40> funcsToFreeUnique;
  for (size_t i = 0; i < funcsToFree.size(); ++i) {
    llvm::Function* func = funcsToFree[i];
    assert(func && "Cannot free NULL function");
    if (funcsToFreeUnique.insert(func).second) {
      for (llvm::Value::use_iterator IU = func->use_begin(),
             EU = func->use_end(); IU != EU; ++IU) {
        llvm::Instruction* instUser = llvm::dyn_cast<llvm::Instruction>(*IU);
        if (!instUser) continue;
        if (!instUser->getParent()) continue;
        if (llvm::Function* userFunc = instUser->getParent()->getParent())
          funcsToFree.push_back(userFunc);
      }
    }
  }
  for (llvm::SmallPtrSet<llvm::Function*, 40>::iterator
         I = funcsToFreeUnique.begin(), E = funcsToFreeUnique.end();
       I != E; ++I) {
    // This should force the JIT to recompile the function. But the stubs stay,
    // and the JIT reuses the stubs now pointing nowhere, i.e. without updating
    // the machine code address. Fix the JIT, or hope that MCJIT helps.
    //engine->freeMachineCodeForFunction(*I);
    engine->updateGlobalMapping(*I, 0);
  }
}
#endif

IncrementalExecutor::ExecutionResult
IncrementalExecutor::runStaticInitializersOnce(const Transaction& T) {
  auto m = T.getModule();
  assert(m.get() && "Module must not be null");

  // We don't care whether something was unresolved before.
  m_unresolvedSymbols.clear();

  // check if there is any unresolved symbol in the list
  if (diagnoseUnresolvedSymbols("static initializers"))
    return kExeUnresolvedSymbols;

  llvm::GlobalVariable* GV
     = m->getGlobalVariable("llvm.global_ctors", true);
  // Nothing to do is good, too.
  if (!GV) return kExeSuccess;

  // Close similarity to
  // m_engine->runStaticConstructorsDestructors(false) aka
  // llvm::ExecutionEngine::runStaticConstructorsDestructors()
  // is intentional; we do an extra pass to check whether the JIT
  // managed to collect all the symbols needed by the niitializers.
  // Should be an array of '{ i32, void ()* }' structs.  The first value is
  // the init priority, which we ignore.
  llvm::ConstantArray *InitList
    = llvm::dyn_cast<llvm::ConstantArray>(GV->getInitializer());

  // We need to delete it here just in case we have recursive inits, otherwise
  // it will call inits multiple times.
  GV->eraseFromParent();

  if (InitList == 0)
    return kExeSuccess;

  //SmallVector<Function*, 2> initFuncs;

  for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) {
    llvm::ConstantStruct *CS
      = llvm::dyn_cast<llvm::ConstantStruct>(InitList->getOperand(i));
    if (CS == 0) continue;

    llvm::Constant *FP = CS->getOperand(1);
    if (FP->isNullValue())
      continue;  // Found a sentinal value, ignore.

    // Strip off constant expression casts.
    if (llvm::ConstantExpr *CE = llvm::dyn_cast<llvm::ConstantExpr>(FP))
      if (CE->isCast())
        FP = CE->getOperand(0);

    // Execute the ctor/dtor function!
    if (llvm::Function *F = llvm::dyn_cast<llvm::Function>(FP)) {
      const llvm::StringRef fName = F->getName();
      executeInit(fName);
/*
      initFuncs.push_back(F);
      if (fName.startswith("_GLOBAL__sub_I_")) {
        BasicBlock& BB = F->getEntryBlock();
        for (BasicBlock::iterator I = BB.begin(), E = BB.end(); I != E; ++I)
          if (CallInst* call = dyn_cast<CallInst>(I))
            initFuncs.push_back(call->getCalledFunction());
      }
*/
    }
  }

/*
  for (SmallVector<Function*,2>::iterator I = initFuncs.begin(),
         E = initFuncs.end(); I != E; ++I) {
    // Cleanup also the dangling init functions. They are in the form:
    // define internal void @_GLOBAL__I_aN() section "..."{
    // entry:
    //   call void @__cxx_global_var_init(N-1)()
    //   call void @__cxx_global_var_initM()
    //   ret void
    // }
    //
    // define internal void @__cxx_global_var_init(N-1)() section "..." {
    // entry:
    //   call void @_ZN7MyClassC1Ev(%struct.MyClass* @n)
    //   ret void
    // }

    // Erase __cxx_global_var_init(N-1)() first.
    (*I)->removeDeadConstantUsers();
    (*I)->eraseFromParent();
  }
*/

  return kExeSuccess;
}

void IncrementalExecutor::runAndRemoveStaticDestructors(Transaction* T) {
  assert(T && "Must be set");
  // Collect all the dtors bound to this transaction.
  AtExitFunctions::mapped_type Local;
  {
    cling::internal::SpinLockGuard slg(m_AtExitFuncsSpinLock);
    auto Itr = m_AtExitFuncs.find(T->getModule());
    if (Itr == m_AtExitFuncs.end()) return;
    m_AtExitFuncs.erase(Itr, &Local);
  } // end of spin lock lifetime block.

  // 'Unload' the cxa_atexit, atexit entities.
  for (auto&& AtExit : llvm::reverse(Local)) {
    AtExit();
    // Run anything that was just registered in 'AtExit()'
    runAndRemoveStaticDestructors(T);
  }
}

void
IncrementalExecutor::installLazyFunctionCreator(LazyFunctionCreatorFunc_t fp)
{
  m_lazyFuncCreator.push_back(fp);
}

bool
IncrementalExecutor::addSymbol(const char* Name,  void* Addr,
                               bool Jit) {
  return m_JIT->lookupSymbol(Name, Addr, Jit).second;
}

void* IncrementalExecutor::getAddressOfGlobal(llvm::StringRef symbolName,
                                              bool* fromJIT /*=0*/) {
  // Return a symbol's address, and whether it was jitted.
  void* address = m_JIT->lookupSymbol(symbolName).first;

  // It's not from the JIT if it's in a dylib.
  if (fromJIT)
    *fromJIT = !address;

  if (!address)
    return (void*)m_JIT->getSymbolAddress(symbolName, false /*no dlsym*/);

  return address;
}

void*
IncrementalExecutor::getPointerToGlobalFromJIT(const llvm::GlobalValue& GV) {
  // Get the function / variable pointer referenced by GV.

  // We don't care whether something was unresolved before.
  m_unresolvedSymbols.clear();

  void* addr = (void*)m_JIT->getSymbolAddress(GV.getName(),
                                              false /*no dlsym*/);

  if (diagnoseUnresolvedSymbols(GV.getName(), "symbol"))
    return 0;
  return addr;
}

bool IncrementalExecutor::diagnoseUnresolvedSymbols(llvm::StringRef trigger,
                                                    llvm::StringRef title) {
  if (m_unresolvedSymbols.empty())
    return false;

  llvm::SmallVector<llvm::Function*, 128> funcsToFree;
  for (const std::string& sym : m_unresolvedSymbols) {
#if 0
    // FIXME: This causes a lot of test failures, for some reason it causes
    // the call to HandleMissingFunction to be elided.
    unsigned diagID = m_Diags.getCustomDiagID(clang::DiagnosticsEngine::Error,
                                              "%0 unresolved while jitting %1");
    (void)diagID;
    //m_Diags.Report(diagID) << sym << funcname; // TODO: demangle the names.
#endif

    cling::errs() << "IncrementalExecutor::executeFunction: symbol '" << sym
                  << "' unresolved while linking ";
    if (trigger.find(utils::Synthesize::UniquePrefix) != llvm::StringRef::npos)
      cling::errs() << "[cling interface function]";
    else {
      if (!title.empty())
        cling::errs() << title << " '";
      cling::errs() << trigger;
      if (!title.empty())
        cling::errs() << "'";
    }
    cling::errs() << "!\n";

    // Be helpful, demangle!
    std::string demangledName = platform::Demangle(sym);
    if (!demangledName.empty()) {
       cling::errs()
          << "You are probably missing the definition of "
          << demangledName << "\n"
          << "Maybe you need to load the corresponding shared library?\n";
    }

    //llvm::Function *ff = m_engine->FindFunctionNamed(i->c_str());
    // i could also reference a global variable, in which case ff == 0.
    //if (ff)
    //  funcsToFree.push_back(ff);
  }
  //freeCallersOfUnresolvedSymbols(funcsToFree, m_engine.get());
  m_unresolvedSymbols.clear();
  return true;
}

}// end namespace cling
<commit_msg>Fix cling on Windows (there is no Emulated TLS on Windows)<commit_after>//--------------------------------------------------------------------*- C++ -*-
// CLING - the C++ LLVM-based InterpreterG :)
// author:  Axel Naumann <axel@cern.ch>
//
// This file is dual-licensed: you can choose to license it under the University
// of Illinois Open Source License or the GNU Lesser General Public License. See
// LICENSE.TXT for details.
//------------------------------------------------------------------------------

#include "IncrementalExecutor.h"
#include "IncrementalJIT.h"
#include "Threading.h"

#include "cling/Interpreter/Value.h"
#include "cling/Interpreter/Transaction.h"
#include "cling/Utils/AST.h"
#include "cling/Utils/Output.h"
#include "cling/Utils/Platform.h"

#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/TargetOptions.h"
#include "clang/Frontend/CodeGenOptions.h"
#include "clang/Frontend/CompilerInstance.h"

#include "llvm/IR/Constants.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Support/Host.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Target/TargetMachine.h"

using namespace llvm;

namespace cling {

namespace {

static std::unique_ptr<TargetMachine>
CreateHostTargetMachine(const clang::CompilerInstance& CI) {
  const clang::TargetOptions& TargetOpts = CI.getTargetOpts();
  const clang::CodeGenOptions& CGOpt = CI.getCodeGenOpts();
  const std::string& Triple = TargetOpts.Triple;

  std::string Error;
  const Target *TheTarget = TargetRegistry::lookupTarget(Triple, Error);
  if (!TheTarget) {
    cling::errs() << "cling::IncrementalExecutor: unable to find target:\n"
                  << Error;
    return std::unique_ptr<TargetMachine>();
  }

// We have to use large code model for PowerPC64 because TOC and text sections
// can be more than 2GB apart.
#if defined(__powerpc64__) || defined(__PPC64__)
  CodeModel::Model CMModel = CodeModel::Large;
#else
  CodeModel::Model CMModel = CodeModel::JITDefault;
#endif
  CodeGenOpt::Level OptLevel = CodeGenOpt::Default;
  switch (CGOpt.OptimizationLevel) {
    case 0: OptLevel = CodeGenOpt::None; break;
    case 1: OptLevel = CodeGenOpt::Less; break;
    case 2: OptLevel = CodeGenOpt::Default; break;
    case 3: OptLevel = CodeGenOpt::Aggressive; break;
    default: OptLevel = CodeGenOpt::Default;
  }

  std::string MCPU;
  std::string FeaturesStr;

  auto TM = std::unique_ptr<TargetMachine>(TheTarget->createTargetMachine(
      Triple, MCPU, FeaturesStr, llvm::TargetOptions(),
      Optional<Reloc::Model>(), CMModel, OptLevel));
#if defined(LLVM_ON_WIN32)
  TM->Options.EmulatedTLS = false;
#else
  TM->Options.EmulatedTLS = true;
#endif
  return TM;
}

} // anonymous namespace

IncrementalExecutor::IncrementalExecutor(clang::DiagnosticsEngine& diags,
                                         const clang::CompilerInstance& CI):
  m_Callbacks(nullptr), m_externalIncrementalExecutor(nullptr)
#if 0
  : m_Diags(diags)
#endif
{

  // MSVC doesn't support m_AtExitFuncsSpinLock=ATOMIC_FLAG_INIT; in the class definition
  std::atomic_flag_clear( &m_AtExitFuncsSpinLock );

  std::unique_ptr<TargetMachine> TM(CreateHostTargetMachine(CI));
  m_BackendPasses.reset(new BackendPasses(CI.getCodeGenOpts(),
                                          CI.getTargetOpts(),
                                          CI.getLangOpts(),
                                          *TM));
  m_JIT.reset(new IncrementalJIT(*this, std::move(TM)));
}

// Keep in source: ~unique_ptr<ClingJIT> needs ClingJIT
IncrementalExecutor::~IncrementalExecutor() {}

void IncrementalExecutor::shuttingDown() {
  // It is legal to register an atexit handler from within another atexit
  // handler and furthor-more the standard says they need to run in reverse
  // order, so this function must be recursion safe.
  AtExitFunctions Local;
  {
    cling::internal::SpinLockGuard slg(m_AtExitFuncsSpinLock);
    // Check this case first, to avoid the swap all-together.
    if (m_AtExitFuncs.empty())
      return;
    Local.swap(m_AtExitFuncs);
  }
  for (auto&& Ordered : llvm::reverse(Local.ordered())) {
    for (auto&& AtExit : llvm::reverse(Ordered->second))
      AtExit();
    // The standard says that they need to run in reverse order, which means
    // anything added from 'AtExit()' must now be run!
    shuttingDown();
  }
}

void IncrementalExecutor::AddAtExitFunc(void (*func)(void*), void* arg,
                                       const std::shared_ptr<llvm::Module>& M) {
  // Register a CXAAtExit function
  cling::internal::SpinLockGuard slg(m_AtExitFuncsSpinLock);
  m_AtExitFuncs[M].emplace_back(func, arg);
}

void unresolvedSymbol()
{
  // This might get called recursively, or a billion of times. Do not generate
  // useless output; unresolvedSymbol() is always handed out with an error
  // message - that's enough.
  //cling::errs() << "IncrementalExecutor: calling unresolved symbol, "
  //  "see previous error message!\n";

  // throw exception instead?
}

void* IncrementalExecutor::HandleMissingFunction(const std::string& mangled_name)
{
  // Not found in the map, add the symbol in the list of unresolved symbols
  if (m_unresolvedSymbols.insert(mangled_name).second) {
    //cling::errs() << "IncrementalExecutor: use of undefined symbol '"
    //             << mangled_name << "'!\n";
  }

  return utils::FunctionToVoidPtr(&unresolvedSymbol);
}

void* IncrementalExecutor::NotifyLazyFunctionCreators(const std::string& mangled_name)
{
  for (std::vector<LazyFunctionCreatorFunc_t>::iterator it
         = m_lazyFuncCreator.begin(), et = m_lazyFuncCreator.end();
       it != et; ++it) {
    void* ret = (void*)((LazyFunctionCreatorFunc_t)*it)(mangled_name);
    if (ret)
      return ret;
  }
  void *address = nullptr;
  if (m_externalIncrementalExecutor)
   address = m_externalIncrementalExecutor->getAddressOfGlobal(mangled_name);

  return (address ? address : HandleMissingFunction(mangled_name));
}

#if 0
// FIXME: employ to empty module dependencies *within* the *current* module.
static void
freeCallersOfUnresolvedSymbols(llvm::SmallVectorImpl<llvm::Function*>&
                               funcsToFree, llvm::ExecutionEngine* engine) {
  llvm::SmallPtrSet<llvm::Function*, 40> funcsToFreeUnique;
  for (size_t i = 0; i < funcsToFree.size(); ++i) {
    llvm::Function* func = funcsToFree[i];
    assert(func && "Cannot free NULL function");
    if (funcsToFreeUnique.insert(func).second) {
      for (llvm::Value::use_iterator IU = func->use_begin(),
             EU = func->use_end(); IU != EU; ++IU) {
        llvm::Instruction* instUser = llvm::dyn_cast<llvm::Instruction>(*IU);
        if (!instUser) continue;
        if (!instUser->getParent()) continue;
        if (llvm::Function* userFunc = instUser->getParent()->getParent())
          funcsToFree.push_back(userFunc);
      }
    }
  }
  for (llvm::SmallPtrSet<llvm::Function*, 40>::iterator
         I = funcsToFreeUnique.begin(), E = funcsToFreeUnique.end();
       I != E; ++I) {
    // This should force the JIT to recompile the function. But the stubs stay,
    // and the JIT reuses the stubs now pointing nowhere, i.e. without updating
    // the machine code address. Fix the JIT, or hope that MCJIT helps.
    //engine->freeMachineCodeForFunction(*I);
    engine->updateGlobalMapping(*I, 0);
  }
}
#endif

IncrementalExecutor::ExecutionResult
IncrementalExecutor::runStaticInitializersOnce(const Transaction& T) {
  auto m = T.getModule();
  assert(m.get() && "Module must not be null");

  // We don't care whether something was unresolved before.
  m_unresolvedSymbols.clear();

  // check if there is any unresolved symbol in the list
  if (diagnoseUnresolvedSymbols("static initializers"))
    return kExeUnresolvedSymbols;

  llvm::GlobalVariable* GV
     = m->getGlobalVariable("llvm.global_ctors", true);
  // Nothing to do is good, too.
  if (!GV) return kExeSuccess;

  // Close similarity to
  // m_engine->runStaticConstructorsDestructors(false) aka
  // llvm::ExecutionEngine::runStaticConstructorsDestructors()
  // is intentional; we do an extra pass to check whether the JIT
  // managed to collect all the symbols needed by the niitializers.
  // Should be an array of '{ i32, void ()* }' structs.  The first value is
  // the init priority, which we ignore.
  llvm::ConstantArray *InitList
    = llvm::dyn_cast<llvm::ConstantArray>(GV->getInitializer());

  // We need to delete it here just in case we have recursive inits, otherwise
  // it will call inits multiple times.
  GV->eraseFromParent();

  if (InitList == 0)
    return kExeSuccess;

  //SmallVector<Function*, 2> initFuncs;

  for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) {
    llvm::ConstantStruct *CS
      = llvm::dyn_cast<llvm::ConstantStruct>(InitList->getOperand(i));
    if (CS == 0) continue;

    llvm::Constant *FP = CS->getOperand(1);
    if (FP->isNullValue())
      continue;  // Found a sentinal value, ignore.

    // Strip off constant expression casts.
    if (llvm::ConstantExpr *CE = llvm::dyn_cast<llvm::ConstantExpr>(FP))
      if (CE->isCast())
        FP = CE->getOperand(0);

    // Execute the ctor/dtor function!
    if (llvm::Function *F = llvm::dyn_cast<llvm::Function>(FP)) {
      const llvm::StringRef fName = F->getName();
      executeInit(fName);
/*
      initFuncs.push_back(F);
      if (fName.startswith("_GLOBAL__sub_I_")) {
        BasicBlock& BB = F->getEntryBlock();
        for (BasicBlock::iterator I = BB.begin(), E = BB.end(); I != E; ++I)
          if (CallInst* call = dyn_cast<CallInst>(I))
            initFuncs.push_back(call->getCalledFunction());
      }
*/
    }
  }

/*
  for (SmallVector<Function*,2>::iterator I = initFuncs.begin(),
         E = initFuncs.end(); I != E; ++I) {
    // Cleanup also the dangling init functions. They are in the form:
    // define internal void @_GLOBAL__I_aN() section "..."{
    // entry:
    //   call void @__cxx_global_var_init(N-1)()
    //   call void @__cxx_global_var_initM()
    //   ret void
    // }
    //
    // define internal void @__cxx_global_var_init(N-1)() section "..." {
    // entry:
    //   call void @_ZN7MyClassC1Ev(%struct.MyClass* @n)
    //   ret void
    // }

    // Erase __cxx_global_var_init(N-1)() first.
    (*I)->removeDeadConstantUsers();
    (*I)->eraseFromParent();
  }
*/

  return kExeSuccess;
}

void IncrementalExecutor::runAndRemoveStaticDestructors(Transaction* T) {
  assert(T && "Must be set");
  // Collect all the dtors bound to this transaction.
  AtExitFunctions::mapped_type Local;
  {
    cling::internal::SpinLockGuard slg(m_AtExitFuncsSpinLock);
    auto Itr = m_AtExitFuncs.find(T->getModule());
    if (Itr == m_AtExitFuncs.end()) return;
    m_AtExitFuncs.erase(Itr, &Local);
  } // end of spin lock lifetime block.

  // 'Unload' the cxa_atexit, atexit entities.
  for (auto&& AtExit : llvm::reverse(Local)) {
    AtExit();
    // Run anything that was just registered in 'AtExit()'
    runAndRemoveStaticDestructors(T);
  }
}

void
IncrementalExecutor::installLazyFunctionCreator(LazyFunctionCreatorFunc_t fp)
{
  m_lazyFuncCreator.push_back(fp);
}

bool
IncrementalExecutor::addSymbol(const char* Name,  void* Addr,
                               bool Jit) {
  return m_JIT->lookupSymbol(Name, Addr, Jit).second;
}

void* IncrementalExecutor::getAddressOfGlobal(llvm::StringRef symbolName,
                                              bool* fromJIT /*=0*/) {
  // Return a symbol's address, and whether it was jitted.
  void* address = m_JIT->lookupSymbol(symbolName).first;

  // It's not from the JIT if it's in a dylib.
  if (fromJIT)
    *fromJIT = !address;

  if (!address)
    return (void*)m_JIT->getSymbolAddress(symbolName, false /*no dlsym*/);

  return address;
}

void*
IncrementalExecutor::getPointerToGlobalFromJIT(const llvm::GlobalValue& GV) {
  // Get the function / variable pointer referenced by GV.

  // We don't care whether something was unresolved before.
  m_unresolvedSymbols.clear();

  void* addr = (void*)m_JIT->getSymbolAddress(GV.getName(),
                                              false /*no dlsym*/);

  if (diagnoseUnresolvedSymbols(GV.getName(), "symbol"))
    return 0;
  return addr;
}

bool IncrementalExecutor::diagnoseUnresolvedSymbols(llvm::StringRef trigger,
                                                    llvm::StringRef title) {
  if (m_unresolvedSymbols.empty())
    return false;

  llvm::SmallVector<llvm::Function*, 128> funcsToFree;
  for (const std::string& sym : m_unresolvedSymbols) {
#if 0
    // FIXME: This causes a lot of test failures, for some reason it causes
    // the call to HandleMissingFunction to be elided.
    unsigned diagID = m_Diags.getCustomDiagID(clang::DiagnosticsEngine::Error,
                                              "%0 unresolved while jitting %1");
    (void)diagID;
    //m_Diags.Report(diagID) << sym << funcname; // TODO: demangle the names.
#endif

    cling::errs() << "IncrementalExecutor::executeFunction: symbol '" << sym
                  << "' unresolved while linking ";
    if (trigger.find(utils::Synthesize::UniquePrefix) != llvm::StringRef::npos)
      cling::errs() << "[cling interface function]";
    else {
      if (!title.empty())
        cling::errs() << title << " '";
      cling::errs() << trigger;
      if (!title.empty())
        cling::errs() << "'";
    }
    cling::errs() << "!\n";

    // Be helpful, demangle!
    std::string demangledName = platform::Demangle(sym);
    if (!demangledName.empty()) {
       cling::errs()
          << "You are probably missing the definition of "
          << demangledName << "\n"
          << "Maybe you need to load the corresponding shared library?\n";
    }

    //llvm::Function *ff = m_engine->FindFunctionNamed(i->c_str());
    // i could also reference a global variable, in which case ff == 0.
    //if (ff)
    //  funcsToFree.push_back(ff);
  }
  //freeCallersOfUnresolvedSymbols(funcsToFree, m_engine.get());
  m_unresolvedSymbols.clear();
  return true;
}

}// end namespace cling
<|endoftext|>


<commit_before>//===-- PIC16TargetAsmInfo.cpp - PIC16 asm properties ---------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains the declarations of the PIC16TargetAsmInfo properties.
//
//===----------------------------------------------------------------------===//

#include "PIC16TargetAsmInfo.h"
#include "PIC16TargetMachine.h"
#include "llvm/GlobalValue.h"
#include "llvm/GlobalVariable.h"
#include "llvm/DerivedTypes.h"

using namespace llvm;

PIC16TargetAsmInfo::
PIC16TargetAsmInfo(const PIC16TargetMachine &TM)
  : TargetAsmInfo(TM) {
  CommentString = ";";
  Data8bitsDirective = " db ";
  Data16bitsDirective = " dw ";
  Data32bitsDirective = " dl ";
  RomData8bitsDirective = " dw ";
  RomData16bitsDirective = " rom_di ";
  RomData32bitsDirective = " rom_dl ";
  ZeroDirective = NULL;
  AsciiDirective = " dt ";
  AscizDirective = NULL;
  BSSSection_  = getNamedSection("udata.# UDATA",
                              SectionFlags::Writeable | SectionFlags::BSS);
  ReadOnlySection = getNamedSection("romdata.# ROMDATA", SectionFlags::None);
  DataSection = getNamedSection("idata.# IDATA", SectionFlags::Writeable);
  SwitchToSectionDirective = "";
  // Need because otherwise a .text symbol is emitted by DwarfWriter
  // in BeginModule, and gpasm cribbs for that .text symbol.
  TextSection = getUnnamedSection("", SectionFlags::Code);
}

const char *PIC16TargetAsmInfo::getRomDirective(unsigned size) const
{
  if (size == 8)
    return RomData8bitsDirective;
  else if (size == 16)
    return RomData16bitsDirective;
  else if (size == 32)
    return RomData32bitsDirective;
  else
    return NULL;
}

const char *PIC16TargetAsmInfo::getASDirective(unsigned size,
                                               unsigned AS) const {
  if (AS == PIC16ISD::ROM_SPACE)
    return getRomDirective(size);
  else
    return NULL;
}

const Section *
PIC16TargetAsmInfo::getBSSSectionForGlobal(const GlobalVariable *GV) const {
  assert (GV->hasInitializer() && "This global doesn't need space");
  Constant *C = GV->getInitializer();
  assert (C->isNullValue() && "Unitialized globals has non-zero initializer");

  // Find how much space this global needs.
  const TargetData *TD = TM.getTargetData();
  const Type *Ty = C->getType();
  unsigned ValSize = TD->getTypePaddedSize(Ty);

  // Go through all BSS Sections and assign this variable
  // to the first available section having enough space.
  PIC16Section *FoundBSS = NULL;
  for (unsigned i = 0; i < BSSSections.size(); i++) {
    if (DataBankSize - BSSSections[i]->Size >= ValSize) {
      FoundBSS = BSSSections[i];
      break;
    }
  }

  // No BSS section spacious enough was found. Crate a new one.
  if (! FoundBSS) {
    char *name = new char[32];
    sprintf (name, "udata.%d.# UDATA", BSSSections.size());
    const Section *NewSection = getNamedSection (name);

    FoundBSS = new PIC16Section(NewSection);

    // Add this newly created BSS section to the list of BSSSections.
    BSSSections.push_back(FoundBSS);
  }

  // Insert the GV into this BSS.
  FoundBSS->Items.push_back(GV);
  FoundBSS->Size += ValSize;

  // We can't do this here because GV is const .
  // const std::string SName = FoundBSS->S_->getName();
  // GV->setSection(SName);

  return FoundBSS->S_;
}

const Section *
PIC16TargetAsmInfo::getIDATASectionForGlobal(const GlobalVariable *GV) const {
  assert (GV->hasInitializer() && "This global doesn't need space");
  Constant *C = GV->getInitializer();
  assert (!C->isNullValue() && "initialized globals has zero initializer");
  assert (GV->getType()->getAddressSpace() == PIC16ISD::RAM_SPACE &&
          "can split initialized RAM data only");

  // Find how much space this global needs.
  const TargetData *TD = TM.getTargetData();
  const Type *Ty = C->getType();
  unsigned ValSize = TD->getTypePaddedSize(Ty);

  // Go through all IDATA Sections and assign this variable
  // to the first available section having enough space.
  PIC16Section *FoundIDATA = NULL;
  for (unsigned i = 0; i < IDATASections.size(); i++) {
    if ( DataBankSize - IDATASections[i]->Size >= ValSize) {
      FoundIDATA = IDATASections[i];
      break;
    }
  }

  // No IDATA section spacious enough was found. Crate a new one.
  if (! FoundIDATA) {
    char *name = new char[32];
    sprintf (name, "idata.%d.# IDATA", IDATASections.size());
    const Section *NewSection = getNamedSection (name);

    FoundIDATA = new PIC16Section(NewSection);

    // Add this newly created IDATA section to the list of IDATASections.
    IDATASections.push_back(FoundIDATA);
  }

  // Insert the GV into this IDATA.
  FoundIDATA->Items.push_back(GV);
  FoundIDATA->Size += ValSize;

  // We can't do this here because GV is const .
  // GV->setSection(FoundIDATA->S->getName());

  return FoundIDATA->S_;
}

// Override default implementation to put the true globals into
// multiple data sections if required.
const Section*
PIC16TargetAsmInfo::SelectSectionForGlobal(const GlobalValue *GV1) const {
  // We select the section based on the initializer here, so it really
  // has to be a GlobalVariable.
  if (!isa<GlobalVariable>(GV1))
    return TargetAsmInfo::SelectSectionForGlobal(GV1);

  const GlobalVariable *GV = dyn_cast<GlobalVariable>(GV1);
  // We are only dealing with true globals here. So names with a "."
  // are local globals. Also declarations are not entertained.
  std::string name = GV->getName();
  if (name.find(".auto.") != std::string::npos
      || name.find(".arg.") != std::string::npos || !GV->hasInitializer())
    return TargetAsmInfo::SelectSectionForGlobal(GV);

  const Constant *C = GV->getInitializer();
  // See if this is an uninitialized global.
  if (C->isNullValue())
    return getBSSSectionForGlobal(GV);

  // This is initialized data. We only deal with initialized data in RAM.
  if (GV->getType()->getAddressSpace() == PIC16ISD::RAM_SPACE)
    return getIDATASectionForGlobal(GV);

  // Else let the default implementation take care of it.
  return TargetAsmInfo::SelectSectionForGlobal(GV);
}

void PIC16TargetAsmInfo::SetSectionForGVs(Module &M) {
  for (Module::global_iterator I = M.global_begin(), E = M.global_end();
       I != E; ++I) {
    if (!I->hasInitializer())   // External global require no code.
      continue;

    // Any variables reaching here with "." in its name is a local scope
    // variable and should not be printed in global data section.
    std::string name = I->getName();
    if (name.find(".auto.") != std::string::npos
      || name.find(".arg.") != std::string::npos)
      continue;
    int AddrSpace = I->getType()->getAddressSpace();

    if (AddrSpace == PIC16ISD::RAM_SPACE)
      I->setSection(SectionForGlobal(I)->getName());
  }
}

// Helper routine.
// Func name starts after prefix and followed by a .
static std::string getFuncNameForSym(const std::string &Sym,
                                      PIC16ABINames::IDs PrefixType) {

  const char *prefix = getIDName (PIC16ABINames::PREFIX_SYMBOL);

  // This name may or may not start with prefix;
  // Func names start after prfix in that case.
  size_t func_name_start = 0;
  if (Sym.find(prefix, 0, strlen(prefix)) != std::string::npos)
    func_name_start = strlen(prefix);

  // Position of the . after func name.
  size_t func_name_end = Sym.find ('.', func_name_start);

  return Sym.substr (func_name_start, func_name_end);
}

// Helper routine to create a section name given the section prefix
// and func name.
static std::string
getSectionNameForFunc (const std::string &Fname,
                       const PIC16ABINames::IDs sec_id) {
  std::string sec_id_string = getIDName (sec_id);
  return sec_id_string + "." + Fname + ".#";
}

// Get the section for the given external symbol names.
// This function is meant for only mangled external symbol names.
std::string
llvm::getSectionNameForSym(const std::string &Sym) {
  std::string SectionName;

  PIC16ABINames::IDs id = getID (Sym);
  std::string Fname = getFuncNameForSym (Sym, id);

  switch (id) {
    default : assert (0 && "Could not determine external symbol type");
    case PIC16ABINames::FUNC_FRAME:
    case PIC16ABINames::FUNC_RET:
    case PIC16ABINames::FUNC_TEMPS:
    case PIC16ABINames::FUNC_ARGS:  {
      return getSectionNameForFunc (Fname, PIC16ABINames::FRAME_SECTION);
    }
    case PIC16ABINames::FUNC_AUTOS: {
      return getSectionNameForFunc (Fname, PIC16ABINames::AUTOS_SECTION);
    }
  }
}

PIC16TargetAsmInfo::~PIC16TargetAsmInfo() {

  for (unsigned i = 0; i < BSSSections.size(); i++) {
      delete BSSSections[i];
  }

  for (unsigned i = 0; i < IDATASections.size(); i++) {
      delete IDATASections[i];
  }
}
<commit_msg>Eliminate compiler warnings.<commit_after>//===-- PIC16TargetAsmInfo.cpp - PIC16 asm properties ---------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains the declarations of the PIC16TargetAsmInfo properties.
//
//===----------------------------------------------------------------------===//

#include "PIC16TargetAsmInfo.h"
#include "PIC16TargetMachine.h"
#include "llvm/GlobalValue.h"
#include "llvm/GlobalVariable.h"
#include "llvm/DerivedTypes.h"

using namespace llvm;

PIC16TargetAsmInfo::
PIC16TargetAsmInfo(const PIC16TargetMachine &TM)
  : TargetAsmInfo(TM) {
  CommentString = ";";
  Data8bitsDirective = " db ";
  Data16bitsDirective = " dw ";
  Data32bitsDirective = " dl ";
  RomData8bitsDirective = " dw ";
  RomData16bitsDirective = " rom_di ";
  RomData32bitsDirective = " rom_dl ";
  ZeroDirective = NULL;
  AsciiDirective = " dt ";
  AscizDirective = NULL;
  BSSSection_  = getNamedSection("udata.# UDATA",
                              SectionFlags::Writeable | SectionFlags::BSS);
  ReadOnlySection = getNamedSection("romdata.# ROMDATA", SectionFlags::None);
  DataSection = getNamedSection("idata.# IDATA", SectionFlags::Writeable);
  SwitchToSectionDirective = "";
  // Need because otherwise a .text symbol is emitted by DwarfWriter
  // in BeginModule, and gpasm cribbs for that .text symbol.
  TextSection = getUnnamedSection("", SectionFlags::Code);
}

const char *PIC16TargetAsmInfo::getRomDirective(unsigned size) const
{
  if (size == 8)
    return RomData8bitsDirective;
  else if (size == 16)
    return RomData16bitsDirective;
  else if (size == 32)
    return RomData32bitsDirective;
  else
    return NULL;
}

const char *PIC16TargetAsmInfo::getASDirective(unsigned size,
                                               unsigned AS) const {
  if (AS == PIC16ISD::ROM_SPACE)
    return getRomDirective(size);
  else
    return NULL;
}

const Section *
PIC16TargetAsmInfo::getBSSSectionForGlobal(const GlobalVariable *GV) const {
  assert (GV->hasInitializer() && "This global doesn't need space");
  Constant *C = GV->getInitializer();
  assert (C->isNullValue() && "Unitialized globals has non-zero initializer");

  // Find how much space this global needs.
  const TargetData *TD = TM.getTargetData();
  const Type *Ty = C->getType();
  unsigned ValSize = TD->getTypePaddedSize(Ty);

  // Go through all BSS Sections and assign this variable
  // to the first available section having enough space.
  PIC16Section *FoundBSS = NULL;
  for (unsigned i = 0; i < BSSSections.size(); i++) {
    if (DataBankSize - BSSSections[i]->Size >= ValSize) {
      FoundBSS = BSSSections[i];
      break;
    }
  }

  // No BSS section spacious enough was found. Crate a new one.
  if (! FoundBSS) {
    char *name = new char[32];
    sprintf (name, "udata.%d.# UDATA", (int)BSSSections.size());
    const Section *NewSection = getNamedSection (name);

    FoundBSS = new PIC16Section(NewSection);

    // Add this newly created BSS section to the list of BSSSections.
    BSSSections.push_back(FoundBSS);
  }

  // Insert the GV into this BSS.
  FoundBSS->Items.push_back(GV);
  FoundBSS->Size += ValSize;

  // We can't do this here because GV is const .
  // const std::string SName = FoundBSS->S_->getName();
  // GV->setSection(SName);

  return FoundBSS->S_;
}

const Section *
PIC16TargetAsmInfo::getIDATASectionForGlobal(const GlobalVariable *GV) const {
  assert (GV->hasInitializer() && "This global doesn't need space");
  Constant *C = GV->getInitializer();
  assert (!C->isNullValue() && "initialized globals has zero initializer");
  assert (GV->getType()->getAddressSpace() == PIC16ISD::RAM_SPACE &&
          "can split initialized RAM data only");

  // Find how much space this global needs.
  const TargetData *TD = TM.getTargetData();
  const Type *Ty = C->getType();
  unsigned ValSize = TD->getTypePaddedSize(Ty);

  // Go through all IDATA Sections and assign this variable
  // to the first available section having enough space.
  PIC16Section *FoundIDATA = NULL;
  for (unsigned i = 0; i < IDATASections.size(); i++) {
    if ( DataBankSize - IDATASections[i]->Size >= ValSize) {
      FoundIDATA = IDATASections[i];
      break;
    }
  }

  // No IDATA section spacious enough was found. Crate a new one.
  if (! FoundIDATA) {
    char *name = new char[32];
    sprintf (name, "idata.%d.# IDATA", (int)IDATASections.size());
    const Section *NewSection = getNamedSection (name);

    FoundIDATA = new PIC16Section(NewSection);

    // Add this newly created IDATA section to the list of IDATASections.
    IDATASections.push_back(FoundIDATA);
  }

  // Insert the GV into this IDATA.
  FoundIDATA->Items.push_back(GV);
  FoundIDATA->Size += ValSize;

  // We can't do this here because GV is const .
  // GV->setSection(FoundIDATA->S->getName());

  return FoundIDATA->S_;
}

// Override default implementation to put the true globals into
// multiple data sections if required.
const Section*
PIC16TargetAsmInfo::SelectSectionForGlobal(const GlobalValue *GV1) const {
  // We select the section based on the initializer here, so it really
  // has to be a GlobalVariable.
  if (!isa<GlobalVariable>(GV1))
    return TargetAsmInfo::SelectSectionForGlobal(GV1);

  const GlobalVariable *GV = dyn_cast<GlobalVariable>(GV1);
  // We are only dealing with true globals here. So names with a "."
  // are local globals. Also declarations are not entertained.
  std::string name = GV->getName();
  if (name.find(".auto.") != std::string::npos
      || name.find(".arg.") != std::string::npos || !GV->hasInitializer())
    return TargetAsmInfo::SelectSectionForGlobal(GV);

  const Constant *C = GV->getInitializer();
  // See if this is an uninitialized global.
  if (C->isNullValue())
    return getBSSSectionForGlobal(GV);

  // This is initialized data. We only deal with initialized data in RAM.
  if (GV->getType()->getAddressSpace() == PIC16ISD::RAM_SPACE)
    return getIDATASectionForGlobal(GV);

  // Else let the default implementation take care of it.
  return TargetAsmInfo::SelectSectionForGlobal(GV);
}

void PIC16TargetAsmInfo::SetSectionForGVs(Module &M) {
  for (Module::global_iterator I = M.global_begin(), E = M.global_end();
       I != E; ++I) {
    if (!I->hasInitializer())   // External global require no code.
      continue;

    // Any variables reaching here with "." in its name is a local scope
    // variable and should not be printed in global data section.
    std::string name = I->getName();
    if (name.find(".auto.") != std::string::npos
      || name.find(".arg.") != std::string::npos)
      continue;
    int AddrSpace = I->getType()->getAddressSpace();

    if (AddrSpace == PIC16ISD::RAM_SPACE)
      I->setSection(SectionForGlobal(I)->getName());
  }
}

// Helper routine.
// Func name starts after prefix and followed by a .
static std::string getFuncNameForSym(const std::string &Sym,
                                      PIC16ABINames::IDs PrefixType) {

  const char *prefix = getIDName (PIC16ABINames::PREFIX_SYMBOL);

  // This name may or may not start with prefix;
  // Func names start after prfix in that case.
  size_t func_name_start = 0;
  if (Sym.find(prefix, 0, strlen(prefix)) != std::string::npos)
    func_name_start = strlen(prefix);

  // Position of the . after func name.
  size_t func_name_end = Sym.find ('.', func_name_start);

  return Sym.substr (func_name_start, func_name_end);
}

// Helper routine to create a section name given the section prefix
// and func name.
static std::string
getSectionNameForFunc (const std::string &Fname,
                       const PIC16ABINames::IDs sec_id) {
  std::string sec_id_string = getIDName (sec_id);
  return sec_id_string + "." + Fname + ".#";
}

// Get the section for the given external symbol names.
// This function is meant for only mangled external symbol names.
std::string
llvm::getSectionNameForSym(const std::string &Sym) {
  std::string SectionName;

  PIC16ABINames::IDs id = getID (Sym);
  std::string Fname = getFuncNameForSym (Sym, id);

  switch (id) {
    default : assert (0 && "Could not determine external symbol type");
    case PIC16ABINames::FUNC_FRAME:
    case PIC16ABINames::FUNC_RET:
    case PIC16ABINames::FUNC_TEMPS:
    case PIC16ABINames::FUNC_ARGS:  {
      return getSectionNameForFunc (Fname, PIC16ABINames::FRAME_SECTION);
    }
    case PIC16ABINames::FUNC_AUTOS: {
      return getSectionNameForFunc (Fname, PIC16ABINames::AUTOS_SECTION);
    }
  }
}

PIC16TargetAsmInfo::~PIC16TargetAsmInfo() {

  for (unsigned i = 0; i < BSSSections.size(); i++) {
      delete BSSSections[i];
  }

  for (unsigned i = 0; i < IDATASections.size(); i++) {
      delete IDATASections[i];
  }
}
<|endoftext|>


<commit_before>//===- HotColdSplitting.cpp -- Outline Cold Regions -------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Outline cold regions to a separate function.
// TODO: Update BFI and BPI
// TODO: Add all the outlined functions to a separate section.
//
//===----------------------------------------------------------------------===//

#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Analysis/BlockFrequencyInfo.h"
#include "llvm/Analysis/BranchProbabilityInfo.h"
#include "llvm/Analysis/CFG.h"
#include "llvm/Analysis/OptimizationRemarkEmitter.h"
#include "llvm/Analysis/PostDominators.h"
#include "llvm/Analysis/ProfileSummaryInfo.h"
#include "llvm/Analysis/TargetTransformInfo.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/CFG.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/DiagnosticInfo.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Metadata.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/PassManager.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/Use.h"
#include "llvm/IR/User.h"
#include "llvm/IR/Value.h"
#include "llvm/Pass.h"
#include "llvm/Support/BlockFrequency.h"
#include "llvm/Support/BranchProbability.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Transforms/IPO.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/Transforms/Utils/Cloning.h"
#include "llvm/Transforms/Utils/CodeExtractor.h"
#include "llvm/Transforms/Utils/Local.h"
#include "llvm/Transforms/Utils/SSAUpdater.h"
#include "llvm/Transforms/Utils/ValueMapper.h"
#include <algorithm>
#include <cassert>

#define DEBUG_TYPE "hotcoldsplit"

STATISTIC(NumColdSESEFound,
          "Number of cold single entry single exit (SESE) regions found.");
STATISTIC(NumColdSESEOutlined,
          "Number of cold single entry single exit (SESE) regions outlined.");

using namespace llvm;

static cl::opt<bool> EnableStaticAnalyis("hot-cold-static-analysis",
                              cl::init(true), cl::Hidden);

namespace {

struct PostDomTree : PostDomTreeBase<BasicBlock> {
  PostDomTree(Function &F) { recalculate(F); }
};

typedef DenseSet<const BasicBlock *> DenseSetBB;
typedef DenseMap<const BasicBlock *, uint64_t> DenseMapBBInt;

// From: https://reviews.llvm.org/D22558
// Exit is not part of the region.
static bool isSingleEntrySingleExit(BasicBlock *Entry, const BasicBlock *Exit,
                                    DominatorTree *DT, PostDomTree *PDT,
                                    SmallVectorImpl<BasicBlock *> &Region) {
  if (!DT->dominates(Entry, Exit))
    return false;

  if (!PDT->dominates(Exit, Entry))
    return false;

  Region.push_back(Entry);
  for (auto I = df_begin(Entry), E = df_end(Entry); I != E;) {
    if (*I == Exit) {
      I.skipChildren();
      continue;
    }
    if (!DT->dominates(Entry, *I))
      return false;
    Region.push_back(*I);
    ++I;
  }
  return true;
}

bool blockEndsInUnreachable(const BasicBlock &BB) {
  if (BB.empty())
    return true;
  const TerminatorInst *I = BB.getTerminator();
  if (isa<ReturnInst>(I) || isa<IndirectBrInst>(I))
    return true;
  // Unreachable blocks do not have any successor.
  return succ_empty(&BB);
}

static
bool unlikelyExecuted(const BasicBlock &BB) {
  if (blockEndsInUnreachable(BB))
    return true;
  // Exception handling blocks are unlikely executed.
  if (BB.isEHPad())
    return true;
  for (const Instruction &I : BB)
    if (const CallInst *CI = dyn_cast<CallInst>(&I)) {
      // The block is cold if it calls functions tagged as cold or noreturn.
      if (CI->hasFnAttr(Attribute::Cold) ||
          CI->hasFnAttr(Attribute::NoReturn))
        return true;

      // Assume that inline assembly is hot code.
      if (isa<InlineAsm>(CI->getCalledValue()))
        return false;
    }
  return false;
}

static DenseSetBB getHotBlocks(Function &F) {

  // Mark all cold basic blocks.
  DenseSetBB ColdBlocks;
  for (BasicBlock &BB : F)
    if (unlikelyExecuted(BB))
      ColdBlocks.insert((const BasicBlock *)&BB);

  // Forward propagation: basic blocks are hot when they are reachable from the
  // beginning of the function through a path that does not contain cold blocks.
  SmallVector<const BasicBlock *, 8> WL;
  DenseSetBB HotBlocks;

  const BasicBlock *It = &F.front();
  if (!ColdBlocks.count(It)) {
    HotBlocks.insert(It);
    // Breadth First Search to mark edges reachable from hot.
    WL.push_back(It);
    while (WL.size() > 0) {
      It = WL.pop_back_val();

      for (const BasicBlock *Succ : successors(It)) {
        // Do not visit blocks that are cold.
        if (!ColdBlocks.count(Succ) && !HotBlocks.count(Succ)) {
          HotBlocks.insert(Succ);
          WL.push_back(Succ);
        }
      }
    }
  }

  assert(WL.empty() && "work list should be empty");

  DenseMapBBInt NumHotSuccessors;
  // Back propagation: when all successors of a basic block are cold, the
  // basic block is cold as well.
  for (BasicBlock &BBRef : F) {
    const BasicBlock *BB = &BBRef;
    if (HotBlocks.count(BB)) {
      // Keep a count of hot successors for every hot block.
      NumHotSuccessors[BB] = 0;
      for (const BasicBlock *Succ : successors(BB))
        if (!ColdBlocks.count(Succ))
          NumHotSuccessors[BB] += 1;

      // Add to work list the blocks with all successors cold. Those are the
      // root nodes in the next loop, where we will move those blocks from
      // HotBlocks to ColdBlocks and iterate over their predecessors.
      if (NumHotSuccessors[BB] == 0)
        WL.push_back(BB);
    }
  }

  while (WL.size() > 0) {
    It = WL.pop_back_val();
    if (ColdBlocks.count(It))
      continue;

    // Move the block from HotBlocks to ColdBlocks.
    HotBlocks.erase(It);
    ColdBlocks.insert(It);

    // Iterate over the predecessors.
    for (const BasicBlock *Pred : predecessors(It)) {
      if (HotBlocks.count(Pred)) {
        NumHotSuccessors[Pred] -= 1;

        // If Pred has no more hot successors, add it to the work list.
        if (NumHotSuccessors[Pred] == 0)
          WL.push_back(Pred);
      }
    }
  }

  return HotBlocks;
}

class HotColdSplitting {
public:
  HotColdSplitting(ProfileSummaryInfo *ProfSI,
                   function_ref<BlockFrequencyInfo *(Function &)> GBFI,
                   function_ref<TargetTransformInfo &(Function &)> GTTI,
                   std::function<OptimizationRemarkEmitter &(Function &)> *GORE)
      : PSI(ProfSI), GetBFI(GBFI), GetTTI(GTTI), GetORE(GORE) {}
  bool run(Module &M);

private:
  bool shouldOutlineFrom(const Function &F) const;
  Function *outlineColdBlocks(Function &F,
                              const DenseSetBB &ColdBlock,
                              DominatorTree *DT, PostDomTree *PDT);
  Function *extractColdRegion(const SmallVectorImpl<BasicBlock *> &Region,
                              DominatorTree *DT, BlockFrequencyInfo *BFI,
                              OptimizationRemarkEmitter &ORE);
  bool isOutlineCandidate(const SmallVectorImpl<BasicBlock *> &Region,
                          const BasicBlock *Exit) const {
    if (!Exit)
      return false;
    // TODO: Find a better metric to compute the size of region being outlined.
    if (Region.size() == 1)
      return false;
    // Regions with landing pads etc.
    for (const BasicBlock *BB : Region) {
      if (BB->isEHPad() || BB->hasAddressTaken())
        return false;
    }
    return true;
  }
  SmallPtrSet<const Function *, 2> OutlinedFunctions;
  ProfileSummaryInfo *PSI;
  function_ref<BlockFrequencyInfo *(Function &)> GetBFI;
  function_ref<TargetTransformInfo &(Function &)> GetTTI;
  std::function<OptimizationRemarkEmitter &(Function &)> *GetORE;
};

class HotColdSplittingLegacyPass : public ModulePass {
public:
  static char ID;
  HotColdSplittingLegacyPass() : ModulePass(ID) {
    initializeHotColdSplittingLegacyPassPass(*PassRegistry::getPassRegistry());
  }

  void getAnalysisUsage(AnalysisUsage &AU) const override {
    AU.addRequired<AssumptionCacheTracker>();
    AU.addRequired<BlockFrequencyInfoWrapperPass>();
    AU.addRequired<ProfileSummaryInfoWrapperPass>();
    AU.addRequired<TargetTransformInfoWrapperPass>();
  }

  bool runOnModule(Module &M) override;
};

} // end anonymous namespace

// Returns false if the function should not be considered for hot-cold split
// optimization. Already outlined functions have coldcc so no need to check
// for them here.
bool HotColdSplitting::shouldOutlineFrom(const Function &F) const {
  if (F.size() <= 2)
    return false;

  if (F.hasAddressTaken())
    return false;

  if (F.hasFnAttribute(Attribute::AlwaysInline))
    return false;

  if (F.hasFnAttribute(Attribute::NoInline))
    return false;

  if (F.getCallingConv() == CallingConv::Cold)
    return false;

  if (PSI->isFunctionEntryCold(&F))
    return false;
  return true;
}

Function *
HotColdSplitting::extractColdRegion(const SmallVectorImpl<BasicBlock *> &Region,
                                    DominatorTree *DT, BlockFrequencyInfo *BFI,
                                    OptimizationRemarkEmitter &ORE) {
  LLVM_DEBUG(for (auto *BB : Region)
          llvm::dbgs() << "\nExtracting: " << *BB;);

  // TODO: Pass BFI and BPI to update profile information.
  CodeExtractor CE(Region, DT);

  SetVector<Value *> Inputs, Outputs, Sinks;
  CE.findInputsOutputs(Inputs, Outputs, Sinks);

  // Do not extract regions that have live exit variables.
  if (Outputs.size() > 0)
    return nullptr;

  if (Function *OutF = CE.extractCodeRegion()) {
    User *U = *OutF->user_begin();
    CallInst *CI = cast<CallInst>(U);
    CallSite CS(CI);
    NumColdSESEOutlined++;
    if (GetTTI(*OutF).useColdCCForColdCall(*OutF)) {
      OutF->setCallingConv(CallingConv::Cold);
      CS.setCallingConv(CallingConv::Cold);
    }
    CI->setIsNoInline();
    LLVM_DEBUG(llvm::dbgs() << "Outlined Region at block: " << Region.front());
    return OutF;
  }

  ORE.emit([&]() {
    return OptimizationRemarkMissed(DEBUG_TYPE, "ExtractFailed",
                                    &*Region[0]->begin())
           << "Failed to extract region at block "
           << ore::NV("Block", Region.front());
  });
  return nullptr;
}

// Return the function created after outlining, nullptr otherwise.
Function *HotColdSplitting::outlineColdBlocks(Function &F,
                                              const DenseSetBB &HotBlocks,
                                              DominatorTree *DT,
                                              PostDomTree *PDT) {
  auto BFI = GetBFI(F);
  auto &ORE = (*GetORE)(F);
  // Walking the dominator tree allows us to find the largest
  // cold region.
  BasicBlock *Begin = DT->getRootNode()->getBlock();
  for (auto I = df_begin(Begin), E = df_end(Begin); I != E; ++I) {
    BasicBlock *BB = *I;
    if (PSI->isColdBB(BB, BFI) || !HotBlocks.count(BB)) {
      SmallVector<BasicBlock *, 4> ValidColdRegion, Region;
      auto *BBNode = (*PDT)[BB];
      auto Exit = BBNode->getIDom()->getBlock();
      // We might need a virtual exit which post-dominates all basic blocks.
      if (!Exit)
        continue;
      BasicBlock *ExitColdRegion = nullptr;
      // Estimated cold region between a BB and its dom-frontier.
      while (isSingleEntrySingleExit(BB, Exit, DT, PDT, Region) &&
             isOutlineCandidate(Region, Exit)) {
        ExitColdRegion = Exit;
        ValidColdRegion = Region;
        Region.clear();
        // Update Exit recursively to its dom-frontier.
        Exit = (*PDT)[Exit]->getIDom()->getBlock();
      }
      if (ExitColdRegion) {
        ++NumColdSESEFound;
        // Candidate for outlining. FIXME: Continue outlining.
        // FIXME: Shouldn't need uniquing, debug isSingleEntrySingleExit
        //std::sort(ValidColdRegion.begin(), ValidColdRegion.end());
        auto last = std::unique(ValidColdRegion.begin(), ValidColdRegion.end());
        ValidColdRegion.erase(last, ValidColdRegion.end());
        return extractColdRegion(ValidColdRegion, DT, BFI, ORE);
      }
    }
  }
  return nullptr;
}

bool HotColdSplitting::run(Module &M) {
  for (auto &F : M) {
    if (!shouldOutlineFrom(F))
      continue;
    DominatorTree DT(F);
    PostDomTree PDT(F);
    PDT.recalculate(F);
    DenseSetBB HotBlocks;
    if (EnableStaticAnalyis) // Static analysis of cold blocks.
      HotBlocks = getHotBlocks(F);

    auto Outlined = outlineColdBlocks(F, HotBlocks, &DT, &PDT);
    if (Outlined)
      OutlinedFunctions.insert(Outlined);
  }
  return true;
}

bool HotColdSplittingLegacyPass::runOnModule(Module &M) {
  if (skipModule(M))
    return false;
  ProfileSummaryInfo *PSI =
      getAnalysis<ProfileSummaryInfoWrapperPass>().getPSI();
  auto GTTI = [this](Function &F) -> TargetTransformInfo & {
    return this->getAnalysis<TargetTransformInfoWrapperPass>().getTTI(F);
  };
  auto GBFI = [this](Function &F) {
    return &this->getAnalysis<BlockFrequencyInfoWrapperPass>(F).getBFI();
  };
  std::unique_ptr<OptimizationRemarkEmitter> ORE;
  std::function<OptimizationRemarkEmitter &(Function &)> GetORE =
      [&ORE](Function &F) -> OptimizationRemarkEmitter & {
    ORE.reset(new OptimizationRemarkEmitter(&F));
    return *ORE.get();
  };

  return HotColdSplitting(PSI, GBFI, GTTI, &GetORE).run(M);
}

char HotColdSplittingLegacyPass::ID = 0;
INITIALIZE_PASS_BEGIN(HotColdSplittingLegacyPass, "hotcoldsplit",
                      "Hot Cold Splitting", false, false)
INITIALIZE_PASS_DEPENDENCY(ProfileSummaryInfoWrapperPass)
INITIALIZE_PASS_DEPENDENCY(BlockFrequencyInfoWrapperPass)
INITIALIZE_PASS_END(HotColdSplittingLegacyPass, "hotcoldsplit",
                    "Hot Cold Splitting", false, false)

ModulePass *llvm::createHotColdSplittingPass() {
  return new HotColdSplittingLegacyPass();
}
<commit_msg>HotColdSplit: fix isSingleEntrySingleExit<commit_after>//===- HotColdSplitting.cpp -- Outline Cold Regions -------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Outline cold regions to a separate function.
// TODO: Update BFI and BPI
// TODO: Add all the outlined functions to a separate section.
//
//===----------------------------------------------------------------------===//

#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Analysis/BlockFrequencyInfo.h"
#include "llvm/Analysis/BranchProbabilityInfo.h"
#include "llvm/Analysis/CFG.h"
#include "llvm/Analysis/OptimizationRemarkEmitter.h"
#include "llvm/Analysis/PostDominators.h"
#include "llvm/Analysis/ProfileSummaryInfo.h"
#include "llvm/Analysis/TargetTransformInfo.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/CFG.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/DiagnosticInfo.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Metadata.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/PassManager.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/Use.h"
#include "llvm/IR/User.h"
#include "llvm/IR/Value.h"
#include "llvm/Pass.h"
#include "llvm/Support/BlockFrequency.h"
#include "llvm/Support/BranchProbability.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Transforms/IPO.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/Transforms/Utils/Cloning.h"
#include "llvm/Transforms/Utils/CodeExtractor.h"
#include "llvm/Transforms/Utils/Local.h"
#include "llvm/Transforms/Utils/SSAUpdater.h"
#include "llvm/Transforms/Utils/ValueMapper.h"
#include <algorithm>
#include <cassert>

#define DEBUG_TYPE "hotcoldsplit"

STATISTIC(NumColdSESEFound,
          "Number of cold single entry single exit (SESE) regions found.");
STATISTIC(NumColdSESEOutlined,
          "Number of cold single entry single exit (SESE) regions outlined.");

using namespace llvm;

static cl::opt<bool> EnableStaticAnalyis("hot-cold-static-analysis",
                              cl::init(true), cl::Hidden);

namespace {

struct PostDomTree : PostDomTreeBase<BasicBlock> {
  PostDomTree(Function &F) { recalculate(F); }
};

typedef DenseSet<const BasicBlock *> DenseSetBB;
typedef DenseMap<const BasicBlock *, uint64_t> DenseMapBBInt;

// From: https://reviews.llvm.org/D22558
// Exit is not part of the region.
static bool isSingleEntrySingleExit(BasicBlock *Entry, const BasicBlock *Exit,
                                    DominatorTree *DT, PostDomTree *PDT,
                                    SmallVectorImpl<BasicBlock *> &Region) {
  if (!DT->dominates(Entry, Exit))
    return false;

  if (!PDT->dominates(Exit, Entry))
    return false;

  for (auto I = df_begin(Entry), E = df_end(Entry); I != E;) {
    if (*I == Exit) {
      I.skipChildren();
      continue;
    }
    if (!DT->dominates(Entry, *I))
      return false;
    Region.push_back(*I);
    ++I;
  }
  return true;
}

bool blockEndsInUnreachable(const BasicBlock &BB) {
  if (BB.empty())
    return true;
  const TerminatorInst *I = BB.getTerminator();
  if (isa<ReturnInst>(I) || isa<IndirectBrInst>(I))
    return true;
  // Unreachable blocks do not have any successor.
  return succ_empty(&BB);
}

static
bool unlikelyExecuted(const BasicBlock &BB) {
  if (blockEndsInUnreachable(BB))
    return true;
  // Exception handling blocks are unlikely executed.
  if (BB.isEHPad())
    return true;
  for (const Instruction &I : BB)
    if (const CallInst *CI = dyn_cast<CallInst>(&I)) {
      // The block is cold if it calls functions tagged as cold or noreturn.
      if (CI->hasFnAttr(Attribute::Cold) ||
          CI->hasFnAttr(Attribute::NoReturn))
        return true;

      // Assume that inline assembly is hot code.
      if (isa<InlineAsm>(CI->getCalledValue()))
        return false;
    }
  return false;
}

static DenseSetBB getHotBlocks(Function &F) {

  // Mark all cold basic blocks.
  DenseSetBB ColdBlocks;
  for (BasicBlock &BB : F)
    if (unlikelyExecuted(BB))
      ColdBlocks.insert((const BasicBlock *)&BB);

  // Forward propagation: basic blocks are hot when they are reachable from the
  // beginning of the function through a path that does not contain cold blocks.
  SmallVector<const BasicBlock *, 8> WL;
  DenseSetBB HotBlocks;

  const BasicBlock *It = &F.front();
  if (!ColdBlocks.count(It)) {
    HotBlocks.insert(It);
    // Breadth First Search to mark edges reachable from hot.
    WL.push_back(It);
    while (WL.size() > 0) {
      It = WL.pop_back_val();

      for (const BasicBlock *Succ : successors(It)) {
        // Do not visit blocks that are cold.
        if (!ColdBlocks.count(Succ) && !HotBlocks.count(Succ)) {
          HotBlocks.insert(Succ);
          WL.push_back(Succ);
        }
      }
    }
  }

  assert(WL.empty() && "work list should be empty");

  DenseMapBBInt NumHotSuccessors;
  // Back propagation: when all successors of a basic block are cold, the
  // basic block is cold as well.
  for (BasicBlock &BBRef : F) {
    const BasicBlock *BB = &BBRef;
    if (HotBlocks.count(BB)) {
      // Keep a count of hot successors for every hot block.
      NumHotSuccessors[BB] = 0;
      for (const BasicBlock *Succ : successors(BB))
        if (!ColdBlocks.count(Succ))
          NumHotSuccessors[BB] += 1;

      // Add to work list the blocks with all successors cold. Those are the
      // root nodes in the next loop, where we will move those blocks from
      // HotBlocks to ColdBlocks and iterate over their predecessors.
      if (NumHotSuccessors[BB] == 0)
        WL.push_back(BB);
    }
  }

  while (WL.size() > 0) {
    It = WL.pop_back_val();
    if (ColdBlocks.count(It))
      continue;

    // Move the block from HotBlocks to ColdBlocks.
    HotBlocks.erase(It);
    ColdBlocks.insert(It);

    // Iterate over the predecessors.
    for (const BasicBlock *Pred : predecessors(It)) {
      if (HotBlocks.count(Pred)) {
        NumHotSuccessors[Pred] -= 1;

        // If Pred has no more hot successors, add it to the work list.
        if (NumHotSuccessors[Pred] == 0)
          WL.push_back(Pred);
      }
    }
  }

  return HotBlocks;
}

class HotColdSplitting {
public:
  HotColdSplitting(ProfileSummaryInfo *ProfSI,
                   function_ref<BlockFrequencyInfo *(Function &)> GBFI,
                   function_ref<TargetTransformInfo &(Function &)> GTTI,
                   std::function<OptimizationRemarkEmitter &(Function &)> *GORE)
      : PSI(ProfSI), GetBFI(GBFI), GetTTI(GTTI), GetORE(GORE) {}
  bool run(Module &M);

private:
  bool shouldOutlineFrom(const Function &F) const;
  Function *outlineColdBlocks(Function &F,
                              const DenseSetBB &ColdBlock,
                              DominatorTree *DT, PostDomTree *PDT);
  Function *extractColdRegion(const SmallVectorImpl<BasicBlock *> &Region,
                              DominatorTree *DT, BlockFrequencyInfo *BFI,
                              OptimizationRemarkEmitter &ORE);
  bool isOutlineCandidate(const SmallVectorImpl<BasicBlock *> &Region,
                          const BasicBlock *Exit) const {
    if (!Exit)
      return false;

    // Regions with landing pads etc.
    for (const BasicBlock *BB : Region) {
      if (BB->isEHPad() || BB->hasAddressTaken())
        return false;
    }
    return true;
  }
  SmallPtrSet<const Function *, 2> OutlinedFunctions;
  ProfileSummaryInfo *PSI;
  function_ref<BlockFrequencyInfo *(Function &)> GetBFI;
  function_ref<TargetTransformInfo &(Function &)> GetTTI;
  std::function<OptimizationRemarkEmitter &(Function &)> *GetORE;
};

class HotColdSplittingLegacyPass : public ModulePass {
public:
  static char ID;
  HotColdSplittingLegacyPass() : ModulePass(ID) {
    initializeHotColdSplittingLegacyPassPass(*PassRegistry::getPassRegistry());
  }

  void getAnalysisUsage(AnalysisUsage &AU) const override {
    AU.addRequired<AssumptionCacheTracker>();
    AU.addRequired<BlockFrequencyInfoWrapperPass>();
    AU.addRequired<ProfileSummaryInfoWrapperPass>();
    AU.addRequired<TargetTransformInfoWrapperPass>();
  }

  bool runOnModule(Module &M) override;
};

} // end anonymous namespace

// Returns false if the function should not be considered for hot-cold split
// optimization. Already outlined functions have coldcc so no need to check
// for them here.
bool HotColdSplitting::shouldOutlineFrom(const Function &F) const {
  if (F.size() <= 2)
    return false;

  if (F.hasAddressTaken())
    return false;

  if (F.hasFnAttribute(Attribute::AlwaysInline))
    return false;

  if (F.hasFnAttribute(Attribute::NoInline))
    return false;

  if (F.getCallingConv() == CallingConv::Cold)
    return false;

  if (PSI->isFunctionEntryCold(&F))
    return false;
  return true;
}

Function *
HotColdSplitting::extractColdRegion(const SmallVectorImpl<BasicBlock *> &Region,
                                    DominatorTree *DT, BlockFrequencyInfo *BFI,
                                    OptimizationRemarkEmitter &ORE) {
  LLVM_DEBUG(for (auto *BB : Region)
          llvm::dbgs() << "\nExtracting: " << *BB;);

  // TODO: Pass BFI and BPI to update profile information.
  CodeExtractor CE(Region, DT);

  SetVector<Value *> Inputs, Outputs, Sinks;
  CE.findInputsOutputs(Inputs, Outputs, Sinks);

  // Do not extract regions that have live exit variables.
  if (Outputs.size() > 0)
    return nullptr;

  if (Function *OutF = CE.extractCodeRegion()) {
    User *U = *OutF->user_begin();
    CallInst *CI = cast<CallInst>(U);
    CallSite CS(CI);
    NumColdSESEOutlined++;
    if (GetTTI(*OutF).useColdCCForColdCall(*OutF)) {
      OutF->setCallingConv(CallingConv::Cold);
      CS.setCallingConv(CallingConv::Cold);
    }
    CI->setIsNoInline();
    LLVM_DEBUG(llvm::dbgs() << "Outlined Region at block: " << Region.front());
    return OutF;
  }

  ORE.emit([&]() {
    return OptimizationRemarkMissed(DEBUG_TYPE, "ExtractFailed",
                                    &*Region[0]->begin())
           << "Failed to extract region at block "
           << ore::NV("Block", Region.front());
  });
  return nullptr;
}

// Return the function created after outlining, nullptr otherwise.
Function *HotColdSplitting::outlineColdBlocks(Function &F,
                                              const DenseSetBB &HotBlocks,
                                              DominatorTree *DT,
                                              PostDomTree *PDT) {
  auto BFI = GetBFI(F);
  auto &ORE = (*GetORE)(F);
  // Walking the dominator tree allows us to find the largest
  // cold region.
  BasicBlock *Begin = DT->getRootNode()->getBlock();
  for (auto I = df_begin(Begin), E = df_end(Begin); I != E; ++I) {
    BasicBlock *BB = *I;
    if (PSI->isColdBB(BB, BFI) || !HotBlocks.count(BB)) {
      SmallVector<BasicBlock *, 4> ValidColdRegion, Region;
      BasicBlock *Exit = (*PDT)[BB]->getIDom()->getBlock();
      // We might need a virtual exit which post-dominates all basic blocks.
      if (!Exit)
        continue;
      BasicBlock *ExitColdRegion = nullptr;
      // Estimated cold region between a BB and its dom-frontier.
      while (isSingleEntrySingleExit(BB, Exit, DT, PDT, Region) &&
             isOutlineCandidate(Region, Exit)) {
        ExitColdRegion = Exit;
        ValidColdRegion = Region;
        Region.clear();
        // Update Exit recursively to its dom-frontier.
        Exit = (*PDT)[Exit]->getIDom()->getBlock();
      }
      if (ExitColdRegion) {
        // Do not outline a region with only one block.
        if (ValidColdRegion.size() == 1)
          continue;

        ++NumColdSESEFound;
        // Candidate for outlining. FIXME: Continue outlining.
        return extractColdRegion(ValidColdRegion, DT, BFI, ORE);
      }
    }
  }
  return nullptr;
}

bool HotColdSplitting::run(Module &M) {
  for (auto &F : M) {
    if (!shouldOutlineFrom(F))
      continue;
    DominatorTree DT(F);
    PostDomTree PDT(F);
    PDT.recalculate(F);
    DenseSetBB HotBlocks;
    if (EnableStaticAnalyis) // Static analysis of cold blocks.
      HotBlocks = getHotBlocks(F);

    auto Outlined = outlineColdBlocks(F, HotBlocks, &DT, &PDT);
    if (Outlined)
      OutlinedFunctions.insert(Outlined);
  }
  return true;
}

bool HotColdSplittingLegacyPass::runOnModule(Module &M) {
  if (skipModule(M))
    return false;
  ProfileSummaryInfo *PSI =
      getAnalysis<ProfileSummaryInfoWrapperPass>().getPSI();
  auto GTTI = [this](Function &F) -> TargetTransformInfo & {
    return this->getAnalysis<TargetTransformInfoWrapperPass>().getTTI(F);
  };
  auto GBFI = [this](Function &F) {
    return &this->getAnalysis<BlockFrequencyInfoWrapperPass>(F).getBFI();
  };
  std::unique_ptr<OptimizationRemarkEmitter> ORE;
  std::function<OptimizationRemarkEmitter &(Function &)> GetORE =
      [&ORE](Function &F) -> OptimizationRemarkEmitter & {
    ORE.reset(new OptimizationRemarkEmitter(&F));
    return *ORE.get();
  };

  return HotColdSplitting(PSI, GBFI, GTTI, &GetORE).run(M);
}

char HotColdSplittingLegacyPass::ID = 0;
INITIALIZE_PASS_BEGIN(HotColdSplittingLegacyPass, "hotcoldsplit",
                      "Hot Cold Splitting", false, false)
INITIALIZE_PASS_DEPENDENCY(ProfileSummaryInfoWrapperPass)
INITIALIZE_PASS_DEPENDENCY(BlockFrequencyInfoWrapperPass)
INITIALIZE_PASS_END(HotColdSplittingLegacyPass, "hotcoldsplit",
                    "Hot Cold Splitting", false, false)

ModulePass *llvm::createHotColdSplittingPass() {
  return new HotColdSplittingLegacyPass();
}
<|endoftext|>