<commit_before>/*
 * Copyright (C) 2004-2010  See the AUTHORS file for details.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 as published
 * by the Free Software Foundation.
 */

#include "User.h"
#include <algorithm>

class CPerform : public CModule {
public:
	MODCONSTRUCTOR(CPerform) {}

	virtual ~CPerform() {}

	virtual bool OnLoad(const CString& sArgs, CString& sMessage) {
		GetNV("Perform").Split("\n", m_vPerform, false);

		return true;
	}

	virtual void OnModCommand(const CString& sCommand) {
		CString sCmdName = sCommand.Token(0).AsLower();
		if (sCmdName == "add") {
			CString sPerf = sCommand.Token(1, true);

			if (sPerf.empty()) {
				PutModule("Usage: add <command>");
				return;
			}

			if (sPerf.Left(1) == "/")
				sPerf.LeftChomp();

			if (sPerf.Token(0).Equals("MSG")) {
				sPerf = "PRIVMSG " + sPerf.Token(1, true);
			}

			if ((sPerf.Token(0).Equals("PRIVMSG") ||
				sPerf.Token(0).Equals("NOTICE")) &&
				sPerf.Token(2).Left(1) != ":") {
				sPerf = sPerf.Token(0) + " " + sPerf.Token(1)
					+ " :" + sPerf.Token(2, true);
			}
			m_vPerform.push_back(sPerf);
			PutModule("Added!");
			Save();
		} else if (sCmdName == "del") {
			u_int iNum = sCommand.Token(1, true).ToUInt();
			if (iNum > m_vPerform.size() || iNum <= 0) {
				PutModule("Illegal # Requested");
				return;
			} else {
				m_vPerform.erase(m_vPerform.begin() + iNum - 1);
				PutModule("Command Erased.");
			}
			Save();
		} else if (sCmdName == "list") {
			int i = 1;
			CString sExpanded;
			for (VCString::iterator it = m_vPerform.begin(); it != m_vPerform.end(); it++, i++) {
				sExpanded = GetUser()->ExpandString(*it);
				if (sExpanded != *it)
					PutModule(CString(i) + ": " + *it + " (" + sExpanded + ")");
				else
					PutModule(CString(i) + ": " + *it);
			}
			PutModule(" -- End of List");
		} else if (sCmdName == "execute") {
			OnIRCConnected();
			PutModule("perform commands sent");
		} else if (sCmdName == "swap") {
			u_int iNumA = sCommand.Token(1).ToUInt();
			u_int iNumB = sCommand.Token(2).ToUInt();

			if (iNumA > m_vPerform.size() || iNumA <= 0 || iNumB > m_vPerform.size() || iNumB <= 0) {
				PutModule("Illegal # Requested");
			} else {
				std::iter_swap(m_vPerform.begin() + (iNumA - 1), m_vPerform.begin() + (iNumB - 1));
				PutModule("Commands Swapped.");
				Save();
			}
		} else {
			PutModule("Commands: add <command>, del <nr>, list, execute, swap <nr> <nr>");
		}
	}

	virtual void OnIRCConnected() {
		for (VCString::iterator it = m_vPerform.begin();
			it != m_vPerform.end();  ++it) {
			PutIRC(GetUser()->ExpandString(*it));
		}
	}

	virtual CString GetWebMenuTitle() { return "Perform"; }

	virtual bool OnWebRequest(CWebSock& WebSock, const CString& sPageName, CTemplate& Tmpl) {
		if (WebSock.IsPost()) {
			WebSock.GetRawParam("perform", true).Split("\n", m_vPerform, false);
			Save();
		}

		for (VCString::iterator it = m_vPerform.begin(); it != m_vPerform.end(); ++it) {
			CTemplate& Row = Tmpl.AddRow("PerformLoop");
			Row["Perform"] = *it;
		}

		return true;
	}

private:
	void Save() {
		CString sBuffer = "";

		for (VCString::iterator it = m_vPerform.begin(); it != m_vPerform.end(); ++it) {
			sBuffer += *it + "\n";
		}
		SetNV("Perform", sBuffer);
	}

	VCString m_vPerform;
};

MODULEDEFS(CPerform, "Keeps a list of commands to be executed when ZNC connects to IRC.")
<commit_msg>Perform: Also parse stuff like "/msg foo bar" via webmods<commit_after>/*
 * Copyright (C) 2004-2010  See the AUTHORS file for details.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 as published
 * by the Free Software Foundation.
 */

#include "User.h"
#include <algorithm>

class CPerform : public CModule {
public:
	MODCONSTRUCTOR(CPerform) {}

	virtual ~CPerform() {}

	CString ParsePerform(const CString& sArg) {
		CString sPerf = sArg;

		if (sPerf.Left(1) == "/")
			sPerf.LeftChomp();

		if (sPerf.Token(0).Equals("MSG")) {
			sPerf = "PRIVMSG " + sPerf.Token(1, true);
		}

		if ((sPerf.Token(0).Equals("PRIVMSG") ||
				sPerf.Token(0).Equals("NOTICE")) &&
				sPerf.Token(2).Left(1) != ":") {
			sPerf = sPerf.Token(0) + " " + sPerf.Token(1)
				+ " :" + sPerf.Token(2, true);
		}

		return sPerf;
	}

	virtual bool OnLoad(const CString& sArgs, CString& sMessage) {
		GetNV("Perform").Split("\n", m_vPerform, false);

		return true;
	}

	virtual void OnModCommand(const CString& sCommand) {
		CString sCmdName = sCommand.Token(0).AsLower();
		if (sCmdName == "add") {
			CString sPerf = sCommand.Token(1, true);

			if (sPerf.empty()) {
				PutModule("Usage: add <command>");
				return;
			}

			m_vPerform.push_back(ParsePerform(sPerf));
			PutModule("Added!");
			Save();
		} else if (sCmdName == "del") {
			u_int iNum = sCommand.Token(1, true).ToUInt();
			if (iNum > m_vPerform.size() || iNum <= 0) {
				PutModule("Illegal # Requested");
				return;
			} else {
				m_vPerform.erase(m_vPerform.begin() + iNum - 1);
				PutModule("Command Erased.");
			}
			Save();
		} else if (sCmdName == "list") {
			int i = 1;
			CString sExpanded;
			for (VCString::iterator it = m_vPerform.begin(); it != m_vPerform.end(); it++, i++) {
				sExpanded = GetUser()->ExpandString(*it);
				if (sExpanded != *it)
					PutModule(CString(i) + ": " + *it + " (" + sExpanded + ")");
				else
					PutModule(CString(i) + ": " + *it);
			}
			PutModule(" -- End of List");
		} else if (sCmdName == "execute") {
			OnIRCConnected();
			PutModule("perform commands sent");
		} else if (sCmdName == "swap") {
			u_int iNumA = sCommand.Token(1).ToUInt();
			u_int iNumB = sCommand.Token(2).ToUInt();

			if (iNumA > m_vPerform.size() || iNumA <= 0 || iNumB > m_vPerform.size() || iNumB <= 0) {
				PutModule("Illegal # Requested");
			} else {
				std::iter_swap(m_vPerform.begin() + (iNumA - 1), m_vPerform.begin() + (iNumB - 1));
				PutModule("Commands Swapped.");
				Save();
			}
		} else {
			PutModule("Commands: add <command>, del <nr>, list, execute, swap <nr> <nr>");
		}
	}

	virtual void OnIRCConnected() {
		for (VCString::iterator it = m_vPerform.begin();
			it != m_vPerform.end();  ++it) {
			PutIRC(GetUser()->ExpandString(*it));
		}
	}

	virtual CString GetWebMenuTitle() { return "Perform"; }

	virtual bool OnWebRequest(CWebSock& WebSock, const CString& sPageName, CTemplate& Tmpl) {
		if (WebSock.IsPost()) {
			VCString vsPerf;
			WebSock.GetRawParam("perform", true).Split("\n", vsPerf, false);
			m_vPerform.clear();

			for (VCString::iterator it = vsPerf.begin(); it != vsPerf.end(); ++it)
				m_vPerform.push_back(ParsePerform(*it));

			Save();
		}

		for (VCString::iterator it = m_vPerform.begin(); it != m_vPerform.end(); ++it) {
			CTemplate& Row = Tmpl.AddRow("PerformLoop");
			Row["Perform"] = *it;
		}

		return true;
	}

private:
	void Save() {
		CString sBuffer = "";

		for (VCString::iterator it = m_vPerform.begin(); it != m_vPerform.end(); ++it) {
			sBuffer += *it + "\n";
		}
		SetNV("Perform", sBuffer);
	}

	VCString m_vPerform;
};

MODULEDEFS(CPerform, "Keeps a list of commands to be executed when ZNC connects to IRC.")
<|endoftext|>


<commit_before>//===-- Sparc.cpp - General implementation file for the Sparc Target ------===//
//
// This file contains the code for the Sparc Target that does not fit in any of
// the other files in this directory.
//
//===----------------------------------------------------------------------===//

#include "SparcInternals.h"
#include "llvm/Target/TargetMachineImpls.h"
#include "llvm/Function.h"
#include "llvm/PassManager.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/PreSelection.h"
#include "llvm/CodeGen/StackSlots.h"
#include "llvm/CodeGen/PeepholeOpts.h"
#include "llvm/CodeGen/InstrSelection.h"
#include "llvm/CodeGen/InstrScheduling.h"
#include "llvm/CodeGen/RegisterAllocation.h"
#include "llvm/CodeGen/MachineCodeForInstruction.h"
#include "llvm/Reoptimizer/Mapping/MappingInfo.h"
#include "llvm/Reoptimizer/Mapping/FInfo.h"
#include "Support/CommandLine.h"
using std::cerr;

static const unsigned ImplicitRegUseList[] = { 0 }; /* not used yet */
// Build the MachineInstruction Description Array...
const MachineInstrDescriptor SparcMachineInstrDesc[] = {
#define I(ENUM, OPCODESTRING, NUMOPERANDS, RESULTPOS, MAXIMM, IMMSE, \
          NUMDELAYSLOTS, LATENCY, SCHEDCLASS, INSTFLAGS)             \
  { OPCODESTRING, NUMOPERANDS, RESULTPOS, MAXIMM, IMMSE,             \
          NUMDELAYSLOTS, LATENCY, SCHEDCLASS, INSTFLAGS, 0,          \
          ImplicitRegUseList, ImplicitRegUseList },
#include "SparcInstr.def"
};

//---------------------------------------------------------------------------
// Command line options to control choice of code generation passes.
//---------------------------------------------------------------------------

static cl::opt<bool> DisablePreSelect("nopreselect",
                                      cl::desc("Disable preselection pass"));

static cl::opt<bool> DisableSched("nosched",
                                  cl::desc("Disable local scheduling pass"));

static cl::opt<bool> DisablePeephole("nopeephole",
                                cl::desc("Disable peephole optimization pass"));

//----------------------------------------------------------------------------
// allocateSparcTargetMachine - Allocate and return a subclass of TargetMachine
// that implements the Sparc backend. (the llvm/CodeGen/Sparc.h interface)
//----------------------------------------------------------------------------

TargetMachine *allocateSparcTargetMachine() { return new UltraSparc(); }

//---------------------------------------------------------------------------
// class UltraSparcFrameInfo
//
// Purpose:
//   Interface to stack frame layout info for the UltraSPARC.
//   Starting offsets for each area of the stack frame are aligned at
//   a multiple of getStackFrameSizeAlignment().
//---------------------------------------------------------------------------

int
UltraSparcFrameInfo::getFirstAutomaticVarOffset(MachineFunction& ,
                                                bool& pos) const
{
  pos = false;                          // static stack area grows downwards
  return StaticAreaOffsetFromFP;
}

int
UltraSparcFrameInfo::getRegSpillAreaOffset(MachineFunction& mcInfo,
                                           bool& pos) const
{
  mcInfo.freezeAutomaticVarsArea();     // ensure no more auto vars are added

  pos = false;                          // static stack area grows downwards
  unsigned int autoVarsSize = mcInfo.getAutomaticVarsSize();
  return StaticAreaOffsetFromFP - autoVarsSize;
}

int
UltraSparcFrameInfo::getTmpAreaOffset(MachineFunction& mcInfo,
                                      bool& pos) const
{
  mcInfo.freezeAutomaticVarsArea();     // ensure no more auto vars are added
  mcInfo.freezeSpillsArea();            // ensure no more spill slots are added

  pos = false;                          // static stack area grows downwards
  unsigned int autoVarsSize = mcInfo.getAutomaticVarsSize();
  unsigned int spillAreaSize = mcInfo.getRegSpillsSize();
  int offset = autoVarsSize + spillAreaSize;
  return StaticAreaOffsetFromFP - offset;
}

