<commit_before>//===- lib/Clang/GraphExpansion.cpp ---------------------------------------===//
//
//                                    SeeC
//
// This file is distributed under The MIT License (MIT). See LICENSE.TXT for
// details.
//
//===----------------------------------------------------------------------===//
///
/// \file
///
//===----------------------------------------------------------------------===//

#include "seec/Clang/GraphExpansion.hpp"
#include "seec/Clang/MappedMallocState.hpp"
#include "seec/Clang/MappedFunctionState.hpp"
#include "seec/Clang/MappedGlobalVariable.hpp"
#include "seec/Clang/MappedProcessState.hpp"
#include "seec/Clang/MappedProcessTrace.hpp"
#include "seec/Clang/MappedThreadState.hpp"
#include "seec/Clang/MappedValue.hpp"
#include "seec/Trace/ProcessState.hpp"
#include "seec/Util/Fallthrough.hpp"
#include "seec/Util/Range.hpp"

#include <map>

namespace seec {

namespace cm {

namespace graph {

//===----------------------------------------------------------------------===//
// ExpansionImpl
//===----------------------------------------------------------------------===//

class ExpansionImpl final {
  /// Map from Value to pointer dereferences that reference that Value.
  ///
  std::multimap<Value const *, Dereference> Edges;

  /// Map from address to pointers that reference that address.
  ///
  std::multimap<uintptr_t, std::shared_ptr<ValueOfPointer const>> Pointers;

public:
  ExpansionImpl()
  : Edges(),
    Pointers()
  {}

  void addReference(Value const &ToValue, Dereference FromPointer)
  {
    Edges.insert(std::make_pair(&ToValue, std::move(FromPointer)));
  }

  /// \brief Add the given pointer if it doesn't already exist.
  ///
  /// \return true iff the Pointer didn't already exist and was added.
  ///
  bool addPointer(std::shared_ptr<ValueOfPointer const> const &Pointer)
  {
    auto const Address = Pointer->getRawValue();

    for (auto const &Pair : range(Pointers.equal_range(Address)))
      if (Pair.second == Pointer)
        return false;

    Pointers.insert(std::make_pair(Address, Pointer));

    return true;
  }

  std::vector<Dereference>
  getReferencesOf(Value const &Val) const;

  std::vector<std::shared_ptr<ValueOfPointer const>>
  getReferencesOfArea(uintptr_t Start, uintptr_t End) const;

  bool isAreaReferenced(uintptr_t Start, uintptr_t End) const;

  std::vector<std::shared_ptr<ValueOfPointer const>>
  getAllPointers() const {
    std::vector<std::shared_ptr<ValueOfPointer const>> Ret;

    for (auto const &Pair : Pointers)
      Ret.emplace_back(Pair.second);

    return Ret;
  }
};

std::vector<Dereference>
ExpansionImpl::getReferencesOf(Value const &Val) const
{
  std::vector<Dereference> Ret;

  for (auto const &Pair : seec::range(Edges.equal_range(&Val)))
    Ret.emplace_back(Pair.second);

  return Ret;
}

std::vector<std::shared_ptr<ValueOfPointer const>>
ExpansionImpl::getReferencesOfArea(uintptr_t Start, uintptr_t End) const
{
  auto const Range = seec::range(Pointers.lower_bound(Start),
                                 Pointers.lower_bound(End));

  std::vector<std::shared_ptr<ValueOfPointer const>> Ret;

  for (auto const &Pair : Range)
    Ret.emplace_back(Pair.second);

  return Ret;
}

bool ExpansionImpl::isAreaReferenced(uintptr_t Start, uintptr_t End) const
{
  return Pointers.lower_bound(Start) != Pointers.lower_bound(End);
}

//===----------------------------------------------------------------------===//
// expand
//===----------------------------------------------------------------------===//

static bool containsPointerType(clang::Type const *CanonTy)
{
  if (!CanonTy)
    return false;

  if (CanonTy->isAnyPointerType())
    return true;

  if (auto const ArrayTy = llvm::dyn_cast<clang::ArrayType>(CanonTy)) {
    auto const ElemTy = ArrayTy->getElementType().getCanonicalType();
    return containsPointerType(ElemTy.getTypePtrOrNull());
  }
  else if (auto const RecordTy = llvm::dyn_cast<clang::RecordType>(CanonTy)) {
    auto const Decl = RecordTy->getDecl();

    for (auto Field : seec::range(Decl->field_begin(), Decl->field_end())) {
      auto const FieldTy = Field->getType().getCanonicalType();
      if (containsPointerType(FieldTy.getTypePtrOrNull()))
        return true;
    }

    return false;
  }

  return false;
}

void expand(ExpansionImpl &EI, std::shared_ptr<Value const> const &State)
{
  assert(State);

  switch (State->getKind()) {
    case seec::cm::Value::Kind::Basic: SEEC_FALLTHROUGH;
    case seec::cm::Value::Kind::Scalar:
      break;

    case seec::cm::Value::Kind::Array:
      {
        if (containsPointerType(State->getCanonicalType())) {
          auto const &Array = *llvm::cast<seec::cm::ValueOfArray>(State.get());
          unsigned const ChildCount = Array.getChildCount();

          for (unsigned i = 0; i < ChildCount; ++i)
            expand(EI, Array.getChildAt(i));
        }
      }
      break;

    case seec::cm::Value::Kind::Record:
      {
        auto const &Record = *llvm::cast<seec::cm::ValueOfRecord>(State.get());
        unsigned const ChildCount = Record.getChildCount();

        for (unsigned i = 0; i < ChildCount; ++i)
          expand(EI, Record.getChildAt(i));
      }
      break;

    case seec::cm::Value::Kind::Pointer:
      {
        auto const Ptr =
          std::static_pointer_cast<seec::cm::ValueOfPointer const>(State);

        if (!EI.addPointer(Ptr)) // Pointer has already been expanded.
          break;

        // If the pointee contains a pointer type, then expand all possible
        // dereferences so that we generate a complete graph. Otherwise, only
        // expand the direct dereference.

        unsigned Limit = Ptr->getDereferenceIndexLimit();

        if (Limit > 1) {
          auto const CanonTy = Ptr->getCanonicalType();
          auto const PtrTy = llvm::cast<clang::PointerType>(CanonTy);
          auto const PointeeTy = PtrTy->getPointeeType().getTypePtrOrNull();
          if (!containsPointerType(PointeeTy))
            Limit = 1;
        }

        for (unsigned i = 0; i < Limit; ++i) {
          auto const Pointee = Ptr->getDereferenced(i);
          EI.addReference(*Pointee, Dereference{Ptr, i});
          expand(EI, Pointee);
        }
      }
      break;
  }
}

void expand(ExpansionImpl &EI, seec::cm::LocalState const &State)
{
  expand(EI, State.getValue());
}

void expand(ExpansionImpl &EI, seec::cm::ParamState const &State)
{
  expand(EI, State.getValue());
}

void expand(ExpansionImpl &EI, seec::cm::FunctionState const &State)
{
  for (auto const &Parameter : State.getParameters())
    expand(EI, Parameter);

  for (auto const &Local : State.getLocals())
    expand(EI, Local);

  if (auto const ActiveStmt = State.getActiveStmt())
    if (auto const Value = State.getStmtValue(ActiveStmt))
      expand(EI, Value);
}

void expand(ExpansionImpl &EI, seec::cm::ThreadState const &State)
{
  for (auto const &FunctionState : State.getCallStack())
    expand(EI, FunctionState);
}

void expand(ExpansionImpl &EI, seec::cm::GlobalVariable const &State)
{
  expand(EI, State.getValue());
}

void expand(ExpansionImpl &EI, seec::cm::ProcessState const &State)
{
  for (std::size_t i = 0; i < State.getThreadCount(); ++i)
    expand(EI, State.getThread(i));

  for (auto const &Global : State.getGlobalVariables())
    expand(EI, *Global);
}

//===----------------------------------------------------------------------===//
// Expansion
//===----------------------------------------------------------------------===//

Expansion::Expansion()
: Impl()
{}

Expansion::~Expansion() = default;

Expansion Expansion::from(seec::cm::ProcessState const &State)
{
  std::unique_ptr<ExpansionImpl> EI {new ExpansionImpl()};

  expand(*EI, State);

  Expansion E;

  E.Impl = std::move(EI);

  return E;
}

bool
Expansion::isReferencedDirectly(Value const &Value) const
{
  for (auto const &Deref : Impl->getReferencesOf(Value))
    if (Deref.getIndex() == 0)
      return true;
  return false;
}

std::vector<std::shared_ptr<ValueOfPointer const>>
Expansion::getReferencesOfArea(uintptr_t Start, uintptr_t End) const
{
  return Impl->getReferencesOfArea(Start, End);
}

bool Expansion::isAreaReferenced(uintptr_t Start, uintptr_t End) const
{
  return Impl->isAreaReferenced(Start, End);
}

std::vector<std::shared_ptr<ValueOfPointer const>>
Expansion::getAllPointers() const
{
  return Impl->getAllPointers();
}

//===----------------------------------------------------------------------===//
// reduceReferences()
//===----------------------------------------------------------------------===//

static
bool
isChildOfAnyDereference(std::shared_ptr<Value const> const &Child,
                        std::shared_ptr<ValueOfPointer const> const &Ptr)
{
  auto const Limit = Ptr->getDereferenceIndexLimit();

  for (unsigned i = 0; i < Limit; ++i) {
    auto const Pointee = Ptr->getDereferenced(i);
    if (isContainedChild(*Child, *Pointee))
      return true;
  }

  return false;
}

void reduceReferences(std::vector<std::shared_ptr<ValueOfPointer const>> &Refs)
{
  typedef std::shared_ptr<ValueOfPointer const> ValOfPtr;

  // Move all the void pointers to the end of the list. If we have nothing but
  // void pointers then return, otherwise remove all of them.
  auto const VoidIt =
    std::partition(Refs.begin(), Refs.end(),
                  [] (ValOfPtr const &Ptr) -> bool {
                    auto const CanTy = Ptr->getCanonicalType();
                    auto const PtrTy = llvm::cast<clang::PointerType>(CanTy);
                    return !PtrTy->getPointeeType()->isVoidType();
                  });

  if (VoidIt == Refs.begin())
    return;

  Refs.erase(VoidIt, Refs.end());
  if (Refs.size() == 1)
    return;

  // Remove all pointers to incomplete types to the end of the list. If we have
  // nothing but pointers to incomplete types, then return.
  auto const IncompleteIt =
    std::partition(Refs.begin(), Refs.end(),
                    [] (ValOfPtr const &Ptr) -> bool {
                      auto const CanTy = Ptr->getCanonicalType();
                      auto const PtrTy = llvm::cast<clang::PointerType>(CanTy);
                      return !PtrTy->getPointeeType()->isIncompleteType();
                    });

  if (IncompleteIt == Refs.begin())
    return;

  Refs.erase(IncompleteIt, Refs.end());
  if (Refs.size() == 1)
    return;

  // Remove all references which refer to a child of another reference. E.g. if
  // we have a pointer to a struct, and a pointer to a member of that struct,
  // then we should remove the member pointer (if the struct is selected for
  // layout then the pointer will be rendered correctly, otherwise it will be
  // rendered as punned).
  //
  // Also remove references which refer either to the same value as another
  // reference. If one of these references has a lower raw value then it should
  // be kept, as it will have more dereferences (and thus a more complete
  // layout will be produced using it).
  auto const CurrentRefs = Refs;
  auto const RemovedIt =
    std::remove_if(Refs.begin(), Refs.end(),
      [&] (ValOfPtr const &Ptr) -> bool
      {
        auto const Pointee = Ptr->getDereferenced(0);
        return std::any_of(CurrentRefs.begin(), CurrentRefs.end(),
                  [&] (ValOfPtr const &Other) -> bool {
                    if (Ptr == Other)
                      return false;

                    // Check if we directly reference another pointer's
                    // dereference. If so, don't bother checking children, as
                    // either us or the other pointer will be removed anyway.
                    auto const Direct = doReferenceSameValue(*Ptr, *Other);
                    if (Direct)
                      return Ptr->getRawValue() >= Other->getRawValue();

                    // Check if this pointer directly references a child.
                    return isChildOfAnyDereference(Pointee, Other);
                  });
      });

  Refs.erase(RemovedIt, Refs.end());
}

} // namespace graph (in cm in seec)

} // namespace cm (in seec)

} // namespace seec
<commit_msg>Simply ignore null Values on LocalState and ParamState objects.<commit_after>//===- lib/Clang/GraphExpansion.cpp ---------------------------------------===//
//
//                                    SeeC
//
// This file is distributed under The MIT License (MIT). See LICENSE.TXT for
// details.
//
//===----------------------------------------------------------------------===//
///
/// \file
///
//===----------------------------------------------------------------------===//

#include "seec/Clang/GraphExpansion.hpp"
#include "seec/Clang/MappedMallocState.hpp"
#include "seec/Clang/MappedFunctionState.hpp"
#include "seec/Clang/MappedGlobalVariable.hpp"
#include "seec/Clang/MappedProcessState.hpp"
#include "seec/Clang/MappedProcessTrace.hpp"
#include "seec/Clang/MappedThreadState.hpp"
#include "seec/Clang/MappedValue.hpp"
#include "seec/Trace/ProcessState.hpp"
#include "seec/Util/Fallthrough.hpp"
#include "seec/Util/Range.hpp"

