<commit_before>//===- SimplifyCFGPass.cpp - CFG Simplification Pass ----------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements dead code elimination and basic block merging, along
// with a collection of other peephole control flow optimizations.  For example:
//
//   * Removes basic blocks with no predecessors.
//   * Merges a basic block into its predecessor if there is only one and the
//     predecessor only has one successor.
//   * Eliminates PHI nodes for basic blocks with a single predecessor.
//   * Eliminates a basic block that only contains an unconditional branch.
//   * Changes invoke instructions to nounwind functions to be calls.
//   * Change things like "if (x) if (y)" into "if (x&y)".
//   * etc..
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "simplifycfg"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Transforms/Utils/Local.h"
#include "llvm/Constants.h"
#include "llvm/Instructions.h"
#include "llvm/IntrinsicInst.h"
#include "llvm/Module.h"
#include "llvm/Attributes.h"
#include "llvm/Support/CFG.h"
#include "llvm/Pass.h"
#include "llvm/Target/TargetData.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/Statistic.h"
using namespace llvm;

STATISTIC(NumSimpl, "Number of blocks simplified");

namespace {
  struct CFGSimplifyPass : public FunctionPass {
    static char ID; // Pass identification, replacement for typeid
    CFGSimplifyPass() : FunctionPass(ID) {
      initializeCFGSimplifyPassPass(*PassRegistry::getPassRegistry());
    }

    virtual bool runOnFunction(Function &F);
  };
}

char CFGSimplifyPass::ID = 0;
INITIALIZE_PASS(CFGSimplifyPass, "simplifycfg",
                "Simplify the CFG", false, false)

// Public interface to the CFGSimplification pass
FunctionPass *llvm::createCFGSimplificationPass() {
  return new CFGSimplifyPass();
}

/// ChangeToUnreachable - Insert an unreachable instruction before the specified
/// instruction, making it and the rest of the code in the block dead.
static void ChangeToUnreachable(Instruction *I, bool UseLLVMTrap) {
  BasicBlock *BB = I->getParent();
  // Loop over all of the successors, removing BB's entry from any PHI
  // nodes.
  for (succ_iterator SI = succ_begin(BB), SE = succ_end(BB); SI != SE; ++SI)
    (*SI)->removePredecessor(BB);

  // Insert a call to llvm.trap right before this.  This turns the undefined
  // behavior into a hard fail instead of falling through into random code.
  if (UseLLVMTrap) {
    Function *TrapFn =
      Intrinsic::getDeclaration(BB->getParent()->getParent(), Intrinsic::trap);
    CallInst *CallTrap = CallInst::Create(TrapFn, "", I);
    CallTrap->setDebugLoc(I->getDebugLoc());
  }
  new UnreachableInst(I->getContext(), I);

  // All instructions after this are dead.
  BasicBlock::iterator BBI = I, BBE = BB->end();
  while (BBI != BBE) {
    if (!BBI->use_empty())
      BBI->replaceAllUsesWith(UndefValue::get(BBI->getType()));
    BB->getInstList().erase(BBI++);
  }
}

/// ChangeToCall - Convert the specified invoke into a normal call.
static void ChangeToCall(InvokeInst *II) {
  SmallVector<Value*, 8> Args(II->op_begin(), II->op_end() - 3);
  CallInst *NewCall = CallInst::Create(II->getCalledValue(), Args, "", II);
  NewCall->takeName(II);
  NewCall->setCallingConv(II->getCallingConv());
  NewCall->setAttributes(II->getAttributes());
  NewCall->setDebugLoc(II->getDebugLoc());
  II->replaceAllUsesWith(NewCall);

  // Follow the call by a branch to the normal destination.
  BranchInst::Create(II->getNormalDest(), II);

  // Update PHI nodes in the unwind destination
  II->getUnwindDest()->removePredecessor(II->getParent());
  II->eraseFromParent();
}

static bool MarkAliveBlocks(BasicBlock *BB,
                            SmallPtrSet<BasicBlock*, 128> &Reachable) {

  SmallVector<BasicBlock*, 128> Worklist;
  Worklist.push_back(BB);
  bool Changed = false;
  do {
    BB = Worklist.pop_back_val();

    if (!Reachable.insert(BB))
      continue;

    // Do a quick scan of the basic block, turning any obviously unreachable
    // instructions into LLVM unreachable insts.  The instruction combining pass
    // canonicalizes unreachable insts into stores to null or undef.
    for (BasicBlock::iterator BBI = BB->begin(), E = BB->end(); BBI != E;++BBI){
      if (CallInst *CI = dyn_cast<CallInst>(BBI)) {
        if (CI->doesNotReturn()) {
          // If we found a call to a no-return function, insert an unreachable
          // instruction after it.  Make sure there isn't *already* one there
          // though.
          ++BBI;
          if (!isa<UnreachableInst>(BBI)) {
            // Don't insert a call to llvm.trap right before the unreachable.
            ChangeToUnreachable(BBI, false);
            Changed = true;
          }
          break;
        }
      }

      // Store to undef and store to null are undefined and used to signal that
      // they should be changed to unreachable by passes that can't modify the
      // CFG.
      if (StoreInst *SI = dyn_cast<StoreInst>(BBI)) {
        // Don't touch volatile stores.
        if (SI->isVolatile()) continue;

        Value *Ptr = SI->getOperand(1);

        if (isa<UndefValue>(Ptr) ||
            (isa<ConstantPointerNull>(Ptr) &&
             SI->getPointerAddressSpace() == 0)) {
          ChangeToUnreachable(SI, true);
          Changed = true;
          break;
        }
      }
    }

    // Turn invokes that call 'nounwind' functions into ordinary calls.
    if (InvokeInst *II = dyn_cast<InvokeInst>(BB->getTerminator())) {
      Value *Callee = II->getCalledValue();
      if (isa<ConstantPointerNull>(Callee) || isa<UndefValue>(Callee)) {
        ChangeToUnreachable(II, true);
        Changed = true;
      } else if (II->doesNotThrow()) {
        if (II->use_empty() && II->onlyReadsMemory()) {
          // jump to the normal destination branch.
          BranchInst::Create(II->getNormalDest(), II);
          II->getUnwindDest()->removePredecessor(II->getParent());
          II->eraseFromParent();
        } else
          ChangeToCall(II);
        Changed = true;
      }
    }

    Changed |= ConstantFoldTerminator(BB, true);
    for (succ_iterator SI = succ_begin(BB), SE = succ_end(BB); SI != SE; ++SI)
      Worklist.push_back(*SI);
  } while (!Worklist.empty());
  return Changed;
}

/// RemoveUnreachableBlocksFromFn - Remove blocks that are not reachable, even
/// if they are in a dead cycle.  Return true if a change was made, false
/// otherwise.
static bool RemoveUnreachableBlocksFromFn(Function &F) {
  SmallPtrSet<BasicBlock*, 128> Reachable;
  bool Changed = MarkAliveBlocks(F.begin(), Reachable);

  // If there are unreachable blocks in the CFG...
  if (Reachable.size() == F.size())
    return Changed;

  assert(Reachable.size() < F.size());
  NumSimpl += F.size()-Reachable.size();

  // Loop over all of the basic blocks that are not reachable, dropping all of
  // their internal references...
  for (Function::iterator BB = ++F.begin(), E = F.end(); BB != E; ++BB) {
    if (Reachable.count(BB))
      continue;

    for (succ_iterator SI = succ_begin(BB), SE = succ_end(BB); SI != SE; ++SI)
      if (Reachable.count(*SI))
        (*SI)->removePredecessor(BB);
    BB->dropAllReferences();
  }

  for (Function::iterator I = ++F.begin(); I != F.end();)
    if (!Reachable.count(I))
      I = F.getBasicBlockList().erase(I);
    else
      ++I;

  return true;
}

/// MergeEmptyReturnBlocks - If we have more than one empty (other than phi
/// node) return blocks, merge them together to promote recursive block merging.
static bool MergeEmptyReturnBlocks(Function &F) {
  bool Changed = false;

  BasicBlock *RetBlock = 0;

  // Scan all the blocks in the function, looking for empty return blocks.
  for (Function::iterator BBI = F.begin(), E = F.end(); BBI != E; ) {
    BasicBlock &BB = *BBI++;

    // Only look at return blocks.
    ReturnInst *Ret = dyn_cast<ReturnInst>(BB.getTerminator());
    if (Ret == 0) continue;

    // Only look at the block if it is empty or the only other thing in it is a
    // single PHI node that is the operand to the return.
    if (Ret != &BB.front()) {
      // Check for something else in the block.
      BasicBlock::iterator I = Ret;
      --I;
      // Skip over debug info.
      while (isa<DbgInfoIntrinsic>(I) && I != BB.begin())
        --I;
      if (!isa<DbgInfoIntrinsic>(I) &&
          (!isa<PHINode>(I) || I != BB.begin() ||
           Ret->getNumOperands() == 0 ||
           Ret->getOperand(0) != I))
        continue;
    }

    // If this is the first returning block, remember it and keep going.
    if (RetBlock == 0) {
      RetBlock = &BB;
      continue;
    }

    // Otherwise, we found a duplicate return block.  Merge the two.
    Changed = true;

    // Case when there is no input to the return or when the returned values
    // agree is trivial.  Note that they can't agree if there are phis in the
    // blocks.
    if (Ret->getNumOperands() == 0 ||
        Ret->getOperand(0) ==
          cast<ReturnInst>(RetBlock->getTerminator())->getOperand(0)) {
      BB.replaceAllUsesWith(RetBlock);
      BB.eraseFromParent();
      continue;
    }

    // If the canonical return block has no PHI node, create one now.
    PHINode *RetBlockPHI = dyn_cast<PHINode>(RetBlock->begin());
    if (RetBlockPHI == 0) {
      Value *InVal = cast<ReturnInst>(RetBlock->getTerminator())->getOperand(0);
      pred_iterator PB = pred_begin(RetBlock), PE = pred_end(RetBlock);
      RetBlockPHI = PHINode::Create(Ret->getOperand(0)->getType(),
                                    std::distance(PB, PE), "merge",
                                    &RetBlock->front());

      for (pred_iterator PI = PB; PI != PE; ++PI)
        RetBlockPHI->addIncoming(InVal, *PI);
      RetBlock->getTerminator()->setOperand(0, RetBlockPHI);
    }

    // Turn BB into a block that just unconditionally branches to the return
    // block.  This handles the case when the two return blocks have a common
    // predecessor but that return different things.
    RetBlockPHI->addIncoming(Ret->getOperand(0), &BB);
    BB.getTerminator()->eraseFromParent();
    BranchInst::Create(RetBlock, &BB);
  }

  return Changed;
}

