<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/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::CodeGenOptions& CGOpt, unsigned Fmt = 0) {
  Triple TheTriple(sys::getProcessTriple());
  if (Fmt) {
    assert(Fmt > llvm::Triple::UnknownObjectFormat &&
           Fmt <= llvm::Triple::MachO && "Invalid Format");
    TheTriple.setObjectFormat(static_cast<llvm::Triple::ObjectFormatType>(Fmt));
  }
#ifdef LLVM_ON_WIN32
  // COFF format currently needs a few changes in LLVM to function properly.
  else
    TheTriple.setObjectFormat(llvm::Triple::ELF);
#endif

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

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

  llvm::TargetOptions Options = llvm::TargetOptions();
// 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::unique_ptr<TargetMachine> TM;
  TM.reset(TheTarget->createTargetMachine(TheTriple.getTriple(),
                                          MCPU, FeaturesStr,
                                          Options,
                                          Optional<Reloc::Model>(),
                                          CMModel,
                                          OptLevel));
  return TM;
}
} // anonymous namespace

IncrementalExecutor::IncrementalExecutor(clang::DiagnosticsEngine& diags,
                                         const clang::CompilerInstance& CI):
  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 );

  // No need to protect this access of m_AtExitFuncs, since nobody
  // can use this object yet.
  m_AtExitFuncs.reserve(256);

  std::unique_ptr<TargetMachine>
    TM(CreateHostTargetMachine(CI.getCodeGenOpts()));
  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() {
  // No need to protect this access, since hopefully there is no concurrent
  // shutdown request.
  for (size_t I = 0, N = m_AtExitFuncs.size(); I < N; ++I) {
    const CXAAtExitElement& AEE = m_AtExitFuncs[N - I - 1];
    (*AEE.m_Func)(AEE.m_Arg);
  }
}

void IncrementalExecutor::AddAtExitFunc(void (*func) (void*), void* arg,
                                        llvm::Module* M) {
  // Register a CXAAtExit function
  cling::internal::SpinLockGuard slg(m_AtExitFuncsSpinLock);
  m_AtExitFuncs.push_back(CXAAtExitElement(func, arg, M));
}

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";
  }

  // Avoid "ISO C++ forbids casting between pointer-to-function and
  // pointer-to-object":
  return (void*)reinterpret_cast<size_t>(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) {
  llvm::Module* m = T.getModule();
  assert(m && "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 boundToT;

  {
    cling::internal::SpinLockGuard slg(m_AtExitFuncsSpinLock);
    for (AtExitFunctions::iterator I = m_AtExitFuncs.begin();
         I != m_AtExitFuncs.end();)
      if (I->m_FromM == T->getModule()) {
        boundToT.push_back(*I);
        I = m_AtExitFuncs.erase(I);
      }
      else
        ++I;
  } // end of spin lock lifetime block.

  // 'Unload' the cxa_atexit entities.
  for (AtExitFunctions::reverse_iterator I = boundToT.rbegin(),
         E = boundToT.rend(); I != E; ++I) {
    const CXAAtExitElement& AEE = *I;
    (*AEE.m_Func)(AEE.m_Arg);
  }
}

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 (std::set<std::string>::const_iterator i = m_unresolvedSymbols.begin(),
         e = m_unresolvedSymbols.end(); i != e; ++i) {
#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) << *i << funcname; // TODO: demangle the names.
#endif

    cling::errs() << "IncrementalExecutor::executeFunction: symbol '" << *i
                  << "' 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(*i);
    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>Use utils::FunctionToVoidPtr for casting unresolvedSymbol.<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/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::CodeGenOptions& CGOpt, unsigned Fmt = 0) {
  Triple TheTriple(sys::getProcessTriple());
  if (Fmt) {
    assert(Fmt > llvm::Triple::UnknownObjectFormat &&
           Fmt <= llvm::Triple::MachO && "Invalid Format");
    TheTriple.setObjectFormat(static_cast<llvm::Triple::ObjectFormatType>(Fmt));
  }
#ifdef LLVM_ON_WIN32
  // COFF format currently needs a few changes in LLVM to function properly.
  else
    TheTriple.setObjectFormat(llvm::Triple::ELF);
#endif

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

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

  llvm::TargetOptions Options = llvm::TargetOptions();
// 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::unique_ptr<TargetMachine> TM;
  TM.reset(TheTarget->createTargetMachine(TheTriple.getTriple(),
                                          MCPU, FeaturesStr,
                                          Options,
                                          Optional<Reloc::Model>(),
                                          CMModel,
                                          OptLevel));
  return TM;
}
} // anonymous namespace