int
UltraSparcFrameInfo::getDynamicAreaOffset(MachineFunction& mcInfo,
                                          bool& pos) const
{
  // Dynamic stack area grows downwards starting at top of opt-args area.
  // The opt-args, required-args, and register-save areas are empty except
  // during calls and traps, so they are shifted downwards on each
  // dynamic-size alloca.
  pos = false;
  unsigned int optArgsSize = mcInfo.getMaxOptionalArgsSize();
  if (int extra = optArgsSize % getStackFrameSizeAlignment())
    optArgsSize += (getStackFrameSizeAlignment() - extra);
  int offset = optArgsSize + FirstOptionalOutgoingArgOffsetFromSP;
  assert((offset - OFFSET) % getStackFrameSizeAlignment() == 0);
  return offset;
}

//---------------------------------------------------------------------------
// class UltraSparcMachine
//
// Purpose:
//   Primary interface to machine description for the UltraSPARC.
//   Primarily just initializes machine-dependent parameters in
//   class TargetMachine, and creates machine-dependent subclasses
//   for classes such as MachineInstrInfo.
//
//---------------------------------------------------------------------------

UltraSparc::UltraSparc()
  : TargetMachine("UltraSparc-Native", false, 4),
    schedInfo(*this),
    regInfo(*this),
    frameInfo(*this),
    cacheInfo(*this),
    optInfo(*this) {
}

// addPassesToEmitAssembly - This method controls the entire code generation
// process for the ultra sparc.
//
bool UltraSparc::addPassesToEmitAssembly(PassManager &PM, std::ostream &Out)
{
  // Construct and initialize the MachineFunction object for this fn.
  PM.add(createMachineCodeConstructionPass(*this));

  //Insert empty stackslots in the stack frame of each function
  //so %fp+offset-8 and %fp+offset-16 are empty slots now!
  PM.add(createStackSlotsPass(*this));

  // Specialize LLVM code for this target machine and then
  // run basic dataflow optimizations on LLVM code.
  if (!DisablePreSelect)
    {
      PM.add(createPreSelectionPass(*this));
      PM.add(createReassociatePass());
      PM.add(createLICMPass());
      PM.add(createGCSEPass());
    }

  PM.add(createInstructionSelectionPass(*this));

  if (!DisableSched)
    PM.add(createInstructionSchedulingWithSSAPass(*this));

  PM.add(getRegisterAllocator(*this));

  PM.add(getPrologEpilogInsertionPass());

  if (!DisablePeephole)
    PM.add(createPeepholeOptsPass(*this));

  PM.add(MappingInfoForFunction(Out));

  // Output assembly language to the .s file.  Assembly emission is split into
  // two parts: Function output and Global value output.  This is because
  // function output is pipelined with all of the rest of code generation stuff,
  // allowing machine code representations for functions to be free'd after the
  // function has been emitted.
  //
  PM.add(getFunctionAsmPrinterPass(Out));
  PM.add(createMachineCodeDestructionPass()); // Free stuff no longer needed

  // Emit Module level assembly after all of the functions have been processed.
  PM.add(getModuleAsmPrinterPass(Out));

  // Emit bytecode to the assembly file into its special section next
  PM.add(getEmitBytecodeToAsmPass(Out));
  PM.add(getFunctionInfo(Out));
  return false;
}
<commit_msg>* Frame & const pool info is no longer directly in MachineFunction<commit_after>//===-- Sparc.cpp - General implementation file for the Sparc Target ------===//
//
// This file contains the code for the Sparc Target that does not fit in any of
// the other files in this directory.
//
//===----------------------------------------------------------------------===//

#include "SparcInternals.h"
#include "llvm/Target/TargetMachineImpls.h"
#include "llvm/Function.h"
#include "llvm/PassManager.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineFunctionInfo.h"
#include "llvm/CodeGen/PreSelection.h"
#include "llvm/CodeGen/StackSlots.h"
#include "llvm/CodeGen/PeepholeOpts.h"
#include "llvm/CodeGen/InstrSelection.h"
#include "llvm/CodeGen/InstrScheduling.h"
#include "llvm/CodeGen/RegisterAllocation.h"
#include "llvm/CodeGen/MachineCodeForInstruction.h"
#include "llvm/Reoptimizer/Mapping/MappingInfo.h"
#include "llvm/Reoptimizer/Mapping/FInfo.h"
#include "Support/CommandLine.h"
using std::cerr;

static const unsigned ImplicitRegUseList[] = { 0 }; /* not used yet */
// Build the MachineInstruction Description Array...
const MachineInstrDescriptor SparcMachineInstrDesc[] = {
#define I(ENUM, OPCODESTRING, NUMOPERANDS, RESULTPOS, MAXIMM, IMMSE, \
          NUMDELAYSLOTS, LATENCY, SCHEDCLASS, INSTFLAGS)             \
  { OPCODESTRING, NUMOPERANDS, RESULTPOS, MAXIMM, IMMSE,             \
          NUMDELAYSLOTS, LATENCY, SCHEDCLASS, INSTFLAGS, 0,          \
          ImplicitRegUseList, ImplicitRegUseList },
#include "SparcInstr.def"
};

//---------------------------------------------------------------------------
// Command line options to control choice of code generation passes.
//---------------------------------------------------------------------------

static cl::opt<bool> DisablePreSelect("nopreselect",
                                      cl::desc("Disable preselection pass"));

static cl::opt<bool> DisableSched("nosched",
                                  cl::desc("Disable local scheduling pass"));

static cl::opt<bool> DisablePeephole("nopeephole",
                                cl::desc("Disable peephole optimization pass"));

//----------------------------------------------------------------------------
// allocateSparcTargetMachine - Allocate and return a subclass of TargetMachine
// that implements the Sparc backend. (the llvm/CodeGen/Sparc.h interface)
//----------------------------------------------------------------------------

TargetMachine *allocateSparcTargetMachine() { return new UltraSparc(); }

//---------------------------------------------------------------------------
// class UltraSparcFrameInfo
//
//   Interface to stack frame layout info for the UltraSPARC.
//   Starting offsets for each area of the stack frame are aligned at
//   a multiple of getStackFrameSizeAlignment().
//---------------------------------------------------------------------------

int
UltraSparcFrameInfo::getFirstAutomaticVarOffset(MachineFunction& ,
                                                bool& pos) const
{
  pos = false;                          // static stack area grows downwards
  return StaticAreaOffsetFromFP;
}

int
UltraSparcFrameInfo::getRegSpillAreaOffset(MachineFunction& mcInfo,
                                           bool& pos) const
{
  // ensure no more auto vars are added
  mcInfo.getInfo()->freezeAutomaticVarsArea();

  pos = false;                          // static stack area grows downwards
  unsigned autoVarsSize = mcInfo.getInfo()->getAutomaticVarsSize();
  return StaticAreaOffsetFromFP - autoVarsSize;
}

int
UltraSparcFrameInfo::getTmpAreaOffset(MachineFunction& mcInfo,
                                      bool& pos) const
{
  MachineFunctionInfo *MFI = mcInfo.getInfo();
  MFI->freezeAutomaticVarsArea();     // ensure no more auto vars are added
  MFI->freezeSpillsArea();            // ensure no more spill slots are added

  pos = false;                          // static stack area grows downwards
  unsigned autoVarsSize = MFI->getAutomaticVarsSize();
  unsigned spillAreaSize = MFI->getRegSpillsSize();
  int offset = autoVarsSize + spillAreaSize;
  return StaticAreaOffsetFromFP - offset;
}

int
UltraSparcFrameInfo::getDynamicAreaOffset(MachineFunction& mcInfo,
                                          bool& pos) const
{
  // Dynamic stack area grows downwards starting at top of opt-args area.
  // The opt-args, required-args, and register-save areas are empty except
  // during calls and traps, so they are shifted downwards on each
  // dynamic-size alloca.
  pos = false;
  unsigned optArgsSize = mcInfo.getInfo()->getMaxOptionalArgsSize();
  if (int extra = optArgsSize % getStackFrameSizeAlignment())
    optArgsSize += (getStackFrameSizeAlignment() - extra);
  int offset = optArgsSize + FirstOptionalOutgoingArgOffsetFromSP;
  assert((offset - OFFSET) % getStackFrameSizeAlignment() == 0);
  return offset;
}

//---------------------------------------------------------------------------
// class UltraSparcMachine
//
// Purpose:
//   Primary interface to machine description for the UltraSPARC.
//   Primarily just initializes machine-dependent parameters in
//   class TargetMachine, and creates machine-dependent subclasses
//   for classes such as MachineInstrInfo.
//
//---------------------------------------------------------------------------

UltraSparc::UltraSparc()
  : TargetMachine("UltraSparc-Native", false, 4),
    schedInfo(*this),
    regInfo(*this),
    frameInfo(*this),
    cacheInfo(*this),
    optInfo(*this) {
}

// addPassesToEmitAssembly - This method controls the entire code generation
// process for the ultra sparc.
//
bool UltraSparc::addPassesToEmitAssembly(PassManager &PM, std::ostream &Out)
{
  // Construct and initialize the MachineFunction object for this fn.
  PM.add(createMachineCodeConstructionPass(*this));

  //Insert empty stackslots in the stack frame of each function
  //so %fp+offset-8 and %fp+offset-16 are empty slots now!
  PM.add(createStackSlotsPass(*this));

  // Specialize LLVM code for this target machine and then
  // run basic dataflow optimizations on LLVM code.
  if (!DisablePreSelect)
    {
      PM.add(createPreSelectionPass(*this));
      PM.add(createReassociatePass());
      PM.add(createLICMPass());
      PM.add(createGCSEPass());
    }

  PM.add(createInstructionSelectionPass(*this));

  if (!DisableSched)
    PM.add(createInstructionSchedulingWithSSAPass(*this));

  PM.add(getRegisterAllocator(*this));

  PM.add(getPrologEpilogInsertionPass());

  if (!DisablePeephole)
    PM.add(createPeepholeOptsPass(*this));

  PM.add(MappingInfoForFunction(Out));

  // Output assembly language to the .s file.  Assembly emission is split into
  // two parts: Function output and Global value output.  This is because
  // function output is pipelined with all of the rest of code generation stuff,
  // allowing machine code representations for functions to be free'd after the
  // function has been emitted.
  //
  PM.add(getFunctionAsmPrinterPass(Out));
  PM.add(createMachineCodeDestructionPass()); // Free stuff no longer needed

  // Emit Module level assembly after all of the functions have been processed.
  PM.add(getModuleAsmPrinterPass(Out));

  // Emit bytecode to the assembly file into its special section next
  PM.add(getEmitBytecodeToAsmPass(Out));
  PM.add(getFunctionInfo(Out));
  return false;
}
<|endoftext|>


<commit_before>//===- BreakCriticalEdges.cpp - Critical Edge Elimination Pass ------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// BreakCriticalEdges pass - Break all of the critical edges in the CFG by
// inserting a dummy basic block.  This pass may be "required" by passes that
// cannot deal with critical edges.  For this usage, the structure type is
// forward declared.  This pass obviously invalidates the CFG, but can update
// forward dominator (set, immediate dominators, tree, and frontier)
// information.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "break-crit-edges"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/Analysis/Dominators.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Function.h"
#include "llvm/Instructions.h"
#include "llvm/Type.h"
#include "llvm/Support/CFG.h"
#include "llvm/Support/Compiler.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
using namespace llvm;

STATISTIC(NumBroken, "Number of blocks inserted");

namespace {
  struct VISIBILITY_HIDDEN BreakCriticalEdges : public FunctionPass {
    virtual bool runOnFunction(Function &F);

    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
      AU.addPreserved<ETForest>();
      AU.addPreserved<DominatorSet>();
      AU.addPreserved<ImmediateDominators>();
      AU.addPreserved<DominatorTree>();
      AU.addPreserved<DominanceFrontier>();
      AU.addPreserved<LoopInfo>();

      // No loop canonicalization guarantees are broken by this pass.
      AU.addPreservedID(LoopSimplifyID);
    }
  };

  RegisterPass<BreakCriticalEdges> X("break-crit-edges",
                                    "Break critical edges in CFG");
}

// Publically exposed interface to pass...
const PassInfo *llvm::BreakCriticalEdgesID = X.getPassInfo();
FunctionPass *llvm::createBreakCriticalEdgesPass() {
  return new BreakCriticalEdges();
}