/// IterativeSimplifyCFG - Call SimplifyCFG on all the blocks in the function,
/// iterating until no more changes are made.
static bool IterativeSimplifyCFG(Function &F, const TargetData *TD) {
  bool Changed = false;
  bool LocalChange = true;
  while (LocalChange) {
    LocalChange = false;

    // Loop over all of the basic blocks and remove them if they are unneeded...
    //
    for (Function::iterator BBIt = F.begin(); BBIt != F.end(); ) {
      if (SimplifyCFG(BBIt++, TD)) {
        LocalChange = true;
        ++NumSimpl;
      }
    }
    Changed |= LocalChange;
  }
  return Changed;
}

// It is possible that we may require multiple passes over the code to fully
// simplify the CFG.
//
bool CFGSimplifyPass::runOnFunction(Function &F) {
  const TargetData *TD = getAnalysisIfAvailable<TargetData>();
  bool EverChanged = RemoveUnreachableBlocksFromFn(F);
  EverChanged |= MergeEmptyReturnBlocks(F);
  EverChanged |= IterativeSimplifyCFG(F, TD);

  // If neither pass changed anything, we're done.
  if (!EverChanged) return false;

  // IterativeSimplifyCFG can (rarely) make some loops dead.  If this happens,
  // RemoveUnreachableBlocksFromFn is needed to nuke them, which means we should
  // iterate between the two optimizations.  We structure the code like this to
  // avoid reruning IterativeSimplifyCFG if the second pass of
  // RemoveUnreachableBlocksFromFn doesn't do anything.
  if (!RemoveUnreachableBlocksFromFn(F))
    return true;

  do {
    EverChanged = IterativeSimplifyCFG(F, TD);
    EverChanged |= RemoveUnreachableBlocksFromFn(F);
  } while (EverChanged);

  return true;
}
<commit_msg>Update function names to conform to guidelines.<commit_after>//===- SimplifyCFGPass.cpp - CFG Simplification Pass ----------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements dead code elimination and basic block merging, along
// with a collection of other peephole control flow optimizations.  For example:
//
//   * Removes basic blocks with no predecessors.
//   * Merges a basic block into its predecessor if there is only one and the
//     predecessor only has one successor.
//   * Eliminates PHI nodes for basic blocks with a single predecessor.
//   * Eliminates a basic block that only contains an unconditional branch.
//   * Changes invoke instructions to nounwind functions to be calls.
//   * Change things like "if (x) if (y)" into "if (x&y)".
//   * etc..
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "simplifycfg"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Transforms/Utils/Local.h"
#include "llvm/Constants.h"
#include "llvm/Instructions.h"
#include "llvm/IntrinsicInst.h"
#include "llvm/Module.h"
#include "llvm/Attributes.h"
#include "llvm/Support/CFG.h"
#include "llvm/Pass.h"
#include "llvm/Target/TargetData.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/Statistic.h"
using namespace llvm;

STATISTIC(NumSimpl, "Number of blocks simplified");

namespace {
  struct CFGSimplifyPass : public FunctionPass {
    static char ID; // Pass identification, replacement for typeid
    CFGSimplifyPass() : FunctionPass(ID) {
      initializeCFGSimplifyPassPass(*PassRegistry::getPassRegistry());
    }

    virtual bool runOnFunction(Function &F);
  };
}

char CFGSimplifyPass::ID = 0;
INITIALIZE_PASS(CFGSimplifyPass, "simplifycfg",
                "Simplify the CFG", false, false)

// Public interface to the CFGSimplification pass
FunctionPass *llvm::createCFGSimplificationPass() {
  return new CFGSimplifyPass();
}

/// changeToUnreachable - Insert an unreachable instruction before the specified
/// instruction, making it and the rest of the code in the block dead.
static void changeToUnreachable(Instruction *I, bool UseLLVMTrap) {
  BasicBlock *BB = I->getParent();
  // Loop over all of the successors, removing BB's entry from any PHI
  // nodes.
  for (succ_iterator SI = succ_begin(BB), SE = succ_end(BB); SI != SE; ++SI)
    (*SI)->removePredecessor(BB);

  // Insert a call to llvm.trap right before this.  This turns the undefined
  // behavior into a hard fail instead of falling through into random code.
  if (UseLLVMTrap) {
    Function *TrapFn =
      Intrinsic::getDeclaration(BB->getParent()->getParent(), Intrinsic::trap);
    CallInst *CallTrap = CallInst::Create(TrapFn, "", I);
    CallTrap->setDebugLoc(I->getDebugLoc());
  }
  new UnreachableInst(I->getContext(), I);

  // All instructions after this are dead.
  BasicBlock::iterator BBI = I, BBE = BB->end();
  while (BBI != BBE) {
    if (!BBI->use_empty())
      BBI->replaceAllUsesWith(UndefValue::get(BBI->getType()));
    BB->getInstList().erase(BBI++);
  }
}

/// changeToCall - Convert the specified invoke into a normal call.
static void changeToCall(InvokeInst *II) {
  SmallVector<Value*, 8> Args(II->op_begin(), II->op_end() - 3);
  CallInst *NewCall = CallInst::Create(II->getCalledValue(), Args, "", II);
  NewCall->takeName(II);
  NewCall->setCallingConv(II->getCallingConv());
  NewCall->setAttributes(II->getAttributes());
  NewCall->setDebugLoc(II->getDebugLoc());
  II->replaceAllUsesWith(NewCall);

  // Follow the call by a branch to the normal destination.
  BranchInst::Create(II->getNormalDest(), II);

  // Update PHI nodes in the unwind destination
  II->getUnwindDest()->removePredecessor(II->getParent());
  II->eraseFromParent();
}

static bool markAliveBlocks(BasicBlock *BB,
                            SmallPtrSet<BasicBlock*, 128> &Reachable) {

  SmallVector<BasicBlock*, 128> Worklist;
  Worklist.push_back(BB);
  bool Changed = false;
  do {
    BB = Worklist.pop_back_val();

    if (!Reachable.insert(BB))
      continue;

    // Do a quick scan of the basic block, turning any obviously unreachable
    // instructions into LLVM unreachable insts.  The instruction combining pass
    // canonicalizes unreachable insts into stores to null or undef.
    for (BasicBlock::iterator BBI = BB->begin(), E = BB->end(); BBI != E;++BBI){
      if (CallInst *CI = dyn_cast<CallInst>(BBI)) {
        if (CI->doesNotReturn()) {
          // If we found a call to a no-return function, insert an unreachable
          // instruction after it.  Make sure there isn't *already* one there
          // though.
          ++BBI;
          if (!isa<UnreachableInst>(BBI)) {
            // Don't insert a call to llvm.trap right before the unreachable.
            changeToUnreachable(BBI, false);
            Changed = true;
          }
          break;
        }
      }

      // Store to undef and store to null are undefined and used to signal that
      // they should be changed to unreachable by passes that can't modify the
      // CFG.
      if (StoreInst *SI = dyn_cast<StoreInst>(BBI)) {
        // Don't touch volatile stores.
        if (SI->isVolatile()) continue;

        Value *Ptr = SI->getOperand(1);

        if (isa<UndefValue>(Ptr) ||
            (isa<ConstantPointerNull>(Ptr) &&
             SI->getPointerAddressSpace() == 0)) {
          changeToUnreachable(SI, true);
          Changed = true;
          break;
        }
      }
    }

    // Turn invokes that call 'nounwind' functions into ordinary calls.
    if (InvokeInst *II = dyn_cast<InvokeInst>(BB->getTerminator())) {
      Value *Callee = II->getCalledValue();
      if (isa<ConstantPointerNull>(Callee) || isa<UndefValue>(Callee)) {
        changeToUnreachable(II, true);
        Changed = true;
      } else if (II->doesNotThrow()) {
        if (II->use_empty() && II->onlyReadsMemory()) {
          // jump to the normal destination branch.
          BranchInst::Create(II->getNormalDest(), II);
          II->getUnwindDest()->removePredecessor(II->getParent());
          II->eraseFromParent();
        } else
          changeToCall(II);
        Changed = true;
      }
    }

    Changed |= ConstantFoldTerminator(BB, true);
    for (succ_iterator SI = succ_begin(BB), SE = succ_end(BB); SI != SE; ++SI)
      Worklist.push_back(*SI);
  } while (!Worklist.empty());
  return Changed;
}

/// removeUnreachableBlocksFromFn - Remove blocks that are not reachable, even
/// if they are in a dead cycle.  Return true if a change was made, false
/// otherwise.
static bool removeUnreachableBlocksFromFn(Function &F) {
  SmallPtrSet<BasicBlock*, 128> Reachable;
  bool Changed = markAliveBlocks(F.begin(), Reachable);

  // If there are unreachable blocks in the CFG...
  if (Reachable.size() == F.size())
    return Changed;

  assert(Reachable.size() < F.size());
  NumSimpl += F.size()-Reachable.size();

  // Loop over all of the basic blocks that are not reachable, dropping all of
  // their internal references...
  for (Function::iterator BB = ++F.begin(), E = F.end(); BB != E; ++BB) {
    if (Reachable.count(BB))
      continue;

    for (succ_iterator SI = succ_begin(BB), SE = succ_end(BB); SI != SE; ++SI)
      if (Reachable.count(*SI))
        (*SI)->removePredecessor(BB);
    BB->dropAllReferences();
  }

  for (Function::iterator I = ++F.begin(); I != F.end();)
    if (!Reachable.count(I))
      I = F.getBasicBlockList().erase(I);
    else
      ++I;

  return true;
}

