<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 "cling/Interpreter/Value.h"
#include "cling/Interpreter/Transaction.h"

#include "clang/Basic/Diagnostic.h"

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

using namespace llvm;

namespace cling {

IncrementalExecutor::IncrementalExecutor(clang::DiagnosticsEngine& diags):
  m_CurrentAtExitModule(0)
#if 0
  : m_Diags(diags)
#endif
{
  m_AtExitFuncs.reserve(256);

  m_JIT.reset(new IncrementalJIT(*this, std::move(CreateHostTargetMachine())));
}

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

std::unique_ptr<TargetMachine>
  IncrementalExecutor::CreateHostTargetMachine() const {
  // TODO: make this configurable.
  Triple TheTriple(sys::getProcessTriple());
  std::string Error;
  const Target *TheTarget
    = TargetRegistry::lookupTarget(TheTriple.getTriple(), Error);
  if (!TheTarget) {
    llvm::errs() << "cling::IncrementalExecutor: unable to find target:\n"
                 << Error;
  }

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

  TargetOptions Options = TargetOptions();
  Options.NoFramePointerElim = 1;
  Options.JITEmitDebugInfo = 1;
  Reloc::Model RelocModel = Reloc::Default;
  CodeModel::Model CMModel = CodeModel::JITDefault;
  CodeGenOpt::Level OptLevel = CodeGenOpt::Less;

  std::unique_ptr<TargetMachine> TM;
  TM.reset(TheTarget->createTargetMachine(TheTriple.getTriple(),
                                          MCPU, FeaturesStr,
                                          Options,
                                          RelocModel, CMModel,
                                          OptLevel));
  return std::move(TM);
}

void IncrementalExecutor::shuttingDown() {
  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) {
  // Register a CXAAtExit function
  m_AtExitFuncs.push_back(CXAAtExitElement(func, arg, m_CurrentAtExitModule));
}

void unresolvedSymbol()
{
  // throw exception?
  llvm::errs() << "IncrementalExecutor: calling unresolved symbol, "
    "see previous error message!\n";
}

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) {
    //llvm::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;
  }

  return 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");

  // Set m_CurrentAtExitModule to the Module, unset to 0 once done.
  struct AtExitModuleSetterRAII {
    llvm::Module*& m_AEM;
    AtExitModuleSetterRAII(llvm::Module* M, llvm::Module*& AEM): m_AEM(AEM)
    { AEM = M; }
    ~AtExitModuleSetterRAII() { m_AEM = 0; }
  } DSOHandleSetter(m, m_CurrentAtExitModule);

  // 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)) {
      executeInit(F->getName());

      initFuncs.push_back(F);
      if (F->getName().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;
  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;

  // '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* symbolName,  void* symbolAddress) {
  void* actualAddress
    = llvm::sys::DynamicLibrary::SearchForAddressOfSymbol(symbolName);
  if (actualAddress)
    return false;

  llvm::sys::DynamicLibrary::AddSymbol(symbolName, symbolAddress);
  return true;
}

void* IncrementalExecutor::getAddressOfGlobal(llvm::StringRef symbolName,
                                              bool* fromJIT /*=0*/) {
  // Return a symbol's address, and whether it was jitted.
  void* address
    = llvm::sys::DynamicLibrary::SearchForAddressOfSymbol(symbolName);

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

  if (!address)
    return (void*)m_JIT->getSymbolAddress(symbolName);

  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());

  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

    llvm::errs() << "IncrementalExecutor::executeFunction: symbol '" << *i
                 << "' unresolved while linking ";
    if (!title.empty())
      llvm::errs() << title << "'";
    llvm::errs() << trigger;
    if (!title.empty())
      llvm::errs() << "'";
    llvm::errs() << "!\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>Improve "missing symbol" error messages (ROOT-6755).<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 "cling/Interpreter/Value.h"
#include "cling/Interpreter/Transaction.h"
#include "cling/Utils/AST.h"

#include "clang/Basic/Diagnostic.h"

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

#ifdef LLVM_ON_WIN32
extern "C"
char *__unDName(char *demangled, const char *mangled, int out_len,
                void * (* pAlloc )(size_t), void (* pFree )(void *),
                unsigned short int flags);
#else
#include <cxxabi.h>
#endif

using namespace llvm;

namespace cling {

IncrementalExecutor::IncrementalExecutor(clang::DiagnosticsEngine& diags):
  m_CurrentAtExitModule(0)
#if 0
  : m_Diags(diags)
#endif
{
  m_AtExitFuncs.reserve(256);

  m_JIT.reset(new IncrementalJIT(*this, std::move(CreateHostTargetMachine())));
}

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

std::unique_ptr<TargetMachine>
  IncrementalExecutor::CreateHostTargetMachine() const {
  // TODO: make this configurable.
  Triple TheTriple(sys::getProcessTriple());
  std::string Error;
  const Target *TheTarget
    = TargetRegistry::lookupTarget(TheTriple.getTriple(), Error);
  if (!TheTarget) {
    llvm::errs() << "cling::IncrementalExecutor: unable to find target:\n"
                 << Error;
  }

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

  TargetOptions Options = TargetOptions();
  Options.NoFramePointerElim = 1;
  Options.JITEmitDebugInfo = 1;
  Reloc::Model RelocModel = Reloc::Default;
  CodeModel::Model CMModel = CodeModel::JITDefault;
  CodeGenOpt::Level OptLevel = CodeGenOpt::Less;

  std::unique_ptr<TargetMachine> TM;
  TM.reset(TheTarget->createTargetMachine(TheTriple.getTriple(),
                                          MCPU, FeaturesStr,
                                          Options,
                                          RelocModel, CMModel,
                                          OptLevel));
  return std::move(TM);
}

void IncrementalExecutor::shuttingDown() {
  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) {
  // Register a CXAAtExit function
  m_AtExitFuncs.push_back(CXAAtExitElement(func, arg, m_CurrentAtExitModule));
}

void unresolvedSymbol()
{
  // throw exception?
  llvm::errs() << "IncrementalExecutor: calling unresolved symbol, "
    "see previous error message!\n";
}

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) {
    //llvm::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;
  }

  return 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");

  // Set m_CurrentAtExitModule to the Module, unset to 0 once done.
  struct AtExitModuleSetterRAII {
    llvm::Module*& m_AEM;
    AtExitModuleSetterRAII(llvm::Module* M, llvm::Module*& AEM): m_AEM(AEM)
    { AEM = M; }
    ~AtExitModuleSetterRAII() { m_AEM = 0; }
  } DSOHandleSetter(m, m_CurrentAtExitModule);

  // 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)) {
      executeInit(F->getName());

      initFuncs.push_back(F);
      if (F->getName().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;
  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;

  // '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* symbolName,  void* symbolAddress) {
  void* actualAddress
    = llvm::sys::DynamicLibrary::SearchForAddressOfSymbol(symbolName);
  if (actualAddress)
    return false;

  llvm::sys::DynamicLibrary::AddSymbol(symbolName, symbolAddress);
  return true;
}