#include <map>

namespace seec {

namespace cm {

namespace graph {

//===----------------------------------------------------------------------===//
// ExpansionImpl
//===----------------------------------------------------------------------===//

class ExpansionImpl final {
  /// Map from Value to pointer dereferences that reference that Value.
  ///
  std::multimap<Value const *, Dereference> Edges;

  /// Map from address to pointers that reference that address.
  ///
  std::multimap<uintptr_t, std::shared_ptr<ValueOfPointer const>> Pointers;

public:
  ExpansionImpl()
  : Edges(),
    Pointers()
  {}

  void addReference(Value const &ToValue, Dereference FromPointer)
  {
    Edges.insert(std::make_pair(&ToValue, std::move(FromPointer)));
  }

  /// \brief Add the given pointer if it doesn't already exist.
  ///
  /// \return true iff the Pointer didn't already exist and was added.
  ///
  bool addPointer(std::shared_ptr<ValueOfPointer const> const &Pointer)
  {
    auto const Address = Pointer->getRawValue();

    for (auto const &Pair : range(Pointers.equal_range(Address)))
      if (Pair.second == Pointer)
        return false;

    Pointers.insert(std::make_pair(Address, Pointer));

    return true;
  }

  std::vector<Dereference>
  getReferencesOf(Value const &Val) const;

  std::vector<std::shared_ptr<ValueOfPointer const>>
  getReferencesOfArea(uintptr_t Start, uintptr_t End) const;

  bool isAreaReferenced(uintptr_t Start, uintptr_t End) const;

  std::vector<std::shared_ptr<ValueOfPointer const>>
  getAllPointers() const {
    std::vector<std::shared_ptr<ValueOfPointer const>> Ret;

    for (auto const &Pair : Pointers)
      Ret.emplace_back(Pair.second);

    return Ret;
  }
};

std::vector<Dereference>
ExpansionImpl::getReferencesOf(Value const &Val) const
{
  std::vector<Dereference> Ret;

  for (auto const &Pair : seec::range(Edges.equal_range(&Val)))
    Ret.emplace_back(Pair.second);

  return Ret;
}

std::vector<std::shared_ptr<ValueOfPointer const>>
ExpansionImpl::getReferencesOfArea(uintptr_t Start, uintptr_t End) const
{
  auto const Range = seec::range(Pointers.lower_bound(Start),
                                 Pointers.lower_bound(End));

  std::vector<std::shared_ptr<ValueOfPointer const>> Ret;

  for (auto const &Pair : Range)
    Ret.emplace_back(Pair.second);

  return Ret;
}

bool ExpansionImpl::isAreaReferenced(uintptr_t Start, uintptr_t End) const
{
  return Pointers.lower_bound(Start) != Pointers.lower_bound(End);
}

//===----------------------------------------------------------------------===//
// expand
//===----------------------------------------------------------------------===//

static bool containsPointerType(clang::Type const *CanonTy)
{
  if (!CanonTy)
    return false;

  if (CanonTy->isAnyPointerType())
    return true;

  if (auto const ArrayTy = llvm::dyn_cast<clang::ArrayType>(CanonTy)) {
    auto const ElemTy = ArrayTy->getElementType().getCanonicalType();
    return containsPointerType(ElemTy.getTypePtrOrNull());
  }
  else if (auto const RecordTy = llvm::dyn_cast<clang::RecordType>(CanonTy)) {
    auto const Decl = RecordTy->getDecl();

    for (auto Field : seec::range(Decl->field_begin(), Decl->field_end())) {
      auto const FieldTy = Field->getType().getCanonicalType();
      if (containsPointerType(FieldTy.getTypePtrOrNull()))
        return true;
    }

    return false;
  }

  return false;
}

void expand(ExpansionImpl &EI, std::shared_ptr<Value const> const &State)
{
  assert(State);

  switch (State->getKind()) {
    case seec::cm::Value::Kind::Basic: SEEC_FALLTHROUGH;
    case seec::cm::Value::Kind::Scalar:
      break;

    case seec::cm::Value::Kind::Array:
      {
        if (containsPointerType(State->getCanonicalType())) {
          auto const &Array = *llvm::cast<seec::cm::ValueOfArray>(State.get());
          unsigned const ChildCount = Array.getChildCount();

          for (unsigned i = 0; i < ChildCount; ++i)
            expand(EI, Array.getChildAt(i));
        }
      }
      break;

    case seec::cm::Value::Kind::Record:
      {
        auto const &Record = *llvm::cast<seec::cm::ValueOfRecord>(State.get());
        unsigned const ChildCount = Record.getChildCount();

        for (unsigned i = 0; i < ChildCount; ++i)
          expand(EI, Record.getChildAt(i));
      }
      break;

    case seec::cm::Value::Kind::Pointer:
      {
        auto const Ptr =
          std::static_pointer_cast<seec::cm::ValueOfPointer const>(State);

        if (!EI.addPointer(Ptr)) // Pointer has already been expanded.
          break;

        // If the pointee contains a pointer type, then expand all possible
        // dereferences so that we generate a complete graph. Otherwise, only
        // expand the direct dereference.

        unsigned Limit = Ptr->getDereferenceIndexLimit();

        if (Limit > 1) {
          auto const CanonTy = Ptr->getCanonicalType();
          auto const PtrTy = llvm::cast<clang::PointerType>(CanonTy);
          auto const PointeeTy = PtrTy->getPointeeType().getTypePtrOrNull();
          if (!containsPointerType(PointeeTy))
            Limit = 1;
        }

        for (unsigned i = 0; i < Limit; ++i) {
          auto const Pointee = Ptr->getDereferenced(i);
          EI.addReference(*Pointee, Dereference{Ptr, i});
          expand(EI, Pointee);
        }
      }
      break;
  }
}

void expand(ExpansionImpl &EI, seec::cm::LocalState const &State)
{
  auto const Value = State.getValue();
  if (Value)
    expand(EI, Value);
}

void expand(ExpansionImpl &EI, seec::cm::ParamState const &State)
{
  auto const Value = State.getValue();
  if (Value)
    expand(EI, Value);
}

void expand(ExpansionImpl &EI, seec::cm::FunctionState const &State)
{
  for (auto const &Parameter : State.getParameters())
    expand(EI, Parameter);

  for (auto const &Local : State.getLocals())
    expand(EI, Local);

  if (auto const ActiveStmt = State.getActiveStmt())
    if (auto const Value = State.getStmtValue(ActiveStmt))
      expand(EI, Value);
}

void expand(ExpansionImpl &EI, seec::cm::ThreadState const &State)
{
  for (auto const &FunctionState : State.getCallStack())
    expand(EI, FunctionState);
}

void expand(ExpansionImpl &EI, seec::cm::GlobalVariable const &State)
{
  expand(EI, State.getValue());
}

void expand(ExpansionImpl &EI, seec::cm::ProcessState const &State)
{
  for (std::size_t i = 0; i < State.getThreadCount(); ++i)
    expand(EI, State.getThread(i));

  for (auto const &Global : State.getGlobalVariables())
    expand(EI, *Global);
}

//===----------------------------------------------------------------------===//
// Expansion
//===----------------------------------------------------------------------===//

Expansion::Expansion()
: Impl()
{}

Expansion::~Expansion() = default;

Expansion Expansion::from(seec::cm::ProcessState const &State)
{
  std::unique_ptr<ExpansionImpl> EI {new ExpansionImpl()};

  expand(*EI, State);

  Expansion E;

  E.Impl = std::move(EI);

  return E;
}

bool
Expansion::isReferencedDirectly(Value const &Value) const
{
  for (auto const &Deref : Impl->getReferencesOf(Value))
    if (Deref.getIndex() == 0)
      return true;
  return false;
}

std::vector<std::shared_ptr<ValueOfPointer const>>
Expansion::getReferencesOfArea(uintptr_t Start, uintptr_t End) const
{
  return Impl->getReferencesOfArea(Start, End);
}

bool Expansion::isAreaReferenced(uintptr_t Start, uintptr_t End) const
{
  return Impl->isAreaReferenced(Start, End);
}

std::vector<std::shared_ptr<ValueOfPointer const>>
Expansion::getAllPointers() const
{
  return Impl->getAllPointers();
}

//===----------------------------------------------------------------------===//
// reduceReferences()
//===----------------------------------------------------------------------===//

static
bool
isChildOfAnyDereference(std::shared_ptr<Value const> const &Child,
                        std::shared_ptr<ValueOfPointer const> const &Ptr)
{
  auto const Limit = Ptr->getDereferenceIndexLimit();

  for (unsigned i = 0; i < Limit; ++i) {
    auto const Pointee = Ptr->getDereferenced(i);
    if (isContainedChild(*Child, *Pointee))
      return true;
  }

  return false;
}

void reduceReferences(std::vector<std::shared_ptr<ValueOfPointer const>> &Refs)
{
  typedef std::shared_ptr<ValueOfPointer const> ValOfPtr;

  // Move all the void pointers to the end of the list. If we have nothing but
  // void pointers then return, otherwise remove all of them.
  auto const VoidIt =
    std::partition(Refs.begin(), Refs.end(),
                  [] (ValOfPtr const &Ptr) -> bool {
                    auto const CanTy = Ptr->getCanonicalType();
                    auto const PtrTy = llvm::cast<clang::PointerType>(CanTy);
                    return !PtrTy->getPointeeType()->isVoidType();
                  });

  if (VoidIt == Refs.begin())
    return;

  Refs.erase(VoidIt, Refs.end());
  if (Refs.size() == 1)
    return;

  // Remove all pointers to incomplete types to the end of the list. If we have
  // nothing but pointers to incomplete types, then return.
  auto const IncompleteIt =
    std::partition(Refs.begin(), Refs.end(),
                    [] (ValOfPtr const &Ptr) -> bool {
                      auto const CanTy = Ptr->getCanonicalType();
                      auto const PtrTy = llvm::cast<clang::PointerType>(CanTy);
                      return !PtrTy->getPointeeType()->isIncompleteType();
                    });

  if (IncompleteIt == Refs.begin())
    return;

  Refs.erase(IncompleteIt, Refs.end());
  if (Refs.size() == 1)
    return;

  // Remove all references which refer to a child of another reference. E.g. if
  // we have a pointer to a struct, and a pointer to a member of that struct,
  // then we should remove the member pointer (if the struct is selected for
  // layout then the pointer will be rendered correctly, otherwise it will be
  // rendered as punned).
  //
  // Also remove references which refer either to the same value as another
  // reference. If one of these references has a lower raw value then it should
  // be kept, as it will have more dereferences (and thus a more complete
  // layout will be produced using it).
  auto const CurrentRefs = Refs;
  auto const RemovedIt =
    std::remove_if(Refs.begin(), Refs.end(),
      [&] (ValOfPtr const &Ptr) -> bool
      {
        auto const Pointee = Ptr->getDereferenced(0);
        return std::any_of(CurrentRefs.begin(), CurrentRefs.end(),
                  [&] (ValOfPtr const &Other) -> bool {
                    if (Ptr == Other)
                      return false;

                    // Check if we directly reference another pointer's
                    // dereference. If so, don't bother checking children, as
                    // either us or the other pointer will be removed anyway.
                    auto const Direct = doReferenceSameValue(*Ptr, *Other);
                    if (Direct)
                      return Ptr->getRawValue() >= Other->getRawValue();

                    // Check if this pointer directly references a child.
                    return isChildOfAnyDereference(Pointee, Other);
                  });
      });

  Refs.erase(RemovedIt, Refs.end());
}

} // namespace graph (in cm in seec)

} // namespace cm (in seec)

} // namespace seec
<|endoftext|>


<commit_before>//===-- MachineInstr.cpp --------------------------------------------------===//
//
//===----------------------------------------------------------------------===//

#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/Value.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/MachineInstrInfo.h"
#include "llvm/Target/MRegisterInfo.h"
using std::cerr;

// Global variable holding an array of descriptors for machine instructions.
// The actual object needs to be created separately for each target machine.
// This variable is initialized and reset by class MachineInstrInfo.
//
// FIXME: This should be a property of the target so that more than one target
// at a time can be active...
//
extern const MachineInstrDescriptor *TargetInstrDescriptors;

// Constructor for instructions with fixed #operands (nearly all)
MachineInstr::MachineInstr(MachineOpCode _opCode)
  : opCode(_opCode),
    operands(TargetInstrDescriptors[_opCode].numOperands, MachineOperand()),
    numImplicitRefs(0)
{
  assert(TargetInstrDescriptors[_opCode].numOperands >= 0);
}

// Constructor for instructions with variable #operands
MachineInstr::MachineInstr(MachineOpCode OpCode, unsigned  numOperands)
  : opCode(OpCode),
    operands(numOperands, MachineOperand()),
    numImplicitRefs(0)
{
}

/// MachineInstr ctor - This constructor only does a _reserve_ of the operands,
/// not a resize for them.  It is expected that if you use this that you call
/// add* methods below to fill up the operands, instead of the Set methods.
/// Eventually, the "resizing" ctors will be phased out.
///
MachineInstr::MachineInstr(MachineOpCode Opcode, unsigned numOperands,
                           bool XX, bool YY)
  : opCode(Opcode),
    numImplicitRefs(0)
{
  operands.reserve(numOperands);
}