/// mergeEmptyReturnBlocks - If we have more than one empty (other than phi
/// node) return blocks, merge them together to promote recursive block merging.
static bool mergeEmptyReturnBlocks(Function &F) {
  bool Changed = false;

  BasicBlock *RetBlock = 0;

  // Scan all the blocks in the function, looking for empty return blocks.
  for (Function::iterator BBI = F.begin(), E = F.end(); BBI != E; ) {
    BasicBlock &BB = *BBI++;

    // Only look at return blocks.
    ReturnInst *Ret = dyn_cast<ReturnInst>(BB.getTerminator());
    if (Ret == 0) continue;

    // Only look at the block if it is empty or the only other thing in it is a
    // single PHI node that is the operand to the return.
    if (Ret != &BB.front()) {
      // Check for something else in the block.
      BasicBlock::iterator I = Ret;
      --I;
      // Skip over debug info.
      while (isa<DbgInfoIntrinsic>(I) && I != BB.begin())
        --I;
      if (!isa<DbgInfoIntrinsic>(I) &&
          (!isa<PHINode>(I) || I != BB.begin() ||
           Ret->getNumOperands() == 0 ||
           Ret->getOperand(0) != I))
        continue;
    }

    // If this is the first returning block, remember it and keep going.
    if (RetBlock == 0) {
      RetBlock = &BB;
      continue;
    }

    // Otherwise, we found a duplicate return block.  Merge the two.
    Changed = true;

    // Case when there is no input to the return or when the returned values
    // agree is trivial.  Note that they can't agree if there are phis in the
    // blocks.
    if (Ret->getNumOperands() == 0 ||
        Ret->getOperand(0) ==
          cast<ReturnInst>(RetBlock->getTerminator())->getOperand(0)) {
      BB.replaceAllUsesWith(RetBlock);
      BB.eraseFromParent();
      continue;
    }

    // If the canonical return block has no PHI node, create one now.
    PHINode *RetBlockPHI = dyn_cast<PHINode>(RetBlock->begin());
    if (RetBlockPHI == 0) {
      Value *InVal = cast<ReturnInst>(RetBlock->getTerminator())->getOperand(0);
      pred_iterator PB = pred_begin(RetBlock), PE = pred_end(RetBlock);
      RetBlockPHI = PHINode::Create(Ret->getOperand(0)->getType(),
                                    std::distance(PB, PE), "merge",
                                    &RetBlock->front());

      for (pred_iterator PI = PB; PI != PE; ++PI)
        RetBlockPHI->addIncoming(InVal, *PI);
      RetBlock->getTerminator()->setOperand(0, RetBlockPHI);
    }

    // Turn BB into a block that just unconditionally branches to the return
    // block.  This handles the case when the two return blocks have a common
    // predecessor but that return different things.
    RetBlockPHI->addIncoming(Ret->getOperand(0), &BB);
    BB.getTerminator()->eraseFromParent();
    BranchInst::Create(RetBlock, &BB);
  }

  return Changed;
}

/// iterativelySimplifyCFG - Call SimplifyCFG on all the blocks in the function,
/// iterating until no more changes are made.
static bool iterativelySimplifyCFG(Function &F, const TargetData *TD) {
  bool Changed = false;
  bool LocalChange = true;
  while (LocalChange) {
    LocalChange = false;

    // Loop over all of the basic blocks and remove them if they are unneeded...
    //
    for (Function::iterator BBIt = F.begin(); BBIt != F.end(); ) {
      if (SimplifyCFG(BBIt++, TD)) {
        LocalChange = true;
        ++NumSimpl;
      }
    }
    Changed |= LocalChange;
  }
  return Changed;
}

// It is possible that we may require multiple passes over the code to fully
// simplify the CFG.
//
bool CFGSimplifyPass::runOnFunction(Function &F) {
  const TargetData *TD = getAnalysisIfAvailable<TargetData>();
  bool EverChanged = removeUnreachableBlocksFromFn(F);
  EverChanged |= mergeEmptyReturnBlocks(F);
  EverChanged |= iterativelySimplifyCFG(F, TD);

  // If neither pass changed anything, we're done.
  if (!EverChanged) return false;

  // iterativelySimplifyCFG can (rarely) make some loops dead.  If this happens,
  // removeUnreachableBlocksFromFn is needed to nuke them, which means we should
  // iterate between the two optimizations.  We structure the code like this to
  // avoid reruning iterativelySimplifyCFG if the second pass of
  // removeUnreachableBlocksFromFn doesn't do anything.
  if (!removeUnreachableBlocksFromFn(F))
    return true;

  do {
    EverChanged = iterativelySimplifyCFG(F, TD);
    EverChanged |= removeUnreachableBlocksFromFn(F);
  } while (EverChanged);

  return true;
}
<|endoftext|>


<commit_before>// (c) ZaKlaus 2016; Apache 2 Licensed, see LICENSE;;

#if !defined(DZM_PRT_H)

static inline void
write_pair(FILE *Out, OBJECT *Obj)
{
    OBJECT *A = pair_get_a(Obj);
    OBJECT *B = pair_get_b(Obj);

    write(Out, A);
    if(is_pair(B))
    {
        fprintf(Out, " ");
        write_pair(Out, B);
    }
    else if(is_nil(B))
    {
        return;
    }
    else
    {
        fprintf(Out, " . ");
        write(Out, B);
    }
}

static inline void
write(FILE *Out, OBJECT *Obj, b32 StripQuotes)
{
    if(Obj == 0)
    {
        return;
    }
    switch(Obj->Type)
    {
        case FIXNUM:
        {
            fprintf(Out, "%" PRId64, Obj->uData.FIXNUM.Value);
        }break;

        case REALNUM:
        {
            fprintf(Out, "%1lf", Obj->uData.REALNUM.Value);
        }break;

        case BOOLEAN:
        {
            fprintf(Out, "#%c", is_false(Obj) ? 'f' : 't');
        }break;

        case CHARACTER:
        {
            u8 C = Obj->uData.CHARACTER.Value;
            if(!StripQuotes)fprintf(Out, "#\\");
            switch(C)
            {
                case '\n':
                {
                     if(!StripQuotes)fprintf(Out, "newline");
                     else fprintf(Out, "\n");
                }break;

                case ' ':
                {
                     if(!StripQuotes)fprintf(Out, "space");
                     else fprintf(Out, " ");
                }break;

            case '\t':
            {
                 if(!StripQuotes)fprintf(Out, "tab");
                 else fprintf(Out, "\t");
            }break;

                default:
                {
                     fprintf(Out, "%c", C);
                }break;
            }
        }break;

        case STRING:
        {
            u8 *Str = Obj->uData.STRING.Value;
            if(!StripQuotes)fprintf(Out, "%c", '"');

            while(*Str != 0)
            {
                // TODO(zaklaus): To print or not to print un-escaped specials?
                // CONCL(zaklaus): Since this is just a simple echo machine, we can't print
                // un-escaped chars. Maybe later in more specialized built-in or so...
                switch(*Str)
                {
                    case '\n':
                    {
                        fprintf(Out, "\\n");
                    }break;

                    case '\\':
                    {
                        fprintf(Out, "\\\\");
                    }break;

                    case '"':
                    {
                        fprintf(Out, "\\\"");
                    }break;

                    default:
                    {
                        fprintf(Out, "%c", *Str);
                    }break;
                }
                Str++;
            }
            if(!StripQuotes)fprintf(Out, "%c", '"');
        }break;

        case NIL:
        {
            fprintf(Out, "()");
        }break;

        case PAIR:
        {
            fprintf(Out, "(");
            write_pair(Out, Obj);
            fprintf(Out, ")");
        }break;

        case SYMBOL:
        {
            if(Obj == VarSymbol)break;

            if(!(Obj == OKSymbol))
            {
                fprintf(Out, "%s", Obj->uData.SYMBOL.Value);
            }
        }break;

        case COMPOUND :
        case PROCEDURE:
        {
            fprintf(Out, "#<PROCEDURE>");
        }break;

        case INPUT:
        {
            fprintf(Out, "#<INPUT>");
        }break;
        case OUTPUT:
        {
            fprintf(Out, "#<OUTPUT>");
        }break;

        default:
        {
            fprintf(stderr, "Unknown value");// for '%#08x'\n", (unsigned int*)&Obj);
            InvalidCodePath;
        }break;
    }

    if(PrintMemUsage)
    {
        LOG(ERR_INFO, "Free: %d, Total: %d", (int)get_arena_size_remaining(GlobalArena, default_arena_params()), (int)GlobalArena->Size);
    }
}

#define DZM_PRT_H
#endif
<commit_msg>Print unescaped special characters.<commit_after>// (c) ZaKlaus 2016; Apache 2 Licensed, see LICENSE;;

#if !defined(DZM_PRT_H)

static inline void
write_pair(FILE *Out, OBJECT *Obj)
{
    OBJECT *A = pair_get_a(Obj);
    OBJECT *B = pair_get_b(Obj);

    write(Out, A);
    if(is_pair(B))
    {
        fprintf(Out, " ");
        write_pair(Out, B);
    }
    else if(is_nil(B))
    {
        return;
    }
    else
    {
        fprintf(Out, " . ");
        write(Out, B);
    }
}

static inline void
write(FILE *Out, OBJECT *Obj, b32 StripQuotes)
{
    if(Obj == 0)
    {
        return;
    }
    switch(Obj->Type)
    {
        case FIXNUM:
        {
            fprintf(Out, "%" PRId64, Obj->uData.FIXNUM.Value);
        }break;

        case REALNUM:
        {
            fprintf(Out, "%1lf", Obj->uData.REALNUM.Value);
        }break;

        case BOOLEAN:
        {
            fprintf(Out, "#%c", is_false(Obj) ? 'f' : 't');
        }break;

        case CHARACTER:
        {
            u8 C = Obj->uData.CHARACTER.Value;
            if(!StripQuotes)fprintf(Out, "#\\");
            switch(C)
            {
                case '\n':
                {
                     if(!StripQuotes)fprintf(Out, "newline");
                     else fprintf(Out, "\n");
                }break;

                case ' ':
                {
                     if(!StripQuotes)fprintf(Out, "space");
                     else fprintf(Out, " ");
                }break;

            case '\t':
            {
                 if(!StripQuotes)fprintf(Out, "tab");
                 else fprintf(Out, "\t");
            }break;

                default:
                {
                     fprintf(Out, "%c", C);
                }break;
            }
        }break;

        case STRING:
        {
            u8 *Str = Obj->uData.STRING.Value;
            if(!StripQuotes)fprintf(Out, "%c", '"');

            while(*Str != 0)
            {
                // TODO(zaklaus): To print or not to print un-escaped specials?
                // CONCL(zaklaus): Since this is just a simple echo machine, we can't print
                // un-escaped chars. Maybe later in more specialized built-in or so...
                switch(*Str)
                {
                    case '\n':
                    {
                        fprintf(Out, "\n");
                    }break;

                    case '\t':
                    {
						fprintf(Out, "\t");
					}break;

                    case '\\':
                    {
                        fprintf(Out, "\\\\");
                    }break;

                    case '"':
                    {
                        fprintf(Out, "\\\"");
                    }break;

                    default:
                    {
                        fprintf(Out, "%c", *Str);
                    }break;
                }
                Str++;
            }
            if(!StripQuotes)fprintf(Out, "%c", '"');
        }break;

        case NIL:
        {
            fprintf(Out, "()");
        }break;

        case PAIR:
        {
            fprintf(Out, "(");
            write_pair(Out, Obj);
            fprintf(Out, ")");
        }break;

        case SYMBOL:
        {
            if(Obj == VarSymbol)break;

            if(!(Obj == OKSymbol))
            {
                fprintf(Out, "%s", Obj->uData.SYMBOL.Value);
            }
        }break;

        case COMPOUND :
        case PROCEDURE:
        {
            fprintf(Out, "#<PROCEDURE>");
        }break;

        case INPUT:
        {
            fprintf(Out, "#<INPUT>");
        }break;
        case OUTPUT:
        {
            fprintf(Out, "#<OUTPUT>");
        }break;

        default:
        {
            fprintf(stderr, "Unknown value");// for '%#08x'\n", (unsigned int*)&Obj);
            InvalidCodePath;
        }break;
    }

    if(PrintMemUsage)
    {
        LOG(ERR_INFO, "Free: %d, Total: %d", (int)get_arena_size_remaining(GlobalArena, default_arena_params()), (int)GlobalArena->Size);
    }
}