// runOnFunction - Loop over all of the edges in the CFG, breaking critical
// edges as they are found.
//
bool BreakCriticalEdges::runOnFunction(Function &F) {
  bool Changed = false;
  for (Function::iterator I = F.begin(), E = F.end(); I != E; ++I) {
    TerminatorInst *TI = I->getTerminator();
    if (TI->getNumSuccessors() > 1)
      for (unsigned i = 0, e = TI->getNumSuccessors(); i != e; ++i)
        if (SplitCriticalEdge(TI, i, this)) {
          ++NumBroken;
          Changed = true;
        }
  }

  return Changed;
}

//===----------------------------------------------------------------------===//
//    Implementation of the external critical edge manipulation functions
//===----------------------------------------------------------------------===//

// isCriticalEdge - Return true if the specified edge is a critical edge.
// Critical edges are edges from a block with multiple successors to a block
// with multiple predecessors.
//
bool llvm::isCriticalEdge(const TerminatorInst *TI, unsigned SuccNum,
                          bool AllowIdenticalEdges) {
  assert(SuccNum < TI->getNumSuccessors() && "Illegal edge specification!");
  if (TI->getNumSuccessors() == 1) return false;

  const BasicBlock *Dest = TI->getSuccessor(SuccNum);
  pred_const_iterator I = pred_begin(Dest), E = pred_end(Dest);

  // If there is more than one predecessor, this is a critical edge...
  assert(I != E && "No preds, but we have an edge to the block?");
  const BasicBlock *FirstPred = *I;
  ++I;        // Skip one edge due to the incoming arc from TI.
  if (!AllowIdenticalEdges)
    return I != E;

  // If AllowIdenticalEdges is true, then we allow this edge to be considered
  // non-critical iff all preds come from TI's block.
  for (; I != E; ++I)
    if (*I != FirstPred) return true;
  return false;
}

// SplitCriticalEdge - If this edge is a critical edge, insert a new node to
// split the critical edge.  This will update DominatorSet, ImmediateDominator,
// DominatorTree, and DominatorFrontier information if it is available, thus
// calling this pass will not invalidate any of them.  This returns true if
// the edge was split, false otherwise.  This ensures that all edges to that
// dest go to one block instead of each going to a different block.
//
bool llvm::SplitCriticalEdge(TerminatorInst *TI, unsigned SuccNum, Pass *P,
                             bool MergeIdenticalEdges) {
  if (!isCriticalEdge(TI, SuccNum, MergeIdenticalEdges)) return false;
  BasicBlock *TIBB = TI->getParent();
  BasicBlock *DestBB = TI->getSuccessor(SuccNum);

  // Create a new basic block, linking it into the CFG.
  BasicBlock *NewBB = new BasicBlock(TIBB->getName() + "." +
                                     DestBB->getName() + "_crit_edge");
  // Create our unconditional branch...
  new BranchInst(DestBB, NewBB);

  // Branch to the new block, breaking the edge.
  TI->setSuccessor(SuccNum, NewBB);

  // Insert the block into the function... right after the block TI lives in.
  Function &F = *TIBB->getParent();
  F.getBasicBlockList().insert(TIBB->getNext(), NewBB);

  // If there are any PHI nodes in DestBB, we need to update them so that they
  // merge incoming values from NewBB instead of from TIBB.
  //
  for (BasicBlock::iterator I = DestBB->begin(); isa<PHINode>(I); ++I) {
    PHINode *PN = cast<PHINode>(I);
    // We no longer enter through TIBB, now we come in through NewBB.  Revector
    // exactly one entry in the PHI node that used to come from TIBB to come
    // from NewBB.
    int BBIdx = PN->getBasicBlockIndex(TIBB);
    PN->setIncomingBlock(BBIdx, NewBB);
  }

  // If there are any other edges from TIBB to DestBB, update those to go
  // through the split block, making those edges non-critical as well (and
  // reducing the number of phi entries in the DestBB if relevant).
  if (MergeIdenticalEdges) {
    for (unsigned i = SuccNum+1, e = TI->getNumSuccessors(); i != e; ++i) {
      if (TI->getSuccessor(i) != DestBB) continue;

      // Remove an entry for TIBB from DestBB phi nodes.
      DestBB->removePredecessor(TIBB);

      // We found another edge to DestBB, go to NewBB instead.
      TI->setSuccessor(i, NewBB);
    }
  }

  // If we don't have a pass object, we can't update anything...
  if (P == 0) return true;

  // Now update analysis information.  Since the only predecessor of NewBB is
  // the TIBB, TIBB clearly dominates NewBB.  TIBB usually doesn't dominate
  // anything, as there are other successors of DestBB.  However, if all other
  // predecessors of DestBB are already dominated by DestBB (e.g. DestBB is a
  // loop header) then NewBB dominates DestBB.
  SmallVector<BasicBlock*, 8> OtherPreds;

  for (pred_iterator I = pred_begin(DestBB), E = pred_end(DestBB); I != E; ++I)
    if (*I != NewBB)
      OtherPreds.push_back(*I);

  // NewBBDominatesDestBB is valid if OtherPreds is empty, otherwise it isn't
  // yet computed.
  bool NewBBDominatesDestBB = true;

  // Should we update DominatorSet information?
  if (DominatorSet *DS = P->getAnalysisToUpdate<DominatorSet>()) {
    // The blocks that dominate the new one are the blocks that dominate TIBB
    // plus the new block itself.
    DominatorSet::DomSetType DomSet = DS->getDominators(TIBB);
    DomSet.insert(NewBB);  // A block always dominates itself.
    DS->addBasicBlock(NewBB, DomSet);

    // If NewBBDominatesDestBB hasn't been computed yet, do so with DS.
    if (!OtherPreds.empty()) {
      while (!OtherPreds.empty() && NewBBDominatesDestBB) {
        NewBBDominatesDestBB = DS->dominates(DestBB, OtherPreds.back());
        OtherPreds.pop_back();
      }
      OtherPreds.clear();
    }

    // If NewBBDominatesDestBB, then NewBB dominates DestBB, otherwise it
    // doesn't dominate anything.  If NewBB does dominates DestBB, then it
    // dominates everything that DestBB dominates.
    if (NewBBDominatesDestBB) {
      for (DominatorSet::iterator I = DS->begin(), E = DS->end(); I != E; ++I)
        if (I->second.count(DestBB))
          I->second.insert(NewBB);
    }
  }

  // Should we update ImmediateDominator information?
  if (ImmediateDominators *ID = P->getAnalysisToUpdate<ImmediateDominators>()) {
    // TIBB is the new immediate dominator for NewBB.
    ID->addNewBlock(NewBB, TIBB);

    // If NewBBDominatesDestBB hasn't been computed yet, do so with ID.
    if (!OtherPreds.empty()) {
      while (!OtherPreds.empty() && NewBBDominatesDestBB) {
        NewBBDominatesDestBB = ID->dominates(DestBB, OtherPreds.back());
        OtherPreds.pop_back();
      }
      OtherPreds.clear();
    }

    // If NewBBDominatesDestBB, then NewBB dominates DestBB, otherwise it
    // doesn't dominate anything.
    if (NewBBDominatesDestBB)
      ID->setImmediateDominator(DestBB, NewBB);
  }

  // Update the forest?
  if (ETForest *EF = P->getAnalysisToUpdate<ETForest>()) {
    // NewBB is dominated by TIBB.
    EF->addNewBlock(NewBB, TIBB);

    // If NewBBDominatesDestBB hasn't been computed yet, do so with EF.
    if (!OtherPreds.empty()) {
      while (!OtherPreds.empty() && NewBBDominatesDestBB) {
        NewBBDominatesDestBB = EF->dominates(DestBB, OtherPreds.back());
        OtherPreds.pop_back();
      }
      OtherPreds.clear();
    }

    // If NewBBDominatesDestBB, then NewBB dominates DestBB, otherwise it
    // doesn't dominate anything.
    if (NewBBDominatesDestBB)
      EF->setImmediateDominator(DestBB, NewBB);
  }

  // Should we update DominatorTree information?
  if (DominatorTree *DT = P->getAnalysisToUpdate<DominatorTree>()) {
    DominatorTree::Node *TINode = DT->getNode(TIBB);

    // The new block is not the immediate dominator for any other nodes, but
    // TINode is the immediate dominator for the new node.
    //
    if (TINode) {       // Don't break unreachable code!
      DominatorTree::Node *NewBBNode = DT->createNewNode(NewBB, TINode);
      DominatorTree::Node *DestBBNode = 0;

      // If NewBBDominatesDestBB hasn't been computed yet, do so with DT.
      if (!OtherPreds.empty()) {
        DestBBNode = DT->getNode(DestBB);
        while (!OtherPreds.empty() && NewBBDominatesDestBB) {
          if (DominatorTree::Node *OPNode = DT->getNode(OtherPreds.back()))
            NewBBDominatesDestBB = DestBBNode->dominates(OPNode);
          OtherPreds.pop_back();
        }
        OtherPreds.clear();
      }

      // If NewBBDominatesDestBB, then NewBB dominates DestBB, otherwise it
      // doesn't dominate anything.
      if (NewBBDominatesDestBB) {
        if (!DestBBNode) DestBBNode = DT->getNode(DestBB);
        DT->changeImmediateDominator(DestBBNode, NewBBNode);
      }
    }
  }

  // Should we update DominanceFrontier information?
  if (DominanceFrontier *DF = P->getAnalysisToUpdate<DominanceFrontier>()) {
    // If NewBBDominatesDestBB hasn't been computed yet, do so with DF.
    if (!OtherPreds.empty()) {
      // FIXME: IMPLEMENT THIS!
      assert(0 && "Requiring domfrontiers but not idom/domtree/domset."
             " not implemented yet!");
    }

    // Since the new block is dominated by its only predecessor TIBB,
    // it cannot be in any block's dominance frontier.  If NewBB dominates
    // DestBB, its dominance frontier is the same as DestBB's, otherwise it is
    // just {DestBB}.
    DominanceFrontier::DomSetType NewDFSet;
    if (NewBBDominatesDestBB) {
      DominanceFrontier::iterator I = DF->find(DestBB);
      if (I != DF->end())
        DF->addBasicBlock(NewBB, I->second);
      else
        DF->addBasicBlock(NewBB, DominanceFrontier::DomSetType());
    } else {
      DominanceFrontier::DomSetType NewDFSet;
      NewDFSet.insert(DestBB);
      DF->addBasicBlock(NewBB, NewDFSet);
    }
  }

  // Update LoopInfo if it is around.
  if (LoopInfo *LI = P->getAnalysisToUpdate<LoopInfo>()) {
    // If one or the other blocks were not in a loop, the new block is not
    // either, and thus LI doesn't need to be updated.
    if (Loop *TIL = LI->getLoopFor(TIBB))
      if (Loop *DestLoop = LI->getLoopFor(DestBB)) {
        if (TIL == DestLoop) {
          // Both in the same loop, the NewBB joins loop.
          DestLoop->addBasicBlockToLoop(NewBB, *LI);
        } else if (TIL->contains(DestLoop->getHeader())) {
          // Edge from an outer loop to an inner loop.  Add to the outer loop.
          TIL->addBasicBlockToLoop(NewBB, *LI);
        } else if (DestLoop->contains(TIL->getHeader())) {
          // Edge from an inner loop to an outer loop.  Add to the outer loop.
          DestLoop->addBasicBlockToLoop(NewBB, *LI);
        } else {
          // Edge from two loops with no containment relation.  Because these
          // are natural loops, we know that the destination block must be the
          // header of its loop (adding a branch into a loop elsewhere would
          // create an irreducible loop).
          assert(DestLoop->getHeader() == DestBB &&
                 "Should not create irreducible loops!");
          if (Loop *P = DestLoop->getParentLoop())
            P->addBasicBlockToLoop(NewBB, *LI);
        }
      }
  }
  return true;
}
<commit_msg>Fix PR1110 and Analysis/Dominators/2007-01-14-BreakCritEdges.ll by being more careful about unreachable code when updating dominator info.<commit_after>//===- BreakCriticalEdges.cpp - Critical Edge Elimination Pass ------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// BreakCriticalEdges pass - Break all of the critical edges in the CFG by
// inserting a dummy basic block.  This pass may be "required" by passes that
// cannot deal with critical edges.  For this usage, the structure type is
// forward declared.  This pass obviously invalidates the CFG, but can update
// forward dominator (set, immediate dominators, tree, and frontier)
// information.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "break-crit-edges"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/Analysis/Dominators.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Function.h"
#include "llvm/Instructions.h"
#include "llvm/Type.h"
#include "llvm/Support/CFG.h"
#include "llvm/Support/Compiler.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
using namespace llvm;