/// MachineInstr ctor - Work exactly the same as the ctor above, except that the
/// MachineInstr is created and added to the end of the specified basic block.
///
MachineInstr::MachineInstr(MachineBasicBlock *MBB, MachineOpCode Opcode,
                           unsigned numOperands)
  : opCode(Opcode),
    numImplicitRefs(0)
{
  assert(MBB && "Cannot use inserting ctor with null basic block!");
  operands.reserve(numOperands);
  MBB->push_back(this);  // Add instruction to end of basic block!
}

// OperandComplete - Return true if it's illegal to add a new operand
bool MachineInstr::OperandsComplete() const
{
  int NumOperands = TargetInstrDescriptors[opCode].numOperands;
  if (NumOperands >= 0 && getNumOperands() >= (unsigned)NumOperands)
    return true;  // Broken!
  return false;
}

//
// Support for replacing opcode and operands of a MachineInstr in place.
// This only resets the size of the operand vector and initializes it.
// The new operands must be set explicitly later.
//
void MachineInstr::replace(MachineOpCode Opcode, unsigned numOperands)
{
  assert(getNumImplicitRefs() == 0 &&
         "This is probably broken because implicit refs are going to be lost.");
  opCode = Opcode;
  operands.clear();
  operands.resize(numOperands, MachineOperand());
}

void
MachineInstr::SetMachineOperandVal(unsigned i,
                                   MachineOperand::MachineOperandType opType,
                                   Value* V,
                                   bool isdef,
                                   bool isDefAndUse)
{
  assert(i < operands.size());          // may be explicit or implicit op
  operands[i].opType = opType;
  operands[i].value = V;
  operands[i].regNum = -1;

  if (isDefAndUse)
    operands[i].flags = MachineOperand::DEFUSEFLAG;
  else if (isdef || TargetInstrDescriptors[opCode].resultPos == (int) i)
    operands[i].flags = MachineOperand::DEFFLAG;
  else
    operands[i].flags = 0;
}

void
MachineInstr::SetMachineOperandConst(unsigned i,
				MachineOperand::MachineOperandType operandType,
                                     int64_t intValue)
{
  assert(i < getNumOperands());          // must be explicit op
  assert(TargetInstrDescriptors[opCode].resultPos != (int) i &&
         "immed. constant cannot be defined");

  operands[i].opType = operandType;
  operands[i].value = NULL;
  operands[i].immedVal = intValue;
  operands[i].regNum = -1;
  operands[i].flags = 0;
}

void
MachineInstr::SetMachineOperandReg(unsigned i,
                                   int regNum,
                                   bool isdef) {
  assert(i < getNumOperands());          // must be explicit op

  operands[i].opType = MachineOperand::MO_MachineRegister;
  operands[i].value = NULL;
  operands[i].regNum = regNum;

  if (isdef || TargetInstrDescriptors[opCode].resultPos == (int) i)
    operands[i].flags = MachineOperand::DEFFLAG;
  else
    operands[i].flags = 0;

  insertUsedReg(regNum);
}

void
MachineInstr::SetRegForOperand(unsigned i, int regNum)
{
  assert(i < getNumOperands());          // must be explicit op
  operands[i].setRegForValue(regNum);
  insertUsedReg(regNum);
}

// Subsitute all occurrences of Value* oldVal with newVal in all operands
// and all implicit refs.  If defsOnly == true, substitute defs only.
unsigned
MachineInstr::substituteValue(const Value* oldVal, Value* newVal, bool defsOnly)
{
  unsigned numSubst = 0;

  // Subsitute operands
  for (MachineInstr::val_op_iterator O = begin(), E = end(); O != E; ++O)
    if (*O == oldVal)
      if (!defsOnly || O.isDef())
        {
          O.getMachineOperand().value = newVal;
          ++numSubst;
        }

  // Subsitute implicit refs
  for (unsigned i=0, N=getNumImplicitRefs(); i < N; ++i)
    if (getImplicitRef(i) == oldVal)
      if (!defsOnly || implicitRefIsDefined(i))
        {
          getImplicitOp(i).value = newVal;
          ++numSubst;
        }

  return numSubst;
}

void
MachineInstr::dump() const
{
  cerr << "  " << *this;
}

static inline std::ostream&
OutputValue(std::ostream &os, const Value* val)
{
  os << "(val ";
  if (val && val->hasName())
    return os << val->getName() << ")";
  else
    return os << (void*) val << ")";              // print address only
}

static inline void OutputReg(std::ostream &os, unsigned RegNo,
                             const MRegisterInfo *MRI = 0) {
  if (MRI) {
    if (RegNo < MRegisterInfo::FirstVirtualRegister)
      os << "%" << MRI->get(RegNo).Name;
    else
      os << "%reg" << RegNo;
  } else
    os << "%mreg(" << RegNo << ")";
}

static void print(const MachineOperand &MO, std::ostream &OS,
                  const TargetMachine &TM) {
  const MRegisterInfo *MRI = TM.getRegisterInfo();
  bool CloseParen = true;
  if (MO.opHiBits32())
    OS << "%lm(";
  else if (MO.opLoBits32())
    OS << "%lo(";
  else if (MO.opHiBits64())
    OS << "%hh(";
  else if (MO.opLoBits64())
    OS << "%hm(";
  else
    CloseParen = false;

  switch (MO.getType()) {
  case MachineOperand::MO_VirtualRegister:
    if (MO.getVRegValue()) {
      OS << "%reg";
      OutputValue(OS, MO.getVRegValue());
      if (MO.hasAllocatedReg())
        OS << "==";
    }
    if (MO.hasAllocatedReg())
      OutputReg(OS, MO.getAllocatedRegNum(), MRI);
    break;
  case MachineOperand::MO_CCRegister:
    OS << "%ccreg";
    OutputValue(OS, MO.getVRegValue());
    if (MO.hasAllocatedReg()) {
      OS << "==";
      OutputReg(OS, MO.getAllocatedRegNum(), MRI);
    }
    break;
  case MachineOperand::MO_MachineRegister:
    OutputReg(OS, MO.getMachineRegNum(), MRI);
    break;
  case MachineOperand::MO_SignExtendedImmed:
    OS << (long)MO.getImmedValue();
    break;
  case MachineOperand::MO_UnextendedImmed:
    OS << (long)MO.getImmedValue();
    break;
  case MachineOperand::MO_PCRelativeDisp: {
    const Value* opVal = MO.getVRegValue();
    bool isLabel = isa<Function>(opVal) || isa<BasicBlock>(opVal);
    OS << "%disp(" << (isLabel? "label " : "addr-of-val ");
    if (opVal->hasName())
      OS << opVal->getName();
    else
      OS << (const void*) opVal;
    OS << ")";
    break;
  }
  case MachineOperand::MO_MachineBasicBlock:
    OS << "bb<"
       << ((Value*)MO.getMachineBasicBlock()->getBasicBlock())->getName()
       << "," << (void*)MO.getMachineBasicBlock()->getBasicBlock() << ">";
    break;
  case MachineOperand::MO_FrameIndex:
    OS << "<fi#" << MO.getFrameIndex() << ">";
    break;
  default:
    assert(0 && "Unrecognized operand type");
  }

  if (CloseParen)
    OS << ")";
}

void MachineInstr::print(std::ostream &OS, const TargetMachine &TM) const {
  unsigned StartOp = 0;

   // Specialize printing if op#0 is definition
  if (getNumOperands() && operandIsDefined(0)) {
    ::print(getOperand(0), OS, TM);
    OS << " = ";
    ++StartOp;   // Don't print this operand again!
  }
  OS << TM.getInstrInfo().getName(getOpcode());

  for (unsigned i = StartOp, e = getNumOperands(); i != e; ++i) {
    if (i != StartOp)
      OS << ",";
    OS << " ";
    ::print(getOperand(i), OS, TM);

    if (operandIsDefinedAndUsed(i))
      OS << "<def&use>";
    else if (operandIsDefined(i))
      OS << "<def>";
  }

  // code for printing implict references
  if (getNumImplicitRefs()) {
    OS << "\tImplicitRefs: ";
    for(unsigned i = 0, e = getNumImplicitRefs(); i != e; ++i) {
      OS << "\t";
      OutputValue(OS, getImplicitRef(i));
      if (implicitRefIsDefinedAndUsed(i))
        OS << "<def&use>";
      else if (implicitRefIsDefined(i))
        OS << "<def>";
    }
  }

  OS << "\n";
}

std::ostream &operator<<(std::ostream& os, const MachineInstr& minstr)
{
  os << TargetInstrDescriptors[minstr.opCode].Name;

  for (unsigned i=0, N=minstr.getNumOperands(); i < N; i++) {
    os << "\t" << minstr.getOperand(i);
    if( minstr.operandIsDefined(i) )
      os << "*";
    if( minstr.operandIsDefinedAndUsed(i) )
      os << "*";
  }

  // code for printing implict references
  unsigned NumOfImpRefs =  minstr.getNumImplicitRefs();
  if(  NumOfImpRefs > 0 ) {
    os << "\tImplicit: ";
    for(unsigned z=0; z < NumOfImpRefs; z++) {
      OutputValue(os, minstr.getImplicitRef(z));
      if( minstr.implicitRefIsDefined(z)) os << "*";
      if( minstr.implicitRefIsDefinedAndUsed(z)) os << "*";
      os << "\t";
    }
  }

  return os << "\n";
}

std::ostream &operator<<(std::ostream &OS, const MachineOperand &MO)
{
  if (MO.opHiBits32())
    OS << "%lm(";
  else if (MO.opLoBits32())
    OS << "%lo(";
  else if (MO.opHiBits64())
    OS << "%hh(";
  else if (MO.opLoBits64())
    OS << "%hm(";

  switch (MO.getType())
    {
    case MachineOperand::MO_VirtualRegister:
      OS << "%reg";
      OutputValue(OS, MO.getVRegValue());
      if (MO.hasAllocatedReg()) {
        OS << "==";
        OutputReg(OS, MO.getAllocatedRegNum());
      }
      break;
    case MachineOperand::MO_CCRegister:
      OS << "%ccreg";
      OutputValue(OS, MO.getVRegValue());
      if (MO.hasAllocatedReg()) {
        OS << "==";
        OutputReg(OS, MO.getAllocatedRegNum());
      }
      break;
    case MachineOperand::MO_MachineRegister:
      OutputReg(OS, MO.getMachineRegNum());
      break;
    case MachineOperand::MO_SignExtendedImmed:
      OS << (long)MO.getImmedValue();
      break;
    case MachineOperand::MO_UnextendedImmed:
      OS << (long)MO.getImmedValue();
      break;
    case MachineOperand::MO_PCRelativeDisp:
      {
        const Value* opVal = MO.getVRegValue();
        bool isLabel = isa<Function>(opVal) || isa<BasicBlock>(opVal);
        OS << "%disp(" << (isLabel? "label " : "addr-of-val ");
        if (opVal->hasName())
          OS << opVal->getName();
        else
          OS << (const void*) opVal;
        OS << ")";
        break;
      }
    case MachineOperand::MO_MachineBasicBlock:
      OS << "bb<"
         << ((Value*)MO.getMachineBasicBlock()->getBasicBlock())->getName()
         << "," << (void*)MO.getMachineBasicBlock()->getBasicBlock() << ">";
      break;
    case MachineOperand::MO_FrameIndex:
      OS << "<fi#" << MO.getFrameIndex() << ">";
      break;
    default:
      assert(0 && "Unrecognized operand type");
      break;
    }

  if (MO.flags &
      (MachineOperand::HIFLAG32 | MachineOperand::LOFLAG32 |
       MachineOperand::HIFLAG64 | MachineOperand::LOFLAG64))
    OS << ")";

  return OS;
}
<commit_msg>Add support for 3 new forms of MachineOperand<commit_after>//===-- MachineInstr.cpp --------------------------------------------------===//
//
//===----------------------------------------------------------------------===//

#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/Value.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/MachineInstrInfo.h"
#include "llvm/Target/MRegisterInfo.h"
using std::cerr;

// Global variable holding an array of descriptors for machine instructions.
// The actual object needs to be created separately for each target machine.
// This variable is initialized and reset by class MachineInstrInfo.
//
// FIXME: This should be a property of the target so that more than one target
// at a time can be active...
//
extern const MachineInstrDescriptor *TargetInstrDescriptors;

// Constructor for instructions with fixed #operands (nearly all)
MachineInstr::MachineInstr(MachineOpCode _opCode)
  : opCode(_opCode),
    operands(TargetInstrDescriptors[_opCode].numOperands, MachineOperand()),
    numImplicitRefs(0)
{
  assert(TargetInstrDescriptors[_opCode].numOperands >= 0);
}

// Constructor for instructions with variable #operands
MachineInstr::MachineInstr(MachineOpCode OpCode, unsigned  numOperands)
  : opCode(OpCode),
    operands(numOperands, MachineOperand()),
    numImplicitRefs(0)
{
}

/// MachineInstr ctor - This constructor only does a _reserve_ of the operands,
/// not a resize for them.  It is expected that if you use this that you call
/// add* methods below to fill up the operands, instead of the Set methods.
/// Eventually, the "resizing" ctors will be phased out.
///
MachineInstr::MachineInstr(MachineOpCode Opcode, unsigned numOperands,
                           bool XX, bool YY)
  : opCode(Opcode),
    numImplicitRefs(0)
{
  operands.reserve(numOperands);
}