#define DZM_PRT_H
#endif
<|endoftext|>


<commit_before>#include <chrono>
#include <iostream>

#include "matrix.h"
//#include "Eigen/Dense"

class Timer {
	std::chrono::high_resolution_clock::time_point _start;
public:
	Timer() : _start(std::chrono::high_resolution_clock::now()) {
	}
	std::chrono::milliseconds elapsed() {
		return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - _start);
	}
	void reset() {
		_start = std::chrono::high_resolution_clock::now();
	}
};

template<typename TMatrixType>
long long MeasureAccessTime(TMatrixType& A) {
	int repeat_number = 1000000;
	Timer timer;
	for (int i_repeat = 0; i_repeat < repeat_number; i_repeat++)
		for (int i = 0; i < 3; i++)
			for (int j = 0; j < 3; j++)
				A(i, j) += i - j;
	return timer.elapsed().count();
}

template<typename TMatrixType>
std::size_t MeasureAssignTime(TMatrixType& A) {
	int repeat_number = 1000000;
	TMatrixType B = A;
	Timer timer;
	for (int i_repeat = 0; i_repeat < repeat_number; i_repeat++) {
		for (int i = 0; i < 3; i++)
			for (int j = 0; j < 3; j++)
				B(i, j) += i - j;
		A = B;
	}

	return timer.elapsed().count();
}

template<typename TMatrixType>
std::size_t MeasureSumTime(TMatrixType& A, TMatrixType& B) {
	int repeat_number = 10000;
	TMatrixType C = A;
	TMatrixType D = A;
	Timer timer;
	for (int i_repeat = 0; i_repeat < repeat_number; i_repeat++) {
		C = A + B ;
		B = C;
	}

	return timer.elapsed().count();
}

template<typename TMatrixType1, typename TMatrixType2>
std::size_t MeasureMultTime(TMatrixType1& A, TMatrixType2& B) {
	int repeat_number = 1000;
	TMatrixType1 C = A;
	TMatrixType1 D = A;
	Timer timer;
	for (int i_repeat = 0; i_repeat < repeat_number; i_repeat++) {
		D = A;
		for (int i = 0; i < 1000; i++) {
			C = D * B;
			D = C;
		}
	}

	return timer.elapsed().count();
}

void CompareAccessTime(){
	AMatrix::Matrix<double,3,3> m_33(0.00);
	std::cout << "A[i,j] += i -j\t\t" << MeasureAccessTime(m_33) << std::endl;
}

void CompareAssignTime(){
	AMatrix::Matrix<double,3,3> m_33(0.00);
	std::cout << "A = B\t\t\t" << MeasureAssignTime(m_33) << std::endl;
}

int main()
{
	std::cout << "operation\t\tAMatrix\t\tEigen\t\tUblas\t\tAtlas" << std::endl;
	CompareAccessTime();
	CompareAssignTime();
	return 0;
}

<commit_msg>Apply styling<commit_after>#include <chrono>
#include <iostream>

#include "matrix.h"
//#include "Eigen/Dense"

class Timer {
    std::chrono::high_resolution_clock::time_point _start;

   public:
    Timer() : _start(std::chrono::high_resolution_clock::now()) {}
    std::chrono::milliseconds elapsed() {
        return std::chrono::duration_cast<std::chrono::milliseconds>(
            std::chrono::high_resolution_clock::now() - _start);
    }
    void reset() { _start = std::chrono::high_resolution_clock::now(); }
};

template <typename TMatrixType>
long long MeasureAccessTime(TMatrixType& A) {
    int repeat_number = 1000000;
    Timer timer;
    for (int i_repeat = 0; i_repeat < repeat_number; i_repeat++)
        for (int i = 0; i < 3; i++)
            for (int j = 0; j < 3; j++)
                A(i, j) += i - j;
    return timer.elapsed().count();
}

template <typename TMatrixType>
std::size_t MeasureAssignTime(TMatrixType& A) {
    int repeat_number = 1000000;
    TMatrixType B = A;
    Timer timer;
    for (int i_repeat = 0; i_repeat < repeat_number; i_repeat++) {
        for (int i = 0; i < 3; i++)
            for (int j = 0; j < 3; j++)
                B(i, j) += i - j;
        A = B;
    }

    return timer.elapsed().count();
}

template <typename TMatrixType>
std::size_t MeasureSumTime(TMatrixType& A, TMatrixType& B) {
    int repeat_number = 10000;
    TMatrixType C = A;
    TMatrixType D = A;
    Timer timer;
    for (int i_repeat = 0; i_repeat < repeat_number; i_repeat++) {
        C = A + B;
        B = C;
    }

    return timer.elapsed().count();
}

template <typename TMatrixType1, typename TMatrixType2>
std::size_t MeasureMultTime(TMatrixType1& A, TMatrixType2& B) {
    int repeat_number = 1000;
    TMatrixType1 C = A;
    TMatrixType1 D = A;
    Timer timer;
    for (int i_repeat = 0; i_repeat < repeat_number; i_repeat++) {
        D = A;
        for (int i = 0; i < 1000; i++) {
            C = D * B;
            D = C;
        }
    }

    return timer.elapsed().count();
}

void CompareAccessTime() {
    AMatrix::Matrix<double, 3, 3> m_33(0.00);
    std::cout << "A[i,j] += i -j\t\t" << MeasureAccessTime(m_33) << std::endl;
}

void CompareAssignTime() {
    AMatrix::Matrix<double, 3, 3> m_33(0.00);
    std::cout << "A = B\t\t\t" << MeasureAssignTime(m_33) << std::endl;
}

int main() {
    std::cout << "operation\t\tAMatrix\t\tEigen\t\tUblas\t\tAtlas" << std::endl;
    CompareAccessTime();
    CompareAssignTime();
    return 0;
}
<|endoftext|>


<commit_before>/*
 * V1_S1.cpp
 *
 *  Created on: Aug 4, 2008
 *      Author: dcoates
 */

#include "V1_S1.hpp"
#include "../connections/PVConnection.h"
#include "../io/io.h"

#include <float.h>
#include <math.h>
#include <stdlib.h>
#include <stdio.h>

namespace PV {

V1_S1::V1_S1(const char * name, HyPerCol * hc)
{
   PVParams * params = hc->parameters();
   no = params->value(name, "no");

   // base constructor stuff
   setParent(hc);
   init(name, TypeGeneric);
   hc->addLayer(this);

   clayer->Vth[0] = 0.6;

   subWeights = (pvdata_t *) malloc(no * clayer->numFeatures * sizeof(pvdata_t));

   const int nf = clayer->numFeatures;
   for (int k = 0; k < no*nf; k++) {
      subWeights[k] = 0.0;
   }

#define VERTICAL
#ifdef VERTICAL
   // temporary vertical orientation
   subWeights[2]  = 0.5;
   subWeights[8]  = 0.5;
   subWeights[10] = 1.0;
   subWeights[1+16] = 0.5;
   subWeights[4+16] = 0.5; // I think this is 4+16
   subWeights[5+16] = 1.0;
   subWeights[2+32]  = 0.5;
   subWeights[8+32]  = 0.5;
   subWeights[10+32] = 1.0;
   subWeights[1+48] = 0.5;
   subWeights[4+48] = 0.5; // I think this is 4+48
   subWeights[5+48] = 1.0;
#endif

#ifdef HORIZONTAL
   // temporary horizontal orientation
   subWeights[4]  = 0.5;
   subWeights[8]  = 0.5;
   subWeights[12] = 1.0;
   subWeights[4+16]  = 0.5;
   subWeights[8+16]  = 0.5;
   subWeights[12+16] = 1.0;
   subWeights[1+32]  = 0.5;
   subWeights[2+32]  = 0.5;
   subWeights[3+32] = 1.0;
   subWeights[1+48] = 0.5;
   subWeights[2+48] = 0.5;
   subWeights[3+48] = 1.0;
#endif

   float sum = 0.0;
   for (int k = 0; k < nf; k++) {
      sum += subWeights[k];
   }
   for (int k = 0; k < nf; k++) {
      subWeights[k] = subWeights[k]/sum;
   }
}

int V1_S1::columnWillAddLayer(InterColComm * comm, int layerId)
{
   setLayerId(layerId);

   // complete initialization now that we have a parent and a communicator
   // WARNING - this must be done before addPublisher is called
   int id = parent->columnId();
   initGlobal(id, comm->commRow(id), comm->commColumn(id),
                  comm->numCommRows(), comm->numCommColumns());

   // shrink activity to represent reduced feature count after subunits
   clayer->activity->numItems = no * clayer->activity->loc.nx * clayer->activity->loc.ny;
   clayer->activity->size = clayer->activity->numItems * sizeof(pvdata_t);

   const float nx = clayer->loc.nx;
   const float ny = clayer->loc.ny;
   // calculate maximum size of a border cube
   // const int maxBorderSize = pvcube_size(nx*ny*no);

// TODO - calculate the maxBorderSize correctly
   comm->addPublisher(this, clayer->activity->size, clayer->activity->size, MAX_F_DELAY);

   return 0;
}

int V1_S1::updateState(float time, float dt)
{
   float data[4*16*16];

   static int hasData = 0;

   pvdata_t * phi = clayer->phi[0];
   const float nx = clayer->loc.nx;
   const float ny = clayer->loc.ny;
   const int   nf = clayer->numFeatures;

   pv_debug_info("[%d]: V1_S1::updateState:", clayer->columnId);

   // sum over subunits with weights to get membrane potential

   for (int f = 0; f < no; f++) {
      for (int kx = 0; kx < nx; kx++) {
         for (int ky = 0; ky < ny; ky++) {
            float tmp = 0.0;
            for (int kf = 0; kf < nf; kf++) {
               int k = kIndex(kx, ky, kf, nx, ny, nf);
               int kPhi = kIndexExtended(k, nx, ny, nf, clayer->numBorder);
               if (phi[kPhi] > 0.0) {
                  tmp += subWeights[kf]*phi[kPhi];
//                  printf("subWeight[%d] = %f %f\n", kf, subWeights[kf], phi[kPhi]);
               }
            }
            int k  = kIndex(kx, ky, f, nx, ny, 4);
            clayer->V[k] = tmp;
            if (clayer->V[k] > clayer->Vth[0]) {
               clayer->activity->data[k] = tmp;
               data[k] = tmp;
               printf("activity[%d] = %f \n", k, tmp);
            }
            else {
               clayer->activity->data[k] = 0.0;
            }
         }
      }
   }

   for (int k = 0; k < clayer->numNeurons; k++) {
      int kPhi = kIndexExtended(k, clayer->loc.nx, clayer->loc.ny, clayer->numFeatures,
                                clayer->numBorder);
      phi[kPhi] = 0.0;     // reset accumulation buffer
   }

   if (hasData) {
      clayer->activity->numItems = nx*ny*4;
      clayer->activity->size     = nx*ny*4 * sizeof(float);
      pv_tiff_write_cube("data.tif", clayer->activity, nx, ny, 4);
   }
   hasData = 1;

   return 0;
}

} // namespace PV
<commit_msg>Added EXTEND_BORDER_INDEX preprocessor guard to remove extending the border.  Borders are now handled by border regions (neighbors).<commit_after>/*
 * V1_S1.cpp
 *
 *  Created on: Aug 4, 2008
 *      Author: dcoates
 */