void* IncrementalExecutor::getAddressOfGlobal(llvm::StringRef symbolName,
                                              bool* fromJIT /*=0*/) {
  // Return a symbol's address, and whether it was jitted.
  void* address
    = llvm::sys::DynamicLibrary::SearchForAddressOfSymbol(symbolName);

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

  if (!address)
    return (void*)m_JIT->getSymbolAddress(symbolName);

  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());

  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

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

    // Be helpful, demangle!
    std::string demangledName;
    {
#ifndef LLVM_ON_WIN32
      int status = 0;
      char *demang = abi::__cxa_demangle(i->c_str(), 0, 0, &status);
      if (status == 0)
        demangledName = demang;
      free(demang);
#else
      if (char* demang = __unDName(0, i->c_str(), 0, malloc, free, 0)) {
        demangledName = demang;
        free(demang);
      }
#endif
    }
    if (!demangledName.empty()) {
       llvm::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><commit_msg>Gui: auto close transaction on Document resetEdit<commit_after><|endoftext|>


<commit_before>#include "stack.hpp"
#include <catch.hpp>

SCENARIO("push") {
	stack<size_t> a;
	a.push(1);
	REQUIRE(a.count() == 1);
}
<commit_msg>Update init.cpp<commit_after>#include <stack.hpp>
#include <catch.hpp>
#include <iostream>
using namespace std;

SCENARIO("count", "[count]"){
  stack<int> s;
  s.push(1);
  REQUIRE(s.count()==1);
}

SCENARIO("push", "[push]"){
  stack<int> s;
  s.push(1);
  REQUIRE(s.count()==1);
  REQUIRE(s.top()==1);
}

SCENARIO("pop", "[pop]"){
  stack<int> s;
  s.push(1);
  s.pop();
  REQUIRE(s.count()==0);
}

SCENARIO("cop", "[cop]"){
   stack<int> s;
   s.push(1);
   stack<int> s2=s;
   REQUIRE(s.count()==1);
   REQUIRE(s.top()==1);
 }

SCENARIO("top", "[top]"){
  stack<int> s;
  s.push(1);
  REQUIRE(s.top()==1);
}

SCENARIO("empty", "[empty]"){
  stack<int> s1, s2;
  s1.push(1);
  REQUIRE(!s1.empty());
  REQUIRE(s2.empty());
}
<|endoftext|>


<commit_before>
#include "stdafx.hpp"

#include <functional>

#include "CppUnitTest.h"
#include "..\TestUtilities\TestUtilities.hpp"
#include "..\TestUtilities\QuantityComparisons.hpp"
#include "..\TestUtilities\GeometryComparisons.hpp"
#include "..\TestUtilities\Algebra.hpp"

#include "..\Quantities\Dimensionless.hpp"
#include "..\Quantities\Quantities.hpp"
#include "..\Quantities\SI.hpp"
#include "..\Quantities\Constants.hpp"
#include "..\Quantities\UK.hpp"
#include "..\Quantities\BIPM.hpp"
#include "..\Quantities\Astronomy.hpp"
#include "..\Geometry\R3Element.hpp"
#include "..\Geometry\Grassmann.hpp"
#include "..\Quantities\ElementaryFunctions.hpp"

using namespace Microsoft::VisualStudio::CppUnitTestFramework;

namespace Principia {
namespace Geometry {
namespace {

using namespace TestUtilities;

using namespace Quantities;
using namespace SI;
using namespace UK;
using namespace BIPM;
using namespace Astronomy;
using namespace Constants;

TEST_CLASS(R3ElementTests) {
 public:
  TEST_METHOD(Dumb3Vector) {
    R3Element<Speed> nullVector(0 * Metre / Second,
                                0 * Metre / Second,
                                0 * Metre / Second);
    R3Element<Speed> u(1 * Metre / Second,
                       120 * Kilo(Metre) / Hour,
                       -SpeedOfLight);
    R3Element<Speed> v(-20 * Knot,
                       2 * π * AstronomicalUnit / JulianYear,
                       1 * Admiralty::NauticalMile / Hour);
    R3Element<Speed> w(-1 * Mile / Hour, -2 * Foot / Second, -3 * Knot);
    R3Element<Speed> a(88 * Mile / Hour, 300 * Metre / Second, 46 * Knot);
    AssertEqual((e * Dimensionless(42)) * v, e * (Dimensionless(42) * v));
    TestVectorSpace<R3Element<Speed>,
                    Dimensionless>(nullVector, u, v, w, Dimensionless(0),
                                   Dimensionless(1), e, Dimensionless(42));
    TestAlternatingBilinearMap(Cross<Speed, Speed>, u,
                               v, w, a, Dimensionless(42));
    TestSymmetricPositiveDefiniteBilinearMap(Dot<Speed, Speed>,
                                             u, v, w, a, Dimensionless(42));
  }
};

}  // namepsace
}  // namespace Geometry
}  // namespace Principia
<commit_msg>Remove blank line.<commit_after>#include "stdafx.hpp"

#include <functional>

#include "CppUnitTest.h"
#include "..\TestUtilities\TestUtilities.hpp"
#include "..\TestUtilities\QuantityComparisons.hpp"
#include "..\TestUtilities\GeometryComparisons.hpp"
#include "..\TestUtilities\Algebra.hpp"

#include "..\Quantities\Dimensionless.hpp"
#include "..\Quantities\Quantities.hpp"
#include "..\Quantities\SI.hpp"
#include "..\Quantities\Constants.hpp"
#include "..\Quantities\UK.hpp"
#include "..\Quantities\BIPM.hpp"
#include "..\Quantities\Astronomy.hpp"
#include "..\Geometry\R3Element.hpp"
#include "..\Geometry\Grassmann.hpp"
#include "..\Quantities\ElementaryFunctions.hpp"

using namespace Microsoft::VisualStudio::CppUnitTestFramework;

namespace Principia {
namespace Geometry {
namespace {

using namespace TestUtilities;

using namespace Quantities;
using namespace SI;
using namespace UK;
using namespace BIPM;
using namespace Astronomy;
using namespace Constants;

TEST_CLASS(R3ElementTests) {
 public:
  TEST_METHOD(Dumb3Vector) {
    R3Element<Speed> nullVector(0 * Metre / Second,
                                0 * Metre / Second,
                                0 * Metre / Second);
    R3Element<Speed> u(1 * Metre / Second,
                       120 * Kilo(Metre) / Hour,
                       -SpeedOfLight);
    R3Element<Speed> v(-20 * Knot,
                       2 * π * AstronomicalUnit / JulianYear,
                       1 * Admiralty::NauticalMile / Hour);
    R3Element<Speed> w(-1 * Mile / Hour, -2 * Foot / Second, -3 * Knot);
    R3Element<Speed> a(88 * Mile / Hour, 300 * Metre / Second, 46 * Knot);
    AssertEqual((e * Dimensionless(42)) * v, e * (Dimensionless(42) * v));
    TestVectorSpace<R3Element<Speed>,
                    Dimensionless>(nullVector, u, v, w, Dimensionless(0),
                                   Dimensionless(1), e, Dimensionless(42));
    TestAlternatingBilinearMap(Cross<Speed, Speed>, u,
                               v, w, a, Dimensionless(42));
    TestSymmetricPositiveDefiniteBilinearMap(Dot<Speed, Speed>,
                                             u, v, w, a, Dimensionless(42));
  }
};

}  // namepsace
}  // namespace Geometry
}  // namespace Principia
<|endoftext|>


<commit_before>/**
 * @file limits.hxx
 *
 * @brief
 */

#pragma once

#include <limits>
#include <cmath>

#include <gunrock/util/type_traits.hxx>

namespace gunrock {

template <typename type_t, typename enable_t = void>
struct numeric_limits : std::numeric_limits<type_t> {};

// Numeric Limits (additional support) for invalid() values.
template <typename type_t>
struct numeric_limits<
    type_t,
    typename std::enable_if_t<std::is_integral<type_t>::value &&
                              std::is_signed<type_t>::value>>
    : std::numeric_limits<type_t> {
  constexpr static type_t invalid() {
    return std::integral_constant<type_t, -1>::value;
  }
};

template <typename type_t>
struct numeric_limits<
    type_t,
    typename std::enable_if_t<std::is_integral<type_t>::value &&
                              std::is_unsigned<type_t>::value>>
    : std::numeric_limits<type_t> {
  constexpr static type_t invalid() {
    return std::integral_constant<type_t,
                                  std::numeric_limits<type_t>::max()>::value;
  }
};

template <typename type_t>
struct numeric_limits<
    type_t,
    typename std::enable_if_t<std::is_floating_point<type_t>::value>>
    : std::numeric_limits<type_t> {
  constexpr static type_t invalid() {
    return std::numeric_limits<type_t>::quiet_NaN();
  }
};

}  // namespace gunrock

namespace gunrock {
namespace util {
namespace limits {

template <typename type_t>
__host__ __device__ __forceinline__ bool is_valid(type_t value) {
  static_assert((std::is_integral<type_t>::value ||
                 std::is_floating_point<type_t>::value),
                "type_t must be an arithmetic type.");
  if constexpr (std::is_integral<type_t>::value)
    return (value != gunrock::numeric_limits<type_t>::invalid());

  // else if constexpr (std::is_floating_point<type_t>::value)
  // just putting else doesn't work (gives a warning), even though it should...
  return isnan(value) ? false : true;  // XXX: test this on device
}

}  // namespace limits
}  // namespace util
}  // namespace gunrock<commit_msg>Better type limit test?<commit_after>/**
 * @file limits.hxx
 *
 * @brief
 */

#pragma once

#include <limits>
#include <cmath>

#include <gunrock/util/type_traits.hxx>

namespace gunrock {

template <typename type_t, typename enable_t = void>
struct numeric_limits : std::numeric_limits<type_t> {};

// Numeric Limits (additional support) for invalid() values.
template <typename type_t>
struct numeric_limits<
    type_t,
    typename std::enable_if_t<std::is_integral<type_t>::value &&
                              std::is_signed<type_t>::value>>
    : std::numeric_limits<type_t> {
  constexpr static type_t invalid() {
    return std::integral_constant<type_t, -1>::value;
  }
};

template <typename type_t>
struct numeric_limits<
    type_t,
    typename std::enable_if_t<std::is_integral<type_t>::value &&
                              std::is_unsigned<type_t>::value>>
    : std::numeric_limits<type_t> {
  constexpr static type_t invalid() {
    return std::integral_constant<type_t,
                                  std::numeric_limits<type_t>::max()>::value;
  }
};

template <typename type_t>
struct numeric_limits<
    type_t,
    typename std::enable_if_t<std::is_floating_point<type_t>::value>>
    : std::numeric_limits<type_t> {
  constexpr static type_t invalid() {
    return std::numeric_limits<type_t>::quiet_NaN();
  }
};

}  // namespace gunrock

namespace gunrock {
namespace util {
namespace limits {

template <typename type_t>
constexpr __host__ __device__ __forceinline__ bool is_valid(type_t value) {
  static_assert((std::is_integral<type_t>::value ||
                 std::is_floating_point<type_t>::value),
                "type_t must be an arithmetic type.");
  if (std::is_integral<type_t>::value)
    return (value != gunrock::numeric_limits<type_t>::invalid());
  else
    return isnan(value) ? false : true;
}

}  // namespace limits
}  // namespace util
}  // namespace gunrock<|endoftext|>


<commit_before>#include <BinaryTree.hpp>
#include <catch.hpp>

SCENARIO ("init", "[init]")
{
  BinaryTree<int> obj;
  REQUIRE(obj.root_() == nullptr);
}

SCENARIO("insert", "[insert]")
{
  BinaryTree<int> obj;
  obj.insert_node(3);
  REQUIRE(obj.find_node(3, obj.root_())->data == 3);
}

SCENARIO("find_node", "[find_node]")
{
  BinaryTree<int> obj;
  obj.insert_node(2);
  REQUIRE(obj.find_node(2, obj.root_()) != nullptr);
  REQUIRE(obj.find_node(2, obj.root_())->data == 2);
}

SCENARIO("get root", "[get root]")
{
  BinaryTree<int> obj;
  obj.insert_node(4);
  REQUIRE(obj.root_() != 0);
}

SCENARIO ("reading/writing", "[read/write]")
{
  BinaryTree<int> obj;
  obj.insert_node(3);
  obj.insert_node(3);
  obj.writing("file2.txt");
  BinaryTree<int> obj_1;
  obj_1.reading("file2.txt");
  REQUIRE(obj_1.find_node(3, obj_1.root_());
  REQUIRE(obj_1.find_node(3, obj_1.root_());
}
<commit_msg>Update init.cpp<commit_after>#include <BinaryTree.hpp>
#include <catch.hpp>

SCENARIO ("init", "[init]")
{
  BinaryTree<int> obj;
  REQUIRE(obj.root_() == nullptr);
}

SCENARIO("insert", "[insert]")
{
  BinaryTree<int> obj;
  obj.insert_node(3);
  REQUIRE(obj.find_node(3, obj.root_())->data == 3);
}

SCENARIO("find_node", "[find_node]")
{
  BinaryTree<int> obj;
  obj.insert_node(2);
  REQUIRE(obj.find_node(2, obj.root_()) != nullptr);
  REQUIRE(obj.find_node(2, obj.root_())->data == 2);
}

SCENARIO("get root", "[get root]")
{
  BinaryTree<int> obj;
  obj.insert_node(4);
  REQUIRE(obj.root_() != 0);
}

SCENARIO ("reading/writing", "[read/write]")
{
  BinaryTree<int> obj;
  obj.insert_node(3);
  obj.insert_node(3);
  obj.writing("file2.txt");
  BinaryTree<int> obj_1;
  obj_1.reading("file2.txt");
  REQUIRE(obj_1.find_node(3, obj_1.root_()));
  REQUIRE(obj_1.find_node(3, obj_1.root_()));
}
<|endoftext|>


<commit_before>//===- SimplifyLibCalls.cpp - Optimize specific well-known librayr calls --===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by Reid Spencer group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements a variety of small optimizations for calls to specific
// well-known (e.g. runtime library) function calls. For example, a call to the
// function "exit(3)" that occurs within the main() function can be transformed
// into a simple "return 3" instruction. Many of the ideas for these
// optimizations were taken from GCC's "builtins.c" file but their
// implementation here is completely knew and LLVM-centric
//
//===----------------------------------------------------------------------===//

#include "llvm/Transforms/IPO.h"
#include "llvm/Module.h"
#include "llvm/Pass.h"
#include "llvm/Instructions.h"
#include "llvm/ADT/Statistic.h"
using namespace llvm;

namespace {
  Statistic<> SimplifiedLibCalls("simplified-lib-calls",
      "Number of well-known library calls simplified");

  /// This class is the base class for a set of small but important
  /// optimizations of calls to well-known functions, such as those in the c
  /// library. This class provides the basic infrastructure for handling
  /// runOnModule. Subclasses register themselves and provide two methods:
  /// RecognizeCall and OptimizeCall. Whenever this class finds a function call,
  /// it asks the subclasses to recognize the call. If it is recognized, then
  /// the OptimizeCall method is called on that subclass instance. In this way
  /// the subclasses implement the calling conditions on which they trigger and
  /// the action to perform, making it easy to add new optimizations of this
  /// form.
  /// @brief A ModulePass for optimizing well-known function calls
  struct SimplifyLibCalls : public ModulePass {

    /// For this pass, process all of the function calls in the module, calling
    /// RecognizeCall and OptimizeCall as appropriate.
    virtual bool runOnModule(Module &M);

  };

  RegisterOpt<SimplifyLibCalls>
    X("simplify-libcalls","Simplify well-known library calls");

  struct CallOptimizer
  {
    /// @brief Constructor that registers the optimization
    CallOptimizer();

    virtual ~CallOptimizer();

    /// The implementations of this function in subclasses is the heart of the
    /// SimplifyLibCalls algorithm. Sublcasses of this class implement
    /// OptimizeCall to determine if (a) the conditions are right for optimizing
    /// the call and (b) to perform the optimization. If an action is taken
    /// against ci, the subclass is responsible for returning true and ensuring
    /// that ci is erased from its parent.
    /// @param ci the call instruction under consideration
    /// @param f the function that ci calls.
    /// @brief Optimize a call, if possible.
    virtual bool OptimizeCall(CallInst* ci, const Function* f) const = 0;
  };

  /// @brief The list of optimizations deriving from CallOptimizer
  std::vector<struct CallOptimizer*> optlist;

  CallOptimizer::CallOptimizer()
  {
    // Register this call optimizer
    optlist.push_back(this);
  }

  /// Make sure we get our virtual table in this file.
  CallOptimizer::~CallOptimizer() {}
}

ModulePass *llvm::createSimplifyLibCallsPass()
{
  return new SimplifyLibCalls();
}

bool SimplifyLibCalls::runOnModule(Module &M)
{
  for (Module::iterator FI = M.begin(), FE = M.end(); FI != FE; ++FI)
  {
    // All the "well-known" functions are external because they live in a
    // runtime library somewhere and were (probably) not compiled by LLVM.
    // So, we only act on external functions that have non-empty uses.
    if (FI->isExternal() && !FI->use_empty())
    {
      // Loop over each of the uses of the function
      for (Value::use_iterator UI = FI->use_begin(), UE = FI->use_end();
           UI != UE ; )
      {
        CallInst* CI = dyn_cast<CallInst>(*UI);
        ++UI;

        // If the use of the function is a call instruction
        if (CI)
        {
          // Loop over each of the registered optimizations and find the one
          // that can optimize this call.
          std::vector<CallOptimizer*>::iterator OI = optlist.begin();
          std::vector<CallOptimizer*>::iterator OE = optlist.end();
          for ( ; OI != OE ; ++OI)
          {
            if ((*OI)->OptimizeCall(CI,&(*FI)))
            {
              ++SimplifiedLibCalls;
              break;
            }
          }
        }
      }
    }
  }
  return true;
}

namespace {

/// This CallOptimizer will find instances of a call to "exit" that occurs
/// within the "main" function and change it to a simple "ret" instruction with
/// the same value as passed to the exit function. It assumes that the
/// instructions after the call to exit(3) can be deleted since they are
/// unreachable anyway.
/// @brief Replace calls to exit in main with a simple return
struct ExitInMainOptimization : public CallOptimizer
{
virtual ~ExitInMainOptimization() {}
bool OptimizeCall(CallInst* ci, const Function* func) const
{
  // If this isn't the exit function then we don't act
  if (func->getName() != "exit")
    return false;

  // If the call isn't coming from main then we don't act
  if (const Function* f = ci->getParent()->getParent())
    if (f->getName() != "main")
      return false;

  // Okay, time to replace it. Get the basic block of the call instruction
  BasicBlock* bb = ci->getParent();

  // Create a return instruction that we'll replace the call with. Note that
  // the argument of the return is the argument of the call instruction.
  ReturnInst* ri = new ReturnInst(ci->getOperand(1), ci);

  // Erase everything from the call instruction to the end of the block. There
  // really shouldn't be anything other than the call instruction, but just in
  // case there is we delete it all because its now dead.
  bb->getInstList().erase(ci, bb->end());

  return true;
}

} ExitInMainOptimizer;

}
<commit_msg>Post-Review Cleanup: * Fix comments at top of file * Change algorithm for running the call optimizations from n*n to something   closer to n. * Use a hash_map to store and lookup the optimizations since there will   eventually (or potentially) be a large number of them. This gets lookup   based on the name of the function to O(1). Each CallOptimizer now has a   std::string member named func_name that tracks the name of the function   that it applies to. It is this string that is entered into the hash_map   for fast comparison against the function names encountered in the module. * Cleanup some style issues pertaining to iterator invalidation * Don't pass the Function pointer to the OptimizeCall function because if   the optimization needs it, it can get it from the CallInst passed in. * Add the skeleton for a new CallOptimizer, StrCatOptimizer which will   eventually replace strcat's of constant strings with direct copies.<commit_after>//===- SimplifyLibCalls.cpp - Optimize specific well-known library calls --===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by Reid Spencer and is distributed under the
// University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements a variety of small optimizations for calls to specific
// well-known (e.g. runtime library) function calls. For example, a call to the
// function "exit(3)" that occurs within the main() function can be transformed
// into a simple "return 3" instruction. Any optimization that takes this form
// (replace call to library function with simpler code that provides same
// result) belongs in this file.
//
//===----------------------------------------------------------------------===//

#include "llvm/Transforms/IPO.h"
#include "llvm/Module.h"
#include "llvm/Pass.h"
#include "llvm/Instructions.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/hash_map"
using namespace llvm;

namespace {
  Statistic<> SimplifiedLibCalls("simplified-lib-calls",
      "Number of well-known library calls simplified");

  /// This class is the base class for a set of small but important
  /// optimizations of calls to well-known functions, such as those in the c
  /// library. This class provides the basic infrastructure for handling
  /// runOnModule. Subclasses register themselves and provide two methods:
  /// RecognizeCall and OptimizeCall. Whenever this class finds a function call,
  /// it asks the subclasses to recognize the call. If it is recognized, then
  /// the OptimizeCall method is called on that subclass instance. In this way
  /// the subclasses implement the calling conditions on which they trigger and
  /// the action to perform, making it easy to add new optimizations of this
  /// form.
  /// @brief A ModulePass for optimizing well-known function calls
  struct SimplifyLibCalls : public ModulePass {

    /// For this pass, process all of the function calls in the module, calling
    /// RecognizeCall and OptimizeCall as appropriate.
    virtual bool runOnModule(Module &M);

  };

  RegisterOpt<SimplifyLibCalls>
    X("simplify-libcalls","Simplify well-known library calls");

  struct CallOptimizer
  {
    /// @brief Constructor that registers the optimization
    CallOptimizer(const char * fname );

    virtual ~CallOptimizer();

    /// The implementations of this function in subclasses is the heart of the
    /// SimplifyLibCalls algorithm. Sublcasses of this class implement
    /// OptimizeCall to determine if (a) the conditions are right for optimizing
    /// the call and (b) to perform the optimization. If an action is taken
    /// against ci, the subclass is responsible for returning true and ensuring
    /// that ci is erased from its parent.
    /// @param ci the call instruction under consideration
    /// @param f the function that ci calls.
    /// @brief Optimize a call, if possible.
    virtual bool OptimizeCall(CallInst* ci) const = 0;

    const std::string& getFunctionName() const { return func_name; }
  private:
    std::string func_name;
  };

  /// @brief The list of optimizations deriving from CallOptimizer
  hash_map<std::string,CallOptimizer*> optlist;

  CallOptimizer::CallOptimizer(const char* fname)
    : func_name(fname)
  {
    // Register this call optimizer
    optlist[func_name] = this;
  }

  /// Make sure we get our virtual table in this file.
  CallOptimizer::~CallOptimizer() {}
}

ModulePass *llvm::createSimplifyLibCallsPass()
{
  return new SimplifyLibCalls();
}

bool SimplifyLibCalls::runOnModule(Module &M)
{
  for (Module::iterator FI = M.begin(), FE = M.end(); FI != FE; ++FI)
  {
    // All the "well-known" functions are external because they live in a
    // runtime library somewhere and were (probably) not compiled by LLVM.
    // So, we only act on external functions that have non-empty uses.
    if (FI->isExternal() && !FI->use_empty())
    {
      // Get the optimization class that pertains to this function
      if (CallOptimizer* CO = optlist[FI->getName()] )
      {
        // Loop over each of the uses of the function
        for (Value::use_iterator UI = FI->use_begin(), UE = FI->use_end();
             UI != UE ; )
        {
          // If the use of the function is a call instruction
          if (CallInst* CI = dyn_cast<CallInst>(*UI++))
          {
            // Do the optimization on the CallOptimizer we found earlier.
            if (CO->OptimizeCall(CI))
            {
              ++SimplifiedLibCalls;
              break;
            }
          }
        }
      }
    }
  }
  return true;
}

namespace {

/// This CallOptimizer will find instances of a call to "exit" that occurs
/// within the "main" function and change it to a simple "ret" instruction with
/// the same value as passed to the exit function. It assumes that the
/// instructions after the call to exit(3) can be deleted since they are
/// unreachable anyway.
/// @brief Replace calls to exit in main with a simple return
struct ExitInMainOptimization : public CallOptimizer
{
  ExitInMainOptimization() : CallOptimizer("exit") {}
  virtual ~ExitInMainOptimization() {}
  virtual bool OptimizeCall(CallInst* ci) const
  {
    // If the call isn't coming from main or  main doesn't have external linkage
    // or the return type of main is not the same as the type of the exit(3)
    // argument then we don't act
    if (const Function* f = ci->getParent()->getParent())
      if (!(f->hasExternalLinkage() &&
            (f->getReturnType() == ci->getOperand(1)->getType()) &&
            (f->getName() == "main")))
        return false;

    // Okay, time to replace it. Get the basic block of the call instruction
    BasicBlock* bb = ci->getParent();

    // Create a return instruction that we'll replace the call with. Note that
    // the argument of the return is the argument of the call instruction.
    ReturnInst* ri = new ReturnInst(ci->getOperand(1), ci);

    // Erase everything from the call instruction to the end of the block. There
    // really shouldn't be anything other than the call instruction, but just in
    // case there is we delete it all because its now dead.
    bb->getInstList().erase(ci, bb->end());

    return true;
  }
} ExitInMainOptimizer;

/// This CallOptimizer will find instances of a call to "exit" that occurs
/// within the "main" function and change it to a simple "ret" instruction with
/// the same value as passed to the exit function. It assumes that the
/// instructions after the call to exit(3) can be deleted since they are
/// unreachable anyway.
/// @brief Replace calls to exit in main with a simple return
struct StrCatOptimization : public CallOptimizer
{
  StrCatOptimization() : CallOptimizer("strcat") {}
  virtual ~StrCatOptimization() {}
  virtual bool OptimizeCall(CallInst* ci) const
  {
    return false;
  }
} StrCatOptimizer;

}
<|endoftext|>


<commit_before>#include "IconRenderer.h"

#include "HumbugApplication.h"

#include <QPixmapCache>
#include <QPainter>
#include <QSvgRenderer>
#include <QDebug>

IconRenderer::IconRenderer(const QString &svgPath, QObject *parent) :
    QObject(parent),
    m_svgPath(svgPath),
    m_renderer(new QSvgRenderer(svgPath, this))
{
    // NOTE: Experimental testing of the menu bar height:
    // CGFloat hgt = [[[NSApplication sharedApplication] mainMenu] menuBarHeight];
    // and qsystemtrayicon_mac.mm (scale = hgt - 4) shows that we want 18px
    // square menu pixmaps for os x, so make sure to give our QIcon that size
    // 16px is the default size on Windows, and 22px is default on X11
    // 36px is in case Qt is smart enough to render for retina displays at double-size
    // (it's not).

    m_defaultSizes << 16 << 18 << 22 << 36;
    QPixmapCache::setCacheLimit(1000);

    QSvgRenderer r(QLatin1String(":images/usericon.svg"));
    foreach(int size, m_defaultSizes) {
        QImage image(QSize(size, size), QImage::Format_ARGB32_Premultiplied);
        image.fill(Qt::transparent);
        QPainter p(&image);
        p.setRenderHint(QPainter::Antialiasing);

        r.render(&p);
        m_personIcon.addPixmap(QPixmap::fromImage(image));
    }
}

QIcon IconRenderer::icon(int unreadNormal, int unreadPMs) {
    // -1x-1 size is our magic key for icons
    const QString cKey = cacheKey(QSize(-1, -1), unreadNormal, unreadPMs);
    QIcon icn = m_iconCache.value(cKey, QIcon());
    if (!icn.isNull()) {
        return icn;
    }

    foreach(int size, m_defaultSizes) {
        const QPixmap pm = pixmap(QSize(size, size), unreadNormal, unreadPMs);
        icn.addPixmap(pm);
    }

    m_iconCache.insert(cKey, icn);

    return icn;
}

QPixmap IconRenderer::pixmap(const QSize &size, int unreadNormal, int unreadPMs) {
    const QString cKey = cacheKey(size, unreadNormal, unreadPMs);
    QPixmap pm;
    if (!QPixmapCache::find(cKey, &pm)) {
        pm = render(size, unreadNormal, unreadPMs);
        QPixmapCache::insert(cKey, pm);
    }

    return pm;
}

QIcon IconRenderer::personIcon() {
    return m_personIcon;
}

QString IconRenderer::cacheKey(const QSize &size, int unreadNormal, int unreadPMs) const {
    return QString("hat_%1x%2_%3_%4").arg(size.width())
                                     .arg(size.height())
                                     .arg(unreadNormal)
                                     .arg(unreadPMs);
}

QPixmap IconRenderer::render(const QSize &size, int unreadNormal, int unreadPMs) {
    QImage image(size, QImage::Format_ARGB32_Premultiplied);
    image.fill(Qt::transparent);
    QPainter p(&image);
    p.setRenderHint(QPainter::Antialiasing);

    QPen textPen(Qt::black, 1, Qt::SolidLine);
    p.setPen(textPen);
    QFont f = APP->font();
    f.setStyleStrategy(QFont::NoAntialias);

    m_renderer->render(&p);

    if (unreadNormal > 0) {
        // Unicode ∞ if greater than 99 unread msgs
        const QString disp = unreadNormal > 99 ? QChar(0x221e) : QString::number(unreadNormal);
        const int padding = 1;
        const QRect bottomHalf(padding, size.height() / 2, size.width() - 2*padding, size.height() / 2 - 2*padding);

        f.setPixelSize(bottomHalf.height() + 2);
        p.setFont(f);

        qDebug() << "Drawing in" << bottomHalf << "from" << QRect(QPoint(0, 0), size);
        p.drawText(bottomHalf, Qt::AlignCenter, disp);
    }

    p.end();

    return QPixmap::fromImage(image);
}
<commit_msg>Slight font placement/aliasing cleanup in tray icon<commit_after>#include "IconRenderer.h"

#include "HumbugApplication.h"

#include <QPixmapCache>
#include <QPainter>
#include <QSvgRenderer>
#include <QDebug>

IconRenderer::IconRenderer(const QString &svgPath, QObject *parent) :
    QObject(parent),
    m_svgPath(svgPath),
    m_renderer(new QSvgRenderer(svgPath, this))
{
    // NOTE: Experimental testing of the menu bar height:
    // CGFloat hgt = [[[NSApplication sharedApplication] mainMenu] menuBarHeight];
    // and qsystemtrayicon_mac.mm (scale = hgt - 4) shows that we want 18px
    // square menu pixmaps for os x, so make sure to give our QIcon that size
    // 16px is the default size on Windows, and 22px is default on X11
    // 36px is in case Qt is smart enough to render for retina displays at double-size
    // (it's not).

    m_defaultSizes << 16 << 18 << 22 << 36;
    QPixmapCache::setCacheLimit(1000);

    QSvgRenderer r(QLatin1String(":images/usericon.svg"));
    foreach(int size, m_defaultSizes) {
        QImage image(QSize(size, size), QImage::Format_ARGB32_Premultiplied);
        image.fill(Qt::transparent);
        QPainter p(&image);
        p.setRenderHint(QPainter::Antialiasing);

        r.render(&p);
        m_personIcon.addPixmap(QPixmap::fromImage(image));
    }
}

QIcon IconRenderer::icon(int unreadNormal, int unreadPMs) {
    // -1x-1 size is our magic key for icons
    const QString cKey = cacheKey(QSize(-1, -1), unreadNormal, unreadPMs);
    QIcon icn = m_iconCache.value(cKey, QIcon());
    if (!icn.isNull()) {
        return icn;
    }

    foreach(int size, m_defaultSizes) {
        const QPixmap pm = pixmap(QSize(size, size), unreadNormal, unreadPMs);
        icn.addPixmap(pm);
    }

    m_iconCache.insert(cKey, icn);

    return icn;
}

QPixmap IconRenderer::pixmap(const QSize &size, int unreadNormal, int unreadPMs) {
    const QString cKey = cacheKey(size, unreadNormal, unreadPMs);
    QPixmap pm;
    if (!QPixmapCache::find(cKey, &pm)) {
        pm = render(size, unreadNormal, unreadPMs);
        QPixmapCache::insert(cKey, pm);
    }

    return pm;
}

QIcon IconRenderer::personIcon() {
    return m_personIcon;
}

QString IconRenderer::cacheKey(const QSize &size, int unreadNormal, int unreadPMs) const {
    return QString("hat_%1x%2_%3_%4").arg(size.width())
                                     .arg(size.height())
                                     .arg(unreadNormal)
                                     .arg(unreadPMs);
}

QPixmap IconRenderer::render(const QSize &size, int unreadNormal, int unreadPMs) {
    QImage image(size, QImage::Format_ARGB32_Premultiplied);
    image.fill(Qt::transparent);
    QPainter p(&image);
    p.setRenderHint(QPainter::Antialiasing);

    QPen textPen(Qt::black, 1, Qt::SolidLine);
    p.setPen(textPen);
    QFont f = APP->font();

    m_renderer->render(&p);

    if (unreadNormal > 0) {
        // Unicode ∞ if greater than 99 unread msgs
        const QString disp = unreadNormal > 99 ? QChar(0x221e) : QString::number(unreadNormal);
        const int padding = 1;
        const QRect bottomHalf(padding + size.width() / 4, size.height() / 2, size.width() - 2*padding, size.height() / 2 - 2*padding);

        f.setPixelSize(bottomHalf.height() + 2);
        p.setFont(f);

//        qDebug() << "Drawing in" << bottomHalf << "from" << QRect(QPoint(0, 0), size);
        p.drawText(bottomHalf, Qt::AlignCenter, disp);
    }

    p.end();

    return QPixmap::fromImage(image);
}
<|endoftext|>


<commit_before>#include <BinaryTree.hpp>
#include <catch.hpp>

SCENARIO ("init", "[init]")
{
  BinaryTree<int> obj;
  REQUIRE(obj.root_() == nullptr);
}

SCENARIO("insert", "[insert]")
{
  BinaryTree<int> obj;
  obj.insert_node(3);
  REQUIRE(obj.find_node(3, obj.root_())->data == 3);
}

SCENARIO("find_node", "[find_node]")
{
  BinaryTree<int> obj;
  test.insert_node(4);
  REQUIRE(obj.find_node(2, obj.root_()) != nullptr);
  REQUIRE(obj.find_node(2, obj.root_())->data == 2);
}

SCENARIO("get root", "[get root]")
{
  BinaryTree<int> obj;
  obj.insert_node(4);
  REQUIRE(obj.root_() != 0);
}
<commit_msg>Update init.cpp<commit_after>#include <BinaryTree.hpp>
#include <catch.hpp>

SCENARIO ("init", "[init]")
{
  BinaryTree<int> obj;
  REQUIRE(obj.root_() == nullptr);
}

SCENARIO("insert", "[insert]")
{
  BinaryTree<int> obj;
  obj.insert_node(3);
  REQUIRE(obj.find_node(3, obj.root_())->data == 3);
}

SCENARIO("find_node", "[find_node]")
{
  BinaryTree<int> obj;
  obj.insert_node(4);
  REQUIRE(obj.find_node(2, obj.root_()) != nullptr);
  REQUIRE(obj.find_node(2, obj.root_())->data == 2);
}

SCENARIO("get root", "[get root]")
{
  BinaryTree<int> obj;
  obj.insert_node(4);
  REQUIRE(obj.root_() != 0);
}
<|endoftext|>


<commit_before>/*

Copyright (c) 2006, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#ifndef NODE_HPP
#define NODE_HPP

#include <algorithm>
#include <map>
#include <set>

#include <libtorrent/config.hpp>
#include <libtorrent/kademlia/routing_table.hpp>
#include <libtorrent/kademlia/rpc_manager.hpp>
#include <libtorrent/kademlia/node_id.hpp>
#include <libtorrent/kademlia/msg.hpp>
#include <libtorrent/kademlia/find_data.hpp>

#include <libtorrent/io.hpp>
#include <libtorrent/session_settings.hpp>
#include <libtorrent/assert.hpp>
#include <libtorrent/thread.hpp>
#include <libtorrent/bloom_filter.hpp>

#include <boost/cstdint.hpp>
#include <boost/ref.hpp>

#include "libtorrent/socket.hpp"

namespace libtorrent {
	class alert_manager;
	struct alert_dispatcher;
}

namespace libtorrent { namespace dht
{

#ifdef TORRENT_DHT_VERBOSE_LOGGING
TORRENT_DECLARE_LOG(node);
#endif

struct traversal_algorithm;

struct key_desc_t
{
	char const* name;
	int type;
	int size;
	int flags;

	enum {
		// this argument is optional, parsing will not
		// fail if it's not present
		optional = 1,
		// for dictionaries, the following entries refer
		// to child nodes to this node, up until and including
		// the next item that has the last_child flag set.
		// these flags are nestable
		parse_children = 2,
		// this is the last item in a child dictionary
		last_child = 4,
		// the size argument refers to that the size
		// has to be divisible by the number, instead
		// of having that exact size
		size_divisible = 8
	};
};

bool TORRENT_EXTRA_EXPORT verify_message(lazy_entry const* msg, key_desc_t const desc[]
	, lazy_entry const* ret[], int size , char* error, int error_size);

// this is the entry for every peer
// the timestamp is there to make it possible
// to remove stale peers
struct peer_entry
{
	tcp::endpoint addr;
	ptime added;
	bool seed;
};

// this is a group. It contains a set of group members
struct torrent_entry
{
	std::string name;
	std::set<peer_entry> peers;
};

struct dht_immutable_item
{
	dht_immutable_item() : value(0), num_announcers(0) {}
	// malloced space for the actual value
	char* value;
	// this counts the number of IPs we have seen
	// announcing this item, this is used to determine
	// popularity if we reach the limit of items to store
	bloom_filter<128> ips;
	// the last time we heard about this
	ptime last_seen;
	// number of IPs in the bloom filter
	int num_announcers;
	// size of malloced space pointed to by value
	int size;
};

struct dht_mutable_item : dht_immutable_item
{
	char sig[256];
	int seq;
};

struct rsa_key { char bytes[268]; };

inline bool operator<(rsa_key const& lhs, rsa_key const& rhs)
{
	return memcmp(lhs.bytes, rhs.bytes, sizeof(lhs.bytes)) < 0;
}

inline bool operator<(peer_entry const& lhs, peer_entry const& rhs)
{
	return lhs.addr.address() == rhs.addr.address()
		? lhs.addr.port() < rhs.addr.port()
		: lhs.addr.address() < rhs.addr.address();
}

struct null_type {};

class announce_observer : public observer
{
public:
	announce_observer(boost::intrusive_ptr<traversal_algorithm> const& algo
		, udp::endpoint const& ep, node_id const& id)
		: observer(algo, ep, id)
	{}

	void reply(msg const&) { flags |= flag_done; }
};

struct count_peers
{
	int& count;
	count_peers(int& c): count(c) {}
	void operator()(std::pair<libtorrent::dht::node_id
		, libtorrent::dht::torrent_entry> const& t)
	{
		count += t.second.peers.size();
	}
};

struct udp_socket_interface
{
	virtual bool send_packet(entry& e, udp::endpoint const& addr, int flags) = 0;
};

class TORRENT_EXTRA_EXPORT node_impl : boost::noncopyable
{
typedef std::map<node_id, torrent_entry> table_t;
typedef std::map<node_id, dht_immutable_item> dht_immutable_table_t;
typedef std::map<rsa_key, dht_mutable_item> dht_mutable_table_t;

public:
	node_impl(alert_dispatcher* alert_disp, udp_socket_interface* sock
		, dht_settings const& settings, node_id nid, address const& external_address
		, dht_observer* observer);

	virtual ~node_impl() {}

	void tick();
	void refresh(node_id const& id, find_data::nodes_callback const& f);
	void bootstrap(std::vector<udp::endpoint> const& nodes
		, find_data::nodes_callback const& f);
	void add_router_node(udp::endpoint router);

	void unreachable(udp::endpoint const& ep);
	void incoming(msg const& m);

	int num_torrents() const { return m_map.size(); }
	int num_peers() const
	{
		int ret = 0;
		std::for_each(m_map.begin(), m_map.end(), count_peers(ret));
		return ret;
	}

	int bucket_size(int bucket);

	node_id const& nid() const { return m_id; }

	boost::tuple<int, int> size() const{ return m_table.size(); }
	size_type num_global_nodes() const
	{ return m_table.num_global_nodes(); }

	int data_size() const { return int(m_map.size()); }

#ifdef TORRENT_DHT_VERBOSE_LOGGING
	void print_state(std::ostream& os) const
	{ m_table.print_state(os); }
#endif

	void announce(sha1_hash const& info_hash, int listen_port, bool seed
		, boost::function<void(std::vector<tcp::endpoint> const&)> f);

	bool verify_token(std::string const& token, char const* info_hash
		, udp::endpoint const& addr);

	std::string generate_token(udp::endpoint const& addr, char const* info_hash);

	// the returned time is the delay until connection_timeout()
	// should be called again the next time
	time_duration connection_timeout();

	// generates a new secret number used to generate write tokens
	void new_write_key();

	// pings the given node, and adds it to
	// the routing table if it respons and if the
	// bucket is not full.
	void add_node(udp::endpoint node);

	void replacement_cache(bucket_t& nodes) const
	{ m_table.replacement_cache(nodes); }

	int branch_factor() const { return m_settings.search_branching; }

	void add_traversal_algorithm(traversal_algorithm* a)
	{
		mutex_t::scoped_lock l(m_mutex);
		m_running_requests.insert(a);
	}

	void remove_traversal_algorithm(traversal_algorithm* a)
	{
		mutex_t::scoped_lock l(m_mutex);
		m_running_requests.erase(a);
	}

	void status(libtorrent::session_status& s);

	dht_settings const& settings() const { return m_settings; }

protected:

	void lookup_peers(sha1_hash const& info_hash, int prefix, entry& reply
		, bool noseed, bool scrape) const;
	bool lookup_torrents(sha1_hash const& target, entry& reply
		, char* tags) const;

	dht_settings const& m_settings;

private:
	typedef libtorrent::mutex mutex_t;
	mutex_t m_mutex;

	// this list must be destructed after the rpc manager
	// since it might have references to it
	std::set<traversal_algorithm*> m_running_requests;

	void incoming_request(msg const& h, entry& e);

	node_id m_id;

public:
	routing_table m_table;
	rpc_manager m_rpc;

private:
	table_t m_map;
	dht_immutable_table_t m_immutable_table;
	dht_mutable_table_t m_mutable_table;

	ptime m_last_tracker_tick;

	// secret random numbers used to create write tokens
	int m_secret[2];

	alert_dispatcher* m_post_alert;
	udp_socket_interface* m_sock;
};

} } // namespace libtorrent::dht

#endif // NODE_HPP

<commit_msg>one more uninitialized member<commit_after>/*

Copyright (c) 2006, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#ifndef NODE_HPP
#define NODE_HPP

#include <algorithm>
#include <map>
#include <set>

#include <libtorrent/config.hpp>
#include <libtorrent/kademlia/routing_table.hpp>
#include <libtorrent/kademlia/rpc_manager.hpp>
#include <libtorrent/kademlia/node_id.hpp>
#include <libtorrent/kademlia/msg.hpp>
#include <libtorrent/kademlia/find_data.hpp>

#include <libtorrent/io.hpp>
#include <libtorrent/session_settings.hpp>
#include <libtorrent/assert.hpp>
#include <libtorrent/thread.hpp>
#include <libtorrent/bloom_filter.hpp>

#include <boost/cstdint.hpp>
#include <boost/ref.hpp>

#include "libtorrent/socket.hpp"

namespace libtorrent {
	class alert_manager;
	struct alert_dispatcher;
}

namespace libtorrent { namespace dht
{

#ifdef TORRENT_DHT_VERBOSE_LOGGING
TORRENT_DECLARE_LOG(node);
#endif

struct traversal_algorithm;

struct key_desc_t
{
	char const* name;
	int type;
	int size;
	int flags;

	enum {
		// this argument is optional, parsing will not
		// fail if it's not present
		optional = 1,
		// for dictionaries, the following entries refer
		// to child nodes to this node, up until and including
		// the next item that has the last_child flag set.
		// these flags are nestable
		parse_children = 2,
		// this is the last item in a child dictionary
		last_child = 4,
		// the size argument refers to that the size
		// has to be divisible by the number, instead
		// of having that exact size
		size_divisible = 8
	};
};

bool TORRENT_EXTRA_EXPORT verify_message(lazy_entry const* msg, key_desc_t const desc[]
	, lazy_entry const* ret[], int size , char* error, int error_size);

// this is the entry for every peer
// the timestamp is there to make it possible
// to remove stale peers
struct peer_entry
{
	tcp::endpoint addr;
	ptime added;
	bool seed;
};

// this is a group. It contains a set of group members
struct torrent_entry
{
	std::string name;
	std::set<peer_entry> peers;
};

struct dht_immutable_item
{
	dht_immutable_item() : value(0), num_announcers(0), size(0) {}
	// malloced space for the actual value
	char* value;
	// this counts the number of IPs we have seen
	// announcing this item, this is used to determine
	// popularity if we reach the limit of items to store
	bloom_filter<128> ips;
	// the last time we heard about this
	ptime last_seen;
	// number of IPs in the bloom filter
	int num_announcers;
	// size of malloced space pointed to by value
	int size;
};

struct dht_mutable_item : dht_immutable_item
{
	char sig[256];
	int seq;
};

struct rsa_key { char bytes[268]; };

inline bool operator<(rsa_key const& lhs, rsa_key const& rhs)
{
	return memcmp(lhs.bytes, rhs.bytes, sizeof(lhs.bytes)) < 0;
}

inline bool operator<(peer_entry const& lhs, peer_entry const& rhs)
{
	return lhs.addr.address() == rhs.addr.address()
		? lhs.addr.port() < rhs.addr.port()
		: lhs.addr.address() < rhs.addr.address();
}

struct null_type {};

class announce_observer : public observer
{
public:
	announce_observer(boost::intrusive_ptr<traversal_algorithm> const& algo
		, udp::endpoint const& ep, node_id const& id)
		: observer(algo, ep, id)
	{}

	void reply(msg const&) { flags |= flag_done; }
};

struct count_peers
{
	int& count;
	count_peers(int& c): count(c) {}
	void operator()(std::pair<libtorrent::dht::node_id
		, libtorrent::dht::torrent_entry> const& t)
	{
		count += t.second.peers.size();
	}
};

struct udp_socket_interface
{
	virtual bool send_packet(entry& e, udp::endpoint const& addr, int flags) = 0;
};

class TORRENT_EXTRA_EXPORT node_impl : boost::noncopyable
{
typedef std::map<node_id, torrent_entry> table_t;
typedef std::map<node_id, dht_immutable_item> dht_immutable_table_t;
typedef std::map<rsa_key, dht_mutable_item> dht_mutable_table_t;

public:
	node_impl(alert_dispatcher* alert_disp, udp_socket_interface* sock
		, dht_settings const& settings, node_id nid, address const& external_address
		, dht_observer* observer);

	virtual ~node_impl() {}

	void tick();
	void refresh(node_id const& id, find_data::nodes_callback const& f);
	void bootstrap(std::vector<udp::endpoint> const& nodes
		, find_data::nodes_callback const& f);
	void add_router_node(udp::endpoint router);

	void unreachable(udp::endpoint const& ep);
	void incoming(msg const& m);

	int num_torrents() const { return m_map.size(); }
	int num_peers() const
	{
		int ret = 0;
		std::for_each(m_map.begin(), m_map.end(), count_peers(ret));
		return ret;
	}

	int bucket_size(int bucket);

	node_id const& nid() const { return m_id; }

	boost::tuple<int, int> size() const{ return m_table.size(); }
	size_type num_global_nodes() const
	{ return m_table.num_global_nodes(); }

	int data_size() const { return int(m_map.size()); }

#ifdef TORRENT_DHT_VERBOSE_LOGGING
	void print_state(std::ostream& os) const
	{ m_table.print_state(os); }
#endif

	void announce(sha1_hash const& info_hash, int listen_port, bool seed
		, boost::function<void(std::vector<tcp::endpoint> const&)> f);

	bool verify_token(std::string const& token, char const* info_hash
		, udp::endpoint const& addr);

	std::string generate_token(udp::endpoint const& addr, char const* info_hash);

	// the returned time is the delay until connection_timeout()
	// should be called again the next time
	time_duration connection_timeout();

	// generates a new secret number used to generate write tokens
	void new_write_key();

	// pings the given node, and adds it to
	// the routing table if it respons and if the
	// bucket is not full.
	void add_node(udp::endpoint node);

	void replacement_cache(bucket_t& nodes) const
	{ m_table.replacement_cache(nodes); }

	int branch_factor() const { return m_settings.search_branching; }

	void add_traversal_algorithm(traversal_algorithm* a)
	{
		mutex_t::scoped_lock l(m_mutex);
		m_running_requests.insert(a);
	}

	void remove_traversal_algorithm(traversal_algorithm* a)
	{
		mutex_t::scoped_lock l(m_mutex);
		m_running_requests.erase(a);
	}

	void status(libtorrent::session_status& s);

	dht_settings const& settings() const { return m_settings; }

protected:

	void lookup_peers(sha1_hash const& info_hash, int prefix, entry& reply
		, bool noseed, bool scrape) const;
	bool lookup_torrents(sha1_hash const& target, entry& reply
		, char* tags) const;

	dht_settings const& m_settings;

private:
	typedef libtorrent::mutex mutex_t;
	mutex_t m_mutex;

	// this list must be destructed after the rpc manager
	// since it might have references to it
	std::set<traversal_algorithm*> m_running_requests;

	void incoming_request(msg const& h, entry& e);

	node_id m_id;

public:
	routing_table m_table;
	rpc_manager m_rpc;

private:
	table_t m_map;
	dht_immutable_table_t m_immutable_table;
	dht_mutable_table_t m_mutable_table;

	ptime m_last_tracker_tick;

	// secret random numbers used to create write tokens
	int m_secret[2];

	alert_dispatcher* m_post_alert;
	udp_socket_interface* m_sock;
};

} } // namespace libtorrent::dht

#endif // NODE_HPP

<|endoftext|>


<commit_before>#include <BinaryTree.hpp>
#include <catch.hpp>

SCENARIO ("init", "[init]")
{
  BinaryTree<int> obj;
  REQUIRE(obj.root_() == nullptr);
}

SCENARIO ("output to cout", "<<")
{
  BinaryTree<int> tree;
  tree.insert_node(3);
  REQUIRE( std::cout << tree );
}

SCENARIO("find_node", "[find_node]")
  {
    BinaryTree<int> obj;
    obj.insert_node(4);
    obj.insert_node(2);
    REQUIRE(obj.find_node(2, obj.root_()) != nullptr);
    REQUIRE(obj.find_node(2, obj.root_())->data == 2);
  }

SCENARIO("insert", "[insert]")
{
  BinaryTree<int> obj;
  obj.insert_node(3);
  REQUIRE(obj.find_node(3, obj.root_())->data == 3);
}

SCENARIO("removeElement", "[remEl]")
{
  BinaryTree<int> obj;
  obj.insert_node(1);
  obj.insert_node(2);
  obj.insert_node(3);
  obj.remove_element(1);
  REQUIRE(obj.find_node(1, obj.root_())== nullptr);
  REQUIRE(obj.find_node(2, obj.root_())== obj.root_());
  REQUIRE(obj.root_() != nullptr);
  REQUIRE(obj.get_count() == 2);
}
<commit_msg>Update init.cpp<commit_after>#include <BinaryTree.hpp>
#include <catch.hpp>

SCENARIO ("init", "[init]")
{
  BinaryTree<int> obj;
  REQUIRE(obj.root_() == nullptr);
}

SCENARIO ("output to cout", "<<")
{
  BinaryTree<int> tree;
  tree.insert_node(3);
  REQUIRE( std::cout << tree );
}

SCENARIO("find_node", "[find_node]")
  {
    BinaryTree<int> obj;
    obj.insert_node(4);
    obj.insert_node(2);
    REQUIRE(obj.find_node(2, obj.root_()) != nullptr);
    REQUIRE(obj.find_node(2, obj.root_())->data == 2);
  }

SCENARIO("insert", "[insert]")
{
  BinaryTree<int> obj;
  obj.insert_node(3);
  REQUIRE(obj.find_node(3, obj.root_())->data == 3);
}

SCENARIO("removeElement", "[remEl]")
{
  BinaryTree<int> obj;
  obj.insert_node(1);
  obj.insert_node(2);
  obj.insert_node(3);
  obj.remove_element(1);
  REQUIRE(obj.find_node(1, obj.root_())== nullptr);
  REQUIRE(obj.find_node(2, obj.root_())== obj.root_());
  REQUIRE(obj.root_() != nullptr);
  REQUIRE(obj.count() == 2);
}
<|endoftext|>