/// MachineInstr ctor - Work exactly the same as the ctor above, except that the
/// MachineInstr is created and added to the end of the specified basic block.
///
MachineInstr::MachineInstr(MachineBasicBlock *MBB, MachineOpCode Opcode,
                           unsigned numOperands)
  : opCode(Opcode),
    numImplicitRefs(0)
{
  assert(MBB && "Cannot use inserting ctor with null basic block!");
  operands.reserve(numOperands);
  MBB->push_back(this);  // Add instruction to end of basic block!
}

// OperandComplete - Return true if it's illegal to add a new operand
bool MachineInstr::OperandsComplete() const
{
  int NumOperands = TargetInstrDescriptors[opCode].numOperands;
  if (NumOperands >= 0 && getNumOperands() >= (unsigned)NumOperands)
    return true;  // Broken!
  return false;
}

//
// Support for replacing opcode and operands of a MachineInstr in place.
// This only resets the size of the operand vector and initializes it.
// The new operands must be set explicitly later.
//
void MachineInstr::replace(MachineOpCode Opcode, unsigned numOperands)
{
  assert(getNumImplicitRefs() == 0 &&
         "This is probably broken because implicit refs are going to be lost.");
  opCode = Opcode;
  operands.clear();
  operands.resize(numOperands, MachineOperand());
}

void
MachineInstr::SetMachineOperandVal(unsigned i,
                                   MachineOperand::MachineOperandType opType,
                                   Value* V,
                                   bool isdef,
                                   bool isDefAndUse)
{
  assert(i < operands.size());          // may be explicit or implicit op
  operands[i].opType = opType;
  operands[i].value = V;
  operands[i].regNum = -1;

  if (isDefAndUse)
    operands[i].flags = MachineOperand::DEFUSEFLAG;
  else if (isdef || TargetInstrDescriptors[opCode].resultPos == (int) i)
    operands[i].flags = MachineOperand::DEFFLAG;
  else
    operands[i].flags = 0;
}

void
MachineInstr::SetMachineOperandConst(unsigned i,
				MachineOperand::MachineOperandType operandType,
                                     int64_t intValue)
{
  assert(i < getNumOperands());          // must be explicit op
  assert(TargetInstrDescriptors[opCode].resultPos != (int) i &&
         "immed. constant cannot be defined");

  operands[i].opType = operandType;
  operands[i].value = NULL;
  operands[i].immedVal = intValue;
  operands[i].regNum = -1;
  operands[i].flags = 0;
}

void
MachineInstr::SetMachineOperandReg(unsigned i,
                                   int regNum,
                                   bool isdef) {
  assert(i < getNumOperands());          // must be explicit op

  operands[i].opType = MachineOperand::MO_MachineRegister;
  operands[i].value = NULL;
  operands[i].regNum = regNum;

  if (isdef || TargetInstrDescriptors[opCode].resultPos == (int) i)
    operands[i].flags = MachineOperand::DEFFLAG;
  else
    operands[i].flags = 0;

  insertUsedReg(regNum);
}

void
MachineInstr::SetRegForOperand(unsigned i, int regNum)
{
  assert(i < getNumOperands());          // must be explicit op
  operands[i].setRegForValue(regNum);
  insertUsedReg(regNum);
}

// Subsitute all occurrences of Value* oldVal with newVal in all operands
// and all implicit refs.  If defsOnly == true, substitute defs only.
unsigned
MachineInstr::substituteValue(const Value* oldVal, Value* newVal, bool defsOnly)
{
  unsigned numSubst = 0;

  // Subsitute operands
  for (MachineInstr::val_op_iterator O = begin(), E = end(); O != E; ++O)
    if (*O == oldVal)
      if (!defsOnly || O.isDef())
        {
          O.getMachineOperand().value = newVal;
          ++numSubst;
        }

  // Subsitute implicit refs
  for (unsigned i=0, N=getNumImplicitRefs(); i < N; ++i)
    if (getImplicitRef(i) == oldVal)
      if (!defsOnly || implicitRefIsDefined(i))
        {
          getImplicitOp(i).value = newVal;
          ++numSubst;
        }

  return numSubst;
}

void
MachineInstr::dump() const
{
  cerr << "  " << *this;
}

static inline std::ostream&
OutputValue(std::ostream &os, const Value* val)
{
  os << "(val ";
  if (val && val->hasName())
    return os << val->getName() << ")";
  else
    return os << (void*) val << ")";              // print address only
}

static inline void OutputReg(std::ostream &os, unsigned RegNo,
                             const MRegisterInfo *MRI = 0) {
  if (MRI) {
    if (RegNo < MRegisterInfo::FirstVirtualRegister)
      os << "%" << MRI->get(RegNo).Name;
    else
      os << "%reg" << RegNo;
  } else
    os << "%mreg(" << RegNo << ")";
}

static void print(const MachineOperand &MO, std::ostream &OS,
                  const TargetMachine &TM) {
  const MRegisterInfo *MRI = TM.getRegisterInfo();
  bool CloseParen = true;
  if (MO.opHiBits32())
    OS << "%lm(";
  else if (MO.opLoBits32())
    OS << "%lo(";
  else if (MO.opHiBits64())
    OS << "%hh(";
  else if (MO.opLoBits64())
    OS << "%hm(";
  else
    CloseParen = false;

  switch (MO.getType()) {
  case MachineOperand::MO_VirtualRegister:
    if (MO.getVRegValue()) {
      OS << "%reg";
      OutputValue(OS, MO.getVRegValue());
      if (MO.hasAllocatedReg())
        OS << "==";
    }
    if (MO.hasAllocatedReg())
      OutputReg(OS, MO.getAllocatedRegNum(), MRI);
    break;
  case MachineOperand::MO_CCRegister:
    OS << "%ccreg";
    OutputValue(OS, MO.getVRegValue());
    if (MO.hasAllocatedReg()) {
      OS << "==";
      OutputReg(OS, MO.getAllocatedRegNum(), MRI);
    }
    break;
  case MachineOperand::MO_MachineRegister:
    OutputReg(OS, MO.getMachineRegNum(), MRI);
    break;
  case MachineOperand::MO_SignExtendedImmed:
    OS << (long)MO.getImmedValue();
    break;
  case MachineOperand::MO_UnextendedImmed:
    OS << (long)MO.getImmedValue();
    break;
  case MachineOperand::MO_PCRelativeDisp: {
    const Value* opVal = MO.getVRegValue();
    bool isLabel = isa<Function>(opVal) || isa<BasicBlock>(opVal);
    OS << "%disp(" << (isLabel? "label " : "addr-of-val ");
    if (opVal->hasName())
      OS << opVal->getName();
    else
      OS << (const void*) opVal;
    OS << ")";
    break;
  }
  case MachineOperand::MO_MachineBasicBlock:
    OS << "bb<"
       << ((Value*)MO.getMachineBasicBlock()->getBasicBlock())->getName()
       << "," << (void*)MO.getMachineBasicBlock()->getBasicBlock() << ">";
    break;
  case MachineOperand::MO_FrameIndex:
    OS << "<fi#" << MO.getFrameIndex() << ">";
    break;
  case MachineOperand::MO_ConstantPoolIndex:
    OS << "<cp#" << MO.getConstantPoolIndex() << ">";
    break;
  case MachineOperand::MO_GlobalAddress:
    OS << "<ga:" << ((Value*)MO.getGlobal())->getName() << ">";
    break;
  case MachineOperand::MO_ExternalSymbol:
    OS << "<es:" << MO.getSymbolName() << ">";
    break;
  default:
    assert(0 && "Unrecognized operand type");
  }

  if (CloseParen)
    OS << ")";
}

void MachineInstr::print(std::ostream &OS, const TargetMachine &TM) const {
  unsigned StartOp = 0;

   // Specialize printing if op#0 is definition
  if (getNumOperands() && operandIsDefined(0)) {
    ::print(getOperand(0), OS, TM);
    OS << " = ";
    ++StartOp;   // Don't print this operand again!
  }
  OS << TM.getInstrInfo().getName(getOpcode());

  for (unsigned i = StartOp, e = getNumOperands(); i != e; ++i) {
    if (i != StartOp)
      OS << ",";
    OS << " ";
    ::print(getOperand(i), OS, TM);

    if (operandIsDefinedAndUsed(i))
      OS << "<def&use>";
    else if (operandIsDefined(i))
      OS << "<def>";
  }

  // code for printing implict references
  if (getNumImplicitRefs()) {
    OS << "\tImplicitRefs: ";
    for(unsigned i = 0, e = getNumImplicitRefs(); i != e; ++i) {
      OS << "\t";
      OutputValue(OS, getImplicitRef(i));
      if (implicitRefIsDefinedAndUsed(i))
        OS << "<def&use>";
      else if (implicitRefIsDefined(i))
        OS << "<def>";
    }
  }

  OS << "\n";
}

std::ostream &operator<<(std::ostream& os, const MachineInstr& MI)
{
  os << TargetInstrDescriptors[MI.opCode].Name;

  for (unsigned i=0, N=MI.getNumOperands(); i < N; i++) {
    os << "\t" << MI.getOperand(i);
    if (MI.operandIsDefined(i))
      os << "<d>";
    if (MI.operandIsDefinedAndUsed(i))
      os << "<d&u>";
  }

  // code for printing implict references
  unsigned NumOfImpRefs = MI.getNumImplicitRefs();
  if (NumOfImpRefs > 0) {
    os << "\tImplicit: ";
    for (unsigned z=0; z < NumOfImpRefs; z++) {
      OutputValue(os, MI.getImplicitRef(z));
      if (MI.implicitRefIsDefined(z)) os << "<d>";
      if (MI.implicitRefIsDefinedAndUsed(z)) os << "<d&u>";
      os << "\t";
    }
  }

  return os << "\n";
}

std::ostream &operator<<(std::ostream &OS, const MachineOperand &MO)
{
  if (MO.opHiBits32())
    OS << "%lm(";
  else if (MO.opLoBits32())
    OS << "%lo(";
  else if (MO.opHiBits64())
    OS << "%hh(";
  else if (MO.opLoBits64())
    OS << "%hm(";

  switch (MO.getType())
    {
    case MachineOperand::MO_VirtualRegister:
      if (MO.hasAllocatedReg())
        OutputReg(OS, MO.getAllocatedRegNum());

      if (MO.getVRegValue()) {
	if (MO.hasAllocatedReg()) OS << "==";
	OS << "%vreg";
	OutputValue(OS, MO.getVRegValue());
      }
      break;
    case MachineOperand::MO_CCRegister:
      OS << "%ccreg";
      OutputValue(OS, MO.getVRegValue());
      if (MO.hasAllocatedReg()) {
        OS << "==";
        OutputReg(OS, MO.getAllocatedRegNum());
      }
      break;
    case MachineOperand::MO_MachineRegister:
      OutputReg(OS, MO.getMachineRegNum());
      break;
    case MachineOperand::MO_SignExtendedImmed:
      OS << (long)MO.getImmedValue();
      break;
    case MachineOperand::MO_UnextendedImmed:
      OS << (long)MO.getImmedValue();
      break;
    case MachineOperand::MO_PCRelativeDisp:
      {
        const Value* opVal = MO.getVRegValue();
        bool isLabel = isa<Function>(opVal) || isa<BasicBlock>(opVal);
        OS << "%disp(" << (isLabel? "label " : "addr-of-val ");
        if (opVal->hasName())
          OS << opVal->getName();
        else
          OS << (const void*) opVal;
        OS << ")";
        break;
      }
    case MachineOperand::MO_MachineBasicBlock:
      OS << "bb<"
         << ((Value*)MO.getMachineBasicBlock()->getBasicBlock())->getName()
         << "," << (void*)MO.getMachineBasicBlock()->getBasicBlock() << ">";
      break;
    case MachineOperand::MO_FrameIndex:
      OS << "<fi#" << MO.getFrameIndex() << ">";
      break;
    case MachineOperand::MO_ConstantPoolIndex:
      OS << "<cp#" << MO.getConstantPoolIndex() << ">";
      break;
    case MachineOperand::MO_GlobalAddress:
      OS << "<ga:" << ((Value*)MO.getGlobal())->getName() << ">";
      break;
    case MachineOperand::MO_ExternalSymbol:
      OS << "<es:" << MO.getSymbolName() << ">";
      break;
    default:
      assert(0 && "Unrecognized operand type");
      break;
    }

  if (MO.flags &
      (MachineOperand::HIFLAG32 | MachineOperand::LOFLAG32 |
       MachineOperand::HIFLAG64 | MachineOperand::LOFLAG64))
    OS << ")";

  return OS;
}
<|endoftext|>


<commit_before>//===-- WinEHPrepare - Prepare exception handling for code generation ---===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This pass lowers LLVM IR exception handling into something closer to what the
// backend wants. It snifs the personality function to see which kind of
// preparation is necessary. If the personality function uses the Itanium LSDA,
// this pass delegates to the DWARF EH preparation pass.
//
//===----------------------------------------------------------------------===//

#include "llvm/CodeGen/Passes.h"
#include "llvm/Analysis/LibCallSemantics.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/Pass.h"
#include "llvm/Target/TargetLowering.h"
using namespace llvm;