#include "V1_S1.hpp"
#include "../connections/PVConnection.h"
#include "../io/io.h"

#include <float.h>
#include <math.h>
#include <stdlib.h>
#include <stdio.h>

namespace PV {

V1_S1::V1_S1(const char * name, HyPerCol * hc)
{
   PVParams * params = hc->parameters();
   no = params->value(name, "no");

   // base constructor stuff
   setParent(hc);
   init(name, TypeGeneric);
   hc->addLayer(this);

   clayer->Vth[0] = 0.6;

   subWeights = (pvdata_t *) malloc(no * clayer->numFeatures * sizeof(pvdata_t));

   const int nf = clayer->numFeatures;
   for (int k = 0; k < no*nf; k++) {
      subWeights[k] = 0.0;
   }

#define VERTICAL
#ifdef VERTICAL
   // temporary vertical orientation
   subWeights[2]  = 0.5;
   subWeights[8]  = 0.5;
   subWeights[10] = 1.0;
   subWeights[1+16] = 0.5;
   subWeights[4+16] = 0.5; // I think this is 4+16
   subWeights[5+16] = 1.0;
   subWeights[2+32]  = 0.5;
   subWeights[8+32]  = 0.5;
   subWeights[10+32] = 1.0;
   subWeights[1+48] = 0.5;
   subWeights[4+48] = 0.5; // I think this is 4+48
   subWeights[5+48] = 1.0;
#endif

#ifdef HORIZONTAL
   // temporary horizontal orientation
   subWeights[4]  = 0.5;
   subWeights[8]  = 0.5;
   subWeights[12] = 1.0;
   subWeights[4+16]  = 0.5;
   subWeights[8+16]  = 0.5;
   subWeights[12+16] = 1.0;
   subWeights[1+32]  = 0.5;
   subWeights[2+32]  = 0.5;
   subWeights[3+32] = 1.0;
   subWeights[1+48] = 0.5;
   subWeights[2+48] = 0.5;
   subWeights[3+48] = 1.0;
#endif

   float sum = 0.0;
   for (int k = 0; k < nf; k++) {
      sum += subWeights[k];
   }
   for (int k = 0; k < nf; k++) {
      subWeights[k] = subWeights[k]/sum;
   }
}

int V1_S1::columnWillAddLayer(InterColComm * comm, int layerId)
{
   setLayerId(layerId);

   // complete initialization now that we have a parent and a communicator
   // WARNING - this must be done before addPublisher is called
   int id = parent->columnId();
   initGlobal(id, comm->commRow(id), comm->commColumn(id),
                  comm->numCommRows(), comm->numCommColumns());

   // shrink activity to represent reduced feature count after subunits
   clayer->activity->numItems = no * clayer->activity->loc.nx * clayer->activity->loc.ny;
   clayer->activity->size = clayer->activity->numItems * sizeof(pvdata_t);

   const float nx = clayer->loc.nx;
   const float ny = clayer->loc.ny;
   // calculate maximum size of a border cube
   // const int maxBorderSize = pvcube_size(nx*ny*no);

// TODO - calculate the maxBorderSize correctly
   comm->addPublisher(this, clayer->activity->size, clayer->activity->size, MAX_F_DELAY);

   return 0;
}

int V1_S1::updateState(float time, float dt)
{
   float data[4*16*16];

   static int hasData = 0;

   pvdata_t * phi = clayer->phi[0];
   const float nx = clayer->loc.nx;
   const float ny = clayer->loc.ny;
   const int   nf = clayer->numFeatures;

   pv_debug_info("[%d]: V1_S1::updateState:", clayer->columnId);

   // sum over subunits with weights to get membrane potential

   for (int f = 0; f < no; f++) {
      for (int kx = 0; kx < nx; kx++) {
         for (int ky = 0; ky < ny; ky++) {
            float tmp = 0.0;
            for (int kf = 0; kf < nf; kf++) {
               int k = kIndex(kx, ky, kf, nx, ny, nf);
#ifdef EXTEND_BORDER_INDEX
               int kPhi = kIndexExtended(k, nx, ny, nf, clayer->numBorder);
#else
               int kPhi = k;
#endif
               if (phi[kPhi] > 0.0) {
                  tmp += subWeights[kf]*phi[kPhi];
//                  printf("subWeight[%d] = %f %f\n", kf, subWeights[kf], phi[kPhi]);
               }
            }
            int k  = kIndex(kx, ky, f, nx, ny, 4);
            clayer->V[k] = tmp;
            if (clayer->V[k] > clayer->Vth[0]) {
               clayer->activity->data[k] = tmp;
               data[k] = tmp;
               printf("activity[%d] = %f \n", k, tmp);
            }
            else {
               clayer->activity->data[k] = 0.0;
            }
         }
      }
   }

   for (int k = 0; k < clayer->numNeurons; k++) {
#ifdef EXTEND_BORDER_INDEX
      int kPhi = kIndexExtended(k, clayer->loc.nx, clayer->loc.ny, clayer->numFeatures,
                                clayer->numBorder);
#else
      int kPhi = k;
#endif
      phi[kPhi] = 0.0;     // reset accumulation buffer
   }

   if (hasData) {
      clayer->activity->numItems = nx*ny*4;
      clayer->activity->size     = nx*ny*4 * sizeof(float);
      pv_tiff_write_cube("data.tif", clayer->activity, nx, ny, 4);
   }
   hasData = 1;

   return 0;
}

} // namespace PV
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    itkSpatialObjectPrintTest.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) 2002 Insight Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#if defined(_MSC_VER)
#pragma warning ( disable : 4786 )
#endif

#include "itkBlobSpatialObject.h"
#include "itkEllipseSpatialObject.h"
#include "itkGroupSpatialObject.h"
#include "itkImageSpatialObject.h"
#include "itkLandmarkSpatialObject.h"
#include "itkLineSpatialObject.h"
#include "itkLineSpatialObjectPoint.h"
#include "itkPlaneSpatialObject.h"
#include "itkPolygonGroupOrientation.h"
#include "itkPolygonGroupSpatialObject.h"
#include "itkPolygonSpatialObject.h"
#include "itkScene.h"
#include "itkSpatialObject.h"
#include "itkSpatialObjectPoint.h"
#include "itkSpatialObjectProperty.h"
#include "itkSurfaceSpatialObject.h"
#include "itkSurfaceSpatialObjectPoint.h"
#include "itkTubeSpatialObject.h"
#include "itkTubeSpatialObjectPoint.h"