STATISTIC(NumBroken, "Number of blocks inserted");

namespace {
  struct VISIBILITY_HIDDEN BreakCriticalEdges : public FunctionPass {
    virtual bool runOnFunction(Function &F);

    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
      AU.addPreserved<ETForest>();
      AU.addPreserved<DominatorSet>();
      AU.addPreserved<ImmediateDominators>();
      AU.addPreserved<DominatorTree>();
      AU.addPreserved<DominanceFrontier>();
      AU.addPreserved<LoopInfo>();

      // No loop canonicalization guarantees are broken by this pass.
      AU.addPreservedID(LoopSimplifyID);
    }
  };

  RegisterPass<BreakCriticalEdges> X("break-crit-edges",
                                    "Break critical edges in CFG");
}

// Publically exposed interface to pass...
const PassInfo *llvm::BreakCriticalEdgesID = X.getPassInfo();
FunctionPass *llvm::createBreakCriticalEdgesPass() {
  return new BreakCriticalEdges();
}

// runOnFunction - Loop over all of the edges in the CFG, breaking critical
// edges as they are found.
//
bool BreakCriticalEdges::runOnFunction(Function &F) {
  bool Changed = false;
  for (Function::iterator I = F.begin(), E = F.end(); I != E; ++I) {
    TerminatorInst *TI = I->getTerminator();
    if (TI->getNumSuccessors() > 1)
      for (unsigned i = 0, e = TI->getNumSuccessors(); i != e; ++i)
        if (SplitCriticalEdge(TI, i, this)) {
          ++NumBroken;
          Changed = true;
        }
  }

  return Changed;
}

//===----------------------------------------------------------------------===//
//    Implementation of the external critical edge manipulation functions
//===----------------------------------------------------------------------===//

// isCriticalEdge - Return true if the specified edge is a critical edge.
// Critical edges are edges from a block with multiple successors to a block
// with multiple predecessors.
//
bool llvm::isCriticalEdge(const TerminatorInst *TI, unsigned SuccNum,
                          bool AllowIdenticalEdges) {
  assert(SuccNum < TI->getNumSuccessors() && "Illegal edge specification!");
  if (TI->getNumSuccessors() == 1) return false;

  const BasicBlock *Dest = TI->getSuccessor(SuccNum);
  pred_const_iterator I = pred_begin(Dest), E = pred_end(Dest);

  // If there is more than one predecessor, this is a critical edge...
  assert(I != E && "No preds, but we have an edge to the block?");
  const BasicBlock *FirstPred = *I;
  ++I;        // Skip one edge due to the incoming arc from TI.
  if (!AllowIdenticalEdges)
    return I != E;

  // If AllowIdenticalEdges is true, then we allow this edge to be considered
  // non-critical iff all preds come from TI's block.
  for (; I != E; ++I)
    if (*I != FirstPred) return true;
  return false;
}

// SplitCriticalEdge - If this edge is a critical edge, insert a new node to
// split the critical edge.  This will update DominatorSet, ImmediateDominator,
// DominatorTree, and DominatorFrontier information if it is available, thus
// calling this pass will not invalidate any of them.  This returns true if
// the edge was split, false otherwise.  This ensures that all edges to that
// dest go to one block instead of each going to a different block.
//
bool llvm::SplitCriticalEdge(TerminatorInst *TI, unsigned SuccNum, Pass *P,
                             bool MergeIdenticalEdges) {
  if (!isCriticalEdge(TI, SuccNum, MergeIdenticalEdges)) return false;
  BasicBlock *TIBB = TI->getParent();
  BasicBlock *DestBB = TI->getSuccessor(SuccNum);

  // Create a new basic block, linking it into the CFG.
  BasicBlock *NewBB = new BasicBlock(TIBB->getName() + "." +
                                     DestBB->getName() + "_crit_edge");
  // Create our unconditional branch...
  new BranchInst(DestBB, NewBB);

  // Branch to the new block, breaking the edge.
  TI->setSuccessor(SuccNum, NewBB);

  // Insert the block into the function... right after the block TI lives in.
  Function &F = *TIBB->getParent();
  F.getBasicBlockList().insert(TIBB->getNext(), NewBB);

  // If there are any PHI nodes in DestBB, we need to update them so that they
  // merge incoming values from NewBB instead of from TIBB.
  //
  for (BasicBlock::iterator I = DestBB->begin(); isa<PHINode>(I); ++I) {
    PHINode *PN = cast<PHINode>(I);
    // We no longer enter through TIBB, now we come in through NewBB.  Revector
    // exactly one entry in the PHI node that used to come from TIBB to come
    // from NewBB.
    int BBIdx = PN->getBasicBlockIndex(TIBB);
    PN->setIncomingBlock(BBIdx, NewBB);
  }

  // If there are any other edges from TIBB to DestBB, update those to go
  // through the split block, making those edges non-critical as well (and
  // reducing the number of phi entries in the DestBB if relevant).
  if (MergeIdenticalEdges) {
    for (unsigned i = SuccNum+1, e = TI->getNumSuccessors(); i != e; ++i) {
      if (TI->getSuccessor(i) != DestBB) continue;

      // Remove an entry for TIBB from DestBB phi nodes.
      DestBB->removePredecessor(TIBB);

      // We found another edge to DestBB, go to NewBB instead.
      TI->setSuccessor(i, NewBB);
    }
  }

  // If we don't have a pass object, we can't update anything...
  if (P == 0) return true;

  // Now update analysis information.  Since the only predecessor of NewBB is
  // the TIBB, TIBB clearly dominates NewBB.  TIBB usually doesn't dominate
  // anything, as there are other successors of DestBB.  However, if all other
  // predecessors of DestBB are already dominated by DestBB (e.g. DestBB is a
  // loop header) then NewBB dominates DestBB.
  SmallVector<BasicBlock*, 8> OtherPreds;

  for (pred_iterator I = pred_begin(DestBB), E = pred_end(DestBB); I != E; ++I)
    if (*I != NewBB)
      OtherPreds.push_back(*I);

  // NewBBDominatesDestBB is valid if OtherPreds is empty, otherwise it isn't
  // yet computed.
  bool NewBBDominatesDestBB = true;

  // Should we update DominatorSet information?
  if (DominatorSet *DS = P->getAnalysisToUpdate<DominatorSet>()) {
    DominatorSet::iterator DSI = DS->find(TIBB);
    if (DSI != DS->end()) {    // TIBB is reachable?
      // The blocks that dominate the new one are the blocks that dominate TIBB
      // plus the new block itself.
      DominatorSet::DomSetType DomSet = DSI->second;  // Copy domset.
      DomSet.insert(NewBB);  // A block always dominates itself.
      DS->addBasicBlock(NewBB, DomSet);

      // If NewBBDominatesDestBB hasn't been computed yet, do so with DS.
      if (!OtherPreds.empty()) {
        while (!OtherPreds.empty() && NewBBDominatesDestBB) {
          NewBBDominatesDestBB = DS->dominates(DestBB, OtherPreds.back());
          OtherPreds.pop_back();
        }
        OtherPreds.clear();
      }

      // If NewBBDominatesDestBB, then NewBB dominates DestBB, otherwise it
      // doesn't dominate anything.  If NewBB does dominates DestBB, then it
      // dominates everything that DestBB dominates.
      if (NewBBDominatesDestBB) {
        for (DominatorSet::iterator I = DS->begin(), E = DS->end(); I != E; ++I)
          if (I->second.count(DestBB))
            I->second.insert(NewBB);
      }
    }
  }

  // Should we update ImmediateDominator information?
  if (ImmediateDominators *ID = P->getAnalysisToUpdate<ImmediateDominators>()) {
    if (ID->get(TIBB)) {  // Only do this if TIBB is reachable.
      // TIBB is the new immediate dominator for NewBB.
      ID->addNewBlock(NewBB, TIBB);

      // If NewBBDominatesDestBB hasn't been computed yet, do so with ID.
      if (!OtherPreds.empty()) {
        while (!OtherPreds.empty() && NewBBDominatesDestBB) {
          NewBBDominatesDestBB = ID->dominates(DestBB, OtherPreds.back());
          OtherPreds.pop_back();
        }
        OtherPreds.clear();
      }

      // If NewBBDominatesDestBB, then NewBB dominates DestBB, otherwise it
      // doesn't dominate anything.
      if (NewBBDominatesDestBB)
        ID->setImmediateDominator(DestBB, NewBB);
    }
  }

  // Update the forest?
  if (ETForest *EF = P->getAnalysisToUpdate<ETForest>()) {
    // NewBB is dominated by TIBB.
    EF->addNewBlock(NewBB, TIBB);

    // If NewBBDominatesDestBB hasn't been computed yet, do so with EF.
    if (!OtherPreds.empty()) {
      while (!OtherPreds.empty() && NewBBDominatesDestBB) {
        NewBBDominatesDestBB = EF->dominates(DestBB, OtherPreds.back());
        OtherPreds.pop_back();
      }
      OtherPreds.clear();
    }

    // If NewBBDominatesDestBB, then NewBB dominates DestBB, otherwise it
    // doesn't dominate anything.
    if (NewBBDominatesDestBB)
      EF->setImmediateDominator(DestBB, NewBB);
  }

  // Should we update DominatorTree information?
  if (DominatorTree *DT = P->getAnalysisToUpdate<DominatorTree>()) {
    DominatorTree::Node *TINode = DT->getNode(TIBB);

    // The new block is not the immediate dominator for any other nodes, but
    // TINode is the immediate dominator for the new node.
    //
    if (TINode) {       // Don't break unreachable code!
      DominatorTree::Node *NewBBNode = DT->createNewNode(NewBB, TINode);
      DominatorTree::Node *DestBBNode = 0;

      // If NewBBDominatesDestBB hasn't been computed yet, do so with DT.
      if (!OtherPreds.empty()) {
        DestBBNode = DT->getNode(DestBB);
        while (!OtherPreds.empty() && NewBBDominatesDestBB) {
          if (DominatorTree::Node *OPNode = DT->getNode(OtherPreds.back()))
            NewBBDominatesDestBB = DestBBNode->dominates(OPNode);
          OtherPreds.pop_back();
        }
        OtherPreds.clear();
      }

      // If NewBBDominatesDestBB, then NewBB dominates DestBB, otherwise it
      // doesn't dominate anything.
      if (NewBBDominatesDestBB) {
        if (!DestBBNode) DestBBNode = DT->getNode(DestBB);
        DT->changeImmediateDominator(DestBBNode, NewBBNode);
      }
    }
  }

  // Should we update DominanceFrontier information?
  if (DominanceFrontier *DF = P->getAnalysisToUpdate<DominanceFrontier>()) {
    // If NewBBDominatesDestBB hasn't been computed yet, do so with DF.
    if (!OtherPreds.empty()) {
      // FIXME: IMPLEMENT THIS!
      assert(0 && "Requiring domfrontiers but not idom/domtree/domset."
             " not implemented yet!");
    }

    // Since the new block is dominated by its only predecessor TIBB,
    // it cannot be in any block's dominance frontier.  If NewBB dominates
    // DestBB, its dominance frontier is the same as DestBB's, otherwise it is
    // just {DestBB}.
    DominanceFrontier::DomSetType NewDFSet;
    if (NewBBDominatesDestBB) {
      DominanceFrontier::iterator I = DF->find(DestBB);
      if (I != DF->end())
        DF->addBasicBlock(NewBB, I->second);
      else
        DF->addBasicBlock(NewBB, DominanceFrontier::DomSetType());
    } else {
      DominanceFrontier::DomSetType NewDFSet;
      NewDFSet.insert(DestBB);
      DF->addBasicBlock(NewBB, NewDFSet);
    }
  }

  // Update LoopInfo if it is around.
  if (LoopInfo *LI = P->getAnalysisToUpdate<LoopInfo>()) {
    // If one or the other blocks were not in a loop, the new block is not
    // either, and thus LI doesn't need to be updated.
    if (Loop *TIL = LI->getLoopFor(TIBB))
      if (Loop *DestLoop = LI->getLoopFor(DestBB)) {
        if (TIL == DestLoop) {
          // Both in the same loop, the NewBB joins loop.
          DestLoop->addBasicBlockToLoop(NewBB, *LI);
        } else if (TIL->contains(DestLoop->getHeader())) {
          // Edge from an outer loop to an inner loop.  Add to the outer loop.
          TIL->addBasicBlockToLoop(NewBB, *LI);
        } else if (DestLoop->contains(TIL->getHeader())) {
          // Edge from an inner loop to an outer loop.  Add to the outer loop.
          DestLoop->addBasicBlockToLoop(NewBB, *LI);
        } else {
          // Edge from two loops with no containment relation.  Because these
          // are natural loops, we know that the destination block must be the
          // header of its loop (adding a branch into a loop elsewhere would
          // create an irreducible loop).
          assert(DestLoop->getHeader() == DestBB &&
                 "Should not create irreducible loops!");
          if (Loop *P = DestLoop->getParentLoop())
            P->addBasicBlockToLoop(NewBB, *LI);
        }
      }
  }
  return true;
}
<|endoftext|>