#define DEBUG_TYPE "winehprepare"

namespace {
class WinEHPrepare : public FunctionPass {
  const TargetMachine *TM;
  FunctionPass *DwarfPrepare;

public:
  static char ID; // Pass identification, replacement for typeid.
  WinEHPrepare(const TargetMachine *TM = nullptr)
      : FunctionPass(ID), TM(TM), DwarfPrepare(createDwarfEHPass(TM)) {
    initializeDominatorTreeWrapperPassPass(*PassRegistry::getPassRegistry());
  }

  bool runOnFunction(Function &Fn) override;

  bool doFinalization(Module &M) override;

  void getAnalysisUsage(AnalysisUsage &AU) const override;

  const char *getPassName() const override {
    return "Windows exception handling preparation";
  }
};
} // end anonymous namespace

char WinEHPrepare::ID = 0;
INITIALIZE_TM_PASS(WinEHPrepare, "winehprepare",
                   "Prepare Windows exceptions", false, false)

FunctionPass *llvm::createWinEHPass(const TargetMachine *TM) {
  return new WinEHPrepare(TM);
}

static bool isMSVCPersonality(EHPersonality Pers) {
  return Pers == EHPersonality::MSVC_Win64SEH ||
         Pers == EHPersonality::MSVC_CXX;
}

bool WinEHPrepare::runOnFunction(Function &Fn) {
  SmallVector<LandingPadInst *, 4> LPads;
  SmallVector<ResumeInst *, 4> Resumes;
  for (BasicBlock &BB : Fn) {
    if (auto *LP = BB.getLandingPadInst())
      LPads.push_back(LP);
    if (auto *Resume = dyn_cast<ResumeInst>(BB.getTerminator()))
      Resumes.push_back(Resume);
  }

  // No need to prepare functions that lack landing pads.
  if (LPads.empty())
    return false;

  // Classify the personality to see what kind of preparation we need.
  EHPersonality Pers = ClassifyEHPersonality(LPads.back()->getPersonalityFn());

  // Delegate through to the DWARF pass if this is unrecognized.
  if (!isMSVCPersonality(Pers))
    return DwarfPrepare->runOnFunction(Fn);

  // FIXME: Cleanups are unimplemented. Replace them with calls to @llvm.trap.
  if (Resumes.empty())
    return false;

  Function *Trap =
      Intrinsic::getDeclaration(Fn.getParent(), Intrinsic::trap, None);
  for (ResumeInst *Resume : Resumes) {
    IRBuilder<>(Resume).CreateUnreachable();
    Resume->eraseFromParent();
  }

  return true;
}

bool WinEHPrepare::doFinalization(Module &M) {
  return DwarfPrepare->doFinalization(M);
}

void WinEHPrepare::getAnalysisUsage(AnalysisUsage &AU) const {
  DwarfPrepare->getAnalysisUsage(AU);
}
<commit_msg>Remove unused variable<commit_after>//===-- WinEHPrepare - Prepare exception handling for code generation ---===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This pass lowers LLVM IR exception handling into something closer to what the
// backend wants. It snifs the personality function to see which kind of
// preparation is necessary. If the personality function uses the Itanium LSDA,
// this pass delegates to the DWARF EH preparation pass.
//
//===----------------------------------------------------------------------===//

#include "llvm/CodeGen/Passes.h"
#include "llvm/Analysis/LibCallSemantics.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/Pass.h"
#include "llvm/Target/TargetLowering.h"
using namespace llvm;

#define DEBUG_TYPE "winehprepare"

namespace {
class WinEHPrepare : public FunctionPass {
  const TargetMachine *TM;
  FunctionPass *DwarfPrepare;

public:
  static char ID; // Pass identification, replacement for typeid.
  WinEHPrepare(const TargetMachine *TM = nullptr)
      : FunctionPass(ID), TM(TM), DwarfPrepare(createDwarfEHPass(TM)) {
    initializeDominatorTreeWrapperPassPass(*PassRegistry::getPassRegistry());
  }

  bool runOnFunction(Function &Fn) override;

  bool doFinalization(Module &M) override;

  void getAnalysisUsage(AnalysisUsage &AU) const override;

  const char *getPassName() const override {
    return "Windows exception handling preparation";
  }
};
} // end anonymous namespace

char WinEHPrepare::ID = 0;
INITIALIZE_TM_PASS(WinEHPrepare, "winehprepare",
                   "Prepare Windows exceptions", false, false)

FunctionPass *llvm::createWinEHPass(const TargetMachine *TM) {
  return new WinEHPrepare(TM);
}

static bool isMSVCPersonality(EHPersonality Pers) {
  return Pers == EHPersonality::MSVC_Win64SEH ||
         Pers == EHPersonality::MSVC_CXX;
}

bool WinEHPrepare::runOnFunction(Function &Fn) {
  SmallVector<LandingPadInst *, 4> LPads;
  SmallVector<ResumeInst *, 4> Resumes;
  for (BasicBlock &BB : Fn) {
    if (auto *LP = BB.getLandingPadInst())
      LPads.push_back(LP);
    if (auto *Resume = dyn_cast<ResumeInst>(BB.getTerminator()))
      Resumes.push_back(Resume);
  }

  // No need to prepare functions that lack landing pads.
  if (LPads.empty())
    return false;

  // Classify the personality to see what kind of preparation we need.
  EHPersonality Pers = ClassifyEHPersonality(LPads.back()->getPersonalityFn());

  // Delegate through to the DWARF pass if this is unrecognized.
  if (!isMSVCPersonality(Pers))
    return DwarfPrepare->runOnFunction(Fn);

  // FIXME: Cleanups are unimplemented. Replace them with calls to @llvm.trap.
  if (Resumes.empty())
    return false;

  for (ResumeInst *Resume : Resumes) {
    IRBuilder<>(Resume).CreateUnreachable();
    Resume->eraseFromParent();
  }

  return true;
}

bool WinEHPrepare::doFinalization(Module &M) {
  return DwarfPrepare->doFinalization(M);
}

void WinEHPrepare::getAnalysisUsage(AnalysisUsage &AU) const {
  DwarfPrepare->getAnalysisUsage(AU);
}
<|endoftext|>


<commit_before>/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * Written (W) 2010 Soeren Sonnenburg
 * Copyright (C) 2010 Berlin Institute of Technology
 */
#include "features/SparsePolyFeatures.h"
#include "lib/Hash.h"

using namespace shogun;

CSparsePolyFeatures::CSparsePolyFeatures(CSparseFeatures<float64_t>* feat, int32_t degree, bool normalize, int32_t hash_bits)
	: CDotFeatures(), m_normalization_values(NULL)
{
	ASSERT(feat);

	m_feat = feat;
	SG_REF(m_feat);
	m_degree=degree;
	m_normalize=normalize;
	m_hash_bits=hash_bits;
	mask=(uint32_t) (((uint64_t) 1)<<m_hash_bits)-1;
	m_output_dimensions=1<<m_hash_bits;
	m_input_dimensions=feat->get_num_features();

	if (m_normalize)
		store_normalization_values();
}

CSparsePolyFeatures::~CSparsePolyFeatures()
{
	delete[] m_normalization_values;
	SG_UNREF(m_feat);
}

float64_t CSparsePolyFeatures::dot(int32_t vec_idx1, int32_t vec_idx2)
{

	int32_t len1, len2;
	bool do_free1, do_free2;
	TSparseEntry<float64_t>* vec1 = m_feat->get_sparse_feature_vector(vec_idx1, len1, do_free1);
	TSparseEntry<float64_t>* vec2 = m_feat->get_sparse_feature_vector(vec_idx2, len2, do_free2);

	float64_t result=CSparseFeatures<float64_t>::sparse_dot(1, vec1, len1, vec2, len2);
	result=CMath::pow(result, m_degree);

	m_feat->free_feature_vector(vec1, len1, do_free1);
	m_feat->free_feature_vector(vec2, len2, do_free2);

	return result;
}

float64_t CSparsePolyFeatures::dense_dot(int32_t vec_idx1, const float64_t* vec2, int32_t vec2_len)
{
	if (vec2_len != m_output_dimensions)
		SG_ERROR("Dimensions don't match, vec2_dim=%d, m_output_dimensions=%d\n", vec2_len, m_output_dimensions);

	int32_t idx[2];
	int32_t vlen;
	bool do_free;
	TSparseEntry<float64_t>* vec = m_feat->get_sparse_feature_vector(vec_idx1, vlen, do_free);

	float64_t result=0;

	if (vec)
	{
		if (m_degree==2)
		{
			/* (a+b)^2 = a^2 + 2ab +b^2 */
			for (int32_t i=0; i<vlen; i++)
			{
				idx[0]=vec[i].feat_index;
				float64_t v1=vec[i].entry;

				for (int32_t j=i; j<vlen; j++)
				{
					idx[1]=vec[j].feat_index;
					float64_t v2=vec[j].entry;

					uint32_t h=CHash::MurmurHash2((uint8_t*) idx, sizeof(idx), 0xDEADBEAF) & mask;
					float64_t v;

					if (i==j)
						v=v1*v1;
					else
						v=CMath::sqrt(2.0)*v1*v2;

					result+=v*vec2[h];
				}
			}
		}
		else if (m_degree==3)
			SG_NOTIMPLEMENTED;
	}

	if (m_normalize)
		result/=m_normalization_values[vec_idx1];

	m_feat->free_feature_vector(vec, vlen, do_free);
	return result;
}

void CSparsePolyFeatures::add_to_dense_vec(float64_t alpha, int32_t vec_idx1, float64_t* vec2, int32_t vec2_len, bool abs_val)
{
	if (vec2_len != m_output_dimensions)
		SG_ERROR("Dimensions don't match, vec2_dim=%d, m_output_dimensions=%d\n", vec2_len, m_output_dimensions);

	int32_t idx[2];
	int32_t vlen;
	bool do_free;
	TSparseEntry<float64_t>* vec = m_feat->get_sparse_feature_vector(vec_idx1, vlen, do_free);

	float64_t norm_val=1.0;
	if (m_normalize)
		norm_val = m_normalization_values[vec_idx1];
	alpha/=norm_val;

	if (m_degree==2)
	{
		/* (a+b)^2 = a^2 + 2ab +b^2 */
		for (int32_t i=0; i<vlen; i++)
		{
			idx[0]=vec[i].feat_index;
			float64_t v1=vec[i].entry;

			for (int32_t j=i; j<vlen; j++)
			{
				idx[1]=vec[j].feat_index;
				float64_t v2=vec[j].entry;

				uint32_t h=CHash::MurmurHash2((uint8_t*) idx, sizeof(idx), 0xDEADBEAF) & mask;
				float64_t v;

				if (i==j)
					v=alpha*v1*v1;
				else
					v=alpha*CMath::sqrt(2.0)*v1*v2;

				if (abs_val)
					vec2[h]+=CMath::abs(v);
				else
					vec2[h]+=v;
			}
		}
	}
	else if (m_degree==3)
		SG_NOTIMPLEMENTED;

	m_feat->free_feature_vector(vec, vlen, do_free);
}

void CSparsePolyFeatures::store_normalization_values()
{
	delete[] m_normalization_values;

	int32_t num_vec = this->get_num_vectors();

	m_normalization_values=new float64_t[num_vec];
	for (int i=0; i<num_vec; i++)
	{
		float64_t val = CMath::sqrt(dot(i,i));
		if (val==0)
			// trap division by zero
			m_normalization_values[i]=1.0;
		else
			m_normalization_values[i]=val;
	}

}

CFeatures* CSparsePolyFeatures::duplicate() const
{
	return new CSparsePolyFeatures(*this);
}
<commit_msg>compute hash incrementally<commit_after>/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * Written (W) 2010 Soeren Sonnenburg
 * Copyright (C) 2010 Berlin Institute of Technology
 */
#include "features/SparsePolyFeatures.h"
#include "lib/Hash.h"

using namespace shogun;

CSparsePolyFeatures::CSparsePolyFeatures(CSparseFeatures<float64_t>* feat, int32_t degree, bool normalize, int32_t hash_bits)
	: CDotFeatures(), m_normalization_values(NULL)
{
	ASSERT(feat);

	m_feat = feat;
	SG_REF(m_feat);
	m_degree=degree;
	m_normalize=normalize;
	m_hash_bits=hash_bits;
	mask=(uint32_t) (((uint64_t) 1)<<m_hash_bits)-1;
	m_output_dimensions=1<<m_hash_bits;
	m_input_dimensions=feat->get_num_features();

	if (m_normalize)
		store_normalization_values();
}

CSparsePolyFeatures::~CSparsePolyFeatures()
{
	delete[] m_normalization_values;
	SG_UNREF(m_feat);
}

float64_t CSparsePolyFeatures::dot(int32_t vec_idx1, int32_t vec_idx2)
{

	int32_t len1, len2;
	bool do_free1, do_free2;
	TSparseEntry<float64_t>* vec1 = m_feat->get_sparse_feature_vector(vec_idx1, len1, do_free1);
	TSparseEntry<float64_t>* vec2 = m_feat->get_sparse_feature_vector(vec_idx2, len2, do_free2);

	float64_t result=CSparseFeatures<float64_t>::sparse_dot(1, vec1, len1, vec2, len2);
	result=CMath::pow(result, m_degree);

	m_feat->free_feature_vector(vec1, len1, do_free1);
	m_feat->free_feature_vector(vec2, len2, do_free2);

	return result;
}