IncrementalExecutor::IncrementalExecutor(clang::DiagnosticsEngine& diags,
                                         const clang::CompilerInstance& CI):
  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 );

  // No need to protect this access of m_AtExitFuncs, since nobody
  // can use this object yet.
  m_AtExitFuncs.reserve(256);

  std::unique_ptr<TargetMachine>
    TM(CreateHostTargetMachine(CI.getCodeGenOpts()));
  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() {
  // No need to protect this access, since hopefully there is no concurrent
  // shutdown request.
  for (size_t I = 0, N = m_AtExitFuncs.size(); I < N; ++I) {
    const CXAAtExitElement& AEE = m_AtExitFuncs[N - I - 1];
    (*AEE.m_Func)(AEE.m_Arg);
  }
}

void IncrementalExecutor::AddAtExitFunc(void (*func) (void*), void* arg,
                                        llvm::Module* M) {
  // Register a CXAAtExit function
  cling::internal::SpinLockGuard slg(m_AtExitFuncsSpinLock);
  m_AtExitFuncs.push_back(CXAAtExitElement(func, arg, M));
}

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) {
  llvm::Module* m = T.getModule();
  assert(m && "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 boundToT;

  {
    cling::internal::SpinLockGuard slg(m_AtExitFuncsSpinLock);
    for (AtExitFunctions::iterator I = m_AtExitFuncs.begin();
         I != m_AtExitFuncs.end();)
      if (I->m_FromM == T->getModule()) {
        boundToT.push_back(*I);
        I = m_AtExitFuncs.erase(I);
      }
      else
        ++I;
  } // end of spin lock lifetime block.

  // 'Unload' the cxa_atexit entities.
  for (AtExitFunctions::reverse_iterator I = boundToT.rbegin(),
         E = boundToT.rend(); I != E; ++I) {
    const CXAAtExitElement& AEE = *I;
    (*AEE.m_Func)(AEE.m_Arg);
  }
}

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 (std::set<std::string>::const_iterator i = m_unresolvedSymbols.begin(),
         e = m_unresolvedSymbols.end(); i != e; ++i) {
#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) << *i << funcname; // TODO: demangle the names.
#endif

    cling::errs() << "IncrementalExecutor::executeFunction: symbol '" << *i
                  << "' 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(*i);
    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>/*
The MIT License (MIT)

Copyright (c) 2016 Arvid Norberg

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

#include "node_buffer.hpp"

#define CATCH_CONFIG_MAIN
#include "catch.hpp"

using v4 = boost::asio::ip::address_v4;
using v6 = boost::asio::ip::address_v6;

namespace {
char const* node_id = "aaaaaaaaaaaaaaaaaaaa";
}

TEST_CASE("node_buffer initial state")
{
	unlink("test-node-buffer-1");
	node_buffer<address_v4> buf("test-node-buffer-1", 10);

	CHECK(buf.empty());

	unlink("test-node-buffer-1");
}

template <size_t N>
bool compare(std::array<span<char const>, N> const& ranges, std::string cmp)
{
	for (auto const& r : ranges) {
		if (cmp.substr(0, r.size()) != std::string(r.data(), r.size()))
			return false;
		cmp = cmp.substr(r.size());
	}
	return cmp.empty();
}

TEST_CASE("node_buffer single")
{
	unlink("test-node-buffer-2");
	node_buffer<address_v4> buf("test-node-buffer-2", 10);

	CHECK(compare(buf.get_nodes(1), ""));

	buf.insert_node(v4::from_string("10.1.1.1"), 6881, node_id);

	CHECK(compare(buf.get_nodes(10), "aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x01\x1a\xe1"));

	// since there's only one entry, we should get it back every time we ask
	CHECK(compare(buf.get_nodes(10), "aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x01\x1a\xe1"));

	unlink("test-node-buffer-2");
}

TEST_CASE("node_buffer duplicate")
{
	unlink("test-node-buffer-3");
	node_buffer<address_v4> buf("test-node-buffer-3", 10);

	// make sure we don't allow duplicate IPs in the node buffer
	buf.insert_node(v4::from_string("10.1.1.1"), 6881, node_id);
	buf.insert_node(v4::from_string("10.1.1.1"), 6881, node_id);
	buf.insert_node(v4::from_string("10.1.1.2"), 6881, node_id);

	// asking for nodes should give 10.1.1.2 as many times as 10.1.1.1
	CHECK(compare(buf.get_nodes(1), "aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x01\x1a\xe1"));
	CHECK(compare(buf.get_nodes(1), "aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x02\x1a\xe1"));
	CHECK(compare(buf.get_nodes(1), "aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x01\x1a\xe1"));
	CHECK(compare(buf.get_nodes(1), "aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x02\x1a\xe1"));

	unlink("test-node-buffer-3");
}

TEST_CASE("node_buffer wrap")
{
	unlink("test-node-buffer-4");
	node_buffer<address_v4> buf("test-node-buffer-4", 10);

	// make sure writing nodes exceeding the capacity starts over at the
	// beginning
	for (int i = 0; i < 20; ++i) {
		std::string ip = "10.1.1." + std::to_string(i);
		buf.insert_node(v4::from_string(ip.c_str()), 6881, node_id);
	}

	// asking for nodes, we should only see the last 10 nodes added
	CHECK(compare(buf.get_nodes(1), "aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x0a\x1a\xe1"));
	CHECK(compare(buf.get_nodes(1), "aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x0b\x1a\xe1"));
	CHECK(compare(buf.get_nodes(1), "aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x0c\x1a\xe1"));
	CHECK(compare(buf.get_nodes(1), "aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x0d\x1a\xe1"));
	CHECK(compare(buf.get_nodes(1), "aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x0e\x1a\xe1"));
	CHECK(compare(buf.get_nodes(1), "aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x0f\x1a\xe1"));
	CHECK(compare(buf.get_nodes(1), "aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x10\x1a\xe1"));
	CHECK(compare(buf.get_nodes(1), "aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x11\x1a\xe1"));
	CHECK(compare(buf.get_nodes(1), "aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x12\x1a\xe1"));
	CHECK(compare(buf.get_nodes(1), "aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x13\x1a\xe1"));

	// and then start over again
	CHECK(compare(buf.get_nodes(1), "aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x0a\x1a\xe1"));

	unlink("test-node-buffer-4");
}

TEST_CASE("node_buffer restore")
{
	unlink("test-node-buffer-5");
	{
		node_buffer<address_v4> buf("test-node-buffer-5", 10);

		for (int i = 1; i < 11; ++i) {
			std::string ip = "10.1.1." + std::to_string(i);
			buf.insert_node(v4::from_string(ip.c_str()), 6881, node_id);
		}

		CHECK(compare(buf.get_nodes(1), "aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x01\x1a\xe1"));
		CHECK(compare(buf.get_nodes(1), "aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x02\x1a\xe1"));
		CHECK(compare(buf.get_nodes(1), "aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x03\x1a\xe1"));
		CHECK(compare(buf.get_nodes(1), "aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x04\x1a\xe1"));
		CHECK(compare(buf.get_nodes(1), "aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x05\x1a\xe1"));
		CHECK(compare(buf.get_nodes(1), "aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x06\x1a\xe1"));
		CHECK(compare(buf.get_nodes(1), "aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x07\x1a\xe1"));
		CHECK(compare(buf.get_nodes(1), "aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x08\x1a\xe1"));
		CHECK(compare(buf.get_nodes(1), "aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x09\x1a\xe1"));
		CHECK(compare(buf.get_nodes(1), "aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x0a\x1a\xe1"));
	}

	{
		node_buffer<address_v4> buf("test-node-buffer-5", 10);

		CHECK(compare(buf.get_nodes(1), "aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x01\x1a\xe1"));
		CHECK(compare(buf.get_nodes(1), "aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x02\x1a\xe1"));
		CHECK(compare(buf.get_nodes(1), "aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x03\x1a\xe1"));
		CHECK(compare(buf.get_nodes(1), "aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x04\x1a\xe1"));
		CHECK(compare(buf.get_nodes(1), "aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x05\x1a\xe1"));
		CHECK(compare(buf.get_nodes(1), "aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x06\x1a\xe1"));
		CHECK(compare(buf.get_nodes(1), "aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x07\x1a\xe1"));
		CHECK(compare(buf.get_nodes(1), "aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x08\x1a\xe1"));
		CHECK(compare(buf.get_nodes(1), "aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x09\x1a\xe1"));
		CHECK(compare(buf.get_nodes(1), "aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x0a\x1a\xe1"));

		// also make sure the IP unordered set used to prevent duplicates was
		// restored
		// this is a duplicate and should be rejeted
		CHECK(buf.insert_node(v4::from_string("10.1.1.1"), 6881, node_id) == false);

		// this is not a duplicate and should be accepted
		CHECK(buf.insert_node(v4::from_string("10.1.1.11"), 6881, node_id) == true);
	}

	unlink("test-node-buffer-5");
}

TEST_CASE("node_buffer multi-request")
{
	unlink("test-node-buffer-6");
	{
		node_buffer<address_v4> buf("test-node-buffer-6", 10);

		for (int i = 1; i < 11; ++i) {
			std::string ip = "10.1.1." + std::to_string(i);
			buf.insert_node(v4::from_string(ip.c_str()), 6881, node_id);
		}

		CHECK(compare(buf.get_nodes(10), "aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x01\x1a\xe1"
			"aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x02\x1a\xe1"
			"aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x03\x1a\xe1"
			"aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x04\x1a\xe1"
			"aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x05\x1a\xe1"
			"aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x06\x1a\xe1"
			"aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x07\x1a\xe1"
			"aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x08\x1a\xe1"
			"aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x09\x1a\xe1"
			"aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x0a\x1a\xe1"));
	}

	unlink("test-node-buffer-6");
}

TEST_CASE("node_buffer wrapping-request")
{
	unlink("test-node-buffer-7");
	{
		node_buffer<address_v4> buf("test-node-buffer-7", 10);

		for (int i = 1; i < 11; ++i) {
			std::string ip = "10.1.1." + std::to_string(i);
			buf.insert_node(v4::from_string(ip.c_str()), 6881, node_id);
		}

		// advance the read cursor
		for (int i = 0; i < 5; ++i) {
			buf.get_nodes(1);
		}

		CHECK(compare(buf.get_nodes(10),
			"aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x06\x1a\xe1"
			"aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x07\x1a\xe1"
			"aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x08\x1a\xe1"
			"aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x09\x1a\xe1"
			"aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x0a\x1a\xe1"
			"aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x01\x1a\xe1"
			"aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x02\x1a\xe1"
			"aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x03\x1a\xe1"
			"aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x04\x1a\xe1"
			"aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x05\x1a\xe1"));
	}

	unlink("test-node-buffer-7");
}
<commit_msg>fix test<commit_after>/*
The MIT License (MIT)

Copyright (c) 2016 Arvid Norberg

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

#include "node_buffer.hpp"

#define CATCH_CONFIG_MAIN
#include "catch.hpp"

using v4 = boost::asio::ip::address_v4;
using v6 = boost::asio::ip::address_v6;

namespace {
char const* node_id = "aaaaaaaaaaaaaaaaaaaa";
}

TEST_CASE("node_buffer initial state")
{
	unlink("test-node-buffer-1");
	node_buffer<address_v4> buf("test-node-buffer-1", 10);

	CHECK(buf.empty());

	unlink("test-node-buffer-1");
}

template <size_t N>
bool compare(std::array<span<char const>, N> const& ranges, std::string cmp)
{
	for (auto const& r : ranges) {
		if (cmp.substr(0, r.size()) != std::string(r.data(), r.size()))
			return false;
		cmp = cmp.substr(r.size());
	}
	return cmp.empty();
}

TEST_CASE("node_buffer single")
{
	unlink("test-node-buffer-2");
	node_buffer<address_v4> buf("test-node-buffer-2", 10);

	CHECK(compare(buf.get_nodes(1), ""));

	buf.insert_node(v4::from_string("10.1.1.1"), 6881, node_id);

	CHECK(compare(buf.get_nodes(10), "aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x01\x1a\xe1"));

	// since there's only one entry, we should get it back every time we ask
	CHECK(compare(buf.get_nodes(10), "aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x01\x1a\xe1"));

	unlink("test-node-buffer-2");
}

TEST_CASE("node_buffer duplicate")
{
	unlink("test-node-buffer-3");
	node_buffer<address_v4> buf("test-node-buffer-3", 10);

	// make sure we don't allow duplicate IPs in the node buffer
	buf.insert_node(v4::from_string("10.1.1.1"), 6881, node_id);
	buf.insert_node(v4::from_string("10.1.1.1"), 6881, node_id);
	buf.insert_node(v4::from_string("10.1.1.2"), 6881, node_id);

	// asking for nodes should give 10.1.1.2 as many times as 10.1.1.1
	CHECK(compare(buf.get_nodes(1), "aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x01\x1a\xe1"));
	CHECK(compare(buf.get_nodes(1), "aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x02\x1a\xe1"));
	CHECK(compare(buf.get_nodes(1), "aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x01\x1a\xe1"));
	CHECK(compare(buf.get_nodes(1), "aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x02\x1a\xe1"));

	unlink("test-node-buffer-3");
}

TEST_CASE("node_buffer wrap")
{
	unlink("test-node-buffer-4");
	node_buffer<address_v4> buf("test-node-buffer-4", 10);

	// make sure writing nodes exceeding the capacity starts over at the
	// beginning
	for (int i = 0; i < 20; ++i) {
		std::string ip = "10.1.1." + std::to_string(i);
		buf.insert_node(v4::from_string(ip.c_str()), 6881, node_id);
	}

	// asking for nodes, we should only see the last 10 nodes added
	CHECK(compare(buf.get_nodes(1), "aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x0a\x1a\xe1"));
	CHECK(compare(buf.get_nodes(1), "aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x0b\x1a\xe1"));
	CHECK(compare(buf.get_nodes(1), "aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x0c\x1a\xe1"));
	CHECK(compare(buf.get_nodes(1), "aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x0d\x1a\xe1"));
	CHECK(compare(buf.get_nodes(1), "aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x0e\x1a\xe1"));
	CHECK(compare(buf.get_nodes(1), "aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x0f\x1a\xe1"));
	CHECK(compare(buf.get_nodes(1), "aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x10\x1a\xe1"));
	CHECK(compare(buf.get_nodes(1), "aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x11\x1a\xe1"));
	CHECK(compare(buf.get_nodes(1), "aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x12\x1a\xe1"));
	CHECK(compare(buf.get_nodes(1), "aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x13\x1a\xe1"));

	// and then start over again
	CHECK(compare(buf.get_nodes(1), "aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x0a\x1a\xe1"));

	unlink("test-node-buffer-4");
}

TEST_CASE("node_buffer restore")
{
	unlink("test-node-buffer-5");
	{
		node_buffer<address_v4> buf("test-node-buffer-5", 10);

		for (int i = 1; i < 11; ++i) {
			std::string ip = "10.1.1." + std::to_string(i);
			buf.insert_node(v4::from_string(ip.c_str()), 6881, node_id);
		}

		CHECK(compare(buf.get_nodes(1), "aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x01\x1a\xe1"));
		CHECK(compare(buf.get_nodes(1), "aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x02\x1a\xe1"));
		CHECK(compare(buf.get_nodes(1), "aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x03\x1a\xe1"));
		CHECK(compare(buf.get_nodes(1), "aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x04\x1a\xe1"));
		CHECK(compare(buf.get_nodes(1), "aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x05\x1a\xe1"));
		CHECK(compare(buf.get_nodes(1), "aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x06\x1a\xe1"));
		CHECK(compare(buf.get_nodes(1), "aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x07\x1a\xe1"));
		CHECK(compare(buf.get_nodes(1), "aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x08\x1a\xe1"));
		CHECK(compare(buf.get_nodes(1), "aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x09\x1a\xe1"));
		CHECK(compare(buf.get_nodes(1), "aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x0a\x1a\xe1"));
	}

	{
		node_buffer<address_v4> buf("test-node-buffer-5", 10);

		CHECK(compare(buf.get_nodes(1), "aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x01\x1a\xe1"));
		CHECK(compare(buf.get_nodes(1), "aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x02\x1a\xe1"));
		CHECK(compare(buf.get_nodes(1), "aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x03\x1a\xe1"));
		CHECK(compare(buf.get_nodes(1), "aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x04\x1a\xe1"));
		CHECK(compare(buf.get_nodes(1), "aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x05\x1a\xe1"));
		CHECK(compare(buf.get_nodes(1), "aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x06\x1a\xe1"));
		CHECK(compare(buf.get_nodes(1), "aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x07\x1a\xe1"));
		CHECK(compare(buf.get_nodes(1), "aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x08\x1a\xe1"));
		CHECK(compare(buf.get_nodes(1), "aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x09\x1a\xe1"));
		CHECK(compare(buf.get_nodes(1), "aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x0a\x1a\xe1"));

		// also make sure the IP unordered set used to prevent duplicates was
		// restored
		// this is a duplicate and should be rejeted
		CHECK(buf.insert_node(v4::from_string("10.1.1.1"), 6881, node_id) == false);

		// this is not a duplicate and should be accepted
		CHECK(buf.insert_node(v4::from_string("10.1.1.11"), 6881, node_id) == true);
	}

	unlink("test-node-buffer-5");
}

TEST_CASE("node_buffer multi-request")
{
	unlink("test-node-buffer-6");
	{
		node_buffer<address_v4> buf("test-node-buffer-6", 10);

		for (int i = 1; i < 11; ++i) {
			std::string ip = "10.1.1." + std::to_string(i);
			buf.insert_node(v4::from_string(ip.c_str()), 6881, node_id);
		}

		CHECK(compare(buf.get_nodes(10), "aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x01\x1a\xe1"
			"aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x02\x1a\xe1"
			"aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x03\x1a\xe1"
			"aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x04\x1a\xe1"
			"aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x05\x1a\xe1"
			"aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x06\x1a\xe1"
			"aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x07\x1a\xe1"
			"aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x08\x1a\xe1"
			"aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x09\x1a\xe1"
			"aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x0a\x1a\xe1"));
	}

	unlink("test-node-buffer-6");
}

TEST_CASE("node_buffer wrapping-request")
{
	unlink("test-node-buffer-7");
	{
		node_buffer<address_v4> buf("test-node-buffer-7", 10);

		for (int i = 1; i < 11; ++i) {
			std::string ip = "10.1.1." + std::to_string(i);
			buf.insert_node(v4::from_string(ip.c_str()), 6881, node_id);
		}

		// advance the read cursor
		for (int i = 0; i < 5; ++i) {
			buf.get_nodes(1);
		}

		CHECK(compare(buf.get_nodes(9),
			"aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x06\x1a\xe1"
			"aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x07\x1a\xe1"
			"aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x08\x1a\xe1"
			"aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x09\x1a\xe1"
			"aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x0a\x1a\xe1"
			"aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x01\x1a\xe1"
			"aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x02\x1a\xe1"
			"aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x03\x1a\xe1"
			"aaaaaaaaaaaaaaaaaaaa\x0a\x01\x01\x04\x1a\xe1"));
	}

	unlink("test-node-buffer-7");
}
<|endoftext|>


<commit_before>char text_vert[] = "$OSG_GLSL_VERSION\n"
                   "$OSG_PRECISION_FLOAT\n"
                   "\n"
                   "$OSG_VARYING_OUT vec2 texCoord;\n"
                   "$OSG_VARYING_OUT vec4 vertexColor;\n"
                   "\n"
                   "void main(void)\n"
                   "{\n"
                   "    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n"
                   "    texCoord = gl_MultiTexCoord0.xy;\n"
                   "    vertexColor = gl_Color;\n"
                   "\n"
                   "#ifndef GL_ES\n"
                   "    gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;\n"
                   "#endif\n"
                   "}\n"
                   "\n";
<commit_msg>Added __VERSION__<140 check for usage of gl_ClipVertex to avoid GL3 core profile usage issues<commit_after>char text_vert[] = "$OSG_GLSL_VERSION\n"
                   "$OSG_PRECISION_FLOAT\n"
                   "\n"
                   "$OSG_VARYING_OUT vec2 texCoord;\n"
                   "$OSG_VARYING_OUT vec4 vertexColor;\n"
                   "\n"
                   "void main(void)\n"
                   "{\n"
                   "    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n"
                   "    texCoord = gl_MultiTexCoord0.xy;\n"
                   "    vertexColor = gl_Color;\n"
                   "\n"
                   "#if !defined(GL_ES) && __VERSION__<140\n"
                   "    gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;\n"
                   "#endif\n"
                   "}\n"
                   "\n";
<|endoftext|>


<commit_before>//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.

#include <vector>

#include "llvm/IR/DataLayout.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Module.h"
#include "llvm/Pass.h"
#include "llvm/IR/Type.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"

#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Analysis/LoopPass.h"

using namespace llvm;

class ClassifyLoops : public LoopPass {
   bool any{false};
   bool nested{false};
   bool nonterm{false};
   public:
    static char ID;

    ClassifyLoops() : LoopPass(ID) {}

    bool runOnLoop(Loop *L, LPPassManager &LPM) override {
      any = true;

      // for now, we detect only nested loops
      if (L->getParentLoop()) {
          nested = true;
      }

      if (!nonterm) {
        SmallVector<llvm::BasicBlock *, 8> ExitBlocks;
        L->getExitBlocks(ExitBlocks);
        if (ExitBlocks.size() == 0) {
          nonterm = true;
        }
      }

      return false;
    }

    bool doFinalization() override {
      if (any) {
          llvm::errs() << "contains loops\n";
          if (nested)
              llvm::errs() << "  nested loops\n";
          if (nonterm)
              llvm::errs() << "  nonterm loops\n";
      }
      return false;
    }
};

static RegisterPass<ClassifyLoops> CL("classify-loops",
                                      "detect what loops are in the program");
char ClassifyLoops::ID;

<commit_msg>classify-loops: check for irreducibility<commit_after>//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.

#include <vector>

#include "llvm/IR/DataLayout.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Module.h"
#include "llvm/Pass.h"
#include "llvm/IR/Type.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"

// for checking irreducibility
#include "llvm/Analysis/LoopIterator.h"
#include "llvm/Analysis/CFG.h"

#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Analysis/LoopPass.h"

using namespace llvm;

class ClassifyLoops : public LoopPass {
   bool any{false};
   bool nested{false};
   bool nonterm{false};
   bool irreducible{false};

   public:
    static char ID;

    ClassifyLoops() : LoopPass(ID) {}

    void getAnalysisUsage(AnalysisUsage &AU) const override {
      AU.setPreservesCFG();
      AU.addRequired<LoopInfoWrapperPass>();
    }

    bool runOnLoop(Loop *L, LPPassManager &LPM) override {
      any = true;

      // for now, we detect only nested loops
      if (L->getParentLoop()) {
          nested = true;
      }

      if (!nonterm) {
        SmallVector<llvm::BasicBlock *, 8> ExitBlocks;
        L->getExitBlocks(ExitBlocks);
        if (ExitBlocks.size() == 0) {
          nonterm = true;
        }
      }

      if (!irreducible) {
        // XXX: hmm, not sure this is working...
        LoopInfo &LI = getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
        LoopBlocksRPO RPOT(L);
        RPOT.perform(&LI);
        irreducible = containsIrreducibleCFG<const BasicBlock *>(RPOT, LI);
      }

      return false;
    }

    bool doFinalization() override {
      if (any) {
          llvm::errs() << "contains loops\n";
          if (nested)
              llvm::errs() << "  nested loops\n";
          if (nonterm)
              llvm::errs() << "  nonterm loops\n";
          if (irreducible)
              llvm::errs() << "  irreducible loops\n";
      }
      return false;
    }
};

static RegisterPass<ClassifyLoops> CL("classify-loops",
                                      "detect what loops are in the program");
char ClassifyLoops::ID;

<|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/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::CodeGenOptions& CGOpt, unsigned Fmt = 0) {
  Triple TheTriple(sys::getProcessTriple());
  if (Fmt) {
    assert(Fmt > llvm::Triple::UnknownObjectFormat &&
           Fmt <= llvm::Triple::MachO && "Invalid Format");
    TheTriple.setObjectFormat(static_cast<llvm::Triple::ObjectFormatType>(Fmt));
  }
#ifdef LLVM_ON_WIN32
  // COFF format currently needs a few changes in LLVM to function properly.
  else
    TheTriple.setObjectFormat(llvm::Triple::ELF);
#endif

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

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

  llvm::TargetOptions Options = llvm::TargetOptions();
// 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::unique_ptr<TargetMachine> TM;
  TM.reset(TheTarget->createTargetMachine(TheTriple.getTriple(),
                                          MCPU, FeaturesStr,
                                          Options,
                                          Optional<Reloc::Model>(),
                                          CMModel,
                                          OptLevel));
  return TM;
}
} // anonymous namespace

IncrementalExecutor::IncrementalExecutor(clang::DiagnosticsEngine& diags,
                                         const clang::CompilerInstance& CI):
  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 );

  // No need to protect this access of m_AtExitFuncs, since nobody
  // can use this object yet.
  m_AtExitFuncs.reserve(256);

  std::unique_ptr<TargetMachine>
    TM(CreateHostTargetMachine(CI.getCodeGenOpts()));
  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() {
  // No need to protect this access, since hopefully there is no concurrent
  // shutdown request.
  for (size_t I = 0, N = m_AtExitFuncs.size(); I < N; ++I) {
    const CXAAtExitElement& AEE = m_AtExitFuncs[N - I - 1];
    (*AEE.m_Func)(AEE.m_Arg);
  }
}

void IncrementalExecutor::AddAtExitFunc(void (*func) (void*), void* arg,
                                        llvm::Module* M) {
  // Register a CXAAtExit function
  cling::internal::SpinLockGuard slg(m_AtExitFuncsSpinLock);
  m_AtExitFuncs.push_back(CXAAtExitElement(func, arg, M));
}

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) {
  llvm::Module* m = T.getModule();
  assert(m && "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 boundToT;

  {
    cling::internal::SpinLockGuard slg(m_AtExitFuncsSpinLock);
    for (AtExitFunctions::iterator I = m_AtExitFuncs.begin();
         I != m_AtExitFuncs.end();)
      if (I->m_FromM == T->getModule()) {
        boundToT.push_back(*I);
        I = m_AtExitFuncs.erase(I);
      }
      else
        ++I;
  } // end of spin lock lifetime block.

  // 'Unload' the cxa_atexit entities.
  for (AtExitFunctions::reverse_iterator I = boundToT.rbegin(),
         E = boundToT.rend(); I != E; ++I) {
    const CXAAtExitElement& AEE = *I;
    (*AEE.m_Func)(AEE.m_Arg);
  }
}

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 (std::set<std::string>::const_iterator i = m_unresolvedSymbols.begin(),
         e = m_unresolvedSymbols.end(); i != e; ++i) {
#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) << *i << funcname; // TODO: demangle the names.
#endif

    cling::errs() << "IncrementalExecutor::executeFunction: symbol '" << *i
                  << "' 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(*i);
    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>Remove the Windows ELF formatting from IncrementalExecutor, since it is now in CIFactory<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/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, unsigned Fmt = 0) {
  const clang::TargetOptions& TargetOpts = CI.getTargetOpts();
  const clang::CodeGenOptions& CGOpt = CI.getCodeGenOpts();
  Triple TheTriple(TargetOpts.Triple);
  if (Fmt) {
    assert(Fmt > llvm::Triple::UnknownObjectFormat &&
           Fmt <= llvm::Triple::MachO && "Invalid Format");
    TheTriple.setObjectFormat(static_cast<llvm::Triple::ObjectFormatType>(Fmt));
  }

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

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

  llvm::TargetOptions Options = llvm::TargetOptions();
// 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::unique_ptr<TargetMachine> TM;
  TM.reset(TheTarget->createTargetMachine(TheTriple.getTriple(),
                                          MCPU, FeaturesStr,
                                          Options,
                                          Optional<Reloc::Model>(),
                                          CMModel,
                                          OptLevel));
  return TM;
}
} // anonymous namespace

IncrementalExecutor::IncrementalExecutor(clang::DiagnosticsEngine& diags,
                                         const clang::CompilerInstance& CI):
  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 );

  // No need to protect this access of m_AtExitFuncs, since nobody
  // can use this object yet.
  m_AtExitFuncs.reserve(256);

  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() {
  // No need to protect this access, since hopefully there is no concurrent
  // shutdown request.
  for (size_t I = 0, N = m_AtExitFuncs.size(); I < N; ++I) {
    const CXAAtExitElement& AEE = m_AtExitFuncs[N - I - 1];
    (*AEE.m_Func)(AEE.m_Arg);
  }
}

void IncrementalExecutor::AddAtExitFunc(void (*func) (void*), void* arg,
                                        llvm::Module* M) {
  // Register a CXAAtExit function
  cling::internal::SpinLockGuard slg(m_AtExitFuncsSpinLock);
  m_AtExitFuncs.push_back(CXAAtExitElement(func, arg, M));
}

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) {
  llvm::Module* m = T.getModule();
  assert(m && "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 boundToT;

  {
    cling::internal::SpinLockGuard slg(m_AtExitFuncsSpinLock);
    for (AtExitFunctions::iterator I = m_AtExitFuncs.begin();
         I != m_AtExitFuncs.end();)
      if (I->m_FromM == T->getModule()) {
        boundToT.push_back(*I);
        I = m_AtExitFuncs.erase(I);
      }
      else
        ++I;
  } // end of spin lock lifetime block.

  // 'Unload' the cxa_atexit entities.
  for (AtExitFunctions::reverse_iterator I = boundToT.rbegin(),
         E = boundToT.rend(); I != E; ++I) {
    const CXAAtExitElement& AEE = *I;
    (*AEE.m_Func)(AEE.m_Arg);
  }
}

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 (std::set<std::string>::const_iterator i = m_unresolvedSymbols.begin(),
         e = m_unresolvedSymbols.end(); i != e; ++i) {
#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) << *i << funcname; // TODO: demangle the names.
#endif

    cling::errs() << "IncrementalExecutor::executeFunction: symbol '" << *i
                  << "' 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(*i);
    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|>