<commit_before>#include "mfem.hpp"
#include <fstream>
#include <iostream>
#include <memory>

using namespace std;
using namespace mfem;

void E_exact(const Vector &xvec, Vector &E)
{
   double x=xvec[0], y=xvec[1];
   constexpr double pi = M_PI;

   E[0] = sin(2*pi*x)*sin(4*pi*y);
   E[1] = sin(4*pi*x)*sin(2*pi*y);
}

void f_exact(const Vector &xvec, Vector &f)
{
   double x=xvec[0], y=xvec[1];
   constexpr double pi = M_PI;
   constexpr double pi2 = M_PI*M_PI;

   f[0] = 8*pi2*cos(4*pi*x)*cos(2*pi*y) + (1 + 16*pi2)*sin(2*pi*x)*sin(4*pi*y);
   f[1] = 8*pi2*cos(2*pi*x)*cos(4*pi*y) + (1 + 16*pi2)*sin(4*pi*x)*sin(2*pi*y);
}

int main(int argc, char *argv[])
{
   // 1. Parse command-line options.
   const char *mesh_file = "../data/star.mesh";
   int ref_levels = 0;
   int order = 3;
   const char *fe = "n";

   OptionsParser args(argc, argv);
   args.AddOption(&mesh_file, "-m", "--mesh", "Mesh file to use.");
   args.AddOption(&ref_levels, "-r", "--refine", "Uniform refinements.");
   args.AddOption(&order, "-o", "--order", "Polynomial degree.");
   args.AddOption(&fe, "-fe", "--fe-type", "FE type. n for Hcurl, r for Hdiv");
   args.ParseCheck();

   bool ND;
   if (string(fe) == "n") { ND = true; }
   else if (string(fe) == "r") { ND = false; }
   else { MFEM_ABORT("Bad FE type. Must be 'n' or 'r'."); }

   Mesh mesh(mesh_file, 1, 1);
   int dim = mesh.Dimension();
   for (int l = 0; l < ref_levels; l++) { mesh.UniformRefinement(); }

   int b1 = BasisType::GaussLobatto, b2 = BasisType::Integrated;
   unique_ptr<FiniteElementCollection> fec;
   if (ND) { fec.reset(new ND_FECollection(order, dim, b1, b2)); }
   else { fec.reset(new RT_FECollection(order-1, dim, b1, b2)); }

   FiniteElementSpace fes(&mesh, fec.get());
   Array<int> ess_dofs_ho;
   fes.GetBoundaryTrueDofs(ess_dofs_ho);

   BilinearForm a_ho(&fes);
   a_ho.AddDomainIntegrator(new VectorFEMassIntegrator);
   if (ND) { a_ho.AddDomainIntegrator(new CurlCurlIntegrator); }
   else { a_ho.AddDomainIntegrator(new DivDivIntegrator); }
   a_ho.SetAssemblyLevel(AssemblyLevel::PARTIAL);
   a_ho.Assemble();

   LinearForm b(&fes);
   VectorFunctionCoefficient f_coeff(dim, f_exact);
   b.AddDomainIntegrator(new VectorFEDomainLFIntegrator(f_coeff));
   b.Assemble();

   GridFunction x(&fes);
   x = 0.0;

   Vector X, B;
   OperatorHandle A;
   a_ho.FormLinearSystem(ess_dofs_ho, x, b, A, X, B);

   LORSolver<UMFPackSolver> lor_solver(a_ho, ess_dofs_ho);

   CGSolver cg;
   cg.SetAbsTol(0.0);
   cg.SetRelTol(1e-12);
   cg.SetMaxIter(100);
   cg.SetPrintLevel(1);
   cg.SetOperator(*A);
   cg.SetPreconditioner(lor_solver);
   cg.Mult(B, X);
   a_ho.RecoverFEMSolution(X, b, x);

   VectorFunctionCoefficient exact_coeff(dim, E_exact);
   double er = x.ComputeL2Error(exact_coeff);
   std::cout << "L^2 error: " << er << '\n';

   ParaViewDataCollection dc("LOR", &mesh);
   dc.SetPrefixPath("ParaView");
   dc.SetHighOrderOutput(true);
   dc.SetLevelsOfDetail(order);
   dc.RegisterField("u", &x);
   dc.SetCycle(0);
   dc.SetTime(0.0);
   dc.Save();

   return 0;
}
<commit_msg>Adding two 3D exact solutions on the unit cube, with homogeneous BC.<commit_after>#include "mfem.hpp"
#include <fstream>
#include <iostream>
#include <memory>

using namespace std;
using namespace mfem;

int exact_sol = 0;
int dim = 0;

void E_exact(const Vector &xvec, Vector &E)
{
   double x=xvec[0], y=xvec[1], z=xvec[2];
   constexpr double pi = M_PI;

   if (exact_sol == 0)
   {
      E[0] = sin(2*pi*x)*sin(4*pi*y);
      E[1] = sin(4*pi*x)*sin(2*pi*y);
   }
   else if (exact_sol == 1)
   {
      E(0) = x * y * (1.0-y) * z * (1.0-z);
      E(1) = x * y * (1.0-x) * z * (1.0-z);
      E(2) = x * z * (1.0-x) * y * (1.0-y);
   }
   else
   {
      constexpr double kappa = 2.0 * pi;
      if (dim == 3)
      {
         E(0) = sin(kappa * y) * sin(kappa * z);
         E(1) = sin(kappa * x) * sin(kappa * z);
         E(2) = sin(kappa * x) * sin(kappa * y);
      }
      else
      {
         E(0) = sin(kappa * y);
         E(1) = sin(kappa * x);
         if (xvec.Size() == 3) { E(2) = 0.0; }
      }
   }
}

void f_exact(const Vector &xvec, Vector &f)
{
   double x=xvec[0], y=xvec[1], z=xvec[2];
   constexpr double pi = M_PI;
   constexpr double pi2 = M_PI*M_PI;

   if (exact_sol == 0)
   {
      f[0] = 8*pi2*cos(4*pi*x)*cos(2*pi*y) + (1 + 16*pi2)*sin(2*pi*x)*sin(4*pi*y);
      f[1] = 8*pi2*cos(2*pi*x)*cos(4*pi*y) + (1 + 16*pi2)*sin(4*pi*x)*sin(2*pi*y);
   }
   else if (exact_sol == 1)
   {
      f(0) = x * y * (1.0-y) * z * (1.0-z);
      f(1) = x * y * (1.0-x) * z * (1.0-z);
      f(2) = x * z * (1.0-x) * y * (1.0-y);

      f(0) += y * (1.0-y) + z * (1.0-z);
      f(1) += x * (1.0-x) + z * (1.0-z);
      f(2) += x * (1.0-x) + y * (1.0-y);
   }
   else
   {
      constexpr double kappa = 2.0 * pi;
      if (dim == 3)
      {
         f(0) = (1.0 + 2.0 * kappa * kappa) * sin(kappa * y) * sin(kappa * z);
         f(1) = (1.0 + 2.0 * kappa * kappa) * sin(kappa * x) * sin(kappa * z);
         f(2) = (1.0 + 2.0 * kappa * kappa) * sin(kappa * x) * sin(kappa * y);
      }
      else
      {
         f(0) = (1. + kappa * kappa) * sin(kappa * y);
         f(1) = (1. + kappa * kappa) * sin(kappa * x);
         if (xvec.Size() == 3) { f(2) = 0.0; }
      }
   }
}

int main(int argc, char *argv[])
{
   // 1. Parse command-line options.
   const char *mesh_file = "../data/star.mesh";
   int ref_levels = 0;
   int order = 3;
   const char *fe = "n";

   OptionsParser args(argc, argv);
   args.AddOption(&mesh_file, "-m", "--mesh", "Mesh file to use.");
   args.AddOption(&ref_levels, "-r", "--refine", "Uniform refinements.");
   args.AddOption(&order, "-o", "--order", "Polynomial degree.");
   args.AddOption(&exact_sol, "-p", "--problem", "Exact solution.");
   args.AddOption(&fe, "-fe", "--fe-type", "FE type. n for Hcurl, r for Hdiv");
   args.ParseCheck();

   bool ND;
   if (string(fe) == "n") { ND = true; }
   else if (string(fe) == "r") { ND = false; }
   else { MFEM_ABORT("Bad FE type. Must be 'n' or 'r'."); }

   Mesh mesh(mesh_file, 1, 1);
   dim = mesh.Dimension();
   for (int l = 0; l < ref_levels; l++) { mesh.UniformRefinement(); }

   int b1 = BasisType::GaussLobatto, b2 = BasisType::Integrated;
   unique_ptr<FiniteElementCollection> fec;
   if (ND) { fec.reset(new ND_FECollection(order, dim, b1, b2)); }
   else { fec.reset(new RT_FECollection(order-1, dim, b1, b2)); }

   FiniteElementSpace fes(&mesh, fec.get());
   Array<int> ess_dofs_ho;
   fes.GetBoundaryTrueDofs(ess_dofs_ho);

   BilinearForm a_ho(&fes);
   a_ho.AddDomainIntegrator(new VectorFEMassIntegrator);
   if (ND) { a_ho.AddDomainIntegrator(new CurlCurlIntegrator); }
   else { a_ho.AddDomainIntegrator(new DivDivIntegrator); }
   a_ho.SetAssemblyLevel(AssemblyLevel::PARTIAL);
   a_ho.Assemble();

   LinearForm b(&fes);
   VectorFunctionCoefficient f_coeff(dim, f_exact);
   b.AddDomainIntegrator(new VectorFEDomainLFIntegrator(f_coeff));
   b.Assemble();

   GridFunction x(&fes);
   x = 0.0;

   Vector X, B;
   OperatorHandle A;
   a_ho.FormLinearSystem(ess_dofs_ho, x, b, A, X, B);

   LORSolver<UMFPackSolver> lor_solver(a_ho, ess_dofs_ho);

   CGSolver cg;
   cg.SetAbsTol(0.0);
   cg.SetRelTol(1e-12);
   cg.SetMaxIter(100);
   cg.SetPrintLevel(1);
   cg.SetOperator(*A);
   cg.SetPreconditioner(lor_solver);
   cg.Mult(B, X);
   a_ho.RecoverFEMSolution(X, b, x);

   VectorFunctionCoefficient exact_coeff(dim, E_exact);
   double er = x.ComputeL2Error(exact_coeff);
   std::cout << "L^2 error: " << er << '\n';

   ParaViewDataCollection dc("LOR", &mesh);
   dc.SetPrefixPath("ParaView");
   dc.SetHighOrderOutput(true);
   dc.SetLevelsOfDetail(order);
   dc.RegisterField("u", &x);
   dc.SetCycle(0);
   dc.SetTime(0.0);
   dc.Save();

   return 0;
}
<|endoftext|>


<commit_before>/*
Highly Optimized Object-oriented Many-particle Dynamics -- Blue Edition
(HOOMD-blue) Open Source Software License Copyright 2008, 2009 Ames Laboratory
Iowa State University and The Regents of the University of Michigan All rights
reserved.

HOOMD-blue may contain modifications ("Contributions") provided, and to which
copyright is held, by various Contributors who have granted The Regents of the
University of Michigan the right to modify and/or distribute such Contributions.

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

* Redistributions of source code must retain the above copyright notice, this
list of conditions, and the following disclaimer.

* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions, and the following disclaimer in the documentation and/or
other materials provided with the distribution.

* Neither the name of the copyright holder nor the names of HOOMD-blue's
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.

Disclaimer

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ``AS IS''
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND/OR
ANY WARRANTIES THAT THIS SOFTWARE IS FREE OF INFRINGEMENT ARE DISCLAIMED.

IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

// $Id$
// $URL$
// Maintainer: joaander

#ifdef WIN32
#pragma warning( push )
#pragma warning( disable : 4103 4244 )
#endif

//! Name the unit test module
#define BOOST_TEST_MODULE TablePotentialTests
#include "boost_utf_configure.h"

#include <fstream>

#include "TablePotential.h"
#include "BinnedNeighborList.h"
#ifdef ENABLE_CUDA
#include "TablePotentialGPU.h"
#endif

using namespace std;
using namespace boost;

/*! \file table_potential_test.cc
    \brief Implements unit tests for TablePotential and descendants
    \ingroup unit_tests
*/