float64_t CSparsePolyFeatures::dense_dot(int32_t vec_idx1, const float64_t* vec2, int32_t vec2_len)
{
	if (vec2_len != m_output_dimensions)
		SG_ERROR("Dimensions don't match, vec2_dim=%d, m_output_dimensions=%d\n", vec2_len, m_output_dimensions);

	int32_t vlen;
	bool do_free;
	TSparseEntry<float64_t>* vec = m_feat->get_sparse_feature_vector(vec_idx1, vlen, do_free);

	float64_t result=0;

	if (vec)
	{
		if (m_degree==2)
		{
			/* (a+b)^2 = a^2 + 2ab +b^2 */
			for (int32_t i=0; i<vlen; i++)
			{
				float64_t v1=vec[i].entry;
				uint32_t seed=CHash::MurmurHash2((uint8_t*) &(vec[i].feat_index), sizeof(int32_t), 0xDEADBEAF);

				for (int32_t j=i; j<vlen; j++)
				{
					float64_t v2=vec[j].entry;
					uint32_t h=CHash::MurmurHash2((uint8_t*) &(vec[j].feat_index), sizeof(int32_t), seed) & mask;
					float64_t v;

					if (i==j)
						v=v1*v1;
					else
						v=CMath::sqrt(2.0)*v1*v2;

					result+=v*vec2[h];
				}
			}
		}
		else if (m_degree==3)
			SG_NOTIMPLEMENTED;
	}

	if (m_normalize)
		result/=m_normalization_values[vec_idx1];

	m_feat->free_feature_vector(vec, vlen, do_free);
	return result;
}

void CSparsePolyFeatures::add_to_dense_vec(float64_t alpha, int32_t vec_idx1, float64_t* vec2, int32_t vec2_len, bool abs_val)
{
	if (vec2_len != m_output_dimensions)
		SG_ERROR("Dimensions don't match, vec2_dim=%d, m_output_dimensions=%d\n", vec2_len, m_output_dimensions);

	int32_t vlen;
	bool do_free;
	TSparseEntry<float64_t>* vec = m_feat->get_sparse_feature_vector(vec_idx1, vlen, do_free);

	float64_t norm_val=1.0;
	if (m_normalize)
		norm_val = m_normalization_values[vec_idx1];
	alpha/=norm_val;

	if (m_degree==2)
	{
		/* (a+b)^2 = a^2 + 2ab +b^2 */
		for (int32_t i=0; i<vlen; i++)
		{
			float64_t v1=vec[i].entry;
			uint32_t seed=CHash::MurmurHash2((uint8_t*) &(vec[i].feat_index), sizeof(int32_t), 0xDEADBEAF);

			for (int32_t j=i; j<vlen; j++)
			{
				float64_t v2=vec[j].entry;
				uint32_t h=CHash::MurmurHash2((uint8_t*) &(vec[j].feat_index), sizeof(int32_t), seed) & mask;
				float64_t v;

				if (i==j)
					v=alpha*v1*v1;
				else
					v=alpha*CMath::sqrt(2.0)*v1*v2;

				if (abs_val)
					vec2[h]+=CMath::abs(v);
				else
					vec2[h]+=v;
			}
		}
	}
	else if (m_degree==3)
		SG_NOTIMPLEMENTED;

	m_feat->free_feature_vector(vec, vlen, do_free);
}

void CSparsePolyFeatures::store_normalization_values()
{
	delete[] m_normalization_values;

	int32_t num_vec = this->get_num_vectors();

	m_normalization_values=new float64_t[num_vec];
	for (int i=0; i<num_vec; i++)
	{
		float64_t val = CMath::sqrt(dot(i,i));
		if (val==0)
			// trap division by zero
			m_normalization_values[i]=1.0;
		else
			m_normalization_values[i]=val;
	}

}

CFeatures* CSparsePolyFeatures::duplicate() const
{
	return new CSparsePolyFeatures(*this);
}
<|endoftext|>


<commit_before>//===- ArchiveWriter.cpp - ar File Format implementation --------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the writeArchive function.
//
//===----------------------------------------------------------------------===//

#include "llvm/Object/ArchiveWriter.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/Object/Archive.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Object/SymbolicFile.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/ToolOutputFile.h"
#include "llvm/Support/raw_ostream.h"

#include <unistd.h>

using namespace llvm;

NewArchiveIterator::NewArchiveIterator() {}

NewArchiveIterator::NewArchiveIterator(object::Archive::child_iterator I,
                                       StringRef Name)
    : IsNewMember(false), Name(Name), OldI(I) {}

NewArchiveIterator::NewArchiveIterator(StringRef NewFilename, StringRef Name)
    : IsNewMember(true), Name(Name), NewFilename(NewFilename) {}

StringRef NewArchiveIterator::getName() const { return Name; }

bool NewArchiveIterator::isNewMember() const { return IsNewMember; }

object::Archive::child_iterator NewArchiveIterator::getOld() const {
  assert(!IsNewMember);
  return OldI;
}

StringRef NewArchiveIterator::getNew() const {
  assert(IsNewMember);
  return NewFilename;
}

llvm::ErrorOr<int>
NewArchiveIterator::getFD(sys::fs::file_status &NewStatus) const {
  assert(IsNewMember);
  int NewFD;
  if (auto EC = sys::fs::openFileForRead(NewFilename, NewFD))
    return EC;
  assert(NewFD != -1);

  if (auto EC = sys::fs::status(NewFD, NewStatus))
    return EC;

  // Opening a directory doesn't make sense. Let it fail.
  // Linux cannot open directories with open(2), although
  // cygwin and *bsd can.
  if (NewStatus.type() == sys::fs::file_type::directory_file)
    return make_error_code(std::errc::is_a_directory);

  return NewFD;
}

template <typename T>
static void printWithSpacePadding(raw_fd_ostream &OS, T Data, unsigned Size,
				  bool MayTruncate = false) {
  uint64_t OldPos = OS.tell();
  OS << Data;
  unsigned SizeSoFar = OS.tell() - OldPos;
  if (Size > SizeSoFar) {
    unsigned Remaining = Size - SizeSoFar;
    for (unsigned I = 0; I < Remaining; ++I)
      OS << ' ';
  } else if (Size < SizeSoFar) {
    assert(MayTruncate && "Data doesn't fit in Size");
    // Some of the data this is used for (like UID) can be larger than the
    // space available in the archive format. Truncate in that case.
    OS.seek(OldPos + Size);
  }
}

static void print32BE(raw_fd_ostream &Out, unsigned Val) {
  // FIXME: Should use Endian.h here.
  for (int I = 3; I >= 0; --I) {
    char V = (Val >> (8 * I)) & 0xff;
    Out << V;
  }
}

static void printRestOfMemberHeader(raw_fd_ostream &Out,
                                    const sys::TimeValue &ModTime, unsigned UID,
                                    unsigned GID, unsigned Perms,
                                    unsigned Size) {
  printWithSpacePadding(Out, ModTime.toEpochTime(), 12);
  printWithSpacePadding(Out, UID, 6, true);
  printWithSpacePadding(Out, GID, 6, true);
  printWithSpacePadding(Out, format("%o", Perms), 8);
  printWithSpacePadding(Out, Size, 10);
  Out << "`\n";
}

static void printMemberHeader(raw_fd_ostream &Out, StringRef Name,
                              const sys::TimeValue &ModTime, unsigned UID,
                              unsigned GID, unsigned Perms, unsigned Size) {
  printWithSpacePadding(Out, Twine(Name) + "/", 16);
  printRestOfMemberHeader(Out, ModTime, UID, GID, Perms, Size);
}

static void printMemberHeader(raw_fd_ostream &Out, unsigned NameOffset,
                              const sys::TimeValue &ModTime, unsigned UID,
                              unsigned GID, unsigned Perms, unsigned Size) {
  Out << '/';
  printWithSpacePadding(Out, NameOffset, 15);
  printRestOfMemberHeader(Out, ModTime, UID, GID, Perms, Size);
}

static void writeStringTable(raw_fd_ostream &Out,
                             ArrayRef<NewArchiveIterator> Members,
                             std::vector<unsigned> &StringMapIndexes) {
  unsigned StartOffset = 0;
  for (ArrayRef<NewArchiveIterator>::iterator I = Members.begin(),
                                              E = Members.end();
       I != E; ++I) {
    StringRef Name = I->getName();
    if (Name.size() < 16)
      continue;
    if (StartOffset == 0) {
      printWithSpacePadding(Out, "//", 58);
      Out << "`\n";
      StartOffset = Out.tell();
    }
    StringMapIndexes.push_back(Out.tell() - StartOffset);
    Out << Name << "/\n";
  }
  if (StartOffset == 0)
    return;
  if (Out.tell() % 2)
    Out << '\n';
  int Pos = Out.tell();
  Out.seek(StartOffset - 12);
  printWithSpacePadding(Out, Pos - StartOffset, 10);
  Out.seek(Pos);
}

// Returns the offset of the first reference to a member offset.
static ErrorOr<unsigned>
writeSymbolTable(raw_fd_ostream &Out, ArrayRef<NewArchiveIterator> Members,
                 ArrayRef<MemoryBufferRef> Buffers,
                 std::vector<unsigned> &MemberOffsetRefs) {
  unsigned StartOffset = 0;
  unsigned MemberNum = 0;
  std::string NameBuf;
  raw_string_ostream NameOS(NameBuf);
  unsigned NumSyms = 0;
  LLVMContext Context;
  for (ArrayRef<NewArchiveIterator>::iterator I = Members.begin(),
                                              E = Members.end();
       I != E; ++I, ++MemberNum) {
    MemoryBufferRef MemberBuffer = Buffers[MemberNum];
    ErrorOr<std::unique_ptr<object::SymbolicFile>> ObjOrErr =
        object::SymbolicFile::createSymbolicFile(
            MemberBuffer, sys::fs::file_magic::unknown, &Context);
    if (!ObjOrErr)
      continue;  // FIXME: check only for "not an object file" errors.
    object::SymbolicFile &Obj = *ObjOrErr.get();

    if (!StartOffset) {
      printMemberHeader(Out, "", sys::TimeValue::now(), 0, 0, 0, 0);
      StartOffset = Out.tell();
      print32BE(Out, 0);
    }

    for (const object::BasicSymbolRef &S : Obj.symbols()) {
      uint32_t Symflags = S.getFlags();
      if (Symflags & object::SymbolRef::SF_FormatSpecific)
        continue;
      if (!(Symflags & object::SymbolRef::SF_Global))
        continue;
      if (Symflags & object::SymbolRef::SF_Undefined)
        continue;
      if (auto EC = S.printName(NameOS))
        return EC;
      NameOS << '\0';
      ++NumSyms;
      MemberOffsetRefs.push_back(MemberNum);
      print32BE(Out, 0);
    }
  }
  Out << NameOS.str();

  if (StartOffset == 0)
    return 0;

  if (Out.tell() % 2)
    Out << '\0';

  unsigned Pos = Out.tell();
  Out.seek(StartOffset - 12);
  printWithSpacePadding(Out, Pos - StartOffset, 10);
  Out.seek(StartOffset);
  print32BE(Out, NumSyms);
  Out.seek(Pos);
  return StartOffset + 4;
}