int itkSpatialObjectPrintTest(int , char* [])
{
  itk::BlobSpatialObject<3>::Pointer BlobSpatialObjectObj =
    itk::BlobSpatialObject<3>::New();
  std::cout << "----------BlobSpatialObject " << BlobSpatialObjectObj;

  itk::EllipseSpatialObject<3>::Pointer EllipseSpatialObjectObj =
    itk::EllipseSpatialObject<3>::New();
  std::cout << "----------EllipseSpatialObject " << EllipseSpatialObjectObj;

  itk::GroupSpatialObject<3>::Pointer GroupSpatialObjectObj =
    itk::GroupSpatialObject<3>::New();
  std::cout << "----------GroupSpatialObject " << GroupSpatialObjectObj;

  typedef unsigned short Pixel;
  itk::ImageSpatialObject<3,Pixel>::Pointer ImageSpatialObjectObj =
    itk::ImageSpatialObject<3,Pixel>::New();
  std::cout << "----------ImageSpatialObject " << ImageSpatialObjectObj;

  itk::LandmarkSpatialObject<3>::Pointer LandmarkSpatialObjectObj =
    itk::LandmarkSpatialObject<3>::New();
  std::cout << "----------LandmarkSpatialObject " << LandmarkSpatialObjectObj;

  itk::LineSpatialObject<3>::Pointer LineSpatialObjectObj =
    itk::LineSpatialObject<3>::New();
  std::cout << "----------LineSpatialObject " << LineSpatialObjectObj;
#if 0
  itk::LineSpatialObjectPoint<3>::Pointer LineSpatialObjectPointObj =
    itk::LineSpatialObjectPoint<3>::New();
  std::cout << "----------LineSpatialObjectPoint " << LineSpatialObjectPointObj;
#endif
  itk::PlaneSpatialObject<3>::Pointer PlaneSpatialObjectObj =
    itk::PlaneSpatialObject<3>::New();
  std::cout << "----------PlaneSpatialObject " << PlaneSpatialObjectObj;
#if 0
  itk::PolygonGroupOrientation::Pointer PolygonGroupOrientationObj =
    itk::PolygonGroupOrientation::New();
  std::cout << "----------PolygonGroupOrientation " << PolygonGroupOrientationObj;
#endif
  itk::PolygonGroupSpatialObject<3>::Pointer PolygonGroupSpatialObjectObj =
    itk::PolygonGroupSpatialObject<3>::New();
  std::cout << "----------PolygonGroupSpatialObject " << PolygonGroupSpatialObjectObj;

  itk::PolygonSpatialObject<3>::Pointer PolygonSpatialObjectObj =
    itk::PolygonSpatialObject<3>::New();
  std::cout << "----------PolygonSpatialObject " << PolygonSpatialObjectObj;

  itk::Scene<3>::Pointer SceneObj =
    itk::Scene<3>::New();
  std::cout << "----------Scene " << SceneObj;

  itk::SpatialObject<3>::Pointer SpatialObjectObj =
    itk::SpatialObject<3>::New();
  std::cout << "----------SpatialObject " << SpatialObjectObj;
#if 0
  itk::SpatialObjectPoint<3>::Pointer SpatialObjectPointObj =
    itk::SpatialObjectPoint<3>::New();
  std::cout << "----------SpatialObjectPoint " << SpatialObjectPointObj;
#endif
  itk::SpatialObjectProperty<float>::Pointer SpatialObjectPropertyObj =
    itk::SpatialObjectProperty<float>::New();
  std::cout << "----------SpatialObjectProperty " << SpatialObjectPropertyObj;

  itk::SurfaceSpatialObject<3>::Pointer SurfaceSpatialObjectObj =
    itk::SurfaceSpatialObject<3>::New();
  std::cout << "----------SurfaceSpatialObject " << SurfaceSpatialObjectObj;
#if 0
  itk::SurfaceSpatialObjectPoint<3>::Pointer SurfaceSpatialObjectPointObj =
    itk::SurfaceSpatialObjectPoint<3>::New();
  std::cout << "----------SurfaceSpatialObjectPoint " << SurfaceSpatialObjectPointObj;
#endif
  itk::TubeSpatialObject<3>::Pointer TubeSpatialObjectObj =
    itk::TubeSpatialObject<3>::New();
  std::cout << "----------TubeSpatialObject " << TubeSpatialObjectObj;
#if 0
  itk::TubeSpatialObjectPoint<3>::Pointer TubeSpatialObjectPointObj =
    itk::TubeSpatialObjectPoint<3>::New();
  std::cout << "----------TubeSpatialObjectPoint " << TubeSpatialObjectPointObj;
#endif

  return 0;
}
<commit_msg>ENH: Enabled testing of print statements<commit_after>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    itkSpatialObjectPrintTest.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) 2002 Insight Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#if defined(_MSC_VER)
#pragma warning ( disable : 4786 )
#endif

#include "itkBlobSpatialObject.h"
#include "itkEllipseSpatialObject.h"
#include "itkGroupSpatialObject.h"
#include "itkImageSpatialObject.h"
#include "itkLandmarkSpatialObject.h"
#include "itkLineSpatialObject.h"
#include "itkLineSpatialObjectPoint.h"
#include "itkPlaneSpatialObject.h"
#include "itkPolygonGroupOrientation.h"
#include "itkPolygonGroupSpatialObject.h"
#include "itkPolygonSpatialObject.h"
#include "itkScene.h"
#include "itkSpatialObject.h"
#include "itkSpatialObjectPoint.h"
#include "itkSpatialObjectProperty.h"
#include "itkSurfaceSpatialObject.h"
#include "itkSurfaceSpatialObjectPoint.h"
#include "itkTubeSpatialObject.h"
#include "itkTubeSpatialObjectPoint.h"

int itkSpatialObjectPrintTest(int , char* [])
{
  itk::BlobSpatialObject<3>::Pointer BlobSpatialObjectObj =
    itk::BlobSpatialObject<3>::New();
  std::cout << "----------BlobSpatialObject " << BlobSpatialObjectObj;

  itk::EllipseSpatialObject<3>::Pointer EllipseSpatialObjectObj =
    itk::EllipseSpatialObject<3>::New();
  std::cout << "----------EllipseSpatialObject " << EllipseSpatialObjectObj;

  itk::GroupSpatialObject<3>::Pointer GroupSpatialObjectObj =
    itk::GroupSpatialObject<3>::New();
  std::cout << "----------GroupSpatialObject " << GroupSpatialObjectObj;

  typedef unsigned short Pixel;
  itk::ImageSpatialObject<3,Pixel>::Pointer ImageSpatialObjectObj =
    itk::ImageSpatialObject<3,Pixel>::New();
  std::cout << "----------ImageSpatialObject " << ImageSpatialObjectObj;

  itk::LandmarkSpatialObject<3>::Pointer LandmarkSpatialObjectObj =
    itk::LandmarkSpatialObject<3>::New();
  std::cout << "----------LandmarkSpatialObject " << LandmarkSpatialObjectObj;

  itk::LineSpatialObject<3>::Pointer LineSpatialObjectObj =
    itk::LineSpatialObject<3>::New();
  std::cout << "----------LineSpatialObject " << LineSpatialObjectObj;

  itk::LineSpatialObjectPoint<3> * LineSpatialObjectPointObj =
    new itk::LineSpatialObjectPoint<3>;
  std::cout << "----------LineSpatialObjectPoint " << LineSpatialObjectPointObj;
  delete LineSpatialObjectPointObj;

  itk::PlaneSpatialObject<3>::Pointer PlaneSpatialObjectObj =
    itk::PlaneSpatialObject<3>::New();
  std::cout << "----------PlaneSpatialObject " << PlaneSpatialObjectObj;
#if 0
  itk::PolygonGroupOrientation::Pointer PolygonGroupOrientationObj =
    itk::PolygonGroupOrientation::New();
  std::cout << "----------PolygonGroupOrientation " << PolygonGroupOrientationObj;
#endif
  itk::PolygonGroupSpatialObject<3>::Pointer PolygonGroupSpatialObjectObj =
    itk::PolygonGroupSpatialObject<3>::New();
  std::cout << "----------PolygonGroupSpatialObject " << PolygonGroupSpatialObjectObj;

  itk::PolygonSpatialObject<3>::Pointer PolygonSpatialObjectObj =
    itk::PolygonSpatialObject<3>::New();
  std::cout << "----------PolygonSpatialObject " << PolygonSpatialObjectObj;

  itk::Scene<3>::Pointer SceneObj =
    itk::Scene<3>::New();
  std::cout << "----------Scene " << SceneObj;

  itk::SpatialObject<3>::Pointer SpatialObjectObj =
    itk::SpatialObject<3>::New();
  std::cout << "----------SpatialObject " << SpatialObjectObj;

  itk::SpatialObjectPoint<3> * SpatialObjectPointObj =
    new itk::SpatialObjectPoint<3>;
  std::cout << "----------SpatialObjectPoint " << SpatialObjectPointObj;
  delete SpatialObjectPointObj;

  itk::SpatialObjectProperty<float>::Pointer SpatialObjectPropertyObj =
    itk::SpatialObjectProperty<float>::New();
  std::cout << "----------SpatialObjectProperty " << SpatialObjectPropertyObj;

  itk::SurfaceSpatialObject<3>::Pointer SurfaceSpatialObjectObj =
    itk::SurfaceSpatialObject<3>::New();
  std::cout << "----------SurfaceSpatialObject " << SurfaceSpatialObjectObj;

  itk::SurfaceSpatialObjectPoint<3> * SurfaceSpatialObjectPointObj =
    new itk::SurfaceSpatialObjectPoint<3>;
  std::cout << "----------SurfaceSpatialObjectPoint " << SurfaceSpatialObjectPointObj;
  delete SurfaceSpatialObjectPointObj;

  itk::TubeSpatialObject<3>::Pointer TubeSpatialObjectObj =
    itk::TubeSpatialObject<3>::New();
  std::cout << "----------TubeSpatialObject " << TubeSpatialObjectObj;

  itk::TubeSpatialObjectPoint<3> *  TubeSpatialObjectPointObj =
    new itk::TubeSpatialObjectPoint<3>;
  std::cout << "----------TubeSpatialObjectPoint " << TubeSpatialObjectPointObj;
  delete TubeSpatialObjectPointObj;

  return 0;
}
<|endoftext|>