BOOST_AUTO_TEST_CASE(potential_writer)
    {
    #ifdef CUDA
    g_gpu_error_checking = true;
    #endif

    // this 2-particle test is just to get a plot of the potential and force vs r cut
    shared_ptr<SystemDefinition> sysdef_2(new SystemDefinition(2, BoxDim(1000.0), 1, 0, 0, 0, 0, ExecutionConfiguration()));
    shared_ptr<ParticleData> pdata_2 = sysdef_2->getParticleData();

    ParticleDataArrays arrays = pdata_2->acquireReadWrite();
    arrays.x[0] = arrays.y[0] = arrays.z[0] = 0.0;
    arrays.x[1] = Scalar(0.9); arrays.y[1] = arrays.z[1] = 0.0;
    pdata_2->release();
    shared_ptr<NeighborList> nlist_2(new NeighborList(sysdef_2, Scalar(7.0), Scalar(0.8)));
    nlist_2->setStorageMode(NeighborList::full);
    shared_ptr<TablePotential> fc(new TablePotentialGPU(sysdef_2, nlist_2, 1000));

    // provide a basic potential and "force"
    vector<Scalar> V, F;
    // 5 point test
//    V.push_back(10.0);  F.push_back(-10.0/1.0);
//    V.push_back(15.0);  F.push_back(-15.0/2.0);
//    V.push_back(5.0);   F.push_back(-5.0/3.0);
//    V.push_back(8.0);   F.push_back(-8.0/4.0);
//    V.push_back(18.0);  F.push_back(-18.0/5.0);

    // 1000 point lj test
    /*Scalar delta_r = (5.0 - 0.5) / (999);
    for (unsigned int i = 0; i < 1000; i++)
        {
        Scalar r = 0.5 + delta_r * Scalar(i);
        V.push_back(4.0 * (pow(1.0 / r, 12) - pow(1.0 / r, 6)));
        F.push_back(4.0 * (12.0 * pow(1.0 / r, 14) - 6 * pow(1.0 / r, 8)));
        }*/

    // 1000 point gaussian test
    Scalar delta_r = (5.0) / (999);
    for (unsigned int i = 0; i < 1000; i++)
        {
        Scalar r = delta_r * Scalar(i);
        V.push_back(1.5 * expf(-r / 0.5));
        if (r == 0.0)
            F.push_back(0);
        else
            F.push_back(1.5 / 0.5 * expf(-r / 0.5) / r);
        }

    fc->setTable(0, 0, V, F, 0.0, 5.0);

    ofstream f("table_dat.m");
    f << "table = [";
    unsigned int count = 0;
    for (float r = 0.0; r <= 5.0; r+= 0.001)
        {
        // set the distance
        ParticleDataArrays arrays = pdata_2->acquireReadWrite();
        arrays.x[0] = arrays.y[0] = arrays.z[0] = 0.0;
        arrays.x[1] = Scalar(r); arrays.y[1] = arrays.z[1] = 0.0;
        pdata_2->release();

        // compute the forces
        fc->compute(count);
        count++;

        ForceDataArrays force_arrays = fc->acquire();
        f << r << " " << force_arrays.fx[0] << " " << fc->calcEnergySum() << " ; " << endl;
        }
    f << "];" << endl;
    f.close();
    }

#ifdef WIN32
#pragma warning( pop )
#endif<commit_msg>Added basic unit tests for TablePotential.<commit_after>/*
Highly Optimized Object-oriented Many-particle Dynamics -- Blue Edition
(HOOMD-blue) Open Source Software License Copyright 2008, 2009 Ames Laboratory
Iowa State University and The Regents of the University of Michigan All rights
reserved.

HOOMD-blue may contain modifications ("Contributions") provided, and to which
copyright is held, by various Contributors who have granted The Regents of the
University of Michigan the right to modify and/or distribute such Contributions.

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

* Redistributions of source code must retain the above copyright notice, this
list of conditions, and the following disclaimer.

* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions, and the following disclaimer in the documentation and/or
other materials provided with the distribution.

* Neither the name of the copyright holder nor the names of HOOMD-blue's
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.

Disclaimer

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ``AS IS''
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND/OR
ANY WARRANTIES THAT THIS SOFTWARE IS FREE OF INFRINGEMENT ARE DISCLAIMED.

IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

// $Id$
// $URL$
// Maintainer: joaander

#ifdef WIN32
#pragma warning( push )
#pragma warning( disable : 4103 4244 )
#endif

//! Name the unit test module
#define BOOST_TEST_MODULE TablePotentialTests
#include "boost_utf_configure.h"

#include <fstream>

#include "TablePotential.h"
#include "BinnedNeighborList.h"
#ifdef ENABLE_CUDA
#include "TablePotentialGPU.h"
#endif

using namespace std;
using namespace boost;

/*! \file table_potential_test.cc
    \brief Implements unit tests for TablePotential and descendants
    \ingroup unit_tests
*/

//! Helper macro for testing if two numbers are close
#define MY_BOOST_CHECK_CLOSE(a,b,c) BOOST_CHECK_CLOSE(a,Scalar(b),Scalar(c))
//! Helper macro for testing if a number is small
#define MY_BOOST_CHECK_SMALL(a,c) BOOST_CHECK_SMALL(a,Scalar(c))

//! Tolerance in percent to use for comparing various LJForceComputes to each other
#ifdef SINGLE_PRECISION
const Scalar tol = Scalar(4);
#else
const Scalar tol = 1e-6;
#endif
//! Global tolerance for check_small comparisons
const Scalar tol_small = 1e-4;

//! Typedef'd TablePotential factory
typedef boost::function<shared_ptr<TablePotential> (shared_ptr<SystemDefinition> sysdef,
                                                    shared_ptr<NeighborList> nlist,
                                                    unsigned int width)> table_potential_creator;

//! performs some really basic checks on the TablePotential class
void table_potential_basic_test(table_potential_creator table_creator, ExecutionConfiguration exec_conf)
    {
    #ifdef CUDA
    g_gpu_error_checking = true;
    #endif

    // perform a basic test to see of the potential and force can be interpolated between two particles
    shared_ptr<SystemDefinition> sysdef_2(new SystemDefinition(2, BoxDim(1000.0), 1, 0, 0, 0, 0, ExecutionConfiguration()));
    shared_ptr<ParticleData> pdata_2 = sysdef_2->getParticleData();

    ParticleDataArrays arrays = pdata_2->acquireReadWrite();
    arrays.x[0] = arrays.y[0] = arrays.z[0] = 0.0;
    arrays.x[1] = Scalar(1.0); arrays.y[1] = arrays.z[1] = 0.0;
    pdata_2->release();

    shared_ptr<NeighborList> nlist_2(new NeighborList(sysdef_2, Scalar(7.0), Scalar(0.8)));
    shared_ptr<TablePotential> fc_2 = table_creator(sysdef_2, nlist_2, 3);

    // first check for proper initialization by seeing if the force and potential come out to be 0
    fc_2->compute(0);

    ForceDataArrays force_arrays = fc_2->acquire();
    MY_BOOST_CHECK_SMALL(force_arrays.fx[0], tol_small);
    MY_BOOST_CHECK_SMALL(force_arrays.fy[0], tol_small);
    MY_BOOST_CHECK_SMALL(force_arrays.fz[0], tol_small);
    MY_BOOST_CHECK_SMALL(force_arrays.pe[0], tol_small);
    MY_BOOST_CHECK_SMALL(force_arrays.virial[0], tol_small);

    MY_BOOST_CHECK_SMALL(force_arrays.fx[1], tol_small);
    MY_BOOST_CHECK_SMALL(force_arrays.fy[1], tol_small);
    MY_BOOST_CHECK_SMALL(force_arrays.fz[1], tol_small);
    MY_BOOST_CHECK_SMALL(force_arrays.pe[1], tol_small);
    MY_BOOST_CHECK_SMALL(force_arrays.virial[1], tol_small);

    // specify a table to interpolate
    vector<Scalar> V, F;
    V.push_back(10.0);  F.push_back(1.0);
    V.push_back(21.0);  F.push_back(6.0);
    V.push_back(5.0);   F.push_back(2.0);
    fc_2->setTable(0, 0, V, F, 2.0, 4.0);

    // compute the forces again and check that they are still 0
    fc_2->compute(1);

    force_arrays = fc_2->acquire();
    MY_BOOST_CHECK_SMALL(force_arrays.fx[0], tol_small);
    MY_BOOST_CHECK_SMALL(force_arrays.fy[0], tol_small);
    MY_BOOST_CHECK_SMALL(force_arrays.fz[0], tol_small);
    MY_BOOST_CHECK_SMALL(force_arrays.pe[0], tol_small);
    MY_BOOST_CHECK_SMALL(force_arrays.virial[0], tol_small);

    MY_BOOST_CHECK_SMALL(force_arrays.fx[1], tol_small);
    MY_BOOST_CHECK_SMALL(force_arrays.fy[1], tol_small);
    MY_BOOST_CHECK_SMALL(force_arrays.fz[1], tol_small);
    MY_BOOST_CHECK_SMALL(force_arrays.pe[1], tol_small);
    MY_BOOST_CHECK_SMALL(force_arrays.virial[1], tol_small);

    // now go to rmin and check for the correct force value
    arrays = pdata_2->acquireReadWrite();
    arrays.x[1] = Scalar(2.0);
    pdata_2->release();

    fc_2->compute(2);

    force_arrays = fc_2->acquire();
    MY_BOOST_CHECK_CLOSE(force_arrays.fx[0], -1.0, tol);
    MY_BOOST_CHECK_SMALL(force_arrays.fy[0], tol_small);
    MY_BOOST_CHECK_SMALL(force_arrays.fz[0], tol_small);
    MY_BOOST_CHECK_CLOSE(force_arrays.pe[0], 5.0, tol);
    MY_BOOST_CHECK_CLOSE(force_arrays.virial[0], (1.0 / 6.0) * 2.0, tol);

    MY_BOOST_CHECK_CLOSE(force_arrays.fx[1], 1.0, tol);
    MY_BOOST_CHECK_SMALL(force_arrays.fy[1], tol_small);
    MY_BOOST_CHECK_SMALL(force_arrays.fz[1], tol_small);
    MY_BOOST_CHECK_CLOSE(force_arrays.pe[1], 5.0, tol);
    MY_BOOST_CHECK_CLOSE(force_arrays.virial[1], (1.0 / 6.0) * 2.0, tol);

    // go halfway in-between two points
    arrays = pdata_2->acquireReadWrite();
    arrays.y[1] = Scalar(3.5);
    arrays.x[1] = Scalar(0.0);
    pdata_2->release();

    // check the forces
    fc_2->compute(3);
    force_arrays = fc_2->acquire();
    MY_BOOST_CHECK_CLOSE(force_arrays.fy[0], -4.0, tol);
    MY_BOOST_CHECK_SMALL(force_arrays.fx[0], tol_small);
    MY_BOOST_CHECK_SMALL(force_arrays.fz[0], tol_small);
    MY_BOOST_CHECK_CLOSE(force_arrays.pe[0], 13.0/2.0, tol);
    MY_BOOST_CHECK_CLOSE(force_arrays.virial[0], (1.0 / 6.0) * 4.0 * 3.5, tol);

    MY_BOOST_CHECK_CLOSE(force_arrays.fy[1], 4.0, tol);
    MY_BOOST_CHECK_SMALL(force_arrays.fx[1], tol_small);
    MY_BOOST_CHECK_SMALL(force_arrays.fz[1], tol_small);
    MY_BOOST_CHECK_CLOSE(force_arrays.pe[1], 13.0 / 2.0, tol);
    MY_BOOST_CHECK_CLOSE(force_arrays.virial[1], (1.0 / 6.0) * 4.0 * 3.5, tol);

    // and now check for when r > rmax
    arrays = pdata_2->acquireReadWrite();
    arrays.z[1] = Scalar(4.0);
    pdata_2->release();

    // compute and check
    fc_2->compute(4);

    force_arrays = fc_2->acquire();
    MY_BOOST_CHECK_SMALL(force_arrays.fx[0], tol_small);
    MY_BOOST_CHECK_SMALL(force_arrays.fy[0], tol_small);
    MY_BOOST_CHECK_SMALL(force_arrays.fz[0], tol_small);
    MY_BOOST_CHECK_SMALL(force_arrays.pe[0], tol_small);
    MY_BOOST_CHECK_SMALL(force_arrays.virial[0], tol_small);

    MY_BOOST_CHECK_SMALL(force_arrays.fx[1], tol_small);
    MY_BOOST_CHECK_SMALL(force_arrays.fy[1], tol_small);
    MY_BOOST_CHECK_SMALL(force_arrays.fz[1], tol_small);
    MY_BOOST_CHECK_SMALL(force_arrays.pe[1], tol_small);
    MY_BOOST_CHECK_SMALL(force_arrays.virial[1], tol_small);
    }

 //! checks to see if TablePotential correctly handles multiple types