std::pair<StringRef, std::error_code>
llvm::writeArchive(StringRef ArcName,
                   std::vector<NewArchiveIterator> &NewMembers,
                   bool WriteSymtab) {
  SmallString<128> TmpArchive;
  int TmpArchiveFD;
  if (auto EC = sys::fs::createUniqueFile(ArcName + ".temp-archive-%%%%%%%.a",
                                          TmpArchiveFD, TmpArchive))
    return std::make_pair(ArcName, EC);

  tool_output_file Output(TmpArchive, TmpArchiveFD);
  raw_fd_ostream &Out = Output.os();
  Out << "!<arch>\n";

  std::vector<unsigned> MemberOffsetRefs;

  std::vector<std::unique_ptr<MemoryBuffer>> Buffers;
  std::vector<MemoryBufferRef> Members;
  std::vector<sys::fs::file_status> NewMemberStatus;

  for (unsigned I = 0, N = NewMembers.size(); I < N; ++I) {
    NewArchiveIterator &Member = NewMembers[I];
    MemoryBufferRef MemberRef;

    if (Member.isNewMember()) {
      StringRef Filename = Member.getNew();
      NewMemberStatus.resize(NewMemberStatus.size() + 1);
      sys::fs::file_status &Status = NewMemberStatus.back();
      ErrorOr<int> FD = Member.getFD(Status);
      if (auto EC = FD.getError())
        return std::make_pair(Filename, EC);
      ErrorOr<std::unique_ptr<MemoryBuffer>> MemberBufferOrErr =
          MemoryBuffer::getOpenFile(FD.get(), Filename, Status.getSize(),
                                    false);
      if (auto EC = MemberBufferOrErr.getError())
        return std::make_pair(Filename, EC);
      if (close(FD.get()) != 0)
        return std::make_pair(Filename,
                              std::error_code(errno, std::generic_category()));
      Buffers.push_back(std::move(MemberBufferOrErr.get()));
      MemberRef = Buffers.back()->getMemBufferRef();
    } else {
      object::Archive::child_iterator OldMember = Member.getOld();
      ErrorOr<MemoryBufferRef> MemberBufferOrErr =
          OldMember->getMemoryBufferRef();
      if (auto EC = MemberBufferOrErr.getError())
        return std::make_pair("", EC);
      MemberRef = MemberBufferOrErr.get();
    }
    Members.push_back(MemberRef);
  }

  unsigned MemberReferenceOffset = 0;
  if (WriteSymtab) {
    ErrorOr<unsigned> MemberReferenceOffsetOrErr =
        writeSymbolTable(Out, NewMembers, Members, MemberOffsetRefs);
    if (auto EC = MemberReferenceOffsetOrErr.getError())
      return std::make_pair(ArcName, EC);
    MemberReferenceOffset = MemberReferenceOffsetOrErr.get();
  }

  std::vector<unsigned> StringMapIndexes;
  writeStringTable(Out, NewMembers, StringMapIndexes);

  unsigned MemberNum = 0;
  unsigned LongNameMemberNum = 0;
  unsigned NewMemberNum = 0;
  std::vector<unsigned> MemberOffset;
  for (std::vector<NewArchiveIterator>::iterator I = NewMembers.begin(),
                                                 E = NewMembers.end();
       I != E; ++I, ++MemberNum) {

    unsigned Pos = Out.tell();
    MemberOffset.push_back(Pos);

    MemoryBufferRef File = Members[MemberNum];
    if (I->isNewMember()) {
      StringRef FileName = I->getNew();
      const sys::fs::file_status &Status = NewMemberStatus[NewMemberNum];
      NewMemberNum++;

      StringRef Name = sys::path::filename(FileName);
      if (Name.size() < 16)
        printMemberHeader(Out, Name, Status.getLastModificationTime(),
                          Status.getUser(), Status.getGroup(),
                          Status.permissions(), Status.getSize());
      else
        printMemberHeader(Out, StringMapIndexes[LongNameMemberNum++],
                          Status.getLastModificationTime(), Status.getUser(),
                          Status.getGroup(), Status.permissions(),
                          Status.getSize());
    } else {
      object::Archive::child_iterator OldMember = I->getOld();
      StringRef Name = I->getName();

      if (Name.size() < 16)
        printMemberHeader(Out, Name, OldMember->getLastModified(),
                          OldMember->getUID(), OldMember->getGID(),
                          OldMember->getAccessMode(), OldMember->getSize());
      else
        printMemberHeader(Out, StringMapIndexes[LongNameMemberNum++],
                          OldMember->getLastModified(), OldMember->getUID(),
                          OldMember->getGID(), OldMember->getAccessMode(),
                          OldMember->getSize());
    }

    Out << File.getBuffer();

    if (Out.tell() % 2)
      Out << '\n';
  }

  if (MemberReferenceOffset) {
    Out.seek(MemberReferenceOffset);
    for (unsigned MemberNum : MemberOffsetRefs)
      print32BE(Out, MemberOffset[MemberNum]);
  }

  Output.keep();
  Out.close();
  sys::fs::rename(TmpArchive, ArcName);
  return std::make_pair("", std::error_code());
}
<commit_msg>Fix Windows build.<commit_after>//===- ArchiveWriter.cpp - ar File Format implementation --------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the writeArchive function.
//
//===----------------------------------------------------------------------===//

#include "llvm/Object/ArchiveWriter.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/Object/Archive.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Object/SymbolicFile.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/ToolOutputFile.h"
#include "llvm/Support/raw_ostream.h"

#if !defined(_MSC_VER) && !defined(__MINGW32__)
#include <unistd.h>
#else
#include <io.h>
#endif

using namespace llvm;

NewArchiveIterator::NewArchiveIterator() {}

NewArchiveIterator::NewArchiveIterator(object::Archive::child_iterator I,
                                       StringRef Name)
    : IsNewMember(false), Name(Name), OldI(I) {}

NewArchiveIterator::NewArchiveIterator(StringRef NewFilename, StringRef Name)
    : IsNewMember(true), Name(Name), NewFilename(NewFilename) {}

StringRef NewArchiveIterator::getName() const { return Name; }

bool NewArchiveIterator::isNewMember() const { return IsNewMember; }

object::Archive::child_iterator NewArchiveIterator::getOld() const {
  assert(!IsNewMember);
  return OldI;
}

StringRef NewArchiveIterator::getNew() const {
  assert(IsNewMember);
  return NewFilename;
}

llvm::ErrorOr<int>
NewArchiveIterator::getFD(sys::fs::file_status &NewStatus) const {
  assert(IsNewMember);
  int NewFD;
  if (auto EC = sys::fs::openFileForRead(NewFilename, NewFD))
    return EC;
  assert(NewFD != -1);

  if (auto EC = sys::fs::status(NewFD, NewStatus))
    return EC;

  // Opening a directory doesn't make sense. Let it fail.
  // Linux cannot open directories with open(2), although
  // cygwin and *bsd can.
  if (NewStatus.type() == sys::fs::file_type::directory_file)
    return make_error_code(std::errc::is_a_directory);

  return NewFD;
}

template <typename T>
static void printWithSpacePadding(raw_fd_ostream &OS, T Data, unsigned Size,
				  bool MayTruncate = false) {
  uint64_t OldPos = OS.tell();
  OS << Data;
  unsigned SizeSoFar = OS.tell() - OldPos;
  if (Size > SizeSoFar) {
    unsigned Remaining = Size - SizeSoFar;
    for (unsigned I = 0; I < Remaining; ++I)
      OS << ' ';
  } else if (Size < SizeSoFar) {
    assert(MayTruncate && "Data doesn't fit in Size");
    // Some of the data this is used for (like UID) can be larger than the
    // space available in the archive format. Truncate in that case.
    OS.seek(OldPos + Size);
  }
}

static void print32BE(raw_fd_ostream &Out, unsigned Val) {
  // FIXME: Should use Endian.h here.
  for (int I = 3; I >= 0; --I) {
    char V = (Val >> (8 * I)) & 0xff;
    Out << V;
  }
}

static void printRestOfMemberHeader(raw_fd_ostream &Out,
                                    const sys::TimeValue &ModTime, unsigned UID,
                                    unsigned GID, unsigned Perms,
                                    unsigned Size) {
  printWithSpacePadding(Out, ModTime.toEpochTime(), 12);
  printWithSpacePadding(Out, UID, 6, true);
  printWithSpacePadding(Out, GID, 6, true);
  printWithSpacePadding(Out, format("%o", Perms), 8);
  printWithSpacePadding(Out, Size, 10);
  Out << "`\n";
}

static void printMemberHeader(raw_fd_ostream &Out, StringRef Name,
                              const sys::TimeValue &ModTime, unsigned UID,
                              unsigned GID, unsigned Perms, unsigned Size) {
  printWithSpacePadding(Out, Twine(Name) + "/", 16);
  printRestOfMemberHeader(Out, ModTime, UID, GID, Perms, Size);
}

static void printMemberHeader(raw_fd_ostream &Out, unsigned NameOffset,
                              const sys::TimeValue &ModTime, unsigned UID,
                              unsigned GID, unsigned Perms, unsigned Size) {
  Out << '/';
  printWithSpacePadding(Out, NameOffset, 15);
  printRestOfMemberHeader(Out, ModTime, UID, GID, Perms, Size);
}

static void writeStringTable(raw_fd_ostream &Out,
                             ArrayRef<NewArchiveIterator> Members,
                             std::vector<unsigned> &StringMapIndexes) {
  unsigned StartOffset = 0;
  for (ArrayRef<NewArchiveIterator>::iterator I = Members.begin(),
                                              E = Members.end();
       I != E; ++I) {
    StringRef Name = I->getName();
    if (Name.size() < 16)
      continue;
    if (StartOffset == 0) {
      printWithSpacePadding(Out, "//", 58);
      Out << "`\n";
      StartOffset = Out.tell();
    }
    StringMapIndexes.push_back(Out.tell() - StartOffset);
    Out << Name << "/\n";
  }
  if (StartOffset == 0)
    return;
  if (Out.tell() % 2)
    Out << '\n';
  int Pos = Out.tell();
  Out.seek(StartOffset - 12);
  printWithSpacePadding(Out, Pos - StartOffset, 10);
  Out.seek(Pos);
}

// Returns the offset of the first reference to a member offset.
static ErrorOr<unsigned>
writeSymbolTable(raw_fd_ostream &Out, ArrayRef<NewArchiveIterator> Members,
                 ArrayRef<MemoryBufferRef> Buffers,
                 std::vector<unsigned> &MemberOffsetRefs) {
  unsigned StartOffset = 0;
  unsigned MemberNum = 0;
  std::string NameBuf;
  raw_string_ostream NameOS(NameBuf);
  unsigned NumSyms = 0;
  LLVMContext Context;
  for (ArrayRef<NewArchiveIterator>::iterator I = Members.begin(),
                                              E = Members.end();
       I != E; ++I, ++MemberNum) {
    MemoryBufferRef MemberBuffer = Buffers[MemberNum];
    ErrorOr<std::unique_ptr<object::SymbolicFile>> ObjOrErr =
        object::SymbolicFile::createSymbolicFile(
            MemberBuffer, sys::fs::file_magic::unknown, &Context);
    if (!ObjOrErr)
      continue;  // FIXME: check only for "not an object file" errors.
    object::SymbolicFile &Obj = *ObjOrErr.get();

    if (!StartOffset) {
      printMemberHeader(Out, "", sys::TimeValue::now(), 0, 0, 0, 0);
      StartOffset = Out.tell();
      print32BE(Out, 0);
    }

    for (const object::BasicSymbolRef &S : Obj.symbols()) {
      uint32_t Symflags = S.getFlags();
      if (Symflags & object::SymbolRef::SF_FormatSpecific)
        continue;
      if (!(Symflags & object::SymbolRef::SF_Global))
        continue;
      if (Symflags & object::SymbolRef::SF_Undefined)
        continue;
      if (auto EC = S.printName(NameOS))
        return EC;
      NameOS << '\0';
      ++NumSyms;
      MemberOffsetRefs.push_back(MemberNum);
      print32BE(Out, 0);
    }
  }
  Out << NameOS.str();

  if (StartOffset == 0)
    return 0;

  if (Out.tell() % 2)
    Out << '\0';

  unsigned Pos = Out.tell();
  Out.seek(StartOffset - 12);
  printWithSpacePadding(Out, Pos - StartOffset, 10);
  Out.seek(StartOffset);
  print32BE(Out, NumSyms);
  Out.seek(Pos);
  return StartOffset + 4;
}

std::pair<StringRef, std::error_code>
llvm::writeArchive(StringRef ArcName,
                   std::vector<NewArchiveIterator> &NewMembers,
                   bool WriteSymtab) {
  SmallString<128> TmpArchive;
  int TmpArchiveFD;
  if (auto EC = sys::fs::createUniqueFile(ArcName + ".temp-archive-%%%%%%%.a",
                                          TmpArchiveFD, TmpArchive))
    return std::make_pair(ArcName, EC);

  tool_output_file Output(TmpArchive, TmpArchiveFD);
  raw_fd_ostream &Out = Output.os();
  Out << "!<arch>\n";

  std::vector<unsigned> MemberOffsetRefs;

  std::vector<std::unique_ptr<MemoryBuffer>> Buffers;
  std::vector<MemoryBufferRef> Members;
  std::vector<sys::fs::file_status> NewMemberStatus;

  for (unsigned I = 0, N = NewMembers.size(); I < N; ++I) {
    NewArchiveIterator &Member = NewMembers[I];
    MemoryBufferRef MemberRef;

    if (Member.isNewMember()) {
      StringRef Filename = Member.getNew();
      NewMemberStatus.resize(NewMemberStatus.size() + 1);
      sys::fs::file_status &Status = NewMemberStatus.back();
      ErrorOr<int> FD = Member.getFD(Status);
      if (auto EC = FD.getError())
        return std::make_pair(Filename, EC);
      ErrorOr<std::unique_ptr<MemoryBuffer>> MemberBufferOrErr =
          MemoryBuffer::getOpenFile(FD.get(), Filename, Status.getSize(),
                                    false);
      if (auto EC = MemberBufferOrErr.getError())
        return std::make_pair(Filename, EC);
      if (close(FD.get()) != 0)
        return std::make_pair(Filename,
                              std::error_code(errno, std::generic_category()));
      Buffers.push_back(std::move(MemberBufferOrErr.get()));
      MemberRef = Buffers.back()->getMemBufferRef();
    } else {
      object::Archive::child_iterator OldMember = Member.getOld();
      ErrorOr<MemoryBufferRef> MemberBufferOrErr =
          OldMember->getMemoryBufferRef();
      if (auto EC = MemberBufferOrErr.getError())
        return std::make_pair("", EC);
      MemberRef = MemberBufferOrErr.get();
    }
    Members.push_back(MemberRef);
  }

  unsigned MemberReferenceOffset = 0;
  if (WriteSymtab) {
    ErrorOr<unsigned> MemberReferenceOffsetOrErr =
        writeSymbolTable(Out, NewMembers, Members, MemberOffsetRefs);
    if (auto EC = MemberReferenceOffsetOrErr.getError())
      return std::make_pair(ArcName, EC);
    MemberReferenceOffset = MemberReferenceOffsetOrErr.get();
  }

  std::vector<unsigned> StringMapIndexes;
  writeStringTable(Out, NewMembers, StringMapIndexes);

  unsigned MemberNum = 0;
  unsigned LongNameMemberNum = 0;
  unsigned NewMemberNum = 0;
  std::vector<unsigned> MemberOffset;
  for (std::vector<NewArchiveIterator>::iterator I = NewMembers.begin(),
                                                 E = NewMembers.end();
       I != E; ++I, ++MemberNum) {

    unsigned Pos = Out.tell();
    MemberOffset.push_back(Pos);

    MemoryBufferRef File = Members[MemberNum];
    if (I->isNewMember()) {
      StringRef FileName = I->getNew();
      const sys::fs::file_status &Status = NewMemberStatus[NewMemberNum];
      NewMemberNum++;

      StringRef Name = sys::path::filename(FileName);
      if (Name.size() < 16)
        printMemberHeader(Out, Name, Status.getLastModificationTime(),
                          Status.getUser(), Status.getGroup(),
                          Status.permissions(), Status.getSize());
      else
        printMemberHeader(Out, StringMapIndexes[LongNameMemberNum++],
                          Status.getLastModificationTime(), Status.getUser(),
                          Status.getGroup(), Status.permissions(),
                          Status.getSize());
    } else {
      object::Archive::child_iterator OldMember = I->getOld();
      StringRef Name = I->getName();

      if (Name.size() < 16)
        printMemberHeader(Out, Name, OldMember->getLastModified(),
                          OldMember->getUID(), OldMember->getGID(),
                          OldMember->getAccessMode(), OldMember->getSize());
      else
        printMemberHeader(Out, StringMapIndexes[LongNameMemberNum++],
                          OldMember->getLastModified(), OldMember->getUID(),
                          OldMember->getGID(), OldMember->getAccessMode(),
                          OldMember->getSize());
    }

    Out << File.getBuffer();

    if (Out.tell() % 2)
      Out << '\n';
  }

  if (MemberReferenceOffset) {
    Out.seek(MemberReferenceOffset);
    for (unsigned MemberNum : MemberOffsetRefs)
      print32BE(Out, MemberOffset[MemberNum]);
  }

  Output.keep();
  Out.close();
  sys::fs::rename(TmpArchive, ArcName);
  return std::make_pair("", std::error_code());
}
<|endoftext|>