<commit_before>/*
 * Copyright 2009-2019 The VOTCA Development Team (http://www.votca.org)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

#include "../../include/votca/csg/beadlist.h"
#include "../../include/votca/csg/topology.h"
#include <votca/tools/tokenizer.h>

namespace votca {
namespace csg {

using namespace std;

Index BeadList::Generate(Topology &top, const string &select) {
  _topology = ⊤
  bool selectByName = false;
  string pSelect;  // parsed selection string

  if (select.substr(0, 5) == "name:") {
    // select according to bead name instead of type
    pSelect = select.substr(5);
    selectByName = true;
  } else {
    pSelect = select;
  }

  for (auto &iter : top.Beads()) {
    if (!selectByName) {
      if (tools::wildcmp(pSelect, iter->getType())) {
        _beads.push_back(iter);
      }
    } else {
      if (tools::wildcmp(pSelect, iter->getName())) {
        _beads.push_back(iter);
      }
    }
  }
  return size();
}

Index BeadList::GenerateInSphericalSubvolume(Topology &top,
                                             const string &select,
                                             Eigen::Vector3d ref,
                                             double radius) {
  _topology = ⊤
  bool selectByName = false;
  string pSelect;  // parsed selection string

  if (select.substr(0, 5) == "name:") {
    // select according to bead name instead of type
    pSelect = select.substr(5);
    selectByName = true;
  } else {
    pSelect = select;
  }

  for (auto &iter : top.Beads()) {
    if (_topology->BCShortestConnection(ref, iter->getPos()).norm() > radius) {
      continue;
    }
    if (!selectByName) {
      if (tools::wildcmp(pSelect, iter->getType())) {
        _beads.push_back(iter);
      }
    } else {
      if (tools::wildcmp(pSelect, iter->getName())) {
        _beads.push_back(iter);
      }
    }
  }
  return size();
}

}  // namespace csg
}  // namespace votca
<commit_msg>first include fix<commit_after>/*
 * Copyright 2009-2019 The VOTCA Development Team (http://www.votca.org)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

// VOTCA includes
#include <votca/tools/tokenizer.h>

// Local VOTCA includes
#include "votca/csg/beadlist.h"
#include "votca/csg/topology.h"

namespace votca {
namespace csg {

using namespace std;

Index BeadList::Generate(Topology &top, const string &select) {
  _topology = ⊤
  bool selectByName = false;
  string pSelect;  // parsed selection string

  if (select.substr(0, 5) == "name:") {
    // select according to bead name instead of type
    pSelect = select.substr(5);
    selectByName = true;
  } else {
    pSelect = select;
  }

  for (auto &iter : top.Beads()) {
    if (!selectByName) {
      if (tools::wildcmp(pSelect, iter->getType())) {
        _beads.push_back(iter);
      }
    } else {
      if (tools::wildcmp(pSelect, iter->getName())) {
        _beads.push_back(iter);
      }
    }
  }
  return size();
}

Index BeadList::GenerateInSphericalSubvolume(Topology &top,
                                             const string &select,
                                             Eigen::Vector3d ref,
                                             double radius) {
  _topology = ⊤
  bool selectByName = false;
  string pSelect;  // parsed selection string

  if (select.substr(0, 5) == "name:") {
    // select according to bead name instead of type
    pSelect = select.substr(5);
    selectByName = true;
  } else {
    pSelect = select;
  }

  for (auto &iter : top.Beads()) {
    if (_topology->BCShortestConnection(ref, iter->getPos()).norm() > radius) {
      continue;
    }
    if (!selectByName) {
      if (tools::wildcmp(pSelect, iter->getType())) {
        _beads.push_back(iter);
      }
    } else {
      if (tools::wildcmp(pSelect, iter->getName())) {
        _beads.push_back(iter);
      }
    }
  }
  return size();
}

}  // namespace csg
}  // namespace votca
<|endoftext|>


<commit_before><commit_msg>nvc0/ir: remove merge/split pairs to allow normal propagation to occur<commit_after><|endoftext|>


<commit_before><commit_msg>Move scom API to share among controllers<commit_after><|endoftext|>


<commit_before>#include "shader_importer.h"
#include "halley/tools/assets/import_assets_database.h"
#include "halley/bytes/byte_serializer.h"
#include "halley/resources/metadata.h"
#include "halley/tools/file/filesystem.h"
#include "halley/core/graphics/shader.h"
#include "halley/support/logger.h"
#include <ShaderConductor/ShaderConductor.hpp>

#ifdef _MSC_VER
#include <D3Dcompiler.h>
#pragma comment(lib, "D3DCompiler.lib")
#pragma comment(lib, "ShaderConductor.lib")
#endif

using namespace Halley;

void ShaderImporter::import(const ImportingAsset& asset, IAssetCollector& collector)
{
	std::map<String, ShaderFile> shaders;
	const Metadata meta = asset.inputFiles.at(0).metadata;
	if (meta.getString("language", "") != "hlsl") {
		return;
	}

	std::array<String, 3> languages = {{ "hlsl", "glsl", "metal" }};

	for (auto& language: languages) {
		ShaderFile shader;
		for (auto& input: asset.inputFiles) {
			const auto shaderType = fromString<ShaderType>(input.name.getExtension().mid(1));
			shader.shaders[shaderType] = fromHLSL(input.name.toString(), shaderType, input.data, language);
		}

		String id = asset.assetId.split(':').at(0) + ":" + language;
		Metadata curMeta = meta;
		curMeta.set("language", language);
		collector.output(id, AssetType::Shader, Serializer::toBytes(shader), curMeta);
	}
}

Bytes ShaderImporter::fromHLSL(const String& name, ShaderType type, const Bytes& data, const String& dstLanguage) const
{
	if (dstLanguage == "hlsl") {
		return compileHLSL(name, type, data);
	} else {
		using namespace ShaderConductor;

		ShaderStage stage;
		switch (type) {
		case ShaderType::Pixel:
			stage = ShaderStage::PixelShader;
			break;
		case ShaderType::Vertex:
			stage = ShaderStage::VertexShader;
			break;
		case ShaderType::Geometry:
			stage = ShaderStage::GeometryShader;
			break;
		default:
			throw Exception("Invalid stage: " + toString(type), HalleyExceptions::Tools);
		}

		String srcStr(reinterpret_cast<const char*>(data.data()), data.size());

		Compiler::SourceDesc source;
		source.fileName = name.c_str();
		source.entryPoint = "main";
		source.stage = stage;
		source.source = srcStr.c_str();
		source.numDefines = 0;
		source.defines = nullptr;

		Compiler::TargetDesc target;
		if (dstLanguage == "glsl") {
			target.language = ShadingLanguage::Glsl;
			target.version = "330";
		} else if (dstLanguage == "metal") {
			target.language = ShadingLanguage::Msl_iOS;
			target.version = "221";
		}

		Compiler::Options options;
		options.shiftAllCBuffersBindings = 0;
		options.shiftAllSamplersBindings = 0;
		options.shiftAllTexturesBindings = 0;
		options.shiftAllUABuffersBindings = 0;

		auto result = Compiler::Compile(source, options, target);

		if (result.hasError) {
			throw Exception("Error converting shader to " + dstLanguage + ": " + String(reinterpret_cast<const char*>(result.errorWarningMsg->Data()), result.errorWarningMsg->Size()), HalleyExceptions::Tools);
		}

		Bytes bytes(result.target->Size());
		memcpy(bytes.data(), result.target->Data(), bytes.size());
		return bytes;
	}
}

void ShaderImporter::importOld(const ImportingAsset& asset, IAssetCollector& collector)
{
	ShaderFile shader;
	for (auto& input: asset.inputFiles) {
		const auto shaderType = fromString<ShaderType>(input.name.getExtension().mid(1));
		const String language = input.metadata.getString("language", "");

		if (language == "glsl" || language == "metal") {
			// Runtime-compiled shader languages
			String strData = String(reinterpret_cast<const char*>(input.data.data()), input.data.size());
			if (language == "glsl") {
				strData = "#version 330\n" + strData;
			}
			Bytes data(strData.size());
			memcpy(data.data(), strData.c_str(), data.size());
			shader.shaders[shaderType] = data;
		} else if (language == "hlsl") {
			shader.shaders[shaderType] = compileHLSL(input.name.toString(), shaderType, input.data);
		}
	}

	collector.output(asset.assetId, AssetType::Shader, Serializer::toBytes(shader), asset.inputFiles.at(0).metadata);
}

Bytes ShaderImporter::compileHLSL(const String& name, ShaderType type, const Bytes& bytes) const
{
#ifdef _MSC_VER

	String target;

	switch (type) {
	case ShaderType::Vertex:
		target = "vs_4_0";
		break;

	case ShaderType::Pixel:
		target = "ps_4_0";
		break;

	case ShaderType::Geometry:
		target = "gs_4_0";
		break;

	default:
		throw Exception("Unsupported shader type: " + toString(type), HalleyExceptions::Tools);
	}

	ID3D10Blob *codeBlob = nullptr;
	ID3D10Blob *errorBlob = nullptr;
	const HRESULT hResult = D3DCompile2(bytes.data(), bytes.size(), name.c_str(), nullptr, nullptr, "main", target.c_str(), 0, 0, 0, nullptr, 0, &codeBlob, &errorBlob);
	if (hResult != S_OK) {
		const auto errorMessage = String(reinterpret_cast<const char*>(errorBlob->GetBufferPointer()), errorBlob->GetBufferSize());
		errorBlob->Release();
		throw Exception("Failed to compile shader " + name + " (" + toString(type) + "):\n" + errorMessage, HalleyExceptions::Tools);
	}

	auto result = Bytes(codeBlob->GetBufferSize());
	memcpy_s(result.data(), result.size(), codeBlob->GetBufferPointer(), codeBlob->GetBufferSize());

	if (errorBlob) {
		errorBlob->Release();
	}
	if (codeBlob) {
		codeBlob->Release();
	}

	return result;

#else

	Logger::logWarning("Compiling HLSL shaders is not supported on non-Windows platforms.");
	return Bytes();

#endif
}
<commit_msg>Free memory after invoking ShaderConductor::Compiler::Compile<commit_after>#include "shader_importer.h"
#include "halley/tools/assets/import_assets_database.h"
#include "halley/bytes/byte_serializer.h"
#include "halley/resources/metadata.h"
#include "halley/tools/file/filesystem.h"
#include "halley/core/graphics/shader.h"
#include "halley/support/logger.h"
#include <ShaderConductor/ShaderConductor.hpp>

#ifdef _MSC_VER
#include <D3Dcompiler.h>
#pragma comment(lib, "D3DCompiler.lib")
#pragma comment(lib, "ShaderConductor.lib")
#endif

using namespace Halley;

void ShaderImporter::import(const ImportingAsset& asset, IAssetCollector& collector)
{
	std::map<String, ShaderFile> shaders;
	const Metadata meta = asset.inputFiles.at(0).metadata;
	if (meta.getString("language", "") != "hlsl") {
		return;
	}

	std::array<String, 3> languages = {{ "hlsl", "glsl", "metal" }};

	for (auto& language: languages) {
		ShaderFile shader;
		for (auto& input: asset.inputFiles) {
			const auto shaderType = fromString<ShaderType>(input.name.getExtension().mid(1));
			shader.shaders[shaderType] = fromHLSL(input.name.toString(), shaderType, input.data, language);
		}

		String id = asset.assetId.split(':').at(0) + ":" + language;
		Metadata curMeta = meta;
		curMeta.set("language", language);
		collector.output(id, AssetType::Shader, Serializer::toBytes(shader), curMeta);
	}
}

Bytes ShaderImporter::fromHLSL(const String& name, ShaderType type, const Bytes& data, const String& dstLanguage) const
{
	if (dstLanguage == "hlsl") {
		return compileHLSL(name, type, data);
	} else {
		using namespace ShaderConductor;

		ShaderStage stage;
		switch (type) {
		case ShaderType::Pixel:
			stage = ShaderStage::PixelShader;
			break;
		case ShaderType::Vertex:
			stage = ShaderStage::VertexShader;
			break;
		case ShaderType::Geometry:
			stage = ShaderStage::GeometryShader;
			break;
		default:
			throw Exception("Invalid stage: " + toString(type), HalleyExceptions::Tools);
		}

		String srcStr(reinterpret_cast<const char*>(data.data()), data.size());

		Compiler::SourceDesc source;
		source.fileName = name.c_str();
		source.entryPoint = "main";
		source.stage = stage;
		source.source = srcStr.c_str();
		source.numDefines = 0;
		source.defines = nullptr;

		Compiler::TargetDesc target;
		if (dstLanguage == "glsl") {
			target.language = ShadingLanguage::Glsl;
			target.version = "330";
		} else if (dstLanguage == "metal") {
			target.language = ShadingLanguage::Msl_iOS;
			target.version = "221";
		}

		Compiler::Options options;
		options.shiftAllCBuffersBindings = 0;
		options.shiftAllSamplersBindings = 0;
		options.shiftAllTexturesBindings = 0;
		options.shiftAllUABuffersBindings = 0;

		auto result = Compiler::Compile(source, options, target);

		if (result.hasError) {
			const auto msg = String(reinterpret_cast<const char*>(result.errorWarningMsg->Data()), result.errorWarningMsg->Size());
			DestroyBlob(result.target);
			DestroyBlob(result.errorWarningMsg);
			throw Exception("Error converting shader to " + dstLanguage + ": " + msg, HalleyExceptions::Tools);
		}

		Bytes bytes(result.target->Size());
		memcpy(bytes.data(), result.target->Data(), bytes.size());
		DestroyBlob(result.target);
		DestroyBlob(result.errorWarningMsg);

		return bytes;
	}
}

void ShaderImporter::importOld(const ImportingAsset& asset, IAssetCollector& collector)
{
	ShaderFile shader;
	for (auto& input: asset.inputFiles) {
		const auto shaderType = fromString<ShaderType>(input.name.getExtension().mid(1));
		const String language = input.metadata.getString("language", "");

		if (language == "glsl" || language == "metal") {
			// Runtime-compiled shader languages
			String strData = String(reinterpret_cast<const char*>(input.data.data()), input.data.size());
			if (language == "glsl") {
				strData = "#version 330\n" + strData;
			}
			Bytes data(strData.size());
			memcpy(data.data(), strData.c_str(), data.size());
			shader.shaders[shaderType] = data;
		} else if (language == "hlsl") {
			shader.shaders[shaderType] = compileHLSL(input.name.toString(), shaderType, input.data);
		}
	}

	collector.output(asset.assetId, AssetType::Shader, Serializer::toBytes(shader), asset.inputFiles.at(0).metadata);
}

Bytes ShaderImporter::compileHLSL(const String& name, ShaderType type, const Bytes& bytes) const
{
#ifdef _MSC_VER

	String target;

	switch (type) {
	case ShaderType::Vertex:
		target = "vs_4_0";
		break;

	case ShaderType::Pixel:
		target = "ps_4_0";
		break;

	case ShaderType::Geometry:
		target = "gs_4_0";
		break;

	default:
		throw Exception("Unsupported shader type: " + toString(type), HalleyExceptions::Tools);
	}

	ID3D10Blob *codeBlob = nullptr;
	ID3D10Blob *errorBlob = nullptr;
	const HRESULT hResult = D3DCompile2(bytes.data(), bytes.size(), name.c_str(), nullptr, nullptr, "main", target.c_str(), 0, 0, 0, nullptr, 0, &codeBlob, &errorBlob);
	if (hResult != S_OK) {
		const auto errorMessage = String(reinterpret_cast<const char*>(errorBlob->GetBufferPointer()), errorBlob->GetBufferSize());
		errorBlob->Release();
		throw Exception("Failed to compile shader " + name + " (" + toString(type) + "):\n" + errorMessage, HalleyExceptions::Tools);
	}

	auto result = Bytes(codeBlob->GetBufferSize());
	memcpy_s(result.data(), result.size(), codeBlob->GetBufferPointer(), codeBlob->GetBufferSize());

	if (errorBlob) {
		errorBlob->Release();
	}
	if (codeBlob) {
		codeBlob->Release();
	}

	return result;

#else

	Logger::logWarning("Compiling HLSL shaders is not supported on non-Windows platforms.");
	return Bytes();

#endif
}
<|endoftext|>


<commit_before>#include <stdexcept>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stropts.h>
#include <sys/ioctl.h>

#include "Debug.h"
#include "Socket.h"

Socket::Socket(std::string addr, uint16_t port) {
    this->addr = addr;
    this->port = port;

    sockaddr_in serverAddr;
    socketFd = socket(AF_INET, SOCK_STREAM, 0);

    if(socketFd < 0)
        throw std::runtime_error("Error: can't open socket (req: " + addr + ")" + DBG_INFO);

    struct hostent *server = gethostbyname(addr.c_str());

    if(server == NULL)
        throw std::runtime_error("Error: host not found (req: " + addr + ")" + DBG_INFO);

    bzero((char *) &serverAddr, sizeof(serverAddr));
    serverAddr.sin_family = AF_INET;
    bcopy(server->h_addr,
          (char *)&serverAddr.sin_addr.s_addr,
          (size_t) server->h_length);
    serverAddr.sin_port = htons(port);

    if (connect(socketFd,(sockaddr *) &serverAddr,sizeof(serverAddr)) < 0)
        throw std::runtime_error("Error: can't connect to server (req: " + addr + ")" + DBG_INFO);
}

Socket::Socket(int socketFd) {
    if(socketFd == -1)
    {
        throw std::runtime_error("Invalid socket file descriptor" + DBG_INFO);
    }
    else
    {
        this->socketFd = socketFd;
    }
}

Socket::~Socket()
{
    this->close();
}

int Socket::bytesAvailable() {
    int bytes;
    if(ioctl(socketFd, FIONREAD, &bytes) < 0)
        throw std::runtime_error("Error: can't get bytes available to read, socket closed?");

    return bytes;
}

std::string Socket::read(int maxRead) {
    char buffer[256];
    std::string ret;
    ssize_t rd = 0;
    size_t buffSize = sizeof(buffer);

    if((maxRead == 0) || (maxRead > bytesAvailable()))
    {
        maxRead = bytesAvailable();
    }

    if(maxRead - ret.size() < sizeof(buffer))
    {
        buffSize = maxRead - ret.size();
    }

    while(rd = ::read(socketFd, buffer, buffSize))
    {
        ret += std::string(buffer, rd);

        if(maxRead == ret.size())
            return ret;

        if(rd < 0)
            throw std::runtime_error("Error: can't read from socket, maybe closed? (req: " + addr + ")" + DBG_INFO);

        if(maxRead - ret.size() < sizeof(buffer))
        {
            buffSize = maxRead - ret.size();
        }
    }
}

void Socket::write(std::string data) {
    const char* byteArray = data.c_str();
    size_t bytesToWrite = data.size();
    ssize_t wr = 0;
    while((bytesToWrite != 0))
    {
        wr = ::write(socketFd, byteArray, bytesToWrite);

        if(wr < 0)
            throw std::runtime_error("Error: can't write to socket, maybe closed? (req: " + addr + ")" + DBG_INFO);

        bytesToWrite -= wr;
        byteArray += wr;
    }
}

void Socket::close() {
    ::close(socketFd);
}
<commit_msg>some socket fixes<commit_after>#include <stdexcept>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stropts.h>
#include <sys/ioctl.h>

#include "Debug.h"
#include "Socket.h"

Socket::Socket(std::string addr, uint16_t port) {
    this->addr = addr;
    this->port = port;

    sockaddr_in serverAddr;
    socketFd = socket(AF_INET, SOCK_STREAM, 0);

    if(socketFd < 0)
        throw std::runtime_error("Error: can't open socket (req: " + addr + ")" + DBG_INFO);

    struct hostent *server = gethostbyname(addr.c_str());

    if(server == NULL)
        throw std::runtime_error("Error: host not found (req: " + addr + ")" + DBG_INFO);

    bzero((char *) &serverAddr, sizeof(serverAddr));
    serverAddr.sin_family = AF_INET;
    bcopy(server->h_addr,
          (char *)&serverAddr.sin_addr.s_addr,
          (size_t) server->h_length);
    serverAddr.sin_port = htons(port);

    if (connect(socketFd,(sockaddr *) &serverAddr,sizeof(serverAddr)) < 0)
        throw std::runtime_error("Error: can't connect to server (req: " + addr + ")" + DBG_INFO);
}

Socket::Socket(int socketFd) {
    if(socketFd == -1)
    {
        throw std::runtime_error("Invalid socket file descriptor" + DBG_INFO);
    }
    else
    {
        this->socketFd = socketFd;
    }
}

Socket::~Socket()
{
    this->close();
}

int Socket::bytesAvailable() {
    int bytes;
    if(ioctl(socketFd, FIONREAD, &bytes) < 0)
        throw std::runtime_error("Error: can't get bytes available to read, socket closed?");

    return bytes;
}

std::string Socket::read(int maxRead) {
    char buffer[256];
    std::string ret;
    ssize_t rd = 0;
    size_t buffSize = sizeof(buffer);

    if((maxRead == 0) || (maxRead > bytesAvailable()))
    {
        maxRead = bytesAvailable();
    }

    if(maxRead - ret.size() < sizeof(buffer))
    {
        buffSize = maxRead - ret.size();
    }

    while((rd = ::read(socketFd, buffer, buffSize)))
    {
        ret += std::string(buffer, rd);

        if(maxRead == ret.size())
            return ret;

        if(rd < 0)
            throw std::runtime_error("Error: can't read from socket, maybe closed? (req: " + addr + ")" + DBG_INFO);

        if(maxRead - ret.size() < sizeof(buffer))
        {
            buffSize = maxRead - ret.size();
        }
    }
}

void Socket::write(std::string data) {
    const char* byteArray = data.c_str();
    size_t bytesToWrite = data.size();
    ssize_t wr = 0;
    while(bytesToWrite != 0)
    {
        wr = ::write(socketFd, byteArray, bytesToWrite);

        if(wr < 0)
            throw std::runtime_error("Error: can't write to socket, maybe closed? (req: " + addr + ")" + DBG_INFO);

        bytesToWrite -= wr;
        byteArray += wr;
    }
}

void Socket::close() {
    ::close(socketFd);
}
<|endoftext|>


<commit_before><commit_msg>avoid depending on global object when making hw accelerator<commit_after><|endoftext|>


<commit_before><commit_msg>More fixes for Lockable<T> to accomodate GCC<commit_after><|endoftext|>


<commit_before><commit_msg>Use TimeSeriesTable instead of Storage for forces.<commit_after><|endoftext|>