/*void table_potential_type_test(table_potential_creator table_creator, ExecutionConfiguration exec_conf)
    {
    #ifdef CUDA
    g_gpu_error_checking = true;
    #endif

    // perform a basic test to see of the potential and force can be interpolated between two particles
    shared_ptr<SystemDefinition> sysdef_3(new SystemDefinition(2, BoxDim(1000.0), 2, 0, 0, 0, 0, ExecutionConfiguration()));
    shared_ptr<ParticleData> pdata_3 = sysdef_2->getParticleData();

    ParticleDataArrays arrays = pdata_3->acquireReadWrite();
    arrays.x[0] = arrays.y[0] = arrays.z[0] = 0.0;
    arrays.x[1] = Scalar(1.0); arrays.y[1] = arrays.z[1] = 0.0;
    pdata_2->release();

    shared_ptr<NeighborList> nlist_2(new NeighborList(sysdef_2, Scalar(7.0), Scalar(0.8)));
    shared_ptr<TablePotential> fc_2 = table_creator(sysdef_2, nlist_2, 3);

    // first check for proper initialization by seeing if the force and potential come out to be 0
    fc_2->compute(0);

    ForceDataArrays force_arrays = fc_2->acquire();
    MY_BOOST_CHECK_SMALL(force_arrays.fx[0], tol_small);
    MY_BOOST_CHECK_SMALL(force_arrays.fy[0], tol_small);
    MY_BOOST_CHECK_SMALL(force_arrays.fz[0], tol_small);
    MY_BOOST_CHECK_SMALL(force_arrays.pe[0], tol_small);
    MY_BOOST_CHECK_SMALL(force_arrays.virial[0], tol_small);

    MY_BOOST_CHECK_SMALL(force_arrays.fx[1], tol_small);
    MY_BOOST_CHECK_SMALL(force_arrays.fy[1], tol_small);
    MY_BOOST_CHECK_SMALL(force_arrays.fz[1], tol_small);
    MY_BOOST_CHECK_SMALL(force_arrays.pe[1], tol_small);
    MY_BOOST_CHECK_SMALL(force_arrays.virial[1], tol_small);

    // specify a table to interpolate
    vector<Scalar> V, F;
    V.push_back(10.0);  F.push_back(1.0);
    V.push_back(21.0);  F.push_back(6.0);
    V.push_back(5.0);   F.push_back(2.0);
    fc_2->setTable(0, 0, V, F, 2.0, 4.0);

    }*/

//! TablePotential creator for unit tests
shared_ptr<TablePotential> base_class_table_creator(shared_ptr<SystemDefinition> sysdef,
                                                    shared_ptr<NeighborList> nlist,
                                                    unsigned int width)
    {
    return shared_ptr<TablePotential>(new TablePotential(sysdef, nlist, width));
    }

#ifdef ENABLE_CUDA
//! TablePotentialGPU creator for unit tests
shared_ptr<TablePotential> gpu_table_creator(shared_ptr<SystemDefinition> sysdef,
                                             shared_ptr<NeighborList> nlist,
                                             unsigned int width)
    {
    nlist->setStorageMode(NeighborList::full);
    shared_ptr<TablePotentialGPU> table(new TablePotentialGPU(sysdef, nlist, width));
    // the default block size kills valgrind :) reduce it
    table->setBlockSize(64);
    return table;
    }
#endif

//! boost test case for basic test on CPU
BOOST_AUTO_TEST_CASE( TablePotential_basic )
    {
    table_potential_creator table_creator_base = bind(base_class_table_creator, _1, _2, _3);
    table_potential_basic_test(table_creator_base, ExecutionConfiguration(ExecutionConfiguration::CPU));
    }

#ifdef ENABLE_CUDA
//! boost test case for basic test on CPU
BOOST_AUTO_TEST_CASE( TablePotentialGPU_basic )
    {
    table_potential_creator table_creator_gpu = bind(gpu_table_creator, _1, _2, _3);
    table_potential_basic_test(table_creator_gpu, ExecutionConfiguration(ExecutionConfiguration::GPU));
    }
#endif

/*BOOST_AUTO_TEST_CASE(potential_writer)
    {
    #ifdef CUDA
    g_gpu_error_checking = true;
    #endif

    // this 2-particle test is just to get a plot of the potential and force vs r cut
    shared_ptr<SystemDefinition> sysdef_2(new SystemDefinition(2, BoxDim(1000.0), 1, 0, 0, 0, 0, ExecutionConfiguration()));
    shared_ptr<ParticleData> pdata_2 = sysdef_2->getParticleData();

    ParticleDataArrays arrays = pdata_2->acquireReadWrite();
    arrays.x[0] = arrays.y[0] = arrays.z[0] = 0.0;
    arrays.x[1] = Scalar(0.9); arrays.y[1] = arrays.z[1] = 0.0;
    pdata_2->release();
    shared_ptr<NeighborList> nlist_2(new NeighborList(sysdef_2, Scalar(7.0), Scalar(0.8)));
    nlist_2->setStorageMode(NeighborList::full);
    shared_ptr<TablePotential> fc(new TablePotentialGPU(sysdef_2, nlist_2, 1000));

    // provide a basic potential and "force"
    vector<Scalar> V, F;
    // 5 point test
//    V.push_back(10.0);  F.push_back(-10.0/1.0);
//    V.push_back(15.0);  F.push_back(-15.0/2.0);
//    V.push_back(5.0);   F.push_back(-5.0/3.0);
//    V.push_back(8.0);   F.push_back(-8.0/4.0);
//    V.push_back(18.0);  F.push_back(-18.0/5.0);

    // 1000 point lj test
//    Scalar delta_r = (5.0 - 0.5) / (999);
//    for (unsigned int i = 0; i < 1000; i++)
//        {
//        Scalar r = 0.5 + delta_r * Scalar(i);
//        V.push_back(4.0 * (pow(1.0 / r, 12) - pow(1.0 / r, 6)));
//        F.push_back(4.0 * (12.0 * pow(1.0 / r, 14) - 6 * pow(1.0 / r, 8)));
//        }

    // 1000 point gaussian test
    Scalar delta_r = (5.0) / (999);
    for (unsigned int i = 0; i < 1000; i++)
        {
        Scalar r = delta_r * Scalar(i);
        V.push_back(1.5 * expf(-r / 0.5));
        if (r == 0.0)
            F.push_back(0);
        else
            F.push_back(1.5 / 0.5 * expf(-r / 0.5) / r);
        }

    fc->setTable(0, 0, V, F, 0.0, 5.0);

    ofstream f("table_dat.m");
    f << "table = [";
    unsigned int count = 0;
    for (float r = 0.0; r <= 5.0; r+= 0.001)
        {
        // set the distance
        ParticleDataArrays arrays = pdata_2->acquireReadWrite();
        arrays.x[0] = arrays.y[0] = arrays.z[0] = 0.0;
        arrays.x[1] = Scalar(r); arrays.y[1] = arrays.z[1] = 0.0;
        pdata_2->release();

        // compute the forces
        fc->compute(count);
        count++;

        ForceDataArrays force_arrays = fc->acquire();
        f << r << " " << force_arrays.fx[0] << " " << fc->calcEnergySum() << " ; " << endl;
        }
    f << "];" << endl;
    f.close();
    }*/

#ifdef WIN32
#pragma warning( pop )
#endif<|endoftext|>


<commit_before>/*
 * Copyright (C) 2008 Apple Inc. All Rights Reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"
#include "NetworkStateNotifier.h"

#include <wtf/MainThread.h>
#include <wtf/Vector.h>

#include <winsock2.h>
#include <iphlpapi.h>

namespace WebCore {

void NetworkStateNotifier::updateState()
{
    // Assume that we're online until proven otherwise.
    m_isOnLine = true;

    Vector<char> buffer;
    DWORD size = 0;

    if (::GetAdaptersAddresses(AF_UNSPEC, 0, 0, 0, &size) != ERROR_BUFFER_OVERFLOW)
        return;

    buffer.resize(size);
    PIP_ADAPTER_ADDRESSES addresses = reinterpret_cast<PIP_ADAPTER_ADDRESSES>(buffer.data());

    if (::GetAdaptersAddresses(AF_UNSPEC, 0, 0, addresses, &size) != ERROR_SUCCESS) {
        // We couldn't determine whether we're online or not, so assume that we are.
        return;
    }

    for (; addresses; addresses = addresses->Next) {
        if (addresses->IfType == MIB_IF_TYPE_LOOPBACK)
            continue;

        if (addresses->OperStatus != IfOperStatusUp)
            continue;

        // We found an interface that was up.
        return;
    }

    // We didn't find any valid interfaces, so we must be offline.
    m_isOnLine = false;
}

void NetworkStateNotifier::addressChanged()
{
    bool oldOnLine = m_isOnLine;

    updateState();

    if (m_isOnLine == oldOnLine)
        return;

    if (m_networkStateChangedFunction)
        m_networkStateChangedFunction();
}

void NetworkStateNotifier::callAddressChanged(void* context)
{
    static_cast<NetworkStateNotifier*>(context)->addressChanged();
}

void CALLBACK NetworkStateNotifier::addrChangeCallback(void* context, BOOLEAN timedOut)
{
    callOnMainThread(callAddressChanged, context);
}

void NetworkStateNotifier::registerForAddressChange()
{
    HANDLE handle;
    ::NotifyAddrChange(&handle, &m_overlapped);
}

NetworkStateNotifier::NetworkStateNotifier()
    : m_isOnLine(false)
{
    updateState();

    memset(&m_overlapped, 0, sizeof(m_overlapped));

    m_overlapped.hEvent = ::CreateEvent(0, false, false, 0);

    ::RegisterWaitForSingleObject(&m_waitHandle, m_overlapped.hEvent, addrChangeCallback, this, INFINITE, 0);

    registerForAddressChange();
}

}
<commit_msg>Test to see if getting the network status on startup is expensive, and causing a performance startup regression. Review URL: http://codereview.chromium.org/5672<commit_after>/*
 * Copyright (C) 2008 Apple Inc. All Rights Reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"
#include "NetworkStateNotifier.h"

#include <wtf/MainThread.h>
#include <wtf/Vector.h>

#include <winsock2.h>
#include <iphlpapi.h>

namespace WebCore {

void NetworkStateNotifier::updateState()
{
    // Assume that we're online until proven otherwise.
    m_isOnLine = true;
    return;

    Vector<char> buffer;
    DWORD size = 0;

    if (::GetAdaptersAddresses(AF_UNSPEC, 0, 0, 0, &size) != ERROR_BUFFER_OVERFLOW)
        return;

    buffer.resize(size);
    PIP_ADAPTER_ADDRESSES addresses = reinterpret_cast<PIP_ADAPTER_ADDRESSES>(buffer.data());

    if (::GetAdaptersAddresses(AF_UNSPEC, 0, 0, addresses, &size) != ERROR_SUCCESS) {
        // We couldn't determine whether we're online or not, so assume that we are.
        return;
    }

    for (; addresses; addresses = addresses->Next) {
        if (addresses->IfType == MIB_IF_TYPE_LOOPBACK)
            continue;

        if (addresses->OperStatus != IfOperStatusUp)
            continue;

        // We found an interface that was up.
        return;
    }

    // We didn't find any valid interfaces, so we must be offline.
    m_isOnLine = false;
}

void NetworkStateNotifier::addressChanged()
{
    bool oldOnLine = m_isOnLine;

    updateState();

    if (m_isOnLine == oldOnLine)
        return;

    if (m_networkStateChangedFunction)
        m_networkStateChangedFunction();
}

void NetworkStateNotifier::callAddressChanged(void* context)
{
    static_cast<NetworkStateNotifier*>(context)->addressChanged();
}

void CALLBACK NetworkStateNotifier::addrChangeCallback(void* context, BOOLEAN timedOut)
{
    callOnMainThread(callAddressChanged, context);
}

void NetworkStateNotifier::registerForAddressChange()
{
    HANDLE handle;
    ::NotifyAddrChange(&handle, &m_overlapped);
}

NetworkStateNotifier::NetworkStateNotifier()
    : m_isOnLine(false)
{
    updateState();

    memset(&m_overlapped, 0, sizeof(m_overlapped));

    m_overlapped.hEvent = ::CreateEvent(0, false, false, 0);

    ::RegisterWaitForSingleObject(&m_waitHandle, m_overlapped.hEvent, addrChangeCallback, this, INFINITE, 0);

    registerForAddressChange();
}

}
<|endoftext|>


<commit_before>/** @file
 *****************************************************************************
 * @author     This file is part of libsnark, developed by SCIPR Lab
 *             and contributors (see AUTHORS).
 * @copyright  MIT license (see LICENSE file)
 *****************************************************************************/