<commit_before>/*
 * ApproxBetweenness.cpp
 *
 *  Created on: 09.04.2014
 *      Author: cls
 */

#include "ApproxBetweenness.h"
#include "../auxiliary/Random.h"
#include "../distance/Diameter.h"
#include "../graph/Sampling.h"
#include "../graph/Dijkstra.h"
#include "../graph/BFS.h"
#include "../graph/SSSP.h"
#include "../auxiliary/Log.h"
#include "../auxiliary/SignalHandling.h"

#include <math.h>
#include <algorithm>
#include <memory>
#include <omp.h>

namespace NetworKit {

ApproxBetweenness::ApproxBetweenness(const Graph& G, double epsilon, double delta, count diameterSamples) : Centrality(G, true), epsilon(epsilon), delta(delta), diameterSamples(diameterSamples) {

}

void ApproxBetweenness::run() {
	Aux::SignalHandler handler;
	scoreData.clear();
	scoreData.resize(G.upperNodeIdBound());

	double c = 0.5; // universal positive constant - see reference in paper

	edgeweight vd = 0;
	if (diameterSamples == 0) {
		INFO("estimating vertex diameter pedantically");
		vd = Diameter::estimatedVertexDiameterPedantic(G);
	} else {
		/**
		* This is an optimization which deviates from the original algorithm.
		* Instead of getting an estimate for each of possibly thousands of connected component and taking the maximum,
		* we sample the graph and take the maximum diameter found. This has a high chance of  hitting the component with the maximum vertex diameter.
		*/
		INFO("estimating vertex diameter roughly");
		vd = Diameter::estimatedVertexDiameter(G, diameterSamples);
	}

	INFO("estimated diameter: ", vd);
	r = ceil((c / (epsilon * epsilon)) * (floor(log(vd - 2)) + 1 + log(1 / delta)));

	INFO("taking ", r, " path samples");
	// parallelization:
	count maxThreads = omp_get_max_threads();
	DEBUG("max threads: ", maxThreads);
	std::vector<std::vector<double> > scorePerThread(maxThreads, std::vector<double>(G.upperNodeIdBound()));
	DEBUG("score per thread size: ", scorePerThread.size());
	handler.assureRunning();
	#pragma omp parallel for
	for (count i = 1; i <= r; i++) {
		count thread = omp_get_thread_num();
		DEBUG("sample ", i);
		// if (i >= 1000) throw std::runtime_error("too many iterations");
		// DEBUG
		// sample random node pair
		node u, v;
		u = Sampling::randomNode(G);
		do {
			v = Sampling::randomNode(G);
		} while (v == u);

		// runs faster for unweighted graphs
		std::unique_ptr<SSSP> sssp;
		if (G.isWeighted()) {
			sssp.reset(new Dijkstra(G, u, true, false, v));
		} else {
			sssp.reset(new BFS(G, u, true, false, v));
		}
		DEBUG("running shortest path algorithm for node ", u);
		if (!handler.isRunning()) continue;
		sssp->run();
		if (!handler.isRunning()) continue;
		if (sssp->numberOfPaths(v) > 0) { // at least one path between {u, v} exists
			DEBUG("updating estimate for path ", u, " <-> ", v);
			// random path sampling and estimation update
			// node s = v;
			node t = v;
			while (t != u)  {
				// sample z in P_u(t) with probability sigma_uz / sigma_us
				std::vector<std::pair<node, double> > choices;
				for (node z : sssp->getPredecessors(t)) {
					bigfloat tmp = sssp->numberOfPaths(z) / sssp->numberOfPaths(t);
					double weight;
					tmp.ToDouble(weight);
					choices.emplace_back(z, weight); 	// sigma_uz / sigma_us
				}
				node z = Aux::Random::weightedChoice(choices);
				assert (z <= G.upperNodeIdBound());
				if (z != u) {
					scorePerThread[thread][z] += 1 / (double) r;
				}
				// s = t;
				t = z;
			}
		}
	}
	handler.assureRunning();

	INFO("adding thread-local scores");
	// add up all thread-local values
	for (auto &local : scorePerThread) {
		G.parallelForNodes([&](node v){
			scoreData[v] += local[v];
		});
	}

	hasRun = true;
}

count ApproxBetweenness::numberOfSamples() {
	INFO("Estimated number of samples", r);
	return r;
}

} /* namespace NetworKit */
<commit_msg>Compute the sample size correctly by using log2 when needed.<commit_after>/*
 * ApproxBetweenness.cpp
 *
 *  Created on: 09.04.2014
 *      Author: cls
 */

#include "ApproxBetweenness.h"
#include "../auxiliary/Random.h"
#include "../distance/Diameter.h"
#include "../graph/Sampling.h"
#include "../graph/Dijkstra.h"
#include "../graph/BFS.h"
#include "../graph/SSSP.h"
#include "../auxiliary/Log.h"
#include "../auxiliary/SignalHandling.h"

#include <math.h>
#include <algorithm>
#include <memory>
#include <omp.h>

namespace NetworKit {

ApproxBetweenness::ApproxBetweenness(const Graph& G, double epsilon, double delta, count diameterSamples) : Centrality(G, true), epsilon(epsilon), delta(delta), diameterSamples(diameterSamples) {

}

void ApproxBetweenness::run() {
	Aux::SignalHandler handler;
	scoreData.clear();
	scoreData.resize(G.upperNodeIdBound());

	const double c = 0.5; // universal positive constant - see reference in paper

	edgeweight vd = 0;
	if (diameterSamples == 0) {
		INFO("estimating vertex diameter pedantically");
		vd = Diameter::estimatedVertexDiameterPedantic(G);
	} else {
		/**
		* This is an optimization which deviates from the original algorithm.
		* Instead of getting an estimate for each of possibly thousands of connected component and taking the maximum,
		* we sample the graph and take the maximum diameter found. This has a high chance of  hitting the component with the maximum vertex diameter.
		*/
		INFO("estimating vertex diameter roughly");
		vd = Diameter::estimatedVertexDiameter(G, diameterSamples);
	}

	INFO("estimated diameter: ", vd);
	r = ceil((c / (epsilon * epsilon)) * (floor(log2(vd - 2)) + 1 + log(1 / delta)));

	INFO("taking ", r, " path samples");
	// parallelization:
	count maxThreads = omp_get_max_threads();
	DEBUG("max threads: ", maxThreads);
	std::vector<std::vector<double> > scorePerThread(maxThreads, std::vector<double>(G.upperNodeIdBound()));
	DEBUG("score per thread size: ", scorePerThread.size());
	handler.assureRunning();
	#pragma omp parallel for
	for (count i = 1; i <= r; i++) {
		count thread = omp_get_thread_num();
		DEBUG("sample ", i);
		// if (i >= 1000) throw std::runtime_error("too many iterations");
		// DEBUG
		// sample random node pair
		node u, v;
		u = Sampling::randomNode(G);
		do {
			v = Sampling::randomNode(G);
		} while (v == u);

		// runs faster for unweighted graphs
		std::unique_ptr<SSSP> sssp;
		if (G.isWeighted()) {
			sssp.reset(new Dijkstra(G, u, true, false, v));
		} else {
			sssp.reset(new BFS(G, u, true, false, v));
		}
		DEBUG("running shortest path algorithm for node ", u);
		if (!handler.isRunning()) continue;
		sssp->run();
		if (!handler.isRunning()) continue;
		if (sssp->numberOfPaths(v) > 0) { // at least one path between {u, v} exists
			DEBUG("updating estimate for path ", u, " <-> ", v);
			// random path sampling and estimation update
			// node s = v;
			node t = v;
			while (t != u)  {
				// sample z in P_u(t) with probability sigma_uz / sigma_us
				std::vector<std::pair<node, double> > choices;
				for (node z : sssp->getPredecessors(t)) {
					bigfloat tmp = sssp->numberOfPaths(z) / sssp->numberOfPaths(t);
					double weight;
					tmp.ToDouble(weight);
					choices.emplace_back(z, weight); 	// sigma_uz / sigma_us
				}
				node z = Aux::Random::weightedChoice(choices);
				assert (z <= G.upperNodeIdBound());
				if (z != u) {
					scorePerThread[thread][z] += 1 / (double) r;
				}
				// s = t;
				t = z;
			}
		}
	}
	handler.assureRunning();

	INFO("adding thread-local scores");
	// add up all thread-local values
	for (auto &local : scorePerThread) {
		G.parallelForNodes([&](node v){
			scoreData[v] += local[v];
		});
	}

	hasRun = true;
}

count ApproxBetweenness::numberOfSamples() {
	INFO("Estimated number of samples", r);
	return r;
}

} /* namespace NetworKit */
<|endoftext|>


<commit_before>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// Utilities shared by both Broker RPC client and server.

#include "ceee/ie/broker/broker_rpc_utils.h"

#include "base/win_util.h"
#include "ceee/common/process_utils_win.h"

// Local interprocess communication only.
const wchar_t kRpcProtocol[] = L"ncalrpc";

std::wstring GetRpcEndPointAddress() {
  std::wstring end_point;
  bool running_as_admin = false;
  // CEEE running as regular user and CEEE running as elevated user will start
  // different broker processes. So make end points names different to connect
  // to appropriate one.
  process_utils_win::IsCurrentProcessUacElevated(&running_as_admin);
  if (running_as_admin)
    end_point += L"ADMIN-";
  std::wstring sid;
  win_util::GetUserSidString(&sid);
  end_point += sid;
  end_point += L"-B4630D08-4621-41A1-A8D0-F1E98DA460D6";
  return end_point;
}

void  __RPC_FAR * __RPC_USER midl_user_allocate(size_t len) {
  return malloc(len);
}

void __RPC_USER midl_user_free(void __RPC_FAR * ptr) {
  free(ptr);
}
<commit_msg>Submitting changes by Vitaly Buka, reviewed here:  http://codereview.chromium.org/5168002<commit_after>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// Utilities shared by both Broker RPC client and server.

#include "ceee/ie/broker/broker_rpc_utils.h"

#include <algorithm>

#include "base/win_util.h"
#include "ceee/common/process_utils_win.h"

// Local interprocess communication only.
const wchar_t kRpcProtocol[] = L"ncalrpc";

std::wstring GetRpcEndPointAddress() {
  std::wstring end_point;
  bool running_as_admin = false;
  // CEEE running as regular user and CEEE running as elevated user will start
  // different broker processes. So make end points names different to connect
  // to appropriate one.
  process_utils_win::IsCurrentProcessUacElevated(&running_as_admin);
  if (running_as_admin)
    end_point += L"ADMIN-";
  std::wstring sid;
  win_util::GetUserSidString(&sid);
  end_point += sid;
  end_point += L"-B4630D08-4621-41A1-A8D0-F1E98DA460D6";
  // XP does not accept endpoints longer than 52.
  end_point.resize(std::min(52u, end_point.size()));
  return end_point;
}

void  __RPC_FAR * __RPC_USER midl_user_allocate(size_t len) {
  return malloc(len);
}

void __RPC_USER midl_user_free(void __RPC_FAR * ptr) {
  free(ptr);
}
<|endoftext|>