#ifndef SIMPLE_EXAMPLE_HPP_
#define SIMPLE_EXAMPLE_HPP_

#include "examples/r1cs_examples.hpp"

namespace libsnark {

template<typename FieldT>
r1cs_example<FieldT> gen_r1cs_example_from_protoboard(const size_t num_constraints,
                                                      const size_t num_inputs);

} // libsnark

#include "examples/gadgetlib1/simple_example.tcc"

#endif // SIMPLE_EXAMPLE_HPP_
<commit_msg>Fix a typo in include path; this closes #7.<commit_after>/** @file
 *****************************************************************************
 * @author     This file is part of libsnark, developed by SCIPR Lab
 *             and contributors (see AUTHORS).
 * @copyright  MIT license (see LICENSE file)
 *****************************************************************************/

#ifndef SIMPLE_EXAMPLE_HPP_
#define SIMPLE_EXAMPLE_HPP_

#include "examples/r1cs_examples.hpp"

namespace libsnark {

template<typename FieldT>
r1cs_example<FieldT> gen_r1cs_example_from_protoboard(const size_t num_constraints,
                                                      const size_t num_inputs);

} // libsnark

#include "gadgetlib1/examples/simple_example.tcc"

#endif // SIMPLE_EXAMPLE_HPP_
<|endoftext|>


<commit_before>#include <cstdio>
#include <stdexcept>
#include <unistd.h>
#include <cstdlib>

#include <typeinfo>
#include <cxxabi.h>
#include <execinfo.h>
#include <dlfcn.h>

#include <vw/config.h>
#include "TerminationHandler.h"

#ifdef VW_HAVE___CXA_DEMANGLE
#  ifdef VW_HAVE___CXA_CURRENT_EXCEPTION_TYPE
#    define USE_INTROSPECTION_EXCEPTION
#  endif
#  if defined(VW_HAVE_BACKTRACE) && defined(VW_HAVE_DLADDR)
#    define USE_INTROSPECTION_BACKTRACE
#  endif
#endif

namespace {

using namespace abi;

// The original default terminate() handler. Should be std::abort, but isn't
// always
void (*real_default)()       = 0;

// Currently installed handler
vw::TerminateHandler current = 0;

void vw_terminate()
{
  static bool terminating = false;
  if (terminating) {
      fputs("terminate called recursively!\n", stderr);
      abort();
  }
  terminating = true;

  if (current)
    current();
  fprintf(stderr, "terminate() called! If you'd like to connect gdb to this process, use:\n");
  fprintf(stderr, "gdb ignored %d\n", getpid());
  fprintf(stderr, "Press 'enter' to abort...\n");
  // It's probably not safe to getchar here, but, given where we are,
  // we can't really make it worse...
  getchar();
  abort();
}

// This is a bit of a hack, but it lets us distinguish between
// DefaultTerminate and an attempt to unset the terminate handler
void noop() {}

// A replacement for the standard terminate_handler which prints
// more information about the terminating exception (if any) on
// stderr.
void print_exception_info()
{
#ifdef USE_INTROSPECTION_EXCEPTION
  // Make sure there was an exception; terminate is also called for an
  // attempt to rethrow when there is no suitable exception.
  std::type_info *t = __cxa_current_exception_type();
  if (t)
  {
    // Note that "name" is the mangled name.
    char const *name = t->name();
    {
      int status = -1;
      char *dem  = __cxa_demangle(name, 0, 0, &status);

      fputs("terminate called after throwing an instance of '", stderr);
      if (status == 0)
        fputs(dem, stderr);
      else
        fputs(name, stderr);
      fputs("'\n", stderr);

      if (status == 0)
        free(dem);
    }

#if defined(VW_NO_EXCEPTIONS) && (VW_NO_EXCEPTIONS== 1)
#else
    // If the exception is derived from std::exception, we can
    // give more information.
      try { __throw_exception_again; }
      catch (std::exception const &exc)
        {
          char const *w = exc.what();
          fputs("  what():  ", stderr);
          fputs(w, stderr);
          fputs("\n", stderr);
        }
      catch (...) { }
#endif // VW_NO_EXCEPTIONS
    }
  else
    fputs("terminate called without an active exception\n", stderr);
#else
    fputs("terminate() called, but no exception support\n", stderr);
#endif  //USE_INTROSPECTION_EXCEPTION
}

// Adapted by Randy Sargent 5/29/2006
// Much comes from glibc verbose termination handler
void do_backtrace()
{
#ifdef USE_INTROSPECTION_BACKTRACE
  print_exception_info();

  void *backtrace_buffer[200];
  int backtrace_size = backtrace(backtrace_buffer, 200);

  if (backtrace_size)
  {
    fprintf(stderr, "Stack backtrace:\n");
    for (int i = 0; i < backtrace_size; ++i)
    {
      Dl_info info;
      fprintf(stderr, "  ");
      if (dladdr(backtrace_buffer[i], &info))
      {
        if (info.dli_fname)
          fprintf(stderr, "%s", info.dli_fname);

        if (info.dli_sname)
        {
          int status = -1;
          char *dem  = __cxa_demangle(info.dli_sname, 0, 0, &status);

          fprintf(stderr, "(%s+0x%lx)", status == 0 ? dem : info.dli_sname,
                  ((long)backtrace_buffer[i])-((long)info.dli_saddr));

          if (status == 0)
            free(dem);
        }
      }
      fprintf(stderr, " [0x%lx]\n", (long)backtrace_buffer[i]);
    }
  }
#else
    fputs("terminate() called, but no backtrace support\n", stderr);
#endif
}

} // anonymous namespace

const vw::TerminateHandler vw::DefaultTerminate = noop;

const vw::TerminateHandler vw::PrettyTerminate =
#ifdef USE_INTROSPECTION_EXCEPTION
  print_exception_info;
#else
  0;
#endif

const vw::TerminateHandler vw::BacktraceTerminate =
#ifdef USE_INTROSPECTION_BACKTRACE
  do_backtrace;
#else
  0;
#endif

bool vw::set_terminate_handler( vw::TerminateHandler const &th )
{
  if (real_default == 0)
  {
    real_default = std::set_terminate(std::abort);
    std::set_terminate(real_default);
  }

  if( th ) {
    current = th;
    std::set_terminate(vw_terminate);
    return true;
  }
  else
  {
    current = 0;
    std::set_terminate(real_default);
    return false;
  }
}
<commit_msg>fix the build on OSX<commit_after>#include <cstdio>
#include <stdexcept>
#include <unistd.h>
#include <cstdlib>

#include <typeinfo>

#include <vw/config.h>

#ifdef VW_HAVE_CXXABI_H
#include <cxxabi.h>
#endif

#ifdef VW_HAVE_EXECINFO_H
// for backtrace
#include <execinfo.h>
#endif

#ifdef VW_HAVE_DLFCN_H
#include <dlfcn.h>
#endif

#include "TerminationHandler.h"

#if defined(VW_HAVE___CXA_DEMANGLE) && defined(VW_HAVE_CXXABI_H)
#  if defined(VW_HAVE___CXA_CURRENT_EXCEPTION_TYPE)
#    define USE_INTROSPECTION_EXCEPTION
#  endif
#  if defined(VW_HAVE_BACKTRACE) && defined(VW_HAVE_DLADDR) && defined(VW_HAVE_DLFCN_H) && defined(VW_HAVE_EXECINFO_H)
#    define USE_INTROSPECTION_BACKTRACE
#  endif
#endif

namespace {

// The original default terminate() handler. Should be std::abort, but isn't
// always
void (*real_default)()       = 0;

// Currently installed handler
vw::TerminateHandler current = 0;

void vw_terminate()
{
  static bool terminating = false;
  if (terminating) {
      fputs("terminate called recursively!\n", stderr);
      abort();
  }
  terminating = true;

  if (current)
    current();
  fprintf(stderr, "terminate() called! If you'd like to connect gdb to this process, use:\n");
  fprintf(stderr, "gdb ignored %d\n", getpid());
  fprintf(stderr, "Press 'enter' to abort...\n");
  // It's probably not safe to getchar here, but, given where we are,
  // we can't really make it worse...
  getchar();
  abort();
}

// This is a bit of a hack, but it lets us distinguish between
// DefaultTerminate and an attempt to unset the terminate handler
void noop() {}

// A replacement for the standard terminate_handler which prints
// more information about the terminating exception (if any) on
// stderr.
void print_exception_info()
{
#ifdef USE_INTROSPECTION_EXCEPTION
  // Make sure there was an exception; terminate is also called for an
  // attempt to rethrow when there is no suitable exception.
  std::type_info *t = abi::__cxa_current_exception_type();
  if (t)
  {
    // Note that "name" is the mangled name.
    char const *name = t->name();
    {
      int status = -1;
      char *dem  = abi::__cxa_demangle(name, 0, 0, &status);

      fputs("terminate called after throwing an instance of '", stderr);
      if (status == 0)
        fputs(dem, stderr);
      else
        fputs(name, stderr);
      fputs("'\n", stderr);

      if (status == 0)
        free(dem);
    }

#if defined(VW_NO_EXCEPTIONS) && (VW_NO_EXCEPTIONS== 1)
#else
    // If the exception is derived from std::exception, we can
    // give more information.
      try { __throw_exception_again; }
      catch (std::exception const &exc)
        {
          char const *w = exc.what();
          fputs("  what():  ", stderr);
          fputs(w, stderr);
          fputs("\n", stderr);
        }
      catch (...) { }
#endif // VW_NO_EXCEPTIONS
    }
  else
    fputs("terminate called without an active exception\n", stderr);
#else
    fputs("terminate() called, but no exception support\n", stderr);
#endif  //USE_INTROSPECTION_EXCEPTION
}

// Adapted by Randy Sargent 5/29/2006
// Much comes from glibc verbose termination handler
void do_backtrace()
{
#ifdef USE_INTROSPECTION_BACKTRACE
  print_exception_info();

  void *backtrace_buffer[200];
  int backtrace_size = backtrace(backtrace_buffer, 200);

  if (backtrace_size)
  {
    fprintf(stderr, "Stack backtrace:\n");
    for (int i = 0; i < backtrace_size; ++i)
    {
      Dl_info info;
      fprintf(stderr, "  ");
      if (dladdr(backtrace_buffer[i], &info))
      {
        if (info.dli_fname)
          fprintf(stderr, "%s", info.dli_fname);

        if (info.dli_sname)
        {
          int status = -1;
          char *dem  = abi::__cxa_demangle(info.dli_sname, 0, 0, &status);

          fprintf(stderr, "(%s+0x%lx)", status == 0 ? dem : info.dli_sname,
                  ((long)backtrace_buffer[i])-((long)info.dli_saddr));

          if (status == 0)
            free(dem);
        }
      }
      fprintf(stderr, " [0x%lx]\n", (long)backtrace_buffer[i]);
    }
  }
#else
    fputs("terminate() called, but no backtrace support\n", stderr);
#endif
}

} // anonymous namespace

const vw::TerminateHandler vw::DefaultTerminate = noop;

const vw::TerminateHandler vw::PrettyTerminate =
#ifdef USE_INTROSPECTION_EXCEPTION
  print_exception_info;
#else
  0;
#endif

const vw::TerminateHandler vw::BacktraceTerminate =
#ifdef USE_INTROSPECTION_BACKTRACE
  do_backtrace;
#else
  0;
#endif

bool vw::set_terminate_handler( vw::TerminateHandler const &th )
{
  if (real_default == 0)
  {
    real_default = std::set_terminate(std::abort);
    std::set_terminate(real_default);
  }

  if( th ) {
    current = th;
    std::set_terminate(vw_terminate);
    return true;
  }
  else
  {
    current = 0;
    std::set_terminate(real_default);
    return false;
  }
}
<|endoftext|>